Compare commits
No commits in common. "95f20adb56cfae324165475af2b9b8c6deffccac" and "deacf373e117b9eb3093846e8d676848e66a6d15" have entirely different histories.
95f20adb56
...
deacf373e1
8 changed files with 53 additions and 294 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -7,25 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [0.5.5.0]
|
## [0.5.5.0]
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added unction to decode Transparent Address in Human Readable Format
|
- Added unction to decode Transparent Address in Human Readable Format
|
||||||
|
- TransparentAddress type refactored
|
||||||
### Changed
|
- TransparentReceiver added to replace old TransparentAddress
|
||||||
|
- sha256 Functionmoved outside of encodeTransparentReceiver
|
||||||
- `TransparentAddress` type refactored
|
|
||||||
- `TransparentReceiver` added to replace old `TransparentAddress`
|
|
||||||
- `sha256` Function moved outside of `encodeTransparentReceiver`
|
|
||||||
|
|
||||||
## [0.5.4.1]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Functions to handle Sapling commitment trees, incremental witnesses and note positions
|
|
||||||
|
|
||||||
## [0.5.4.0]
|
## [0.5.4.0]
|
||||||
|
|
||||||
### Added
|
|
||||||
- Function to decode Orchard actions with a spending key
|
- Function to decode Orchard actions with a spending key
|
||||||
- Functions for Bech32 encoding
|
- Functions for Bech32 encoding
|
||||||
- Function to encode a Sapling address
|
- Function to encode a Sapling address
|
||||||
|
|
|
@ -6,8 +6,7 @@ use std::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
io::{
|
io::{
|
||||||
Write,
|
Write,
|
||||||
Cursor,
|
Cursor
|
||||||
Error
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,20 +23,11 @@ use haskell_ffi::{
|
||||||
FromHaskell, HaskellSize, ToHaskell
|
FromHaskell, HaskellSize, ToHaskell
|
||||||
};
|
};
|
||||||
|
|
||||||
use incrementalmerkletree::{
|
use incrementalmerkletree::frontier::CommitmentTree;
|
||||||
frontier::CommitmentTree,
|
|
||||||
witness::IncrementalWitness
|
|
||||||
};
|
|
||||||
|
|
||||||
use zip32;
|
use zip32;
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
merkle_tree::{
|
|
||||||
read_commitment_tree,
|
|
||||||
write_commitment_tree,
|
|
||||||
read_incremental_witness,
|
|
||||||
write_incremental_witness
|
|
||||||
},
|
|
||||||
zip32::{
|
zip32::{
|
||||||
Scope as SaplingScope,
|
Scope as SaplingScope,
|
||||||
ChildIndex,
|
ChildIndex,
|
||||||
|
@ -67,7 +57,6 @@ use zcash_primitives::{
|
||||||
MerklePath,
|
MerklePath,
|
||||||
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
NOTE_COMMITMENT_TREE_DEPTH as SAPLING_DEPTH,
|
||||||
PaymentAddress,
|
PaymentAddress,
|
||||||
note::ExtractedNoteCommitment as SaplingNoteCommitment,
|
|
||||||
keys::{
|
keys::{
|
||||||
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
PreparedIncomingViewingKey as SaplingPreparedIncomingViewingKey,
|
||||||
ExpandedSpendingKey,
|
ExpandedSpendingKey,
|
||||||
|
@ -199,14 +188,6 @@ pub struct Hhex {
|
||||||
bytes: Vec<u8>
|
bytes: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Hhex {
|
|
||||||
fn to_haskell<W: Write>(&self, writer: &mut W, _tag: PhantomData<RW>) -> Result<()> {
|
|
||||||
self.serialize(writer)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(BorshSerialize, BorshDeserialize)]
|
#[derive(BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Haction {
|
pub struct Haction {
|
||||||
nf: Hhex,
|
nf: Hhex,
|
||||||
|
@ -240,8 +221,7 @@ impl Haction {
|
||||||
pub struct Hnote {
|
pub struct Hnote {
|
||||||
note: u64,
|
note: u64,
|
||||||
recipient: Vec<u8>,
|
recipient: Vec<u8>,
|
||||||
memo: Vec<u8>,
|
memo: Vec<u8>
|
||||||
nullifier: Vec<u8>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Hnote {
|
impl<RW> ToHaskell<RW> for Hnote {
|
||||||
|
@ -733,7 +713,6 @@ pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
||||||
note_len: usize,
|
note_len: usize,
|
||||||
external: bool,
|
external: bool,
|
||||||
net: bool,
|
net: bool,
|
||||||
pos: u64,
|
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
out_len: &mut usize
|
out_len: &mut usize
|
||||||
){
|
){
|
||||||
|
@ -761,24 +740,24 @@ pub extern "C" fn rust_wrapper_sapling_esk_decrypt(
|
||||||
else {zcash_note_encryption::try_note_decryption(&test_domain, &pivk, &action2)};
|
else {zcash_note_encryption::try_note_decryption(&test_domain, &pivk, &action2)};
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let nullifier = n.nf(&nk, pos);
|
//let nullifier = n.nf(&nk, MerklePath<Node::from_cmu(&n.cmu()), SAPLING_DEPTH>.position());
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: nullifier.to_vec() };
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec() };
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e1) => {
|
Err(_e1) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0] };
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -808,23 +787,23 @@ pub extern "C" fn rust_wrapper_sapling_note_decrypt_v2(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action3);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec(), nullifier: vec![0]};
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_bytes().to_vec(), memo: m.as_slice().to_vec()};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_e1) => {
|
Err(_e1) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] , nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0] };
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,17 +837,17 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec()};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -906,11 +885,11 @@ pub extern "C" fn rust_wrapper_orchard_note_decrypt_sk(
|
||||||
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
let result = zcash_note_encryption::try_note_decryption(&domain, &pivk, &action);
|
||||||
match result {
|
match result {
|
||||||
Some((n, r, m)) => {
|
Some((n, r, m)) => {
|
||||||
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec(), nullifier: vec![0]};
|
let hn = Hnote {note: n.value().inner(), recipient: r.to_raw_address_bytes().to_vec(), memo: m.to_vec()};
|
||||||
marshall_to_haskell_var(&hn, out, out_len, RW);
|
marshall_to_haskell_var(&hn, out, out_len, RW);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0], nullifier: vec![0]};
|
let hn0 = Hnote { note: 0, recipient: vec![0], memo: vec![0]};
|
||||||
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
marshall_to_haskell_var(&hn0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1168,77 +1147,3 @@ pub extern "C" fn rust_wrapper_bech32_encode(
|
||||||
marshall_to_haskell_var(&string, out, out_len, RW);
|
marshall_to_haskell_var(&string, out, out_len, RW);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rust_wrapper_read_sapling_commitment_tree(
|
|
||||||
tree: *const u8,
|
|
||||||
tree_len: usize,
|
|
||||||
node: *const u8,
|
|
||||||
node_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 mut ct: CommitmentTree<Node, SAPLING_DEPTH> = read_commitment_tree(tree_reader).unwrap();
|
|
||||||
|
|
||||||
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
|
||||||
let n = Node::from_cmu(&SaplingNoteCommitment::from_bytes(&to_array(node_in)).unwrap());
|
|
||||||
ct.append(n);
|
|
||||||
let mut out_bytes: Vec<u8> = Vec::new();
|
|
||||||
let result = write_commitment_tree(&ct, &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_sapling_witness(
|
|
||||||
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 ct: CommitmentTree<Node, SAPLING_DEPTH> = read_commitment_tree(tree_reader).unwrap();
|
|
||||||
let inc_wit = IncrementalWitness::from_tree(ct);
|
|
||||||
let mut out_bytes: Vec<u8> = Vec::new();
|
|
||||||
let result = write_incremental_witness(&inc_wit, &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_sapling_position(
|
|
||||||
wit: *const u8,
|
|
||||||
wit_len: usize,
|
|
||||||
) -> u64 {
|
|
||||||
let wit_in: Vec<u8> = marshall_from_haskell_var(wit, wit_len, RW);
|
|
||||||
let wit_reader = Cursor::new(wit_in);
|
|
||||||
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(wit_reader).unwrap();
|
|
||||||
let path = iw.path();
|
|
||||||
match path {
|
|
||||||
Some(p) => {
|
|
||||||
let pos = p.position();
|
|
||||||
return u64::from(pos);
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import qualified Data.Text as T
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Data.Int
|
import Data.Int
|
||||||
import Data.Structured
|
import Data.Structured
|
||||||
import Data.HexString (HexString(..))
|
|
||||||
import Foreign.C.Types
|
import Foreign.C.Types
|
||||||
import Foreign.Rust.Marshall.External
|
import Foreign.Rust.Marshall.External
|
||||||
import Foreign.Rust.Marshall.Fixed
|
import Foreign.Rust.Marshall.Fixed
|
||||||
|
@ -107,7 +106,6 @@ import ZcashHaskell.Types
|
||||||
, toBorshVar* `BS.ByteString'&
|
, toBorshVar* `BS.ByteString'&
|
||||||
, `Bool'
|
, `Bool'
|
||||||
, `Bool'
|
, `Bool'
|
||||||
, `Word64'
|
|
||||||
, getVarBuffer `Buffer DecodedNote'&
|
, getVarBuffer `Buffer DecodedNote'&
|
||||||
}
|
}
|
||||||
-> `()'
|
-> `()'
|
||||||
|
@ -203,27 +201,6 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_sapling_commitment_tree as rustWrapperReadSaplingCommitmentTree
|
|
||||||
{ toBorshVar* `BS.ByteString'&
|
|
||||||
, toBorshVar* `BS.ByteString'&
|
|
||||||
, getVarBuffer `Buffer HexString'&
|
|
||||||
}
|
|
||||||
-> `()'
|
|
||||||
#}
|
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_sapling_witness as rustWrapperReadSaplingWitness
|
|
||||||
{ toBorshVar* `BS.ByteString'&
|
|
||||||
, getVarBuffer `Buffer HexString'&
|
|
||||||
}
|
|
||||||
-> `()'
|
|
||||||
#}
|
|
||||||
|
|
||||||
{# fun pure unsafe rust_wrapper_read_sapling_position as rustWrapperReadSaplingPosition
|
|
||||||
{ toBorshVar* `BS.ByteString'&
|
|
||||||
}
|
|
||||||
-> `Word64'
|
|
||||||
#}
|
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_bech32_encode as rustWrapperBech32Encode
|
{# fun unsafe rust_wrapper_bech32_encode as rustWrapperBech32Encode
|
||||||
{ toBorshVar* `BS.ByteString'&
|
{ toBorshVar* `BS.ByteString'&
|
||||||
, toBorshVar* `BS.ByteString'&
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
|
|
@ -19,9 +19,6 @@ module ZcashHaskell.Sapling where
|
||||||
|
|
||||||
import C.Zcash
|
import C.Zcash
|
||||||
( rustWrapperIsShielded
|
( rustWrapperIsShielded
|
||||||
, rustWrapperReadSaplingCommitmentTree
|
|
||||||
, rustWrapperReadSaplingPosition
|
|
||||||
, rustWrapperReadSaplingWitness
|
|
||||||
, rustWrapperSaplingCheck
|
, rustWrapperSaplingCheck
|
||||||
, rustWrapperSaplingChgPaymentAddress
|
, rustWrapperSaplingChgPaymentAddress
|
||||||
, rustWrapperSaplingDecodeEsk
|
, rustWrapperSaplingDecodeEsk
|
||||||
|
@ -33,7 +30,7 @@ import C.Zcash
|
||||||
)
|
)
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.HexString (HexString(..), fromText, hexString, toBytes, toText)
|
import Data.HexString (HexString(..), fromText, toBytes, toText)
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Foreign.Rust.Marshall.Variable
|
import Foreign.Rust.Marshall.Variable
|
||||||
( withPureBorshVarBuffer
|
( withPureBorshVarBuffer
|
||||||
|
@ -45,10 +42,8 @@ import ZcashHaskell.Types
|
||||||
, DecodedNote(..)
|
, DecodedNote(..)
|
||||||
, RawData(..)
|
, RawData(..)
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
, SaplingCommitmentTree(..)
|
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
, SaplingWitness(..)
|
|
||||||
, Scope(..)
|
, Scope(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
|
@ -121,9 +116,8 @@ decodeSaplingOutputEsk ::
|
||||||
-> ShieldedOutput
|
-> ShieldedOutput
|
||||||
-> ZcashNet
|
-> ZcashNet
|
||||||
-> Scope
|
-> Scope
|
||||||
-> Integer
|
|
||||||
-> Maybe DecodedNote
|
-> Maybe DecodedNote
|
||||||
decodeSaplingOutputEsk key out znet scope pos =
|
decodeSaplingOutputEsk key out znet scope =
|
||||||
case a_value decodedAction of
|
case a_value decodedAction of
|
||||||
0 -> Nothing
|
0 -> Nothing
|
||||||
_ -> Just decodedAction
|
_ -> Just decodedAction
|
||||||
|
@ -135,7 +129,6 @@ decodeSaplingOutputEsk key out znet scope pos =
|
||||||
(serializeShieldedOutput out)
|
(serializeShieldedOutput out)
|
||||||
(znet == MainNet)
|
(znet == MainNet)
|
||||||
(scope == External)
|
(scope == External)
|
||||||
(fromIntegral pos)
|
|
||||||
|
|
||||||
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
|
-- | Attempts to obtain a sapling SpendingKey using a HDSeed
|
||||||
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
|
genSaplingSpendingKey :: Seed -> CoinType -> Int -> Maybe SaplingSpendingKey
|
||||||
|
@ -173,35 +166,3 @@ genSaplingInternalAddress sk =
|
||||||
where
|
where
|
||||||
res =
|
res =
|
||||||
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
withPureBorshVarBuffer (rustWrapperSaplingChgPaymentAddress $ getBytes sk)
|
||||||
|
|
||||||
-- | Update a Sapling commitment tree
|
|
||||||
updateSaplingCommitmentTree ::
|
|
||||||
SaplingCommitmentTree -- ^ the base tree
|
|
||||||
-> HexString -- ^ the new note commitment
|
|
||||||
-> Maybe SaplingCommitmentTree
|
|
||||||
updateSaplingCommitmentTree tree cmu =
|
|
||||||
if BS.length (hexBytes updatedTree) > 1
|
|
||||||
then Just $ SaplingCommitmentTree updatedTree
|
|
||||||
else Nothing
|
|
||||||
where
|
|
||||||
updatedTree =
|
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperReadSaplingCommitmentTree
|
|
||||||
(hexBytes $ sapTree tree)
|
|
||||||
(hexBytes cmu)
|
|
||||||
|
|
||||||
-- | Get the Sapling incremental witness from a commitment tree
|
|
||||||
getSaplingWitness :: SaplingCommitmentTree -> Maybe SaplingWitness
|
|
||||||
getSaplingWitness tree =
|
|
||||||
if BS.length (hexBytes wit) > 1
|
|
||||||
then Just $ SaplingWitness wit
|
|
||||||
else Nothing
|
|
||||||
where
|
|
||||||
wit =
|
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperReadSaplingWitness (hexBytes $ sapTree tree)
|
|
||||||
|
|
||||||
-- | Get the Sapling note position from a witness
|
|
||||||
getSaplingNotePosition :: SaplingWitness -> Integer
|
|
||||||
getSaplingNotePosition =
|
|
||||||
fromIntegral . rustWrapperReadSaplingPosition . hexBytes . sapWit
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ import Crypto.Hash
|
||||||
import Crypto.Secp256k1
|
import Crypto.Secp256k1
|
||||||
import qualified Data.ByteArray as BA
|
import qualified Data.ByteArray as BA
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
import Data.ByteString.Base58 (bitcoinAlphabet, encodeBase58, decodeBase58)
|
||||||
import Data.Char (chr)
|
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
import Data.Word
|
import Data.Word
|
||||||
|
import Data.Char (chr)
|
||||||
import Haskoin.Address (Address(..))
|
import Haskoin.Address (Address(..))
|
||||||
import qualified Haskoin.Crypto.Hash as H
|
import qualified Haskoin.Crypto.Hash as H
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
|
@ -35,8 +35,8 @@ import ZcashHaskell.Types
|
||||||
, Scope(..)
|
, Scope(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ToBytes(..)
|
, ToBytes(..)
|
||||||
, TransparentAddress(..)
|
|
||||||
, TransparentReceiver(..)
|
, TransparentReceiver(..)
|
||||||
|
, TransparentAddress(..)
|
||||||
, TransparentSpendingKey(..)
|
, TransparentSpendingKey(..)
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
, ZcashNet(..)
|
, ZcashNet(..)
|
||||||
|
@ -101,44 +101,31 @@ genTransparentReceiver i scope xprvk = do
|
||||||
-- } decode a Transparent Address in HRF and return a TransparentAddress object
|
-- } decode a Transparent Address in HRF and return a TransparentAddress object
|
||||||
decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress
|
decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress
|
||||||
decodeTransparentAddress taddress = do
|
decodeTransparentAddress taddress = do
|
||||||
if BS.length taddress < 34
|
if BS.length taddress < 34
|
||||||
then Nothing -- Not a valid transparent address
|
then Nothing -- Not a valid transparent address
|
||||||
else do
|
else do
|
||||||
let maybeDecoded = decodeBase58 bitcoinAlphabet taddress
|
let maybeDecoded = decodeBase58 bitcoinAlphabet taddress
|
||||||
case maybeDecoded of
|
case maybeDecoded of
|
||||||
Nothing -> Nothing
|
Nothing -> Nothing
|
||||||
Just decoded -> do
|
Just decoded -> do
|
||||||
let digest = BS.take 22 decoded
|
let digest = BS.take 22 decoded
|
||||||
let chksum = BS.drop 22 decoded
|
let chksum = BS.drop 22 decoded
|
||||||
let chksumd = BS.take 4 (sha256 $ sha256 digest)
|
let chksumd = BS.take 4 (sha256 $ sha256 digest)
|
||||||
if chksum /= chksumd
|
if chksum /= chksum
|
||||||
then Nothing -- Invalid address ( invalid checksum )
|
then Nothing -- Invalid address ( invalid checksum )
|
||||||
-- build the TransparentAddress Object
|
|
||||||
else do
|
else do
|
||||||
|
-- build the TransparentAddress Object
|
||||||
let addressType = BS.take 2 digest
|
let addressType = BS.take 2 digest
|
||||||
let transparentReceiver = BS.drop 2 digest
|
let transparentReceiver = BS.drop 2 digest
|
||||||
let fb = BS.index addressType 0
|
let fb = BS.index addressType 0
|
||||||
let sb = BS.index addressType 1
|
let sb = BS.index addressType 1
|
||||||
case fb of
|
case fb of
|
||||||
28 ->
|
28 -> case sb of
|
||||||
case sb of
|
189 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2SH (fromRawBytes digest)
|
||||||
189 ->
|
186 -> Just $ TransparentAddress TestNet $ TransparentReceiver P2SH (fromRawBytes digest)
|
||||||
Just $
|
184 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2PKH (fromRawBytes digest)
|
||||||
TransparentAddress MainNet $
|
_ -> Nothing
|
||||||
TransparentReceiver P2SH (fromRawBytes digest)
|
29 -> if sb == 37
|
||||||
186 ->
|
then Just $ TransparentAddress TestNet $ TransparentReceiver P2PKH (fromRawBytes digest)
|
||||||
Just $
|
else Nothing
|
||||||
TransparentAddress TestNet $
|
_ -> Nothing
|
||||||
TransparentReceiver P2SH (fromRawBytes digest)
|
|
||||||
184 ->
|
|
||||||
Just $
|
|
||||||
TransparentAddress MainNet $
|
|
||||||
TransparentReceiver P2PKH (fromRawBytes digest)
|
|
||||||
_ -> Nothing
|
|
||||||
29 ->
|
|
||||||
if sb == 37
|
|
||||||
then Just $
|
|
||||||
TransparentAddress TestNet $
|
|
||||||
TransparentReceiver P2PKH (fromRawBytes digest)
|
|
||||||
else Nothing
|
|
||||||
_ -> Nothing
|
|
||||||
|
|
|
@ -525,16 +525,6 @@ instance FromJSON ShieldedOutput where
|
||||||
p <- obj .: "proof"
|
p <- obj .: "proof"
|
||||||
pure $ ShieldedOutput cv cmu ephKey encText outText p
|
pure $ ShieldedOutput cv cmu ephKey encText outText p
|
||||||
|
|
||||||
-- | Type for a Sapling note commitment tree
|
|
||||||
newtype SaplingCommitmentTree = SaplingCommitmentTree
|
|
||||||
{ sapTree :: HexString
|
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
|
||||||
|
|
||||||
-- | Type for a Sapling incremental witness
|
|
||||||
newtype SaplingWitness = SaplingWitness
|
|
||||||
{ sapWit :: HexString
|
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
|
||||||
|
|
||||||
-- * Orchard
|
-- * Orchard
|
||||||
-- | A spending key for Orchard
|
-- | A spending key for Orchard
|
||||||
newtype OrchardSpendingKey =
|
newtype OrchardSpendingKey =
|
||||||
|
|
61
test/Spec.hs
61
test/Spec.hs
|
@ -50,13 +50,10 @@ import ZcashHaskell.Sapling
|
||||||
, genSaplingInternalAddress
|
, genSaplingInternalAddress
|
||||||
, genSaplingPaymentAddress
|
, genSaplingPaymentAddress
|
||||||
, genSaplingSpendingKey
|
, genSaplingSpendingKey
|
||||||
, getSaplingNotePosition
|
|
||||||
, getSaplingWitness
|
|
||||||
, getShieldedOutputs
|
, getShieldedOutputs
|
||||||
, isValidSaplingViewingKey
|
, isValidSaplingViewingKey
|
||||||
, isValidShieldedAddress
|
, isValidShieldedAddress
|
||||||
, matchSaplingAddress
|
, matchSaplingAddress
|
||||||
, updateSaplingCommitmentTree
|
|
||||||
)
|
)
|
||||||
import ZcashHaskell.Transparent
|
import ZcashHaskell.Transparent
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
|
@ -74,16 +71,15 @@ import ZcashHaskell.Types
|
||||||
, RawTxOut(..)
|
, RawTxOut(..)
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
, RawZebraTx(..)
|
, RawZebraTx(..)
|
||||||
, SaplingCommitmentTree(..)
|
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
, Scope(..)
|
, Scope(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
, ToBytes(..)
|
, ToBytes(..)
|
||||||
|
, TransparentReceiver(..)
|
||||||
, TransparentAddress(..)
|
, TransparentAddress(..)
|
||||||
, TransparentBundle(..)
|
, TransparentBundle(..)
|
||||||
, TransparentReceiver(..)
|
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
, UnifiedAddress(..)
|
, UnifiedAddress(..)
|
||||||
, UnifiedFullViewingKey(..)
|
, UnifiedFullViewingKey(..)
|
||||||
|
@ -847,50 +843,18 @@ main = do
|
||||||
Nothing -> assertFailure "Couldn't decode"
|
Nothing -> assertFailure "Couldn't decode"
|
||||||
Just t' -> do
|
Just t' -> do
|
||||||
let tb = zt_tBundle t'
|
let tb = zt_tBundle t'
|
||||||
|
print tb
|
||||||
show tb `shouldNotBe` ""
|
show tb `shouldNotBe` ""
|
||||||
describe "Sapling commitment trees" $ do
|
|
||||||
let tree =
|
|
||||||
SaplingCommitmentTree $
|
|
||||||
hexString
|
|
||||||
"01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
|
||||||
let cmu1 =
|
|
||||||
hexString
|
|
||||||
"45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
|
||||||
let cmu2 =
|
|
||||||
hexString
|
|
||||||
"426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
|
||||||
let tree2 =
|
|
||||||
hexString
|
|
||||||
"01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
|
||||||
it "Commitment tree is updated correctly" $ do
|
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
|
||||||
t1 `shouldNotBe` Nothing
|
|
||||||
it "Incremental witness is generated" $ do
|
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
|
||||||
case t1 of
|
|
||||||
Nothing -> assertFailure "Failed to append node to tree"
|
|
||||||
Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
|
||||||
it "Position of note is obtained" $ do
|
|
||||||
let p =
|
|
||||||
getSaplingNotePosition <$>
|
|
||||||
(getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
|
||||||
p `shouldBe` Just 129405
|
|
||||||
describe "Extract Sapling Address - UA Valid" $ do
|
describe "Extract Sapling Address - UA Valid" $ do
|
||||||
let sr =
|
let sr = getSaplingFromUA "u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
||||||
getSaplingFromUA
|
|
||||||
"u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
|
||||||
it "Extract sapling address" $ do
|
it "Extract sapling address" $ do
|
||||||
case sr of
|
case sr of
|
||||||
Nothing ->
|
Nothing -> assertFailure "UA invalid or does not contain a Sapling receiver"
|
||||||
assertFailure "UA invalid or does not contain a Sapling receiver"
|
|
||||||
Just t -> do
|
Just t -> do
|
||||||
print t
|
print t
|
||||||
t `shouldBe`
|
t `shouldBe` "zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
|
||||||
"zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
|
|
||||||
describe "Extract Sapling Address - UA Invalid" $ do
|
describe "Extract Sapling Address - UA Invalid" $ do
|
||||||
let sr =
|
let sr = getSaplingFromUA "u14a5c4ufn9qfevxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
||||||
getSaplingFromUA
|
|
||||||
"u14a5c4ufn9qfevxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
|
||||||
it "Try to extract sapling address from invalid UA" $ do
|
it "Try to extract sapling address from invalid UA" $ do
|
||||||
sr `shouldBe` Nothing
|
sr `shouldBe` Nothing
|
||||||
describe "Decode a Transparent Address" $ do
|
describe "Decode a Transparent Address" $ do
|
||||||
|
@ -898,19 +862,6 @@ main = do
|
||||||
it "Try to decode a valid Transparent Address" $ do
|
it "Try to decode a valid Transparent Address" $ do
|
||||||
print ta
|
print ta
|
||||||
ta `shouldNotBe` Nothing
|
ta `shouldNotBe` Nothing
|
||||||
it "Encode and decode should be the same" $ do
|
|
||||||
let ua =
|
|
||||||
"u17n7hpwaujyq7ux8f9jpyymtnk5urw7pyrf60smp5mawy7jgz325hfvz3jn3zsfya8yxryf9q7ldk8nu8df0emra5wne28zq9d9nm2pu4x6qwjha565av9aze0xgujgslz74ufkj0c0cylqwjyrh9msjfh7jzal6d3qzrnhkkqy3pqm8j63y07jxj7txqeac982778rmt64f32aum94x"
|
|
||||||
case isValidUnifiedAddress ua of
|
|
||||||
Nothing -> assertFailure "Bad UA"
|
|
||||||
Just u -> do
|
|
||||||
let tAdd =
|
|
||||||
maybe
|
|
||||||
"No transparent"
|
|
||||||
(encodeTransparentReceiver (ua_net u)) $
|
|
||||||
t_rec u
|
|
||||||
(ta_receiver <$> decodeTransparentAddress (E.encodeUtf8 tAdd)) `shouldBe`
|
|
||||||
t_rec u
|
|
||||||
|
|
||||||
-- | Properties
|
-- | Properties
|
||||||
prop_PhraseLength :: Property
|
prop_PhraseLength :: Property
|
||||||
|
|
|
@ -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.0
|
version: 0.5.4.0
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue