Merge branch 'dev040' into rvv040
This commit is contained in:
commit
95f20adb56
6 changed files with 224 additions and 20 deletions
|
@ -17,8 +17,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `TransparentReceiver` added to replace old `TransparentAddress`
|
||||
- `sha256` Function moved outside of `encodeTransparentReceiver`
|
||||
|
||||
## [0.5.4.1]
|
||||
|
||||
### Added
|
||||
|
||||
- Functions to handle Sapling commitment trees, incremental witnesses and note positions
|
||||
|
||||
## [0.5.4.0]
|
||||
|
||||
### Added
|
||||
- Function to decode Orchard actions with a spending key
|
||||
- Functions for Bech32 encoding
|
||||
- Function to encode a Sapling address
|
||||
|
|
|
@ -6,7 +6,8 @@ use std::{
|
|||
marker::PhantomData,
|
||||
io::{
|
||||
Write,
|
||||
Cursor
|
||||
Cursor,
|
||||
Error
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -23,11 +24,20 @@ use haskell_ffi::{
|
|||
FromHaskell, HaskellSize, ToHaskell
|
||||
};
|
||||
|
||||
use incrementalmerkletree::frontier::CommitmentTree;
|
||||
use incrementalmerkletree::{
|
||||
frontier::CommitmentTree,
|
||||
witness::IncrementalWitness
|
||||
};
|
||||
|
||||
use zip32;
|
||||
|
||||
use zcash_primitives::{
|
||||
merkle_tree::{
|
||||
read_commitment_tree,
|
||||
write_commitment_tree,
|
||||
read_incremental_witness,
|
||||
write_incremental_witness
|
||||
},
|
||||
zip32::{
|
||||
Scope as SaplingScope,
|
||||
ChildIndex,
|
||||
|
@ -57,6 +67,7 @@ use zcash_primitives::{
|
|||
MerklePath,
|
||||
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
||||
PaymentAddress,
|
||||
note::ExtractedNoteCommitment as SaplingNoteCommitment,
|
||||
keys::{
|
||||
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
||||
ExpandedSpendingKey,
|
||||
|
@ -188,6 +199,14 @@ pub struct Hhex {
|
|||
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)]
|
||||
pub struct Haction {
|
||||
nf: Hhex,
|
||||
|
@ -221,7 +240,8 @@ impl Haction {
|
|||
pub struct Hnote {
|
||||
note: u64,
|
||||
recipient: Vec<u8>,
|
||||
memo: Vec<u8>
|
||||
memo: Vec<u8>,
|
||||
nullifier: Vec<u8>
|
||||
}
|
||||
|
||||
impl<RW> ToHaskell<RW> for Hnote {
|
||||
|
@ -713,6 +733,7 @@ pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
|||
note_len: usize,
|
||||
external: bool,
|
||||
net: bool,
|
||||
pos: u64,
|
||||
out: *mut u8,
|
||||
out_len: &mut usize
|
||||
){
|
||||
|
@ -740,24 +761,24 @@ pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
|||
else {zcash_note_encryption::try_note_decryption(&test_domain, &pivk, &action2)};
|
||||
match result {
|
||||
Some((n, r, m)) => {
|
||||
//let nullifier = n.nf(&nk, MerklePath<Node::from_cmu(&n.cmu()), SAPLING_DEPTH>.position());
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec() };
|
||||
let nullifier = n.nf(&nk, pos);
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: nullifier.to_vec() };
|
||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||
},
|
||||
None => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_e1) => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
|
@ -787,23 +808,23 @@ pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
|||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
|
||||
match result {
|
||||
Some((n, r, m)) => {
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec()};
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||
}
|
||||
None => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_e1) => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] , nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_e) => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
|
@ -837,17 +858,17 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt(
|
|||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||
match result {
|
||||
Some((n, r, m)) => {
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec()};
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||
}
|
||||
None => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
|
@ -885,11 +906,11 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt_sk(
|
|||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||
match result {
|
||||
Some((n, r, m)) => {
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec()};
|
||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||
}
|
||||
None => {
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||
}
|
||||
}
|
||||
|
@ -1147,3 +1168,77 @@ pub extern "C" fn rust_wrapper_bech32_encode(
|
|||
marshall_to_haskell_var(&string, out, out_len, RW);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_wrapper_read_sapling_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_wrapper_read_sapling_witness(
|
||||
tree: *const u8,
|
||||
tree_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 ct: CommitmentTree<Node, SAPLING_DEPTH> = read_commitment_tree(tree_reader).unwrap();
|
||||
let inc_wit = IncrementalWitness::from_tree(ct);
|
||||
let mut out_bytes: Vec<u8> = Vec::new();
|
||||
let result = write_incremental_witness(&inc_wit, &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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_wrapper_read_sapling_position(
|
||||
wit: *const u8,
|
||||
wit_len: usize,
|
||||
) -> u64 {
|
||||
let wit_in: Vec<u8> = marshall_from_haskell_var(wit, wit_len, RW);
|
||||
let wit_reader = Cursor::new(wit_in);
|
||||
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(wit_reader).unwrap();
|
||||
let path = iw.path();
|
||||
match path {
|
||||
Some(p) => {
|
||||
let pos = p.position();
|
||||
return u64::from(pos);
|
||||
},
|
||||
None => {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import qualified Data.Text as T
|
|||
import Data.Word
|
||||
import Data.Int
|
||||
import Data.Structured
|
||||
import Data.HexString (HexString(..))
|
||||
import Foreign.C.Types
|
||||
import Foreign.Rust.Marshall.External
|
||||
import Foreign.Rust.Marshall.Fixed
|
||||
|
@ -106,6 +107,7 @@ import ZcashHaskell.Types
|
|||
, toBorshVar* `BS.ByteString'&
|
||||
, `Bool'
|
||||
, `Bool'
|
||||
, `Word64'
|
||||
, getVarBuffer `Buffer DecodedNote'&
|
||||
}
|
||||
-> `()'
|
||||
|
@ -201,6 +203,27 @@ import ZcashHaskell.Types
|
|||
-> `()'
|
||||
#}
|
||||
|
||||
{# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree
|
||||
{ toBorshVar* `BS.ByteString'&
|
||||
, toBorshVar* `BS.ByteString'&
|
||||
, getVarBuffer `Buffer HexString'&
|
||||
}
|
||||
-> `()'
|
||||
#}
|
||||
|
||||
{# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness
|
||||
{ toBorshVar* `BS.ByteString'&
|
||||
, getVarBuffer `Buffer HexString'&
|
||||
}
|
||||
-> `()'
|
||||
#}
|
||||
|
||||
{# fun pure unsafe rust_wrapper_read_sapling_position as rustWrapperReadSaplingPosition
|
||||
{ toBorshVar* `BS.ByteString'&
|
||||
}
|
||||
-> `Word64'
|
||||
#}
|
||||
|
||||
{# fun unsafe rust_wrapper_bech32_encode as rustWrapperBech32Encode
|
||||
{ toBorshVar* `BS.ByteString'&
|
||||
, toBorshVar* `BS.ByteString'&
|
||||
|
|
|
@ -19,6 +19,9 @@ module ZcashHaskell.Sapling where
|
|||
|
||||
import C.Zcash
|
||||
( rustWrapperIsShielded
|
||||
, rustWrapperReadSaplingCommitmentTree
|
||||
, rustWrapperReadSaplingPosition
|
||||
, rustWrapperReadSaplingWitness
|
||||
, rustWrapperSaplingCheck
|
||||
, rustWrapperSaplingChgPaymentAddress
|
||||
, rustWrapperSaplingDecodeEsk
|
||||
|
@ -30,7 +33,7 @@ import C.Zcash
|
|||
)
|
||||
import Data.Aeson
|
||||
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 Foreign.Rust.Marshall.Variable
|
||||
( withPureBorshVarBuffer
|
||||
|
@ -42,8 +45,10 @@ import ZcashHaskell.Types
|
|||
, DecodedNote(..)
|
||||
, RawData(..)
|
||||
, RawTxResponse(..)
|
||||
, SaplingCommitmentTree(..)
|
||||
, SaplingReceiver(..)
|
||||
, SaplingSpendingKey(..)
|
||||
, SaplingWitness(..)
|
||||
, Scope(..)
|
||||
, Seed(..)
|
||||
, ShieldedOutput(..)
|
||||
|
@ -116,8 +121,9 @@ decodeSaplingOutputEsk ::
|
|||
-> ShieldedOutput
|
||||
-> ZcashNet
|
||||
-> Scope
|
||||
-> Integer
|
||||
-> Maybe DecodedNote
|
||||
decodeSaplingOutputEsk key out znet scope =
|
||||
decodeSaplingOutputEsk key out znet scope pos =
|
||||
case a_value decodedAction of
|
||||
0 -> Nothing
|
||||
_ -> Just decodedAction
|
||||
|
@ -129,6 +135,7 @@ decodeSaplingOutputEsk key out znet scope =
|
|||
(serializeShieldedOutput out)
|
||||
(znet == MainNet)
|
||||
(scope == External)
|
||||
(fromIntegral pos)
|
||||
|
||||
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
|
||||
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
|
||||
|
@ -166,3 +173,35 @@ genSaplingInternalAddress sk =
|
|||
where
|
||||
res =
|
||||
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
||||
|
||||
-- | Update a Sapling commitment tree
|
||||
updateSaplingCommitmentTree ::
|
||||
SaplingCommitmentTree -- ^ the base tree
|
||||
-> HexString -- ^ the new note commitment
|
||||
-> Maybe SaplingCommitmentTree
|
||||
updateSaplingCommitmentTree tree cmu =
|
||||
if BS.length (hexBytes updatedTree) > 1
|
||||
then Just $ SaplingCommitmentTree updatedTree
|
||||
else Nothing
|
||||
where
|
||||
updatedTree =
|
||||
withPureBorshVarBuffer $
|
||||
rustWrapperReadSaplingCommitmentTree
|
||||
(hexBytes $ sapTree tree)
|
||||
(hexBytes cmu)
|
||||
|
||||
-- | Get the Sapling incremental witness from a commitment tree
|
||||
getSaplingWitness :: SaplingCommitmentTree -> Maybe SaplingWitness
|
||||
getSaplingWitness tree =
|
||||
if BS.length (hexBytes wit) > 1
|
||||
then Just $ SaplingWitness wit
|
||||
else Nothing
|
||||
where
|
||||
wit =
|
||||
withPureBorshVarBuffer $
|
||||
rustWrapperReadSaplingWitness (hexBytes $ sapTree tree)
|
||||
|
||||
-- | Get the Sapling note position from a witness
|
||||
getSaplingNotePosition :: SaplingWitness -> Integer
|
||||
getSaplingNotePosition =
|
||||
fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit
|
||||
|
|
|
@ -525,6 +525,16 @@ instance FromJSON ShieldedOutput where
|
|||
p <- obj .: "proof"
|
||||
pure $ ShieldedOutput cv cmu ephKey encText outText p
|
||||
|
||||
-- | Type for a Sapling note commitment tree
|
||||
newtype SaplingCommitmentTree = SaplingCommitmentTree
|
||||
{ sapTree :: HexString
|
||||
} deriving (Eq, Prelude.Show, Read)
|
||||
|
||||
-- | Type for a Sapling incremental witness
|
||||
newtype SaplingWitness = SaplingWitness
|
||||
{ sapWit :: HexString
|
||||
} deriving (Eq, Prelude.Show, Read)
|
||||
|
||||
-- * Orchard
|
||||
-- | A spending key for Orchard
|
||||
newtype OrchardSpendingKey =
|
||||
|
|
32
test/Spec.hs
32
test/Spec.hs
|
@ -50,10 +50,13 @@ import ZcashHaskell.Sapling
|
|||
, genSaplingInternalAddress
|
||||
, genSaplingPaymentAddress
|
||||
, genSaplingSpendingKey
|
||||
, getSaplingNotePosition
|
||||
, getSaplingWitness
|
||||
, getShieldedOutputs
|
||||
, isValidSaplingViewingKey
|
||||
, isValidShieldedAddress
|
||||
, matchSaplingAddress
|
||||
, updateSaplingCommitmentTree
|
||||
)
|
||||
import ZcashHaskell.Transparent
|
||||
import ZcashHaskell.Types
|
||||
|
@ -71,6 +74,7 @@ import ZcashHaskell.Types
|
|||
, RawTxOut(..)
|
||||
, RawTxResponse(..)
|
||||
, RawZebraTx(..)
|
||||
, SaplingCommitmentTree(..)
|
||||
, SaplingReceiver(..)
|
||||
, SaplingSpendingKey(..)
|
||||
, Scope(..)
|
||||
|
@ -843,8 +847,34 @@ main = do
|
|||
Nothing -> assertFailure "Couldn't decode"
|
||||
Just t' -> do
|
||||
let tb = zt_tBundle t'
|
||||
print tb
|
||||
show tb `shouldNotBe` ""
|
||||
describe "Sapling commitment trees" $ do
|
||||
let tree =
|
||||
SaplingCommitmentTree $
|
||||
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
|
||||
t1 `shouldNotBe` Nothing
|
||||
it "Incremental witness is generated" $ do
|
||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
||||
case t1 of
|
||||
Nothing -> assertFailure "Failed to append node to tree"
|
||||
Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
||||
it "Position of note is obtained" $ do
|
||||
let p =
|
||||
getSaplingNotePosition <$>
|
||||
(getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
||||
p `shouldBe` Just 129405
|
||||
describe "Extract Sapling Address - UA Valid" $ do
|
||||
let sr =
|
||||
getSaplingFromUA
|
||||
|
|
Loading…
Reference in a new issue