Optimize transaction creation #98
8 changed files with 437 additions and 184 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -5,6 +5,18 @@ 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.7.3.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Function to create an Orchard hash from a note commitment
|
||||||
|
- Function to hash Orchard commitments
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Modified frontiers to use `HexString` for ommers
|
||||||
|
- Optimized `createTransaction`
|
||||||
|
|
||||||
## [0.7.2.0]
|
## [0.7.2.0]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -20,9 +20,9 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||||
|
|
||||||
use haskell_ffi::{
|
use haskell_ffi::{
|
||||||
error::Result,
|
error::Result,
|
||||||
from_haskell::{marshall_from_haskell_var, marshall_from_haskell_fixed},
|
from_haskell::marshall_from_haskell_var,
|
||||||
to_haskell::{marshall_to_haskell_var, marshall_to_haskell_fixed},
|
to_haskell::marshall_to_haskell_var,
|
||||||
FromHaskell, HaskellSize, ToHaskell
|
FromHaskell, ToHaskell
|
||||||
};
|
};
|
||||||
|
|
||||||
use secp256k1::SecretKey;
|
use secp256k1::SecretKey;
|
||||||
|
@ -30,6 +30,8 @@ use secp256k1::SecretKey;
|
||||||
use jubjub::Fr;
|
use jubjub::Fr;
|
||||||
|
|
||||||
use incrementalmerkletree::{
|
use incrementalmerkletree::{
|
||||||
|
Hashable,
|
||||||
|
Level,
|
||||||
Position,
|
Position,
|
||||||
frontier::{
|
frontier::{
|
||||||
CommitmentTree,
|
CommitmentTree,
|
||||||
|
@ -40,8 +42,7 @@ use incrementalmerkletree::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use zip32::{
|
use zip32::{
|
||||||
Scope as SaplingScope,
|
Scope as SaplingScope
|
||||||
ChildIndex
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +93,8 @@ use zcash_primitives::{
|
||||||
write_commitment_tree,
|
write_commitment_tree,
|
||||||
read_incremental_witness,
|
read_incremental_witness,
|
||||||
write_incremental_witness,
|
write_incremental_witness,
|
||||||
read_frontier_v1
|
read_frontier_v1,
|
||||||
|
read_nonempty_frontier_v1
|
||||||
},
|
},
|
||||||
legacy::{
|
legacy::{
|
||||||
Script,
|
Script,
|
||||||
|
@ -697,7 +699,7 @@ impl<RW> ToHaskell<RW> for Hsvk {
|
||||||
pub struct Hfrontier {
|
pub struct Hfrontier {
|
||||||
position: u64,
|
position: u64,
|
||||||
leaf: Hhex,
|
leaf: Hhex,
|
||||||
ommers: Vec<Vec<u8>>
|
ommers: Vec<Hhex>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<RW> ToHaskell<RW> for Hfrontier {
|
impl<RW> ToHaskell<RW> for Hfrontier {
|
||||||
|
@ -1384,11 +1386,11 @@ pub extern "C" fn rust_wrapper_read_sapling_frontier(
|
||||||
match frontier.value() {
|
match frontier.value() {
|
||||||
Some(f1) => {
|
Some(f1) => {
|
||||||
let (pos, leaf, omm) = f1.clone().into_parts();
|
let (pos, leaf, omm) = f1.clone().into_parts();
|
||||||
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()};
|
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()};
|
||||||
marshall_to_haskell_var(&f, out, out_len, RW);
|
marshall_to_haskell_var(&f, out, out_len, RW);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]};
|
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]};
|
||||||
marshall_to_haskell_var(&f0, out, out_len, RW);
|
marshall_to_haskell_var(&f0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1405,17 +1407,17 @@ pub extern "C" fn rust_wrapper_read_sapling_commitment_tree(
|
||||||
){
|
){
|
||||||
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap();
|
let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap();
|
||||||
let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap();
|
let mut comm_tree = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap();
|
||||||
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
||||||
let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in));
|
let sap_note_comm = SaplingNoteCommitment::from_bytes(&to_array(node_in));
|
||||||
if sap_note_comm.is_some().into() {
|
if sap_note_comm.is_some().into() {
|
||||||
let n = Node::from_cmu(&sap_note_comm.unwrap());
|
let n = Node::from_cmu(&sap_note_comm.unwrap());
|
||||||
comm_tree.append(n);
|
comm_tree.append(n);
|
||||||
let (pos, leaf, omm) = comm_tree.into_parts();
|
let (pos, leaf, omm) = comm_tree.into_parts();
|
||||||
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()};
|
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()};
|
||||||
marshall_to_haskell_var(&f, out, out_len, RW);
|
marshall_to_haskell_var(&f, out, out_len, RW);
|
||||||
} else {
|
} else {
|
||||||
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]};
|
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]};
|
||||||
marshall_to_haskell_var(&f0, out, out_len, RW);
|
marshall_to_haskell_var(&f0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1431,7 @@ pub extern "C" fn rust_wrapper_read_sapling_witness(
|
||||||
){
|
){
|
||||||
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap();
|
let leaf = Node::from_bytes(to_array(tree_in.leaf.bytes)).unwrap();
|
||||||
let frontier: Frontier<Node, SAPLING_DEPTH> = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.clone())).unwrap() ).collect()).unwrap();
|
let frontier: Frontier<Node, SAPLING_DEPTH> = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| Node::from_bytes(to_array(x.bytes.clone())).unwrap() ).collect()).unwrap();
|
||||||
let ct: CommitmentTree<Node, SAPLING_DEPTH> = CommitmentTree::from_frontier(&frontier);
|
let ct: CommitmentTree<Node, SAPLING_DEPTH> = CommitmentTree::from_frontier(&frontier);
|
||||||
let inc_wit = IncrementalWitness::from_tree(ct);
|
let inc_wit = IncrementalWitness::from_tree(ct);
|
||||||
let mut out_bytes: Vec<u8> = Vec::new();
|
let mut out_bytes: Vec<u8> = Vec::new();
|
||||||
|
@ -1501,23 +1503,120 @@ pub extern "C" fn rust_wrapper_read_orchard_frontier(
|
||||||
){
|
){
|
||||||
let tree_in: Vec<u8> = marshall_from_haskell_var(tree, tree_len, RW);
|
let tree_in: Vec<u8> = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
let tree_reader = Cursor::new(tree_in);
|
let tree_reader = Cursor::new(tree_in);
|
||||||
let comm_tree: CommitmentTree<MerkleHashOrchard, 32> = read_commitment_tree(tree_reader).unwrap();
|
let comm_tree = read_commitment_tree(tree_reader);
|
||||||
//let comm_tree: Frontier<MerkleHashOrchard, 32> = read_frontier_v1(tree_reader).unwrap();
|
//let comm_tree = read_frontier_v1(tree_reader);
|
||||||
let frontier: Frontier<MerkleHashOrchard, 32> = comm_tree.to_frontier();
|
//let frontier: Frontier<MerkleHashOrchard, 32> = comm_tree.to_frontier();
|
||||||
|
match comm_tree {
|
||||||
|
Ok::<CommitmentTree<MerkleHashOrchard, 32>, _>(f1) => {
|
||||||
|
let frontier = f1.to_frontier();
|
||||||
match frontier.value() {
|
match frontier.value() {
|
||||||
Some(f1) => {
|
Some(f2) => {
|
||||||
let (pos, leaf, omm) = f1.clone().into_parts();
|
let (pos, leaf, omm) = f2.clone().into_parts();
|
||||||
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()};
|
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()};
|
||||||
marshall_to_haskell_var(&f, out, out_len, RW);
|
marshall_to_haskell_var(&f, out, out_len, RW);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]};
|
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]};
|
||||||
|
marshall_to_haskell_var(&f0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]};
|
||||||
marshall_to_haskell_var(&f0, out, out_len, RW);
|
marshall_to_haskell_var(&f0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_read_orchard_tree_anchor(
|
||||||
|
tree: *const u8,
|
||||||
|
tree_len: usize,
|
||||||
|
out: *mut u8,
|
||||||
|
out_len: &mut usize
|
||||||
|
){
|
||||||
|
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
|
let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap();
|
||||||
|
let comm_tree: NonEmptyFrontier<MerkleHashOrchard> = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap();
|
||||||
|
let root = comm_tree.root(None);
|
||||||
|
let h = Hhex { bytes: root.to_bytes().to_vec() };
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_read_orchard_witness_anchor(
|
||||||
|
wit: *const u8,
|
||||||
|
wit_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 iw: IncrementalWitness<MerkleHashOrchard, 32> = read_incremental_witness(wit_reader).unwrap();
|
||||||
|
let root = iw.root();
|
||||||
|
let h = Hhex { bytes: root.to_bytes().to_vec() };
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_read_orchard_node(
|
||||||
|
cmx: *const u8,
|
||||||
|
cmx_len: usize,
|
||||||
|
out: *mut u8,
|
||||||
|
out_len: &mut usize
|
||||||
|
){
|
||||||
|
let node_in: Vec<u8> = marshall_from_haskell_var(cmx, cmx_len, RW);
|
||||||
|
let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in));
|
||||||
|
if orchard_note_comm.is_some().into() {
|
||||||
|
let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap());
|
||||||
|
let h = Hhex { bytes: n.to_bytes().to_vec()};
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
} else {
|
||||||
|
let h0 = Hhex { bytes: vec![0] };
|
||||||
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn rust_wrapper_combine_orchard_nodes(
|
||||||
|
level: u8,
|
||||||
|
left: *const u8,
|
||||||
|
left_len: usize,
|
||||||
|
right: *const u8,
|
||||||
|
right_len: usize,
|
||||||
|
out: *mut u8,
|
||||||
|
out_len: &mut usize
|
||||||
|
){
|
||||||
|
let left_in: Vec<u8> = marshall_from_haskell_var(left, left_len, RW);
|
||||||
|
let right_in: Vec<u8> = marshall_from_haskell_var(right, right_len, RW);
|
||||||
|
if left_in.len() == 1 {
|
||||||
|
let n = MerkleHashOrchard::combine(Level::new(level), &MerkleHashOrchard::empty_leaf(), &MerkleHashOrchard::empty_leaf());
|
||||||
|
let h = Hhex { bytes: n.to_bytes().to_vec() };
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
} else {
|
||||||
|
let left_node = MerkleHashOrchard::from_bytes(&to_array(left_in));
|
||||||
|
if left_node.is_some().into() {
|
||||||
|
if right_in.len() > 1 {
|
||||||
|
let right_node = MerkleHashOrchard::from_bytes(&to_array(right_in));
|
||||||
|
if right_node.is_some().into() {
|
||||||
|
let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &right_node.unwrap());
|
||||||
|
let h = Hhex { bytes: n.to_bytes().to_vec() };
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
} else {
|
||||||
|
let h0 = Hhex { bytes: vec![0] };
|
||||||
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let n = MerkleHashOrchard::combine(Level::new(level), &left_node.unwrap(), &MerkleHashOrchard::empty_leaf());
|
||||||
|
let h = Hhex { bytes: n.to_bytes().to_vec() };
|
||||||
|
marshall_to_haskell_var(&h, out, out_len, RW);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let h0 = Hhex { bytes: vec![0] };
|
||||||
|
marshall_to_haskell_var(&h0, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -1534,17 +1633,17 @@ pub extern "C" fn rust_wrapper_read_orchard_commitment_tree(
|
||||||
//let mut comm_tree: CommitmentTree<MerkleHashOrchard, 32> = read_commitment_tree(tree_reader).unwrap();
|
//let mut comm_tree: CommitmentTree<MerkleHashOrchard, 32> = read_commitment_tree(tree_reader).unwrap();
|
||||||
//let mut comm_tree: Frontier<MerkleHashOrchard, 32> = read_frontier_v1(tree_reader).unwrap();
|
//let mut comm_tree: Frontier<MerkleHashOrchard, 32> = read_frontier_v1(tree_reader).unwrap();
|
||||||
let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap();
|
let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap();
|
||||||
let mut comm_tree: NonEmptyFrontier<MerkleHashOrchard> = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap();
|
let mut comm_tree: NonEmptyFrontier<MerkleHashOrchard> = NonEmptyFrontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap();
|
||||||
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
let node_in: Vec<u8> = marshall_from_haskell_var(node, node_len, RW);
|
||||||
let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in));
|
let orchard_note_comm = ExtractedNoteCommitment::from_bytes(&to_array(node_in));
|
||||||
if orchard_note_comm.is_some().into() {
|
if orchard_note_comm.is_some().into() {
|
||||||
let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap());
|
let n = MerkleHashOrchard::from_cmx(&orchard_note_comm.unwrap());
|
||||||
comm_tree.append(n);
|
comm_tree.append(n);
|
||||||
let (pos, leaf, omm) = comm_tree.into_parts();
|
let (pos, leaf, omm) = comm_tree.into_parts();
|
||||||
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| x.to_bytes().to_vec()).collect()};
|
let f = Hfrontier { position: <u64>::from(pos), leaf: Hhex { bytes: leaf.to_bytes().to_vec()}, ommers: omm.iter().map(|&x| Hhex { bytes: x.to_bytes().to_vec()}).collect()};
|
||||||
marshall_to_haskell_var(&f, out, out_len, RW);
|
marshall_to_haskell_var(&f, out, out_len, RW);
|
||||||
} else {
|
} else {
|
||||||
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![vec![0]]};
|
let f0 = Hfrontier { position: 0, leaf: Hhex { bytes: vec![0]}, ommers: vec![Hhex { bytes: vec![0]}]};
|
||||||
marshall_to_haskell_var(&f0, out, out_len, RW);
|
marshall_to_haskell_var(&f0, out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1558,7 +1657,7 @@ pub extern "C" fn rust_wrapper_read_orchard_witness(
|
||||||
){
|
){
|
||||||
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
let tree_in: Hfrontier = marshall_from_haskell_var(tree, tree_len, RW);
|
||||||
let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap();
|
let leaf = MerkleHashOrchard::from_bytes(&to_array(tree_in.leaf.bytes)).unwrap();
|
||||||
let frontier: Frontier<MerkleHashOrchard, 32> = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.clone())).unwrap() ).collect()).unwrap();
|
let frontier: Frontier<MerkleHashOrchard, 32> = Frontier::from_parts(Position::from(tree_in.position), leaf, tree_in.ommers.iter().map(|x| MerkleHashOrchard::from_bytes(&to_array(x.bytes.clone())).unwrap() ).collect()).unwrap();
|
||||||
let ct: CommitmentTree<MerkleHashOrchard, 32> = CommitmentTree::from_frontier(&frontier);
|
let ct: CommitmentTree<MerkleHashOrchard, 32> = CommitmentTree::from_frontier(&frontier);
|
||||||
let inc_wit = IncrementalWitness::from_tree(ct);
|
let inc_wit = IncrementalWitness::from_tree(ct);
|
||||||
let mut out_bytes: Vec<u8> = Vec::new();
|
let mut out_bytes: Vec<u8> = Vec::new();
|
||||||
|
@ -1695,43 +1794,41 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
build: bool,
|
build: bool,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
out_len: &mut usize){
|
out_len: &mut usize){
|
||||||
//let sap_wit_in: Vec<u8> = marshall_from_haskell_var(sap_wit, sap_wit_len, RW);
|
|
||||||
//let sap_wit_reader = Cursor::new(sap_wit_in);
|
|
||||||
//let sap_iw = read_commitment_tree::<Node, Cursor<Vec<u8>>, SAPLING_DEPTH>(sap_wit_reader);
|
|
||||||
let sap_input: Vec<HsaplingInput> = marshall_from_haskell_var(s_input, s_input_len, RW);
|
let sap_input: Vec<HsaplingInput> = marshall_from_haskell_var(s_input, s_input_len, RW);
|
||||||
let sap_anchor =
|
let sap_anchor =
|
||||||
if sap_input.is_empty() {
|
if sap_input.is_empty() {
|
||||||
|
let sap_wit_in: Vec<u8> = marshall_from_haskell_var(sap_wit, sap_wit_len, RW);
|
||||||
|
let sap_wit_reader = Cursor::new(sap_wit_in);
|
||||||
|
let sap_iw = read_commitment_tree::<Node, Cursor<Vec<u8>>, SAPLING_DEPTH>(sap_wit_reader);
|
||||||
|
match sap_iw {
|
||||||
|
Ok(s_iw) => {
|
||||||
|
Some(SaplingAnchor::from(s_iw.root()))
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let si = &sap_input[0];
|
let si = &sap_input[0];
|
||||||
let swit_reader = Cursor::new(&si.iw);
|
let swit_reader = Cursor::new(&si.iw);
|
||||||
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(swit_reader).unwrap();
|
let iw: IncrementalWitness<Node, SAPLING_DEPTH> = read_incremental_witness(swit_reader).unwrap();
|
||||||
Some(SaplingAnchor::from(iw.root()))
|
Some(SaplingAnchor::from(iw.root()))
|
||||||
};
|
};
|
||||||
//let sap_anchor = match sap_iw {
|
|
||||||
//Ok(s_iw) => {
|
|
||||||
//Some(SaplingAnchor::from(s_iw.root()))
|
|
||||||
//},
|
|
||||||
//Err(_e) => {
|
|
||||||
//None
|
|
||||||
//}
|
|
||||||
//};
|
|
||||||
//println!("{:?}", sap_anchor);
|
//println!("{:?}", sap_anchor);
|
||||||
//let orch_wit_in: Vec<u8> = marshall_from_haskell_var(orch_wit, orch_wit_len, RW);
|
|
||||||
//let orch_wit_reader = Cursor::new(orch_wit_in);
|
|
||||||
//let orch_iw = read_commitment_tree::<MerkleHashOrchard, Cursor<Vec<u8>>, 32>(orch_wit_reader);
|
|
||||||
let orch_input: Vec<HorchardInput> = marshall_from_haskell_var(o_input, o_input_len, RW);
|
let orch_input: Vec<HorchardInput> = marshall_from_haskell_var(o_input, o_input_len, RW);
|
||||||
//let orch_anchor = match orch_iw {
|
|
||||||
//Ok(o_iw) => {
|
|
||||||
//Some(OrchardAnchor::from(o_iw.root()))
|
|
||||||
//},
|
|
||||||
//Err(_e) => {
|
|
||||||
//None
|
|
||||||
//}
|
|
||||||
//};
|
|
||||||
let orch_anchor =
|
let orch_anchor =
|
||||||
if orch_input.is_empty() {
|
if orch_input.is_empty() {
|
||||||
|
let orch_wit_in: Vec<u8> = marshall_from_haskell_var(orch_wit, orch_wit_len, RW);
|
||||||
|
let orch_wit_reader = Cursor::new(orch_wit_in);
|
||||||
|
let orch_iw = read_commitment_tree::<MerkleHashOrchard, Cursor<Vec<u8>>, 32>(orch_wit_reader);
|
||||||
|
match orch_iw {
|
||||||
|
Ok(o_iw) => {
|
||||||
|
Some(OrchardAnchor::from(o_iw.root()))
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
None
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let oi = &orch_input[0];
|
let oi = &orch_input[0];
|
||||||
let wit_reader = Cursor::new(&oi.iw);
|
let wit_reader = Cursor::new(&oi.iw);
|
||||||
|
@ -1744,6 +1841,7 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
let trans_input: Vec<HtransparentInput> = marshall_from_haskell_var(t_input, t_input_len, RW);
|
let trans_input: Vec<HtransparentInput> = marshall_from_haskell_var(t_input, t_input_len, RW);
|
||||||
for t_in in trans_input {
|
for t_in in trans_input {
|
||||||
if t_in.sk.len() > 1 {
|
if t_in.sk.len() > 1 {
|
||||||
|
//println!("t inp: {:?}", t_in);
|
||||||
let k = SecretKey::from_slice(&t_in.sk).unwrap();
|
let k = SecretKey::from_slice(&t_in.sk).unwrap();
|
||||||
if net {
|
if net {
|
||||||
match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) {
|
match main_builder.add_transparent_input(k, t_in.utxo.unpack(), t_in.coin.unpack()) {
|
||||||
|
@ -1766,6 +1864,7 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
}
|
}
|
||||||
for s_in in sap_input {
|
for s_in in sap_input {
|
||||||
if s_in.sk.len() > 1 {
|
if s_in.sk.len() > 1 {
|
||||||
|
//println!("s inp: {:?}", s_in);
|
||||||
let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk);
|
let sp_key = ExtendedSpendingKey::from_bytes(&s_in.sk);
|
||||||
match sp_key {
|
match sp_key {
|
||||||
Ok(sk) => {
|
Ok(sk) => {
|
||||||
|
@ -1817,6 +1916,7 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap();
|
let rho = Rho::from_bytes(&to_array(o_in.note.rho)).unwrap();
|
||||||
let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap();
|
let rseed = RandomSeed::from_bytes(to_array(o_in.note.rseed.bytes), &rho).unwrap();
|
||||||
let val = NoteValue::from_raw(o_in.note.note);
|
let val = NoteValue::from_raw(o_in.note.note);
|
||||||
|
//println!("o inp: {:?}", val);
|
||||||
let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap();
|
let note = Note::from_parts(pay_addr, val, rho, rseed).unwrap();
|
||||||
let wit_reader = Cursor::new(o_in.iw);
|
let wit_reader = Cursor::new(o_in.iw);
|
||||||
let iw: IncrementalWitness<MerkleHashOrchard, 32> = read_incremental_witness(wit_reader).unwrap();
|
let iw: IncrementalWitness<MerkleHashOrchard, 32> = read_incremental_witness(wit_reader).unwrap();
|
||||||
|
@ -1852,19 +1952,49 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
1 => {
|
1 => {
|
||||||
let recipient = TransparentAddress::PublicKeyHash(to_array(output.to));
|
let recipient = TransparentAddress::PublicKeyHash(to_array(output.to));
|
||||||
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
|
//println!("t out: {:?} {:?}", val, output.chg);
|
||||||
if net {
|
if net {
|
||||||
let _mb = main_builder.add_transparent_output(&recipient, val);
|
let mb = main_builder.add_transparent_output(&recipient, val);
|
||||||
|
match mb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![4]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let _tb = test_builder.add_transparent_output(&recipient, val);
|
let tb = test_builder.add_transparent_output(&recipient, val);
|
||||||
|
match tb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![4]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
2 => {
|
2 => {
|
||||||
let recipient = TransparentAddress::ScriptHash(to_array(output.to));
|
let recipient = TransparentAddress::ScriptHash(to_array(output.to));
|
||||||
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
|
//println!("t out: {:?} {:?}", val, output.chg);
|
||||||
if net {
|
if net {
|
||||||
let _mb = main_builder.add_transparent_output(&recipient, val);
|
let mb = main_builder.add_transparent_output(&recipient, val);
|
||||||
|
match mb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![4]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let _tb = test_builder.add_transparent_output(&recipient, val);
|
let tb = test_builder.add_transparent_output(&recipient, val);
|
||||||
|
match tb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![4]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
3 => {
|
3 => {
|
||||||
|
@ -1872,10 +2002,26 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap();
|
let recipient = PaymentAddress::from_bytes(&to_array(output.to)).unwrap();
|
||||||
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
let val = NonNegativeAmount::from_u64(output.amt).unwrap();
|
||||||
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
||||||
|
//println!("s out: {:?} {:?}", val, output.chg);
|
||||||
if net {
|
if net {
|
||||||
let _mb = main_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
let mb = main_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
||||||
|
match mb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![5]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let _tb = test_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
let tb = test_builder.add_sapling_output::<String>(ovk, recipient, val, memo);
|
||||||
|
match tb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![5]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//println!("add sap: {:?}", tb);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
|
@ -1887,11 +2033,26 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
};
|
};
|
||||||
let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap();
|
let recipient = OrchardAddress::from_raw_address_bytes(&to_array(output.to)).unwrap();
|
||||||
let val = output.amt;
|
let val = output.amt;
|
||||||
|
//println!("o out: {:?} {:?}", val, output.chg);
|
||||||
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
let memo = MemoBytes::from_bytes(&output.memo).unwrap();
|
||||||
if net {
|
if net {
|
||||||
let _mb = main_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
let mb = main_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
||||||
|
match mb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![6]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let _tb = test_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
let tb = test_builder.add_orchard_output::<String>(ovk, recipient, val, memo);
|
||||||
|
match tb {
|
||||||
|
Ok(()) => { continue; },
|
||||||
|
Err(_e) => {
|
||||||
|
let x = Hhex {bytes: vec![6]};
|
||||||
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1900,6 +2061,12 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if build {
|
if build {
|
||||||
|
//let fee_result = if net {
|
||||||
|
//main_builder.get_fee(&FeeRule::standard())
|
||||||
|
//} else {
|
||||||
|
//test_builder.get_fee(&FeeRule::standard())
|
||||||
|
//};
|
||||||
|
//println!("fee: {:?}", fee_result);
|
||||||
let (spend_params_in, output_params_in) = load_sapling_parameters();
|
let (spend_params_in, output_params_in) = load_sapling_parameters();
|
||||||
//let spend_params_in: Vec<u8> = marshall_from_haskell_var(sapspend, sapspend_len, RW);
|
//let spend_params_in: Vec<u8> = marshall_from_haskell_var(sapspend, sapspend_len, RW);
|
||||||
let spend_params_reader = Cursor::new(spend_params_in);
|
let spend_params_reader = Cursor::new(spend_params_in);
|
||||||
|
@ -1926,6 +2093,7 @@ pub extern "C" fn rust_wrapper_create_transaction(
|
||||||
marshall_to_haskell_var(&x, out, out_len, RW);
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
},
|
},
|
||||||
Error::ChangeRequired(y1) => {
|
Error::ChangeRequired(y1) => {
|
||||||
|
//println!("change req: {:?}", y1);
|
||||||
let x = Hhex {bytes: vec![1]};
|
let x = Hhex {bytes: vec![1]};
|
||||||
marshall_to_haskell_var(&x, out, out_len, RW);
|
marshall_to_haskell_var(&x, out, out_len, RW);
|
||||||
},
|
},
|
||||||
|
|
|
@ -246,6 +246,36 @@ import ZcashHaskell.Types
|
||||||
-> `()'
|
-> `()'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_node as rustWrapperReadOrchardNode
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_combine_orchard_nodes as rustWrapperCombineOrchardNodes
|
||||||
|
{ `Int8'
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_tree_anchor as rustWrapperReadOrchardTreeAnchor
|
||||||
|
{ toBorshVar* `OrchardFrontier'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe rust_wrapper_read_orchard_witness_anchor as rustWrapperReadOrchardWitnessAnchor
|
||||||
|
{ toBorshVar* `BS.ByteString'&
|
||||||
|
, getVarBuffer `Buffer HexString'&
|
||||||
|
}
|
||||||
|
-> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
{# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree
|
{# fun unsafe rust_wrapper_read_orchard_commitment_tree as rustWrapperReadOrchardCommitmentTree
|
||||||
{ toBorshVar* `OrchardFrontier'&
|
{ toBorshVar* `OrchardFrontier'&
|
||||||
, toBorshVar* `BS.ByteString'&
|
, toBorshVar* `BS.ByteString'&
|
||||||
|
|
|
@ -18,15 +18,19 @@
|
||||||
module ZcashHaskell.Orchard where
|
module ZcashHaskell.Orchard where
|
||||||
|
|
||||||
import C.Zcash
|
import C.Zcash
|
||||||
( rustWrapperGenOrchardReceiver
|
( rustWrapperCombineOrchardNodes
|
||||||
|
, rustWrapperGenOrchardReceiver
|
||||||
, rustWrapperGenOrchardSpendKey
|
, rustWrapperGenOrchardSpendKey
|
||||||
, rustWrapperOrchardCheck
|
, rustWrapperOrchardCheck
|
||||||
, rustWrapperOrchardNoteDecode
|
, rustWrapperOrchardNoteDecode
|
||||||
, rustWrapperOrchardNoteDecodeSK
|
, rustWrapperOrchardNoteDecodeSK
|
||||||
, rustWrapperReadOrchardCommitmentTree
|
, rustWrapperReadOrchardCommitmentTree
|
||||||
, rustWrapperReadOrchardFrontier
|
, rustWrapperReadOrchardFrontier
|
||||||
|
, rustWrapperReadOrchardNode
|
||||||
, rustWrapperReadOrchardPosition
|
, rustWrapperReadOrchardPosition
|
||||||
|
, rustWrapperReadOrchardTreeAnchor
|
||||||
, rustWrapperReadOrchardWitness
|
, rustWrapperReadOrchardWitness
|
||||||
|
, rustWrapperReadOrchardWitnessAnchor
|
||||||
, rustWrapperUADecode
|
, rustWrapperUADecode
|
||||||
, rustWrapperUfvkDecode
|
, rustWrapperUfvkDecode
|
||||||
, rustWrapperUpdateOrchardWitness
|
, rustWrapperUpdateOrchardWitness
|
||||||
|
@ -205,6 +209,15 @@ getOrchardFrontier tree =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree
|
rustWrapperReadOrchardFrontier $ toBytes $ orchTree tree
|
||||||
|
|
||||||
|
getOrchardTreeAnchor :: OrchardFrontier -> HexString
|
||||||
|
getOrchardTreeAnchor tree =
|
||||||
|
withPureBorshVarBuffer $ rustWrapperReadOrchardTreeAnchor tree
|
||||||
|
|
||||||
|
getOrchardWitnessAnchor :: OrchardWitness -> HexString
|
||||||
|
getOrchardWitnessAnchor wit =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperReadOrchardWitnessAnchor $ toBytes $ orchWit wit
|
||||||
|
|
||||||
-- | Update a Orchard commitment tree
|
-- | Update a Orchard commitment tree
|
||||||
updateOrchardCommitmentTree ::
|
updateOrchardCommitmentTree ::
|
||||||
OrchardFrontier -- ^ the base tree
|
OrchardFrontier -- ^ the base tree
|
||||||
|
@ -244,6 +257,27 @@ updateOrchardWitness wit cmus =
|
||||||
(map toBytes cmus)
|
(map toBytes cmus)
|
||||||
else wit
|
else wit
|
||||||
|
|
||||||
|
getOrchardNodeValue :: BS.ByteString -> Maybe HexString
|
||||||
|
getOrchardNodeValue cmx =
|
||||||
|
if BS.length (hexBytes n) > 1
|
||||||
|
then Just n
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
n = withPureBorshVarBuffer $ rustWrapperReadOrchardNode cmx
|
||||||
|
|
||||||
|
combineOrchardNodes :: Integer -> HexString -> HexString -> Maybe HexString
|
||||||
|
combineOrchardNodes level n1 n2 =
|
||||||
|
if BS.length (hexBytes r) > 1
|
||||||
|
then Just r
|
||||||
|
else Nothing
|
||||||
|
where
|
||||||
|
r =
|
||||||
|
withPureBorshVarBuffer $
|
||||||
|
rustWrapperCombineOrchardNodes
|
||||||
|
(fromIntegral level)
|
||||||
|
(toBytes n1)
|
||||||
|
(toBytes n2)
|
||||||
|
|
||||||
-- | Parse a potential Zcash address
|
-- | Parse a potential Zcash address
|
||||||
parseAddress :: BS.ByteString -> Maybe ValidAddress
|
parseAddress :: BS.ByteString -> Maybe ValidAddress
|
||||||
parseAddress t =
|
parseAddress t =
|
||||||
|
|
|
@ -614,7 +614,7 @@ newtype SaplingCommitmentTree = SaplingCommitmentTree
|
||||||
data SaplingFrontier = SaplingFrontier
|
data SaplingFrontier = SaplingFrontier
|
||||||
{ sf_pos :: !Int64
|
{ sf_pos :: !Int64
|
||||||
, sf_leaf :: !HexString
|
, sf_leaf :: !HexString
|
||||||
, sf_ommers :: ![BS.ByteString]
|
, sf_ommers :: ![HexString]
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
@ -730,7 +730,7 @@ newtype OrchardCommitmentTree = OrchardCommitmentTree
|
||||||
data OrchardFrontier = OrchardFrontier
|
data OrchardFrontier = OrchardFrontier
|
||||||
{ of_pos :: !Int64
|
{ of_pos :: !Int64
|
||||||
, of_leaf :: !HexString
|
, of_leaf :: !HexString
|
||||||
, of_ommers :: ![BS.ByteString]
|
, of_ommers :: ![HexString]
|
||||||
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
} deriving stock (Eq, Prelude.Show, GHC.Generic)
|
||||||
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
|
||||||
deriving anyclass (Data.Structured.Show)
|
deriving anyclass (Data.Structured.Show)
|
||||||
|
|
|
@ -132,29 +132,10 @@ createTransaction ::
|
||||||
-> ZcashNet -- ^ the network to be used
|
-> ZcashNet -- ^ the network to be used
|
||||||
-> Int -- ^ target block height
|
-> Int -- ^ target block height
|
||||||
-> Bool -- ^ True to build, False to estimate fee
|
-> Bool -- ^ True to build, False to estimate fee
|
||||||
-> Either TxError HexString
|
-> IO (Either TxError HexString)
|
||||||
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build =
|
createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh build = do
|
||||||
processResult $! txResult
|
txResult <-
|
||||||
where
|
withBorshBufferOfInitSize 51200 $
|
||||||
processResult :: HexString -> Either TxError HexString
|
|
||||||
processResult input =
|
|
||||||
if BS.length (hexBytes input) > 1
|
|
||||||
then Right input
|
|
||||||
else case head (BS.unpack $ hexBytes input) of
|
|
||||||
0 -> Left InsufficientFunds
|
|
||||||
1 -> Left ChangeRequired
|
|
||||||
2 -> Left Fee
|
|
||||||
3 -> Left Balance
|
|
||||||
4 -> Left TransparentBuild
|
|
||||||
5 -> Left SaplingBuild
|
|
||||||
6 -> Left OrchardBuild
|
|
||||||
7 -> Left OrchardSpend
|
|
||||||
8 -> Left OrchardRecipient
|
|
||||||
9 -> Left SaplingBuilderNotAvailable
|
|
||||||
10 -> Left OrchardBuilderNotAvailable
|
|
||||||
_ -> Left ZHError
|
|
||||||
txResult =
|
|
||||||
withPureBorshVarBuffer $
|
|
||||||
rustWrapperCreateTx
|
rustWrapperCreateTx
|
||||||
(case sapAnchor of
|
(case sapAnchor of
|
||||||
Nothing -> "0"
|
Nothing -> "0"
|
||||||
|
@ -169,3 +150,18 @@ createTransaction sapAnchor orchAnchor tSpend sSpend oSpend outgoing znet bh bui
|
||||||
(znet == MainNet)
|
(znet == MainNet)
|
||||||
(fromIntegral bh)
|
(fromIntegral bh)
|
||||||
build
|
build
|
||||||
|
if BS.length (hexBytes txResult) > 1
|
||||||
|
then pure $ Right txResult
|
||||||
|
else case head (BS.unpack $ hexBytes txResult) of
|
||||||
|
0 -> pure $ Left InsufficientFunds
|
||||||
|
1 -> pure $ Left ChangeRequired
|
||||||
|
2 -> pure $ Left Fee
|
||||||
|
3 -> pure $ Left Balance
|
||||||
|
4 -> pure $ Left TransparentBuild
|
||||||
|
5 -> pure $ Left SaplingBuild
|
||||||
|
6 -> pure $ Left OrchardBuild
|
||||||
|
7 -> pure $ Left OrchardSpend
|
||||||
|
8 -> pure $ Left OrchardRecipient
|
||||||
|
9 -> pure $ Left SaplingBuilderNotAvailable
|
||||||
|
10 -> pure $ Left OrchardBuilderNotAvailable
|
||||||
|
_ -> pure $ Left ZHError
|
||||||
|
|
107
test/Spec.hs
107
test/Spec.hs
|
@ -55,6 +55,7 @@ import ZcashHaskell.Sapling
|
||||||
, genSaplingInternalAddress
|
, genSaplingInternalAddress
|
||||||
, genSaplingPaymentAddress
|
, genSaplingPaymentAddress
|
||||||
, genSaplingSpendingKey
|
, genSaplingSpendingKey
|
||||||
|
, getSaplingFrontier
|
||||||
, getSaplingNotePosition
|
, getSaplingNotePosition
|
||||||
, getSaplingWitness
|
, getSaplingWitness
|
||||||
, getShieldedOutputs
|
, getShieldedOutputs
|
||||||
|
@ -73,6 +74,7 @@ import ZcashHaskell.Types
|
||||||
, OrchardAction(..)
|
, OrchardAction(..)
|
||||||
, OrchardBundle(..)
|
, OrchardBundle(..)
|
||||||
, OrchardCommitmentTree(..)
|
, OrchardCommitmentTree(..)
|
||||||
|
, OrchardFrontier(..)
|
||||||
, OrchardSpendingKey(..)
|
, OrchardSpendingKey(..)
|
||||||
, OrchardWitness(..)
|
, OrchardWitness(..)
|
||||||
, Phrase(..)
|
, Phrase(..)
|
||||||
|
@ -88,6 +90,7 @@ import ZcashHaskell.Types
|
||||||
, SaplingAddress(..)
|
, SaplingAddress(..)
|
||||||
, SaplingBundle(..)
|
, SaplingBundle(..)
|
||||||
, SaplingCommitmentTree(..)
|
, SaplingCommitmentTree(..)
|
||||||
|
, SaplingFrontier(..)
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
, SaplingWitness(..)
|
, SaplingWitness(..)
|
||||||
|
@ -895,33 +898,35 @@ main = do
|
||||||
Just t' -> do
|
Just t' -> do
|
||||||
let tb = zt_tBundle t'
|
let tb = zt_tBundle t'
|
||||||
show tb `shouldNotBe` ""
|
show tb `shouldNotBe` ""
|
||||||
describe "Sapling commitment trees" $ do
|
{-
|
||||||
let tree =
|
-describe "Sapling commitment trees" $ do
|
||||||
SaplingCommitmentTree $
|
- let tree =
|
||||||
hexString
|
- SaplingCommitmentTree $
|
||||||
"01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
- hexString
|
||||||
let cmu1 =
|
- "01916df07670600aefa3b412a120d6b8d9a3d2ff9466a7ec770cd52d34ddb42313001000013c60b031a5e44650059fcc7101a3f551b807ab8b3a116a5a9c7fa0f3babbe735017c0d36686294ff19d59e58b6a2ac6a7ad607a804bc202c84012d8e94f233970c0128dbde5180af5304d8577376d78297130b615a327974c10881f6d876869aea05011b80b4ca60f74dfe33c78b062df73c84b8b44dab4604db16f5b61eea40134373010c96e4cc8a6a80fba0d41e4eb3070d80769104dc33fb61133b1304c15bf9e23e000107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
hexString
|
- let cmu1 =
|
||||||
"45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
- hexString
|
||||||
let cmu2 =
|
- "45e47c5df6f5c5e48aa3526e977b2d1b57eda57214e36f06128008cb17b0125f"
|
||||||
hexString
|
- let cmu2 =
|
||||||
"426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
- hexString
|
||||||
let tree2 =
|
- "426ef44b3b22e0eeda7e4d2b62bac63966572b224e50f97ee56c9490cde4910d"
|
||||||
hexString
|
- let tree2 =
|
||||||
"01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
- hexString
|
||||||
it "Commitment tree is updated correctly" $ do
|
- "01a47029e9b43722c57143a5d07681bff3e2315c9a28ad49d69e7c1f2f6e81ac160010000000000000012f4f72c03f8c937a94919a01a07f21165cc8394295291cb888ca91ed003810390107114fe4bb4cd08b47f6ae47477c182d5da9fe5c189061808c1091e9bf3b4524000001447d6b9100cddd5f80c8cf4ddee2b87eba053bd987465aec2293bd0514e68b0d015f6c95e75f4601a0a31670a7deb970fc8988c611685161d2e1629d0a1a0ebd07015f8b9205e0514fa235d75c150b87e23866b882b39786852d1ab42aab11d31a4a0117ddeb3a5f8d2f6b2d0a07f28f01ab25e03a05a9319275bb86d72fcaef6fc01501f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
- it "Commitment tree is updated correctly" $ do
|
||||||
t1 `shouldNotBe` Nothing
|
- let t1 = updateSaplingCommitmentTree tree cmu1
|
||||||
it "Incremental witness is generated" $ do
|
- t1 `shouldNotBe` Nothing
|
||||||
let t1 = updateSaplingCommitmentTree tree cmu1
|
- it "Incremental witness is generated" $ do
|
||||||
case t1 of
|
- let t1 = updateSaplingCommitmentTree tree cmu1
|
||||||
Nothing -> assertFailure "Failed to append node to tree"
|
- case t1 of
|
||||||
Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
- Nothing -> assertFailure "Failed to append node to tree"
|
||||||
it "Position of note is obtained" $ do
|
- Just t -> getSaplingWitness t `shouldNotBe` Nothing
|
||||||
let p =
|
- it "Position of note is obtained" $ do
|
||||||
getSaplingNotePosition <$>
|
- let p =
|
||||||
(getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
- getSaplingNotePosition <$>
|
||||||
p `shouldBe` Just 129405
|
- (getSaplingWitness =<< updateSaplingCommitmentTree tree cmu1)
|
||||||
|
- p `shouldBe` Just 129405
|
||||||
|
-}
|
||||||
{- describe "Orchard commitment trees" $ do
|
{- describe "Orchard commitment trees" $ do
|
||||||
let tree =
|
let tree =
|
||||||
OrchardCommitmentTree $
|
OrchardCommitmentTree $
|
||||||
|
@ -1061,17 +1066,21 @@ main = do
|
||||||
(hexString
|
(hexString
|
||||||
"97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892")
|
"97e5f003d16720844ba1bd157688a7697133f4bb4a33a7c91974937a1351d7af56d16d4a10bd196ddda700fcd8be517f8f9e39a17ba0eea235d98450a626be3a998ac31f35e8e082106a31fe94da11d02b73748db4aa519df6bbf25c1d62a2cf0b192c6a486bca2632fee9e4124ce2dba6f3366a14850f6a3b784d863119f52458ed774f8d63105b4f6a3d2e09cc74e3a02ec8386213087b4c849172ded6724a45c9c12744ec4a0f86a29b803b17187df5dd5f90e71d1f3f4578d4e1496e8892")
|
||||||
it "Sap output 1" $ do
|
it "Sap output 1" $ do
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "failed to read comm tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
sf_pos <$>
|
||||||
(getSaplingWitness =<<
|
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858"))
|
"fa430c51bb108db782764cff55de9c6b11bbecd2493d2e0fa9f646428feef858")
|
||||||
case pos of
|
case pos of
|
||||||
Nothing -> assertFailure "couldn't get note position"
|
Nothing -> assertFailure "couldn't get note position"
|
||||||
Just p -> do
|
Just p -> do
|
||||||
let dn = decodeSaplingOutputEsk sk so1 TestNet External p
|
let dn =
|
||||||
|
decodeSaplingOutputEsk sk so1 TestNet External $
|
||||||
|
fromIntegral p
|
||||||
dn `shouldBe` Nothing
|
dn `shouldBe` Nothing
|
||||||
it "Sap output 2" $ do
|
it "Sap output 2" $ do
|
||||||
case readZebraTransaction txHex2 of
|
case readZebraTransaction txHex2 of
|
||||||
|
@ -1082,11 +1091,14 @@ main = do
|
||||||
Nothing -> assertFailure "Failed to get sapling bundle"
|
Nothing -> assertFailure "Failed to get sapling bundle"
|
||||||
Just sB -> do
|
Just sB -> do
|
||||||
let sOuts = sbOutputs sB
|
let sOuts = sbOutputs sB
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "Failed to read tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
getSaplingNotePosition <$>
|
||||||
(getSaplingWitness =<<
|
(getSaplingWitness =<<
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
||||||
case pos of
|
case pos of
|
||||||
|
@ -1112,13 +1124,15 @@ main = do
|
||||||
Nothing -> assertFailure "Failed to get sapling bundle"
|
Nothing -> assertFailure "Failed to get sapling bundle"
|
||||||
Just sB -> do
|
Just sB -> do
|
||||||
let sOuts = sbOutputs sB
|
let sOuts = sbOutputs sB
|
||||||
|
case getSaplingFrontier tree of
|
||||||
|
Nothing -> assertFailure "failed to read comm tree"
|
||||||
|
Just tree' -> do
|
||||||
let pos =
|
let pos =
|
||||||
getSaplingNotePosition <$>
|
sf_pos <$>
|
||||||
(getSaplingWitness =<<
|
|
||||||
updateSaplingCommitmentTree
|
updateSaplingCommitmentTree
|
||||||
tree
|
tree'
|
||||||
(fromText
|
(fromText
|
||||||
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843"))
|
"d163c69029e8cb05d874b798c7973b3b1b1b0e04f984a252b73c848698320843")
|
||||||
case pos of
|
case pos of
|
||||||
Nothing -> assertFailure "couldn't get note position"
|
Nothing -> assertFailure "couldn't get note position"
|
||||||
Just p -> do
|
Just p -> do
|
||||||
|
@ -1128,7 +1142,7 @@ main = do
|
||||||
(head . tail $ sOuts)
|
(head . tail $ sOuts)
|
||||||
MainNet
|
MainNet
|
||||||
External
|
External
|
||||||
p
|
(fromIntegral p)
|
||||||
dn `shouldNotBe` Nothing
|
dn `shouldNotBe` Nothing
|
||||||
describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do
|
describe "Generate an ExchangeAddress (MainNet) from transparent address" $ do
|
||||||
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
||||||
|
@ -1176,15 +1190,14 @@ main = do
|
||||||
Just t1 ->
|
Just t1 ->
|
||||||
case updateOrchardCommitmentTree t1 cmx1 of
|
case updateOrchardCommitmentTree t1 cmx1 of
|
||||||
Nothing -> assertFailure "Failed to update frontier with cmx"
|
Nothing -> assertFailure "Failed to update frontier with cmx"
|
||||||
Just t2 ->
|
Just t2 -> do
|
||||||
case updateOrchardCommitmentTree t2 cmx2 of
|
case getOrchardWitness t2 of
|
||||||
Nothing -> assertFailure "Failed to update frontier with cmx"
|
Nothing -> assertFailure "Failed to get witness"
|
||||||
Just t3 ->
|
Just wit -> do
|
||||||
case updateOrchardCommitmentTree t3 cmx3 of
|
let uWit = updateOrchardWitness wit [cmx2, cmx3, cmx4]
|
||||||
Nothing ->
|
Just (getOrchardWitnessAnchor uWit) `shouldBe`
|
||||||
assertFailure "Failed to update frontier with cmx"
|
getOrchardTreeAnchor <$>
|
||||||
Just t4 ->
|
finalTree
|
||||||
updateOrchardCommitmentTree t4 cmx4 `shouldBe` finalTree
|
|
||||||
describe "Witness updates" $ do
|
describe "Witness updates" $ do
|
||||||
it "Sapling" $ do
|
it "Sapling" $ do
|
||||||
let wit =
|
let wit =
|
||||||
|
|
|
@ -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.7.2.0
|
version: 0.7.3.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