diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index a234c82..9054ed0 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -738,6 +738,26 @@ impl FromHaskell for Htree { } } +#[derive(BorshSerialize, BorshDeserialize)] +pub struct Hpath { + position: u32, + path: Vec +} + +impl ToHaskell for Hpath { + fn to_haskell(&self, writer: &mut W, _tag: PhantomData) -> Result<()> { + self.serialize(writer)?; + Ok(()) + } +} + +impl FromHaskell for Hpath { + fn from_haskell(buf: &mut &[u8], _tag: PhantomData) -> Result { + let x = Hpath::deserialize(buf)?; + Ok(x) + } +} + fn to_array(v: Vec) -> [T; N] { v.try_into().unwrap_or_else(|v: Vec| panic!("Expected a Vec of length {} but it was {}", N, v.len())) } @@ -1659,6 +1679,29 @@ pub extern "C" fn rust_wrapper_read_orchard_node( } } +#[no_mangle] +pub extern "C" fn rust_wrapper_read_orchard_path_anchor( + path: *const u8, + path_len: usize, + cmx: *const u8, + cmx_len: usize, + out: *mut u8, + out_len: &mut usize + ){ + let path_in: Hpath = marshall_from_haskell_var(path, path_len, RW); + let cmx_in: Vec = marshall_from_haskell_var(cmx, cmx_len, RW); + let mk_path = orchard::tree::MerklePath::from_parts(path_in.position, to_array(path_in.path.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap()).collect())); + let nc = ExtractedNoteCommitment::from_bytes(&to_array(cmx_in)); + if nc.is_some().into() { + let anchor = mk_path.root(nc.unwrap()); + let h = Hhex { bytes: anchor.to_bytes().to_vec() }; + marshall_to_haskell_var(&h, out, out_len, RW); + } else { + let h0 = Hhex { bytes: vec![0] }; + marshall_to_haskell_var(&h0, out, out_len, RW); + } +} + #[no_mangle] pub extern "C" fn rust_wrapper_combine_orchard_nodes( level: u8, diff --git a/src/C/Zcash.chs b/src/C/Zcash.chs index 9c485d2..a896a10 100644 --- a/src/C/Zcash.chs +++ b/src/C/Zcash.chs @@ -276,6 +276,14 @@ import ZcashHaskell.Types -> `()' #} +{# fun unsafe rust_wrapper_read_orchard_path_anchor as rustWrapperReadOrchardPathAnchor + { toBorshVar* `MerklePath'& + , toBorshVar* `BS.ByteString'& + , getVarBuffer `Buffer HexString'& + } + -> `()' +#} + {# fun unsafe rust_wrapper_get_orchard_root as rustWrapperGetOrchardRootTest { `Int8' , getVarBuffer `Buffer HexString'& diff --git a/src/ZcashHaskell/Orchard.hs b/src/ZcashHaskell/Orchard.hs index e99e9e3..7991138 100644 --- a/src/ZcashHaskell/Orchard.hs +++ b/src/ZcashHaskell/Orchard.hs @@ -29,6 +29,7 @@ import C.Zcash , rustWrapperReadOrchardCommitmentTree , rustWrapperReadOrchardFrontier , rustWrapperReadOrchardNode + , rustWrapperReadOrchardPathAnchor , rustWrapperReadOrchardPosition , rustWrapperReadOrchardTreeAnchor , rustWrapperReadOrchardTreeParts @@ -249,6 +250,10 @@ getOrchardTreeParts h = withPureBorshVarBuffer $ rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h +getOrchardPathAnchor :: HexString -> MerklePath -> HexString +getOrchardPathAnchor hex p = + withPureBorshVarBuffer $ rustWrapperReadOrchardPathAnchor p (hexBytes hex) + -- | Update a Orchard commitment tree updateOrchardCommitmentTree :: OrchardFrontier -- ^ the base tree