Implement the Rust side of the incremental merkle tree FFI.

This commit is contained in:
Kris Nuttycombe 2021-06-17 11:02:52 -06:00
parent 0247c0c682
commit 68ce7e4828
5 changed files with 494 additions and 52 deletions

117
Cargo.lock generated
View File

@ -74,9 +74,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "arrayvec"
version = "0.7.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
[[package]]
name = "atomic-shim"
@ -109,7 +109,7 @@ dependencies = [
"group",
"num_cpus",
"pairing",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
@ -123,6 +123,15 @@ dependencies = [
"crunchy",
]
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.2.1"
@ -197,7 +206,7 @@ dependencies = [
"ff",
"group",
"pairing",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
@ -255,9 +264,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "cpufeatures"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
dependencies = [
"libc",
]
@ -457,7 +466,7 @@ source = "git+https://github.com/ZcashFoundation/ed25519-zebra.git?rev=d35124002
dependencies = [
"curve25519-dalek",
"hex",
"rand_core 0.6.2",
"rand_core 0.6.3",
"serde",
"sha2",
"thiserror",
@ -473,7 +482,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "equihash"
version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6"
source = "git+https://github.com/nuttycom/librustzcash.git?branch=incremental_merkle_tree#0fa09e052226ef70e5487be66ede75de11c30206"
dependencies = [
"blake2b_simd",
"byteorder",
@ -486,7 +495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63eec06c61e487eecf0f7e6e6372e596a81922c28d33e645d6983ca6493a1af0"
dependencies = [
"bitvec",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
@ -605,7 +614,7 @@ checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
dependencies = [
"byteorder",
"ff",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
@ -710,6 +719,14 @@ dependencies = [
"want",
]
[[package]]
name = "incrementalmerkletree"
version = "0.1.0"
source = "git+https://github.com/nuttycom/incrementalmerkletree.git?branch=merkle_bridge#cf68d49d3f63279dac6b2ec704927ceadca156ee"
dependencies = [
"serde",
]
[[package]]
name = "indexmap"
version = "1.6.2"
@ -731,9 +748,9 @@ dependencies = [
[[package]]
name = "ipnet"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "itoa"
@ -751,7 +768,7 @@ dependencies = [
"bls12_381",
"ff",
"group",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
@ -763,15 +780,16 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.95"
version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "librustzcash"
version = "0.2.0"
dependencies = [
"bellman",
"bincode",
"blake2b_simd",
"blake2s_simd",
"bls12_381",
@ -779,6 +797,7 @@ dependencies = [
"ed25519-zebra",
"group",
"hyper",
"incrementalmerkletree",
"ipnet",
"jubjub",
"libc",
@ -786,7 +805,7 @@ dependencies = [
"metrics-exporter-prometheus",
"nonempty",
"orchard",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
"thiserror",
"tokio",
@ -795,6 +814,7 @@ dependencies = [
"tracing-core",
"tracing-subscriber",
"zcash_history",
"zcash_note_encryption",
"zcash_primitives",
"zcash_proofs",
]
@ -931,9 +951,9 @@ dependencies = [
[[package]]
name = "mio"
version = "0.7.11"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
dependencies = [
"libc",
"log",
@ -1017,9 +1037,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.7.2"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "opaque-debug"
@ -1030,21 +1050,23 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "orchard"
version = "0.0.0"
source = "git+https://github.com/zcash/orchard.git?rev=93a7f1db228479228f768e9d86dd5868e4c2ff1e#93a7f1db228479228f768e9d86dd5868e4c2ff1e"
source = "git+https://github.com/nuttycom/orchard.git?branch=incremental_merkle_tree#52394b8e8d16cf848519975ca6b1c6c2ca908a43"
dependencies = [
"aes",
"arrayvec 0.7.0",
"arrayvec 0.7.1",
"bitvec",
"blake2b_simd",
"ff",
"fpe",
"group",
"halo2",
"incrementalmerkletree",
"lazy_static",
"nonempty",
"pasta_curves",
"rand",
"reddsa",
"serde",
"subtle",
"zcash_note_encryption",
]
@ -1202,24 +1224,24 @@ dependencies = [
[[package]]
name = "rand"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core 0.6.2",
"rand_core 0.6.3",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.2",
"rand_core 0.6.3",
]
[[package]]
@ -1233,20 +1255,20 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom 0.2.3",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.2",
"rand_core 0.6.3",
]
[[package]]
@ -1269,7 +1291,7 @@ dependencies = [
"group",
"jubjub",
"pasta_curves",
"rand_core 0.6.2",
"rand_core 0.6.3",
"serde",
"thiserror",
"zeroize",
@ -1277,9 +1299,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
dependencies = [
"bitflags",
]
@ -1429,9 +1451,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]]
name = "syn"
version = "1.0.72"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
dependencies = [
"proc-macro2",
"quote",
@ -1509,15 +1531,16 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.6.1"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a38d31d7831c6ed7aad00aa4c12d9375fd225a6dd77da1d25b707346319a975"
checksum = "5fb2ed024293bb19f7a5dc54fe83bf86532a44c12a2bb8ba40d64a4509395ca2"
dependencies = [
"autocfg",
"libc",
"mio",
"pin-project-lite",
"tokio-macros",
"winapi",
]
[[package]]
@ -1677,7 +1700,7 @@ dependencies = [
[[package]]
name = "zcash_history"
version = "0.2.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6"
source = "git+https://github.com/nuttycom/librustzcash.git?branch=incremental_merkle_tree#0fa09e052226ef70e5487be66ede75de11c30206"
dependencies = [
"bigint",
"blake2b_simd",
@ -1687,21 +1710,21 @@ dependencies = [
[[package]]
name = "zcash_note_encryption"
version = "0.0.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6"
source = "git+https://github.com/nuttycom/librustzcash.git?branch=incremental_merkle_tree#0fa09e052226ef70e5487be66ede75de11c30206"
dependencies = [
"blake2b_simd",
"byteorder",
"crypto_api_chachapoly",
"ff",
"group",
"rand_core 0.6.2",
"rand_core 0.6.3",
"subtle",
]
[[package]]
name = "zcash_primitives"
version = "0.5.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6"
source = "git+https://github.com/nuttycom/librustzcash.git?branch=incremental_merkle_tree#0fa09e052226ef70e5487be66ede75de11c30206"
dependencies = [
"aes",
"bitvec",
@ -1722,7 +1745,7 @@ dependencies = [
"orchard",
"pasta_curves",
"rand",
"rand_core 0.6.2",
"rand_core 0.6.3",
"sha2",
"subtle",
"zcash_note_encryption",
@ -1731,7 +1754,7 @@ dependencies = [
[[package]]
name = "zcash_proofs"
version = "0.5.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6"
source = "git+https://github.com/nuttycom/librustzcash.git?branch=incremental_merkle_tree#0fa09e052226ef70e5487be66ede75de11c30206"
dependencies = [
"bellman",
"blake2b_simd",
@ -1742,7 +1765,7 @@ dependencies = [
"group",
"jubjub",
"lazy_static",
"rand_core 0.6.2",
"rand_core 0.6.3",
"zcash_primitives",
]

View File

@ -21,11 +21,13 @@ crate-type = ["staticlib"]
[dependencies]
bellman = "0.10"
bincode = "1.3"
blake2b_simd = "0.5"
blake2s_simd = "0.5"
bls12_381 = "0.5"
byteorder = "1"
group = "0.10"
incrementalmerkletree = "0.1"
libc = "0.2"
jubjub = "0.7"
nonempty = "0.6"
@ -36,6 +38,7 @@ tracing = "0.1"
tracing-core = "0.1"
tracing-appender = "0.1"
zcash_history = "0.2"
zcash_note_encryption = "0.0"
zcash_primitives = "0.5"
zcash_proofs = "0.5"
ed25519-zebra = "2.2.0"
@ -61,8 +64,9 @@ codegen-units = 1
[patch.crates-io]
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "d04b532368d05b505e622f8cac4c0693574fbd93" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "93a7f1db228479228f768e9d86dd5868e4c2ff1e" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" }
incrementalmerkletree = { git = "https://github.com/nuttycom/incrementalmerkletree.git", branch = "merkle_bridge" }
orchard = { git = "https://github.com/nuttycom/orchard.git", branch = "incremental_merkle_tree" }
zcash_history = { git = "https://github.com/nuttycom/librustzcash.git", branch = "incremental_merkle_tree" }
zcash_note_encryption = { git = "https://github.com/nuttycom/librustzcash.git", branch = "incremental_merkle_tree" }
zcash_primitives = { git = "https://github.com/nuttycom/librustzcash.git", branch = "incremental_merkle_tree" }
zcash_proofs = { git = "https://github.com/nuttycom/librustzcash.git", branch = "incremental_merkle_tree" }

View File

@ -0,0 +1,150 @@
// Copyright (c) 2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef ZCASH_RUST_INCLUDE_INCREMENTAL_MERKLE_H
#define ZCASH_RUST_INCLUDE_INCREMENTAL_MERKLE_H
#include "rust/streams.h"
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SINSEMILLA_DIGEST_LEN 32U
/// Pointer to an Orchard incremental merkle tree frontier
struct OrchardMerkleFrontierPtr;
typedef struct OrchardMerkleFrontierPtr OrchardMerkleFrontierPtr;
// Create an empty Orchard Merkle frontier.
//
// Memory allocated to the resulting value must be manually freed.
OrchardMerkleFrontierPtr* orchard_merkle_frontier_empty();
// Create an empty Orchard Merkle frontier.
//
// Memory allocated to the resulting value must be manually freed.
OrchardMerkleFrontierPtr* orchard_merkle_frontier_empty();
// Clones the given Orchard Merkle frontier and returns
// a pointer to the newly created tree. Both the original
// tree's memory and the newly allocated one need to be freed
// independently.
OrchardMerkleFrontierPtr* orchard_merkle_frontier_clone(
const OrchardMerkleFrontierPtr* tree_ptr
);
// Free the memory allocated for the given Orchard Merkle frontier.
void orchard_merkle_frontier_free(
OrchardMerkleFrontierPtr* tree_ptr
);
// Parses an Orchard Merkle frontier from a stream. If parsing
// fails, this will return the null pointer.
//
// Memory allocated to the resulting value must be manually freed.
OrchardMerkleFrontierPtr* orchard_merkle_frontier_parse(
void* stream,
read_callback_t read_cb
);
// Parses an Orchard Merkle frontier from a stream. If parsing
// fails, this will return the null pointer.
//
// Memory allocated to the resulting value must be manually freed.
bool orchard_merkle_frontier_serialize(
const OrchardMerkleFrontierPtr* tree_ptr,
void* stream,
write_callback_t write_cb
);
// For each action in the provided bundle, append its
// commitment to the frontier.
bool orchard_merkle_frontier_append_bundle(
OrchardMerkleFrontierPtr* tree_ptr,
const OrchardBundlePtr* bundle
);
/// Pointer to an Orchard incremental sinsemilla tree
struct IncrementalSinsemillaTreePtr;
typedef struct IncrementalSinsemillaTreePtr IncrementalSinsemillaTreePtr;
// Create an empty incremental sinsemilla tree.
//
// Memory allocated to the resulting value must be manually freed.
IncrementalSinsemillaTreePtr* incremental_sinsemilla_tree_empty();
// Clones the given incremental sinsemilla tree and returns
// a pointer to the newly created tree. Both the original
// tree's memory and the newly allocated one need to be freed
// independently.
IncrementalSinsemillaTreePtr* incremental_sinsemilla_tree_clone(
const IncrementalSinsemillaTreePtr* tree_ptr
);
// Free the memory allocated for the given incremental sinsemilla tree.
void incremental_sinsemilla_tree_free(
IncrementalSinsemillaTreePtr* tree_ptr
);
// Parses an incremental sinsemilla tree from a stream. If parsing
// fails, this will return the null pointer.
//
// Memory allocated to the resulting value must be manually freed.
IncrementalSinsemillaTreePtr* incremental_sinsemilla_tree_parse(
void* stream,
read_callback_t read_cb
);
// Parses an incremental sinsemilla tree from a stream. If parsing
// fails, this will return the null pointer.
//
// Memory allocated to the resulting value must be manually freed.
bool incremental_sinsemilla_tree_serialize(
const IncrementalSinsemillaTreePtr* tree_ptr,
void* stream,
write_callback_t write_cb
);
// For each action in the provided bundle, append its
// commitment to the incremental Merkle tree.
bool incremental_sinsemilla_tree_append_bundle(
IncrementalSinsemillaTreePtr* tree_ptr,
const OrchardBundlePtr* bundle
);
// Save the current state of the incremental merkle tree
// as a point to which the tree can be rewound.
void incremental_sinsemilla_tree_checkpoint(
IncrementalSinsemillaTreePtr* tree_ptr
);
// Rewind the incremental merkle tree to the latest checkpoint.
bool incremental_sinsemilla_tree_rewind(
IncrementalSinsemillaTreePtr* tree_ptr
);
// Compute the root of the provided incremental sinsemilla tree.
//
// If no error occurs, `digest_ret` will point to the resulting
// digest and this procedure returns `true`.
// If an error occurs, `digest_ret` will be unaltered and this
// procedure returns `false`.
bool incremental_sinsemilla_tree_root(
const IncrementalSinsemillaTreePtr* tree_ptr,
unsigned char* digest_ret
);
// Return the empty leaf value for the incremental sinsemilla tree.
bool incremental_sinsemilla_tree_empty_leaf(
unsigned char* digest_ret
);
#ifdef __cplusplus
}
#endif
#endif // ZCASH_RUST_INCLUDE_INCREMENTAL_MERKLE_H

View File

@ -14,6 +14,8 @@ use zcash_primitives::transaction::{
use crate::streams_ffi::{CppStreamReader, CppStreamWriter, ReadCb, StreamObj, WriteCb};
mod incremental_sinsemilla_tree_ffi;
#[no_mangle]
pub extern "C" fn orchard_bundle_clone(
bundle: *const Bundle<Authorized, Amount>,

View File

@ -0,0 +1,263 @@
use bincode;
use incrementalmerkletree::{Tree, Frontier, Hashable, bridgetree::{self, BridgeTree}};
use std::ptr;
use orchard::{bundle::Authorized, tree::OrchardIncrementalTreeDigest};
use zcash_primitives::transaction::components::Amount;
use crate::orchard_ffi::{CppStreamReader, CppStreamWriter, ReadCb, StreamObj, WriteCb, error};
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_empty(
) -> *mut bridgetree::Frontier<OrchardIncrementalTreeDigest> {
let empty_tree = bridgetree::Frontier::new(32);
Box::into_raw(Box::new(empty_tree))
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_clone(
tree: *const bridgetree::Frontier<OrchardIncrementalTreeDigest>,
) -> *mut bridgetree::Frontier<OrchardIncrementalTreeDigest> {
unsafe { tree.as_ref() }
.map(|tree| Box::into_raw(Box::new(tree.clone())))
.unwrap_or(std::ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_free(
tree: *mut bridgetree::Frontier<OrchardIncrementalTreeDigest>,
) {
if !tree.is_null() {
drop(unsafe { Box::from_raw(tree) });
}
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_parse(
stream: Option<StreamObj>,
read_cb: Option<ReadCb>,
) -> *mut bridgetree::Frontier<OrchardIncrementalTreeDigest> {
let reader = CppStreamReader::from_raw_parts(stream, read_cb.unwrap());
match bincode::deserialize_from(reader) {
Ok(parsed) => Box::into_raw(Box::new(parsed)),
Err(e) => {
error!("Failed to parse Orchard bundle: {}", e);
ptr::null_mut()
}
}
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_serialize(
tree: *const bridgetree::Frontier<OrchardIncrementalTreeDigest>,
stream: Option<StreamObj>,
write_cb: Option<WriteCb>,
) -> bool {
let tree = unsafe {
tree.as_ref()
.expect("Orchard tree pointer may not be null.")
};
let writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap());
match bincode::serialize_into(writer, tree) {
Ok(()) => true,
Err(e) => {
error!("{}", e);
false
}
}
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_append_bundle(
tree: *mut bridgetree::Frontier<OrchardIncrementalTreeDigest>,
bundle: *const orchard::Bundle<Authorized, Amount>,
) -> bool {
let tree = unsafe {
tree.as_mut()
.expect("Orchard note commitment tree pointer may not be null.")
};
if let Some(bundle) = unsafe { bundle.as_ref() } {
for action in bundle.actions().iter() {
if !tree.append(&OrchardIncrementalTreeDigest::from_cmx(action.cmx())) {
error!("Orchard note commitment tree is full.");
return false;
}
}
true
} else {
false
}
}
#[no_mangle]
pub extern "C" fn orchard_merkle_frontier_root(
tree: *mut bridgetree::Frontier<OrchardIncrementalTreeDigest>,
root_ret: *mut [u8; 32],
) -> bool {
let root_ret = unsafe {
root_ret
.as_mut()
.expect("Cannot return to the null pointer.")
};
if let Some(tree) = unsafe { tree.as_ref() } {
if let Some(root) = tree.root().to_bytes() {
root_ret.copy_from_slice(&root);
true
} else {
false
}
} else {
false
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_empty(
) -> *mut BridgeTree<OrchardIncrementalTreeDigest> {
let empty_tree = BridgeTree::new(32, 100);
Box::into_raw(Box::new(empty_tree))
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_clone(
tree: *const BridgeTree<OrchardIncrementalTreeDigest>,
) -> *mut BridgeTree<OrchardIncrementalTreeDigest> {
unsafe { tree.as_ref() }
.map(|tree| Box::into_raw(Box::new(tree.clone())))
.unwrap_or(std::ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_free(
tree: *mut BridgeTree<OrchardIncrementalTreeDigest>,
) {
if !tree.is_null() {
drop(unsafe { Box::from_raw(tree) });
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_parse(
stream: Option<StreamObj>,
read_cb: Option<ReadCb>,
) -> *mut BridgeTree<OrchardIncrementalTreeDigest> {
let reader = CppStreamReader::from_raw_parts(stream, read_cb.unwrap());
match bincode::deserialize_from(reader) {
Ok(parsed) => Box::into_raw(Box::new(parsed)),
Err(e) => {
error!("Failed to parse Orchard bundle: {}", e);
ptr::null_mut()
}
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_serialize(
tree: *const BridgeTree<OrchardIncrementalTreeDigest>,
stream: Option<StreamObj>,
write_cb: Option<WriteCb>,
) -> bool {
let tree = unsafe {
tree.as_ref()
.expect("Orchard tree pointer may not be null.")
};
let writer = CppStreamWriter::from_raw_parts(stream, write_cb.unwrap());
match bincode::serialize_into(writer, tree) {
Ok(()) => true,
Err(e) => {
error!("{}", e);
false
}
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_append_bundle(
tree: *mut BridgeTree<OrchardIncrementalTreeDigest>,
bundle: *const orchard::Bundle<Authorized, Amount>,
) -> bool {
let tree = unsafe {
tree.as_mut()
.expect("Orchard note commitment tree pointer may not be null.")
};
if let Some(bundle) = unsafe { bundle.as_ref() } {
for action in bundle.actions().iter() {
if !tree.append(&OrchardIncrementalTreeDigest::from_cmx(action.cmx())) {
error!("Orchard note commitment tree is full.");
return false;
}
}
true
} else {
false
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_checkpoint(
tree: *mut BridgeTree<OrchardIncrementalTreeDigest>,
) {
let tree = unsafe {
tree.as_mut()
.expect("Orchard tree pointer may not be null.")
};
tree.checkpoint()
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_rewind(
tree: *mut BridgeTree<OrchardIncrementalTreeDigest>,
) -> bool {
let tree = unsafe {
tree.as_mut()
.expect("Orchard tree pointer may not be null.")
};
tree.rewind()
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_root(
tree: *mut BridgeTree<OrchardIncrementalTreeDigest>,
root_ret: *mut [u8; 32],
) -> bool {
let root_ret = unsafe {
root_ret
.as_mut()
.expect("Cannot return to the null pointer.")
};
if let Some(tree) = unsafe { tree.as_ref() } {
if let Some(root) = tree.root().to_bytes() {
root_ret.copy_from_slice(&root);
true
} else {
false
}
} else {
false
}
}
#[no_mangle]
pub extern "C" fn incremental_sinsemilla_tree_empty_leaf(
root_ret: *mut [u8; 32],
) {
let root_ret = unsafe {
root_ret
.as_mut()
.expect("Cannot return to the null pointer.")
};
let digest = OrchardIncrementalTreeDigest::empty_leaf().to_bytes().unwrap();
root_ret.copy_from_slice(&digest);
}