Add witness update functionality #71

Merged
pitmutt merged 2 commits from rav001 into dev040 2024-04-26 01:00:19 +00:00
6 changed files with 127 additions and 23 deletions

View file

@ -5,14 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.5.5.4]
### Added
- Functions to update Sapling witnesses.
- Functions to update Orchard witnesses.
## [0.5.5.3] ## [0.5.5.3]
### Added ### Added
- Added unction to generate an ExchangeAddress in Human Readable Format Using a TransparentAddress in HRF - Added function to generate an `ExchangeAddress` in Human Readable Format Using a `TransparentAddress` in HRF
`encodeExchangeAddress` a function to create a ExchangeAddress in HRF - `encodeExchangeAddress` a function to create a `ExchangeAddress` in HRF
`decodeExchangeAddress` a function to obtaina a TransparentAddress object from an ExchangeAddress in HRF - `decodeExchangeAddress` a function to obtain a `TransparentAddress` object from an `ExchangeAddress` in HRF
- Added new type ExchangeAddress - Added new type `ExchangeAddress`
### Fixed ### Fixed

View file

@ -1251,6 +1251,40 @@ pub extern "C" fn rust_wrapper_read_sapling_position(
return u64::from(pos); return u64::from(pos);
} }
#[no_mangle]
pub extern "C" fn rust_wrapper_update_sapling_witness(
wit: *const u8,
wit_len: usize,
cmus: *const u8,
cmus_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let wit_in: Vec<u8> = marshall_from_haskell_var(wit, wit_len, RW);
let wit_reader = Cursor::new(wit_in);
let mut iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(wit_reader).unwrap();
let cmu: Vec<Vec<u8>> = marshall_from_haskell_var(cmus, cmus_len, RW);
for c in cmu {
let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(c));
if sap_note_comm.is_some().into() {
let n = Node::from_cmu(&sap_note_comm.unwrap());
iw.append(n);
}
}
let mut out_bytes: Vec<u8> = Vec::new();
let result = write_incremental_witness(&iw, &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] #[no_mangle]
pub extern "C" fn rust_wrapper_read_orchard_commitment_tree( pub extern "C" fn rust_wrapper_read_orchard_commitment_tree(
tree: *const u8, tree: *const u8,
@ -1340,6 +1374,40 @@ pub extern "C" fn rust_wrapper_read_orchard_position(
} }
} }
#[no_mangle]
pub extern "C" fn rust_wrapper_update_orchard_witness(
wit: *const u8,
wit_len: usize,
cm: *const u8,
cm_len: usize,
out: *mut u8,
out_len: &mut usize
) {
let wit_in: Vec<u8> = marshall_from_haskell_var(wit, wit_len, RW);
let wit_reader = Cursor::new(wit_in);
let mut iw: IncrementalWitness<MerkleHashOrchard, 32> = read_incremental_witness(wit_reader).unwrap();
let cmu: Vec<Vec<u8>> = marshall_from_haskell_var(cm, cm_len, RW);
for c in cmu {
let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(c));
if orchard_note_comm.is_some().into() {
let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap());
iw.append(n);
}
let mut out_bytes: Vec<u8> = Vec::new();
let result = write_incremental_witness(&iw, &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] #[no_mangle]
pub extern "C" fn rust_wrapper_decode_sapling_address( pub extern "C" fn rust_wrapper_decode_sapling_address(
sapling: *const u8, sapling: *const u8,

View file

@ -259,3 +259,19 @@ import ZcashHaskell.Types
} }
-> `Word64' -> `Word64'
#} #}
{# fun unsafe rust_wrapper_update_sapling_witness as rustWrapperUpdateSaplingWitness
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `[BS.ByteString]'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}
{# fun unsafe rust_wrapper_update_orchard_witness as rustWrapperUpdateOrchardWitness
{ toBorshVar* `BS.ByteString'&
, toBorshVar* `[BS.ByteString]'&
, getVarBuffer `Buffer HexString'&
}
-> `()'
#}

View file

@ -28,6 +28,7 @@ import C.Zcash
, rustWrapperReadOrchardWitness , rustWrapperReadOrchardWitness
, rustWrapperUADecode , rustWrapperUADecode
, rustWrapperUfvkDecode , rustWrapperUfvkDecode
, rustWrapperUpdateOrchardWitness
) )
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Char8 as C
@ -219,3 +220,9 @@ getOrchardWitness tree =
getOrchardNotePosition :: OrchardWitness -> Integer getOrchardNotePosition :: OrchardWitness -> Integer
getOrchardNotePosition = getOrchardNotePosition =
fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit fromIntegral . rustWrapperReadOrchardPosition . hexBytes . orchWit
updateOrchardWitness :: OrchardWitness -> [HexString] -> OrchardWitness
updateOrchardWitness wit cmus =
OrchardWitness $
withPureBorshVarBuffer $
rustWrapperUpdateOrchardWitness (toBytes $ orchWit wit) (map toBytes cmus)

View file

@ -18,11 +18,11 @@
module ZcashHaskell.Sapling where module ZcashHaskell.Sapling where
import C.Zcash import C.Zcash
( rustWrapperIsShielded ( rustWrapperDecodeSaplingAddress
, rustWrapperIsShielded
, rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingCommitmentTree
, rustWrapperReadSaplingPosition , rustWrapperReadSaplingPosition
, rustWrapperReadSaplingWitness , rustWrapperReadSaplingWitness
, rustWrapperDecodeSaplingAddress
, rustWrapperSaplingCheck , rustWrapperSaplingCheck
, rustWrapperSaplingChgPaymentAddress , rustWrapperSaplingChgPaymentAddress
, rustWrapperSaplingDecodeEsk , rustWrapperSaplingDecodeEsk
@ -31,12 +31,13 @@ import C.Zcash
, rustWrapperSaplingSpendingkey , rustWrapperSaplingSpendingkey
, rustWrapperSaplingVkDecode , rustWrapperSaplingVkDecode
, rustWrapperTxParse , rustWrapperTxParse
, rustWrapperUpdateSaplingWitness
) )
import Data.Aeson import Data.Aeson
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText) import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
import qualified Data.Text as T
import Data.Word import Data.Word
import Foreign.Rust.Marshall.Variable import Foreign.Rust.Marshall.Variable
( withPureBorshVarBuffer ( withPureBorshVarBuffer
@ -192,17 +193,22 @@ getSaplingNotePosition :: SaplingWitness -> Integer
getSaplingNotePosition = getSaplingNotePosition =
fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit
updateSaplingWitness :: SaplingWitness -> [HexString] -> SaplingWitness
updateSaplingWitness wit cmus =
SaplingWitness $
withPureBorshVarBuffer $
rustWrapperUpdateSaplingWitness (toBytes $ sapWit wit) (map toBytes cmus)
-- | Encode a SaplingReceiver into HRF text -- | Encode a SaplingReceiver into HRF text
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
encodeSaplingAddress net sr = do encodeSaplingAddress net sr = do
case net of case net of
MainNet -> MainNet -> Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sr)
Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sr)
TestNet -> TestNet ->
Just $ encodeBech32 (C.pack sapTestPaymentAddressHrp) (getBytes sr) Just $ encodeBech32 (C.pack sapTestPaymentAddressHrp) (getBytes sr)
-- | Helper to get de Nework Id from FFI response -- | Helper to get de Nework Id from FFI response
getNetId:: [Word8] -> ZcashNet getNetId :: [Word8] -> ZcashNet
getNetId [x] = do getNetId [x] = do
case x of case x of
1 -> MainNet 1 -> MainNet
@ -214,10 +220,10 @@ decodeSaplingAddress sapling_address = do
if BS.length sa > 1 if BS.length sa > 1
then do then do
let sa0 = BS.unpack sa let sa0 = BS.unpack sa
Just $ SaplingAddress (getNetId (take 1 sa0)) Just $
$ SaplingReceiver (BS.pack (drop 1 sa0)) SaplingAddress (getNetId (take 1 sa0)) $
SaplingReceiver (BS.pack (drop 1 sa0))
else Nothing else Nothing
where where
sa = sa =
withPureBorshVarBuffer $ withPureBorshVarBuffer $ rustWrapperDecodeSaplingAddress sapling_address
rustWrapperDecodeSaplingAddress sapling_address

View file

@ -5,7 +5,7 @@ cabal-version: 3.0
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: zcash-haskell name: zcash-haskell
version: 0.5.5.3 version: 0.5.5.4
synopsis: Utilities to interact with the Zcash blockchain synopsis: Utilities to interact with the Zcash blockchain
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme> description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
category: Blockchain category: Blockchain