@@ -3,6 +3,7 @@ use crate::{
33 types,
44 verifier:: SugondatVerifier ,
55} ;
6+ use async_trait:: async_trait;
67use sov_rollup_interface:: { da:: DaSpec , services:: da:: DaService } ;
78use std:: { future:: Future , pin:: Pin } ;
89use subxt:: backend:: rpc:: { rpc_params, RpcClient } ;
@@ -43,6 +44,7 @@ impl DaProvider {
4344 }
4445}
4546
47+ #[ async_trait]
4648impl sov_rollup_interface:: services:: da:: DaService for DaProvider {
4749 type Spec = DaLayerSpec ;
4850 type FilteredBlock = crate :: types:: Block ;
@@ -51,143 +53,127 @@ impl sov_rollup_interface::services::da::DaService for DaProvider {
5153
5254 // Make an RPC call to the node to get the finalized block at the given height, if one exists.
5355 // 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 > {
6257 let client = self . client . clone ( ) ;
6358 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 ;
7971 }
72+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
73+ }
8074
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 ;
10295 }
103- _ => { }
10496 }
97+ _ => { }
10598 }
99+ }
106100
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 ;
146135 }
147136
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+ }
171141
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+ } ,
176161 } )
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,
177170 } )
178171 }
179172
180173 // Make an RPC call to the node to get the block at the given height
181174 // 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
191177 }
192178
193179 // 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 {
201187 block. transactions . clone ( )
202188 }
203189
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 ( ) , ( ) )
226199 }
227200
228201 // 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 > {
238203 let client = self . client . clone ( ) ;
239204 let blob = blob. to_vec ( ) ;
240205 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;
245207
246- let client = client. client ( ) . await ?;
208+ let client = client. client ( ) . await ?;
247209
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) ) ;
251213
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 ?;
259221
260- Ok ( ( ) )
261- } )
222+ Ok ( ( ) )
262223 }
263224}
0 commit comments