adds revealing tx ids for nullifiers in finalized and non-finalized states
This commit is contained in:
parent
2c6bac8f13
commit
69035327e2
|
@ -1,9 +1,9 @@
|
||||||
//! Checks for nullifier uniqueness.
|
//! Checks for nullifier uniqueness.
|
||||||
|
|
||||||
use std::{collections::HashSet, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
use zebra_chain::transaction::Transaction;
|
use zebra_chain::transaction::{self, Transaction};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::DuplicateNullifierError,
|
error::DuplicateNullifierError,
|
||||||
|
@ -105,19 +105,22 @@ pub(crate) fn tx_no_duplicates_in_chain(
|
||||||
find_duplicate_nullifier(
|
find_duplicate_nullifier(
|
||||||
transaction.sprout_nullifiers(),
|
transaction.sprout_nullifiers(),
|
||||||
|nullifier| finalized_chain.contains_sprout_nullifier(nullifier),
|
|nullifier| finalized_chain.contains_sprout_nullifier(nullifier),
|
||||||
non_finalized_chain.map(|chain| |nullifier| chain.sprout_nullifiers.contains(nullifier)),
|
non_finalized_chain
|
||||||
|
.map(|chain| |nullifier| chain.sprout_nullifiers.contains_key(nullifier)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
find_duplicate_nullifier(
|
find_duplicate_nullifier(
|
||||||
transaction.sapling_nullifiers(),
|
transaction.sapling_nullifiers(),
|
||||||
|nullifier| finalized_chain.contains_sapling_nullifier(nullifier),
|
|nullifier| finalized_chain.contains_sapling_nullifier(nullifier),
|
||||||
non_finalized_chain.map(|chain| |nullifier| chain.sapling_nullifiers.contains(nullifier)),
|
non_finalized_chain
|
||||||
|
.map(|chain| |nullifier| chain.sapling_nullifiers.contains_key(nullifier)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
find_duplicate_nullifier(
|
find_duplicate_nullifier(
|
||||||
transaction.orchard_nullifiers(),
|
transaction.orchard_nullifiers(),
|
||||||
|nullifier| finalized_chain.contains_orchard_nullifier(nullifier),
|
|nullifier| finalized_chain.contains_orchard_nullifier(nullifier),
|
||||||
non_finalized_chain.map(|chain| |nullifier| chain.orchard_nullifiers.contains(nullifier)),
|
non_finalized_chain
|
||||||
|
.map(|chain| |nullifier| chain.orchard_nullifiers.contains_key(nullifier)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -156,8 +159,9 @@ pub(crate) fn tx_no_duplicates_in_chain(
|
||||||
/// [5]: service::non_finalized_state::Chain
|
/// [5]: service::non_finalized_state::Chain
|
||||||
#[tracing::instrument(skip(chain_nullifiers, shielded_data_nullifiers))]
|
#[tracing::instrument(skip(chain_nullifiers, shielded_data_nullifiers))]
|
||||||
pub(crate) fn add_to_non_finalized_chain_unique<'block, NullifierT>(
|
pub(crate) fn add_to_non_finalized_chain_unique<'block, NullifierT>(
|
||||||
chain_nullifiers: &mut HashSet<NullifierT>,
|
chain_nullifiers: &mut HashMap<NullifierT, transaction::Hash>,
|
||||||
shielded_data_nullifiers: impl IntoIterator<Item = &'block NullifierT>,
|
shielded_data_nullifiers: impl IntoIterator<Item = &'block NullifierT>,
|
||||||
|
revealing_tx_id: transaction::Hash,
|
||||||
) -> Result<(), ValidateContextError>
|
) -> Result<(), ValidateContextError>
|
||||||
where
|
where
|
||||||
NullifierT: DuplicateNullifierError + Copy + std::fmt::Debug + Eq + std::hash::Hash + 'block,
|
NullifierT: DuplicateNullifierError + Copy + std::fmt::Debug + Eq + std::hash::Hash + 'block,
|
||||||
|
@ -166,7 +170,10 @@ where
|
||||||
trace!(?nullifier, "adding nullifier");
|
trace!(?nullifier, "adding nullifier");
|
||||||
|
|
||||||
// reject the nullifier if it is already present in this non-finalized chain
|
// reject the nullifier if it is already present in this non-finalized chain
|
||||||
if !chain_nullifiers.insert(*nullifier) {
|
if chain_nullifiers
|
||||||
|
.insert(*nullifier, revealing_tx_id)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
Err(nullifier.duplicate_nullifier_error(false))?;
|
Err(nullifier.duplicate_nullifier_error(false))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +207,7 @@ where
|
||||||
/// [1]: service::non_finalized_state::Chain
|
/// [1]: service::non_finalized_state::Chain
|
||||||
#[tracing::instrument(skip(chain_nullifiers, shielded_data_nullifiers))]
|
#[tracing::instrument(skip(chain_nullifiers, shielded_data_nullifiers))]
|
||||||
pub(crate) fn remove_from_non_finalized_chain<'block, NullifierT>(
|
pub(crate) fn remove_from_non_finalized_chain<'block, NullifierT>(
|
||||||
chain_nullifiers: &mut HashSet<NullifierT>,
|
chain_nullifiers: &mut HashMap<NullifierT, transaction::Hash>,
|
||||||
shielded_data_nullifiers: impl IntoIterator<Item = &'block NullifierT>,
|
shielded_data_nullifiers: impl IntoIterator<Item = &'block NullifierT>,
|
||||||
) where
|
) where
|
||||||
NullifierT: std::fmt::Debug + Eq + std::hash::Hash + 'block,
|
NullifierT: std::fmt::Debug + Eq + std::hash::Hash + 'block,
|
||||||
|
@ -209,7 +216,7 @@ pub(crate) fn remove_from_non_finalized_chain<'block, NullifierT>(
|
||||||
trace!(?nullifier, "removing nullifier");
|
trace!(?nullifier, "removing nullifier");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
chain_nullifiers.remove(nullifier),
|
chain_nullifiers.remove(nullifier).is_some(),
|
||||||
"nullifier must be present if block was added to chain"
|
"nullifier must be present if block was added to chain"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ use zebra_chain::{
|
||||||
parallel::tree::NoteCommitmentTrees,
|
parallel::tree::NoteCommitmentTrees,
|
||||||
sapling, sprout,
|
sapling, sprout,
|
||||||
subtree::{NoteCommitmentSubtreeData, NoteCommitmentSubtreeIndex},
|
subtree::{NoteCommitmentSubtreeData, NoteCommitmentSubtreeIndex},
|
||||||
transaction::Transaction,
|
transaction::{self, Transaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -33,7 +33,7 @@ use crate::{
|
||||||
disk_format::RawBytes,
|
disk_format::RawBytes,
|
||||||
zebra_db::ZebraDb,
|
zebra_db::ZebraDb,
|
||||||
},
|
},
|
||||||
BoxError,
|
BoxError, TransactionLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Doc-only items
|
// Doc-only items
|
||||||
|
@ -61,6 +61,42 @@ impl ZebraDb {
|
||||||
self.db.zs_contains(&orchard_nullifiers, &orchard_nullifier)
|
self.db.zs_contains(&orchard_nullifiers, &orchard_nullifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`transaction::Hash`] of the transaction that revealed
|
||||||
|
/// the given [`sprout::Nullifier`], if it is revealed in the finalized state.
|
||||||
|
#[allow(clippy::unwrap_in_result)]
|
||||||
|
pub fn sprout_revealing_tx_id(
|
||||||
|
&self,
|
||||||
|
sprout_nullifier: &sprout::Nullifier,
|
||||||
|
) -> Option<transaction::Hash> {
|
||||||
|
let sprout_nullifiers = self.db.cf_handle("sprout_nullifiers").unwrap();
|
||||||
|
let revealing_tx_location = self.db.zs_get(&sprout_nullifiers, &sprout_nullifier)?;
|
||||||
|
self.transaction_hash(revealing_tx_location)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`transaction::Hash`] of the transaction that revealed
|
||||||
|
/// the given [`sapling::Nullifier`], if it is revealed in the finalized state.
|
||||||
|
#[allow(clippy::unwrap_in_result)]
|
||||||
|
pub fn sapling_revealing_tx_id(
|
||||||
|
&self,
|
||||||
|
sapling_nullifier: &sapling::Nullifier,
|
||||||
|
) -> Option<transaction::Hash> {
|
||||||
|
let sapling_nullifiers = self.db.cf_handle("sapling_nullifiers").unwrap();
|
||||||
|
let revealing_tx_location = self.db.zs_get(&sapling_nullifiers, &sapling_nullifier)?;
|
||||||
|
self.transaction_hash(revealing_tx_location)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`transaction::Hash`] of the transaction that revealed
|
||||||
|
/// the given [`orchard::Nullifier`], if it is revealed in the finalized state.
|
||||||
|
#[allow(clippy::unwrap_in_result)]
|
||||||
|
pub fn orchard_revealing_tx_id(
|
||||||
|
&self,
|
||||||
|
orchard_nullifier: &orchard::Nullifier,
|
||||||
|
) -> Option<transaction::Hash> {
|
||||||
|
let orchard_nullifiers = self.db.cf_handle("orchard_nullifiers").unwrap();
|
||||||
|
let revealing_tx_location = self.db.zs_get(&orchard_nullifiers, &orchard_nullifier)?;
|
||||||
|
self.transaction_hash(revealing_tx_location)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the finalized state contains `sprout_anchor`.
|
/// Returns `true` if the finalized state contains `sprout_anchor`.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn contains_sprout_anchor(&self, sprout_anchor: &sprout::tree::Root) -> bool {
|
pub fn contains_sprout_anchor(&self, sprout_anchor: &sprout::tree::Root) -> bool {
|
||||||
|
@ -440,11 +476,12 @@ impl DiskWriteBatch {
|
||||||
db: &DiskDb,
|
db: &DiskDb,
|
||||||
finalized: &FinalizedBlock,
|
finalized: &FinalizedBlock,
|
||||||
) -> Result<(), BoxError> {
|
) -> Result<(), BoxError> {
|
||||||
let FinalizedBlock { block, .. } = finalized;
|
let FinalizedBlock { block, height, .. } = finalized;
|
||||||
|
|
||||||
// Index each transaction's shielded data
|
// Index each transaction's shielded data
|
||||||
for transaction in &block.transactions {
|
for (tx_index, transaction) in block.transactions.iter().enumerate() {
|
||||||
self.prepare_nullifier_batch(db, transaction)?;
|
let tx_loc = TransactionLocation::from_usize(*height, tx_index);
|
||||||
|
self.prepare_nullifier_batch(db, transaction, tx_loc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -461,6 +498,7 @@ impl DiskWriteBatch {
|
||||||
&mut self,
|
&mut self,
|
||||||
db: &DiskDb,
|
db: &DiskDb,
|
||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
|
transaction_location: TransactionLocation,
|
||||||
) -> Result<(), BoxError> {
|
) -> Result<(), BoxError> {
|
||||||
let sprout_nullifiers = db.cf_handle("sprout_nullifiers").unwrap();
|
let sprout_nullifiers = db.cf_handle("sprout_nullifiers").unwrap();
|
||||||
let sapling_nullifiers = db.cf_handle("sapling_nullifiers").unwrap();
|
let sapling_nullifiers = db.cf_handle("sapling_nullifiers").unwrap();
|
||||||
|
@ -468,13 +506,13 @@ impl DiskWriteBatch {
|
||||||
|
|
||||||
// Mark sprout, sapling and orchard nullifiers as spent
|
// Mark sprout, sapling and orchard nullifiers as spent
|
||||||
for sprout_nullifier in transaction.sprout_nullifiers() {
|
for sprout_nullifier in transaction.sprout_nullifiers() {
|
||||||
self.zs_insert(&sprout_nullifiers, sprout_nullifier, ());
|
self.zs_insert(&sprout_nullifiers, sprout_nullifier, transaction_location);
|
||||||
}
|
}
|
||||||
for sapling_nullifier in transaction.sapling_nullifiers() {
|
for sapling_nullifier in transaction.sapling_nullifiers() {
|
||||||
self.zs_insert(&sapling_nullifiers, sapling_nullifier, ());
|
self.zs_insert(&sapling_nullifiers, sapling_nullifier, transaction_location);
|
||||||
}
|
}
|
||||||
for orchard_nullifier in transaction.orchard_nullifiers() {
|
for orchard_nullifier in transaction.orchard_nullifiers() {
|
||||||
self.zs_insert(&orchard_nullifiers, orchard_nullifier, ());
|
self.zs_insert(&orchard_nullifiers, orchard_nullifier, transaction_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -540,7 +540,7 @@ impl NonFinalizedState {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn best_contains_sprout_nullifier(&self, sprout_nullifier: &sprout::Nullifier) -> bool {
|
pub fn best_contains_sprout_nullifier(&self, sprout_nullifier: &sprout::Nullifier) -> bool {
|
||||||
self.best_chain()
|
self.best_chain()
|
||||||
.map(|best_chain| best_chain.sprout_nullifiers.contains(sprout_nullifier))
|
.map(|best_chain| best_chain.sprout_nullifiers.contains_key(sprout_nullifier))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +552,11 @@ impl NonFinalizedState {
|
||||||
sapling_nullifier: &zebra_chain::sapling::Nullifier,
|
sapling_nullifier: &zebra_chain::sapling::Nullifier,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.best_chain()
|
self.best_chain()
|
||||||
.map(|best_chain| best_chain.sapling_nullifiers.contains(sapling_nullifier))
|
.map(|best_chain| {
|
||||||
|
best_chain
|
||||||
|
.sapling_nullifiers
|
||||||
|
.contains_key(sapling_nullifier)
|
||||||
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +568,11 @@ impl NonFinalizedState {
|
||||||
orchard_nullifier: &zebra_chain::orchard::Nullifier,
|
orchard_nullifier: &zebra_chain::orchard::Nullifier,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.best_chain()
|
self.best_chain()
|
||||||
.map(|best_chain| best_chain.orchard_nullifiers.contains(orchard_nullifier))
|
.map(|best_chain| {
|
||||||
|
best_chain
|
||||||
|
.orchard_nullifiers
|
||||||
|
.contains_key(orchard_nullifier)
|
||||||
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,11 +177,11 @@ pub struct ChainInner {
|
||||||
// Nullifiers
|
// Nullifiers
|
||||||
//
|
//
|
||||||
/// The Sprout nullifiers revealed by `blocks`.
|
/// The Sprout nullifiers revealed by `blocks`.
|
||||||
pub(crate) sprout_nullifiers: HashSet<sprout::Nullifier>,
|
pub(crate) sprout_nullifiers: HashMap<sprout::Nullifier, transaction::Hash>,
|
||||||
/// The Sapling nullifiers revealed by `blocks`.
|
/// The Sapling nullifiers revealed by `blocks`.
|
||||||
pub(crate) sapling_nullifiers: HashSet<sapling::Nullifier>,
|
pub(crate) sapling_nullifiers: HashMap<sapling::Nullifier, transaction::Hash>,
|
||||||
/// The Orchard nullifiers revealed by `blocks`.
|
/// The Orchard nullifiers revealed by `blocks`.
|
||||||
pub(crate) orchard_nullifiers: HashSet<orchard::Nullifier>,
|
pub(crate) orchard_nullifiers: HashMap<orchard::Nullifier, transaction::Hash>,
|
||||||
|
|
||||||
// Transparent Transfers
|
// Transparent Transfers
|
||||||
// TODO: move to the transparent section
|
// TODO: move to the transparent section
|
||||||
|
@ -1546,10 +1546,13 @@ impl Chain {
|
||||||
self.update_chain_tip_with(&(inputs, &transaction_hash, spent_outputs))?;
|
self.update_chain_tip_with(&(inputs, &transaction_hash, spent_outputs))?;
|
||||||
|
|
||||||
// add the shielded data
|
// add the shielded data
|
||||||
self.update_chain_tip_with(joinsplit_data)?;
|
self.update_chain_tip_with(&(joinsplit_data, &transaction_hash))?;
|
||||||
self.update_chain_tip_with(sapling_shielded_data_per_spend_anchor)?;
|
self.update_chain_tip_with(&(
|
||||||
self.update_chain_tip_with(sapling_shielded_data_shared_anchor)?;
|
sapling_shielded_data_per_spend_anchor,
|
||||||
self.update_chain_tip_with(orchard_shielded_data)?;
|
&transaction_hash,
|
||||||
|
))?;
|
||||||
|
self.update_chain_tip_with(&(sapling_shielded_data_shared_anchor, &transaction_hash))?;
|
||||||
|
self.update_chain_tip_with(&(orchard_shielded_data, &transaction_hash))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the chain value pool balances
|
// update the chain value pool balances
|
||||||
|
@ -1704,10 +1707,17 @@ impl UpdateWith<ContextuallyVerifiedBlock> for Chain {
|
||||||
);
|
);
|
||||||
|
|
||||||
// remove the shielded data
|
// remove the shielded data
|
||||||
self.revert_chain_with(joinsplit_data, position);
|
|
||||||
self.revert_chain_with(sapling_shielded_data_per_spend_anchor, position);
|
self.revert_chain_with(&(joinsplit_data, transaction_hash), position);
|
||||||
self.revert_chain_with(sapling_shielded_data_shared_anchor, position);
|
self.revert_chain_with(
|
||||||
self.revert_chain_with(orchard_shielded_data, position);
|
&(sapling_shielded_data_per_spend_anchor, transaction_hash),
|
||||||
|
position,
|
||||||
|
);
|
||||||
|
self.revert_chain_with(
|
||||||
|
&(sapling_shielded_data_shared_anchor, transaction_hash),
|
||||||
|
position,
|
||||||
|
);
|
||||||
|
self.revert_chain_with(&(orchard_shielded_data, transaction_hash), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move these to the shielded UpdateWith.revert...()?
|
// TODO: move these to the shielded UpdateWith.revert...()?
|
||||||
|
@ -1939,11 +1949,19 @@ impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateWith<Option<transaction::JoinSplitData<Groth16Proof>>> for Chain {
|
impl
|
||||||
|
UpdateWith<(
|
||||||
|
&Option<transaction::JoinSplitData<Groth16Proof>>,
|
||||||
|
&transaction::Hash,
|
||||||
|
)> for Chain
|
||||||
|
{
|
||||||
#[instrument(skip(self, joinsplit_data))]
|
#[instrument(skip(self, joinsplit_data))]
|
||||||
fn update_chain_tip_with(
|
fn update_chain_tip_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
joinsplit_data: &Option<transaction::JoinSplitData<Groth16Proof>>,
|
&(joinsplit_data, revealing_tx_id): &(
|
||||||
|
&Option<transaction::JoinSplitData<Groth16Proof>>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
) -> Result<(), ValidateContextError> {
|
) -> Result<(), ValidateContextError> {
|
||||||
if let Some(joinsplit_data) = joinsplit_data {
|
if let Some(joinsplit_data) = joinsplit_data {
|
||||||
// We do note commitment tree updates in parallel rayon threads.
|
// We do note commitment tree updates in parallel rayon threads.
|
||||||
|
@ -1951,6 +1969,7 @@ impl UpdateWith<Option<transaction::JoinSplitData<Groth16Proof>>> for Chain {
|
||||||
check::nullifier::add_to_non_finalized_chain_unique(
|
check::nullifier::add_to_non_finalized_chain_unique(
|
||||||
&mut self.sprout_nullifiers,
|
&mut self.sprout_nullifiers,
|
||||||
joinsplit_data.nullifiers(),
|
joinsplit_data.nullifiers(),
|
||||||
|
*revealing_tx_id,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1964,7 +1983,10 @@ impl UpdateWith<Option<transaction::JoinSplitData<Groth16Proof>>> for Chain {
|
||||||
#[instrument(skip(self, joinsplit_data))]
|
#[instrument(skip(self, joinsplit_data))]
|
||||||
fn revert_chain_with(
|
fn revert_chain_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
joinsplit_data: &Option<transaction::JoinSplitData<Groth16Proof>>,
|
&(joinsplit_data, _revealing_tx_id): &(
|
||||||
|
&Option<transaction::JoinSplitData<Groth16Proof>>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
_position: RevertPosition,
|
_position: RevertPosition,
|
||||||
) {
|
) {
|
||||||
if let Some(joinsplit_data) = joinsplit_data {
|
if let Some(joinsplit_data) = joinsplit_data {
|
||||||
|
@ -1980,14 +2002,17 @@ impl UpdateWith<Option<transaction::JoinSplitData<Groth16Proof>>> for Chain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AnchorV> UpdateWith<Option<sapling::ShieldedData<AnchorV>>> for Chain
|
impl<AnchorV> UpdateWith<(&Option<sapling::ShieldedData<AnchorV>>, &transaction::Hash)> for Chain
|
||||||
where
|
where
|
||||||
AnchorV: sapling::AnchorVariant + Clone,
|
AnchorV: sapling::AnchorVariant + Clone,
|
||||||
{
|
{
|
||||||
#[instrument(skip(self, sapling_shielded_data))]
|
#[instrument(skip(self, sapling_shielded_data))]
|
||||||
fn update_chain_tip_with(
|
fn update_chain_tip_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
sapling_shielded_data: &Option<sapling::ShieldedData<AnchorV>>,
|
&(sapling_shielded_data, revealing_tx_id): &(
|
||||||
|
&Option<sapling::ShieldedData<AnchorV>>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
) -> Result<(), ValidateContextError> {
|
) -> Result<(), ValidateContextError> {
|
||||||
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
||||||
// We do note commitment tree updates in parallel rayon threads.
|
// We do note commitment tree updates in parallel rayon threads.
|
||||||
|
@ -1995,6 +2020,7 @@ where
|
||||||
check::nullifier::add_to_non_finalized_chain_unique(
|
check::nullifier::add_to_non_finalized_chain_unique(
|
||||||
&mut self.sapling_nullifiers,
|
&mut self.sapling_nullifiers,
|
||||||
sapling_shielded_data.nullifiers(),
|
sapling_shielded_data.nullifiers(),
|
||||||
|
*revealing_tx_id,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2008,7 +2034,10 @@ where
|
||||||
#[instrument(skip(self, sapling_shielded_data))]
|
#[instrument(skip(self, sapling_shielded_data))]
|
||||||
fn revert_chain_with(
|
fn revert_chain_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
sapling_shielded_data: &Option<sapling::ShieldedData<AnchorV>>,
|
&(sapling_shielded_data, _revealing_tx_id): &(
|
||||||
|
&Option<sapling::ShieldedData<AnchorV>>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
_position: RevertPosition,
|
_position: RevertPosition,
|
||||||
) {
|
) {
|
||||||
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
if let Some(sapling_shielded_data) = sapling_shielded_data {
|
||||||
|
@ -2024,11 +2053,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateWith<Option<orchard::ShieldedData>> for Chain {
|
impl UpdateWith<(&Option<orchard::ShieldedData>, &transaction::Hash)> for Chain {
|
||||||
#[instrument(skip(self, orchard_shielded_data))]
|
#[instrument(skip(self, orchard_shielded_data))]
|
||||||
fn update_chain_tip_with(
|
fn update_chain_tip_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
orchard_shielded_data: &Option<orchard::ShieldedData>,
|
&(orchard_shielded_data, revealing_tx_id): &(
|
||||||
|
&Option<orchard::ShieldedData>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
) -> Result<(), ValidateContextError> {
|
) -> Result<(), ValidateContextError> {
|
||||||
if let Some(orchard_shielded_data) = orchard_shielded_data {
|
if let Some(orchard_shielded_data) = orchard_shielded_data {
|
||||||
// We do note commitment tree updates in parallel rayon threads.
|
// We do note commitment tree updates in parallel rayon threads.
|
||||||
|
@ -2036,6 +2068,7 @@ impl UpdateWith<Option<orchard::ShieldedData>> for Chain {
|
||||||
check::nullifier::add_to_non_finalized_chain_unique(
|
check::nullifier::add_to_non_finalized_chain_unique(
|
||||||
&mut self.orchard_nullifiers,
|
&mut self.orchard_nullifiers,
|
||||||
orchard_shielded_data.nullifiers(),
|
orchard_shielded_data.nullifiers(),
|
||||||
|
*revealing_tx_id,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2049,7 +2082,10 @@ impl UpdateWith<Option<orchard::ShieldedData>> for Chain {
|
||||||
#[instrument(skip(self, orchard_shielded_data))]
|
#[instrument(skip(self, orchard_shielded_data))]
|
||||||
fn revert_chain_with(
|
fn revert_chain_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
orchard_shielded_data: &Option<orchard::ShieldedData>,
|
(orchard_shielded_data, _revealing_tx_id): &(
|
||||||
|
&Option<orchard::ShieldedData>,
|
||||||
|
&transaction::Hash,
|
||||||
|
),
|
||||||
_position: RevertPosition,
|
_position: RevertPosition,
|
||||||
) {
|
) {
|
||||||
if let Some(orchard_shielded_data) = orchard_shielded_data {
|
if let Some(orchard_shielded_data) = orchard_shielded_data {
|
||||||
|
|
Loading…
Reference in New Issue