diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7df0bebae0..4d2699f6c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -258,7 +258,6 @@ jobs: matrix: target: - wasm32-wasi - steps: - uses: actions/checkout@v4 with: @@ -318,6 +317,9 @@ jobs: - name: Add pczt as a dependency of the synthetic crate working-directory: ./ci-build run: cargo add --no-default-features --path ../crates/pczt + - name: Add zcash_primitives as a dependency of the synthetic crate + working-directory: ./ci-build + run: cargo add --no-default-features --path ../crates/zcash_primitives - name: Add lazy_static with the spin_no_std feature working-directory: ./ci-build run: cargo add lazy_static --features "spin_no_std" diff --git a/Cargo.lock b/Cargo.lock index 17b61d5463..11d4c20437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -825,9 +825,9 @@ dependencies = [ [[package]] name = "cpp_demangle" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if", ] @@ -1501,7 +1501,7 @@ name = "equihash" version = "0.2.0" dependencies = [ "blake2b_simd", - "byteorder", + "core2", ] [[package]] @@ -2277,9 +2277,9 @@ dependencies = [ [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", "indexmap 2.6.0", @@ -2837,7 +2837,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.10.1" -source = "git+https://github.com/zcash/orchard.git?rev=cd3e0901ccac2c630dd7fd03eb496d5030c1bbfe#cd3e0901ccac2c630dd7fd03eb496d5030c1bbfe" +source = "git+https://github.com/zcash/orchard.git?rev=c684e9185a0449efb00428f807d3bf286b5dae03#c684e9185a0449efb00428f807d3bf286b5dae03" dependencies = [ "aes", "bitvec", @@ -3533,12 +3533,10 @@ dependencies = [ [[package]] name = "redjubjub" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a60db2c3bc9c6fd1e8631fee75abc008841d27144be744951d6b9b75f9b569c" +source = "git+https://github.com/ZcashFoundation/redjubjub?rev=eae848c5c14d9c795d000dd9f4c4762d1aee7ee1#eae848c5c14d9c795d000dd9f4c4762d1aee7ee1" dependencies = [ "rand_core", "reddsa", - "serde", "thiserror", "zeroize", ] @@ -3625,9 +3623,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -3879,8 +3877,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c2acdbbab83d554fc2dceea5f7d6d3da71e57adb18a6c80b8901bd0eee54b0" +source = "git+https://github.com/zcash/sapling-crypto.git?rev=e607c52d13bb7ade66293f9ab8d07e311f4ad868#e607c52d13bb7ade66293f9ab8d07e311f4ad868" dependencies = [ "aes", "bellman", @@ -3888,7 +3885,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "bls12_381", - "byteorder", + "core2", "document-features", "ff", "fpe", @@ -4399,9 +4396,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.9.2" +version = "12.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71297dc3e250f7dbdf8adb99e235da783d690f5819fdeb4cce39d9cfb0aca9f1" +checksum = "13a4dfe4bbeef59c1f32fc7524ae7c95b9e1de5e79a43ce1604e181081d71b0c" dependencies = [ "debugid", "memmap2", @@ -4411,9 +4408,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.9.2" +version = "12.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424fa2c9bf2c862891b9cfd354a752751a6730fd838a4691e7f6c2c7957b9daf" +checksum = "98cf6a95abff97de4d7ff3473f33cacd38f1ddccad5c1feab435d6760300e3b6" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -6392,6 +6389,8 @@ dependencies = [ "zcash_address", "zcash_primitives", "zcash_proofs", + "zcash_protocol", + "zcash_transparent", ] [[package]] @@ -6453,13 +6452,12 @@ dependencies = [ name = "zcash_primitives" version = "0.21.0" dependencies = [ - "aes", "assert_matches", "bip32", "blake2b_simd", "bs58", - "byteorder", "chacha20poly1305", + "core2", "criterion", "document-features", "equihash", @@ -6533,9 +6531,9 @@ dependencies = [ [[package]] name = "zcash_spec" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b" +checksum = "9cede95491c2191d3e278cab76e097a44b17fde8d6ca0d4e3a22cf4807b2d857" dependencies = [ "blake2b_simd", ] @@ -6605,13 +6603,14 @@ dependencies = [ [[package]] name = "zip32" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" +checksum = "2e9943793abf9060b68e1889012dafbd5523ab5b125c0fcc24802d69182f2ac9" dependencies = [ "blake2b_simd", "memuse", "subtle", + "zcash_spec", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 504f282211..caef180d25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ categories = ["cryptography::cryptocurrencies"] # part of a public API, and which can be updated without a SemVer bump. [workspace.dependencies] # Intra-workspace dependencies -equihash = { version = "0.2", path = "components/equihash" } +equihash = { version = "0.2", path = "components/equihash", default-features = false } zcash_address = { version = "0.6", path = "components/zcash_address", default-features = false } zcash_client_backend = { version = "0.16", path = "zcash_client_backend" } zcash_encoding = { version = "0.2.1", path = "components/zcash_encoding", default-features = false } @@ -61,7 +61,7 @@ bitvec = { version = "1", default-features = false, features = ["alloc"] } blake2s_simd = { version = "1", default-features = false } bls12_381 = "0.8" jubjub = "0.10" -redjubjub = "0.7" +redjubjub = { version = "0.7", default-features = false } sapling = { package = "sapling-crypto", version = "0.4", default-features = false } # - Orchard @@ -195,4 +195,6 @@ debug = true unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("zfuture"))'] } [patch.crates-io] -orchard = { git = "https://github.com/zcash/orchard.git", rev = "cd3e0901ccac2c630dd7fd03eb496d5030c1bbfe" } +orchard = { git = "https://github.com/zcash/orchard.git", rev = "c684e9185a0449efb00428f807d3bf286b5dae03" } +redjubjub = { git = "https://github.com/ZcashFoundation/redjubjub", rev = "eae848c5c14d9c795d000dd9f4c4762d1aee7ee1" } +sapling = { package = "sapling-crypto", git = "https://github.com/zcash/sapling-crypto.git", rev = "e607c52d13bb7ade66293f9ab8d07e311f4ad868" } diff --git a/components/equihash/Cargo.toml b/components/equihash/Cargo.toml index 33eafb4a8a..b7de2df128 100644 --- a/components/equihash/Cargo.toml +++ b/components/equihash/Cargo.toml @@ -10,11 +10,15 @@ edition = "2021" rust-version = "1.56.1" [dependencies] -blake2b_simd = "1" -byteorder = "1" +core2.workspace = true +blake2b_simd.workspace = true [lib] bench = false [lints] workspace = true + +[features] +default = ["std"] +std = [] diff --git a/components/equihash/src/lib.rs b/components/equihash/src/lib.rs index cb6131ca3b..c65fc2d7d1 100644 --- a/components/equihash/src/lib.rs +++ b/components/equihash/src/lib.rs @@ -19,6 +19,13 @@ // Catch documentation errors caused by code changes. #![deny(rustdoc::broken_intra_doc_links)] +#![no_std] + +#[cfg(feature = "std")] +extern crate std; + +#[macro_use] +extern crate alloc; mod minimal; mod params; diff --git a/components/equihash/src/minimal.rs b/components/equihash/src/minimal.rs index 81da63e657..4edc717d6f 100644 --- a/components/equihash/src/minimal.rs +++ b/components/equihash/src/minimal.rs @@ -1,7 +1,6 @@ -use std::io::Cursor; -use std::mem::size_of; - -use byteorder::{BigEndian, ReadBytesExt}; +use alloc::vec::Vec; +use core::mem::size_of; +use core2::io::{Cursor, Read}; use crate::params::Params; @@ -50,6 +49,12 @@ pub(crate) fn expand_array(vin: &[u8], bit_len: usize, byte_pad: usize) -> Vec>) -> core2::io::Result { + let mut n = [0; 4]; + csr.read_exact(&mut n)?; + Ok(u32::from_be_bytes(n)) +} + /// Returns `None` if the parameters are invalid for this minimal encoding. pub(crate) fn indices_from_minimal(p: Params, minimal: &[u8]) -> Option> { let c_bit_len = p.collision_bit_length(); @@ -67,7 +72,7 @@ pub(crate) fn indices_from_minimal(p: Params, minimal: &[u8]) -> Option // Big-endian so that lexicographic array comparison is equivalent to integer // comparison - while let Ok(i) = csr.read_u32::() { + while let Ok(i) = read_u32_be(&mut csr) { ret.push(i); } diff --git a/components/equihash/src/verify.rs b/components/equihash/src/verify.rs index 53071ddc01..e0eafe4f11 100644 --- a/components/equihash/src/verify.rs +++ b/components/equihash/src/verify.rs @@ -2,9 +2,10 @@ //! //! [Equihash]: https://zips.z.cash/protocol/protocol.pdf#equihash +use alloc::vec::Vec; use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams, State as Blake2bState}; -use byteorder::{LittleEndian, WriteBytesExt}; -use std::fmt; +use core::fmt; +use core2::io::Write; use crate::{ minimal::{expand_array, indices_from_minimal}, @@ -91,6 +92,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl std::error::Error for Error {} #[derive(Debug, PartialEq)] @@ -116,8 +118,8 @@ impl fmt::Display for Kind { fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState { let mut personalization: Vec = Vec::from("ZcashPoW"); - personalization.write_u32::(n).unwrap(); - personalization.write_u32::(k).unwrap(); + personalization.write_all(&n.to_le_bytes()).unwrap(); + personalization.write_all(&k.to_le_bytes()).unwrap(); Blake2bParams::new() .hash_length(digest_len as usize) @@ -127,7 +129,7 @@ fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState { fn generate_hash(base_state: &Blake2bState, i: u32) -> Blake2bHash { let mut lei = [0u8; 4]; - (&mut lei[..]).write_u32::(i).unwrap(); + (&mut lei[..]).write_all(&i.to_le_bytes()).unwrap(); let mut state = base_state.clone(); state.update(&lei); diff --git a/components/zcash_encoding/Cargo.toml b/components/zcash_encoding/Cargo.toml index 0a3b8b0abb..f2847204f7 100644 --- a/components/zcash_encoding/Cargo.toml +++ b/components/zcash_encoding/Cargo.toml @@ -17,11 +17,11 @@ keywords = ["zcash"] [dependencies] core2.workspace = true -nonempty = { workspace = true, optional = true } +nonempty.workspace = true [features] default = ["std"] -std = ["core2/std", "dep:nonempty"] +std = ["core2/std"] [lib] bench = false diff --git a/components/zcash_encoding/src/lib.rs b/components/zcash_encoding/src/lib.rs index fcc8d3018a..4e611e25a6 100644 --- a/components/zcash_encoding/src/lib.rs +++ b/components/zcash_encoding/src/lib.rs @@ -17,7 +17,6 @@ use alloc::vec::Vec; use core::iter::FromIterator; use core2::io::{self, Read, Write}; -#[cfg(feature = "std")] use nonempty::NonEmpty; /// The maximum allowed value representable as a `[CompactSize]` @@ -171,7 +170,6 @@ impl Vector { /// Writes a NonEmpty container of values to the stream using the same encoding as /// `[Vector::write]` - #[cfg(feature = "std")] pub fn write_nonempty( mut writer: W, vec: &NonEmpty, diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index c0066a8dd9..6e035db535 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -78,6 +78,12 @@ who = "Jack Grigg " criteria = "safe-to-run" delta = "4.5.0 -> 4.4.18" +[[audits.cpp_demangle]] +who = "Kris Nuttycombe " +criteria = "safe-to-run" +delta = "0.4.3 -> 0.4.4" +notes = "No added unsafe code; adds support for additional c++23 types." + [[audits.darling]] who = "Jack Grigg " criteria = "safe-to-deploy" @@ -219,6 +225,12 @@ who = "Daira-Emma Hopwood " criteria = "safe-to-run" delta = "0.11.17 -> 0.11.19" +[[audits.inferno]] +who = "Kris Nuttycombe " +criteria = "safe-to-run" +delta = "0.11.19 -> 0.11.21" +notes = "No added unsafe code." + [[audits.is-terminal]] who = "Daira-Emma Hopwood " criteria = "safe-to-run" @@ -412,6 +424,15 @@ who = "Jack Grigg " criteria = "safe-to-deploy" delta = "0.8.3 -> 0.8.4" +[[audits.rgb]] +who = "Kris Nuttycombe " +criteria = "safe-to-run" +delta = "0.8.37 -> 0.8.50" +notes = """ +Some clearly-marked unsafe code is moved; adds safer alternative to the +`as-bytes` feature (which is still enabled by default) +""" + [[audits.rustc-demangle]] who = "Daira-Emma Hopwood " criteria = "safe-to-deploy" @@ -518,6 +539,12 @@ criteria = "safe-to-deploy" delta = "0.5.6 -> 0.5.7" notes = "The new uses of unsafe to access getsockopt/setsockopt look reasonable." +[[audits.symbolic-common]] +who = "Kris Nuttycombe " +criteria = "safe-to-run" +delta = "12.9.2 -> 12.13.3" +notes = "Just minor code & Cargo.toml cleanups." + [[audits.syn]] who = "Daira-Emma Hopwood " criteria = "safe-to-deploy" diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 744e41be34..0bdc6d76e6 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -1246,7 +1246,7 @@ version = "12.9.2" criteria = "safe-to-run" [[exemptions.symbolic-demangle]] -version = "12.9.2" +version = "12.13.3" criteria = "safe-to-run" [[exemptions.syn]] diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index e826885b67..b770d86e17 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -84,13 +84,6 @@ user-id = 169181 user-login = "nuttycom" user-name = "Kris Nuttycombe" -[[publisher.sapling-crypto]] -version = "0.4.0" -when = "2024-12-17" -user-id = 169181 -user-login = "nuttycom" -user-name = "Kris Nuttycombe" - [[publisher.schemerz]] version = "0.2.0" when = "2024-10-16" @@ -344,8 +337,8 @@ user-login = "nuttycom" user-name = "Kris Nuttycombe" [[publisher.zcash_spec]] -version = "0.1.0" -when = "2023-12-07" +version = "0.1.2" +when = "2024-10-22" user-id = 6289 user-login = "str4d" user-name = "Jack Grigg" @@ -358,8 +351,8 @@ user-login = "nuttycom" user-name = "Kris Nuttycombe" [[publisher.zip32]] -version = "0.1.1" -when = "2024-03-14" +version = "0.1.3" +when = "2024-12-13" user-id = 6289 user-login = "str4d" user-name = "Jack Grigg" @@ -3104,24 +3097,6 @@ criteria = "safe-to-deploy" version = "0.3.0" aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" -[[audits.zcash.audits.redjubjub]] -who = "Daira Emma Hopwood " -criteria = "safe-to-deploy" -version = "0.7.0" -notes = """ -This crate is a thin wrapper around the `reddsa` crate, which I did not review. I also -did not review tests or verify test vectors. - -The comment on `batch::Verifier::verify` has an error in the batch verification equation, -filed as https://github.com/ZcashFoundation/redjubjub/issues/163 . It does not affect the -implementation which just delegates to `reddsa`. `reddsa` has the same comment bug filed as -https://github.com/ZcashFoundation/reddsa/issues/52 , but its batch verification implementation -is correct. (I checked the latter against https://zips.z.cash/protocol/protocol.pdf#reddsabatchvalidate -which has had previous cryptographic review by NCC group; see finding NCC-Zcash2018-009 in -https://research.nccgroup.com/wp-content/uploads/2020/07/NCC_Group_Zcash2018_Public_Report_2019-01-30_v1.3.pdf ). -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - [[audits.zcash.audits.redox_users]] who = "Jack Grigg " criteria = "safe-to-deploy" diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index 6e3f1ed4ae..25680760c4 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -29,7 +29,7 @@ zcash_address.workspace = true zcash_encoding.workspace = true zcash_keys = { workspace = true, features = ["sapling"] } zcash_note_encryption.workspace = true -zcash_primitives.workspace = true +zcash_primitives = { workspace = true, features = ["std", "circuits"] } zcash_protocol.workspace = true zip32.workspace = true zip321.workspace = true diff --git a/zcash_client_backend/src/fees/fixed.rs b/zcash_client_backend/src/fees/fixed.rs index eaa6207787..cf8d489d52 100644 --- a/zcash_client_backend/src/fees/fixed.rs +++ b/zcash_client_backend/src/fees/fixed.rs @@ -1,6 +1,6 @@ //! Change strategies designed for use with a fixed fee. -use std::marker::PhantomData; +use core::marker::PhantomData; use zcash_primitives::transaction::fees::{fixed::FeeRule as FixedFeeRule, transparent}; use zcash_protocol::{ diff --git a/zcash_client_backend/src/fees/zip317.rs b/zcash_client_backend/src/fees/zip317.rs index 3a77f6b1f7..e833dada05 100644 --- a/zcash_client_backend/src/fees/zip317.rs +++ b/zcash_client_backend/src/fees/zip317.rs @@ -4,7 +4,7 @@ //! to ensure that inputs added to a transaction do not cause fees to rise by //! an amount greater than their value. -use std::marker::PhantomData; +use core::marker::PhantomData; use zcash_primitives::transaction::fees::{transparent, zip317 as prim_zip317, FeeRule}; use zcash_protocol::{ @@ -264,7 +264,7 @@ where #[cfg(test)] mod tests { - use std::{convert::Infallible, num::NonZeroUsize}; + use core::{convert::Infallible, num::NonZeroUsize}; use ::transparent::{address::Script, bundle::TxOut}; use zcash_primitives::transaction::fees::zip317::FeeRule as Zip317FeeRule; diff --git a/zcash_extensions/Cargo.toml b/zcash_extensions/Cargo.toml index 6cf04207fc..b61e136497 100644 --- a/zcash_extensions/Cargo.toml +++ b/zcash_extensions/Cargo.toml @@ -16,7 +16,8 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] blake2b_simd.workspace = true -zcash_primitives.workspace = true +zcash_primitives = { workspace = true, features = ["non-standard-fees"] } +zcash_protocol.workspace = true [dev-dependencies] ff.workspace = true @@ -24,8 +25,9 @@ jubjub.workspace = true rand_core.workspace = true sapling.workspace = true orchard.workspace = true +transparent.workspace = true zcash_address.workspace = true -zcash_proofs.workspace = true +zcash_proofs = { workspace = true, features = ["local-prover", "bundled-prover"] } [features] transparent-inputs = [] diff --git a/zcash_extensions/src/transparent/demo.rs b/zcash_extensions/src/transparent/demo.rs index 84054ccc8f..0c3378026c 100644 --- a/zcash_extensions/src/transparent/demo.rs +++ b/zcash_extensions/src/transparent/demo.rs @@ -25,11 +25,9 @@ use blake2b_simd::Params; use zcash_primitives::{ extensions::transparent::{Extension, ExtensionTxBuilder, FromPayload, ToPayload}, - transaction::components::{ - amount::Amount, - tze::{OutPoint, TzeOut}, - }, + transaction::components::tze::{OutPoint, TzeOut}, }; +use zcash_protocol::value::Zatoshis; /// Types and constants used for Mode 0 (open a channel) mod open { @@ -377,7 +375,7 @@ impl<'a, B: ExtensionTxBuilder<'a>> DemoBuilder { /// construction. pub fn demo_open( &mut self, - value: Amount, + value: Zatoshis, hash_1: [u8; 32], ) -> Result<(), DemoBuildError> { // Call through to the generic builder. @@ -391,7 +389,7 @@ impl<'a, B: ExtensionTxBuilder<'a>> DemoBuilder { pub fn demo_transfer_to_close( &mut self, prevout: (OutPoint, TzeOut), - transfer_amount: Amount, + transfer_amount: Zatoshis, preimage_1: [u8; 32], hash_2: [u8; 32], ) -> Result<(), DemoBuildError> { @@ -483,21 +481,21 @@ mod tests { use rand_core::OsRng; use sapling::{zip32::ExtendedSpendingKey, Node, Rseed}; + use transparent::{address::TransparentAddress, builder::TransparentSigningSet}; use zcash_primitives::{ - consensus::{BlockHeight, BranchId, NetworkType, NetworkUpgrade, Parameters}, extensions::transparent::{self as tze, Extension, FromPayload, ToPayload}, - legacy::TransparentAddress, transaction::{ builder::{BuildConfig, Builder}, - components::{ - amount::{Amount, NonNegativeAmount}, - transparent::builder::TransparentSigningSet, - tze::{Authorized, Bundle, OutPoint, TzeIn, TzeOut}, - }, + components::tze::{Authorized, Bundle, OutPoint, TzeIn, TzeOut}, fees::{fixed, zip317::MINIMUM_FEE}, Transaction, TransactionData, TxVersion, }, }; + use zcash_protocol::{ + consensus::{BlockHeight, BranchId, NetworkType, NetworkUpgrade, Parameters}, + value::Zatoshis, + }; + use zcash_proofs::prover::LocalTxProver; use super::{close, hash_1, open, Context, DemoBuilder, Precondition, Program, Witness}; @@ -669,7 +667,7 @@ mod tests { // let out_a = TzeOut { - value: Amount::from_u64(1).unwrap(), + value: Zatoshis::from_u64(1).unwrap(), precondition: tze::Precondition::from(0, &Precondition::open(hash_1)), }; @@ -700,7 +698,7 @@ mod tests { witness: tze::Witness::from(0, &Witness::open(preimage_1)), }; let out_b = TzeOut { - value: Amount::from_u64(1).unwrap(), + value: Zatoshis::const_from_u64(1), precondition: tze::Precondition::from(0, &Precondition::close(hash_2)), }; @@ -818,7 +816,7 @@ mod tests { .add_sapling_spend::(dfvk.fvk().clone(), note1, witness1.path().unwrap()) .unwrap(); - let value = NonNegativeAmount::const_from_u64(100000); + let value = Zatoshis::const_from_u64(100000); let (h1, h2) = demo_hashes(&preimage_1, &preimage_2); builder_a .demo_open(value.into(), h1) diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 9efd853e64..229360eea6 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -21,7 +21,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] equihash.workspace = true zcash_address.workspace = true -zcash_encoding = { workspace = true, features = ["std"] } +zcash_encoding.workspace = true zcash_protocol.workspace = true zip32.workspace = true @@ -37,17 +37,17 @@ sha2.workspace = true # - Logging and metrics memuse.workspace = true -tracing.workspace = true +tracing = { workspace = true, default-features = false } # - Secret management subtle.workspace = true # - Shielded protocols ff.workspace = true -group = { workspace = true, features = ["wnaf-memuse"] } +group.workspace = true jubjub.workspace = true nonempty.workspace = true -orchard = { workspace = true, features = ["circuit"] } +orchard.workspace = true sapling.workspace = true zcash_spec.workspace = true @@ -72,23 +72,24 @@ secp256k1 = { workspace = true, optional = true } getset.workspace = true # - Documentation -document-features.workspace = true +document-features = { workspace = true, optional = true } # - Encodings bs58.workspace = true -byteorder.workspace = true hex.workspace = true # - Shielded protocols -redjubjub = "0.7" +redjubjub.workspace = true # - Transparent protocol ripemd.workspace = true # - ZIP 32 -aes.workspace = true fpe.workspace = true +# No-std support +core2.workspace = true + [dependencies.zcash_note_encryption] workspace = true features = ["pre-zip-212"] @@ -100,6 +101,7 @@ incrementalmerkletree = { workspace = true, features = ["legacy-api", "test-depe proptest.workspace = true assert_matches.workspace = true rand_xorshift.workspace = true +transparent = { workspace = true, features = ["test-dependencies"] } sapling = { workspace = true, features = ["test-dependencies"] } orchard = { workspace = true, features = ["test-dependencies"] } zcash_protocol = { workspace = true, features = ["test-dependencies"] } @@ -108,7 +110,11 @@ zcash_protocol = { workspace = true, features = ["test-dependencies"] } pprof = { version = "0.13", features = ["criterion", "flamegraph"] } [features] -default = ["multicore"] +default = ["multicore", "std", "circuits"] +std = ["document-features", "redjubjub/std"] + +## Enables creating proofs +circuits = ["orchard/circuit", "sapling/circuit"] ## Enables multithreading support for creating proofs. multicore = ["orchard/multicore", "sapling/multicore"] @@ -127,6 +133,7 @@ temporary-zcashd = [] ## Exposes APIs that are useful for testing, such as `proptest` strategies. test-dependencies = [ "dep:proptest", + "incrementalmerkletree/test-dependencies", "orchard/test-dependencies", "sapling/test-dependencies", "transparent/test-dependencies", diff --git a/zcash_primitives/benches/note_decryption.rs b/zcash_primitives/benches/note_decryption.rs index 9cc1424b1c..9ea3504a2e 100644 --- a/zcash_primitives/benches/note_decryption.rs +++ b/zcash_primitives/benches/note_decryption.rs @@ -1,4 +1,4 @@ -use std::iter; +use core::iter; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ff::Field; diff --git a/zcash_primitives/src/block.rs b/zcash_primitives/src/block.rs index e24dc1d2d3..9748941f00 100644 --- a/zcash_primitives/src/block.rs +++ b/zcash_primitives/src/block.rs @@ -1,11 +1,15 @@ //! Structs and methods for handling Zcash block headers. -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use alloc::string::ToString; +use alloc::vec::Vec; +use core::fmt; +use core::ops::Deref; +use core2::io::{self, Read, Write}; + +use crate::encoding::{ReadBytesExt, WriteBytesExt}; use memuse::DynamicUsage; use sha2::{Digest, Sha256}; -use std::fmt; -use std::io::{self, Read, Write}; -use std::ops::Deref; + use zcash_encoding::Vector; pub use equihash; @@ -112,7 +116,7 @@ impl BlockHeader { } pub fn read(mut reader: R) -> io::Result { - let version = reader.read_i32::()?; + let version = reader.read_i32_le()?; let mut prev_block = BlockHash([0; 32]); reader.read_exact(&mut prev_block.0)?; @@ -123,8 +127,8 @@ impl BlockHeader { let mut final_sapling_root = [0; 32]; reader.read_exact(&mut final_sapling_root)?; - let time = reader.read_u32::()?; - let bits = reader.read_u32::()?; + let time = reader.read_u32_le()?; + let bits = reader.read_u32_le()?; let mut nonce = [0; 32]; reader.read_exact(&mut nonce)?; @@ -144,12 +148,12 @@ impl BlockHeader { } pub fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_i32::(self.version)?; + writer.write_i32_le(self.version)?; writer.write_all(&self.prev_block.0)?; writer.write_all(&self.merkle_root)?; writer.write_all(&self.final_sapling_root)?; - writer.write_u32::(self.time)?; - writer.write_u32::(self.bits)?; + writer.write_u32_le(self.time)?; + writer.write_u32_le(self.bits)?; writer.write_all(&self.nonce)?; Vector::write(&mut writer, &self.solution, |w, b| w.write_u8(*b))?; @@ -160,6 +164,7 @@ impl BlockHeader { #[cfg(test)] mod tests { use super::BlockHeader; + use alloc::vec::Vec; const HEADER_MAINNET_415000: [u8; 1487] = [ 0x04, 0x00, 0x00, 0x00, 0x52, 0x74, 0xb4, 0x3b, 0x9e, 0x4a, 0xd8, 0xf4, 0x3e, 0x93, 0xf7, diff --git a/zcash_primitives/src/encoding.rs b/zcash_primitives/src/encoding.rs new file mode 100644 index 0000000000..d9221880cb --- /dev/null +++ b/zcash_primitives/src/encoding.rs @@ -0,0 +1,83 @@ +//! Utility traits for encoding and decoding using core2.io primitives. +//! +//! This module is used in lieu of the `byteorder` crate, which uses `std::io::{Read, Write}` +//! and therefore does not support `no_std` usage. +use blake2b_simd::{Hash, State}; +use core2::io::{self, Read, Write}; + +pub(crate) trait ReadBytesExt { + fn read_u8(self) -> io::Result; + fn read_u32_le(self) -> io::Result; + fn read_i32_le(self) -> io::Result; + fn read_u64_le(self) -> io::Result; +} + +impl ReadBytesExt for &mut R { + fn read_u8(self) -> io::Result { + let mut repr = [0u8; 1]; + self.read_exact(&mut repr)?; + Ok(repr[0]) + } + + fn read_u32_le(self) -> io::Result { + let mut repr = [0u8; 4]; + self.read_exact(&mut repr)?; + Ok(u32::from_le_bytes(repr)) + } + + fn read_i32_le(self) -> io::Result { + let mut repr = [0u8; 4]; + self.read_exact(&mut repr)?; + Ok(i32::from_le_bytes(repr)) + } + + fn read_u64_le(self) -> io::Result { + let mut repr = [0u8; 8]; + self.read_exact(&mut repr)?; + Ok(u64::from_le_bytes(repr)) + } +} + +pub(crate) trait WriteBytesExt { + fn write_u8(self, value: u8) -> io::Result<()>; + fn write_u32_le(self, value: u32) -> io::Result<()>; + fn write_i32_le(self, value: i32) -> io::Result<()>; + fn write_u64_le(self, value: u64) -> io::Result<()>; +} + +impl WriteBytesExt for &mut W { + fn write_u8(self, value: u8) -> io::Result<()> { + self.write_all(&[value]) + } + + fn write_i32_le(self, value: i32) -> io::Result<()> { + self.write_all(&value.to_le_bytes()) + } + + fn write_u32_le(self, value: u32) -> io::Result<()> { + self.write_all(&value.to_le_bytes()) + } + + fn write_u64_le(self, value: u64) -> io::Result<()> { + self.write_all(&value.to_le_bytes()) + } +} + +pub(crate) struct StateWrite(pub(crate) State); + +impl StateWrite { + pub(crate) fn finalize(&self) -> Hash { + self.0.finalize() + } +} + +impl Write for StateWrite { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.update(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/zcash_primitives/src/extensions/transparent.rs b/zcash_primitives/src/extensions/transparent.rs index 65ed7f78f7..513eadaf9f 100644 --- a/zcash_primitives/src/extensions/transparent.rs +++ b/zcash_primitives/src/extensions/transparent.rs @@ -1,11 +1,10 @@ //! Core traits and structs for Transparent Zcash Extensions. -use std::fmt; +use alloc::vec::Vec; +use core::fmt; -use crate::transaction::components::{ - tze::{self, TzeOut}, - Amount, -}; +use crate::transaction::components::tze::{self, TzeOut}; +use zcash_protocol::value::Zatoshis; /// A typesafe wrapper for witness payloads #[derive(Debug, Clone, PartialEq, Eq)] @@ -203,11 +202,11 @@ pub trait ExtensionTxBuilder<'a> { WBuilder: 'a + (FnOnce(&Self::BuildCtx) -> Result); /// Adds a TZE precondition to the transaction which must be satisfied by a future transaction's - /// witness in order to spend the specified `amount`. + /// witness in order to spend the specified value. fn add_tze_output( &mut self, extension_id: u32, - value: Amount, + value: Zatoshis, guarded_by: &Precondition, ) -> Result<(), Self::BuildError>; } diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 2fa7ef08ff..7aac5940ae 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -4,7 +4,7 @@ //! for working with Zcash. //! //! ## Feature flags -#![doc = document_features::document_features!()] +#![cfg_attr(feature = "std", doc = document_features::document_features!())] //! #![cfg_attr(docsrs, feature(doc_cfg))] @@ -16,8 +16,16 @@ // Present to reduce refactoring noise from changing all the imports inside this crate for // the `sapling` crate extraction. #![allow(clippy::single_component_path_imports)] +#![no_std] + +#[cfg(feature = "std")] +extern crate std; + +#[macro_use] +extern crate alloc; pub mod block; +pub(crate) mod encoding; #[cfg(zcash_unstable = "zfuture")] pub mod extensions; pub mod merkle_tree; diff --git a/zcash_primitives/src/merkle_tree.rs b/zcash_primitives/src/merkle_tree.rs index 74888c38da..bd1424ae60 100644 --- a/zcash_primitives/src/merkle_tree.rs +++ b/zcash_primitives/src/merkle_tree.rs @@ -1,13 +1,15 @@ //! Parsers and serializers for Zcash Merkle trees. -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use alloc::vec::Vec; +use core2::io::{self, Read, Write}; + +use crate::encoding::{ReadBytesExt, WriteBytesExt}; use incrementalmerkletree::{ frontier::{CommitmentTree, Frontier, NonEmptyFrontier}, witness::IncrementalWitness, Address, Hashable, Level, MerklePath, Position, }; use orchard::tree::MerkleHashOrchard; -use std::io::{self, Read, Write}; use zcash_encoding::{Optional, Vector}; /// A hashable node within a Merkle tree. @@ -62,41 +64,44 @@ impl HashSer for MerkleHashOrchard { /// is platform-dependent, we consistently represent it as u64 in serialized /// formats. pub fn write_usize_leu64(mut writer: W, value: usize) -> io::Result<()> { - // Panic if we get a usize value that can't fit into a u64. - writer.write_u64::(value.try_into().unwrap()) + writer.write_u64_le(u64::try_from(value).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidData, + "usize value was outside the representable range of a u64", + ) + })?) } /// Reads a usize value encoded as a u64 in little-endian order. Since usize /// is platform-dependent, we consistently represent it as u64 in serialized /// formats. pub fn read_leu64_usize(mut reader: R) -> io::Result { - reader.read_u64::()?.try_into().map_err(|e| { + let mut repr = [0u8; 8]; + reader.read_exact(&mut repr)?; + usize::try_from(u64::from_le_bytes(repr)).map_err(|_| { io::Error::new( io::ErrorKind::InvalidData, - format!( - "usize could not be decoded from a 64-bit value on this platform: {:?}", - e - ), + "usize could not be decoded from a 64-bit value", ) }) } pub fn write_position(mut writer: W, position: Position) -> io::Result<()> { - writer.write_u64::(position.into()) + writer.write_u64_le(u64::from(position)) } pub fn read_position(mut reader: R) -> io::Result { - reader.read_u64::().map(Position::from) + reader.read_u64_le().map(Position::from) } pub fn write_address(mut writer: W, addr: Address) -> io::Result<()> { writer.write_u8(addr.level().into())?; - writer.write_u64::(addr.index()) + writer.write_u64_le(addr.index()) } pub fn read_address(mut reader: R) -> io::Result
{ let level = reader.read_u8().map(Level::from)?; - let index = reader.read_u64::()?; + let index = reader.read_u64_le()?; Ok(Address::from_parts(level, index)) } @@ -149,10 +154,10 @@ pub fn read_nonempty_frontier_v1( left }; - NonEmptyFrontier::from_parts(position, leaf, ommers).map_err(|err| { + NonEmptyFrontier::from_parts(position, leaf, ommers).map_err(|_err| { io::Error::new( io::ErrorKind::InvalidData, - format!("Parsing resulted in an invalid Merkle frontier: {:?}", err), + "Parsing resulted in an invalid Merkle frontier", ) }) } @@ -168,10 +173,10 @@ pub fn write_frontier_v1( pub fn read_frontier_v1(reader: R) -> io::Result> { match Optional::read(reader, read_nonempty_frontier_v1)? { None => Ok(Frontier::empty()), - Some(f) => Frontier::try_from(f).map_err(|err| { + Some(f) => Frontier::try_from(f).map_err(|_err| { io::Error::new( io::ErrorKind::InvalidData, - format!("Parsing resulted in an invalid Merkle frontier: {:?}", err), + "Parsing resulted in an invalid Merkle frontier", ) }), } @@ -266,25 +271,21 @@ pub fn merkle_path_from_slice( if auth_path.len() != usize::from(DEPTH) { return Err(io::Error::new( io::ErrorKind::InvalidData, - format!("length of auth path is not the expected {} elements", DEPTH), + "auth path has unexpected length", )); } // Read the position from the witness - let position = witness.read_u64::().map(Position::from)?; + let position = witness.read_u64_le().map(Position::from)?; // The witness should be empty now; if it wasn't, the caller would // have provided more information than they should have, indicating // a bug downstream if witness.is_empty() { - let path_len = auth_path.len(); MerklePath::from_parts(auth_path, position).map_err(|_| { io::Error::new( io::ErrorKind::InvalidData, - format!( - "auth path expected to contain {} elements, got {}", - DEPTH, path_len - ), + "auth path contained incorrect number of elements", ) }) } else { @@ -297,43 +298,43 @@ pub fn merkle_path_from_slice( #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { - use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + use crate::encoding::{ReadBytesExt, WriteBytesExt}; + use alloc::string::String; + use core2::io::{self, Read, Write}; use incrementalmerkletree::frontier::testing::TestNode; - use std::io::{self, Read, Write}; use zcash_encoding::Vector; use super::HashSer; impl HashSer for TestNode { fn read(mut reader: R) -> io::Result { - reader.read_u64::().map(TestNode) + reader.read_u64_le().map(TestNode) } fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_u64::(self.0) + writer.write_u64_le(self.0) } } impl HashSer for String { fn read(reader: R) -> io::Result { Vector::read(reader, |r| r.read_u8()).and_then(|xs| { - String::from_utf8(xs).map_err(|e| { - io::Error::new( - io::ErrorKind::InvalidData, - format!("Not a valid utf8 string: {:?}", e), - ) + String::from_utf8(xs).map_err(|_e| { + io::Error::new(io::ErrorKind::InvalidData, "not a valid utf8 string") }) }) } fn write(&self, writer: W) -> io::Result<()> { - Vector::write(writer, self.as_bytes(), |w, b| w.write_u8(*b)) + Vector::write(writer, self.as_bytes(), |w, b| w.write_all(&[*b])) } } } #[cfg(test)] mod tests { + use alloc::string::{String, ToString}; + use alloc::vec::Vec; use assert_matches::assert_matches; use incrementalmerkletree::{ frontier::{testing::arb_commitment_tree, Frontier, PathFiller}, diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index bf3d4cb677..21a08bd55f 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -1,16 +1,10 @@ //! Structs for building transactions. +use core::cmp::Ordering; +use core::fmt; use rand::{CryptoRng, RngCore}; -use std::cmp::Ordering; -use std::error; -use std::fmt; -use std::sync::mpsc::Sender; -use ::sapling::{ - builder::SaplingMetadata, - prover::{OutputProver, SpendProver}, - Note, PaymentAddress, -}; +use ::sapling::{builder::SaplingMetadata, Note, PaymentAddress}; use ::transparent::{address::TransparentAddress, builder::TransparentBuilder, bundle::TxOut}; use zcash_protocol::{ consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters}, @@ -23,16 +17,29 @@ use crate::transaction::{ transparent::{InputView, OutputView}, FeeRule, }, - sighash::{signature_hash, SignableInput}, - txid::TxIdDigester, - Transaction, TransactionData, TxVersion, Unauthorized, + Transaction, TxVersion, +}; + +#[cfg(feature = "std")] +use std::sync::mpsc::Sender; + +#[cfg(feature = "circuits")] +use { + crate::transaction::{ + sighash::{signature_hash, SignableInput}, + txid::TxIdDigester, + TransactionData, Unauthorized, + }, + ::sapling::prover::{OutputProver, SpendProver}, + ::transparent::builder::TransparentSigningSet, + alloc::vec::Vec, }; #[cfg(feature = "transparent-inputs")] use ::transparent::builder::TransparentInputInfo; #[cfg(not(feature = "transparent-inputs"))] -use std::convert::Infallible; +use core::convert::Infallible; #[cfg(zcash_unstable = "zfuture")] use crate::{ @@ -47,7 +54,6 @@ use crate::{ }; use super::components::sapling::zip212_enforcement; -use ::transparent::builder::TransparentSigningSet; /// Since Blossom activation, the default transaction expiry delta should be 40 blocks. /// @@ -137,7 +143,8 @@ impl fmt::Display for Error { } } -impl error::Error for Error {} +#[cfg(feature = "std")] +impl std::error::Error for Error {} impl From for Error { fn from(e: BalanceError) -> Self { @@ -304,8 +311,8 @@ pub struct Builder<'a, P, U: sapling::builder::ProverProgress> { #[cfg(zcash_unstable = "zfuture")] tze_builder: TzeBuilder<'a, TransactionData>, #[cfg(not(zcash_unstable = "zfuture"))] - tze_builder: std::marker::PhantomData<&'a ()>, - progress_notifier: U, + tze_builder: core::marker::PhantomData<&'a ()>, + _progress_notifier: U, } impl<'a, P, U: sapling::builder::ProverProgress> Builder<'a, P, U> { @@ -387,8 +394,8 @@ impl<'a, P: consensus::Parameters> Builder<'a, P, ()> { #[cfg(zcash_unstable = "zfuture")] tze_builder: TzeBuilder::empty(), #[cfg(not(zcash_unstable = "zfuture"))] - tze_builder: std::marker::PhantomData, - progress_notifier: (), + tze_builder: core::marker::PhantomData, + _progress_notifier: (), } } @@ -398,9 +405,10 @@ impl<'a, P: consensus::Parameters> Builder<'a, P, ()> { /// sent represents the total steps completed so far. It will eventually send number /// of spends + outputs. If there's an error building the transaction, the channel is /// closed. + #[cfg(feature = "std")] pub fn with_progress_notifier( self, - progress_notifier: Sender, + _progress_notifier: Sender, ) -> Builder<'a, P, Sender> { Builder { params: self.params, @@ -411,7 +419,7 @@ impl<'a, P: consensus::Parameters> Builder<'a, P, ()> { sapling_builder: self.sapling_builder, orchard_builder: self.orchard_builder, tze_builder: self.tze_builder, - progress_notifier, + _progress_notifier, } } } @@ -639,6 +647,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< /// Upon success, returns a tuple containing the final transaction, and the /// [`SaplingMetadata`] generated during the build process. #[allow(clippy::too_many_arguments)] + #[cfg(feature = "circuits")] pub fn build( self, transparent_signing_set: &TransparentSigningSet, @@ -694,6 +703,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< } #[allow(clippy::too_many_arguments)] + #[cfg(feature = "circuits")] fn build_internal( self, transparent_signing_set: &TransparentSigningSet, @@ -746,7 +756,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< spend_prover, output_prover, &mut rng, - self.progress_notifier, + self._progress_notifier, ), sapling_meta, ) @@ -981,10 +991,11 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Extensio fn add_tze_output( &mut self, extension_id: u32, - value: ZatBalance, + value: Zatoshis, guarded_by: &G, ) -> Result<(), Self::BuildError> { - self.tze_builder.add_output(extension_id, value, guarded_by) + self.tze_builder.add_output(extension_id, value, guarded_by); + Ok(()) } } @@ -1046,7 +1057,7 @@ mod testing { #[cfg(test)] mod tests { - use std::convert::Infallible; + use core::convert::Infallible; use assert_matches::assert_matches; use ff::Field; @@ -1102,8 +1113,8 @@ mod tests { #[cfg(zcash_unstable = "zfuture")] tze_builder: TzeBuilder::empty(), #[cfg(not(zcash_unstable = "zfuture"))] - tze_builder: std::marker::PhantomData, - progress_notifier: (), + tze_builder: core::marker::PhantomData, + _progress_notifier: (), orchard_builder: None, }; diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 70fb5b6d15..281ebaa11b 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -1,8 +1,10 @@ -/// Functions for parsing & serialization of Orchard transaction components. -use std::convert::TryFrom; -use std::io::{self, Read, Write}; +//! Functions for parsing & serialization of Orchard transaction components. +use crate::encoding::ReadBytesExt; + +use alloc::vec::Vec; +use core::convert::TryFrom; +use core2::io::{self, Read, Write}; -use byteorder::{ReadBytesExt, WriteBytesExt}; use nonempty::NonEmpty; use orchard::{ @@ -90,7 +92,7 @@ pub fn read_value_commitment(mut reader: R) -> io::Result(mut reader: R) -> io::Result { if nullifier_ctopt.is_none().into() { Err(io::Error::new( io::ErrorKind::InvalidInput, - "invalid Pallas point for nullifier".to_owned(), + "invalid Pallas point for nullifier", )) } else { Ok(nullifier_ctopt.unwrap()) @@ -114,12 +116,8 @@ pub fn read_nullifier(mut reader: R) -> io::Result { pub fn read_verification_key(mut reader: R) -> io::Result> { let mut bytes = [0u8; 32]; reader.read_exact(&mut bytes)?; - VerificationKey::try_from(bytes).map_err(|_| { - io::Error::new( - io::ErrorKind::InvalidInput, - "invalid verification key".to_owned(), - ) - }) + VerificationKey::try_from(bytes) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid verification key")) } pub fn read_cmx(mut reader: R) -> io::Result { @@ -129,7 +127,7 @@ pub fn read_cmx(mut reader: R) -> io::Result { Option::from(cmx).ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, - "invalid Pallas base for field cmx".to_owned(), + "invalid Pallas base for field cmx", ) }) } @@ -168,23 +166,15 @@ pub fn read_action_without_auth(mut reader: R) -> io::Result pub fn read_flags(mut reader: R) -> io::Result { let mut byte = [0u8; 1]; reader.read_exact(&mut byte)?; - Flags::from_byte(byte[0]).ok_or_else(|| { - io::Error::new( - io::ErrorKind::InvalidInput, - "invalid Orchard flags".to_owned(), - ) - }) + Flags::from_byte(byte[0]) + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "invalid Orchard flags")) } pub fn read_anchor(mut reader: R) -> io::Result { let mut bytes = [0u8; 32]; reader.read_exact(&mut bytes)?; - Option::from(Anchor::from_bytes(bytes)).ok_or_else(|| { - io::Error::new( - io::ErrorKind::InvalidInput, - "invalid Orchard anchor".to_owned(), - ) - }) + Option::from(Anchor::from_bytes(bytes)) + .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "invalid Orchard anchor")) } pub fn read_signature(mut reader: R) -> io::Result> { @@ -209,7 +199,7 @@ pub fn write_v5_bundle( Vector::write( &mut writer, bundle.authorization().proof().as_ref(), - |w, b| w.write_u8(*b), + |w, b| w.write_all(&[*b]), )?; Array::write( &mut writer, diff --git a/zcash_primitives/src/transaction/components/sapling.rs b/zcash_primitives/src/transaction/components/sapling.rs index 82e1e01890..943b11a387 100644 --- a/zcash_primitives/src/transaction/components/sapling.rs +++ b/zcash_primitives/src/transaction/components/sapling.rs @@ -1,5 +1,6 @@ +use alloc::vec::Vec; +use core2::io::{self, Read, Write}; use ff::PrimeField; -use std::io::{self, Read, Write}; use ::sapling::{ bundle::{ @@ -109,13 +110,13 @@ fn read_cmu(mut reader: R) -> io::Result { /// Consensus rules (§7.3) & (§7.4): /// - Canonical encoding is enforced here -pub fn read_base(mut reader: R, field: &str) -> io::Result { +pub fn read_base(mut reader: R, _field: &str) -> io::Result { let mut f = [0u8; 32]; reader.read_exact(&mut f)?; Option::from(jubjub::Base::from_repr(f)).ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, - format!("{} not in field", field), + "base value not a valid field element", ) }) } @@ -145,7 +146,7 @@ fn read_rk(mut reader: R) -> io::Result) -> Result<(), std::fmt::Error> { +impl core::fmt::Debug for SproutProof { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { match self { SproutProof::Groth(_) => write!(f, "SproutProof::Groth"), SproutProof::PHGR(_) => write!(f, "SproutProof::PHGR"), @@ -60,8 +61,8 @@ pub struct JsDescription { pub(crate) ciphertexts: [[u8; 601]; ZC_NUM_JS_OUTPUTS], } -impl std::fmt::Debug for JsDescription { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +impl core::fmt::Debug for JsDescription { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { write!( f, "JSDescription( diff --git a/zcash_primitives/src/transaction/components/tze.rs b/zcash_primitives/src/transaction/components/tze.rs index 72dfe26731..e62f1450f6 100644 --- a/zcash_primitives/src/transaction/components/tze.rs +++ b/zcash_primitives/src/transaction/components/tze.rs @@ -1,18 +1,21 @@ //! Structs representing the TZE components within Zcash transactions. -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use std::convert::TryFrom; -use std::fmt::Debug; -use std::io::{self, Read, Write}; - +use alloc::vec::Vec; +use core::convert::TryFrom; +use core::fmt::Debug; +use core2::io::{self, Read, Write}; + +use crate::{ + encoding::{ReadBytesExt, WriteBytesExt}, + extensions::transparent as tze, + transaction::TxId, +}; use zcash_encoding::{CompactSize, Vector}; - -use super::amount::Amount; -use crate::{extensions::transparent as tze, transaction::TxId}; +use zcash_protocol::value::Zatoshis; pub mod builder; -fn to_io_error(_: std::num::TryFromIntError) -> io::Error { +fn to_io_error(_: core::num::TryFromIntError) -> io::Error { io::Error::new(io::ErrorKind::InvalidData, "value out of range") } @@ -20,8 +23,8 @@ pub trait Authorization: Debug { type Witness: Debug + Clone + PartialEq; } -impl Authorization for std::convert::Infallible { - type Witness = std::convert::Infallible; +impl Authorization for core::convert::Infallible { + type Witness = core::convert::Infallible; } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -92,13 +95,13 @@ impl OutPoint { pub fn read(mut reader: R) -> io::Result { let txid = TxId::read(&mut reader)?; - let n = reader.read_u32::()?; + let n = reader.read_u32_le()?; Ok(OutPoint { txid, n }) } pub fn write(&self, mut writer: W) -> io::Result<()> { self.txid.write(&mut writer)?; - writer.write_u32::(self.n) + writer.write_u32_le(self.n) } pub fn n(&self) -> u32 { @@ -190,7 +193,7 @@ impl TzeIn<::Witness> { #[derive(Clone, Debug, PartialEq, Eq)] pub struct TzeOut { - pub value: Amount, + pub value: Zatoshis, pub precondition: tze::Precondition, } @@ -199,7 +202,7 @@ impl TzeOut { let value = { let mut tmp = [0; 8]; reader.read_exact(&mut tmp)?; - Amount::from_nonnegative_i64_le_bytes(tmp) + Zatoshis::from_nonnegative_i64_le_bytes(tmp) } .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "value out of range"))?; diff --git a/zcash_primitives/src/transaction/components/tze/builder.rs b/zcash_primitives/src/transaction/components/tze/builder.rs index 974dac9ce8..1625b6d7d7 100644 --- a/zcash_primitives/src/transaction/components/tze/builder.rs +++ b/zcash_primitives/src/transaction/components/tze/builder.rs @@ -1,17 +1,17 @@ //! Types and functions for building TZE transaction components -use std::fmt; +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::fmt; use crate::{ extensions::transparent::{self as tze, ToPayload}, transaction::{ self as tx, - components::{ - amount::{Amount, BalanceError}, - tze::{Authorization, Authorized, Bundle, OutPoint, TzeIn, TzeOut}, - }, + components::tze::{Authorization, Authorized, Bundle, OutPoint, TzeIn, TzeOut}, }, }; +use zcash_protocol::value::{BalanceError, ZatBalance, Zatoshis}; #[derive(Debug, PartialEq, Eq)] pub enum Error { @@ -100,13 +100,9 @@ impl<'a, BuildCtx> TzeBuilder<'a, BuildCtx> { pub fn add_output( &mut self, extension_id: u32, - value: Amount, + value: Zatoshis, guarded_by: &G, - ) -> Result<(), Error> { - if value.is_negative() { - return Err(Error::InvalidAmount); - } - + ) -> () { let (mode, payload) = guarded_by.to_payload(); self.vout.push(TzeOut { value, @@ -116,26 +112,24 @@ impl<'a, BuildCtx> TzeBuilder<'a, BuildCtx> { payload, }, }); - - Ok(()) } - pub fn value_balance(&self) -> Result { + pub fn value_balance(&self) -> Result { let total_in = self .vin .iter() .map(|tzi| tzi.coin.value) - .sum::>() + .sum::>() .ok_or(BalanceError::Overflow)?; let total_out = self .vout .iter() .map(|tzo| tzo.value) - .sum::>() + .sum::>() .ok_or(BalanceError::Overflow)?; - (total_in - total_out).ok_or(BalanceError::Underflow) + (ZatBalance::from(total_in) - ZatBalance::from(total_out)).ok_or(BalanceError::Underflow) } pub fn build(self) -> (Option>, Vec>) { diff --git a/zcash_primitives/src/transaction/fees/fixed.rs b/zcash_primitives/src/transaction/fees/fixed.rs index c69dd38940..7674e4cb29 100644 --- a/zcash_primitives/src/transaction/fees/fixed.rs +++ b/zcash_primitives/src/transaction/fees/fixed.rs @@ -28,7 +28,7 @@ impl FeeRule { } impl super::FeeRule for FeeRule { - type Error = std::convert::Infallible; + type Error = core::convert::Infallible; fn fee_required( &self, diff --git a/zcash_primitives/src/transaction/fees/transparent.rs b/zcash_primitives/src/transaction/fees/transparent.rs index 4ee98977f9..aa09c075e4 100644 --- a/zcash_primitives/src/transaction/fees/transparent.rs +++ b/zcash_primitives/src/transaction/fees/transparent.rs @@ -1,7 +1,7 @@ //! Types related to computation of fees and change related to the transparent components //! of a transaction. -use std::convert::Infallible; +use core::convert::Infallible; use crate::transaction::fees::zip317::P2PKH_STANDARD_INPUT_SIZE; use transparent::{ @@ -31,7 +31,7 @@ impl InputSize { /// This trait provides a minimized view of a transparent input suitable for use in /// fee and change computation. -pub trait InputView: std::fmt::Debug { +pub trait InputView: core::fmt::Debug { /// The outpoint to which the input refers. fn outpoint(&self) -> &OutPoint; @@ -69,7 +69,7 @@ impl InputView for Infallible { /// This trait provides a minimized view of a transparent output suitable for use in /// fee and change computation. -pub trait OutputView: std::fmt::Debug { +pub trait OutputView: core::fmt::Debug { /// Returns the value of the output being created. fn value(&self) -> Zatoshis; diff --git a/zcash_primitives/src/transaction/fees/tze.rs b/zcash_primitives/src/transaction/fees/tze.rs index 1a603f2065..457f1ae680 100644 --- a/zcash_primitives/src/transaction/fees/tze.rs +++ b/zcash_primitives/src/transaction/fees/tze.rs @@ -2,11 +2,9 @@ use crate::{ extensions::transparent as tze, - transaction::components::{ - amount::Amount, - tze::{builder::TzeBuildInput, OutPoint, TzeOut}, - }, + transaction::components::tze::{builder::TzeBuildInput, OutPoint, TzeOut}, }; +use zcash_protocol::value::Zatoshis; /// This trait provides a minimized view of a TZE input suitable for use in /// fee computation. @@ -30,13 +28,13 @@ impl InputView for TzeBuildInput { /// fee computation. pub trait OutputView { /// The value of the newly created output - fn value(&self) -> Amount; + fn value(&self) -> Zatoshis; /// The precondition that must be satisfied in order to spend this output. fn precondition(&self) -> &tze::Precondition; } impl OutputView for TzeOut { - fn value(&self) -> Amount { + fn value(&self) -> Zatoshis { self.value } diff --git a/zcash_primitives/src/transaction/fees/zip317.rs b/zcash_primitives/src/transaction/fees/zip317.rs index 24c7f77d97..41199bff92 100644 --- a/zcash_primitives/src/transaction/fees/zip317.rs +++ b/zcash_primitives/src/transaction/fees/zip317.rs @@ -2,6 +2,7 @@ //! //! [`FeeRule`]: crate::transaction::fees::FeeRule //! [ZIP 317]: https//zips.z.cash/zip-0317 +use alloc::vec::Vec; use core::cmp::max; use ::transparent::bundle::OutPoint; @@ -136,8 +137,8 @@ impl From for FeeError { } } -impl std::fmt::Display for FeeError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Display for FeeError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match &self { FeeError::Balance(e) => write!( f, diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index f80a9d3540..4727537fa4 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -11,14 +11,13 @@ pub mod util; #[cfg(test)] mod tests; +use crate::encoding::{ReadBytesExt, WriteBytesExt}; use blake2b_simd::Hash as Blake2bHash; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use std::convert::TryFrom; -use std::fmt::Debug; -use std::io::{self, Read, Write}; -use std::ops::Deref; +use core::convert::TryFrom; +use core::fmt::Debug; +use core::ops::Deref; +use core2::io::{self, Read, Write}; -use ::sapling::builder as sapling_builder; use ::transparent::bundle::{self as transparent, OutPoint, TxIn, TxOut}; use zcash_encoding::{CompactSize, Vector}; use zcash_protocol::{ @@ -35,6 +34,9 @@ use self::{ util::sha256d::{HashReader, HashWriter}, }; +#[cfg(feature = "circuits")] +use ::sapling::builder as sapling_builder; + #[cfg(zcash_unstable = "zfuture")] use self::components::tze::{self, TzeIn, TzeOut}; @@ -78,12 +80,12 @@ pub enum TxVersion { impl TxVersion { pub fn read(mut reader: R) -> io::Result { - let header = reader.read_u32::()?; + let header = reader.read_u32_le()?; let overwintered = (header >> 31) == 1; let version = header & 0x7FFFFFFF; if overwintered { - match (version, reader.read_u32::()?) { + match (version, reader.read_u32_le()?) { (OVERWINTER_TX_VERSION, OVERWINTER_VERSION_GROUP_ID) => Ok(TxVersion::Overwinter), (SAPLING_TX_VERSION, SAPLING_VERSION_GROUP_ID) => Ok(TxVersion::Sapling), (V5_TX_VERSION, V5_VERSION_GROUP_ID) => Ok(TxVersion::Zip225), @@ -134,10 +136,10 @@ impl TxVersion { } pub fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_u32::(self.header())?; + writer.write_u32_le(self.header())?; match self { TxVersion::Sprout(_) => Ok(()), - _ => writer.write_u32::(self.version_group_id()), + _ => writer.write_u32_le(self.version_group_id()), } } @@ -227,6 +229,7 @@ impl Authorization for Authorized { /// transactions, which commit to the Sapling proofs in the transaction digest. pub struct Unauthorized; +#[cfg(feature = "circuits")] impl Authorization for Unauthorized { type TransparentAuth = ::transparent::builder::Unauthorized; type SaplingAuth = @@ -602,9 +605,9 @@ impl Transaction { ) -> io::Result { let transparent_bundle = Self::read_transparent(&mut reader)?; - let lock_time = reader.read_u32::()?; + let lock_time = reader.read_u32_le()?; let expiry_height: BlockHeight = if version.has_overwinter() { - reader.read_u32::()?.into() + reader.read_u32_le()?.into() } else { 0u32.into() }; @@ -725,16 +728,13 @@ impl Transaction { } fn read_v5_header_fragment(mut reader: R) -> io::Result<(BranchId, u32, BlockHeight)> { - let consensus_branch_id = reader.read_u32::().and_then(|value| { - BranchId::try_from(value).map_err(|e| { - io::Error::new( - io::ErrorKind::InvalidInput, - "invalid consensus branch id: ".to_owned() + e, - ) + let consensus_branch_id = reader.read_u32_le().and_then(|value| { + BranchId::try_from(value).map_err(|_e| { + io::Error::new(io::ErrorKind::InvalidInput, "invalid consensus branch id") }) })?; - let lock_time = reader.read_u32::()?; - let expiry_height: BlockHeight = reader.read_u32::()?.into(); + let lock_time = reader.read_u32_le()?; + let expiry_height: BlockHeight = reader.read_u32_le()?.into(); Ok((consensus_branch_id, lock_time, expiry_height)) } @@ -775,9 +775,9 @@ impl Transaction { self.version.write(&mut writer)?; self.write_transparent(&mut writer)?; - writer.write_u32::(self.lock_time)?; + writer.write_u32_le(self.lock_time)?; if self.version.has_overwinter() { - writer.write_u32::(u32::from(self.expiry_height))?; + writer.write_u32_le(u32::from(self.expiry_height))?; } sapling_serialization::write_v4_components( @@ -842,9 +842,9 @@ impl Transaction { pub fn write_v5_header(&self, mut writer: W) -> io::Result<()> { self.version.write(&mut writer)?; - writer.write_u32::(u32::from(self.consensus_branch_id))?; - writer.write_u32::(self.lock_time)?; - writer.write_u32::(u32::from(self.expiry_height))?; + writer.write_u32_le(u32::from(self.consensus_branch_id))?; + writer.write_u32_le(self.lock_time)?; + writer.write_u32_le(u32::from(self.expiry_height))?; Ok(()) } diff --git a/zcash_primitives/src/transaction/sighash_v4.rs b/zcash_primitives/src/transaction/sighash_v4.rs index de0186b0db..55f10e798a 100644 --- a/zcash_primitives/src/transaction/sighash_v4.rs +++ b/zcash_primitives/src/transaction/sighash_v4.rs @@ -1,3 +1,4 @@ +use alloc::vec::Vec; use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use ff::PrimeField; diff --git a/zcash_primitives/src/transaction/sighash_v5.rs b/zcash_primitives/src/transaction/sighash_v5.rs index bc7c6f442b..08ad375727 100644 --- a/zcash_primitives/src/transaction/sighash_v5.rs +++ b/zcash_primitives/src/transaction/sighash_v5.rs @@ -1,5 +1,5 @@ -use blake2b_simd::{Hash as Blake2bHash, Params, State}; -use std::io::Write; +use blake2b_simd::{Hash as Blake2bHash, Params}; +use core2::io::Write; use ::transparent::{ bundle::{self as transparent, TxOut}, @@ -10,19 +10,25 @@ use ::transparent::{ }; use zcash_encoding::Array; -use crate::transaction::{ - sighash::SignableInput, - txid::{ - hash_transparent_txid_data, to_hash, transparent_outputs_hash, transparent_prevout_hash, - transparent_sequence_hash, ZCASH_TRANSPARENT_HASH_PERSONALIZATION, +use crate::{ + encoding::StateWrite, + transaction::{ + sighash::SignableInput, + txid::{ + hash_transparent_txid_data, to_hash, transparent_outputs_hash, + transparent_prevout_hash, transparent_sequence_hash, + ZCASH_TRANSPARENT_HASH_PERSONALIZATION, + }, + Authorization, TransactionData, TransparentDigests, TxDigests, }, - Authorization, TransactionData, TransparentDigests, TxDigests, }; #[cfg(zcash_unstable = "zfuture")] use { - crate::transaction::{components::tze, TzeDigests}, - byteorder::WriteBytesExt, + crate::{ + encoding::WriteBytesExt, + transaction::{components::tze, TzeDigests}, + }, zcash_encoding::{CompactSize, Vector}, }; @@ -33,8 +39,8 @@ const ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxTrScripts #[cfg(zcash_unstable = "zfuture")] const ZCASH_TZE_INPUT_HASH_PERSONALIZATION: &[u8; 16] = b"Zcash__TzeInHash"; -fn hasher(personal: &[u8; 16]) -> State { - Params::new().hash_length(32).personal(personal).to_state() +fn hasher(personal: &[u8; 16]) -> StateWrite { + StateWrite(Params::new().hash_length(32).personal(personal).to_state()) } /// Implements [ZIP 244 section S.2](https://zips.z.cash/zip-0244#s-2-transparent-sig-digest). diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 66fe4e0ef7..1e1a8f3890 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -1,10 +1,12 @@ -use ::transparent::sighash::SighashType; +use alloc::vec::Vec; use blake2b_simd::Hash as Blake2bHash; -use std::ops::Deref; +use core::ops::Deref; use proptest::prelude::*; -use ::transparent::{address::Script, sighash::TransparentAuthorizingContext}; +use ::transparent::{ + address::Script, sighash::SighashType, sighash::TransparentAuthorizingContext, +}; use zcash_protocol::{consensus::BranchId, value::Zatoshis}; use super::{ diff --git a/zcash_primitives/src/transaction/tests/data.rs b/zcash_primitives/src/transaction/tests/data.rs index 1d58c923a1..43c0d5b7c6 100644 --- a/zcash_primitives/src/transaction/tests/data.rs +++ b/zcash_primitives/src/transaction/tests/data.rs @@ -140,6 +140,7 @@ pub mod tx_read_write { } pub mod zip_0143 { + use alloc::vec::Vec; use transparent::address::Script; use zcash_protocol::consensus; @@ -1954,6 +1955,7 @@ pub mod zip_0143 { } pub mod zip_0243 { + use alloc::vec::Vec; use transparent::address::Script; use zcash_protocol::consensus; @@ -5688,6 +5690,7 @@ pub mod zip_0243 { } pub mod zip_0244 { + use alloc::vec::Vec; pub struct TestVector { pub tx: Vec, pub txid: [u8; 32], diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 108b83a365..f59932e491 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -1,9 +1,9 @@ -use std::borrow::Borrow; -use std::convert::TryFrom; -use std::io::Write; +use crate::encoding::{StateWrite, WriteBytesExt}; +use core::borrow::Borrow; +use core::convert::TryFrom; +use core2::io::Write; -use blake2b_simd::{Hash as Blake2bHash, Params, State}; -use byteorder::{LittleEndian, WriteBytesExt}; +use blake2b_simd::{Hash as Blake2bHash, Params}; use ff::PrimeField; use ::orchard::bundle::{self as orchard}; @@ -62,8 +62,8 @@ const ZCASH_SAPLING_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthSapliHash"; #[cfg(zcash_unstable = "zfuture")] const ZCASH_TZE_WITNESSES_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthTZE__Hash"; -fn hasher(personal: &[u8; 16]) -> State { - Params::new().hash_length(32).personal(personal).to_state() +fn hasher(personal: &[u8; 16]) -> StateWrite { + StateWrite(Params::new().hash_length(32).personal(personal).to_state()) } /// Sequentially append the serialized value of each transparent input @@ -87,7 +87,7 @@ pub(crate) fn transparent_sequence_hash Blake2bHash { let mut h = hasher(ZCASH_SEQUENCE_HASH_PERSONALIZATION); for t_in in vin { - h.write_u32::(t_in.sequence).unwrap(); + h.write_u32_le(t_in.sequence).unwrap(); } h.finalize() } @@ -226,13 +226,11 @@ fn hash_header_txid_data( ) -> Blake2bHash { let mut h = hasher(ZCASH_HEADERS_HASH_PERSONALIZATION); - h.write_u32::(version.header()).unwrap(); - h.write_u32::(version.version_group_id()) - .unwrap(); - h.write_u32::(consensus_branch_id.into()) - .unwrap(); - h.write_u32::(lock_time).unwrap(); - h.write_u32::(expiry_height.into()).unwrap(); + h.write_u32_le(version.header()).unwrap(); + h.write_u32_le(version.version_group_id()).unwrap(); + h.write_u32_le(consensus_branch_id.into()).unwrap(); + h.write_u32_le(lock_time).unwrap(); + h.write_u32_le(expiry_height.into()).unwrap(); h.finalize() } @@ -372,7 +370,7 @@ pub(crate) fn to_hash( let mut personal = [0; 16]; personal[..12].copy_from_slice(ZCASH_TX_PERSONALIZATION_PREFIX); (&mut personal[12..]) - .write_u32::(consensus_branch_id.into()) + .write_u32_le(consensus_branch_id.into()) .unwrap(); let mut h = hasher(&personal); @@ -519,7 +517,7 @@ impl TransactionDigest for BlockTxCommitmentDigester { let mut personal = [0; 16]; personal[..12].copy_from_slice(ZCASH_AUTH_PERSONALIZATION_PREFIX); (&mut personal[12..]) - .write_u32::(consensus_branch_id.into()) + .write_u32_le(consensus_branch_id.into()) .unwrap(); let mut h = hasher(&personal); diff --git a/zcash_primitives/src/transaction/util/sha256d.rs b/zcash_primitives/src/transaction/util/sha256d.rs index 439bab9fde..90ea9d9af5 100644 --- a/zcash_primitives/src/transaction/util/sha256d.rs +++ b/zcash_primitives/src/transaction/util/sha256d.rs @@ -1,5 +1,5 @@ +use core2::io::{self, Read, Write}; use sha2::{digest::Output, Digest, Sha256}; -use std::io::{self, Read, Write}; /// Abstraction over a reader which SHA-256d-hashes the data being read. pub struct HashReader { diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 66bafe0713..83c1b273ae 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -18,7 +18,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -zcash_primitives.workspace = true +zcash_primitives = { workspace = true, features = ["circuits"] } # Dependencies exposed in a public API: # (Breaking upgrades to these require a breaking upgrade to this crate.)