Add `Anchor` type for symmetry with Orchard.
This commit is contained in:
parent
43d4133af4
commit
954a27ee9b
|
@ -10,6 +10,7 @@ The entries below are relative to the `zcash_primitives::sapling` module as of
|
||||||
`zcash_primitives 0.13.0`.
|
`zcash_primitives 0.13.0`.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- `sapling_crypto::Anchor`
|
||||||
- `sapling_crypto::BatchValidator` (moved from `zcash_proofs::sapling`).
|
- `sapling_crypto::BatchValidator` (moved from `zcash_proofs::sapling`).
|
||||||
- `sapling_crypto::SaplingVerificationContext` (moved from
|
- `sapling_crypto::SaplingVerificationContext` (moved from
|
||||||
`zcash_proofs::sapling`).
|
`zcash_proofs::sapling`).
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment, ValueSum,
|
CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment, ValueSum,
|
||||||
},
|
},
|
||||||
zip32::ExtendedSpendingKey,
|
zip32::ExtendedSpendingKey,
|
||||||
Diversifier, MerklePath, Node, Note, PaymentAddress, ProofGenerationKey, SaplingIvk,
|
Anchor, Diversifier, MerklePath, Node, Note, PaymentAddress, ProofGenerationKey, SaplingIvk,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// If there are any shielded inputs, always have at least two shielded outputs, padding
|
/// If there are any shielded inputs, always have at least two shielded outputs, padding
|
||||||
|
@ -146,12 +146,12 @@ impl SpendInfo {
|
||||||
self.note.value()
|
self.note.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_matching_anchor(&self, anchor: &Node) -> bool {
|
fn has_matching_anchor(&self, anchor: &Anchor) -> bool {
|
||||||
if self.note.value() == NoteValue::ZERO {
|
if self.note.value() == NoteValue::ZERO {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let node = Node::from_cmu(&self.note.cmu());
|
let node = Node::from_cmu(&self.note.cmu());
|
||||||
&self.merkle_path.root(node) == anchor
|
&Anchor::from(self.merkle_path.root(node)) == anchor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,14 +384,14 @@ pub struct Builder {
|
||||||
outputs: Vec<OutputInfo>,
|
outputs: Vec<OutputInfo>,
|
||||||
zip212_enforcement: Zip212Enforcement,
|
zip212_enforcement: Zip212Enforcement,
|
||||||
bundle_type: BundleType,
|
bundle_type: BundleType,
|
||||||
anchor: Node,
|
anchor: Anchor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
zip212_enforcement: Zip212Enforcement,
|
zip212_enforcement: Zip212Enforcement,
|
||||||
bundle_type: BundleType,
|
bundle_type: BundleType,
|
||||||
anchor: Node,
|
anchor: Anchor,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Builder {
|
Builder {
|
||||||
value_balance: ValueSum::zero(),
|
value_balance: ValueSum::zero(),
|
||||||
|
@ -502,7 +502,7 @@ pub fn bundle<SP: SpendProver, OP: OutputProver, R: RngCore, V: TryFrom<i64>>(
|
||||||
mut rng: R,
|
mut rng: R,
|
||||||
bundle_type: BundleType,
|
bundle_type: BundleType,
|
||||||
zip212_enforcement: Zip212Enforcement,
|
zip212_enforcement: Zip212Enforcement,
|
||||||
anchor: Node,
|
anchor: Anchor,
|
||||||
spends: Vec<SpendInfo>,
|
spends: Vec<SpendInfo>,
|
||||||
outputs: Vec<OutputInfo>,
|
outputs: Vec<OutputInfo>,
|
||||||
) -> Result<Option<(UnauthorizedBundle<V>, SaplingMetadata)>, Error> {
|
) -> Result<Option<(UnauthorizedBundle<V>, SaplingMetadata)>, Error> {
|
||||||
|
@ -993,10 +993,10 @@ pub mod testing {
|
||||||
testing::{arb_node, arb_note},
|
testing::{arb_node, arb_note},
|
||||||
value::testing::arb_positive_note_value,
|
value::testing::arb_positive_note_value,
|
||||||
zip32::testing::arb_extended_spending_key,
|
zip32::testing::arb_extended_spending_key,
|
||||||
Node, NOTE_COMMITMENT_TREE_DEPTH,
|
Anchor, Node,
|
||||||
};
|
};
|
||||||
use incrementalmerkletree::{
|
use incrementalmerkletree::{
|
||||||
frontier::testing::arb_commitment_tree, witness::IncrementalWitness, Hashable, Level,
|
frontier::testing::arb_commitment_tree, witness::IncrementalWitness,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Builder, BundleType};
|
use super::{Builder, BundleType};
|
||||||
|
@ -1029,10 +1029,10 @@ pub mod testing {
|
||||||
.first()
|
.first()
|
||||||
.zip(commitment_trees.first())
|
.zip(commitment_trees.first())
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| Node::empty_root(Level::from(NOTE_COMMITMENT_TREE_DEPTH)),
|
|| Anchor::empty_tree(),
|
||||||
|(note, tree)| {
|
|(note, tree)| {
|
||||||
let node = Node::from_cmu(¬e.cmu());
|
let node = Node::from_cmu(¬e.cmu());
|
||||||
Node::from_scalar(*tree.root(node).inner())
|
Anchor::from(*tree.root(node).inner())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let mut builder = Builder::new(zip212_enforcement, BundleType::DEFAULT, anchor);
|
let mut builder = Builder::new(zip212_enforcement, BundleType::DEFAULT, anchor);
|
||||||
|
|
|
@ -34,7 +34,8 @@ pub use bundle::Bundle;
|
||||||
pub use keys::{Diversifier, NullifierDerivingKey, ProofGenerationKey, SaplingIvk, ViewingKey};
|
pub use keys::{Diversifier, NullifierDerivingKey, ProofGenerationKey, SaplingIvk, ViewingKey};
|
||||||
pub use note::{nullifier::Nullifier, Note, Rseed};
|
pub use note::{nullifier::Nullifier, Note, Rseed};
|
||||||
pub use tree::{
|
pub use tree::{
|
||||||
merkle_hash, CommitmentTree, IncrementalWitness, MerklePath, Node, NOTE_COMMITMENT_TREE_DEPTH,
|
merkle_hash, Anchor, CommitmentTree, IncrementalWitness, MerklePath, Node,
|
||||||
|
NOTE_COMMITMENT_TREE_DEPTH,
|
||||||
};
|
};
|
||||||
pub use verifier::{BatchValidator, SaplingVerificationContext};
|
pub use verifier::{BatchValidator, SaplingVerificationContext};
|
||||||
|
|
||||||
|
|
37
src/tree.rs
37
src/tree.rs
|
@ -67,6 +67,43 @@ fn merkle_hash_field(depth: usize, lhs: &[u8; 32], rhs: &[u8; 32]) -> jubjub::Ba
|
||||||
.get_u()
|
.get_u()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The root of a Sapling commitment tree.
|
||||||
|
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
|
||||||
|
pub struct Anchor(jubjub::Base);
|
||||||
|
|
||||||
|
impl From<jubjub::Base> for Anchor {
|
||||||
|
fn from(anchor_field: jubjub::Base) -> Anchor {
|
||||||
|
Anchor(anchor_field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Node> for Anchor {
|
||||||
|
fn from(anchor: Node) -> Anchor {
|
||||||
|
Anchor(anchor.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Anchor {
|
||||||
|
/// The anchor of the empty Orchard note commitment tree.
|
||||||
|
///
|
||||||
|
/// This anchor does not correspond to any valid anchor for a spend, so it
|
||||||
|
/// may only be used for coinbase bundles or in circumstances where Orchard
|
||||||
|
/// functionality is not active.
|
||||||
|
pub fn empty_tree() -> Anchor {
|
||||||
|
Anchor(Node::empty_root(NOTE_COMMITMENT_TREE_DEPTH.into()).0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses an Orchard anchor from a byte encoding.
|
||||||
|
pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Anchor> {
|
||||||
|
jubjub::Base::from_repr(bytes).map(Self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the byte encoding of this anchor.
|
||||||
|
pub fn to_bytes(self) -> [u8; 32] {
|
||||||
|
self.0.to_repr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A node within the Sapling commitment tree.
|
/// A node within the Sapling commitment tree.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Node(jubjub::Base);
|
pub struct Node(jubjub::Base);
|
||||||
|
|
Loading…
Reference in New Issue