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/),
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]
### Added
- Added unction to generate an ExchangeAddress in Human Readable Format Using a TransparentAddress in HRF
`encodeExchangeAddress` a function to create a ExchangeAddress in HRF
`decodeExchangeAddress` a function to obtaina a TransparentAddress object from an ExchangeAddress in HRF
- Added new type ExchangeAddress
- Added function to generate an `ExchangeAddress` in Human Readable Format Using a `TransparentAddress` in HRF
- `encodeExchangeAddress` a function to create a `ExchangeAddress` in HRF
- `decodeExchangeAddress` a function to obtain a `TransparentAddress` object from an `ExchangeAddress` in HRF
- Added new type `ExchangeAddress`
### Fixed

View file

@ -1251,6 +1251,40 @@ pub extern "C" fn rust_wrapper_read_sapling_position(
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]
pub extern "C" fn rust_wrapper_read_orchard_commitment_tree(
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]
pub extern "C" fn rust_wrapper_decode_sapling_address(
sapling: *const u8,

View file

@ -259,3 +259,19 @@ import ZcashHaskell.Types
}
-> `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
, rustWrapperUADecode
, rustWrapperUfvkDecode
, rustWrapperUpdateOrchardWitness
)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
@ -219,3 +220,9 @@ getOrchardWitness tree =
getOrchardNotePosition :: OrchardWitness -> Integer
getOrchardNotePosition =
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
import C.Zcash
( rustWrapperIsShielded
( rustWrapperDecodeSaplingAddress
, rustWrapperIsShielded
, rustWrapperReadSaplingCommitmentTree
, rustWrapperReadSaplingPosition
, rustWrapperReadSaplingWitness
, rustWrapperDecodeSaplingAddress
, rustWrapperSaplingCheck
, rustWrapperSaplingChgPaymentAddress
, rustWrapperSaplingDecodeEsk
@ -31,18 +31,19 @@ import C.Zcash
, rustWrapperSaplingSpendingkey
, rustWrapperSaplingVkDecode
, rustWrapperTxParse
, rustWrapperUpdateSaplingWitness
)
import Data.Aeson
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
import qualified Data.Text as T
import Data.Word
import Foreign.Rust.Marshall.Variable
( withPureBorshVarBuffer
, withPureBorshVarBuffer
)
import ZcashHaskell.Types
import ZcashHaskell.Types
import ZcashHaskell.Utils (decodeBech32, encodeBech32, encodeBech32m)
-- | Check if given bytesting is a valid encoded shielded address
@ -192,32 +193,37 @@ getSaplingNotePosition :: SaplingWitness -> Integer
getSaplingNotePosition =
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
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
encodeSaplingAddress net sr = do
encodeSaplingAddress net sr = do
case net of
MainNet ->
Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sr)
MainNet -> Just $ encodeBech32 (C.pack sapPaymentAddressHrp) (getBytes sr)
TestNet ->
Just $ encodeBech32 (C.pack sapTestPaymentAddressHrp) (getBytes sr)
-- | Helper to get de Nework Id from FFI response
getNetId:: [Word8] -> ZcashNet
getNetId [x] = do
case x of
getNetId :: [Word8] -> ZcashNet
getNetId [x] = do
case x of
1 -> MainNet
2 -> TestNet
2 -> TestNet
-- | decode a Sapling address
decodeSaplingAddress :: BS.ByteString -> Maybe SaplingAddress
decodeSaplingAddress sapling_address = do
decodeSaplingAddress sapling_address = do
if BS.length sa > 1
then do
let sa0 = BS.unpack sa
Just $ SaplingAddress (getNetId (take 1 sa0))
$ SaplingReceiver (BS.pack (drop 1 sa0))
Just $
SaplingAddress (getNetId (take 1 sa0)) $
SaplingReceiver (BS.pack (drop 1 sa0))
else Nothing
where
sa =
withPureBorshVarBuffer $
rustWrapperDecodeSaplingAddress sapling_address
where
sa =
withPureBorshVarBuffer $ rustWrapperDecodeSaplingAddress sapling_address

View file

@ -5,7 +5,7 @@ cabal-version: 3.0
-- see: https://github.com/sol/hpack
name: zcash-haskell
version: 0.5.5.3
version: 0.5.5.4
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>
category: Blockchain