Merge pull request #6531 from str4d/cxx-merge-bridges
Merge most `cxx::bridge` definitions into a single bridge
This commit is contained in:
commit
83dc372394
|
@ -50,34 +50,21 @@ if ENABLE_WALLET
|
|||
LIBBITCOIN_WALLET=libbitcoin_wallet.a
|
||||
endif
|
||||
|
||||
# TODO: Figure out how to avoid an explicit file list.
|
||||
CXXBRIDGE_RS = \
|
||||
rust/src/blake2b.rs \
|
||||
rust/src/bundlecache.rs \
|
||||
rust/src/equihash.rs \
|
||||
rust/src/merkle_frontier.rs \
|
||||
rust/src/orchard_bundle.rs \
|
||||
rust/src/sapling.rs \
|
||||
rust/src/streams.rs \
|
||||
rust/src/wallet_scanner.rs
|
||||
rust/src/bridge.rs
|
||||
CXXBRIDGE_H = \
|
||||
rust/gen/include/rust/blake2b.h \
|
||||
rust/gen/include/rust/bundlecache.h \
|
||||
rust/gen/include/rust/equihash.h \
|
||||
rust/gen/include/rust/merkle_frontier.h \
|
||||
rust/gen/include/rust/orchard_bundle.h \
|
||||
rust/gen/include/rust/sapling.h \
|
||||
rust/gen/include/rust/streams.h \
|
||||
rust/gen/include/rust/wallet_scanner.h
|
||||
rust/gen/include/rust/bridge.h
|
||||
CXXBRIDGE_CPP = \
|
||||
rust/gen/src/blake2b.cpp \
|
||||
rust/gen/src/bundlecache.cpp \
|
||||
rust/gen/src/equihash.cpp \
|
||||
rust/gen/src/merkle_frontier.cpp \
|
||||
rust/gen/src/orchard_bundle.cpp \
|
||||
rust/gen/src/sapling.cpp \
|
||||
rust/gen/src/streams.cpp \
|
||||
rust/gen/src/wallet_scanner.cpp
|
||||
rust/gen/src/bridge.cpp
|
||||
|
||||
# We add a rust/cxx.h include to indicate that we provide this (via the rustcxx depends
|
||||
# package), so that cxxbridge doesn't include it within the generated headers and code.
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#include "version.h"
|
||||
|
||||
#include "librustzcash.h"
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/ed25519.h>
|
||||
#include <rust/sapling.h>
|
||||
|
||||
static void ECDSA(benchmark::State& state)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <rust/wallet_scanner.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
struct CDNSSeedData {
|
||||
std::string name, host;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <sodium.h>
|
||||
#include <tracing.h>
|
||||
|
||||
#include <rust/bundlecache.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
#include "zcash/JoinSplit.hpp"
|
||||
|
||||
#include <librustzcash.h>
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/ed25519.h>
|
||||
#include <rust/sapling.h>
|
||||
#include <rust/orchard.h>
|
||||
|
||||
// Subclass of CTransaction which doesn't call UpdateHash when constructing
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
#include "zmq/zmqnotificationinterface.h"
|
||||
#endif
|
||||
|
||||
#include <rust/bundlecache.h>
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/init.h>
|
||||
#include <rust/metrics.h>
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <rust/sapling.h>
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/orchard.h>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "validationinterface.h"
|
||||
|
||||
#include <librustzcash.h>
|
||||
#include <rust/sapling.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
#include "streams.h"
|
||||
|
||||
#include <amount.h>
|
||||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/orchard.h>
|
||||
#include <rust/orchard_bundle.h>
|
||||
#include <rust/orchard/wallet.h>
|
||||
#include "zcash/address/orchard.hpp"
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
#include <univalue.h>
|
||||
#include <rust/orchard_bundle.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
//! FFI bridges between `zcashd`'s Rust and C++ code.
|
||||
//!
|
||||
//! These are all collected into a single file because we can't use the same Rust type
|
||||
//! across multiple bridges until https://github.com/dtolnay/cxx/issues/496 is closed.
|
||||
//!
|
||||
//! The bridges that we leave separate are either standalone Rust code, or exporting C++
|
||||
//! types to Rust (because we _can_ use the same C++ type across multiple bridges).
|
||||
|
||||
use crate::{
|
||||
bundlecache::init as bundlecache_init,
|
||||
merkle_frontier::{new_orchard, orchard_empty_root, parse_orchard, Orchard, OrchardWallet},
|
||||
note_encryption::{
|
||||
try_sapling_note_decryption, try_sapling_output_recovery, DecryptedSaplingOutput,
|
||||
},
|
||||
orchard_bundle::{from_tx_bundle, Action, Bundle, OrchardBundle},
|
||||
params::{network, Network},
|
||||
sapling::{
|
||||
finish_bundle_assembly, init_batch_validator, init_prover, init_verifier,
|
||||
new_bundle_assembler, BatchValidator, Bundle as SaplingBundle,
|
||||
BundleAssembler as SaplingBundleAssembler, Prover, Verifier,
|
||||
},
|
||||
wallet_scanner::{init_batch_scanner, BatchResult, BatchScanner},
|
||||
};
|
||||
|
||||
#[cxx::bridge]
|
||||
pub(crate) mod ffi {
|
||||
extern "C++" {
|
||||
include!("streams.h");
|
||||
|
||||
#[cxx_name = "RustDataStream"]
|
||||
type RustStream = crate::streams::ffi::RustStream;
|
||||
}
|
||||
|
||||
#[namespace = "consensus"]
|
||||
extern "Rust" {
|
||||
type Network;
|
||||
|
||||
fn network(
|
||||
network: &str,
|
||||
overwinter: i32,
|
||||
sapling: i32,
|
||||
blossom: i32,
|
||||
heartwood: i32,
|
||||
canopy: i32,
|
||||
nu5: i32,
|
||||
) -> Result<Box<Network>>;
|
||||
}
|
||||
|
||||
#[namespace = "libzcash"]
|
||||
unsafe extern "C++" {
|
||||
include!("zcash/cache.h");
|
||||
|
||||
type BundleValidityCache;
|
||||
|
||||
fn NewBundleValidityCache(kind: &str, bytes: usize) -> UniquePtr<BundleValidityCache>;
|
||||
fn insert(self: Pin<&mut BundleValidityCache>, entry: [u8; 32]);
|
||||
fn contains(&self, entry: &[u8; 32], erase: bool) -> bool;
|
||||
}
|
||||
#[namespace = "bundlecache"]
|
||||
extern "Rust" {
|
||||
#[rust_name = "bundlecache_init"]
|
||||
fn init(cache_bytes: usize);
|
||||
}
|
||||
|
||||
#[namespace = "sapling"]
|
||||
extern "Rust" {
|
||||
#[rust_name = "SaplingBundle"]
|
||||
type Bundle;
|
||||
|
||||
#[rust_name = "SaplingBundleAssembler"]
|
||||
type BundleAssembler;
|
||||
|
||||
fn new_bundle_assembler() -> Box<SaplingBundleAssembler>;
|
||||
fn add_spend(
|
||||
self: &mut SaplingBundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
nullifier: [u8; 32],
|
||||
rk: &[u8; 32],
|
||||
zkproof: [u8; 192], // GROTH_PROOF_SIZE
|
||||
spend_auth_sig: &[u8; 64],
|
||||
) -> bool;
|
||||
fn add_output(
|
||||
self: &mut SaplingBundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
cmu: &[u8; 32],
|
||||
ephemeral_key: [u8; 32],
|
||||
enc_ciphertext: [u8; 580],
|
||||
out_ciphertext: [u8; 80],
|
||||
zkproof: [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn finish_bundle_assembly(
|
||||
assembler: Box<SaplingBundleAssembler>,
|
||||
value_balance: i64,
|
||||
binding_sig: [u8; 64],
|
||||
) -> Box<SaplingBundle>;
|
||||
|
||||
type Prover;
|
||||
|
||||
fn init_prover() -> Box<Prover>;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn create_spend_proof(
|
||||
self: &mut Prover,
|
||||
ak: &[u8; 32],
|
||||
nsk: &[u8; 32],
|
||||
diversifier: &[u8; 11],
|
||||
rcm: &[u8; 32],
|
||||
ar: &[u8; 32],
|
||||
value: u64,
|
||||
anchor: &[u8; 32],
|
||||
merkle_path: &[u8; 1065], // 1 + 33 * SAPLING_TREE_DEPTH + 8
|
||||
cv: &mut [u8; 32],
|
||||
rk_out: &mut [u8; 32],
|
||||
zkproof: &mut [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn create_output_proof(
|
||||
self: &mut Prover,
|
||||
esk: &[u8; 32],
|
||||
payment_address: &[u8; 43],
|
||||
rcm: &[u8; 32],
|
||||
value: u64,
|
||||
cv: &mut [u8; 32],
|
||||
zkproof: &mut [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn binding_sig(
|
||||
self: &mut Prover,
|
||||
value_balance: i64,
|
||||
sighash: &[u8; 32],
|
||||
result: &mut [u8; 64],
|
||||
) -> bool;
|
||||
|
||||
type Verifier;
|
||||
|
||||
fn init_verifier() -> Box<Verifier>;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn check_spend(
|
||||
self: &mut Verifier,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
nullifier: &[u8; 32],
|
||||
rk: &[u8; 32],
|
||||
zkproof: &[u8; 192], // GROTH_PROOF_SIZE
|
||||
spend_auth_sig: &[u8; 64],
|
||||
sighash_value: &[u8; 32],
|
||||
) -> bool;
|
||||
fn check_output(
|
||||
self: &mut Verifier,
|
||||
cv: &[u8; 32],
|
||||
cm: &[u8; 32],
|
||||
ephemeral_key: &[u8; 32],
|
||||
zkproof: &[u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn final_check(
|
||||
self: &Verifier,
|
||||
value_balance: i64,
|
||||
binding_sig: &[u8; 64],
|
||||
sighash_value: &[u8; 32],
|
||||
) -> bool;
|
||||
|
||||
type BatchValidator;
|
||||
fn init_batch_validator(cache_store: bool) -> Box<BatchValidator>;
|
||||
fn check_bundle(
|
||||
self: &mut BatchValidator,
|
||||
bundle: Box<SaplingBundle>,
|
||||
sighash: [u8; 32],
|
||||
) -> bool;
|
||||
fn validate(self: &mut BatchValidator) -> bool;
|
||||
}
|
||||
|
||||
#[namespace = "orchard_bundle"]
|
||||
extern "Rust" {
|
||||
type Action;
|
||||
type Bundle;
|
||||
type OrchardBundle;
|
||||
|
||||
fn cv(self: &Action) -> [u8; 32];
|
||||
fn nullifier(self: &Action) -> [u8; 32];
|
||||
fn rk(self: &Action) -> [u8; 32];
|
||||
fn cmx(self: &Action) -> [u8; 32];
|
||||
fn ephemeral_key(self: &Action) -> [u8; 32];
|
||||
fn enc_ciphertext(self: &Action) -> [u8; 580];
|
||||
fn out_ciphertext(self: &Action) -> [u8; 80];
|
||||
fn spend_auth_sig(self: &Action) -> [u8; 64];
|
||||
|
||||
unsafe fn from_tx_bundle(bundle: *const OrchardBundle) -> Box<Bundle>;
|
||||
fn actions(self: &Bundle) -> Vec<Action>;
|
||||
fn num_actions(self: &Bundle) -> usize;
|
||||
fn enable_spends(self: &Bundle) -> bool;
|
||||
fn enable_outputs(self: &Bundle) -> bool;
|
||||
fn value_balance_zat(self: &Bundle) -> i64;
|
||||
fn anchor(self: &Bundle) -> [u8; 32];
|
||||
fn proof(self: &Bundle) -> Vec<u8>;
|
||||
fn binding_sig(self: &Bundle) -> [u8; 64];
|
||||
}
|
||||
|
||||
#[namespace = "merkle_frontier"]
|
||||
extern "Rust" {
|
||||
type Orchard;
|
||||
type OrchardWallet;
|
||||
|
||||
fn orchard_empty_root() -> [u8; 32];
|
||||
fn new_orchard() -> Box<Orchard>;
|
||||
fn box_clone(self: &Orchard) -> Box<Orchard>;
|
||||
fn parse_orchard(stream: Pin<&mut RustStream>) -> Result<Box<Orchard>>;
|
||||
fn serialize(self: &Orchard, stream: Pin<&mut RustStream>) -> Result<()>;
|
||||
fn serialize_legacy(self: &Orchard, stream: Pin<&mut RustStream>) -> Result<()>;
|
||||
fn dynamic_memory_usage(self: &Orchard) -> usize;
|
||||
fn root(self: &Orchard) -> [u8; 32];
|
||||
fn size(self: &Orchard) -> u64;
|
||||
fn append_bundle(self: &mut Orchard, bundle: &Bundle) -> bool;
|
||||
unsafe fn init_wallet(self: &Orchard, wallet: *mut OrchardWallet) -> bool;
|
||||
}
|
||||
|
||||
#[namespace = "wallet"]
|
||||
struct SaplingDecryptionResult {
|
||||
txid: [u8; 32],
|
||||
output: u32,
|
||||
ivk: [u8; 32],
|
||||
diversifier: [u8; 11],
|
||||
pk_d: [u8; 32],
|
||||
}
|
||||
|
||||
#[namespace = "wallet"]
|
||||
pub(crate) struct SaplingShieldedOutput {
|
||||
cv: [u8; 32],
|
||||
cmu: [u8; 32],
|
||||
ephemeral_key: [u8; 32],
|
||||
enc_ciphertext: [u8; 580],
|
||||
out_ciphertext: [u8; 80],
|
||||
}
|
||||
|
||||
#[namespace = "wallet"]
|
||||
extern "Rust" {
|
||||
fn try_sapling_note_decryption(
|
||||
network: &Network,
|
||||
height: u32,
|
||||
raw_ivk: &[u8; 32],
|
||||
output: SaplingShieldedOutput,
|
||||
) -> Result<Box<DecryptedSaplingOutput>>;
|
||||
fn try_sapling_output_recovery(
|
||||
network: &Network,
|
||||
height: u32,
|
||||
ovk: [u8; 32],
|
||||
output: SaplingShieldedOutput,
|
||||
) -> Result<Box<DecryptedSaplingOutput>>;
|
||||
|
||||
type DecryptedSaplingOutput;
|
||||
fn note_value(self: &DecryptedSaplingOutput) -> u64;
|
||||
fn note_rseed(self: &DecryptedSaplingOutput) -> [u8; 32];
|
||||
fn zip_212_enabled(self: &DecryptedSaplingOutput) -> bool;
|
||||
fn recipient_d(self: &DecryptedSaplingOutput) -> [u8; 11];
|
||||
fn recipient_pk_d(self: &DecryptedSaplingOutput) -> [u8; 32];
|
||||
fn memo(self: &DecryptedSaplingOutput) -> [u8; 512];
|
||||
|
||||
type BatchScanner;
|
||||
type BatchResult;
|
||||
|
||||
fn init_batch_scanner(
|
||||
network: &Network,
|
||||
sapling_ivks: &[[u8; 32]],
|
||||
) -> Result<Box<BatchScanner>>;
|
||||
fn add_transaction(
|
||||
self: &mut BatchScanner,
|
||||
block_tag: [u8; 32],
|
||||
tx_bytes: &[u8],
|
||||
height: u32,
|
||||
) -> Result<()>;
|
||||
fn flush(self: &mut BatchScanner);
|
||||
fn collect_results(
|
||||
self: &mut BatchScanner,
|
||||
block_tag: [u8; 32],
|
||||
txid: [u8; 32],
|
||||
) -> Box<BatchResult>;
|
||||
|
||||
fn get_sapling(self: &BatchResult) -> Vec<SaplingDecryptionResult>;
|
||||
}
|
||||
}
|
|
@ -5,23 +5,7 @@ use std::{
|
|||
|
||||
use rand_core::{OsRng, RngCore};
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
#[namespace = "libzcash"]
|
||||
unsafe extern "C++" {
|
||||
include!("zcash/cache.h");
|
||||
|
||||
type BundleValidityCache;
|
||||
|
||||
fn NewBundleValidityCache(kind: &str, bytes: usize) -> UniquePtr<BundleValidityCache>;
|
||||
fn insert(self: Pin<&mut BundleValidityCache>, entry: [u8; 32]);
|
||||
fn contains(&self, entry: &[u8; 32], erase: bool) -> bool;
|
||||
}
|
||||
#[namespace = "bundlecache"]
|
||||
extern "Rust" {
|
||||
fn init(cache_bytes: usize);
|
||||
}
|
||||
}
|
||||
use crate::bridge::ffi;
|
||||
|
||||
pub(crate) struct CacheEntry([u8; 32]);
|
||||
|
||||
|
@ -114,7 +98,7 @@ static BUNDLE_CACHES_LOADED: Once = Once::new();
|
|||
static mut SAPLING_BUNDLE_VALIDITY_CACHE: Option<RwLock<BundleValidityCache>> = None;
|
||||
static mut ORCHARD_BUNDLE_VALIDITY_CACHE: Option<RwLock<BundleValidityCache>> = None;
|
||||
|
||||
fn init(cache_bytes: usize) {
|
||||
pub(crate) fn init(cache_bytes: usize) {
|
||||
BUNDLE_CACHES_LOADED.call_once(|| unsafe {
|
||||
SAPLING_BUNDLE_VALIDITY_CACHE = Some(RwLock::new(BundleValidityCache::new(
|
||||
"Sapling",
|
||||
|
|
|
@ -2,63 +2,31 @@ use core::mem::size_of_val;
|
|||
use core::pin::Pin;
|
||||
|
||||
use incrementalmerkletree::{bridgetree, Altitude, Frontier, Hashable};
|
||||
use orchard::{bundle::Authorized, tree::MerkleHashOrchard};
|
||||
use orchard::tree::MerkleHashOrchard;
|
||||
use tracing::error;
|
||||
use zcash_primitives::{
|
||||
merkle_tree::{
|
||||
use zcash_primitives::merkle_tree::{
|
||||
incremental::{read_frontier_v1, write_frontier_v1},
|
||||
CommitmentTree, HashSer,
|
||||
},
|
||||
transaction::components::Amount,
|
||||
};
|
||||
|
||||
use crate::{streams::CppStream, wallet::Wallet};
|
||||
use crate::{bridge::ffi, orchard_bundle, streams::CppStream, wallet::Wallet};
|
||||
|
||||
pub const MERKLE_DEPTH: u8 = 32;
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
extern "C++" {
|
||||
include!("streams.h");
|
||||
|
||||
#[cxx_name = "RustDataStream"]
|
||||
type RustStream = crate::streams::ffi::RustStream;
|
||||
}
|
||||
|
||||
#[namespace = "merkle_frontier"]
|
||||
extern "Rust" {
|
||||
type Orchard;
|
||||
type OrchardBundle;
|
||||
type OrchardWallet;
|
||||
|
||||
fn orchard_empty_root() -> [u8; 32];
|
||||
fn new_orchard() -> Box<Orchard>;
|
||||
fn box_clone(self: &Orchard) -> Box<Orchard>;
|
||||
fn parse_orchard(stream: Pin<&mut RustStream>) -> Result<Box<Orchard>>;
|
||||
fn serialize(self: &Orchard, stream: Pin<&mut RustStream>) -> Result<()>;
|
||||
fn serialize_legacy(self: &Orchard, stream: Pin<&mut RustStream>) -> Result<()>;
|
||||
fn dynamic_memory_usage(self: &Orchard) -> usize;
|
||||
fn root(self: &Orchard) -> [u8; 32];
|
||||
fn size(self: &Orchard) -> u64;
|
||||
unsafe fn append_bundle(self: &mut Orchard, bundle: *const OrchardBundle) -> bool;
|
||||
unsafe fn init_wallet(self: &Orchard, wallet: *mut OrchardWallet) -> bool;
|
||||
}
|
||||
}
|
||||
|
||||
type Inner<H> = bridgetree::Frontier<H, MERKLE_DEPTH>;
|
||||
|
||||
/// An incremental Merkle frontier.
|
||||
#[derive(Clone)]
|
||||
struct MerkleFrontier<H>(Inner<H>);
|
||||
pub(crate) struct MerkleFrontier<H>(Inner<H>);
|
||||
|
||||
impl<H: Copy + Hashable + HashSer> MerkleFrontier<H> {
|
||||
/// Returns a copy of the value.
|
||||
fn box_clone(&self) -> Box<Self> {
|
||||
pub(crate) fn box_clone(&self) -> Box<Self> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
/// Attempts to parse a Merkle frontier from the given C++ stream.
|
||||
fn parse(stream: Pin<&mut ffi::RustStream>) -> Result<Box<Self>, String> {
|
||||
pub(crate) fn parse(stream: Pin<&mut ffi::RustStream>) -> Result<Box<Self>, String> {
|
||||
let reader = CppStream::from(stream);
|
||||
|
||||
match read_frontier_v1(reader) {
|
||||
|
@ -68,14 +36,14 @@ impl<H: Copy + Hashable + HashSer> MerkleFrontier<H> {
|
|||
}
|
||||
|
||||
/// Serializes the frontier to the given C++ stream.
|
||||
fn serialize(&self, stream: Pin<&mut ffi::RustStream>) -> Result<(), String> {
|
||||
pub(crate) fn serialize(&self, stream: Pin<&mut ffi::RustStream>) -> Result<(), String> {
|
||||
let writer = CppStream::from(stream);
|
||||
write_frontier_v1(writer, &self.0)
|
||||
.map_err(|e| format!("Failed to serialize v5 Merkle frontier: {}", e))
|
||||
}
|
||||
|
||||
/// Serializes the frontier to the given C++ stream in the legacy frontier encoding.
|
||||
fn serialize_legacy(&self, stream: Pin<&mut ffi::RustStream>) -> Result<(), String> {
|
||||
pub(crate) fn serialize_legacy(&self, stream: Pin<&mut ffi::RustStream>) -> Result<(), String> {
|
||||
let writer = CppStream::from(stream);
|
||||
let commitment_tree = CommitmentTree::from_frontier(&self.0);
|
||||
commitment_tree.write(writer).map_err(|e| {
|
||||
|
@ -89,13 +57,13 @@ impl<H: Copy + Hashable + HashSer> MerkleFrontier<H> {
|
|||
/// Returns the amount of memory dynamically allocated for the frontier.
|
||||
///
|
||||
/// Includes `self` because this type is stored on the heap when passed to C++.
|
||||
fn dynamic_memory_usage(&self) -> usize {
|
||||
pub(crate) fn dynamic_memory_usage(&self) -> usize {
|
||||
size_of_val(&self.0) + self.0.dynamic_memory_usage()
|
||||
}
|
||||
|
||||
/// Obtains the current root of this Merkle frontier by hashing against empty nodes up
|
||||
/// to the maximum height of the pruned tree that the frontier represents.
|
||||
fn root(&self) -> [u8; 32] {
|
||||
pub(crate) fn root(&self) -> [u8; 32] {
|
||||
let mut root = [0; 32];
|
||||
self.0
|
||||
.root()
|
||||
|
@ -105,39 +73,36 @@ impl<H: Copy + Hashable + HashSer> MerkleFrontier<H> {
|
|||
}
|
||||
|
||||
/// Returns the number of leaves appended to the frontier.
|
||||
fn size(&self) -> u64 {
|
||||
pub(crate) fn size(&self) -> u64 {
|
||||
self.0.position().map_or(0, |p| <u64>::from(p) + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the root of an empty Orchard Merkle tree.
|
||||
fn orchard_empty_root() -> [u8; 32] {
|
||||
pub(crate) fn orchard_empty_root() -> [u8; 32] {
|
||||
let altitude = Altitude::from(MERKLE_DEPTH);
|
||||
MerkleHashOrchard::empty_root(altitude).to_bytes()
|
||||
}
|
||||
|
||||
/// An Orchard incremental Merkle frontier.
|
||||
type Orchard = MerkleFrontier<MerkleHashOrchard>;
|
||||
pub(crate) type Orchard = MerkleFrontier<MerkleHashOrchard>;
|
||||
|
||||
/// Constructs a new empty Orchard Merkle frontier.
|
||||
fn new_orchard() -> Box<Orchard> {
|
||||
pub(crate) fn new_orchard() -> Box<Orchard> {
|
||||
Box::new(MerkleFrontier(Inner::empty()))
|
||||
}
|
||||
|
||||
/// Attempts to parse an Orchard Merkle frontier from the given C++ stream.
|
||||
fn parse_orchard(stream: Pin<&mut ffi::RustStream>) -> Result<Box<Orchard>, String> {
|
||||
pub(crate) fn parse_orchard(stream: Pin<&mut ffi::RustStream>) -> Result<Box<Orchard>, String> {
|
||||
Orchard::parse(stream)
|
||||
}
|
||||
|
||||
struct OrchardBundle;
|
||||
struct OrchardWallet;
|
||||
pub(crate) struct OrchardWallet;
|
||||
|
||||
impl Orchard {
|
||||
/// Appends the note commitments in the given bundle to this frontier.
|
||||
fn append_bundle(&mut self, bundle: *const OrchardBundle) -> bool {
|
||||
let bundle = unsafe { (bundle as *const orchard::Bundle<Authorized, Amount>).as_ref() };
|
||||
|
||||
if let Some(bundle) = bundle {
|
||||
pub(crate) fn append_bundle(&mut self, bundle: &orchard_bundle::Bundle) -> bool {
|
||||
if let Some(bundle) = bundle.inner() {
|
||||
for action in bundle.actions().iter() {
|
||||
if !self.0.append(&MerkleHashOrchard::from_cmx(action.cmx())) {
|
||||
error!("Orchard note commitment tree is full.");
|
||||
|
@ -155,7 +120,7 @@ impl Orchard {
|
|||
/// This will fail with an assertion error if any checkpoints exist in the tree.
|
||||
///
|
||||
/// TODO: Remove once `crate::wallet` is migrated to `cxx`.
|
||||
fn init_wallet(&self, wallet: *mut OrchardWallet) -> bool {
|
||||
pub(crate) fn init_wallet(&self, wallet: *mut OrchardWallet) -> bool {
|
||||
crate::wallet::orchard_wallet_init_from_frontier(wallet as *mut Wallet, &self.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use zcash_primitives::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::{params::Network, wallet_scanner::ffi::SaplingShieldedOutput};
|
||||
use crate::{bridge::ffi::SaplingShieldedOutput, params::Network};
|
||||
|
||||
/// Trial decryption of the full note plaintext by the recipient.
|
||||
///
|
||||
|
|
|
@ -4,80 +4,56 @@ use orchard::{
|
|||
};
|
||||
use zcash_primitives::transaction::components::Amount;
|
||||
|
||||
#[cxx::bridge(namespace = "orchard_bundle")]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
type Action;
|
||||
type Bundle;
|
||||
type OrchardBundle;
|
||||
|
||||
fn cv(self: &Action) -> [u8; 32];
|
||||
fn nullifier(self: &Action) -> [u8; 32];
|
||||
fn rk(self: &Action) -> [u8; 32];
|
||||
fn cmx(self: &Action) -> [u8; 32];
|
||||
fn ephemeral_key(self: &Action) -> [u8; 32];
|
||||
fn enc_ciphertext(self: &Action) -> [u8; 580];
|
||||
fn out_ciphertext(self: &Action) -> [u8; 80];
|
||||
fn spend_auth_sig(self: &Action) -> [u8; 64];
|
||||
|
||||
unsafe fn from_tx_bundle(bundle: *const OrchardBundle) -> Box<Bundle>;
|
||||
fn actions(self: &Bundle) -> Vec<Action>;
|
||||
fn num_actions(self: &Bundle) -> usize;
|
||||
fn enable_spends(self: &Bundle) -> bool;
|
||||
fn enable_outputs(self: &Bundle) -> bool;
|
||||
fn value_balance_zat(self: &Bundle) -> i64;
|
||||
fn anchor(self: &Bundle) -> [u8; 32];
|
||||
fn proof(self: &Bundle) -> Vec<u8>;
|
||||
fn binding_sig(self: &Bundle) -> [u8; 64];
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Action(orchard::Action<Signature<SpendAuth>>);
|
||||
|
||||
impl Action {
|
||||
fn cv(&self) -> [u8; 32] {
|
||||
pub(crate) fn cv(&self) -> [u8; 32] {
|
||||
self.0.cv_net().to_bytes()
|
||||
}
|
||||
|
||||
fn nullifier(&self) -> [u8; 32] {
|
||||
pub(crate) fn nullifier(&self) -> [u8; 32] {
|
||||
self.0.nullifier().to_bytes()
|
||||
}
|
||||
|
||||
fn rk(&self) -> [u8; 32] {
|
||||
pub(crate) fn rk(&self) -> [u8; 32] {
|
||||
self.0.rk().into()
|
||||
}
|
||||
|
||||
fn cmx(&self) -> [u8; 32] {
|
||||
pub(crate) fn cmx(&self) -> [u8; 32] {
|
||||
self.0.cmx().to_bytes()
|
||||
}
|
||||
|
||||
fn ephemeral_key(&self) -> [u8; 32] {
|
||||
pub(crate) fn ephemeral_key(&self) -> [u8; 32] {
|
||||
self.0.encrypted_note().epk_bytes
|
||||
}
|
||||
|
||||
fn enc_ciphertext(&self) -> [u8; 580] {
|
||||
pub(crate) fn enc_ciphertext(&self) -> [u8; 580] {
|
||||
self.0.encrypted_note().enc_ciphertext
|
||||
}
|
||||
|
||||
fn out_ciphertext(&self) -> [u8; 80] {
|
||||
pub(crate) fn out_ciphertext(&self) -> [u8; 80] {
|
||||
self.0.encrypted_note().out_ciphertext
|
||||
}
|
||||
|
||||
fn spend_auth_sig(&self) -> [u8; 64] {
|
||||
pub(crate) fn spend_auth_sig(&self) -> [u8; 64] {
|
||||
self.0.authorization().into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bundle(Option<orchard::Bundle<Authorized, Amount>>);
|
||||
pub struct OrchardBundle;
|
||||
unsafe fn from_tx_bundle(bundle: *const OrchardBundle) -> Box<Bundle> {
|
||||
pub(crate) unsafe fn from_tx_bundle(bundle: *const OrchardBundle) -> Box<Bundle> {
|
||||
Box::new(Bundle(
|
||||
{ (bundle as *const orchard::Bundle<Authorized, Amount>).as_ref() }.cloned(),
|
||||
))
|
||||
}
|
||||
|
||||
impl Bundle {
|
||||
fn actions(&self) -> Vec<Action> {
|
||||
pub(crate) fn inner(&self) -> Option<&orchard::Bundle<Authorized, Amount>> {
|
||||
self.0.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn actions(&self) -> Vec<Action> {
|
||||
self.0
|
||||
.iter()
|
||||
.flat_map(|b| b.actions().iter())
|
||||
|
@ -86,42 +62,35 @@ impl Bundle {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn num_actions(&self) -> usize {
|
||||
self.0.as_ref().map(|b| b.actions().len()).unwrap_or(0)
|
||||
pub(crate) fn num_actions(&self) -> usize {
|
||||
self.inner().map(|b| b.actions().len()).unwrap_or(0)
|
||||
}
|
||||
|
||||
fn enable_spends(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
pub(crate) fn enable_spends(&self) -> bool {
|
||||
self.inner()
|
||||
.map(|b| b.flags().spends_enabled())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn enable_outputs(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
pub(crate) fn enable_outputs(&self) -> bool {
|
||||
self.inner()
|
||||
.map(|b| b.flags().outputs_enabled())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn value_balance_zat(&self) -> i64 {
|
||||
self.0
|
||||
.as_ref()
|
||||
.map(|b| b.value_balance().into())
|
||||
.unwrap_or(0)
|
||||
pub(crate) fn value_balance_zat(&self) -> i64 {
|
||||
self.inner().map(|b| b.value_balance().into()).unwrap_or(0)
|
||||
}
|
||||
|
||||
fn anchor(&self) -> [u8; 32] {
|
||||
self.0
|
||||
.as_ref()
|
||||
pub(crate) fn anchor(&self) -> [u8; 32] {
|
||||
self.inner()
|
||||
.expect("Bundle actions should have been checked to be non-empty")
|
||||
.anchor()
|
||||
.to_bytes()
|
||||
}
|
||||
|
||||
fn proof(&self) -> Vec<u8> {
|
||||
self.0
|
||||
.as_ref()
|
||||
pub(crate) fn proof(&self) -> Vec<u8> {
|
||||
self.inner()
|
||||
.expect("Bundle actions should have been checked to be non-empty")
|
||||
.authorization()
|
||||
.proof()
|
||||
|
@ -129,9 +98,8 @@ impl Bundle {
|
|||
.to_vec()
|
||||
}
|
||||
|
||||
fn binding_sig(&self) -> [u8; 64] {
|
||||
self.0
|
||||
.as_ref()
|
||||
pub(crate) fn binding_sig(&self) -> [u8; 64] {
|
||||
self.inner()
|
||||
.expect("Bundle actions should have been checked to be non-empty")
|
||||
.authorization()
|
||||
.binding_signature()
|
||||
|
|
|
@ -70,6 +70,8 @@ mod streams_ffi;
|
|||
mod tracing_ffi;
|
||||
mod zcashd_orchard;
|
||||
|
||||
mod bridge;
|
||||
|
||||
mod address_ffi;
|
||||
mod builder_ffi;
|
||||
mod bundlecache;
|
||||
|
|
|
@ -36,106 +36,7 @@ use crate::bundlecache::{
|
|||
sapling_bundle_validity_cache, sapling_bundle_validity_cache_mut, CacheEntries,
|
||||
};
|
||||
|
||||
#[cxx::bridge(namespace = "sapling")]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
type Bundle;
|
||||
type BundleAssembler;
|
||||
fn new_bundle_assembler() -> Box<BundleAssembler>;
|
||||
fn add_spend(
|
||||
self: &mut BundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
nullifier: [u8; 32],
|
||||
rk: &[u8; 32],
|
||||
zkproof: [u8; 192], // GROTH_PROOF_SIZE
|
||||
spend_auth_sig: &[u8; 64],
|
||||
) -> bool;
|
||||
fn add_output(
|
||||
self: &mut BundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
cmu: &[u8; 32],
|
||||
ephemeral_key: [u8; 32],
|
||||
enc_ciphertext: [u8; 580],
|
||||
out_ciphertext: [u8; 80],
|
||||
zkproof: [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn finish_bundle_assembly(
|
||||
assembler: Box<BundleAssembler>,
|
||||
value_balance: i64,
|
||||
binding_sig: [u8; 64],
|
||||
) -> Box<Bundle>;
|
||||
|
||||
type Prover;
|
||||
|
||||
fn init_prover() -> Box<Prover>;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn create_spend_proof(
|
||||
self: &mut Prover,
|
||||
ak: &[u8; 32],
|
||||
nsk: &[u8; 32],
|
||||
diversifier: &[u8; 11],
|
||||
rcm: &[u8; 32],
|
||||
ar: &[u8; 32],
|
||||
value: u64,
|
||||
anchor: &[u8; 32],
|
||||
merkle_path: &[u8; 1065], // 1 + 33 * SAPLING_TREE_DEPTH + 8
|
||||
cv: &mut [u8; 32],
|
||||
rk_out: &mut [u8; 32],
|
||||
zkproof: &mut [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn create_output_proof(
|
||||
self: &mut Prover,
|
||||
esk: &[u8; 32],
|
||||
payment_address: &[u8; 43],
|
||||
rcm: &[u8; 32],
|
||||
value: u64,
|
||||
cv: &mut [u8; 32],
|
||||
zkproof: &mut [u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn binding_sig(
|
||||
self: &mut Prover,
|
||||
value_balance: i64,
|
||||
sighash: &[u8; 32],
|
||||
result: &mut [u8; 64],
|
||||
) -> bool;
|
||||
|
||||
type Verifier;
|
||||
|
||||
fn init_verifier() -> Box<Verifier>;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn check_spend(
|
||||
self: &mut Verifier,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
nullifier: &[u8; 32],
|
||||
rk: &[u8; 32],
|
||||
zkproof: &[u8; 192], // GROTH_PROOF_SIZE
|
||||
spend_auth_sig: &[u8; 64],
|
||||
sighash_value: &[u8; 32],
|
||||
) -> bool;
|
||||
fn check_output(
|
||||
self: &mut Verifier,
|
||||
cv: &[u8; 32],
|
||||
cm: &[u8; 32],
|
||||
ephemeral_key: &[u8; 32],
|
||||
zkproof: &[u8; 192], // GROTH_PROOF_SIZE
|
||||
) -> bool;
|
||||
fn final_check(
|
||||
self: &Verifier,
|
||||
value_balance: i64,
|
||||
binding_sig: &[u8; 64],
|
||||
sighash_value: &[u8; 32],
|
||||
) -> bool;
|
||||
|
||||
type BatchValidator;
|
||||
fn init_batch_validator(cache_store: bool) -> Box<BatchValidator>;
|
||||
fn check_bundle(self: &mut BatchValidator, bundle: Box<Bundle>, sighash: [u8; 32]) -> bool;
|
||||
fn validate(self: &mut BatchValidator) -> bool;
|
||||
}
|
||||
}
|
||||
|
||||
struct Bundle(sapling::Bundle<sapling::Authorized>);
|
||||
pub(crate) struct Bundle(sapling::Bundle<sapling::Authorized>);
|
||||
|
||||
impl Bundle {
|
||||
fn commitment<D: TransactionDigest<Authorized>>(&self, digester: D) -> D::SaplingDigest {
|
||||
|
@ -143,12 +44,12 @@ impl Bundle {
|
|||
}
|
||||
}
|
||||
|
||||
struct BundleAssembler {
|
||||
pub(crate) struct BundleAssembler {
|
||||
shielded_spends: Vec<sapling::SpendDescription<sapling::Authorized>>,
|
||||
shielded_outputs: Vec<sapling::OutputDescription<[u8; 192]>>, // GROTH_PROOF_SIZE
|
||||
}
|
||||
|
||||
fn new_bundle_assembler() -> Box<BundleAssembler> {
|
||||
pub(crate) fn new_bundle_assembler() -> Box<BundleAssembler> {
|
||||
Box::new(BundleAssembler {
|
||||
shielded_spends: vec![],
|
||||
shielded_outputs: vec![],
|
||||
|
@ -156,7 +57,7 @@ fn new_bundle_assembler() -> Box<BundleAssembler> {
|
|||
}
|
||||
|
||||
impl BundleAssembler {
|
||||
fn add_spend(
|
||||
pub(crate) fn add_spend(
|
||||
self: &mut BundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
|
@ -203,7 +104,7 @@ impl BundleAssembler {
|
|||
true
|
||||
}
|
||||
|
||||
fn add_output(
|
||||
pub(crate) fn add_output(
|
||||
self: &mut BundleAssembler,
|
||||
cv: &[u8; 32],
|
||||
cm: &[u8; 32],
|
||||
|
@ -239,7 +140,7 @@ impl BundleAssembler {
|
|||
}
|
||||
|
||||
#[allow(clippy::boxed_local)]
|
||||
fn finish_bundle_assembly(
|
||||
pub(crate) fn finish_bundle_assembly(
|
||||
assembler: Box<BundleAssembler>,
|
||||
value_balance: i64,
|
||||
binding_sig: [u8; 64],
|
||||
|
@ -255,15 +156,15 @@ fn finish_bundle_assembly(
|
|||
)))
|
||||
}
|
||||
|
||||
struct Prover(SaplingProvingContext);
|
||||
pub(crate) struct Prover(SaplingProvingContext);
|
||||
|
||||
fn init_prover() -> Box<Prover> {
|
||||
pub(crate) fn init_prover() -> Box<Prover> {
|
||||
Box::new(Prover(SaplingProvingContext::new()))
|
||||
}
|
||||
|
||||
impl Prover {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn create_spend_proof(
|
||||
pub(crate) fn create_spend_proof(
|
||||
&mut self,
|
||||
ak: &[u8; 32],
|
||||
nsk: &[u8; 32],
|
||||
|
@ -361,7 +262,8 @@ impl Prover {
|
|||
|
||||
true
|
||||
}
|
||||
fn create_output_proof(
|
||||
|
||||
pub(crate) fn create_output_proof(
|
||||
&mut self,
|
||||
esk: &[u8; 32],
|
||||
payment_address: &[u8; 43],
|
||||
|
@ -409,7 +311,8 @@ impl Prover {
|
|||
|
||||
true
|
||||
}
|
||||
fn binding_sig(
|
||||
|
||||
pub(crate) fn binding_sig(
|
||||
&mut self,
|
||||
value_balance: i64,
|
||||
sighash: &[u8; 32],
|
||||
|
@ -434,9 +337,9 @@ impl Prover {
|
|||
}
|
||||
}
|
||||
|
||||
struct Verifier(SaplingVerificationContext);
|
||||
pub(crate) struct Verifier(SaplingVerificationContext);
|
||||
|
||||
fn init_verifier() -> Box<Verifier> {
|
||||
pub(crate) fn init_verifier() -> Box<Verifier> {
|
||||
// We consider ZIP 216 active all of the time because blocks prior to NU5
|
||||
// activation (on mainnet and testnet) did not contain Sapling transactions
|
||||
// that violated its canonicity rule.
|
||||
|
@ -445,7 +348,7 @@ fn init_verifier() -> Box<Verifier> {
|
|||
|
||||
impl Verifier {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn check_spend(
|
||||
pub(crate) fn check_spend(
|
||||
&mut self,
|
||||
cv: &[u8; 32],
|
||||
anchor: &[u8; 32],
|
||||
|
@ -500,7 +403,8 @@ impl Verifier {
|
|||
),
|
||||
)
|
||||
}
|
||||
fn check_output(
|
||||
|
||||
pub(crate) fn check_output(
|
||||
&mut self,
|
||||
cv: &[u8; 32],
|
||||
cm: &[u8; 32],
|
||||
|
@ -543,7 +447,8 @@ impl Verifier {
|
|||
),
|
||||
)
|
||||
}
|
||||
fn final_check(
|
||||
|
||||
pub(crate) fn final_check(
|
||||
&self,
|
||||
value_balance: i64,
|
||||
binding_sig: &[u8; 64],
|
||||
|
@ -570,9 +475,9 @@ struct BatchValidatorInner {
|
|||
queued_entries: CacheEntries,
|
||||
}
|
||||
|
||||
struct BatchValidator(Option<BatchValidatorInner>);
|
||||
pub(crate) struct BatchValidator(Option<BatchValidatorInner>);
|
||||
|
||||
fn init_batch_validator(cache_store: bool) -> Box<BatchValidator> {
|
||||
pub(crate) fn init_batch_validator(cache_store: bool) -> Box<BatchValidator> {
|
||||
Box::new(BatchValidator(Some(BatchValidatorInner {
|
||||
validator: sapling_proofs::BatchValidator::new(),
|
||||
queued_entries: CacheEntries::new(cache_store),
|
||||
|
@ -594,7 +499,7 @@ impl BatchValidator {
|
|||
/// the global bundle validity cache, it will have been removed (and this method will
|
||||
/// return `true`).
|
||||
#[allow(clippy::boxed_local)]
|
||||
fn check_bundle(&mut self, bundle: Box<Bundle>, sighash: [u8; 32]) -> bool {
|
||||
pub(crate) fn check_bundle(&mut self, bundle: Box<Bundle>, sighash: [u8; 32]) -> bool {
|
||||
if let Some(inner) = &mut self.0 {
|
||||
let cache = sapling_bundle_validity_cache();
|
||||
|
||||
|
@ -637,7 +542,7 @@ impl BatchValidator {
|
|||
/// If this batch was configured to cache the results, then if this method returns
|
||||
/// `true` every bundle added to the batch will have also been added to the global
|
||||
/// bundle validity cache.
|
||||
fn validate(&mut self) -> bool {
|
||||
pub(crate) fn validate(&mut self) -> bool {
|
||||
if let Some(inner) = self.0.take() {
|
||||
if inner.validator.validate(
|
||||
unsafe { SAPLING_SPEND_VK.as_ref() }
|
||||
|
|
|
@ -21,95 +21,7 @@ use zcash_primitives::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
note_encryption::{
|
||||
parse_and_prepare_sapling_ivk, try_sapling_note_decryption, try_sapling_output_recovery,
|
||||
DecryptedSaplingOutput,
|
||||
},
|
||||
params::{network, Network},
|
||||
};
|
||||
|
||||
#[cxx::bridge]
|
||||
pub(crate) mod ffi {
|
||||
#[namespace = "wallet"]
|
||||
pub(crate) struct SaplingShieldedOutput {
|
||||
cv: [u8; 32],
|
||||
cmu: [u8; 32],
|
||||
ephemeral_key: [u8; 32],
|
||||
enc_ciphertext: [u8; 580],
|
||||
out_ciphertext: [u8; 80],
|
||||
}
|
||||
|
||||
#[namespace = "wallet"]
|
||||
struct SaplingDecryptionResult {
|
||||
txid: [u8; 32],
|
||||
output: u32,
|
||||
ivk: [u8; 32],
|
||||
diversifier: [u8; 11],
|
||||
pk_d: [u8; 32],
|
||||
}
|
||||
|
||||
#[namespace = "consensus"]
|
||||
extern "Rust" {
|
||||
type Network;
|
||||
|
||||
fn network(
|
||||
network: &str,
|
||||
overwinter: i32,
|
||||
sapling: i32,
|
||||
blossom: i32,
|
||||
heartwood: i32,
|
||||
canopy: i32,
|
||||
nu5: i32,
|
||||
) -> Result<Box<Network>>;
|
||||
}
|
||||
|
||||
#[namespace = "wallet"]
|
||||
extern "Rust" {
|
||||
fn try_sapling_note_decryption(
|
||||
network: &Network,
|
||||
height: u32,
|
||||
raw_ivk: &[u8; 32],
|
||||
output: SaplingShieldedOutput,
|
||||
) -> Result<Box<DecryptedSaplingOutput>>;
|
||||
fn try_sapling_output_recovery(
|
||||
network: &Network,
|
||||
height: u32,
|
||||
ovk: [u8; 32],
|
||||
output: SaplingShieldedOutput,
|
||||
) -> Result<Box<DecryptedSaplingOutput>>;
|
||||
|
||||
type DecryptedSaplingOutput;
|
||||
fn note_value(self: &DecryptedSaplingOutput) -> u64;
|
||||
fn note_rseed(self: &DecryptedSaplingOutput) -> [u8; 32];
|
||||
fn zip_212_enabled(self: &DecryptedSaplingOutput) -> bool;
|
||||
fn recipient_d(self: &DecryptedSaplingOutput) -> [u8; 11];
|
||||
fn recipient_pk_d(self: &DecryptedSaplingOutput) -> [u8; 32];
|
||||
fn memo(self: &DecryptedSaplingOutput) -> [u8; 512];
|
||||
|
||||
type BatchScanner;
|
||||
type BatchResult;
|
||||
|
||||
fn init_batch_scanner(
|
||||
network: &Network,
|
||||
sapling_ivks: &[[u8; 32]],
|
||||
) -> Result<Box<BatchScanner>>;
|
||||
fn add_transaction(
|
||||
self: &mut BatchScanner,
|
||||
block_tag: [u8; 32],
|
||||
tx_bytes: &[u8],
|
||||
height: u32,
|
||||
) -> Result<()>;
|
||||
fn flush(self: &mut BatchScanner);
|
||||
fn collect_results(
|
||||
self: &mut BatchScanner,
|
||||
block_tag: [u8; 32],
|
||||
txid: [u8; 32],
|
||||
) -> Box<BatchResult>;
|
||||
|
||||
fn get_sapling(self: &BatchResult) -> Vec<SaplingDecryptionResult>;
|
||||
}
|
||||
}
|
||||
use crate::{bridge::ffi, note_encryption::parse_and_prepare_sapling_ivk, params::Network};
|
||||
|
||||
/// The minimum number of outputs to trial decrypt in a batch.
|
||||
///
|
||||
|
@ -641,7 +553,7 @@ type SaplingRunner =
|
|||
BatchRunner<[u8; 32], SaplingDomain<Network>, OutputDescription<GrothProofBytes>, WithUsage>;
|
||||
|
||||
/// A batch scanner for the `zcashd` wallet.
|
||||
struct BatchScanner {
|
||||
pub(crate) struct BatchScanner {
|
||||
params: Network,
|
||||
sapling_runner: Option<SaplingRunner>,
|
||||
}
|
||||
|
@ -656,7 +568,7 @@ impl DynamicUsage for BatchScanner {
|
|||
}
|
||||
}
|
||||
|
||||
fn init_batch_scanner(
|
||||
pub(crate) fn init_batch_scanner(
|
||||
network: &Network,
|
||||
sapling_ivks: &[[u8; 32]],
|
||||
) -> Result<Box<BatchScanner>, &'static str> {
|
||||
|
@ -690,7 +602,7 @@ impl BatchScanner {
|
|||
/// After adding the outputs, any accumulated batch of sufficient size is run on the
|
||||
/// global threadpool. Subsequent calls to `Self::add_transaction` will accumulate
|
||||
/// those output kinds into new batches.
|
||||
fn add_transaction(
|
||||
pub(crate) fn add_transaction(
|
||||
&mut self,
|
||||
block_tag: [u8; 32],
|
||||
tx_bytes: &[u8],
|
||||
|
@ -724,7 +636,7 @@ impl BatchScanner {
|
|||
/// Runs the currently accumulated batches on the global threadpool.
|
||||
///
|
||||
/// Subsequent calls to `Self::add_transaction` will be accumulated into new batches.
|
||||
fn flush(&mut self) {
|
||||
pub(crate) fn flush(&mut self) {
|
||||
if let Some(runner) = &mut self.sapling_runner {
|
||||
runner.flush();
|
||||
}
|
||||
|
@ -737,7 +649,11 @@ impl BatchScanner {
|
|||
/// mempool change).
|
||||
///
|
||||
/// TODO: Return the `HashMap`s directly once `cxx` supports it.
|
||||
fn collect_results(&mut self, block_tag: [u8; 32], txid: [u8; 32]) -> Box<BatchResult> {
|
||||
pub(crate) fn collect_results(
|
||||
&mut self,
|
||||
block_tag: [u8; 32],
|
||||
txid: [u8; 32],
|
||||
) -> Box<BatchResult> {
|
||||
let block_tag = BlockHash(block_tag);
|
||||
let txid = TxId::from_bytes(txid);
|
||||
|
||||
|
@ -754,12 +670,12 @@ impl BatchScanner {
|
|||
}
|
||||
}
|
||||
|
||||
struct BatchResult {
|
||||
pub(crate) struct BatchResult {
|
||||
sapling: HashMap<(TxId, usize), DecryptedNote<[u8; 32], SaplingDomain<Network>>>,
|
||||
}
|
||||
|
||||
impl BatchResult {
|
||||
fn get_sapling(&self) -> Vec<ffi::SaplingDecryptionResult> {
|
||||
pub(crate) fn get_sapling(&self) -> Vec<ffi::SaplingDecryptionResult> {
|
||||
self.sapling
|
||||
.iter()
|
||||
.map(
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "librustzcash.h"
|
||||
|
||||
#include <rust/bundlecache.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/data/test_case.hpp>
|
||||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/ed25519.h>
|
||||
#include <rust/sapling.h>
|
||||
#include <rust/orchard.h>
|
||||
|
||||
#include <univalue.h>
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
#include <optional>
|
||||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/builder.h>
|
||||
#include <rust/sapling.h>
|
||||
|
||||
#define NO_MEMO {{0xF6}}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <rust/wallet_scanner.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "zcash/util.h"
|
||||
|
||||
#include <primitives/orchard.h>
|
||||
#include <rust/merkle_frontier.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
|
@ -316,8 +316,7 @@ public:
|
|||
}
|
||||
|
||||
bool AppendBundle(const OrchardBundle& bundle) {
|
||||
return inner->append_bundle(
|
||||
reinterpret_cast<merkle_frontier::OrchardBundle*>(bundle.inner.get()));
|
||||
return inner->append_bundle(*bundle.GetDetails());
|
||||
}
|
||||
|
||||
const uint256 root() const {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
#include <rust/wallet_scanner.h>
|
||||
#include <rust/bridge.h>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
#include "zcash/Note.hpp"
|
||||
#include "librustzcash.h"
|
||||
|
||||
#include <rust/bridge.h>
|
||||
#include <rust/ed25519/types.h>
|
||||
#include <rust/sapling.h>
|
||||
|
||||
using namespace libzcash;
|
||||
// This method is based on Shutdown from init.cpp
|
||||
|
|
Loading…
Reference in New Issue