state: insert into nullifier trees
This commit is contained in:
parent
6758fdbd1c
commit
2095b4f0d3
|
|
@ -31,7 +31,7 @@ fn prf_nf(nk: [u8; 32], rho: [u8; 32]) -> [u8; 32] {
|
||||||
any(test, feature = "proptest-impl"),
|
any(test, feature = "proptest-impl"),
|
||||||
derive(proptest_derive::Arbitrary)
|
derive(proptest_derive::Arbitrary)
|
||||||
)]
|
)]
|
||||||
pub struct Nullifier([u8; 32]);
|
pub struct Nullifier(pub [u8; 32]);
|
||||||
|
|
||||||
impl From<[u8; 32]> for Nullifier {
|
impl From<[u8; 32]> for Nullifier {
|
||||||
fn from(buf: [u8; 32]) -> Self {
|
fn from(buf: [u8; 32]) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl From<NullifierSeed> for [u8; 32] {
|
||||||
any(test, feature = "proptest-impl"),
|
any(test, feature = "proptest-impl"),
|
||||||
derive(proptest_derive::Arbitrary)
|
derive(proptest_derive::Arbitrary)
|
||||||
)]
|
)]
|
||||||
pub struct Nullifier(pub(crate) [u8; 32]);
|
pub struct Nullifier(pub [u8; 32]);
|
||||||
|
|
||||||
impl From<[u8; 32]> for Nullifier {
|
impl From<[u8; 32]> for Nullifier {
|
||||||
fn from(bytes: [u8; 32]) -> Self {
|
fn from(bytes: [u8; 32]) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ use crate::{
|
||||||
block,
|
block,
|
||||||
parameters::NetworkUpgrade,
|
parameters::NetworkUpgrade,
|
||||||
primitives::{Bctv14Proof, Groth16Proof},
|
primitives::{Bctv14Proof, Groth16Proof},
|
||||||
transparent,
|
sapling, sprout, transparent,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A Zcash transaction.
|
/// A Zcash transaction.
|
||||||
|
|
@ -147,6 +147,53 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Access the sprout::Nullifiers in this transaction, regardless of version.
|
||||||
|
pub fn sprout_nullifiers(&self) -> Box<dyn Iterator<Item = &sprout::Nullifier> + '_> {
|
||||||
|
// This function returns a boxed iterator because the different
|
||||||
|
// transaction variants end up having different iterator types
|
||||||
|
match self {
|
||||||
|
// JoinSplits with Bctv14 Proofs
|
||||||
|
Transaction::V2 {
|
||||||
|
joinsplit_data: Some(joinsplit_data),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| Transaction::V3 {
|
||||||
|
joinsplit_data: Some(joinsplit_data),
|
||||||
|
..
|
||||||
|
} => Box::new(
|
||||||
|
joinsplit_data
|
||||||
|
.joinsplits()
|
||||||
|
.flat_map(|joinsplit| joinsplit.nullifiers.iter()),
|
||||||
|
),
|
||||||
|
// JoinSplits with Groth Proofs
|
||||||
|
Transaction::V4 {
|
||||||
|
joinsplit_data: Some(joinsplit_data),
|
||||||
|
..
|
||||||
|
} => Box::new(
|
||||||
|
joinsplit_data
|
||||||
|
.joinsplits()
|
||||||
|
.flat_map(|joinsplit| joinsplit.nullifiers.iter()),
|
||||||
|
),
|
||||||
|
// No JoinSplits
|
||||||
|
_ => Box::new(std::iter::empty()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the sapling::Nullifiers in this transaction, regardless of version.
|
||||||
|
pub fn sapling_nullifiers(&self) -> Box<dyn Iterator<Item = &sapling::Nullifier> + '_> {
|
||||||
|
// This function returns a boxed iterator because the different
|
||||||
|
// transaction variants end up having different iterator types
|
||||||
|
match self {
|
||||||
|
// JoinSplits with Groth Proofs
|
||||||
|
Transaction::V4 {
|
||||||
|
shielded_data: Some(shielded_data),
|
||||||
|
..
|
||||||
|
} => Box::new(shielded_data.nullifiers()),
|
||||||
|
// No JoinSplits
|
||||||
|
_ => Box::new(std::iter::empty()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if transaction contains any coinbase inputs.
|
/// Returns `true` if transaction contains any coinbase inputs.
|
||||||
pub fn contains_coinbase_input(&self) -> bool {
|
pub fn contains_coinbase_input(&self) -> bool {
|
||||||
self.inputs()
|
self.inputs()
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,13 @@ impl ShieldedData {
|
||||||
|
|
||||||
/// Collect the [`Nullifier`]s for this transaction, if it contains
|
/// Collect the [`Nullifier`]s for this transaction, if it contains
|
||||||
/// [`Spend`]s.
|
/// [`Spend`]s.
|
||||||
pub fn nullifiers(&self) -> Vec<Nullifier> {
|
pub fn nullifiers(&self) -> impl Iterator<Item = &Nullifier> {
|
||||||
self.spends().map(|spend| spend.nullifier).collect()
|
self.spends().map(|spend| &spend.nullifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect the cm_u's for this transaction, if it contains [`Output`]s.
|
/// Collect the cm_u's for this transaction, if it contains [`Output`]s.
|
||||||
pub fn note_commitments(&self) -> Vec<jubjub::Fq> {
|
pub fn note_commitments(&self) -> impl Iterator<Item = &jubjub::Fq> {
|
||||||
self.outputs().map(|output| output.cm_u).collect()
|
self.outputs().map(|output| &output.cm_u)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the Spend/Output binding verification key.
|
/// Calculate the Spend/Output binding verification key.
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ pub struct FinalizedState {
|
||||||
block_by_height: sled::Tree,
|
block_by_height: sled::Tree,
|
||||||
tx_by_hash: sled::Tree,
|
tx_by_hash: sled::Tree,
|
||||||
utxo_by_outpoint: sled::Tree,
|
utxo_by_outpoint: sled::Tree,
|
||||||
// sprout_nullifiers: sled::Tree,
|
sprout_nullifiers: sled::Tree,
|
||||||
// sapling_nullifiers: sled::Tree,
|
sapling_nullifiers: sled::Tree,
|
||||||
// sprout_anchors: sled::Tree,
|
// sprout_anchors: sled::Tree,
|
||||||
// sapling_anchors: sled::Tree,
|
// sapling_anchors: sled::Tree,
|
||||||
/// Commit blocks to the finalized state up to this height, then exit Zebra.
|
/// Commit blocks to the finalized state up to this height, then exit Zebra.
|
||||||
|
|
@ -69,8 +69,8 @@ impl FinalizedState {
|
||||||
block_by_height: db.open_tree(b"block_by_height").unwrap(),
|
block_by_height: db.open_tree(b"block_by_height").unwrap(),
|
||||||
tx_by_hash: db.open_tree(b"tx_by_hash").unwrap(),
|
tx_by_hash: db.open_tree(b"tx_by_hash").unwrap(),
|
||||||
utxo_by_outpoint: db.open_tree(b"utxo_by_outpoint").unwrap(),
|
utxo_by_outpoint: db.open_tree(b"utxo_by_outpoint").unwrap(),
|
||||||
// sprout_nullifiers: db.open_tree(b"sprout_nullifiers").unwrap(),
|
sprout_nullifiers: db.open_tree(b"sprout_nullifiers").unwrap(),
|
||||||
// sapling_nullifiers: db.open_tree(b"sapling_nullifiers").unwrap(),
|
sapling_nullifiers: db.open_tree(b"sapling_nullifiers").unwrap(),
|
||||||
debug_stop_at_height: config.debug_stop_at_height.map(block::Height),
|
debug_stop_at_height: config.debug_stop_at_height.map(block::Height),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -97,8 +97,8 @@ impl FinalizedState {
|
||||||
total_flushed += self.block_by_height.flush()?;
|
total_flushed += self.block_by_height.flush()?;
|
||||||
total_flushed += self.tx_by_hash.flush()?;
|
total_flushed += self.tx_by_hash.flush()?;
|
||||||
total_flushed += self.utxo_by_outpoint.flush()?;
|
total_flushed += self.utxo_by_outpoint.flush()?;
|
||||||
// total_flushed += self.sprout_nullifiers.flush()?;
|
total_flushed += self.sprout_nullifiers.flush()?;
|
||||||
// total_flushed += self.sapling_nullifiers.flush()?;
|
total_flushed += self.sapling_nullifiers.flush()?;
|
||||||
|
|
||||||
Ok(total_flushed)
|
Ok(total_flushed)
|
||||||
}
|
}
|
||||||
|
|
@ -221,6 +221,8 @@ impl FinalizedState {
|
||||||
&self.block_by_height,
|
&self.block_by_height,
|
||||||
&self.utxo_by_outpoint,
|
&self.utxo_by_outpoint,
|
||||||
&self.tx_by_hash,
|
&self.tx_by_hash,
|
||||||
|
&self.sprout_nullifiers,
|
||||||
|
&self.sapling_nullifiers,
|
||||||
)
|
)
|
||||||
.transaction(
|
.transaction(
|
||||||
move |(
|
move |(
|
||||||
|
|
@ -229,6 +231,8 @@ impl FinalizedState {
|
||||||
block_by_height,
|
block_by_height,
|
||||||
utxo_by_outpoint,
|
utxo_by_outpoint,
|
||||||
tx_by_hash,
|
tx_by_hash,
|
||||||
|
sprout_nullifiers,
|
||||||
|
sapling_nullifiers,
|
||||||
)| {
|
)| {
|
||||||
// TODO: check highest entry of hash_by_height as in RFC
|
// TODO: check highest entry of hash_by_height as in RFC
|
||||||
|
|
||||||
|
|
@ -248,9 +252,14 @@ impl FinalizedState {
|
||||||
|
|
||||||
utxo_by_outpoint.zs_insert(outpoint, output)?;
|
utxo_by_outpoint.zs_insert(outpoint, output)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for sprout_nullifier in transaction.sprout_nullifiers() {
|
||||||
|
sprout_nullifiers.zs_insert(sprout_nullifier, ())?;
|
||||||
|
}
|
||||||
|
for sapling_nullifier in transaction.sapling_nullifiers() {
|
||||||
|
sapling_nullifiers.zs_insert(sapling_nullifier, ())?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// sprout_nullifiers
|
|
||||||
// sapling_nullifiers
|
|
||||||
|
|
||||||
// for some reason type inference fails here
|
// for some reason type inference fails here
|
||||||
Ok::<_, sled::transaction::ConflictableTransactionError>(hash)
|
Ok::<_, sled::transaction::ConflictableTransactionError>(hash)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ use std::{convert::TryInto, sync::Arc};
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
block,
|
block,
|
||||||
block::Block,
|
block::Block,
|
||||||
|
sapling,
|
||||||
serialization::{ZcashDeserialize, ZcashSerialize},
|
serialization::{ZcashDeserialize, ZcashSerialize},
|
||||||
transaction,
|
sprout, transaction,
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
transparent,
|
transparent,
|
||||||
};
|
};
|
||||||
|
|
@ -89,6 +90,42 @@ impl IntoSled for block::Hash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoSled for &sprout::Nullifier {
|
||||||
|
type Bytes = [u8; 32];
|
||||||
|
|
||||||
|
fn as_bytes(&self) -> Self::Bytes {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_ivec(self) -> sled::IVec {
|
||||||
|
self.as_bytes().as_ref().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoSled for &sapling::Nullifier {
|
||||||
|
type Bytes = [u8; 32];
|
||||||
|
|
||||||
|
fn as_bytes(&self) -> Self::Bytes {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_ivec(self) -> sled::IVec {
|
||||||
|
self.as_bytes().as_ref().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoSled for () {
|
||||||
|
type Bytes = [u8; 0];
|
||||||
|
|
||||||
|
fn as_bytes(&self) -> Self::Bytes {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_ivec(self) -> sled::IVec {
|
||||||
|
sled::IVec::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromSled for block::Hash {
|
impl FromSled for block::Hash {
|
||||||
fn from_ivec(bytes: sled::IVec) -> Result<Self, BoxError> {
|
fn from_ivec(bytes: sled::IVec) -> Result<Self, BoxError> {
|
||||||
let array = bytes.as_ref().try_into().unwrap();
|
let array = bytes.as_ref().try_into().unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue