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`.
|
||||
|
||||
### Added
|
||||
- `sapling_crypto::Anchor`
|
||||
- `sapling_crypto::BatchValidator` (moved from `zcash_proofs::sapling`).
|
||||
- `sapling_crypto::SaplingVerificationContext` (moved from
|
||||
`zcash_proofs::sapling`).
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
|||
CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment, ValueSum,
|
||||
},
|
||||
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
|
||||
|
@ -146,12 +146,12 @@ impl SpendInfo {
|
|||
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 {
|
||||
true
|
||||
} else {
|
||||
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>,
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
bundle_type: BundleType,
|
||||
anchor: Node,
|
||||
anchor: Anchor,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub fn new(
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
bundle_type: BundleType,
|
||||
anchor: Node,
|
||||
anchor: Anchor,
|
||||
) -> Self {
|
||||
Builder {
|
||||
value_balance: ValueSum::zero(),
|
||||
|
@ -502,7 +502,7 @@ pub fn bundle<SP: SpendProver, OP: OutputProver, R: RngCore, V: TryFrom<i64>>(
|
|||
mut rng: R,
|
||||
bundle_type: BundleType,
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
anchor: Node,
|
||||
anchor: Anchor,
|
||||
spends: Vec<SpendInfo>,
|
||||
outputs: Vec<OutputInfo>,
|
||||
) -> Result<Option<(UnauthorizedBundle<V>, SaplingMetadata)>, Error> {
|
||||
|
@ -993,10 +993,10 @@ pub mod testing {
|
|||
testing::{arb_node, arb_note},
|
||||
value::testing::arb_positive_note_value,
|
||||
zip32::testing::arb_extended_spending_key,
|
||||
Node, NOTE_COMMITMENT_TREE_DEPTH,
|
||||
Anchor, Node,
|
||||
};
|
||||
use incrementalmerkletree::{
|
||||
frontier::testing::arb_commitment_tree, witness::IncrementalWitness, Hashable, Level,
|
||||
frontier::testing::arb_commitment_tree, witness::IncrementalWitness,
|
||||
};
|
||||
|
||||
use super::{Builder, BundleType};
|
||||
|
@ -1029,10 +1029,10 @@ pub mod testing {
|
|||
.first()
|
||||
.zip(commitment_trees.first())
|
||||
.map_or_else(
|
||||
|| Node::empty_root(Level::from(NOTE_COMMITMENT_TREE_DEPTH)),
|
||||
|| Anchor::empty_tree(),
|
||||
|(note, tree)| {
|
||||
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);
|
||||
|
|
|
@ -34,7 +34,8 @@ pub use bundle::Bundle;
|
|||
pub use keys::{Diversifier, NullifierDerivingKey, ProofGenerationKey, SaplingIvk, ViewingKey};
|
||||
pub use note::{nullifier::Nullifier, Note, Rseed};
|
||||
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};
|
||||
|
||||
|
|
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()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Node(jubjub::Base);
|
||||
|
|
Loading…
Reference in New Issue