diff --git a/Cargo.lock b/Cargo.lock index 0b49fd51b..dc02df377 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -430,6 +430,15 @@ dependencies = [ "libc", ] +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr", +] + [[package]] name = "cpp_demangle" version = "0.4.3" @@ -1113,9 +1122,9 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45063fbc4b0a37837f6bfe0445f269d13d730ad0aa3b5a7f74aa7bf27a0f4df" +checksum = "216c71634ac6f6ed13c2102d64354c0a04dcbdc30e31692c5972d3974d8b6d97" dependencies = [ "either", "proptest", @@ -1306,12 +1315,9 @@ dependencies = [ [[package]] name = "memuse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" -dependencies = [ - "nonempty", -] +checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" [[package]] name = "miniz_oxide" @@ -1345,9 +1351,8 @@ dependencies = [ [[package]] name = "nonempty" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" +version = "0.10.0" +source = "git+https://github.com/nuttycom/nonempty.git?rev=090815ca02ff969d23c6331f9f5b1e4c7720160a#090815ca02ff969d23c6331f9f5b1e4c7720160a" [[package]] name = "num-bigint" @@ -1446,6 +1451,7 @@ dependencies = [ "bitvec", "blake2b_simd", "bridgetree", + "core2", "criterion", "ff", "fpe", diff --git a/Cargo.toml b/Cargo.toml index 04a9508d2..45865616b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,27 +24,27 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] [dependencies] aes = "0.8" -bitvec = "1" -blake2b_simd = "1" -ff = "0.13" -fpe = "0.6" -group = { version = "0.13", features = ["wnaf-memuse"] } -hex = "0.4" +bitvec = { version = "1", default-features = false } +blake2b_simd = { version = "1", default-features = false } +ff = { version = "0.13", default-features = false } +fpe = { version = "0.6", default-features = false, features = ["alloc"] } +group = "0.13" +hex = { version = "0.4", default-features = false, features = ["alloc"] } lazy_static = "1" -memuse = { version = "0.2.1", features = ["nonempty"] } +memuse = { version = "0.2.2", default-features = false } pasta_curves = "0.5" proptest = { version = "1.0.0", optional = true } -rand = "0.8" -reddsa = "0.5" -nonempty = "0.7" +rand = { version = "0.8", default-features = false } +reddsa = { version = "0.5", default-features = false } +nonempty = { version = "0.10", default-features = false } poseidon = { package = "halo2_poseidon", version = "0.1" } -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["derive"] } sinsemilla = "0.1" -subtle = "2.3" +subtle = { version = "2.3", default-features = false } zcash_note_encryption = "0.4" -incrementalmerkletree = "0.7" +incrementalmerkletree = { version = "0.7", default-features = false } zcash_spec = "0.1" -zip32 = "0.1" +zip32 = { version = "0.1", default-features = false } visibility = "0.1.1" # Circuit @@ -55,7 +55,10 @@ halo2_proofs = { version = "0.3", optional = true, default-features = false, fea getset = "0.1" # Logging -tracing = "0.1" +tracing = { version = "0.1", default-features = false } + +# No-std support +core2 = { version = "0.3", default-features = false, features = ["alloc"] } # Developer tooling dependencies image = { version = "0.24", optional = true } @@ -78,8 +81,9 @@ pprof = { version = "0.11", features = ["criterion", "flamegraph"] } bench = false [features] -default = ["circuit", "multicore"] -circuit = ["dep:halo2_gadgets", "dep:halo2_proofs"] +default = ["circuit", "multicore", "std"] +std = ["core2/std", "group/wnaf-memuse", "reddsa/std"] +circuit = ["dep:halo2_gadgets", "dep:halo2_proofs", "std"] unstable-frost = [] multicore = ["halo2_proofs?/multicore"] dev-graph = ["halo2_proofs?/dev-graph", "image", "plotters"] @@ -102,3 +106,6 @@ debug = true [profile.bench] debug = true + +[patch.crates-io] +nonempty = { git = "https://github.com/nuttycom/nonempty.git", rev = "090815ca02ff969d23c6331f9f5b1e4c7720160a" } diff --git a/src/builder.rs b/src/builder.rs index 622230cb1..f15269235 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,9 +1,9 @@ //! Logic for building Orchard components of transactions. +use alloc::collections::BTreeMap; +use alloc::vec::Vec; use core::fmt; use core::iter; -use std::collections::BTreeMap; -use std::fmt::Display; use ff::Field; use pasta_curves::pallas; @@ -141,7 +141,7 @@ pub enum BuildError { BundleTypeNotSatisfiable, } -impl Display for BuildError { +impl fmt::Display for BuildError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use BuildError::*; match self { @@ -163,6 +163,7 @@ impl Display for BuildError { } } +#[cfg(feature = "std")] impl std::error::Error for BuildError {} #[cfg(feature = "circuit")] @@ -189,7 +190,7 @@ pub enum SpendError { FvkMismatch, } -impl Display for SpendError { +impl fmt::Display for SpendError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use SpendError::*; f.write_str(match self { @@ -200,18 +201,20 @@ impl Display for SpendError { } } +#[cfg(feature = "std")] impl std::error::Error for SpendError {} /// The only error that can occur here is if outputs are disabled for this builder. #[derive(Debug, PartialEq, Eq)] pub struct OutputError; -impl Display for OutputError { +impl fmt::Display for OutputError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Outputs are not enabled for this builder") } } +#[cfg(feature = "std")] impl std::error::Error for OutputError {} /// Information about a specific note to be spent in an [`Action`]. @@ -1137,7 +1140,9 @@ impl OutputView for OutputInfo { #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { + use alloc::vec::Vec; use core::fmt::Debug; + use incrementalmerkletree::{frontier::Frontier, Hashable}; use rand::{rngs::StdRng, CryptoRng, SeedableRng}; diff --git a/src/bundle.rs b/src/bundle.rs index 36bc14fa9..4e0c20640 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -1,5 +1,7 @@ //! Structs related to bundles of Orchard actions. +use alloc::vec::Vec; + pub mod commitments; #[cfg(feature = "circuit")] @@ -10,10 +12,12 @@ pub use batch::BatchValidator; use core::fmt; use blake2b_simd::Hash as Blake2bHash; -use memuse::DynamicUsage; use nonempty::NonEmpty; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; +#[cfg(feature = "std")] +use memuse::DynamicUsage; + use crate::{ action::Action, address::Address, @@ -472,16 +476,17 @@ impl Bundle { } } +#[cfg(feature = "std")] impl DynamicUsage for Bundle { fn dynamic_usage(&self) -> usize { - self.actions.dynamic_usage() + self.actions.tail.dynamic_usage() + self.value_balance.dynamic_usage() + self.authorization.proof.dynamic_usage() } fn dynamic_usage_bounds(&self) -> (usize, Option) { let bounds = ( - self.actions.dynamic_usage_bounds(), + self.actions.tail.dynamic_usage_bounds(), self.value_balance.dynamic_usage_bounds(), self.authorization.proof.dynamic_usage_bounds(), ); @@ -519,6 +524,8 @@ pub struct BundleAuthorizingCommitment(pub Blake2bHash); #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { + use alloc::vec::Vec; + use group::ff::FromUniformBytes; use nonempty::NonEmpty; use pasta_curves::pallas; diff --git a/src/bundle/batch.rs b/src/bundle/batch.rs index 6626b9162..2786bdd69 100644 --- a/src/bundle/batch.rs +++ b/src/bundle/batch.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use halo2_proofs::plonk; use pasta_curves::vesta; use rand::{CryptoRng, RngCore}; diff --git a/src/circuit.rs b/src/circuit.rs index 67715d639..bdfead6f6 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,5 +1,7 @@ //! The Orchard Action circuit implementation. +use alloc::vec::Vec; + use group::{Curve, GroupEncoding}; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, @@ -919,6 +921,7 @@ impl Proof { #[cfg(test)] mod tests { + use alloc::vec::Vec; use core::iter; use ff::Field; diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index 23d110c26..0e3a73906 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -1,4 +1,8 @@ //! Orchard fixed bases. + +#[cfg(feature = "circuit")] +use alloc::vec::Vec; + use super::{L_ORCHARD_SCALAR, L_VALUE}; #[cfg(feature = "circuit")] diff --git a/src/keys.rs b/src/keys.rs index f66928eeb..ab96e9f84 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,6 +1,7 @@ //! Key structures for Orchard. -use std::io::{self, Read, Write}; +use alloc::vec::Vec; +use core2::io::{self, Read, Write}; use ::zip32::{AccountId, ChildIndex}; use aes::Aes256; @@ -405,7 +406,7 @@ impl FullViewingKey { Self::from_bytes(&data).ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, - "Unable to deserialize a valid Orchard FullViewingKey from bytes".to_owned(), + "Unable to deserialize a valid Orchard FullViewingKey from bytes", ) }) } @@ -681,6 +682,7 @@ impl IncomingViewingKey { #[derive(Clone, Debug)] pub struct PreparedIncomingViewingKey(PreparedNonZeroScalar); +#[cfg(feature = "std")] impl memuse::DynamicUsage for PreparedIncomingViewingKey { fn dynamic_usage(&self) -> usize { self.0.dynamic_usage() diff --git a/src/lib.rs b/src/lib.rs index 2ac5dcecb..3a52af5c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ //! implicitly mean it is an Orchard payment address (as opposed to e.g. a Sapling payment //! address, which is also shielded). +#![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] // Temporary until we have more of the crate implemented. #![allow(dead_code)] @@ -16,6 +17,14 @@ #![deny(missing_docs)] #![deny(unsafe_code)] +#[macro_use] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +use alloc::vec::Vec; + mod action; mod address; pub mod builder; diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 56d5599cf..1e13c3aa5 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -1,5 +1,6 @@ //! In-band secret distribution for Orchard bundles. +use alloc::vec::Vec; use core::fmt; use blake2b_simd::{Hash, Params}; diff --git a/src/pczt.rs b/src/pczt.rs index cebc3eab5..38cc0a757 100644 --- a/src/pczt.rs +++ b/src/pczt.rs @@ -1,7 +1,9 @@ //! PCZT support for Orchard. -use std::collections::BTreeMap; -use std::fmt; +use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::vec::Vec; +use core::fmt; use getset::Getters; use pasta_curves::pallas; diff --git a/src/pczt/io_finalizer.rs b/src/pczt/io_finalizer.rs index b227df3be..6f9a7ec9c 100644 --- a/src/pczt/io_finalizer.rs +++ b/src/pczt/io_finalizer.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use rand::{CryptoRng, RngCore}; use crate::{ diff --git a/src/pczt/parse.rs b/src/pczt/parse.rs index eb0c66861..f36e09de6 100644 --- a/src/pczt/parse.rs +++ b/src/pczt/parse.rs @@ -1,4 +1,6 @@ -use std::collections::BTreeMap; +use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::vec::Vec; use ff::PrimeField; use incrementalmerkletree::Hashable; diff --git a/src/pczt/prover.rs b/src/pczt/prover.rs index 57a055a42..73ce0c863 100644 --- a/src/pczt/prover.rs +++ b/src/pczt/prover.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use halo2_proofs::plonk; use rand::{CryptoRng, RngCore}; diff --git a/src/pczt/updater.rs b/src/pczt/updater.rs index 5c2e00713..c7691f777 100644 --- a/src/pczt/updater.rs +++ b/src/pczt/updater.rs @@ -1,3 +1,6 @@ +use alloc::string::String; +use alloc::vec::Vec; + use super::{Action, Bundle, Zip32Derivation}; impl Bundle { diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index d19a05048..cbef23436 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -5,6 +5,7 @@ use core::cmp::{Ord, Ordering, PartialOrd}; use pasta_curves::pallas; use rand::{CryptoRng, RngCore}; +#[cfg(feature = "std")] pub use reddsa::batch; #[cfg(test)] @@ -126,6 +127,7 @@ impl VerificationKey { } /// Creates a batch validation item from a `SpendAuth` signature. + #[cfg(feature = "std")] pub fn create_batch_item>( &self, sig: Signature, @@ -135,6 +137,7 @@ impl VerificationKey { } } +#[cfg(feature = "std")] impl VerificationKey { /// Creates a batch validation item from a `Binding` signature. pub fn create_batch_item>( diff --git a/src/spec.rs b/src/spec.rs index d1365f1c5..f1c3e4459 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -7,6 +7,7 @@ use ff::{Field, FromUniformBytes, PrimeField, PrimeFieldBits}; use group::{Curve, Group, GroupEncoding, WnafBase, WnafScalar}; #[cfg(feature = "circuit")] use halo2_gadgets::{poseidon::primitives as poseidon, sinsemilla::primitives as sinsemilla}; +#[cfg(feature = "std")] use memuse::DynamicUsage; use pasta_curves::{ arithmetic::{CurveAffine, CurveExt}, @@ -156,6 +157,7 @@ impl PreparedNonIdentityBase { #[derive(Clone, Debug)] pub(crate) struct PreparedNonZeroScalar(WnafScalar); +#[cfg(feature = "std")] impl DynamicUsage for PreparedNonZeroScalar { fn dynamic_usage(&self) -> usize { self.0.dynamic_usage() diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 39d7dc00d..5551a268d 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -1,5 +1,7 @@ //! Test vectors for Orchard key components. +use alloc::vec::Vec; + pub(crate) struct TestVector { pub(crate) sk: [u8; 32], pub(crate) ask: [u8; 32], diff --git a/src/test_vectors/merkle_path.rs b/src/test_vectors/merkle_path.rs index ff0270d2d..dc3a26fd2 100644 --- a/src/test_vectors/merkle_path.rs +++ b/src/test_vectors/merkle_path.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + pub(crate) struct TestVector { pub(crate) leaves: [[u8; 32]; 16], pub(crate) paths: [[[u8; 32]; 4]; 16], diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index e27ec24d8..fc7c5ad5f 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -1,5 +1,7 @@ //! Test vectors for Orchard key components. +use alloc::vec::Vec; + pub(crate) struct TestVector { pub(crate) incoming_viewing_key: [u8; 64], pub(crate) ovk: [u8; 32], diff --git a/src/tree.rs b/src/tree.rs index 98824ac83..57fdae308 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,5 +1,6 @@ //! Types related to Orchard note commitment trees and anchors. +use alloc::vec::Vec; use core::iter; use crate::{ diff --git a/src/value.rs b/src/value.rs index 058feb103..dac380ece 100644 --- a/src/value.rs +++ b/src/value.rs @@ -81,6 +81,7 @@ impl fmt::Display for OverflowError { } } +#[cfg(feature = "std")] impl std::error::Error for OverflowError {} /// The non-negative value of an individual Orchard note.