Skip to content

Commit

Permalink
Cancel out utreexo removals/insertions in the same diff
Browse files Browse the repository at this point in the history
  • Loading branch information
Ash-L2L committed Jan 30, 2025
1 parent 3692b26 commit ad6122b
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 137 deletions.
20 changes: 14 additions & 6 deletions integration_tests/unknown_withdrawal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use bip300301_enforcer_integration_tests::{
use futures::{
channel::mpsc, future::BoxFuture, FutureExt as _, StreamExt as _,
};
use thunder::types::OutPoint;
use thunder_app_rpc_api::RpcClient as _;
use tokio::time::sleep;
use tracing::Instrument as _;
Expand Down Expand Up @@ -118,18 +119,25 @@ async fn unknown_withdrawal_task(
tracing::info!("Deposited to sidechain successfully");
tracing::debug!("Checking that withdrawer sidechain recognizes deposit");
{
let withdrawer_utxos_count =
sidechain_withdrawer.rpc_client.list_utxos().await?.len();
let withdrawer_deposit_utxos_count = sidechain_withdrawer
.rpc_client
.list_utxos()
.await?
.into_iter()
.filter(|utxo| matches!(utxo.outpoint, OutPoint::Deposit(_)))
.count();
sidechain_withdrawer
.bmm_single(&mut enforcer_post_setup)
.await?;
let utxos_count_delta = sidechain_withdrawer
let deposit_utxos_count_delta = sidechain_withdrawer
.rpc_client
.list_utxos()
.await?
.len()
.checked_sub(withdrawer_utxos_count);
anyhow::ensure!(utxos_count_delta == Some(1));
.into_iter()
.filter(|utxo| matches!(utxo.outpoint, OutPoint::Deposit(_)))
.count()
.checked_sub(withdrawer_deposit_utxos_count);
anyhow::ensure!(deposit_utxos_count_delta == Some(1));
}
drop(sidechain_successor);
drop(sidechain_withdrawer);
Expand Down
11 changes: 6 additions & 5 deletions lib/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ use std::collections::VecDeque;

use heed::{types::SerdeBincode, Database, RoTxn, RwTxn};

use crate::types::{Accumulator, AuthorizedTransaction, OutPoint, Txid};
use crate::types::{
Accumulator, AuthorizedTransaction, OutPoint, Txid, UtreexoError,
};

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("heed error")]
Heed(#[from] heed::Error),
#[error("Utreexo error: {0}")]
Utreexo(String),
#[error(transparent)]
Utreexo(#[from] UtreexoError),
#[error("can't add transaction, utxo double spent")]
UtxoDoubleSpent,
}
Expand Down Expand Up @@ -118,8 +120,7 @@ impl MemPool {
.iter()
.map(|(_, utxo_hash)| utxo_hash.into())
.collect();
tx.transaction.proof =
accumulator.0.prove(&targets).map_err(Error::Utreexo)?;
tx.transaction.proof = accumulator.prove(&targets)?;
unsafe { iter.put_current(&txid, &tx) }?;
}
Ok(())
Expand Down
64 changes: 20 additions & 44 deletions lib/state/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use rustreexo::accumulator::node_hash::BitcoinNodeHash;
use crate::{
state::{error, Error, State},
types::{
AmountOverflowError, Body, GetAddress as _, GetValue as _, Header,
InPoint, OutPoint, PointedOutput, SpentOutput, Verify as _,
AccumulatorDiff, AmountOverflowError, Body, GetAddress as _,
GetValue as _, Header, InPoint, OutPoint, PointedOutput, SpentOutput,
Verify as _,
},
util::UnitKey,
wallet::Authorization,
Expand Down Expand Up @@ -42,10 +43,7 @@ pub fn validate(
.utreexo_accumulator
.get(rotxn, &UnitKey)?
.unwrap_or_default();
// New leaves for the accumulator
let mut accumulator_add = Vec::<BitcoinNodeHash>::new();
// Accumulator leaves to delete
let mut accumulator_del = Vec::<BitcoinNodeHash>::new();
let mut accumulator_diff = AccumulatorDiff::default();
let mut coinbase_value = bitcoin::Amount::ZERO;
let merkle_root = body.compute_merkle_root();
if merkle_root != header.merkle_root {
Expand All @@ -67,7 +65,7 @@ pub fn validate(
outpoint,
output: output.clone(),
};
accumulator_add.push((&pointed_output).into());
accumulator_diff.insert((&pointed_output).into());
}
let mut total_fees = bitcoin::Amount::ZERO;
let mut spent_utxos = HashSet::new();
Expand All @@ -86,7 +84,7 @@ pub fn validate(
}
spent_utxos.insert(*outpoint);
spent_utxo_hashes.push(utxo_hash.into());
accumulator_del.push(utxo_hash.into());
accumulator_diff.remove(utxo_hash.into());
}
for (vout, output) in
filled_transaction.transaction.outputs.iter().enumerate()
Expand All @@ -99,16 +97,14 @@ pub fn validate(
outpoint,
output: output.clone(),
};
accumulator_add.push((&pointed_output).into());
accumulator_diff.insert((&pointed_output).into());
}
total_fees = total_fees
.checked_add(state.validate_filled_transaction(filled_transaction)?)
.ok_or(AmountOverflowError)?;
// verify utreexo proof
if !accumulator
.0
.verify(&filled_transaction.transaction.proof, &spent_utxo_hashes)
.map_err(Error::Utreexo)?
.verify(&filled_transaction.transaction.proof, &spent_utxo_hashes)?
{
return Err(Error::UtreexoProofFailed { txid });
}
Expand All @@ -129,16 +125,8 @@ pub fn validate(
if Authorization::verify_body(body).is_err() {
return Err(Error::AuthorizationError);
}
accumulator
.0
.modify(&accumulator_add, &accumulator_del)
.map_err(Error::Utreexo)?;
let roots: Vec<BitcoinNodeHash> = accumulator
.0
.get_roots()
.iter()
.map(|node| node.get_data())
.collect();
let () = accumulator.apply_diff(accumulator_diff)?;
let roots: Vec<BitcoinNodeHash> = accumulator.get_roots();
if roots != header.roots {
return Err(Error::UtreexoRootsMismatch);
}
Expand Down Expand Up @@ -171,10 +159,7 @@ pub fn connect(
.utreexo_accumulator
.get(rwtxn, &UnitKey)?
.unwrap_or_default();
// New leaves for the accumulator
let mut accumulator_add = Vec::<BitcoinNodeHash>::new();
// Accumulator leaves to delete
let mut accumulator_del = Vec::<BitcoinNodeHash>::new();
let mut accumulator_diff = AccumulatorDiff::default();
for (vout, output) in body.coinbase.iter().enumerate() {
let outpoint = OutPoint::Coinbase {
merkle_root,
Expand All @@ -184,7 +169,7 @@ pub fn connect(
outpoint,
output: output.clone(),
};
accumulator_add.push((&pointed_output).into());
accumulator_diff.insert((&pointed_output).into());
state.utxos.put(rwtxn, &outpoint, output)?;
}
for transaction in &body.transactions {
Expand All @@ -196,7 +181,7 @@ pub fn connect(
state.utxos.get(rwtxn, outpoint)?.ok_or(Error::NoUtxo {
outpoint: *outpoint,
})?;
accumulator_del.push(utxo_hash.into());
accumulator_diff.remove(utxo_hash.into());
state.utxos.delete(rwtxn, outpoint)?;
let spent_output = SpentOutput {
output: spent_output,
Expand All @@ -216,18 +201,15 @@ pub fn connect(
outpoint,
output: output.clone(),
};
accumulator_add.push((&pointed_output).into());
accumulator_diff.insert((&pointed_output).into());
state.utxos.put(rwtxn, &outpoint, output)?;
}
}
let block_hash = header.hash();
let height = state.try_get_height(rwtxn)?.map_or(0, |height| height + 1);
state.tip.put(rwtxn, &UnitKey, &block_hash)?;
state.height.put(rwtxn, &UnitKey, &height)?;
accumulator
.0
.modify(&accumulator_add, &accumulator_del)
.map_err(Error::Utreexo)?;
let () = accumulator.apply_diff(accumulator_diff)?;
state
.utreexo_accumulator
.put(rwtxn, &UnitKey, &accumulator)?;
Expand Down Expand Up @@ -261,10 +243,7 @@ pub fn disconnect_tip(
.get(rwtxn, &UnitKey)?
.unwrap_or_default();
tracing::debug!("Got acc");
// New leaves for the accumulator
let mut accumulator_add = Vec::<BitcoinNodeHash>::new();
// Accumulator leaves to delete
let mut accumulator_del = Vec::<BitcoinNodeHash>::new();
let mut accumulator_diff = AccumulatorDiff::default();
// revert txs, last-to-first
body.transactions.iter().rev().try_for_each(|tx| {
let txid = tx.txid();
Expand All @@ -279,7 +258,7 @@ pub fn disconnect_tip(
outpoint,
output: output.clone(),
};
accumulator_del.push((&pointed_output).into());
accumulator_diff.remove((&pointed_output).into());
if state.utxos.delete(rwtxn, &outpoint)? {
Ok(())
} else {
Expand All @@ -293,7 +272,7 @@ pub fn disconnect_tip(
.rev()
.try_for_each(|(outpoint, utxo_hash)| {
if let Some(spent_output) = state.stxos.get(rwtxn, outpoint)? {
accumulator_add.push(utxo_hash.into());
accumulator_diff.insert(utxo_hash.into());
state.stxos.delete(rwtxn, outpoint)?;
state.utxos.put(rwtxn, outpoint, &spent_output.output)?;
Ok(())
Expand All @@ -318,7 +297,7 @@ pub fn disconnect_tip(
outpoint,
output: output.clone(),
};
accumulator_del.push((&pointed_output).into());
accumulator_diff.remove((&pointed_output).into());
if state.utxos.delete(rwtxn, &outpoint)? {
Ok(())
} else {
Expand All @@ -339,10 +318,7 @@ pub fn disconnect_tip(
state.height.put(rwtxn, &UnitKey, &(height - 1))?;
}
}
accumulator
.0
.modify(&accumulator_add, &accumulator_del)
.map_err(Error::Utreexo)?;
let () = accumulator.apply_diff(accumulator_diff)?;
state
.utreexo_accumulator
.put(rwtxn, &UnitKey, &accumulator)?;
Expand Down
6 changes: 3 additions & 3 deletions lib/state/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use thiserror::Error;

use crate::types::{
AmountOverflowError, AmountUnderflowError, BlockHash, M6id, MerkleRoot,
OutPoint, Txid, WithdrawalBundleError,
OutPoint, Txid, UtreexoError, WithdrawalBundleError,
};

#[derive(Debug, Error)]
Expand Down Expand Up @@ -54,8 +54,8 @@ pub enum Error {
NoUtxo { outpoint: OutPoint },
#[error("Withdrawal bundle event block doesn't exist")]
NoWithdrawalBundleEventBlock,
#[error("utreexo error: {0}")]
Utreexo(String),
#[error(transparent)]
Utreexo(#[from] UtreexoError),
#[error("Utreexo proof verification failed for tx {txid}")]
UtreexoProofFailed { txid: Txid },
#[error("Computed Utreexo roots do not match the header roots")]
Expand Down
4 changes: 2 additions & 2 deletions lib/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl State {
.iter()
.map(|(_, utxo_hash)| utxo_hash.into())
.collect();
tx.proof = accumulator.0.prove(&targets).map_err(Error::Utreexo)?;
tx.proof = accumulator.prove(&targets)?;
Ok(())
}

Expand All @@ -216,7 +216,7 @@ impl State {
let accumulator = self.get_accumulator(rotxn)?;
let targets: Vec<BitcoinNodeHash> =
utxos.into_iter().map(BitcoinNodeHash::from).collect();
let proof = accumulator.0.prove(&targets).map_err(Error::Utreexo)?;
let proof = accumulator.prove(&targets)?;
Ok(proof)
}

Expand Down
Loading

0 comments on commit ad6122b

Please sign in to comment.