@@ -46,6 +46,161 @@ fn bundle_to_tx(
4646 . into ( )
4747}
4848
49+ enum Error {
50+ BadMmrProof ,
51+ UnexpectedMmrProof ,
52+ BadStoragePoof ,
53+ }
54+
55+ // Helper function port from `pallet-domains`
56+ fn verify_mmr_proof_and_extract_state_root (
57+ mmr_leaf_proof : ConsensusChainMmrLeafProof < NumberFor < Block > , BlockHashFor < Block > , mmr:: Hash > ,
58+ expected_block_number : NumberFor < Block > ,
59+ ) -> Result < BlockHashFor < Block > , Error > {
60+ let leaf_data = MmrProofVerifier :: verify_proof_and_extract_leaf ( mmr_leaf_proof)
61+ . ok_or ( Error :: BadMmrProof ) ?;
62+
63+ // Ensure it is a proof of the exact block that we expected
64+ if expected_block_number != leaf_data. block_number ( ) {
65+ return Err ( Error :: UnexpectedMmrProof ) ;
66+ }
67+
68+ Ok ( leaf_data. state_root ( ) )
69+ }
70+
71+ async fn prepare_mmr_proof_and_runtime_code_proof (
72+ tokio_handle : Handle ,
73+ ) -> (
74+ ( TempDir , MockConsensusNode , EvmDomainNode ) ,
75+ NumberFor < Block > ,
76+ NumberFor < Block > ,
77+ ConsensusChainMmrLeafProof < NumberFor < Block > , BlockHashFor < Block > , mmr:: Hash > ,
78+ DomainRuntimeCodeAt < NumberFor < Block > , BlockHashFor < Block > , mmr:: Hash > ,
79+ ) {
80+ let directory = TempDir :: new ( ) . expect ( "Must be able to create temporary directory" ) ;
81+
82+ // Start Ferdie
83+ let mut ferdie = MockConsensusNode :: run (
84+ tokio_handle. clone ( ) ,
85+ Ferdie ,
86+ BasePath :: new ( directory. path ( ) . join ( "ferdie" ) ) ,
87+ ) ;
88+
89+ // Run Alice (a evm domain authority node)
90+ let alice = domain_test_service:: DomainNodeBuilder :: new (
91+ tokio_handle. clone ( ) ,
92+ BasePath :: new ( directory. path ( ) . join ( "alice" ) ) ,
93+ )
94+ . build_evm_node ( Role :: Authority , Alice , & mut ferdie)
95+ . await ;
96+
97+ produce_blocks ! ( ferdie, alice, 5 ) . await . unwrap ( ) ;
98+
99+ let consensus_block_number = ferdie. client . info ( ) . best_number ;
100+ let ( parent_consensus_number, parent_consensus_hash) = {
101+ let best_hash = ferdie. client . info ( ) . best_hash ;
102+ let header = ferdie. client . header ( best_hash) . unwrap ( ) . unwrap ( ) ;
103+ ( consensus_block_number - 1 , header. parent_hash )
104+ } ;
105+
106+ produce_blocks ! ( ferdie, alice, 1 ) . await . unwrap ( ) ;
107+
108+ let consensus_state_root_mmr_proof =
109+ sc_domains:: generate_mmr_proof ( & ferdie. client , consensus_block_number) . unwrap ( ) ;
110+
111+ let domain_runtime_code_at_proof = {
112+ let mmr_proof =
113+ sc_domains:: generate_mmr_proof ( & ferdie. client , parent_consensus_number) . unwrap ( ) ;
114+ let domain_runtime_code_proof = DomainRuntimeCodeProof :: generate (
115+ ferdie. client . as_ref ( ) ,
116+ parent_consensus_hash,
117+ 0 , // runtime_id
118+ & FPStorageKeyProvider :: new ( ferdie. client . clone ( ) ) ,
119+ )
120+ . unwrap ( ) ;
121+ DomainRuntimeCodeAt {
122+ mmr_proof,
123+ domain_runtime_code_proof,
124+ }
125+ } ;
126+
127+ (
128+ ( directory, ferdie, alice) ,
129+ consensus_block_number,
130+ parent_consensus_number,
131+ consensus_state_root_mmr_proof,
132+ domain_runtime_code_at_proof,
133+ )
134+ }
135+
136+ fn mmr_proof_and_runtime_code_proof_verification ( c : & mut Criterion ) {
137+ let rt = TokioRuntime :: new ( ) . unwrap ( ) ;
138+ let tokio_handle = rt. handle ( ) ;
139+
140+ let (
141+ ( _dir, ferdie, _alice) ,
142+ consensus_block_number,
143+ parent_consensus_block_number,
144+ consensus_state_root_mmr_proof,
145+ domain_runtime_code_proof,
146+ ) = tokio_handle. block_on ( prepare_mmr_proof_and_runtime_code_proof (
147+ tokio_handle. clone ( ) ,
148+ ) ) ;
149+ let runtime_id = 0 ;
150+ let mut overlay = OverlayedChanges :: default ( ) ;
151+ let state = ferdie
152+ . backend
153+ . state_at ( ferdie. client . info ( ) . best_hash )
154+ . unwrap ( ) ;
155+ let mut ext = Ext :: new ( & mut overlay, & state, None ) ;
156+
157+ c. bench_function ( "Consensus state root MMR proof verification" , |b| {
158+ b. iter_batched (
159+ || consensus_state_root_mmr_proof. clone ( ) ,
160+ |consensus_state_root_mmr_proof| {
161+ assert ! (
162+ sp_externalities:: set_and_run_with_externalities( & mut ext, || {
163+ verify_mmr_proof_and_extract_state_root(
164+ consensus_state_root_mmr_proof,
165+ consensus_block_number,
166+ )
167+ } )
168+ . is_ok( )
169+ ) ;
170+ } ,
171+ BatchSize :: SmallInput ,
172+ )
173+ } ) ;
174+
175+ c. bench_function ( "Domain runtime code proof verification" , |b| {
176+ b. iter_batched (
177+ || domain_runtime_code_proof. clone ( ) ,
178+ |domain_runtime_code_proof| {
179+ assert ! (
180+ sp_externalities:: set_and_run_with_externalities( & mut ext, || {
181+ let DomainRuntimeCodeAt {
182+ mmr_proof,
183+ domain_runtime_code_proof,
184+ } = domain_runtime_code_proof;
185+
186+ let state_root = verify_mmr_proof_and_extract_state_root(
187+ mmr_proof,
188+ parent_consensus_block_number,
189+ ) ?;
190+
191+ <DomainRuntimeCodeProof as BasicStorageProof <Block >>:: verify:: <
192+ StorageKeyProvider ,
193+ >( domain_runtime_code_proof, runtime_id, & state_root)
194+ . map_err( |_| Error :: BadStoragePoof )
195+ } )
196+ . is_ok( )
197+ ) ;
198+ } ,
199+ BatchSize :: SmallInput ,
200+ )
201+ } ) ;
202+ }
203+
49204async fn prepare_fraud_proof (
50205 tokio_handle : Handle ,
51206 bad_receipt_maker : impl Fn ( & mut ExecutionReceiptFor < HeaderFor < DomainBlock > , Block , Balance > )
@@ -765,6 +920,7 @@ fn invalid_bundle_weight_fraud_proof_verification(c: &mut Criterion) {
765920
766921criterion_group ! (
767922 benches,
923+ mmr_proof_and_runtime_code_proof_verification,
768924 invalid_state_transition_proof_verification,
769925 valid_bundle_proof_verification,
770926 invalid_domain_extrinsics_root_fraud_proof,
0 commit comments