Merge pull request #151 from zcash/no_std
Implement `no_std` support via a default-enabled `std` feature flag.
This commit is contained in:
commit
87e5ddfc41
|
@ -41,12 +41,36 @@ jobs:
|
|||
matrix:
|
||||
target:
|
||||
- wasm32-wasi
|
||||
- thumbv7em-none-eabihf
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: crate_root
|
||||
# We use a synthetic crate to ensure no dev-dependencies are enabled, which can
|
||||
# be incompatible with some of these targets.
|
||||
- name: Create synthetic crate for testing
|
||||
run: cargo init --lib ci-build
|
||||
- name: Copy Rust version into synthetic crate
|
||||
run: cp crate_root/rust-toolchain.toml ci-build/
|
||||
- name: Copy patch directives into synthetic crate
|
||||
run: |
|
||||
echo "[patch.crates-io]" >> ./ci-build/Cargo.toml
|
||||
cat ./crate_root/Cargo.toml | sed "0,/.\+\(patch.crates.\+\)/d" >> ./ci-build/Cargo.toml
|
||||
- name: Add no_std pragma to lib.rs
|
||||
run: |
|
||||
echo "#![no_std]" > ./ci-build/src/lib.rs
|
||||
- name: Add sapling-crypto as a dependency of the synthetic crate
|
||||
working-directory: ./ci-build
|
||||
run: cargo add --no-default-features --path ../crate_root
|
||||
- name: Add lazy_static with the spin_no_std feature
|
||||
working-directory: ./ci-build
|
||||
run: cargo add lazy_static --features "spin_no_std"
|
||||
- name: Add target
|
||||
working-directory: ./ci-build
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
- name: Build crate
|
||||
run: cargo build --no-default-features --verbose --target ${{ matrix.target }}
|
||||
- name: Build for target
|
||||
working-directory: ./ci-build
|
||||
run: cargo build --verbose --target ${{ matrix.target }}
|
||||
|
||||
bitrot:
|
||||
name: Bitrot check
|
||||
|
|
|
@ -9,6 +9,13 @@ and this library adheres to Rust's notion of
|
|||
|
||||
### Added
|
||||
- `sapling_crypto::pczt::Zip32Derivation::extract_account_index`
|
||||
- `no_std` compatibility has been introduced by means of a default-enabled
|
||||
`std` feature flag.
|
||||
- A default-enabled `circuit` is now provided to enable downstream users to
|
||||
avoid the need to depend upon the `bellman` crate.
|
||||
|
||||
### Changed
|
||||
- MSRV is now 1.66
|
||||
|
||||
## [0.4.0] - 2024-12-16
|
||||
|
||||
|
|
|
@ -342,6 +342,15 @@ version = "0.2.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6"
|
||||
|
||||
[[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"
|
||||
|
@ -815,9 +824,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"
|
||||
checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
|
@ -1202,12 +1211,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/nuttycom/redjubjub?rev=e413019904400f4caa3550df7c4040befadfbb14#e413019904400f4caa3550df7c4040befadfbb14"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"reddsa",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"zeroize",
|
||||
]
|
||||
|
@ -1315,8 +1322,8 @@ dependencies = [
|
|||
"blake2b_simd",
|
||||
"blake2s_simd",
|
||||
"bls12_381",
|
||||
"byteorder",
|
||||
"chacha20poly1305",
|
||||
"core2",
|
||||
"criterion",
|
||||
"document-features",
|
||||
"ff",
|
||||
|
@ -1504,29 +1511,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
|
@ -1893,9 +1885,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zip32"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d724a63be4dfb50b7f3617e542984e22e4b4a5b8ca5de91f55613152885e6b22"
|
||||
checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"memuse",
|
||||
|
|
68
Cargo.toml
68
Cargo.toml
|
@ -7,7 +7,7 @@ authors = [
|
|||
"Kris Nuttycombe <kris@electriccoin.co>",
|
||||
]
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
rust-version = "1.66"
|
||||
description = "Cryptographic library for Zcash Sapling"
|
||||
homepage = "https://github.com/zcash/sapling-crypto"
|
||||
repository = "https://github.com/zcash/sapling-crypto"
|
||||
|
@ -18,48 +18,50 @@ features = ["test-dependencies"]
|
|||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[dependencies]
|
||||
ff = "0.13"
|
||||
group = { version = "0.13", features = ["wnaf-memuse"] }
|
||||
ff = { version = "0.13", default-features = false }
|
||||
group = "0.13"
|
||||
|
||||
bls12_381 = "0.8"
|
||||
jubjub = "0.10"
|
||||
redjubjub = "0.7"
|
||||
bls12_381 = { version = "0.8", default-features = false, features = ["alloc"] }
|
||||
jubjub = { version = "0.10", default-features = false, features = ["alloc"] }
|
||||
redjubjub = { version = "0.7", default-features = false }
|
||||
zcash_spec = "0.1"
|
||||
|
||||
# Boilerplate
|
||||
getset = "0.1"
|
||||
|
||||
# No-std support
|
||||
core2 = { version = "0.3", default-features = false, features = ["alloc"] }
|
||||
|
||||
# Circuits
|
||||
bellman = { version = "0.14", default-features = false, features = ["groth16"] }
|
||||
bellman = { version = "0.14", default-features = false, features = ["groth16"], optional = true }
|
||||
|
||||
# CSPRNG
|
||||
rand = "0.8"
|
||||
rand_core = "0.6"
|
||||
rand = { version = "0.8", default-features = false }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
|
||||
# Digests
|
||||
blake2b_simd = "1"
|
||||
blake2s_simd = "1"
|
||||
blake2b_simd = { version = "1", default-features = false }
|
||||
blake2s_simd = { version = "1", default-features = false }
|
||||
|
||||
# Documentation
|
||||
document-features = "0.2"
|
||||
document-features = { version = "0.2", optional = true }
|
||||
|
||||
# Encodings
|
||||
byteorder = "1"
|
||||
hex = "0.4"
|
||||
hex = { version = "0.4", default-features = false, features = ["alloc"] }
|
||||
|
||||
# Logging and metrics
|
||||
memuse = "0.2.1"
|
||||
tracing = "0.1"
|
||||
memuse = { version = "0.2.2", default-features = false }
|
||||
tracing = { version = "0.1", default-features = false }
|
||||
|
||||
# Note Commitment Trees
|
||||
bitvec = "1"
|
||||
incrementalmerkletree = { version = "0.7", features = ["legacy-api"] }
|
||||
bitvec = { version = "1", default-features = false }
|
||||
incrementalmerkletree = { version = "0.7", default-features = false, features = ["legacy-api"] }
|
||||
|
||||
# Note encryption
|
||||
zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] }
|
||||
|
||||
# Secret management
|
||||
subtle = "2.2.3"
|
||||
subtle = { version = "2.2.3", default-features = false }
|
||||
|
||||
# Static constants
|
||||
lazy_static = "1"
|
||||
|
@ -69,8 +71,9 @@ proptest = { version = "1", optional = true }
|
|||
|
||||
# ZIP 32
|
||||
aes = "0.8"
|
||||
fpe = "0.6"
|
||||
zip32 = "0.1"
|
||||
fpe = { version = "0.6", default-features = false, features = ["alloc"] }
|
||||
zip32 = { version = "0.1.1", default-features = false }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
chacha20poly1305 = "0.10"
|
||||
|
@ -83,10 +86,26 @@ rand_xorshift = "0.3"
|
|||
pprof = { version = "0.11", features = ["criterion", "flamegraph"] } # MSRV 1.56
|
||||
|
||||
[features]
|
||||
default = ["multicore"]
|
||||
default = ["multicore", "circuit"]
|
||||
std = [
|
||||
"core2/std",
|
||||
"dep:document-features",
|
||||
"group/wnaf-memuse",
|
||||
"redjubjub/std",
|
||||
]
|
||||
|
||||
## Enables creation of Sapling proofs
|
||||
circuit = [
|
||||
"dep:bellman",
|
||||
"bls12_381/bits",
|
||||
"bls12_381/groups",
|
||||
"bls12_381/pairings",
|
||||
"jubjub/bits",
|
||||
"std"
|
||||
]
|
||||
|
||||
## Enables multithreading support for creating proofs.
|
||||
multicore = ["bellman/multicore"]
|
||||
multicore = ["bellman?/multicore"]
|
||||
|
||||
### A temporary feature flag that exposes granular APIs needed by `zcashd`. These APIs
|
||||
### should not be relied upon and will be removed in a future release.
|
||||
|
@ -105,3 +124,6 @@ harness = false
|
|||
[[bench]]
|
||||
name = "pedersen_hash"
|
||||
harness = false
|
||||
|
||||
[patch.crates-io]
|
||||
redjubjub = { git = "https://github.com/nuttycom/redjubjub", rev = "e413019904400f4caa3550df7c4040befadfbb14" }
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
# sapling-crypto
|
||||
|
||||
This repository contains a (work-in-progress) implementation of Zcash's "Sapling" cryptography.
|
||||
This repository contains an implementation of Zcash's "Sapling" cryptography.
|
||||
|
||||
## `no_std` compatibility
|
||||
|
||||
Downstream users of this crate must enable the `spin_no_std` feature of the
|
||||
`lazy_static` crate in order to take advantage of `no_std` builds; this is due
|
||||
to the fact that `--no-default-features` builds of `lazy_static` still rely on
|
||||
`std`.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "1.65.0"
|
||||
channel = "1.66.0"
|
||||
components = ["clippy", "rustfmt"]
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
//! Types and functions for building Sapling transaction components.
|
||||
|
||||
use core::fmt;
|
||||
use std::{collections::BTreeMap, iter, marker::PhantomData};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use core::{fmt, iter, marker::PhantomData};
|
||||
|
||||
use group::ff::Field;
|
||||
use incrementalmerkletree::Position;
|
||||
|
@ -11,24 +12,27 @@ use redjubjub::{Binding, SpendAuth};
|
|||
use zcash_note_encryption::EphemeralKeyBytes;
|
||||
|
||||
use crate::{
|
||||
bundle::{
|
||||
Authorization, Authorized, Bundle, GrothProofBytes, OutputDescription, SpendDescription,
|
||||
},
|
||||
circuit,
|
||||
bundle::{Authorization, Authorized, Bundle, GrothProofBytes},
|
||||
keys::{
|
||||
EphemeralSecretKey, ExpandedSpendingKey, FullViewingKey, OutgoingViewingKey,
|
||||
SpendAuthorizingKey, SpendValidatingKey,
|
||||
},
|
||||
note::ExtractedNoteCommitment,
|
||||
note_encryption::{sapling_note_encryption, Zip212Enforcement},
|
||||
prover::{OutputProver, SpendProver},
|
||||
util::generate_random_rseed_internal,
|
||||
value::{
|
||||
CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment, ValueSum,
|
||||
},
|
||||
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum},
|
||||
Anchor, Diversifier, MerklePath, Node, Note, Nullifier, PaymentAddress, SaplingIvk,
|
||||
NOTE_COMMITMENT_TREE_DEPTH,
|
||||
};
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
use crate::{
|
||||
bundle::{OutputDescription, SpendDescription},
|
||||
circuit,
|
||||
prover::{OutputProver, SpendProver},
|
||||
value::{CommitmentSum, TrapdoorSum},
|
||||
zip32::ExtendedSpendingKey,
|
||||
Anchor, Diversifier, MerklePath, Node, Note, Nullifier, PaymentAddress, ProofGenerationKey,
|
||||
SaplingIvk, NOTE_COMMITMENT_TREE_DEPTH,
|
||||
ProofGenerationKey,
|
||||
};
|
||||
|
||||
/// If there are any shielded inputs, always have at least two shielded outputs, padding
|
||||
|
@ -268,6 +272,7 @@ impl PreparedSpendInfo {
|
|||
(cv, nullifier, rk, alpha)
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
fn build<Pr: SpendProver, R: RngCore>(
|
||||
self,
|
||||
proof_generation_key: Option<ProofGenerationKey>,
|
||||
|
@ -464,6 +469,7 @@ impl PreparedOutputInfo {
|
|||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
fn build<Pr: OutputProver, R: RngCore>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
|
@ -664,6 +670,7 @@ impl Builder {
|
|||
}
|
||||
|
||||
/// Constructs the Sapling bundle from the builder's accumulated state.
|
||||
#[cfg(feature = "circuit")]
|
||||
pub fn build<SP: SpendProver, OP: OutputProver, R: RngCore, V: TryFrom<i64>>(
|
||||
self,
|
||||
extsks: &[ExtendedSpendingKey],
|
||||
|
@ -726,6 +733,7 @@ impl Builder {
|
|||
|
||||
/// Constructs a new Sapling transaction bundle of the given type from the specified set of spends
|
||||
/// and outputs.
|
||||
#[cfg(feature = "circuit")]
|
||||
pub fn bundle<SP: SpendProver, OP: OutputProver, R: RngCore, V: TryFrom<i64>>(
|
||||
rng: R,
|
||||
bundle_type: BundleType,
|
||||
|
@ -917,6 +925,7 @@ fn build_bundle<B, SP, OP, R: RngCore>(
|
|||
/// Type alias for an in-progress bundle that has no proofs or signatures.
|
||||
///
|
||||
/// This is returned by [`Builder::build`].
|
||||
#[cfg(feature = "circuit")]
|
||||
pub type UnauthorizedBundle<V> = Bundle<InProgress<Unproven, Unsigned>, V>;
|
||||
|
||||
/// Marker trait representing bundle proofs in the process of being created.
|
||||
|
@ -951,9 +960,11 @@ impl<P: InProgressProofs, S: InProgressSignatures> Authorization for InProgress<
|
|||
///
|
||||
/// The [`SpendDescription`]s and [`OutputDescription`]s within the bundle contain the
|
||||
/// private data needed to create proofs.
|
||||
#[cfg(feature = "circuit")]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Unproven;
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
impl InProgressProofs for Unproven {
|
||||
type SpendProof = circuit::Spend;
|
||||
type OutputProof = circuit::Output;
|
||||
|
@ -969,16 +980,19 @@ impl InProgressProofs for Proven {
|
|||
}
|
||||
|
||||
/// Reports on the progress made towards creating proofs for a bundle.
|
||||
#[cfg(feature = "circuit")]
|
||||
pub trait ProverProgress {
|
||||
/// Updates the progress instance with the number of steps completed and the total
|
||||
/// number of steps.
|
||||
fn update(&mut self, cur: u32, end: u32);
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
impl ProverProgress for () {
|
||||
fn update(&mut self, _: u32, _: u32) {}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "circuit", feature = "std"))]
|
||||
impl<U: From<(u32, u32)>> ProverProgress for std::sync::mpsc::Sender<U> {
|
||||
fn update(&mut self, cur: u32, end: u32) {
|
||||
// If the send fails, we should ignore the error, not crash.
|
||||
|
@ -986,12 +1000,14 @@ impl<U: From<(u32, u32)>> ProverProgress for std::sync::mpsc::Sender<U> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
impl<U: ProverProgress> ProverProgress for &mut U {
|
||||
fn update(&mut self, cur: u32, end: u32) {
|
||||
(*self).update(cur, end);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
struct CreateProofs<'a, SP: SpendProver, OP: OutputProver, R: RngCore, U: ProverProgress> {
|
||||
spend_prover: &'a SP,
|
||||
output_prover: &'a OP,
|
||||
|
@ -1001,6 +1017,7 @@ struct CreateProofs<'a, SP: SpendProver, OP: OutputProver, R: RngCore, U: Prover
|
|||
progress: u32,
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
impl<'a, SP: SpendProver, OP: OutputProver, R: RngCore, U: ProverProgress>
|
||||
CreateProofs<'a, SP, OP, R, U>
|
||||
{
|
||||
|
@ -1052,6 +1069,7 @@ impl<'a, SP: SpendProver, OP: OutputProver, R: RngCore, U: ProverProgress>
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
impl<S: InProgressSignatures, V> Bundle<InProgress<Unproven, S>, V> {
|
||||
/// Creates the proofs for this bundle.
|
||||
pub fn create_proofs<SP: SpendProver, OP: OutputProver>(
|
||||
|
@ -1282,9 +1300,9 @@ impl<V> Bundle<InProgress<Proven, PartiallyAuthorized>, V> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
#[cfg(all(feature = "circuit", any(test, feature = "test-dependencies")))]
|
||||
pub(crate) mod testing {
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
use proptest::collection::vec;
|
||||
use proptest::prelude::*;
|
||||
|
@ -1293,7 +1311,6 @@ pub(crate) mod testing {
|
|||
use crate::{
|
||||
bundle::{Authorized, Bundle},
|
||||
note_encryption::Zip212Enforcement,
|
||||
prover::mock::{MockOutputProver, MockSpendProver},
|
||||
testing::{arb_node, arb_note},
|
||||
value::testing::arb_positive_note_value,
|
||||
zip32::testing::arb_extended_spending_key,
|
||||
|
@ -1305,7 +1322,11 @@ pub(crate) mod testing {
|
|||
|
||||
use super::{Builder, BundleType};
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
use crate::prover::mock::{MockOutputProver, MockSpendProver};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(feature = "circuit")]
|
||||
fn arb_bundle<V: fmt::Debug + From<i64>>(
|
||||
max_money: u64,
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use alloc::vec::Vec;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use memuse::DynamicUsage;
|
||||
|
@ -9,7 +10,7 @@ use zcash_note_encryption::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
circuit::GROTH_PROOF_SIZE,
|
||||
constants::GROTH_PROOF_SIZE,
|
||||
note::ExtractedNoteCommitment,
|
||||
note_encryption::{CompactOutputDescription, SaplingDomain},
|
||||
value::ValueCommitment,
|
||||
|
@ -220,8 +221,8 @@ pub struct SpendDescription<A: Authorization> {
|
|||
spend_auth_sig: A::AuthSig,
|
||||
}
|
||||
|
||||
impl<A: Authorization> std::fmt::Debug for SpendDescription<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
impl<A: Authorization> core::fmt::Debug for SpendDescription<A> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
write!(
|
||||
f,
|
||||
"SpendDescription(cv = {:?}, anchor = {:?}, nullifier = {:?}, rk = {:?}, spend_auth_sig = {:?})",
|
||||
|
@ -431,8 +432,8 @@ impl<A> ShieldedOutput<SaplingDomain, ENC_CIPHERTEXT_SIZE> for OutputDescription
|
|||
}
|
||||
}
|
||||
|
||||
impl<A> std::fmt::Debug for OutputDescription<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
impl<A> core::fmt::Debug for OutputDescription<A> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
write!(
|
||||
f,
|
||||
"OutputDescription(cv = {:?}, cmu = {:?}, ephemeral_key = {:?})",
|
||||
|
@ -498,7 +499,7 @@ impl<A> From<OutputDescription<A>> for CompactOutputDescription {
|
|||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))]
|
||||
pub mod testing {
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
use ff::Field;
|
||||
use group::{Group, GroupEncoding};
|
||||
|
@ -507,7 +508,7 @@ pub mod testing {
|
|||
use rand::{rngs::StdRng, SeedableRng};
|
||||
|
||||
use crate::{
|
||||
circuit::GROTH_PROOF_SIZE,
|
||||
constants::GROTH_PROOF_SIZE,
|
||||
note::testing::arb_cmu,
|
||||
value::{
|
||||
testing::{arb_note_value_bounded, arb_trapdoor},
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
//! The Sapling circuits.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use std::io;
|
||||
use core2::io;
|
||||
|
||||
use group::{ff::PrimeField, Curve};
|
||||
|
||||
use bellman::{groth16, Circuit, ConstraintSystem, SynthesisError};
|
||||
use bls12_381::Bls12;
|
||||
|
||||
use super::{value::NoteValue, PaymentAddress, ProofGenerationKey};
|
||||
|
||||
use bellman::gadgets::blake2s;
|
||||
use bellman::gadgets::boolean;
|
||||
use bellman::gadgets::multipack;
|
||||
|
@ -21,6 +20,7 @@ use self::constants::{
|
|||
PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
VALUE_COMMITMENT_VALUE_GENERATOR,
|
||||
};
|
||||
use crate::{value::NoteValue, PaymentAddress, ProofGenerationKey};
|
||||
|
||||
#[cfg(test)]
|
||||
use group::ff::PrimeFieldBits;
|
||||
|
@ -29,9 +29,6 @@ mod constants;
|
|||
mod ecc;
|
||||
mod pedersen_hash;
|
||||
|
||||
// π_A + π_B + π_C
|
||||
pub(crate) const GROTH_PROOF_SIZE: usize = 48 + 96 + 48;
|
||||
|
||||
/// The opening (value and randomness) of a Sapling value commitment.
|
||||
#[derive(Clone)]
|
||||
pub struct ValueCommitmentOpening {
|
||||
|
@ -565,7 +562,10 @@ impl SpendParameters {
|
|||
/// Only set `verify_point_encodings` to false if you are verifying the parameters in
|
||||
/// another way (such as checking the hash of the parameters file on disk).
|
||||
pub fn read<R: io::Read>(reader: R, verify_point_encodings: bool) -> io::Result<Self> {
|
||||
groth16::Parameters::<Bls12>::read(reader, verify_point_encodings).map(Self)
|
||||
Ok(Self(groth16::Parameters::<Bls12>::read(
|
||||
reader,
|
||||
verify_point_encodings,
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Returns the verifying key for the Sapling Spend circuit.
|
||||
|
@ -703,7 +703,7 @@ fn test_input_circuit_with_bls12_381() {
|
|||
let mut rhs = uncle;
|
||||
|
||||
if b {
|
||||
::std::mem::swap(&mut lhs, &mut rhs);
|
||||
::core::mem::swap(&mut lhs, &mut rhs);
|
||||
}
|
||||
|
||||
let lhs = lhs.to_le_bits();
|
||||
|
@ -886,7 +886,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
|
|||
let mut rhs = uncle;
|
||||
|
||||
if b {
|
||||
::std::mem::swap(&mut lhs, &mut rhs);
|
||||
::core::mem::swap(&mut lhs, &mut rhs);
|
||||
}
|
||||
|
||||
let lhs = lhs.to_le_bits();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use crate::constants::{PEDERSEN_HASH_CHUNKS_PER_GENERATOR, PEDERSEN_HASH_GENERATORS};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use bls12_381::Scalar;
|
||||
use group::{ff::Field, Curve, Group};
|
||||
use jubjub::ExtendedPoint;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Gadgets implementing Jubjub elliptic curve operations.
|
||||
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
|
||||
use bellman::{ConstraintSystem, SynthesisError};
|
||||
|
||||
|
@ -620,6 +621,7 @@ impl MontgomeryPoint {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use alloc::vec::Vec;
|
||||
use bellman::ConstraintSystem;
|
||||
use group::{
|
||||
ff::{Field, PrimeField, PrimeFieldBits},
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use super::ecc::{EdwardsPoint, MontgomeryPoint};
|
||||
pub use crate::pedersen_hash::Personalization;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use bellman::gadgets::boolean::Boolean;
|
||||
use bellman::gadgets::lookup::*;
|
||||
use bellman::{ConstraintSystem, SynthesisError};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Various constants used by the Sapling protocol.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use ff::PrimeField;
|
||||
use group::Group;
|
||||
use jubjub::SubgroupPoint;
|
||||
|
@ -38,6 +39,9 @@ pub const VALUE_COMMITMENT_GENERATOR_PERSONALIZATION: &[u8; 8] = b"Zcash_cv";
|
|||
/// BLAKE2s Personalization for the nullifier position generator (for computing rho)
|
||||
pub const NULLIFIER_POSITION_IN_TREE_GENERATOR_PERSONALIZATION: &[u8; 8] = b"Zcash_J_";
|
||||
|
||||
// π_A + π_B + π_C
|
||||
pub(crate) const GROTH_PROOF_SIZE: usize = 48 + 96 + 48;
|
||||
|
||||
/// The prover will demonstrate knowledge of discrete log with respect to this base when
|
||||
/// they are constructing a proof, in order to authorize proof construction.
|
||||
pub const PROOF_GENERATION_KEY_GENERATOR: SubgroupPoint = SubgroupPoint::from_raw_unchecked(
|
||||
|
|
11
src/keys.rs
11
src/keys.rs
|
@ -4,8 +4,9 @@
|
|||
//!
|
||||
//! [section 4.2.2]: https://zips.z.cash/protocol/protocol.pdf#saplingkeycomponents
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, Read, Write};
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use core2::io::{self, Read, Write};
|
||||
|
||||
use super::{
|
||||
address::PaymentAddress,
|
||||
|
@ -26,7 +27,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
|||
use zcash_note_encryption::EphemeralKeyBytes;
|
||||
use zcash_spec::PrfExpand;
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(all(feature = "circuit", test))]
|
||||
use rand_core::RngCore;
|
||||
|
||||
/// Errors that can occur in the decoding of Sapling spending keys.
|
||||
|
@ -153,7 +154,7 @@ impl Eq for SpendValidatingKey {}
|
|||
|
||||
impl SpendValidatingKey {
|
||||
/// For circuit tests only.
|
||||
#[cfg(test)]
|
||||
#[cfg(all(feature = "circuit", test))]
|
||||
pub(crate) fn fake_random<R: RngCore>(mut rng: R) -> Self {
|
||||
loop {
|
||||
if let Some(k) = Self::from_bytes(&jubjub::SubgroupPoint::random(&mut rng).to_bytes()) {
|
||||
|
@ -444,6 +445,7 @@ impl SaplingIvk {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct PreparedIncomingViewingKey(PreparedScalar);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl memuse::DynamicUsage for PreparedIncomingViewingKey {
|
||||
fn dynamic_usage(&self) -> usize {
|
||||
self.0.dynamic_usage()
|
||||
|
@ -690,6 +692,7 @@ pub mod testing {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloc::string::ToString;
|
||||
use group::{Group, GroupEncoding};
|
||||
|
||||
use super::{FullViewingKey, SpendAuthorizingKey, SpendValidatingKey};
|
||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -7,18 +7,27 @@
|
|||
//! shielded payment address; we implicitly mean it is an Sapling payment address (as
|
||||
//! opposed to e.g. an Orchard payment address, which is also shielded).
|
||||
//!
|
||||
//! ## Feature flags
|
||||
#![doc = document_features::document_features!()]
|
||||
#![cfg_attr(feature = "std", doc = "## Feature flags")]
|
||||
#![cfg_attr(feature = "std", doc = document_features::document_features!())]
|
||||
//!
|
||||
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
// Catch documentation errors caused by code changes.
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
mod address;
|
||||
pub mod builder;
|
||||
pub mod bundle;
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
pub mod circuit;
|
||||
pub mod constants;
|
||||
pub mod group_hash;
|
||||
|
@ -27,11 +36,13 @@ pub mod note;
|
|||
pub mod note_encryption;
|
||||
pub mod pczt;
|
||||
pub mod pedersen_hash;
|
||||
#[cfg(feature = "circuit")]
|
||||
pub mod prover;
|
||||
mod spec;
|
||||
mod tree;
|
||||
pub mod util;
|
||||
pub mod value;
|
||||
#[cfg(feature = "circuit")]
|
||||
mod verifier;
|
||||
pub mod zip32;
|
||||
|
||||
|
@ -43,6 +54,8 @@ pub use tree::{
|
|||
merkle_hash, Anchor, CommitmentTree, IncrementalWitness, MerklePath, Node,
|
||||
NOTE_COMMITMENT_TREE_DEPTH,
|
||||
};
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
pub use verifier::{BatchValidator, SaplingVerificationContext};
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::array::TryFromSliceError;
|
||||
use std::fmt;
|
||||
use alloc::fmt;
|
||||
use alloc::vec::Vec;
|
||||
use core::array::TryFromSliceError;
|
||||
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//!
|
||||
//! NB: the example code is only covering the post-Canopy case.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use ff::PrimeField;
|
||||
use memuse::DynamicUsage;
|
||||
use rand_core::RngCore;
|
||||
|
@ -193,9 +193,7 @@ impl Domain for SaplingDomain {
|
|||
Rseed::AfterZip212(_) => 2,
|
||||
};
|
||||
input[1..12].copy_from_slice(¬e.recipient().diversifier().0);
|
||||
(&mut input[12..20])
|
||||
.write_u64::<LittleEndian>(note.value().inner())
|
||||
.unwrap();
|
||||
input[12..20].copy_from_slice(¬e.value().inner().to_le_bytes());
|
||||
|
||||
match note.rseed() {
|
||||
Rseed::BeforeZip212(rcm) => {
|
||||
|
@ -462,6 +460,7 @@ pub fn try_sapling_output_recovery(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloc::vec::Vec;
|
||||
use chacha20poly1305::{
|
||||
aead::{AeadInPlace, KeyInit},
|
||||
ChaCha20Poly1305,
|
||||
|
@ -486,7 +485,7 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
bundle::{GrothProofBytes, OutputDescription},
|
||||
circuit::GROTH_PROOF_SIZE,
|
||||
constants::GROTH_PROOF_SIZE,
|
||||
keys::{DiversifiedTransmissionKey, EphemeralSecretKey, OutgoingViewingKey},
|
||||
note::ExtractedNoteCommitment,
|
||||
note_encryption::PreparedIncomingViewingKey,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! PCZT support for Sapling.
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use getset::Getters;
|
||||
use redjubjub::{Binding, SpendAuth};
|
||||
|
@ -30,7 +32,9 @@ pub use io_finalizer::IoFinalizerError;
|
|||
mod updater;
|
||||
pub use updater::{OutputUpdater, SpendUpdater, Updater, UpdaterError};
|
||||
|
||||
#[cfg(feature = "circuit")]
|
||||
mod prover;
|
||||
#[cfg(feature = "circuit")]
|
||||
pub use prover::ProverError;
|
||||
|
||||
mod signer;
|
||||
|
@ -277,7 +281,7 @@ pub struct Output {
|
|||
}
|
||||
|
||||
impl fmt::Debug for Output {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("Output")
|
||||
.field("cv", &self.cv)
|
||||
.field("cmu", &self.cmu)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use alloc::vec::Vec;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
|
||||
use crate::value::{CommitmentSum, TrapdoorSum};
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::collections::BTreeMap;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use ff::PrimeField;
|
||||
use zcash_note_encryption::{EphemeralKeyBytes, OutgoingCipherKey};
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::ProofGenerationKey;
|
||||
|
||||
use super::{Bundle, Output, Spend, Zip32Derivation};
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
#[cfg(test)]
|
||||
pub(crate) mod test_vectors;
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::{AddAssign, Neg};
|
||||
use ff::PrimeField;
|
||||
use group::Group;
|
||||
use std::ops::{AddAssign, Neg};
|
||||
|
||||
use super::constants::{
|
||||
PEDERSEN_HASH_CHUNKS_PER_GENERATOR, PEDERSEN_HASH_EXP_TABLE, PEDERSEN_HASH_EXP_WINDOW_SIZE,
|
||||
};
|
||||
use super::constants::{PEDERSEN_HASH_CHUNKS_PER_GENERATOR, PEDERSEN_HASH_EXP_WINDOW_SIZE};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Personalization {
|
||||
|
@ -41,7 +39,7 @@ where
|
|||
.chain(bits.into_iter());
|
||||
|
||||
let mut result = jubjub::SubgroupPoint::identity();
|
||||
let mut generators = PEDERSEN_HASH_EXP_TABLE.iter();
|
||||
let mut generators = crate::constants::PEDERSEN_HASH_EXP_TABLE.iter();
|
||||
|
||||
loop {
|
||||
let mut acc = jubjub::Fr::zero();
|
||||
|
@ -94,7 +92,9 @@ where
|
|||
let acc = acc.to_repr();
|
||||
let num_limbs: usize = acc.as_ref().len() / 8;
|
||||
let mut limbs = vec![0u64; num_limbs + 1];
|
||||
LittleEndian::read_u64_into(acc.as_ref(), &mut limbs[..num_limbs]);
|
||||
for (src, dst) in acc.chunks_exact(8).zip(limbs[..num_limbs].iter_mut()) {
|
||||
*dst = u64::from_le_bytes(src.try_into().expect("correct length"));
|
||||
}
|
||||
|
||||
let mut tmp = jubjub::SubgroupPoint::identity();
|
||||
|
||||
|
@ -124,6 +124,7 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use alloc::string::ToString;
|
||||
use group::Curve;
|
||||
|
||||
use super::*;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Test vectors from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/sapling_pedersen.py
|
||||
|
||||
use super::{test::TestVector, Personalization};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub fn get_vectors<'a>() -> Vec<TestVector<'a>> {
|
||||
vec![
|
||||
|
|
|
@ -6,7 +6,8 @@ use rand_core::RngCore;
|
|||
|
||||
use crate::{
|
||||
bundle::GrothProofBytes,
|
||||
circuit::{self, GROTH_PROOF_SIZE},
|
||||
circuit,
|
||||
constants::GROTH_PROOF_SIZE,
|
||||
keys::EphemeralSecretKey,
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
MerklePath,
|
||||
|
@ -179,7 +180,8 @@ pub mod mock {
|
|||
use super::{OutputProver, SpendProver};
|
||||
use crate::{
|
||||
bundle::GrothProofBytes,
|
||||
circuit::{self, ValueCommitmentOpening, GROTH_PROOF_SIZE},
|
||||
circuit::{self, ValueCommitmentOpening},
|
||||
constants::GROTH_PROOF_SIZE,
|
||||
keys::EphemeralSecretKey,
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
Diversifier, MerklePath, PaymentAddress, ProofGenerationKey, Rseed,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use alloc::vec::Vec;
|
||||
|
||||
pub(crate) struct TestVector {
|
||||
pub ovk: [u8; 32],
|
||||
pub ivk: [u8; 32],
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use alloc::vec::Vec;
|
||||
|
||||
pub(crate) struct TestVector {
|
||||
pub(crate) sk: [u8; 32],
|
||||
pub(crate) vk: [u8; 32],
|
||||
|
|
22
src/tree.rs
22
src/tree.rs
|
@ -4,7 +4,8 @@ use incrementalmerkletree::{Hashable, Level};
|
|||
use lazy_static::lazy_static;
|
||||
use subtle::CtOption;
|
||||
|
||||
use std::fmt;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
|
||||
use super::{
|
||||
note::ExtractedNoteCommitment,
|
||||
|
@ -20,14 +21,16 @@ pub type MerklePath = incrementalmerkletree::MerklePath<Node, NOTE_COMMITMENT_TR
|
|||
|
||||
lazy_static! {
|
||||
static ref UNCOMMITTED_SAPLING: bls12_381::Scalar = bls12_381::Scalar::one();
|
||||
static ref EMPTY_ROOTS: Vec<Node> = {
|
||||
let mut v = vec![Node::empty_leaf()];
|
||||
for d in 0..NOTE_COMMITMENT_TREE_DEPTH {
|
||||
let next = Node::combine(d.into(), &v[usize::from(d)], &v[usize::from(d)]);
|
||||
v.push(next);
|
||||
}
|
||||
v
|
||||
};
|
||||
static ref EMPTY_ROOTS: Vec<Node> = empty_roots();
|
||||
}
|
||||
|
||||
fn empty_roots() -> Vec<Node> {
|
||||
let mut v = vec![Node::empty_leaf()];
|
||||
for d in 0..NOTE_COMMITMENT_TREE_DEPTH {
|
||||
let next = Node::combine(d.into(), &v[usize::from(d)], &v[usize::from(d)]);
|
||||
v.push(next);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
/// Compute a parent node in the Sapling commitment tree given its two children.
|
||||
|
@ -144,6 +147,7 @@ impl Node {
|
|||
}
|
||||
|
||||
/// Returns the wrapped value
|
||||
#[cfg(feature = "circuit")]
|
||||
pub(crate) fn inner(&self) -> &jubjub::Base {
|
||||
&self.0
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ impl fmt::Display for OverflowError {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for OverflowError {}
|
||||
|
||||
/// A sum of Sapling note values.
|
||||
|
|
|
@ -140,7 +140,10 @@ impl BatchValidator {
|
|||
}
|
||||
|
||||
if let Err(e) = self.signatures.verify(&mut rng) {
|
||||
#[cfg(feature = "std")]
|
||||
tracing::debug!("Signature batch validation failed: {}", e);
|
||||
#[cfg(not(feature = "std"))]
|
||||
tracing::debug!("Signature batch validation failed: {:?}", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
58
src/zip32.rs
58
src/zip32.rs
|
@ -6,14 +6,13 @@
|
|||
|
||||
use aes::Aes256;
|
||||
use blake2b_simd::Params as Blake2bParams;
|
||||
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use fpe::ff1::{BinaryNumeralString, FF1};
|
||||
use subtle::CtOption;
|
||||
use zcash_spec::PrfExpand;
|
||||
use zip32::{ChainCode, ChildIndex, DiversifierIndex, Scope};
|
||||
|
||||
use std::io::{self, Read, Write};
|
||||
use std::ops::AddAssign;
|
||||
use core::ops::AddAssign;
|
||||
use core2::io::{self, Read, Write};
|
||||
|
||||
use super::{Diversifier, NullifierDerivingKey, PaymentAddress, ViewingKey};
|
||||
use crate::note_encryption::PreparedIncomingViewingKey;
|
||||
|
@ -269,7 +268,7 @@ pub struct ExtendedSpendingKey {
|
|||
dk: DiversifierKey,
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for ExtendedSpendingKey {
|
||||
impl core::cmp::PartialEq for ExtendedSpendingKey {
|
||||
fn eq(&self, rhs: &ExtendedSpendingKey) -> bool {
|
||||
self.depth == rhs.depth
|
||||
&& self.parent_fvk_tag == rhs.parent_fvk_tag
|
||||
|
@ -282,8 +281,8 @@ impl std::cmp::PartialEq for ExtendedSpendingKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ExtendedSpendingKey {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
impl core::fmt::Debug for ExtendedSpendingKey {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
write!(
|
||||
f,
|
||||
"ExtendedSpendingKey(d = {}, tag_p = {:?}, i = {:?})",
|
||||
|
@ -354,17 +353,20 @@ impl ExtendedSpendingKey {
|
|||
/// Reads and decodes the encoded form of the extended spending key as defined in
|
||||
/// [ZIP 32](https://zips.z.cash/zip-0032) from the provided reader.
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let depth = reader.read_u8()?;
|
||||
let mut depth = [0; 1];
|
||||
reader.read_exact(&mut depth)?;
|
||||
let depth = depth[0];
|
||||
let mut tag = [0; 4];
|
||||
reader.read_exact(&mut tag)?;
|
||||
let child_index = reader.read_u32::<LittleEndian>().and_then(|i| {
|
||||
KeyIndex::new(depth, i).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Unsupported,
|
||||
let mut child_index_bytes = [0; 4];
|
||||
reader.read_exact(&mut child_index_bytes)?;
|
||||
let child_index =
|
||||
KeyIndex::new(depth, u32::from_le_bytes(child_index_bytes)).ok_or_else(|| {
|
||||
core2::io::Error::new(
|
||||
core2::io::ErrorKind::InvalidData,
|
||||
"Unsupported child index in encoding",
|
||||
)
|
||||
})
|
||||
})?;
|
||||
})?;
|
||||
let mut c = [0; 32];
|
||||
reader.read_exact(&mut c)?;
|
||||
let expsk = ExpandedSpendingKey::read(&mut reader)?;
|
||||
|
@ -419,8 +421,7 @@ impl ExtendedSpendingKey {
|
|||
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
||||
let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
|
||||
let tmp = {
|
||||
let mut le_i = [0; 4];
|
||||
LittleEndian::write_u32(&mut le_i, i.index());
|
||||
let le_i = i.index().to_le_bytes();
|
||||
PrfExpand::SAPLING_ZIP32_CHILD_HARDENED.with(
|
||||
self.chain_code.as_bytes(),
|
||||
&self.expsk.to_bytes(),
|
||||
|
@ -529,7 +530,7 @@ pub struct ExtendedFullViewingKey {
|
|||
pub(crate) dk: DiversifierKey,
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for ExtendedFullViewingKey {
|
||||
impl core::cmp::PartialEq for ExtendedFullViewingKey {
|
||||
fn eq(&self, rhs: &ExtendedFullViewingKey) -> bool {
|
||||
self.depth == rhs.depth
|
||||
&& self.parent_fvk_tag == rhs.parent_fvk_tag
|
||||
|
@ -542,8 +543,8 @@ impl std::cmp::PartialEq for ExtendedFullViewingKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ExtendedFullViewingKey {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
impl core::fmt::Debug for ExtendedFullViewingKey {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
write!(
|
||||
f,
|
||||
"ExtendedFullViewingKey(d = {}, tag_p = {:?}, i = {:?})",
|
||||
|
@ -554,17 +555,20 @@ impl std::fmt::Debug for ExtendedFullViewingKey {
|
|||
|
||||
impl ExtendedFullViewingKey {
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let depth = reader.read_u8()?;
|
||||
let mut depth = [0; 1];
|
||||
reader.read_exact(&mut depth)?;
|
||||
let depth = depth[0];
|
||||
let mut tag = [0; 4];
|
||||
reader.read_exact(&mut tag)?;
|
||||
let child_index = reader.read_u32::<LittleEndian>().and_then(|i| {
|
||||
KeyIndex::new(depth, i).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Unsupported,
|
||||
let mut child_index_bytes = [0; 4];
|
||||
reader.read_exact(&mut child_index_bytes)?;
|
||||
let child_index =
|
||||
KeyIndex::new(depth, u32::from_le_bytes(child_index_bytes)).ok_or_else(|| {
|
||||
core2::io::Error::new(
|
||||
core2::io::ErrorKind::InvalidData,
|
||||
"Unsupported child index in encoding",
|
||||
)
|
||||
})
|
||||
})?;
|
||||
})?;
|
||||
let mut c = [0; 32];
|
||||
reader.read_exact(&mut c)?;
|
||||
let fvk = FullViewingKey::read(&mut reader)?;
|
||||
|
@ -582,9 +586,9 @@ impl ExtendedFullViewingKey {
|
|||
}
|
||||
|
||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
writer.write_u8(self.depth)?;
|
||||
writer.write_all(&[self.depth])?;
|
||||
writer.write_all(&self.parent_fvk_tag.0)?;
|
||||
writer.write_u32::<LittleEndian>(self.child_index.index())?;
|
||||
writer.write_all(&self.child_index.index().to_le_bytes())?;
|
||||
writer.write_all(self.chain_code.as_bytes())?;
|
||||
writer.write_all(&self.fvk.to_bytes())?;
|
||||
writer.write_all(&self.dk.0)?;
|
||||
|
|
Loading…
Reference in New Issue