16
16
17
17
use std:: path:: PathBuf ;
18
18
19
+ use alloy:: {
20
+ hex:: FromHex ,
21
+ network:: EthereumWallet ,
22
+ primitives:: { hex, Address , FixedBytes } ,
23
+ providers:: ProviderBuilder ,
24
+ signers:: local:: PrivateKeySigner ,
25
+ } ;
26
+ use alloy_sol_types:: sol;
19
27
use clap:: Parser ;
20
28
use host:: prove_block_range;
29
+ use risc0_tm_core:: IBlobstream ;
21
30
use tendermint_rpc:: HttpClient ;
22
31
use tokio:: fs;
23
- use tracing_subscriber:: EnvFilter ;
32
+ use tracing_subscriber:: fmt:: format;
33
+ use tracing_subscriber:: { fmt:: format:: FmtSpan , EnvFilter } ;
34
+
35
+ // TODO elsewhere if keeping dev mode deploy through CLI
36
+ sol ! (
37
+ #[ sol( rpc) ]
38
+ MockVerifier ,
39
+ // TODO probably not ideal to reference build directory, fine for now.
40
+ "../contracts/out/RiscZeroMockVerifier.sol/RiscZeroMockVerifier.json"
41
+ ) ;
42
+ sol ! (
43
+ #[ sol( rpc) ]
44
+ RiscZeroGroth16Verifier ,
45
+ // TODO probably not ideal to reference build directory, fine for now.
46
+ "../contracts/out/RiscZeroGroth16Verifier.sol/RiscZeroGroth16Verifier.json"
47
+ ) ;
48
+
49
+ // Pulled from https://github.com/risc0/risc0-ethereum/blob/ebec385cc526adb9279c1af55d699c645ca6d694/contracts/src/groth16/ControlID.sol
50
+ const CONTROL_ID : [ u8 ; 32 ] =
51
+ hex ! ( "a516a057c9fbf5629106300934d48e0e775d4230e41e503347cad96fcbde7e2e" ) ;
52
+ const BN254_CONTROL_ID : [ u8 ; 32 ] =
53
+ hex ! ( "0eb6febcf06c5df079111be116f79bd8c7e85dc9448776ef9a59aaf2624ab551" ) ;
54
+
55
+ #[ derive( Parser , Debug ) ]
56
+ #[ command( name = "blobstream0-cli" ) ]
57
+ #[ command( bin_name = "blobstream0-cli" ) ]
58
+ enum BlobstreamCli {
59
+ ProveRange ( ProveRangeArgs ) ,
60
+ Deploy ( DeployArgs ) ,
61
+ }
24
62
25
63
#[ derive( Parser , Debug ) ]
26
64
#[ clap( author, version, about, long_about = None ) ]
27
- struct Args {
65
+ struct ProveRangeArgs {
28
66
/// The start height
29
67
#[ clap( long) ]
30
68
start : u64 ,
@@ -42,24 +80,101 @@ struct Args {
42
80
out : PathBuf ,
43
81
}
44
82
83
+ #[ derive( Parser , Debug ) ]
84
+ #[ clap( author, version, about, long_about = None ) ]
85
+ struct DeployArgs {
86
+ /// The Ethereum RPC URL
87
+ #[ clap( long) ]
88
+ eth_rpc : String ,
89
+
90
+ /// Hex encoded private key to use for submitting proofs to Ethereum
91
+ #[ clap( long) ]
92
+ private_key_hex : String ,
93
+
94
+ /// Address of risc0 verifier to use (either mock or groth16)
95
+ #[ clap( long) ]
96
+ verifier_address : Option < String > ,
97
+
98
+ /// Trusted height for contract
99
+ #[ clap( long) ]
100
+ tm_height : u64 ,
101
+
102
+ /// Trusted block hash for contract
103
+ #[ clap( long) ]
104
+ tm_block_hash : String ,
105
+
106
+ /// If deploying verifier, will it deploy the mock verifier
107
+ #[ clap( long) ]
108
+ dev : bool ,
109
+ }
110
+
45
111
#[ tokio:: main]
46
112
async fn main ( ) -> anyhow:: Result < ( ) > {
47
113
tracing_subscriber:: fmt ( )
114
+ . event_format ( format ( ) . compact ( ) )
115
+ . with_span_events ( FmtSpan :: CLOSE )
48
116
. with_env_filter ( EnvFilter :: from_default_env ( ) )
49
117
. init ( ) ;
50
118
51
- let Args {
52
- start,
53
- end,
54
- tendermint_rpc,
55
- out,
56
- } = Args :: parse ( ) ;
119
+ match BlobstreamCli :: parse ( ) {
120
+ BlobstreamCli :: ProveRange ( range) => {
121
+ let ProveRangeArgs {
122
+ start,
123
+ end,
124
+ tendermint_rpc,
125
+ out,
126
+ } = range;
127
+
128
+ let client = HttpClient :: new ( tendermint_rpc. as_str ( ) ) ?;
129
+
130
+ let receipt = prove_block_range ( & client, start..end) . await ?;
131
+
132
+ fs:: write ( out, bincode:: serialize ( & receipt) ?) . await ?;
133
+ }
134
+ BlobstreamCli :: Deploy ( deploy) => {
135
+ let signer: PrivateKeySigner = deploy. private_key_hex . parse ( ) ?;
136
+ let wallet = EthereumWallet :: from ( signer) ;
57
137
58
- let client = HttpClient :: new ( tendermint_rpc. as_str ( ) ) ?;
138
+ let provider = ProviderBuilder :: new ( )
139
+ . with_recommended_fillers ( )
140
+ . wallet ( wallet)
141
+ . on_http ( deploy. eth_rpc . parse ( ) ?) ;
142
+ let verifier_address: Address = if let Some ( address) = deploy. verifier_address {
143
+ address. parse ( ) ?
144
+ } else {
145
+ let deployed_address = if deploy. dev {
146
+ tracing:: debug!( "Deploying mock verifier" ) ;
147
+ MockVerifier :: deploy ( & provider, [ 0 , 0 , 0 , 0 ] . into ( ) )
148
+ . await ?
149
+ . address ( )
150
+ . clone ( )
151
+ } else {
152
+ tracing:: debug!( "Deploying groth16 verifier" ) ;
153
+ RiscZeroGroth16Verifier :: deploy (
154
+ & provider,
155
+ CONTROL_ID . into ( ) ,
156
+ BN254_CONTROL_ID . into ( ) ,
157
+ )
158
+ . await ?
159
+ . address ( )
160
+ . clone ( )
161
+ } ;
162
+ println ! ( "deployed verifier to address: {}" , deployed_address) ;
163
+ deployed_address
164
+ } ;
59
165
60
- let receipt = prove_block_range ( & client, start..end) . await ?;
166
+ // Deploy the contract.
167
+ let contract = IBlobstream :: deploy (
168
+ & provider,
169
+ verifier_address,
170
+ FixedBytes :: < 32 > :: from_hex ( deploy. tm_block_hash ) ?,
171
+ deploy. tm_height ,
172
+ )
173
+ . await ?;
61
174
62
- fs:: write ( out, bincode:: serialize ( & receipt) ?) . await ?;
175
+ println ! ( "deployed contract to address: {}" , contract. address( ) ) ;
176
+ }
177
+ }
63
178
64
179
Ok ( ( ) )
65
180
}
0 commit comments