@@ -13,8 +13,10 @@ use simplicityhl::{Arguments, CompiledProgram, TemplateProgram};
1313use simplicityhl_core:: { ProgramError , run_program} ;
1414
1515mod build_witness;
16+ mod smt;
1617
1718pub use build_witness:: { DEPTH , SMTWitness , build_smt_storage_witness, u256} ;
19+ pub use smt:: SparseMerkleTree ;
1820
1921pub const SMT_STORAGE_SOURCE : & str = include_str ! ( "source_simf/smt_storage.simf" ) ;
2022
@@ -69,7 +71,10 @@ fn smt_storage_script_ver(cmr: Cmr) -> (Script, LeafVersion) {
6971/// All hashing operations (`sha256::Hash::engine`, `input`, `from_engine`) are
7072/// infallible, and iterating over the state limbs is safe.
7173#[ must_use]
72- pub fn compute_tapdata_tagged_hash_of_the_state ( leaf : & u256 , path : & [ bool ; DEPTH ] ) -> sha256:: Hash {
74+ pub fn compute_tapdata_tagged_hash_of_the_state (
75+ leaf : & u256 ,
76+ path : & [ ( u256 , bool ) ; DEPTH ] ,
77+ ) -> sha256:: Hash {
7378 let tag = sha256:: Hash :: hash ( b"TapData" ) ;
7479 let mut eng = sha256:: Hash :: engine ( ) ;
7580 eng. input ( tag. as_byte_array ( ) ) ;
@@ -78,19 +83,15 @@ pub fn compute_tapdata_tagged_hash_of_the_state(leaf: &u256, path: &[bool; DEPTH
7883
7984 let mut current_hash = sha256:: Hash :: from_engine ( eng) ;
8085
81- // Change to valid tree hashes
82- let dummy_hash = [ 0u8 ; 32 ] ;
83-
84- for is_right_direction in path {
86+ for ( hash, is_right_direction) in path {
8587 let mut eng = sha256:: Hash :: engine ( ) ;
86- dbg ! ( * is_right_direction) ;
8788
8889 if * is_right_direction {
89- eng. input ( & dummy_hash ) ;
90+ eng. input ( hash ) ;
9091 eng. input ( & current_hash. to_byte_array ( ) ) ;
9192 } else {
9293 eng. input ( & current_hash. to_byte_array ( ) ) ;
93- eng. input ( & dummy_hash ) ;
94+ eng. input ( hash ) ;
9495 }
9596
9697 current_hash = sha256:: Hash :: from_engine ( eng) ;
@@ -111,7 +112,7 @@ pub fn compute_tapdata_tagged_hash_of_the_state(leaf: &u256, path: &[bool; DEPTH
111112pub fn smt_storage_taproot_spend_info (
112113 internal_key : secp256k1:: XOnlyPublicKey ,
113114 leaf : & u256 ,
114- path : & [ bool ; DEPTH ] ,
115+ path : & [ ( u256 , bool ) ; DEPTH ] ,
115116 cmr : Cmr ,
116117) -> TaprootSpendInfo {
117118 let ( script, version) = smt_storage_script_ver ( cmr) ;
@@ -133,6 +134,7 @@ pub fn smt_storage_taproot_spend_info(
133134mod smt_storage_tests {
134135 use super :: * ;
135136 use anyhow:: Result ;
137+ use rand:: Rng as _;
136138 use std:: sync:: Arc ;
137139
138140 use simplicityhl:: elements:: confidential:: { Asset , Value } ;
@@ -150,34 +152,55 @@ mod smt_storage_tests {
150152 . expect ( "key should be valid" )
151153 }
152154
155+ fn add_elements ( smt : & mut SparseMerkleTree , num : u64 ) -> ( u256 , [ u256 ; DEPTH ] , [ bool ; DEPTH ] ) {
156+ let mut rng = rand:: rng ( ) ;
157+
158+ let mut leaf = [ 0u8 ; 32 ] ;
159+ let mut merkle_hashes = [ [ 0u8 ; 32 ] ; DEPTH ] ;
160+ let mut path = [ false ; DEPTH ] ;
161+
162+ for _ in 0 ..num {
163+ leaf = rng. random ( ) ;
164+ path = std:: array:: from_fn ( |_| rng. random ( ) ) ;
165+ merkle_hashes = smt. update ( & leaf, path) ;
166+ }
167+
168+ ( leaf, merkle_hashes, path)
169+ }
170+
153171 #[ test]
154172 fn test_smt_storage_mint_path ( ) -> Result < ( ) > {
155- let old_leaf = [ 0u8 ; 32 ] ;
156- let mut path = [ true ; DEPTH ] ;
157- path[ 1 ] = false ;
158- path[ 4 ] = false ;
173+ let mut smt = SparseMerkleTree :: new ( ) ;
174+ let ( old_leaf, merkle_hashes, path) = add_elements ( & mut smt, 30 ) ;
175+
176+ let merkle_data =
177+ std:: array:: from_fn ( |i| ( merkle_hashes[ DEPTH - i - 1 ] , path[ DEPTH - i - 1 ] ) ) ;
159178
160- let merkle_data = path. map ( |is_right| ( [ 0u8 ; 32 ] , is_right) ) ;
161179 let witness = SMTWitness :: new ( & old_leaf, & merkle_data) ;
162180
181+ // Set last leaf qword to 1
163182 let mut new_leaf = old_leaf;
183+ for byte in new_leaf. iter_mut ( ) . skip ( 24 ) {
184+ * byte = 0 ;
185+ }
164186 new_leaf[ 31 ] = 1 ;
187+ smt. update ( & new_leaf, path) ;
165188
166189 let program = get_smt_storage_compiled_program ( ) ;
167190 let cmr = program. commit ( ) . cmr ( ) ;
168191
169- let old_spend_info = smt_storage_taproot_spend_info (
192+ let old_spend_info: TaprootSpendInfo = smt_storage_taproot_spend_info (
170193 smt_storage_unspendable_internal_key ( ) ,
171194 & old_leaf,
172- & path ,
195+ & merkle_data ,
173196 cmr,
174197 ) ;
175198 let old_script_pubkey = Script :: new_v1_p2tr_tweaked ( old_spend_info. output_key ( ) ) ;
176199
177200 let new_spend_info = smt_storage_taproot_spend_info (
178201 smt_storage_unspendable_internal_key ( ) ,
179202 & new_leaf,
180- & path ,
203+ & merkle_data ,
181204 cmr,
182205 ) ;
183206 let new_script_pubkey = Script :: new_v1_p2tr_tweaked ( new_spend_info. output_key ( ) ) ;
0 commit comments