rust: Move history tree FFI logic into a module
This commit is contained in:
parent
b0e6119551
commit
fbeb9412f2
|
@ -0,0 +1,181 @@
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
use libc::{c_uchar, size_t};
|
||||||
|
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
|
||||||
|
|
||||||
|
fn construct_mmr_tree(
|
||||||
|
// Consensus branch id
|
||||||
|
cbranch: u32,
|
||||||
|
// Length of tree in array representation
|
||||||
|
t_len: u32,
|
||||||
|
|
||||||
|
// Indices of provided tree nodes, length of p_len+e_len
|
||||||
|
ni_ptr: *const u32,
|
||||||
|
// Provided tree nodes data, length of p_len+e_len
|
||||||
|
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
||||||
|
|
||||||
|
// Peaks count
|
||||||
|
p_len: size_t,
|
||||||
|
// Extra nodes loaded (for deletion) count
|
||||||
|
e_len: size_t,
|
||||||
|
) -> Result<MMRTree, &'static str> {
|
||||||
|
let (indices, nodes) = unsafe {
|
||||||
|
(
|
||||||
|
slice::from_raw_parts(ni_ptr, p_len + e_len),
|
||||||
|
slice::from_raw_parts(n_ptr, p_len + e_len),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut peaks: Vec<_> = indices
|
||||||
|
.iter()
|
||||||
|
.zip(nodes.iter())
|
||||||
|
.map(
|
||||||
|
|(index, node)| match MMREntry::from_bytes(cbranch, &node[..]) {
|
||||||
|
Ok(entry) => Ok((*index, entry)),
|
||||||
|
Err(_) => Err("Invalid encoding"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
let extra = peaks.split_off(p_len);
|
||||||
|
|
||||||
|
Ok(MMRTree::new(t_len, peaks, extra))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn librustzcash_mmr_append(
|
||||||
|
// Consensus branch id
|
||||||
|
cbranch: u32,
|
||||||
|
// Length of tree in array representation
|
||||||
|
t_len: u32,
|
||||||
|
// Indices of provided tree nodes, length of p_len
|
||||||
|
ni_ptr: *const u32,
|
||||||
|
// Provided tree nodes data, length of p_len
|
||||||
|
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
||||||
|
// Peaks count
|
||||||
|
p_len: size_t,
|
||||||
|
// New node pointer
|
||||||
|
nn_ptr: *const [u8; zcash_history::MAX_NODE_DATA_SIZE],
|
||||||
|
// Return of root commitment
|
||||||
|
rt_ret: *mut [u8; 32],
|
||||||
|
// Return buffer for appended leaves, should be pre-allocated of ceiling(log2(t_len)) length
|
||||||
|
buf_ret: *mut [c_uchar; zcash_history::MAX_NODE_DATA_SIZE],
|
||||||
|
) -> u32 {
|
||||||
|
let new_node_bytes: &[u8; zcash_history::MAX_NODE_DATA_SIZE] = unsafe {
|
||||||
|
match nn_ptr.as_ref() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => {
|
||||||
|
return 0;
|
||||||
|
} // Null pointer passed, error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tree = match construct_mmr_tree(cbranch, t_len, ni_ptr, n_ptr, p_len, 0) {
|
||||||
|
Ok(t) => t,
|
||||||
|
_ => {
|
||||||
|
return 0;
|
||||||
|
} // error
|
||||||
|
};
|
||||||
|
|
||||||
|
let node = match MMRNodeData::from_bytes(cbranch, &new_node_bytes[..]) {
|
||||||
|
Ok(node) => node,
|
||||||
|
_ => {
|
||||||
|
return 0;
|
||||||
|
} // error
|
||||||
|
};
|
||||||
|
|
||||||
|
let appended = match tree.append_leaf(node) {
|
||||||
|
Ok(appended) => appended,
|
||||||
|
_ => {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let return_count = appended.len();
|
||||||
|
|
||||||
|
let root_node = tree
|
||||||
|
.root_node()
|
||||||
|
.expect("Just added, should resolve always; qed");
|
||||||
|
unsafe {
|
||||||
|
*rt_ret = root_node.data().hash();
|
||||||
|
|
||||||
|
for (idx, next_buf) in slice::from_raw_parts_mut(buf_ret, return_count as usize)
|
||||||
|
.iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
tree.resolve_link(appended[idx])
|
||||||
|
.expect("This was generated by the tree and thus resolvable; qed")
|
||||||
|
.data()
|
||||||
|
.write(&mut &mut next_buf[..])
|
||||||
|
.expect("Write using cursor with enough buffer size cannot fail; qed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_count as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn librustzcash_mmr_delete(
|
||||||
|
// Consensus branch id
|
||||||
|
cbranch: u32,
|
||||||
|
// Length of tree in array representation
|
||||||
|
t_len: u32,
|
||||||
|
// Indices of provided tree nodes, length of p_len+e_len
|
||||||
|
ni_ptr: *const u32,
|
||||||
|
// Provided tree nodes data, length of p_len+e_len
|
||||||
|
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
||||||
|
// Peaks count
|
||||||
|
p_len: size_t,
|
||||||
|
// Extra nodes loaded (for deletion) count
|
||||||
|
e_len: size_t,
|
||||||
|
// Return of root commitment
|
||||||
|
rt_ret: *mut [u8; 32],
|
||||||
|
) -> u32 {
|
||||||
|
let mut tree = match construct_mmr_tree(cbranch, t_len, ni_ptr, n_ptr, p_len, e_len) {
|
||||||
|
Ok(t) => t,
|
||||||
|
_ => {
|
||||||
|
return 0;
|
||||||
|
} // error
|
||||||
|
};
|
||||||
|
|
||||||
|
let truncate_len = match tree.truncate_leaf() {
|
||||||
|
Ok(v) => v,
|
||||||
|
_ => {
|
||||||
|
return 0;
|
||||||
|
} // Error
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*rt_ret = tree
|
||||||
|
.root_node()
|
||||||
|
.expect("Just generated without errors, root should be resolving")
|
||||||
|
.data()
|
||||||
|
.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
truncate_len
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn librustzcash_mmr_hash_node(
|
||||||
|
cbranch: u32,
|
||||||
|
n_ptr: *const [u8; zcash_history::MAX_NODE_DATA_SIZE],
|
||||||
|
h_ret: *mut [u8; 32],
|
||||||
|
) -> u32 {
|
||||||
|
let node_bytes: &[u8; zcash_history::MAX_NODE_DATA_SIZE] = unsafe {
|
||||||
|
match n_ptr.as_ref() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => return 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let node = match MMRNodeData::from_bytes(cbranch, &node_bytes[..]) {
|
||||||
|
Ok(n) => n,
|
||||||
|
_ => return 1, // error
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*h_ret = node.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
|
@ -61,14 +61,13 @@ use zcash_proofs::{
|
||||||
sprout,
|
sprout,
|
||||||
};
|
};
|
||||||
|
|
||||||
use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree};
|
|
||||||
|
|
||||||
mod blake2b;
|
mod blake2b;
|
||||||
mod ed25519;
|
mod ed25519;
|
||||||
mod metrics_ffi;
|
mod metrics_ffi;
|
||||||
mod streams_ffi;
|
mod streams_ffi;
|
||||||
mod tracing_ffi;
|
mod tracing_ffi;
|
||||||
|
|
||||||
|
mod history_ffi;
|
||||||
mod orchard_ffi;
|
mod orchard_ffi;
|
||||||
mod transaction_ffi;
|
mod transaction_ffi;
|
||||||
|
|
||||||
|
@ -1092,183 +1091,6 @@ pub extern "C" fn librustzcash_zip32_xfvk_address(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_mmr_tree(
|
|
||||||
// Consensus branch id
|
|
||||||
cbranch: u32,
|
|
||||||
// Length of tree in array representation
|
|
||||||
t_len: u32,
|
|
||||||
|
|
||||||
// Indices of provided tree nodes, length of p_len+e_len
|
|
||||||
ni_ptr: *const u32,
|
|
||||||
// Provided tree nodes data, length of p_len+e_len
|
|
||||||
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
|
||||||
|
|
||||||
// Peaks count
|
|
||||||
p_len: size_t,
|
|
||||||
// Extra nodes loaded (for deletion) count
|
|
||||||
e_len: size_t,
|
|
||||||
) -> Result<MMRTree, &'static str> {
|
|
||||||
let (indices, nodes) = unsafe {
|
|
||||||
(
|
|
||||||
slice::from_raw_parts(ni_ptr, p_len + e_len),
|
|
||||||
slice::from_raw_parts(n_ptr, p_len + e_len),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut peaks: Vec<_> = indices
|
|
||||||
.iter()
|
|
||||||
.zip(nodes.iter())
|
|
||||||
.map(
|
|
||||||
|(index, node)| match MMREntry::from_bytes(cbranch, &node[..]) {
|
|
||||||
Ok(entry) => Ok((*index, entry)),
|
|
||||||
Err(_) => Err("Invalid encoding"),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect::<Result<_, _>>()?;
|
|
||||||
let extra = peaks.split_off(p_len);
|
|
||||||
|
|
||||||
Ok(MMRTree::new(t_len, peaks, extra))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "system" fn librustzcash_mmr_append(
|
|
||||||
// Consensus branch id
|
|
||||||
cbranch: u32,
|
|
||||||
// Length of tree in array representation
|
|
||||||
t_len: u32,
|
|
||||||
// Indices of provided tree nodes, length of p_len
|
|
||||||
ni_ptr: *const u32,
|
|
||||||
// Provided tree nodes data, length of p_len
|
|
||||||
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
|
||||||
// Peaks count
|
|
||||||
p_len: size_t,
|
|
||||||
// New node pointer
|
|
||||||
nn_ptr: *const [u8; zcash_history::MAX_NODE_DATA_SIZE],
|
|
||||||
// Return of root commitment
|
|
||||||
rt_ret: *mut [u8; 32],
|
|
||||||
// Return buffer for appended leaves, should be pre-allocated of ceiling(log2(t_len)) length
|
|
||||||
buf_ret: *mut [c_uchar; zcash_history::MAX_NODE_DATA_SIZE],
|
|
||||||
) -> u32 {
|
|
||||||
let new_node_bytes: &[u8; zcash_history::MAX_NODE_DATA_SIZE] = unsafe {
|
|
||||||
match nn_ptr.as_ref() {
|
|
||||||
Some(r) => r,
|
|
||||||
None => {
|
|
||||||
return 0;
|
|
||||||
} // Null pointer passed, error
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut tree = match construct_mmr_tree(cbranch, t_len, ni_ptr, n_ptr, p_len, 0) {
|
|
||||||
Ok(t) => t,
|
|
||||||
_ => {
|
|
||||||
return 0;
|
|
||||||
} // error
|
|
||||||
};
|
|
||||||
|
|
||||||
let node = match MMRNodeData::from_bytes(cbranch, &new_node_bytes[..]) {
|
|
||||||
Ok(node) => node,
|
|
||||||
_ => {
|
|
||||||
return 0;
|
|
||||||
} // error
|
|
||||||
};
|
|
||||||
|
|
||||||
let appended = match tree.append_leaf(node) {
|
|
||||||
Ok(appended) => appended,
|
|
||||||
_ => {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let return_count = appended.len();
|
|
||||||
|
|
||||||
let root_node = tree
|
|
||||||
.root_node()
|
|
||||||
.expect("Just added, should resolve always; qed");
|
|
||||||
unsafe {
|
|
||||||
*rt_ret = root_node.data().hash();
|
|
||||||
|
|
||||||
for (idx, next_buf) in slice::from_raw_parts_mut(buf_ret, return_count as usize)
|
|
||||||
.iter_mut()
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
tree.resolve_link(appended[idx])
|
|
||||||
.expect("This was generated by the tree and thus resolvable; qed")
|
|
||||||
.data()
|
|
||||||
.write(&mut &mut next_buf[..])
|
|
||||||
.expect("Write using cursor with enough buffer size cannot fail; qed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return_count as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "system" fn librustzcash_mmr_delete(
|
|
||||||
// Consensus branch id
|
|
||||||
cbranch: u32,
|
|
||||||
// Length of tree in array representation
|
|
||||||
t_len: u32,
|
|
||||||
// Indices of provided tree nodes, length of p_len+e_len
|
|
||||||
ni_ptr: *const u32,
|
|
||||||
// Provided tree nodes data, length of p_len+e_len
|
|
||||||
n_ptr: *const [c_uchar; zcash_history::MAX_ENTRY_SIZE],
|
|
||||||
// Peaks count
|
|
||||||
p_len: size_t,
|
|
||||||
// Extra nodes loaded (for deletion) count
|
|
||||||
e_len: size_t,
|
|
||||||
// Return of root commitment
|
|
||||||
rt_ret: *mut [u8; 32],
|
|
||||||
) -> u32 {
|
|
||||||
let mut tree = match construct_mmr_tree(cbranch, t_len, ni_ptr, n_ptr, p_len, e_len) {
|
|
||||||
Ok(t) => t,
|
|
||||||
_ => {
|
|
||||||
return 0;
|
|
||||||
} // error
|
|
||||||
};
|
|
||||||
|
|
||||||
let truncate_len = match tree.truncate_leaf() {
|
|
||||||
Ok(v) => v,
|
|
||||||
_ => {
|
|
||||||
return 0;
|
|
||||||
} // Error
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
*rt_ret = tree
|
|
||||||
.root_node()
|
|
||||||
.expect("Just generated without errors, root should be resolving")
|
|
||||||
.data()
|
|
||||||
.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
truncate_len
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "system" fn librustzcash_mmr_hash_node(
|
|
||||||
cbranch: u32,
|
|
||||||
n_ptr: *const [u8; zcash_history::MAX_NODE_DATA_SIZE],
|
|
||||||
h_ret: *mut [u8; 32],
|
|
||||||
) -> u32 {
|
|
||||||
let node_bytes: &[u8; zcash_history::MAX_NODE_DATA_SIZE] = unsafe {
|
|
||||||
match n_ptr.as_ref() {
|
|
||||||
Some(r) => r,
|
|
||||||
None => return 1,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let node = match MMRNodeData::from_bytes(cbranch, &node_bytes[..]) {
|
|
||||||
Ok(n) => n,
|
|
||||||
_ => return 1, // error
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
*h_ret = node.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn librustzcash_getrandom(buf: *mut u8, buf_len: usize) {
|
pub extern "C" fn librustzcash_getrandom(buf: *mut u8, buf_len: usize) {
|
||||||
let buf = unsafe { slice::from_raw_parts_mut(buf, buf_len) };
|
let buf = unsafe { slice::from_raw_parts_mut(buf, buf_len) };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use zcash_history::{Entry, EntryLink, NodeData};
|
use zcash_history::{Entry, EntryLink, NodeData};
|
||||||
|
|
||||||
use crate::{librustzcash_mmr_append, librustzcash_mmr_delete};
|
use crate::history_ffi::{librustzcash_mmr_append, librustzcash_mmr_delete};
|
||||||
|
|
||||||
const NODE_DATA_16L: &[u8] = include_bytes!("./res/tree16.dat");
|
const NODE_DATA_16L: &[u8] = include_bytes!("./res/tree16.dat");
|
||||||
const NODE_DATA_1023L: &[u8] = include_bytes!("./res/tree1023.dat");
|
const NODE_DATA_1023L: &[u8] = include_bytes!("./res/tree1023.dat");
|
||||||
|
|
Loading…
Reference in New Issue