From f6546ae264a496d035d9be0609c1f517427fd5d5 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Thu, 9 Apr 2026 14:08:50 +0300 Subject: [PATCH 1/4] Add basic ProgramStorage implementation --- crates/build/src/generator.rs | 20 ++++- crates/sdk/src/program/core.rs | 76 ++++++++++++++++-- crates/sdk/src/program/error.rs | 6 ++ crates/sdk/src/program/mod.rs | 2 + crates/sdk/src/program/storage.rs | 123 ++++++++++++++++++++++++++++++ crates/sdk/src/utils.rs | 10 +++ 6 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 crates/sdk/src/program/storage.rs diff --git a/crates/build/src/generator.rs b/crates/build/src/generator.rs index 7e6a38b..7bf80ab 100644 --- a/crates/build/src/generator.rs +++ b/crates/build/src/generator.rs @@ -162,7 +162,7 @@ impl ArtifactsGenerator { let code = quote! { use simplex::include_simf; - use simplex::program::{ArgumentsTrait, Program}; + use simplex::program::{ArgumentsTrait, Program, ProgramStorage}; use simplex::simplicityhl::elements::secp256k1_zkp::XOnlyPublicKey; pub struct #program_name { @@ -178,6 +178,16 @@ impl ArtifactsGenerator { } } + pub fn new_with_storage( + public_key: XOnlyPublicKey, + arguments: impl ArgumentsTrait + 'static, + storage_slots_count: usize, + ) -> Self { + Self { + program: Program::new_with_storage(Self::SOURCE, public_key, Box::new(arguments), storage_slots_count), + } + } + pub fn get_program(&self) -> &Program { &self.program } @@ -185,6 +195,14 @@ impl ArtifactsGenerator { pub fn get_program_mut(&mut self) -> &mut Program { &mut self.program } + + pub fn get_storage(&self) -> &ProgramStorage { + self.program.storage() + } + + pub fn get_storage_mut(&mut self) -> &mut ProgramStorage { + self.program.storage_mut() + } } include_simf!(#pathdiff); diff --git a/crates/sdk/src/program/core.rs b/crates/sdk/src/program/core.rs index 3399147..bd7c96f 100644 --- a/crates/sdk/src/program/core.rs +++ b/crates/sdk/src/program/core.rs @@ -1,3 +1,4 @@ +use std::iter; use std::sync::Arc; use dyn_clone::DynClone; @@ -15,8 +16,9 @@ use simplicityhl::tracker::{DefaultTracker, TrackerLogLevel}; use super::arguments::ArgumentsTrait; use super::error::ProgramError; +use crate::program::ProgramStorage; use crate::provider::SimplicityNetwork; -use crate::utils::hash_script; +use crate::utils::{hash_script, tap_data_hash}; pub trait ProgramTrait: DynClone { fn get_env( @@ -48,6 +50,7 @@ pub struct Program { source: &'static str, pub_key: XOnlyPublicKey, arguments: Box, + storage: ProgramStorage, } dyn_clone::clone_trait_object!(ProgramTrait); @@ -150,6 +153,21 @@ impl Program { source, pub_key, arguments, + storage: ProgramStorage::default(), + } + } + + pub fn new_with_storage( + source: &'static str, + pub_key: XOnlyPublicKey, + arguments: Box, + storage_slots_count: usize, + ) -> Self { + Self { + source, + pub_key, + arguments, + storage: ProgramStorage::new(storage_slots_count), } } @@ -173,6 +191,14 @@ impl Program { hash_script(&self.get_script_pubkey(network)) } + pub fn storage(&self) -> &ProgramStorage { + &self.storage + } + + pub fn storage_mut(&mut self) -> &mut ProgramStorage { + &mut self.storage + } + fn load(&self) -> Result { let compiled = CompiledProgram::new(self.source, self.arguments.build_arguments(), true) .map_err(ProgramError::Compilation)?; @@ -186,15 +212,38 @@ impl Program { Ok((script, leaf_version())) } - // TODO: taproot storage + fn taproot_leaf_depths(total_leaves: usize) -> Vec { + assert!(total_leaves > 0, "Taproot tree must contain at least one leaf"); + + let next_pow2 = total_leaves.next_power_of_two(); + let depth = next_pow2.ilog2() as usize; + + let shallow_count = next_pow2 - total_leaves; + let deep_count = total_leaves - shallow_count; + + let mut depths = Vec::with_capacity(total_leaves); + depths.extend(iter::repeat_n(depth, deep_count)); + if depth > 0 { + depths.extend(iter::repeat_n(depth - 1, shallow_count)); + } + depths + } + fn taproot_spending_info(&self) -> Result { - let builder = taproot::TaprootBuilder::new(); + let mut builder = taproot::TaprootBuilder::new(); let (script, version) = self.script_version()?; + let depths = Self::taproot_leaf_depths(1 + self.storage.len()); - let builder = builder - .add_leaf_with_ver(0, script, version) + builder = builder + .add_leaf_with_ver(depths[0], script, version) .expect("tap tree should be valid"); + for (slot, depth) in self.storage.slots().iter().zip(depths.into_iter().skip(1)) { + builder = builder + .add_hidden(depth, tap_data_hash(slot)) + .expect("tap tree should be valid"); + } + Ok(builder .finalize(secp256k1::SECP256K1, self.pub_key) .expect("tap tree should be valid")) @@ -304,4 +353,21 @@ mod tests { assert!(program.get_env(&pst, 1, &network).is_ok()); } + + #[test] + fn test_taproot_leaf_depths_known_values() { + let cases = [ + (1, vec![0]), + (2, vec![1, 1]), + (3, vec![2, 2, 1]), + (4, vec![2, 2, 2, 2]), + (5, vec![3, 3, 2, 2, 2]), + (6, vec![3, 3, 3, 3, 2, 2]), + (8, vec![3, 3, 3, 3, 3, 3, 3, 3]), + ]; + + for (n, expected) in cases { + assert_eq!(Program::taproot_leaf_depths(n), expected, "n={n}"); + } + } } diff --git a/crates/sdk/src/program/error.rs b/crates/sdk/src/program/error.rs index b80e8e1..9efd40b 100644 --- a/crates/sdk/src/program/error.rs +++ b/crates/sdk/src/program/error.rs @@ -26,4 +26,10 @@ pub enum ProgramError { #[error("Input index exceeds u32 maximum: {0}")] InputIndexOverflow(#[from] std::num::TryFromIntError), + + #[error("Storage slot index {index} out of bounds (have {slots_count} slots)")] + StorageSlotOutOfBounds { index: usize, slots_count: usize }, + + #[error("Storage slot count mismatch: expected {expected}, got {actual}")] + StorageSlotCountMismatch { expected: usize, actual: usize }, } diff --git a/crates/sdk/src/program/mod.rs b/crates/sdk/src/program/mod.rs index 6982d16..a37790a 100644 --- a/crates/sdk/src/program/mod.rs +++ b/crates/sdk/src/program/mod.rs @@ -1,9 +1,11 @@ pub mod arguments; pub mod core; pub mod error; +pub mod storage; pub mod witness; pub use arguments::ArgumentsTrait; pub use core::{Program, ProgramTrait}; pub use error::ProgramError; +pub use storage::ProgramStorage; pub use witness::WitnessTrait; diff --git a/crates/sdk/src/program/storage.rs b/crates/sdk/src/program/storage.rs new file mode 100644 index 0000000..4cbef39 --- /dev/null +++ b/crates/sdk/src/program/storage.rs @@ -0,0 +1,123 @@ +use crate::program::ProgramError; + +#[derive(Debug, Clone, Default)] +pub struct ProgramStorage { + slots: Vec<[u8; 32]>, +} + +impl ProgramStorage { + pub fn new(slots_count: usize) -> Self { + Self { + slots: vec![[0u8; 32]; slots_count], + } + } + + pub fn set_slots(&mut self, values: &[[u8; 32]]) -> Result<(), ProgramError> { + let slots_count = self.len(); + if values.len() != slots_count { + return Err(ProgramError::StorageSlotCountMismatch { + expected: slots_count, + actual: values.len(), + }); + } + + self.slots.copy_from_slice(values); + + Ok(()) + } + + pub fn set_slot(&mut self, index: usize, new_value: [u8; 32]) -> Result<(), ProgramError> { + let slots_count = self.len(); + let slot = self + .slots + .get_mut(index) + .ok_or(ProgramError::StorageSlotOutOfBounds { index, slots_count })?; + + *slot = new_value; + + Ok(()) + } + + pub fn len(&self) -> usize { + self.slots.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn slots(&self) -> &[[u8; 32]] { + &self.slots + } + + pub fn slot(&self, index: usize) -> Option<&[u8; 32]> { + self.slots.get(index) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_initializes_requested_slot_count_with_zeros() { + let storage = ProgramStorage::new(3); + + assert_eq!(storage.len(), 3); + assert_eq!(storage.slots(), &[[0u8; 32], [0u8; 32], [0u8; 32]]); + } + + #[test] + fn set_slot_updates_value_in_place() { + let mut storage = ProgramStorage::new(2); + let value = [0xAB; 32]; + + storage.set_slot(1, value).unwrap(); + + assert_eq!(storage.slot(0), Some(&[0u8; 32])); + assert_eq!(storage.slot(1), Some(&value)); + } + + #[test] + fn set_slot_returns_error_for_out_of_bounds_index() { + let mut storage = ProgramStorage::new(1); + let err = storage.set_slot(5, [1u8; 32]).unwrap_err(); + + assert!(matches!( + err, + ProgramError::StorageSlotOutOfBounds { + index: 5, + slots_count: 1 + } + )); + } + + #[test] + fn set_slots_overwrites_all_slots_when_lengths_match() { + let mut storage = ProgramStorage::new(2); + let values = [[1u8; 32], [2u8; 32]]; + + storage.set_slots(&values).unwrap(); + + assert_eq!(storage.slots(), &values); + } + + #[test] + fn set_slots_returns_error_for_length_mismatch() { + let mut storage = ProgramStorage::new(2); + let values = [[1u8; 32]]; + let err = storage.set_slots(&values).unwrap_err(); + + assert!(matches!( + err, + ProgramError::StorageSlotCountMismatch { expected: 2, actual: 1 } + )); + } + + #[test] + fn default_storage_is_empty() { + let storage = ProgramStorage::default(); + assert_eq!(storage.len(), 0); + assert!(storage.slots().is_empty()); + } +} diff --git a/crates/sdk/src/utils.rs b/crates/sdk/src/utils.rs index d522aa0..2076ebc 100644 --- a/crates/sdk/src/utils.rs +++ b/crates/sdk/src/utils.rs @@ -1,3 +1,4 @@ +use bitcoin_hashes::HashEngine; use sha2::{Digest, Sha256}; use simplicityhl::elements::{AssetId, ContractHash, OutPoint, Script}; @@ -18,6 +19,15 @@ pub fn asset_entropy(outpoint: &OutPoint, entropy: [u8; 32]) -> sha256::Midstate AssetId::generate_asset_entropy(*outpoint, contract_hash) } +pub fn tap_data_hash(data: &[u8]) -> sha256::Hash { + let tag = sha256::Hash::hash(b"TapData"); + let mut eng = sha256::Hash::engine(); + eng.input(tag.as_byte_array()); + eng.input(tag.as_byte_array()); + eng.input(data); + sha256::Hash::from_engine(eng) +} + pub fn hash_script(script: &Script) -> [u8; 32] { let mut hasher = Sha256::new(); From e07c47c411bc382563270d4b3b0de2794b243ce7 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Fri, 10 Apr 2026 16:36:42 +0300 Subject: [PATCH 2/4] Remove unnecessary ProgramStorage struct --- crates/build/src/generator.rs | 48 +++++++----- crates/sdk/src/program/core.rs | 72 ++++++++--------- crates/sdk/src/program/error.rs | 6 -- crates/sdk/src/program/mod.rs | 2 - crates/sdk/src/program/storage.rs | 123 ------------------------------ crates/sdk/src/utils.rs | 2 + 6 files changed, 69 insertions(+), 184 deletions(-) delete mode 100644 crates/sdk/src/program/storage.rs diff --git a/crates/build/src/generator.rs b/crates/build/src/generator.rs index 7bf80ab..c21e07d 100644 --- a/crates/build/src/generator.rs +++ b/crates/build/src/generator.rs @@ -162,7 +162,7 @@ impl ArtifactsGenerator { let code = quote! { use simplex::include_simf; - use simplex::program::{ArgumentsTrait, Program, ProgramStorage}; + use simplex::program::{ArgumentsTrait, Program}; use simplex::simplicityhl::elements::secp256k1_zkp::XOnlyPublicKey; pub struct #program_name { @@ -172,36 +172,46 @@ impl ArtifactsGenerator { impl #program_name { pub const SOURCE: &'static str = #include_simf_module::#include_simf_source_const; - pub fn new(public_key: XOnlyPublicKey, arguments: impl ArgumentsTrait + 'static) -> Self { + pub fn new(arguments: impl ArgumentsTrait + 'static) -> Self { Self { - program: Program::new(Self::SOURCE, public_key, Box::new(arguments)), + program: Program::new(Self::SOURCE, Box::new(arguments)), } } - pub fn new_with_storage( - public_key: XOnlyPublicKey, - arguments: impl ArgumentsTrait + 'static, - storage_slots_count: usize, - ) -> Self { - Self { - program: Program::new_with_storage(Self::SOURCE, public_key, Box::new(arguments), storage_slots_count), - } + pub fn with_pub_key(mut self, pub_key: XOnlyPublicKey) -> Self { + self.program = self.program.with_pub_key(pub_key); + + self } - pub fn get_program(&self) -> &Program { - &self.program + pub fn with_storage_capacity(mut self, capacity: usize) -> Self { + self.program = self.program.with_storage_capacity(capacity); + + self } - pub fn get_program_mut(&mut self) -> &mut Program { - &mut self.program + pub fn set(&mut self, index: usize, new_value: [u8; 32]) { + self.program.set(index, new_value); + } + + pub fn get_storage_len(&self) -> usize { + self.program.get_storage_len() + } + + pub fn get_storage(&self) -> &[[u8; 32]] { + self.program.get_storage() } - pub fn get_storage(&self) -> &ProgramStorage { - self.program.storage() + pub fn get_storage_at(&self, index: usize) -> [u8; 32] { + self.program.get_storage_at(index) } - pub fn get_storage_mut(&mut self) -> &mut ProgramStorage { - self.program.storage_mut() + pub fn get_program(&self) -> &Program { + &self.program + } + + pub fn get_program_mut(&mut self) -> &mut Program { + &mut self.program } } diff --git a/crates/sdk/src/program/core.rs b/crates/sdk/src/program/core.rs index bd7c96f..8ba1a69 100644 --- a/crates/sdk/src/program/core.rs +++ b/crates/sdk/src/program/core.rs @@ -16,9 +16,8 @@ use simplicityhl::tracker::{DefaultTracker, TrackerLogLevel}; use super::arguments::ArgumentsTrait; use super::error::ProgramError; -use crate::program::ProgramStorage; use crate::provider::SimplicityNetwork; -use crate::utils::{hash_script, tap_data_hash}; +use crate::utils::{hash_script, tap_data_hash, tr_unspendable_key}; pub trait ProgramTrait: DynClone { fn get_env( @@ -50,7 +49,7 @@ pub struct Program { source: &'static str, pub_key: XOnlyPublicKey, arguments: Box, - storage: ProgramStorage, + storage: Vec<[u8; 32]>, } dyn_clone::clone_trait_object!(ProgramTrait); @@ -148,27 +147,43 @@ impl ProgramTrait for Program { } impl Program { - pub fn new(source: &'static str, pub_key: XOnlyPublicKey, arguments: Box) -> Self { + pub fn new(source: &'static str, arguments: Box) -> Self { Self { source, - pub_key, + pub_key: tr_unspendable_key(), arguments, - storage: ProgramStorage::default(), + storage: Vec::new(), } } - pub fn new_with_storage( - source: &'static str, - pub_key: XOnlyPublicKey, - arguments: Box, - storage_slots_count: usize, - ) -> Self { - Self { - source, - pub_key, - arguments, - storage: ProgramStorage::new(storage_slots_count), - } + pub fn with_pub_key(mut self, pub_key: XOnlyPublicKey) -> Self { + self.pub_key = pub_key; + + self + } + + pub fn with_storage_capacity(mut self, capacity: usize) -> Self { + self.storage = vec![[0u8; 32]; capacity]; + + self + } + + pub fn set(&mut self, index: usize, new_value: [u8; 32]) { + let slot = self.storage.get_mut(index).expect("Index out of bounds"); + + *slot = new_value; + } + + pub fn get_storage_len(&self) -> usize { + self.storage.len() + } + + pub fn get_storage(&self) -> &[[u8; 32]] { + &self.storage + } + + pub fn get_storage_at(&self, index: usize) -> [u8; 32] { + self.storage[index] } pub fn get_tr_address(&self, network: &SimplicityNetwork) -> Address { @@ -191,14 +206,6 @@ impl Program { hash_script(&self.get_script_pubkey(network)) } - pub fn storage(&self) -> &ProgramStorage { - &self.storage - } - - pub fn storage_mut(&mut self) -> &mut ProgramStorage { - &mut self.storage - } - fn load(&self) -> Result { let compiled = CompiledProgram::new(self.source, self.arguments.build_arguments(), true) .map_err(ProgramError::Compilation)?; @@ -223,22 +230,24 @@ impl Program { let mut depths = Vec::with_capacity(total_leaves); depths.extend(iter::repeat_n(depth, deep_count)); + if depth > 0 { depths.extend(iter::repeat_n(depth - 1, shallow_count)); } + depths } fn taproot_spending_info(&self) -> Result { let mut builder = taproot::TaprootBuilder::new(); let (script, version) = self.script_version()?; - let depths = Self::taproot_leaf_depths(1 + self.storage.len()); + let depths = Self::taproot_leaf_depths(1 + self.get_storage_len()); builder = builder .add_leaf_with_ver(depths[0], script, version) .expect("tap tree should be valid"); - for (slot, depth) in self.storage.slots().iter().zip(depths.into_iter().skip(1)) { + for (slot, depth) in self.get_storage().iter().zip(depths.into_iter().skip(1)) { builder = builder .add_hidden(depth, tap_data_hash(slot)) .expect("tap tree should be valid"); @@ -291,13 +300,8 @@ mod tests { AssetId::from_slice(&[byte; 32]).unwrap() } - fn dummy_pubkey(seed: u64) -> XOnlyPublicKey { - let mut rng = ::seed_from_u64(seed); - secp256k1::Keypair::new_global(&mut rng).x_only_public_key().0 - } - fn dummy_program() -> Program { - Program::new(DUMMY_PROGRAM, dummy_pubkey(0), Box::new(EmptyArguments)) + Program::new(DUMMY_PROGRAM, Box::new(EmptyArguments)) } fn dummy_network() -> SimplicityNetwork { diff --git a/crates/sdk/src/program/error.rs b/crates/sdk/src/program/error.rs index 9efd40b..b80e8e1 100644 --- a/crates/sdk/src/program/error.rs +++ b/crates/sdk/src/program/error.rs @@ -26,10 +26,4 @@ pub enum ProgramError { #[error("Input index exceeds u32 maximum: {0}")] InputIndexOverflow(#[from] std::num::TryFromIntError), - - #[error("Storage slot index {index} out of bounds (have {slots_count} slots)")] - StorageSlotOutOfBounds { index: usize, slots_count: usize }, - - #[error("Storage slot count mismatch: expected {expected}, got {actual}")] - StorageSlotCountMismatch { expected: usize, actual: usize }, } diff --git a/crates/sdk/src/program/mod.rs b/crates/sdk/src/program/mod.rs index a37790a..6982d16 100644 --- a/crates/sdk/src/program/mod.rs +++ b/crates/sdk/src/program/mod.rs @@ -1,11 +1,9 @@ pub mod arguments; pub mod core; pub mod error; -pub mod storage; pub mod witness; pub use arguments::ArgumentsTrait; pub use core::{Program, ProgramTrait}; pub use error::ProgramError; -pub use storage::ProgramStorage; pub use witness::WitnessTrait; diff --git a/crates/sdk/src/program/storage.rs b/crates/sdk/src/program/storage.rs deleted file mode 100644 index 4cbef39..0000000 --- a/crates/sdk/src/program/storage.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::program::ProgramError; - -#[derive(Debug, Clone, Default)] -pub struct ProgramStorage { - slots: Vec<[u8; 32]>, -} - -impl ProgramStorage { - pub fn new(slots_count: usize) -> Self { - Self { - slots: vec![[0u8; 32]; slots_count], - } - } - - pub fn set_slots(&mut self, values: &[[u8; 32]]) -> Result<(), ProgramError> { - let slots_count = self.len(); - if values.len() != slots_count { - return Err(ProgramError::StorageSlotCountMismatch { - expected: slots_count, - actual: values.len(), - }); - } - - self.slots.copy_from_slice(values); - - Ok(()) - } - - pub fn set_slot(&mut self, index: usize, new_value: [u8; 32]) -> Result<(), ProgramError> { - let slots_count = self.len(); - let slot = self - .slots - .get_mut(index) - .ok_or(ProgramError::StorageSlotOutOfBounds { index, slots_count })?; - - *slot = new_value; - - Ok(()) - } - - pub fn len(&self) -> usize { - self.slots.len() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn slots(&self) -> &[[u8; 32]] { - &self.slots - } - - pub fn slot(&self, index: usize) -> Option<&[u8; 32]> { - self.slots.get(index) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn new_initializes_requested_slot_count_with_zeros() { - let storage = ProgramStorage::new(3); - - assert_eq!(storage.len(), 3); - assert_eq!(storage.slots(), &[[0u8; 32], [0u8; 32], [0u8; 32]]); - } - - #[test] - fn set_slot_updates_value_in_place() { - let mut storage = ProgramStorage::new(2); - let value = [0xAB; 32]; - - storage.set_slot(1, value).unwrap(); - - assert_eq!(storage.slot(0), Some(&[0u8; 32])); - assert_eq!(storage.slot(1), Some(&value)); - } - - #[test] - fn set_slot_returns_error_for_out_of_bounds_index() { - let mut storage = ProgramStorage::new(1); - let err = storage.set_slot(5, [1u8; 32]).unwrap_err(); - - assert!(matches!( - err, - ProgramError::StorageSlotOutOfBounds { - index: 5, - slots_count: 1 - } - )); - } - - #[test] - fn set_slots_overwrites_all_slots_when_lengths_match() { - let mut storage = ProgramStorage::new(2); - let values = [[1u8; 32], [2u8; 32]]; - - storage.set_slots(&values).unwrap(); - - assert_eq!(storage.slots(), &values); - } - - #[test] - fn set_slots_returns_error_for_length_mismatch() { - let mut storage = ProgramStorage::new(2); - let values = [[1u8; 32]]; - let err = storage.set_slots(&values).unwrap_err(); - - assert!(matches!( - err, - ProgramError::StorageSlotCountMismatch { expected: 2, actual: 1 } - )); - } - - #[test] - fn default_storage_is_empty() { - let storage = ProgramStorage::default(); - assert_eq!(storage.len(), 0); - assert!(storage.slots().is_empty()); - } -} diff --git a/crates/sdk/src/utils.rs b/crates/sdk/src/utils.rs index 2076ebc..e506fe0 100644 --- a/crates/sdk/src/utils.rs +++ b/crates/sdk/src/utils.rs @@ -21,10 +21,12 @@ pub fn asset_entropy(outpoint: &OutPoint, entropy: [u8; 32]) -> sha256::Midstate pub fn tap_data_hash(data: &[u8]) -> sha256::Hash { let tag = sha256::Hash::hash(b"TapData"); + let mut eng = sha256::Hash::engine(); eng.input(tag.as_byte_array()); eng.input(tag.as_byte_array()); eng.input(data); + sha256::Hash::from_engine(eng) } From 191b3409c1f1e03bd847256d2608c4b38df602aa Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Fri, 10 Apr 2026 18:20:13 +0300 Subject: [PATCH 3/4] Rename set function --- crates/build/src/generator.rs | 4 ++-- crates/sdk/src/program/core.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/build/src/generator.rs b/crates/build/src/generator.rs index c21e07d..c86aab4 100644 --- a/crates/build/src/generator.rs +++ b/crates/build/src/generator.rs @@ -190,8 +190,8 @@ impl ArtifactsGenerator { self } - pub fn set(&mut self, index: usize, new_value: [u8; 32]) { - self.program.set(index, new_value); + pub fn set_storage_at(&mut self, index: usize, new_value: [u8; 32]) { + self.program.set_storage_at(index, new_value); } pub fn get_storage_len(&self) -> usize { diff --git a/crates/sdk/src/program/core.rs b/crates/sdk/src/program/core.rs index 8ba1a69..6e33d24 100644 --- a/crates/sdk/src/program/core.rs +++ b/crates/sdk/src/program/core.rs @@ -168,7 +168,7 @@ impl Program { self } - pub fn set(&mut self, index: usize, new_value: [u8; 32]) { + pub fn set_storage_at(&mut self, index: usize, new_value: [u8; 32]) { let slot = self.storage.get_mut(index).expect("Index out of bounds"); *slot = new_value; From ee2ad7c67cf199e468e56166e9ee9eb3d3f216f5 Mon Sep 17 00:00:00 2001 From: Oleh Komendant Date: Fri, 10 Apr 2026 18:34:34 +0300 Subject: [PATCH 4/4] Fix example --- .github/workflows/ci.yml | 2 ++ examples/basic/tests/basic_test.rs | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d13cd8d..39d859b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,6 +137,8 @@ jobs: env: RUSTFLAGS: -Dwarnings + # TODO: test example + ci-success: runs-on: ubuntu-latest if: always() diff --git a/examples/basic/tests/basic_test.rs b/examples/basic/tests/basic_test.rs index c898292..413aa21 100644 --- a/examples/basic/tests/basic_test.rs +++ b/examples/basic/tests/basic_test.rs @@ -2,7 +2,6 @@ use simplex::simplicityhl::elements::{Script, Txid}; use simplex::constants::DUMMY_SIGNATURE; use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; -use simplex::utils::tr_unspendable_key; use simplex_example::artifacts::p2pk::P2pkProgram; use simplex_example::artifacts::p2pk::derived_p2pk::{P2pkArguments, P2pkWitness}; @@ -14,7 +13,7 @@ fn get_p2pk(context: &simplex::TestContext) -> (P2pkProgram, Script) { public_key: signer.get_schnorr_public_key().serialize(), }; - let p2pk = P2pkProgram::new(tr_unspendable_key(), arguments); + let p2pk = P2pkProgram::new(arguments); let p2pk_script = p2pk.get_program().get_script_pubkey(context.get_network()); (p2pk, p2pk_script)