@@ -4,35 +4,88 @@ sp1_zkvm::entrypoint!(main);
44
55use demo_stf:: MultiAddressEvmSolana ;
66use sha2:: { Digest , Sha256 } ;
7- use sov_aggregated_proof_shared:: DeferredProofInput ;
7+ use sov_aggregated_proof_shared:: { AggregatedProofWitness , DeferredProofInput } ;
88use sov_mock_da:: MockDaSpec ;
99use sov_mock_zkvm:: MockZkvm ;
1010use sov_modules_api:: configurable_spec:: ConfigurableSpec ;
1111use sov_modules_api:: da:: BlockHeaderTrait ;
1212use sov_modules_api:: execution_mode:: Zk ;
13+ use sov_modules_api:: DaSpec ;
1314use sov_modules_api:: Spec ;
1415use sov_modules_api:: StateTransitionPublicData ;
1516use sov_modules_api:: Storage ;
1617use sov_sp1_adapter:: SP1 ;
1718
1819type S = ConfigurableSpec < MockDaSpec , SP1 , MockZkvm , MultiAddressEvmSolana , Zk > ;
1920
21+ type StPubData < S : Spec , Da : DaSpec > =
22+ StateTransitionPublicData < <S as Spec >:: Address , Da , <<S as Spec >:: Storage as Storage >:: Root > ;
23+
2024pub fn main ( ) {
21- let proof_inputs = sp1_zkvm:: io:: read :: < Vec < DeferredProofInput > > ( ) ;
25+ let witness = sp1_zkvm:: io:: read :: < AggregatedProofWitness < MockDaSpec > > ( ) ;
26+ let proof_inputs = witness. proof_inputs ;
27+ let vkey_hash = witness. vkey_hash ;
28+
29+ verify :: < S , MockDaSpec > ( proof_inputs, vkey_hash) ;
30+ }
31+
32+ fn verify < S : Spec , Da : DaSpec > ( proof_inputs : Vec < DeferredProofInput < Da > > , vkey_hash : [ u32 ; 8 ] ) {
33+ assert ! (
34+ !proof_inputs. is_empty( ) ,
35+ "Aggregated proof must contain at least one proof input"
36+ ) ;
37+
38+ // `None` means no predecessor to check against (first iteration).
39+ let mut expected_prev_hash = None ;
40+ let mut expected_state_root = None ;
2241
2342 for ( index, proof_input) in proof_inputs. iter ( ) . enumerate ( ) {
24- let stf_public_data: StateTransitionPublicData <
25- <S as Spec >:: Address ,
26- MockDaSpec ,
27- <<S as Spec >:: Storage as Storage >:: Root ,
28- > = bincode:: deserialize ( proof_input. public_values . as_slice ( ) ) . unwrap ( ) ;
29-
30- let da_block_header = & proof_input. da_block_header ;
31- assert_eq ! ( da_block_header. hash( ) , stf_public_data. slot_hash) ;
32-
33- println ! ( "[guest] verifying proof {index}" ) ;
34- let public_values_digest: [ u8 ; 32 ] = Sha256 :: digest ( & proof_input. public_values ) . into ( ) ;
35- sp1_zkvm:: lib:: verify:: verify_sp1_proof ( & proof_input. vkey_hash , & public_values_digest) ;
36- println ! ( "[guest] verified proof {index}" ) ;
43+ let stf_public_data =
44+ deserialize_pub_data :: < S , Da > ( proof_input. public_values . as_slice ( ) , index) ;
45+
46+ // Check that DA blocks form a chain.
47+ {
48+ let da_block_header = & proof_input. da_block_header ;
49+ let current_block_hash = da_block_header. hash ( ) ;
50+
51+ if let Some ( expected_prev_hash) = & expected_prev_hash {
52+ assert_eq ! (
53+ expected_prev_hash,
54+ & da_block_header. prev_hash( ) ,
55+ "DA block chain broken at index {index}: prev_hash mismatch"
56+ ) ;
57+ }
58+
59+ // Check that the slot hash from the public input matches the current block hash.
60+ assert_eq ! (
61+ current_block_hash, stf_public_data. slot_hash,
62+ "Slot hash mismatch at index {index}: DA block header hash doesn't match public data"
63+ ) ;
64+ expected_prev_hash = Some ( current_block_hash) ;
65+ }
66+
67+ // Check that state roots are sequentially related by the state transition.
68+ {
69+ if let Some ( expected_state_root) = & expected_state_root {
70+ assert_eq ! (
71+ expected_state_root, & stf_public_data. initial_state_root,
72+ "State root discontinuity at index {index}: previous final_state_root != current initial_state_root"
73+ ) ;
74+ }
75+
76+ verify_sp1_proof ( proof_input, vkey_hash) ;
77+ expected_state_root = Some ( stf_public_data. final_state_root . clone ( ) ) ;
78+ }
3779 }
3880}
81+
82+ fn verify_sp1_proof < Da : DaSpec > ( proof_input : & DeferredProofInput < Da > , vkey_hash : [ u32 ; 8 ] ) {
83+ let public_values_digest: [ u8 ; 32 ] = Sha256 :: digest ( & proof_input. public_values ) . into ( ) ;
84+ sp1_zkvm:: lib:: verify:: verify_sp1_proof ( & vkey_hash, & public_values_digest) ;
85+ }
86+
87+ fn deserialize_pub_data < S : Spec , Da : DaSpec > ( data : & [ u8 ] , index : usize ) -> StPubData < S , Da > {
88+ bincode:: deserialize ( data) . unwrap_or_else ( |error| {
89+ panic ! ( "Failed to deserialize public values from proof input {index}: {error}" )
90+ } )
91+ }
0 commit comments