Add function to append nodes to commitment tree
This commit is contained in:
parent
ea937f8e51
commit
27b291c49a
4 changed files with 88 additions and 2 deletions
|
@ -6,7 +6,8 @@ use std::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
io::{
|
io::{
|
||||||
Write,
|
Write,
|
||||||
Cursor
|
Cursor,
|
||||||
|
Error
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +29,10 @@ use incrementalmerkletree::frontier::CommitmentTree;
|
||||||
use zip32;
|
use zip32;
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
|
merkle_tree::{
|
||||||
|
read_commitment_tree,
|
||||||
|
write_commitment_tree
|
||||||
|
},
|
||||||
zip32::{
|
zip32::{
|
||||||
Scope as SaplingScope,
|
Scope as SaplingScope,
|
||||||
ChildIndex,
|
ChildIndex,
|
||||||
|
@ -57,6 +62,7 @@ use zcash_primitives::{
|
||||||
MerklePath,
|
MerklePath,
|
||||||
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
||||||
PaymentAddress,
|
PaymentAddress,
|
||||||
|
note::ExtractedNoteCommitment as SaplingNoteCommitment,
|
||||||
keys::{
|
keys::{
|
||||||
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
||||||
ExpandedSpendingKey,
|
ExpandedSpendingKey,
|
||||||
|
@ -187,6 +193,14 @@ pub struct Hhex {
|
||||||
bytes: Vec<u8>
|
bytes: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<RW> ToHaskell<RW> for Hhex {
|
||||||
|
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
||||||
|
self.serialize(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Haction {
|
pub struct Haction {
|
||||||
nf: Hhex,
|
nf: Hhex,
|
||||||
|
@ -1129,3 +1143,33 @@ pub extern "C" fn rust_wrapper_derive_orchard_receiver(
|
||||||
marshall_to_haskell_var(&o_rec.to_raw_address_bytes().to_vec(), out, out_len, RW);
|
marshall_to_haskell_var(&o_rec.to_raw_address_bytes().to_vec(), out, out_len, RW);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_read_commitment_tree(
|
||||||
|
tree: *const u8,
|
||||||
|
tree_len: usize,
|
||||||
|
node: *const u8,
|
||||||
|
node_len: usize,
|
||||||
|
out: *mut u8,
|
||||||
|
out_len: &mut usize
|
||||||
|
){
|
||||||
|
let tree_in: Vec<u8> = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
|
let tree_reader = Cursor::new(tree_in);
|
||||||
|
let mut ct: CommitmentTree<Node, SAPLING_DEPTH> = read_commitment_tree(tree_reader).unwrap();
|
||||||
|
|
||||||
|
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
||||||
|
let n = Node::from_cmu(&SaplingNoteCommitment::from_bytes(&to_array(node_in)).unwrap());
|
||||||
|
ct.append(n);
|
||||||
|
let mut out_bytes: Vec<u8> = Vec::new();
|
||||||
|
let result = write_commitment_tree(&ct, &mut out_bytes );
|
||||||
|
match result {
|
||||||
|
Ok(()) => {
|
||||||
|
let h = Hhex { bytes: out_bytes};
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
let h0 = Hhex { bytes: vec![0]};
|
||||||
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -200,3 +200,11 @@ import ZcashHaskell.Types
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_commitment_tree as rustWrapperReadSaplingCommitmentTree
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer (BS.ByteString)'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
|
@ -19,6 +19,7 @@ module ZcashHaskell.Sapling where
|
||||||
|
|
||||||
import C.Zcash
|
import C.Zcash
|
||||||
( rustWrapperIsShielded
|
( rustWrapperIsShielded
|
||||||
|
, rustWrapperReadSaplingCommitmentTree
|
||||||
, rustWrapperSaplingCheck
|
, rustWrapperSaplingCheck
|
||||||
, rustWrapperSaplingChgPaymentAddress
|
, rustWrapperSaplingChgPaymentAddress
|
||||||
, rustWrapperSaplingDecodeEsk
|
, rustWrapperSaplingDecodeEsk
|
||||||
|
@ -30,7 +31,7 @@ import C.Zcash
|
||||||
)
|
)
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.HexString (HexString(..), fromText, toBytes, toText)
|
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
( withPureBorshVarBuffer
|
( withPureBorshVarBuffer
|
||||||
|
@ -166,3 +167,17 @@ genSaplingInternalAddress sk =
|
||||||
where
|
where
|
||||||
res =
|
res =
|
||||||
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
||||||
|
|
||||||
|
-- | Update a Sapling commitment tree
|
||||||
|
updateSaplingCommitmentTree ::
|
||||||
|
HexString -- ^ the base tree
|
||||||
|
-> HexString -- ^ the new note commitment
|
||||||
|
-> Maybe HexString
|
||||||
|
updateSaplingCommitmentTree tree cmu =
|
||||||
|
if BS.length updatedTree > 1
|
||||||
|
then Just $ HexString updatedTree
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
updatedTree =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadSaplingCommitmentTree (hexBytes tree) (hexBytes cmu)
|
||||||
|
|
19
test/Spec.hs
19
test/Spec.hs
|
@ -54,6 +54,7 @@ import ZcashHaskell.Sapling
|
||||||
, isValidSaplingViewingKey
|
, isValidSaplingViewingKey
|
||||||
, isValidShieldedAddress
|
, isValidShieldedAddress
|
||||||
, matchSaplingAddress
|
, matchSaplingAddress
|
||||||
|
, updateSaplingCommitmentTree
|
||||||
)
|
)
|
||||||
import ZcashHaskell.Transparent
|
import ZcashHaskell.Transparent
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
|
@ -844,6 +845,24 @@ main = do
|
||||||
let tb = zt_tBundle t'
|
let tb = zt_tBundle t'
|
||||||
print tb
|
print tb
|
||||||
show tb `shouldNotBe` ""
|
show tb `shouldNotBe` ""
|
||||||
|
describe "Sapling commitment trees" $ do
|
||||||
|
let tree =
|
||||||
|
hexString
|
||||||
|
"01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
|
let cmu1 =
|
||||||
|
hexString
|
||||||
|
"45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
||||||
|
let cmu2 =
|
||||||
|
hexString
|
||||||
|
"426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
||||||
|
let tree2 =
|
||||||
|
hexString
|
||||||
|
"01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
|
it "Commitment tree is updated correctly" $ do
|
||||||
|
let t1 = updateSaplingCommitmentTree tree cmu1
|
||||||
|
case t1 of
|
||||||
|
Nothing -> assertFailure "Tree 1 failed"
|
||||||
|
Just t2 -> updateSaplingCommitmentTree t2 cmu2 `shouldBe` Just tree2
|
||||||
|
|
||||||
-- | Properties
|
-- | Properties
|
||||||
prop_PhraseLength :: Property
|
prop_PhraseLength :: Property
|
||||||
|
|
Loading…
Reference in a new issue