@@ -3,6 +3,7 @@ use crate::{
3
3
types,
4
4
verifier:: SugondatVerifier ,
5
5
} ;
6
+ use async_trait:: async_trait;
6
7
use sov_rollup_interface:: { da:: DaSpec , services:: da:: DaService } ;
7
8
use std:: { future:: Future , pin:: Pin } ;
8
9
use subxt:: backend:: rpc:: { rpc_params, RpcClient } ;
@@ -43,6 +44,7 @@ impl DaProvider {
43
44
}
44
45
}
45
46
47
+ #[ async_trait]
46
48
impl sov_rollup_interface:: services:: da:: DaService for DaProvider {
47
49
type Spec = DaLayerSpec ;
48
50
type FilteredBlock = crate :: types:: Block ;
@@ -51,143 +53,127 @@ impl sov_rollup_interface::services::da::DaService for DaProvider {
51
53
52
54
// Make an RPC call to the node to get the finalized block at the given height, if one exists.
53
55
// If no such block exists, block until one does.
54
- fn get_finalized_at < ' life0 , ' async_trait > (
55
- & ' life0 self ,
56
- height : u64 ,
57
- ) -> Pin < Box < dyn Future < Output = Result < Self :: FilteredBlock , Self :: Error > > + Send + ' async_trait > >
58
- where
59
- Self : ' async_trait ,
60
- ' life0 : ' async_trait ,
61
- {
56
+ async fn get_finalized_at ( & self , height : u64 ) -> Result < Self :: FilteredBlock , Self :: Error > {
62
57
let client = self . client . clone ( ) ;
63
58
let namespace = self . namespace ;
64
- Box :: pin ( async move {
65
- let client_url = client. url ( ) . await ;
66
- let client = client. client ( ) . await ?;
67
-
68
- loop {
69
- let finalized_head = client. backend ( ) . latest_finalized_block_ref ( ) . await ?;
70
- let header = client
71
- . backend ( )
72
- . block_header ( finalized_head. hash ( ) )
73
- . await ?
74
- . unwrap ( ) ;
75
- if header. number as u64 >= height {
76
- break ;
77
- }
78
- tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
59
+ let client_url = client. url ( ) . await ;
60
+ let client = client. client ( ) . await ?;
61
+
62
+ loop {
63
+ let finalized_head = client. backend ( ) . latest_finalized_block_ref ( ) . await ?;
64
+ let header = client
65
+ . backend ( )
66
+ . block_header ( finalized_head. hash ( ) )
67
+ . await ?
68
+ . unwrap ( ) ;
69
+ if header. number as u64 >= height {
70
+ break ;
79
71
}
72
+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
73
+ }
80
74
81
- // between version 0.29 and 0.32 they remove subxt::rpc::Rpc
82
- // so this 'raw' rpc call is required to extract the hash of the block with a certain height
83
- let rpc_client = RpcClient :: from_url ( client_url) . await ?;
84
- let hash: subxt:: utils:: H256 = rpc_client
85
- . request ( "chain_getBlockHash" , rpc_params ! [ height] )
86
- . await ?;
87
-
88
- let block = client. blocks ( ) . at ( hash) . await ?;
89
-
90
- let header = block. header ( ) . clone ( ) ;
91
-
92
- let mut nmt_root = None ;
93
- for log in & header. digest . logs {
94
- match log {
95
- subxt:: config:: substrate:: DigestItem :: Other ( ref bytes) => {
96
- if bytes. starts_with ( b"snmt" ) {
97
- nmt_root = Some ( sugondat_nmt:: TreeRoot :: from_raw_bytes (
98
- bytes[ 4 ..] . try_into ( ) . unwrap ( ) ,
99
- ) ) ;
100
- break ;
101
- }
75
+ // between version 0.29 and 0.32 they remove subxt::rpc::Rpc
76
+ // so this 'raw' rpc call is required to extract the hash of the block with a certain height
77
+ let rpc_client = RpcClient :: from_url ( client_url) . await ?;
78
+ let hash: subxt:: utils:: H256 = rpc_client
79
+ . request ( "chain_getBlockHash" , rpc_params ! [ height] )
80
+ . await ?;
81
+
82
+ let block = client. blocks ( ) . at ( hash) . await ?;
83
+
84
+ let header = block. header ( ) . clone ( ) ;
85
+
86
+ let mut nmt_root = None ;
87
+ for log in & header. digest . logs {
88
+ match log {
89
+ subxt:: config:: substrate:: DigestItem :: Other ( ref bytes) => {
90
+ if bytes. starts_with ( b"snmt" ) {
91
+ nmt_root = Some ( sugondat_nmt:: TreeRoot :: from_raw_bytes (
92
+ bytes[ 4 ..] . try_into ( ) . unwrap ( ) ,
93
+ ) ) ;
94
+ break ;
102
95
}
103
- _ => { }
104
96
}
97
+ _ => { }
105
98
}
99
+ }
106
100
107
- // fetch timestamp from block
108
- let timestamp = block
109
- . storage ( )
110
- . fetch ( & storage ( ) . timestamp ( ) . now ( ) )
111
- . await ?
112
- . ok_or ( anyhow:: anyhow!( "no timestamp found" ) ) ?;
113
-
114
- let header = types:: Header :: new (
115
- types:: Hash ( hash. 0 ) ,
116
- types:: Hash ( header. parent_hash . 0 ) ,
117
- nmt_root. unwrap ( ) ,
118
- header. number as u64 ,
119
- timestamp,
120
- ) ;
121
-
122
- let mut transactions = vec ! [ ] ;
123
- for ext in block. extrinsics ( ) . await ?. iter ( ) {
124
- let ext = ext?;
125
- let Some ( address) = ext. address_bytes ( ) . map ( |a| {
126
- tracing:: info!( "Address: {:?}" , hex:: encode( & a) ) ;
127
- types:: Address :: try_from ( & a[ 1 ..] ) . unwrap ( )
128
- } ) else {
129
- continue ;
130
- } ;
131
- let Ok ( Some ( submit_blob_extrinsic) ) =
132
- ext. as_extrinsic :: < sugondat_subxt:: sugondat:: blob:: calls:: types:: SubmitBlob > ( )
133
- else {
134
- // Not a submit blob extrinsic, skip.
135
- continue ;
136
- } ;
137
-
138
- if submit_blob_extrinsic. namespace_id != namespace. namespace_id ( ) {
139
- // Not for our app.
140
- continue ;
141
- }
142
-
143
- let blob_data = submit_blob_extrinsic. blob . 0 ;
144
- tracing:: info!( "received a blob: {}" , hex:: encode( & blob_data) ) ;
145
- transactions. push ( types:: BlobTransaction :: new ( address, blob_data) ) ;
101
+ // fetch timestamp from block
102
+ let timestamp = block
103
+ . storage ( )
104
+ . fetch ( & storage ( ) . timestamp ( ) . now ( ) )
105
+ . await ?
106
+ . ok_or ( anyhow:: anyhow!( "no timestamp found" ) ) ?;
107
+
108
+ let header = types:: Header :: new (
109
+ types:: Hash ( hash. 0 ) ,
110
+ types:: Hash ( header. parent_hash . 0 ) ,
111
+ nmt_root. unwrap ( ) ,
112
+ header. number as u64 ,
113
+ timestamp,
114
+ ) ;
115
+
116
+ let mut transactions = vec ! [ ] ;
117
+ for ext in block. extrinsics ( ) . await ?. iter ( ) {
118
+ let ext = ext?;
119
+ let Some ( address) = ext. address_bytes ( ) . map ( |a| {
120
+ tracing:: info!( "Address: {:?}" , hex:: encode( & a) ) ;
121
+ types:: Address :: try_from ( & a[ 1 ..] ) . unwrap ( )
122
+ } ) else {
123
+ continue ;
124
+ } ;
125
+ let Ok ( Some ( submit_blob_extrinsic) ) =
126
+ ext. as_extrinsic :: < sugondat_subxt:: sugondat:: blob:: calls:: types:: SubmitBlob > ( )
127
+ else {
128
+ // Not a submit blob extrinsic, skip.
129
+ continue ;
130
+ } ;
131
+
132
+ if submit_blob_extrinsic. namespace_id != namespace. namespace_id ( ) {
133
+ // Not for our app.
134
+ continue ;
146
135
}
147
136
148
- let address = sugondat_subxt:: sugondat:: blob:: storage:: StorageApi . blob_list ( ) ;
149
- let blobs = client
150
- . storage ( )
151
- . at ( hash)
152
- . fetch ( & address)
153
- . await
154
- . unwrap ( )
155
- . map ( |x| x. 0 )
156
- . unwrap_or_default ( ) ;
157
-
158
- let blobs = blobs
159
- . into_iter ( )
160
- . map ( |blob| sugondat_nmt:: BlobMetadata {
161
- namespace : sugondat_nmt:: Namespace :: with_namespace_id ( blob. namespace_id ) ,
162
- leaf : sugondat_nmt:: NmtLeaf {
163
- extrinsic_index : blob. extrinsic_index ,
164
- who : blob. who . 0 ,
165
- blob_hash : blob. blob_hash ,
166
- } ,
167
- } )
168
- . collect ( ) ;
169
- let mut tree = sugondat_nmt:: tree_from_blobs ( blobs) ;
170
- let blob_proof = tree. proof ( namespace) ;
137
+ let blob_data = submit_blob_extrinsic. blob . 0 ;
138
+ tracing:: info!( "received a blob: {}" , hex:: encode( & blob_data) ) ;
139
+ transactions. push ( types:: BlobTransaction :: new ( address, blob_data) ) ;
140
+ }
171
141
172
- Ok ( types:: Block {
173
- header,
174
- transactions,
175
- blob_proof,
142
+ let address = sugondat_subxt:: sugondat:: blob:: storage:: StorageApi . blob_list ( ) ;
143
+ let blobs = client
144
+ . storage ( )
145
+ . at ( hash)
146
+ . fetch ( & address)
147
+ . await
148
+ . unwrap ( )
149
+ . map ( |x| x. 0 )
150
+ . unwrap_or_default ( ) ;
151
+
152
+ let blobs = blobs
153
+ . into_iter ( )
154
+ . map ( |blob| sugondat_nmt:: BlobMetadata {
155
+ namespace : sugondat_nmt:: Namespace :: with_namespace_id ( blob. namespace_id ) ,
156
+ leaf : sugondat_nmt:: NmtLeaf {
157
+ extrinsic_index : blob. extrinsic_index ,
158
+ who : blob. who . 0 ,
159
+ blob_hash : blob. blob_hash ,
160
+ } ,
176
161
} )
162
+ . collect ( ) ;
163
+ let mut tree = sugondat_nmt:: tree_from_blobs ( blobs) ;
164
+ let blob_proof = tree. proof ( namespace) ;
165
+
166
+ Ok ( types:: Block {
167
+ header,
168
+ transactions,
169
+ blob_proof,
177
170
} )
178
171
}
179
172
180
173
// Make an RPC call to the node to get the block at the given height
181
174
// If no such block exists, block until one does.
182
- fn get_block_at < ' life0 , ' async_trait > (
183
- & ' life0 self ,
184
- height : u64 ,
185
- ) -> Pin < Box < dyn Future < Output = Result < Self :: FilteredBlock , Self :: Error > > + Send + ' async_trait > >
186
- where
187
- Self : ' async_trait ,
188
- ' life0 : ' async_trait ,
189
- {
190
- self . get_finalized_at ( height)
175
+ async fn get_block_at ( & self , height : u64 ) -> Result < Self :: FilteredBlock , Self :: Error > {
176
+ self . get_finalized_at ( height) . await
191
177
}
192
178
193
179
// Extract the blob transactions relevant to a particular rollup from a block.
@@ -201,63 +187,38 @@ impl sov_rollup_interface::services::da::DaService for DaProvider {
201
187
block. transactions . clone ( )
202
188
}
203
189
204
- fn get_extraction_proof < ' life0 , ' life1 , ' life2 , ' async_trait > (
205
- & ' life0 self ,
206
- block : & ' life1 Self :: FilteredBlock ,
207
- blobs : & ' life2 [ <Self :: Spec as DaSpec >:: BlobTransaction ] ,
208
- ) -> Pin <
209
- Box <
210
- dyn Future <
211
- Output = (
212
- <Self :: Spec as DaSpec >:: InclusionMultiProof ,
213
- <Self :: Spec as DaSpec >:: CompletenessProof ,
214
- ) ,
215
- > + Send
216
- + ' async_trait ,
217
- > ,
218
- >
219
- where
220
- Self : ' async_trait ,
221
- ' life0 : ' async_trait ,
222
- ' life1 : ' async_trait ,
223
- ' life2 : ' async_trait ,
224
- {
225
- Box :: pin ( async { ( block. blob_proof . clone ( ) , ( ) ) } )
190
+ async fn get_extraction_proof (
191
+ & self ,
192
+ block : & Self :: FilteredBlock ,
193
+ blobs : & [ <Self :: Spec as DaSpec >:: BlobTransaction ] ,
194
+ ) -> (
195
+ <Self :: Spec as DaSpec >:: InclusionMultiProof ,
196
+ <Self :: Spec as DaSpec >:: CompletenessProof ,
197
+ ) {
198
+ ( block. blob_proof . clone ( ) , ( ) )
226
199
}
227
200
228
201
// Send the blob to the DA layer, using the submit_blob extrinsic
229
- fn send_transaction < ' life0 , ' life1 , ' async_trait > (
230
- & ' life0 self ,
231
- blob : & ' life1 [ u8 ] ,
232
- ) -> Pin < Box < dyn Future < Output = Result < ( ) , Self :: Error > > + Send + ' async_trait > >
233
- where
234
- Self : ' async_trait ,
235
- ' life0 : ' async_trait ,
236
- ' life1 : ' async_trait ,
237
- {
202
+ async fn send_transaction ( & self , blob : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
238
203
let client = self . client . clone ( ) ;
239
204
let blob = blob. to_vec ( ) ;
240
205
let namespace_id = self . namespace . namespace_id ( ) ;
241
- Box :: pin ( async move {
242
- use sp_keyring:: AccountKeyring ;
243
- use subxt:: tx:: Signer ;
244
- use subxt_signer:: sr25519:: dev;
206
+ use subxt_signer:: sr25519:: dev;
245
207
246
- let client = client. client ( ) . await ?;
208
+ let client = client. client ( ) . await ?;
247
209
248
- let extrinsic = sugondat_subxt:: sugondat:: tx ( )
249
- . blob ( )
250
- . submit_blob ( namespace_id, BoundedVec ( blob) ) ;
210
+ let extrinsic = sugondat_subxt:: sugondat:: tx ( )
211
+ . blob ( )
212
+ . submit_blob ( namespace_id, BoundedVec ( blob) ) ;
251
213
252
- let from = dev:: alice ( ) ;
253
- let _events = client
254
- . tx ( )
255
- . sign_and_submit_then_watch_default ( & extrinsic, & from)
256
- . await ?
257
- . wait_for_finalized_success ( )
258
- . await ?;
214
+ let from = dev:: alice ( ) ;
215
+ let _events = client
216
+ . tx ( )
217
+ . sign_and_submit_then_watch_default ( & extrinsic, & from)
218
+ . await ?
219
+ . wait_for_finalized_success ( )
220
+ . await ?;
259
221
260
- Ok ( ( ) )
261
- } )
222
+ Ok ( ( ) )
262
223
}
263
224
}
0 commit comments