Functions to handle commitment tree nodes for Sapling and Orchard #100

Merged
pitmutt merged 50 commits from rav001 into milestone2 2024-11-15 18:48:36 +00:00
4 changed files with 109 additions and 0 deletions
Showing only changes of commit 8f03811fca - Show all commits

View file

@ -717,6 +717,27 @@ impl<RW> FromHaskell<RW> for Hfrontier {
} }
} }
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Htree {
left: Hhex,
right: Hhex,
parents: Vec<Hhex>
}
impl<RW> ToHaskell<RW> for Htree {
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
self.serialize(writer)?;
Ok(())
}
}
impl<RW> FromHaskell<RW> for Htree {
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<RW>) -> Result<Self> {
let x = Htree::deserialize(buf)?;
Ok(x)
}
}
fn to_array<T, const N: usize>(v: Vec<T>) -> [T; N] { fn to_array<T, const N: usize>(v: Vec<T>) -> [T; N] {
v.try_into().unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len())) v.try_into().unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
} }
@ -1550,6 +1571,52 @@ pub extern "C" fn rust_wrapper_read_orchard_tree_anchor(
marshall_to_haskell_var(&h, out, out_len, RW); marshall_to_haskell_var(&h, out, out_len, RW);
} }
#[no_mangle]
pub extern "C" fn rust_wrapper_read_orchard_commitment_tree_parts(
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 comm_tree = read_commitment_tree(tree_reader);
match comm_tree {
Ok::<CommitmentTree<MerkleHashOrchard, 32>, _>(c1) => {
let left = match c1.left() {
Some(x) => {
Hhex { bytes: x.to_bytes().to_vec() }
},
None => {
Hhex { bytes: vec![0] }
}
};
let right = match c1.right() {
Some(x) => {
Hhex { bytes: x.to_bytes().to_vec() }
},
None => {
Hhex { bytes: vec![0] }
}
};
let parents = c1.parents().iter().map(|x| match x {
Some(y) => {
Hhex { bytes: y.to_bytes().to_vec() }
},
None => {
Hhex { bytes: vec![0] }
}
}).collect();
let ht = Htree { left, right, parents};
marshall_to_haskell_var(&ht, out, out_len, RW);
},
Err(_e) => {
let ht0 = Htree { left: Hhex { bytes: vec![0] } , right: Hhex { bytes: vec![0] }, parents: vec![Hhex { bytes: vec![0] }]};
marshall_to_haskell_var(&ht0, out, out_len, RW);
}
}
}
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_wrapper_read_orchard_witness_anchor( pub extern "C" fn rust_wrapper_read_orchard_witness_anchor(
wit: *const u8, wit: *const u8,

View file

@ -291,6 +291,13 @@ import ZcashHaskell.Types
-> `()' -> `()'
#} #}
{# fun unsafe rust_wrapper_read_orchard_commitment_tree_parts as rustWrapperReadOrchardTreeParts
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer OrchardRawTree'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier {# fun unsafe rust_wrapper_read_orchard_frontier as rustWrapperReadOrchardFrontier
{ toBorshVar* `BS.ByteString'& { toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer OrchardFrontier'& , getVarBuffer `Buffer OrchardFrontier'&

View file

@ -31,6 +31,7 @@ import C.Zcash
, rustWrapperReadOrchardNode , rustWrapperReadOrchardNode
, rustWrapperReadOrchardPosition , rustWrapperReadOrchardPosition
, rustWrapperReadOrchardTreeAnchor , rustWrapperReadOrchardTreeAnchor
, rustWrapperReadOrchardTreeParts
, rustWrapperReadOrchardWitness , rustWrapperReadOrchardWitness
, rustWrapperReadOrchardWitnessAnchor , rustWrapperReadOrchardWitnessAnchor
, rustWrapperUADecode , rustWrapperUADecode
@ -228,6 +229,25 @@ addOrchardNodeGetRoot :: Int -> BS.ByteString -> HexString
addOrchardNodeGetRoot l n = addOrchardNodeGetRoot l n =
withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n withPureBorshVarBuffer $ rustWrapperOrchardAddNodeTest (fromIntegral l) n
getOrchardTreeParts :: OrchardCommitmentTree -> Maybe OrchardTree
getOrchardTreeParts h =
if isBlank (ort_left tree) && isBlank (ort_right tree)
then Nothing
else Just $
OrchardTree
(parseHex $ ort_left tree)
(parseHex $ ort_right tree)
(map parseHex (ort_parents tree))
where
isBlank h = (BS.length $ hexBytes $ h) == 1
parseHex h =
if (BS.length $ hexBytes $ h) > 1
then Just h
else Nothing
tree =
withPureBorshVarBuffer $
rustWrapperReadOrchardTreeParts $ toBytes $ orchTree h
-- | Update a Orchard commitment tree -- | Update a Orchard commitment tree
updateOrchardCommitmentTree :: updateOrchardCommitmentTree ::
OrchardFrontier -- ^ the base tree OrchardFrontier -- ^ the base tree

View file

@ -727,6 +727,21 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree
{ orchTree :: HexString { orchTree :: HexString
} deriving (Eq, Prelude.Show, Read) } deriving (Eq, Prelude.Show, Read)
data OrchardRawTree = OrchardRawTree
{ ort_left :: !HexString
, ort_right :: !HexString
, ort_parents :: ![HexString]
} deriving stock (Eq, Prelude.Show, GHC.Generic)
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
deriving anyclass (Data.Structured.Show)
deriving (BorshSize, ToBorsh, FromBorsh) via AsStruct OrchardRawTree
data OrchardTree = OrchardTree
{ ot_left :: !(Maybe HexString)
, ot_right :: !(Maybe HexString)
, ot_parents :: ![Maybe HexString]
} deriving (Eq, Prelude.Show, Read)
data OrchardFrontier = OrchardFrontier data OrchardFrontier = OrchardFrontier
{ of_pos :: !Int64 { of_pos :: !Int64
, of_leaf :: !HexString , of_leaf :: !HexString