Merge pull request 'rvv040' (#63) from rvv040 into dev040

Reviewed-on: #63
This commit is contained in:
pitmutt 2024-04-17 14:26:38 +00:00 committed by Vergara Technologies LLC
commit 5abc57081a
Signed by: Vergara Technologies LLC
GPG key ID: 99DB473BB4715618
6 changed files with 178 additions and 21 deletions

View file

@ -5,6 +5,31 @@ 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.2]
### Added
- Added unction to encode a Sappling Address in Human Readable Format Using a SaplingReceiver
`encodeSaplingAddress` a zcash sapling address is returned or Nothing if the function fails
- Added decoding and encoding test
## [0.5.5.1]
### Added
- Added unction to decode a Sappling Address in Human Readable Format
`decodeSaplingAddress` returns 43 byte array containing
- Added a new Datatype `SaplingAddress`
- Added a new FFI function `rust_wrapper_decode_sapling_address` to haskell-rust interface
### Changed
- `TransparentAddress` type refactored
- `TransparentReceiver` added to replace old `TransparentAddress`
- `sha256` Function moved outside of `encodeTransparentReceiver`
## [0.5.5.0] ## [0.5.5.0]
### Added ### Added
@ -16,7 +41,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `TransparentAddress` type refactored - `TransparentAddress` type refactored
- `TransparentReceiver` added to replace old `TransparentAddress` - `TransparentReceiver` added to replace old `TransparentAddress`
- `sha256` Function moved outside of `encodeTransparentReceiver` - `sha256` Function moved outside of `encodeTransparentReceiver`
## [0.5.4.1] ## [0.5.4.1]
### Added ### Added

View file

@ -90,6 +90,7 @@ use zcash_address::{
ZcashAddress ZcashAddress
}; };
use zcash_client_backend::encoding::decode_payment_address;
use zcash_client_backend::keys::sapling::{ use zcash_client_backend::keys::sapling::{
spending_key, spending_key,
ExtendedFullViewingKey, ExtendedFullViewingKey,
@ -1256,3 +1257,50 @@ pub extern "C" fn rust_wrapper_read_sapling_position(
} }
} }
} }
#[no_mangle]
pub extern "C" fn rust_wrapper_decode_sapling_address(
sapling: *const u8,
sapling_len: usize,
out: *mut u8,
out_len: &mut usize){
let sapling_address_from_haskell : Vec<u8> = marshall_from_haskell_var(sapling, sapling_len, RW);
let sapling_address = std::str::from_utf8(&sapling_address_from_haskell).unwrap();
let mut netid = 0;
match sapling_address.find("1") {
Some(ix) => {
let netstr = &sapling_address[0..ix];
if netstr == "zs" {
netid = 1
} else {
if netstr == "ztestsapling" {
netid = 2
}
}
match decode_payment_address(netstr, sapling_address) {
Ok( t )=> {
let address_to_bytes = t.to_bytes();
let mut out_bytes_temp : [u8;44] = [0;44];
out_bytes_temp[0] = netid;
let mut iy = 1;
for ix in 0..43 {
out_bytes_temp[iy] = address_to_bytes[ix];
iy += 1;
}
let out_bytes: Vec<u8> = out_bytes_temp.to_vec();
marshall_to_haskell_var(&out_bytes, out, out_len, RW);
}
Err(e) => {
let h = vec![0];
marshall_to_haskell_var(&h, out, out_len, RW);
}
}
}
None => {
let h = vec![0];
marshall_to_haskell_var(&h, out, out_len, RW);
}
}
}

View file

