Allow `no_std` use of `incrementalmerkletree`

This commit is contained in:
Kris Nuttycombe 2024-12-16 10:00:00 -07:00
parent d663a8f64f
commit 0eecd6dae7
7 changed files with 45 additions and 23 deletions

4
Cargo.lock generated
View File

@ -64,9 +64,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "either"
version = "1.9.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "errno"

View File

@ -7,6 +7,9 @@ and this project adheres to Rust's notion of
## Unreleased
### Added
- `no-std` support, via a default-enabled `std` feature flag.
## [0.7.0] - 2024-09-25
### Changed

View File

@ -18,7 +18,7 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
either = "1.8"
either = { version = "1.8", default-features = false }
proptest = { workspace = true, optional = true }
rand = { version = "0.8", optional = true }
rand_core = { version = "0.6", optional = true }
@ -30,10 +30,12 @@ rand_core = "0.6"
rand_chacha = "0.3"
[features]
default = ["std"]
std = []
# The legacy-api feature guards types and functions that were previously
# part of the `zcash_primitives` crate. Those types were removed in the
# `zcash_primitives` 0.12 release and are now maintained here.
legacy-api = []
# The test-dependencies feature guards types and functions that are
# useful for testing incremental Merkle trees and Merkle tree frontiers.
test-dependencies = ["dep:proptest", "dep:rand", "dep:rand_core"]
test-dependencies = ["dep:proptest", "dep:rand", "dep:rand_core", "std"]

View File

@ -1,17 +1,18 @@
use std::mem::size_of;
use alloc::vec::Vec;
use core::mem::size_of;
use crate::{Address, Hashable, Level, MerklePath, Position, Source};
#[cfg(feature = "legacy-api")]
use {std::collections::VecDeque, std::iter::repeat};
use {alloc::boxed::Box, alloc::collections::VecDeque, core::iter::repeat};
#[cfg(any(test, feature = "test-dependencies"))]
use {
core::num::{NonZeroU64, NonZeroU8},
rand::{
distributions::{Distribution, Standard},
Rng, RngCore,
},
std::num::{NonZeroU64, NonZeroU8},
};
/// Validation errors that can occur during reconstruction of a Merkle frontier from
@ -195,7 +196,7 @@ where
NonEmptyFrontier::from_parts(
position,
rng.gen(),
std::iter::repeat_with(|| rng.gen())
core::iter::repeat_with(|| rng.gen())
.take(position.past_ommer_count().into())
.collect(),
)
@ -209,7 +210,7 @@ where
) -> (Vec<H>, Self) {
let prior_subtree_count: u64 = u64::from(tree_size) >> u8::from(subtree_depth);
if prior_subtree_count > 0 {
let prior_roots: Vec<H> = std::iter::repeat_with(|| rng.gen())
let prior_roots: Vec<H> = core::iter::repeat_with(|| rng.gen())
.take(prior_subtree_count as usize)
.collect();
@ -673,12 +674,13 @@ impl<H: Hashable + Clone, const DEPTH: u8> CommitmentTree<H, DEPTH> {
}
}
#[cfg(any(test, feature = "test-dependencies"))]
#[cfg(any(all(test, feature = "std"), feature = "test-dependencies"))]
pub mod testing {
use core::fmt::Debug;
use proptest::collection::vec;
use proptest::prelude::*;
use rand::{distributions::Standard, prelude::Distribution};
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
@ -762,9 +764,9 @@ pub mod testing {
}
}
#[cfg(test)]
#[cfg(all(test, feature = "std"))]
mod tests {
use alloc::string::{String, ToString};
use rand::SeedableRng;
use rand_chacha::ChaChaRng;

View File

@ -44,13 +44,21 @@
//! context `ommers` refers to the node's ommer, plus each ancestor's ommer.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]
#[cfg(feature = "std")]
extern crate std;
#[macro_use]
extern crate alloc;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::convert::{TryFrom, TryInto};
use core::fmt;
use core::num::TryFromIntError;
use core::ops::{Add, AddAssign, Range, Sub};
use either::Either;
use std::cmp::Ordering;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::num::TryFromIntError;
use std::ops::{Add, AddAssign, Range, Sub};
pub mod frontier;
@ -445,7 +453,7 @@ impl Address {
let level_delta = (u64::BITS - index_delta.leading_zeros()) as u8;
Address {
level: higher.level + level_delta,
index: std::cmp::max(higher.index, lower_ancestor_idx) >> level_delta,
index: core::cmp::max(higher.index, lower_ancestor_idx) >> level_delta,
}
}
@ -672,12 +680,14 @@ pub trait Hashable: fmt::Debug {
#[cfg(test)]
pub(crate) mod tests {
use crate::MerklePath;
use super::{Address, Level, Position, Source};
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::ops::Range;
use either::Either;
use super::{Address, Level, Position, Source};
use crate::MerklePath;
#[test]
fn position_is_complete_subtree() {
assert!(Position(0).is_complete_subtree(Level(0)));

View File

@ -1,4 +1,5 @@
use crate::{Hashable, Level};
use alloc::string::{String, ToString};
/// A possibly-empty incremental Merkle frontier.
pub trait Frontier<H> {

View File

@ -1,5 +1,6 @@
use std::convert::TryInto;
use std::iter::repeat;
use alloc::vec::Vec;
use core::convert::TryInto;
use core::iter::repeat;
use crate::{
frontier::{CommitmentTree, PathFiller},
@ -241,7 +242,10 @@ impl<H: Hashable + Clone, const DEPTH: u8> IncrementalWitness<H, DEPTH> {
#[cfg(test)]
mod tests {
use alloc::string::{String, ToString};
use crate::{frontier::CommitmentTree, witness::IncrementalWitness, Position};
#[test]
fn witness_tip_position() {
let mut base_tree = CommitmentTree::<String, 6>::empty();