Skip to content

Commit cfc92e0

Browse files
committed
feat: add smt to rust and fill with some elements
1 parent aa8da37 commit cfc92e0

4 files changed

Lines changed: 274 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 73 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/contracts/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ simplicityhl = { workspace = true }
3939
simplicityhl-core = { workspace = true }
4040

4141
[dev-dependencies]
42-
anyhow = "1"
42+
anyhow = "1"
43+
rand = "0.9.2"

crates/contracts/src/smt_storage/mod.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ use simplicityhl::{Arguments, CompiledProgram, TemplateProgram};
1313
use simplicityhl_core::{ProgramError, run_program};
1414

1515
mod build_witness;
16+
mod smt;
1617

1718
pub use build_witness::{DEPTH, SMTWitness, build_smt_storage_witness, u256};
19+
pub use smt::SparseMerkleTree;
1820

1921
pub 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
111112
pub 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(
133134
mod 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

Comments
 (0)