Skip to content

Commit

Permalink
chore: remove now unused mostly duplicated code
Browse files Browse the repository at this point in the history
  • Loading branch information
grumbach committed May 16, 2024
1 parent dfe90d5 commit 770c5a7
Showing 1 changed file with 3 additions and 138 deletions.
141 changes: 3 additions & 138 deletions sn_client/src/audit/spend_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use crate::{
error::{Error, Result},
Client,
};
use crate::Client;

use futures::future::join_all;
use sn_networking::{target_arch::Instant, GetRecordError, NetworkError};
use sn_transfers::{Hash, SignedSpend, SpendAddress, WalletError, WalletResult};
use sn_transfers::{SpendAddress, WalletError, WalletResult};
use std::{collections::BTreeSet, iter::Iterator};
use tokio::time::Instant;

impl Client {
/// Verify that a spend is valid on the network.
Expand Down Expand Up @@ -125,136 +122,4 @@ impl Client {
println!("Verified all the way to genesis! Through {depth} generations, verifying {n} transactions in {elapsed:?}");
Ok(())
}

/// This function does the opposite of verify_spend.
/// It recursively follows the descendants of a Spend, all the way to unspent Transaction Outputs (UTXOs).
///
/// Prints progress on stdout
///
/// Starting from Genesis, this amounts to Auditing the entire currency.
/// This is how the DAG it follows could look like:
///
/// ```text
/// -> Spend7 ---> UTXO_11
/// /
/// Genesis -> Spend1 -----> Spend2 ---> Spend5 ---> UTXO_10
/// \
/// ---> Spend3 ---> Spend6 ---> UTXO_9
/// \
/// -> Spend4 ---> UTXO_8
///
/// gen0 gen1 gen2 gen3
///
/// ```
///
/// This function will return the UTXOs (Spend addresses not spent yet)
/// Future calls to this function could start from those UTXOs to avoid
/// re-checking all previously checked branches.
pub async fn follow_spend(
&self,
spend_addr: SpendAddress,
) -> WalletResult<BTreeSet<SpendAddress>> {
let first_spend = self
.get_spend_from_network(spend_addr)
.await
.map_err(|err| WalletError::CouldNotVerifyTransfer(err.to_string()))?;
println!("Generation 0 - Found first spend: {spend_addr:#?}");

// use iteration instead of recursion to avoid stack overflow
let mut txs_to_follow = BTreeSet::from_iter([first_spend.spend.spent_tx]);
let mut all_utxos = BTreeSet::new();
let mut verified_tx = BTreeSet::new();
let mut gen = 0;
let start = Instant::now();

while !txs_to_follow.is_empty() {
let mut next_gen_tx = BTreeSet::new();
let mut next_gen_spends = BTreeSet::new();
let mut next_gen_utxos = BTreeSet::new();

for descendant_tx in txs_to_follow.iter() {
let descendant_tx_hash = descendant_tx.hash();
let descendant_keys = descendant_tx
.outputs
.iter()
.map(|output| output.unique_pubkey);
let addrs_to_follow = descendant_keys.map(|k| SpendAddress::from_unique_pubkey(&k));
debug!("Gen {gen} - Following descendant Tx : {descendant_tx_hash:?} with outputs: {addrs_to_follow:?}");

// get all descendant spends in parallel
let tasks: Vec<_> = addrs_to_follow
.clone()
.map(|a| self.get_spend_from_network(a))
.collect();
let spends_res = join_all(tasks)
.await
.into_iter()
.zip(addrs_to_follow)
.collect::<Vec<_>>();

// split spends into utxos and spends
let (utxos, spends) = split_utxos_and_spends(spends_res, gen, descendant_tx_hash)?;
debug!("Gen {gen} - Got {:?} spends and {:?} utxos for descendant Tx: {descendant_tx_hash:?}", spends.len(), utxos.len());
trace!("Spends for {descendant_tx_hash:?} - {spends:?}");
next_gen_utxos.extend(utxos);
next_gen_spends.extend(
spends
.iter()
.map(|s| SpendAddress::from_unique_pubkey(&s.spend.unique_pubkey)),
);

// add new descendant spends to next gen
next_gen_tx.extend(spends.into_iter().map(|s| s.spend.spent_tx));
}

// print stats
gen += 1;
let elapsed = start.elapsed();
let u = next_gen_utxos.len();
let s = next_gen_spends.len();
println!("Generation {gen} - Found {u} UTXOs and {s} Spends in {elapsed:?}");
debug!("Generation {gen} - UTXOs: {:#?}", next_gen_utxos);
debug!("Generation {gen} - Spends: {:#?}", next_gen_spends);
all_utxos.extend(next_gen_utxos);

// only verify tx we haven't already verified
verified_tx.extend(txs_to_follow.iter().map(|tx| tx.hash()));
txs_to_follow = next_gen_tx
.into_iter()
.filter(|tx| !verified_tx.contains(&tx.hash()))
.collect();
}

let elapsed = start.elapsed();
let n = all_utxos.len();
let tx = verified_tx.len();
println!("Finished auditing! Through {gen} generations, found {n} UTXOs and verified {tx} Transactions in {elapsed:?}");
Ok(all_utxos)
}
}

fn split_utxos_and_spends(
spends_res: Vec<(Result<SignedSpend>, SpendAddress)>,
gen: usize,
descendant_tx_hash: Hash,
) -> WalletResult<(Vec<SpendAddress>, Vec<SignedSpend>)> {
let mut utxos = Vec::new();
let mut spends = Vec::new();

for (res, addr) in spends_res {
match res {
Ok(spend) => {
spends.push(spend);
}
Err(Error::Network(NetworkError::GetRecordError(GetRecordError::RecordNotFound))) => {
utxos.push(addr);
}
Err(err) => {
warn!("Error while following spend {addr:?}: {err}");
return Err(WalletError::CouldNotVerifyTransfer(format!("at gen {gen} - Failed to get spend {addr:?} from network for descendant Tx {descendant_tx_hash:?}: {err}")));
}
}
}

Ok((utxos, spends))
}

0 comments on commit 770c5a7

Please sign in to comment.