@ -232,3 +232,10 @@ import ZcashHaskell.Types
-> `()' -> `()'
#} #}
{# fun unsafe rust_wrapper_decode_sapling_address as rustWrapperDecodeSaplingAddress
{ toBorshVar* `BS.ByteString'&
, getVarBuffer `Buffer (BS.ByteString)'&
}
-> `()'
#}

View file

@ -22,6 +22,7 @@ import C.Zcash
, rustWrapperReadSaplingCommitmentTree , rustWrapperReadSaplingCommitmentTree
, rustWrapperReadSaplingPosition , rustWrapperReadSaplingPosition
, rustWrapperReadSaplingWitness , rustWrapperReadSaplingWitness
, rustWrapperDecodeSaplingAddress
, rustWrapperSaplingCheck , rustWrapperSaplingCheck
, rustWrapperSaplingChgPaymentAddress , rustWrapperSaplingChgPaymentAddress
, rustWrapperSaplingDecodeEsk , rustWrapperSaplingDecodeEsk
@ -33,31 +34,35 @@ import C.Zcash
) )
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.Text as T
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText) import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
import Data.Word import Data.Word
import Foreign.Rust.Marshall.Variable import Foreign.Rust.Marshall.Variable
( withPureBorshVarBuffer ( withPureBorshVarBuffer
, withPureBorshVarBuffer , withPureBorshVarBuffer
) )
import ZcashHaskell.Types import ZcashHaskell.Types
( AccountId --import ZcashHaskell.Types
, CoinType -- ( AccountId
, DecodedNote(..) -- , CoinType
, RawData(..) -- , DecodedNote(..)
, RawTxResponse(..) -- , RawData(..)
, SaplingCommitmentTree(..) -- , RawTxResponse(..)
, SaplingReceiver(..) -- , SaplingAddress(..)
, SaplingSpendingKey(..) -- , SaplingCommitmentTree(..)
, SaplingWitness(..) -- , SaplingReceiver(..)
, Scope(..) -- , SaplingSpendingKey(..)
, Seed(..) -- , SaplingWitness(..)
, ShieldedOutput(..) -- , Scope(..)
, ToBytes(..) -- , Seed(..)
, ZcashNet(..) -- , ShieldedOutput(..)
, decodeHexText -- , ToBytes(..)
, getValue -- , ZcashNet(..)
) -- , decodeHexText
import ZcashHaskell.Utils (decodeBech32) -- , getValue
-- )
import ZcashHaskell.Utils (decodeBech32, encodeBech32, encodeBech32m)
-- | Check if given bytesting is a valid encoded shielded address -- | Check if given bytesting is a valid encoded shielded address
isValidShieldedAddress :: BS.ByteString -> Bool isValidShieldedAddress :: BS.ByteString -> Bool
@ -205,3 +210,33 @@ getSaplingWitness tree =
getSaplingNotePosition :: SaplingWitness -> Integer getSaplingNotePosition :: SaplingWitness -> Integer
getSaplingNotePosition = getSaplingNotePosition =
fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit
-- | Encode a SaplingReceiver into HRF text
encodeSaplingAddress :: ZcashNet -> SaplingReceiver -> Maybe T.Text
encodeSaplingAddress net sr = do
case net of
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
1 -> MainNet
2 -> TestNet
-- | decode a Sapling address
decodeSaplingAddress :: BS.ByteString -> Maybe SaplingAddress
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))
else Nothing
where
sa =
withPureBorshVarBuffer $
rustWrapperDecodeSaplingAddress sapling_address

View file

@ -477,6 +477,12 @@ newtype SaplingReceiver =
instance ToBytes SaplingReceiver where instance ToBytes SaplingReceiver where
getBytes (SaplingReceiver s) = s getBytes (SaplingReceiver s) = s
data SaplingAddress = SaplingAddress
{
net_type :: !ZcashNet
, sa_receiver :: !SaplingReceiver
} deriving (Eq, Prelude.Show, Read)
-- | Type to represent a Sapling Shielded Spend as provided by the @getrawtransaction@ RPC method -- | Type to represent a Sapling Shielded Spend as provided by the @getrawtransaction@ RPC method
data ShieldedSpend = ShieldedSpend data ShieldedSpend = ShieldedSpend
{ sp_cv :: !HexString { sp_cv :: !HexString

View file

@ -46,8 +46,10 @@ import Test.QuickCheck
import ZcashHaskell.Keys (generateWalletSeedPhrase, getWalletSeed) import ZcashHaskell.Keys (generateWalletSeedPhrase, getWalletSeed)
import ZcashHaskell.Orchard import ZcashHaskell.Orchard
import ZcashHaskell.Sapling import ZcashHaskell.Sapling
( decodeSaplingOutput ( decodeSaplingAddress
, decodeSaplingOutput
, decodeSaplingOutputEsk , decodeSaplingOutputEsk
, encodeSaplingAddress
, genSaplingInternalAddress , genSaplingInternalAddress
, genSaplingPaymentAddress , genSaplingPaymentAddress
, genSaplingSpendingKey , genSaplingSpendingKey
@ -75,6 +77,7 @@ import ZcashHaskell.Types
, RawTxOut(..) , RawTxOut(..)
, RawTxResponse(..) , RawTxResponse(..)
, RawZebraTx(..) , RawZebraTx(..)
, SaplingAddress(..)
, SaplingBundle(..) , SaplingBundle(..)
, SaplingCommitmentTree(..) , SaplingCommitmentTree(..)
, SaplingReceiver(..) , SaplingReceiver(..)
@ -913,6 +916,40 @@ main = do
t_rec u t_rec u
(ta_receiver <$> decodeTransparentAddress (E.encodeUtf8 tAdd)) `shouldBe` (ta_receiver <$> decodeTransparentAddress (E.encodeUtf8 tAdd)) `shouldBe`
t_rec u t_rec u
describe "Decode a Sapling Address (MainNet)" $ do
let sa =
decodeSaplingAddress
"zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
it "Try to decode a valid MainNet Sapling Address" $ do
case sa of
Nothing -> assertFailure "Failed to decode MainNet SaplingAddress"
Just s -- Sapling address decoded succesfully
-> do
let sh = encodeSaplingAddress (net_type s) (sa_receiver s)
case sh of
Nothing ->
assertFailure "Failed to encode MainNet SaplingAddress"
Just zsh -> do
print zsh
zsh `shouldBe`
"zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
describe "Decode a Sapling Address (TestNet)" $ do
let sa =
decodeSaplingAddress
"ztestsapling188csdsvhdny25am8ume03qr2026hdy03zpg5pq7jmmfxtxtct0e93p0rg80yfxvynqd4gwlwft5"
it "Try to decode a valid TestNet Sapling Address " $ do
case sa of
Nothing -> assertFailure "Failed to decode TestNet SaplingAddress"
Just s -- Sapling address decoded succesfully
-> do
let sh = encodeSaplingAddress (net_type s) (sa_receiver s)
case sh of
Nothing ->
assertFailure "Failed to encode TestNet SaplingAddress"
Just zsh -> do
print zsh
zsh `shouldBe`
"ztestsapling188csdsvhdny25am8ume03qr2026hdy03zpg5pq7jmmfxtxtct0e93p0rg80yfxvynqd4gwlwft5"
describe "Decode Sapling Output with spending key" $ do describe "Decode Sapling Output with spending key" $ do
let p = let p =
Phrase Phrase