Skip to content

Commit

Permalink
esplora: fix history reconstruction
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Oct 10, 2023
1 parent e587004 commit 38d1b63
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 28 deletions.
5 changes: 4 additions & 1 deletion cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub enum Command {
#[clap(short = '2')]
v2: bool,

/// Bitcoin invoice, either in form of `<sats>@<address>`. To spend full wallet balance use
/// Bitcoin invoice in form of `<sats>@<address>`. To spend full wallet balance use
/// `MAX` for the amount.
invoice: Invoice,

Expand Down Expand Up @@ -192,6 +192,7 @@ impl<O: DescriptorOpts> Exec for Args<Command, O> {
addr: false,
utxo: false,
};
self.resolver.sync = false;
self.exec(config, name)?;
}
Command::Balance {
Expand All @@ -210,6 +211,7 @@ impl<O: DescriptorOpts> Exec for Args<Command, O> {
addr: false,
utxo: false,
};
self.resolver.sync = false;
self.exec(config, name)?;
}
Command::Balance {
Expand All @@ -229,6 +231,7 @@ impl<O: DescriptorOpts> Exec for Args<Command, O> {
addr: false,
utxo: false,
};
self.resolver.sync = false;
self.exec(config, name)?;
}
Command::Addr {
Expand Down
15 changes: 15 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ impl Inpoint {
pub fn new(txid: Txid, vin: u32) -> Self { Inpoint { txid, vin } }
}

impl From<Outpoint> for Inpoint {
fn from(outpoint: Outpoint) -> Self {
Inpoint {
txid: outpoint.txid,
vin: outpoint.vout.into_u32(),
}
}
}

#[derive(Clone, Eq, PartialEq, Debug, Display, From, Error)]
#[display(doc_comments)]
pub enum InpointParseError {
Expand Down Expand Up @@ -242,6 +251,12 @@ impl Party {
_ => None,
}
}
pub fn from_wallet_addr<T>(wallet_addr: &WalletAddr<T>) -> Self {
Party::Wallet(DerivedAddr {
addr: wallet_addr.addr,
terminal: wallet_addr.terminal,
})
}
}

impl Display for Party {
Expand Down
61 changes: 34 additions & 27 deletions src/indexers/esplora.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use descriptors::Descriptor;
use esplora::{BlockingClient, Error};

use super::BATCH_SIZE;
use crate::data::Inpoint;
use crate::{
Indexer, Layer2, MayError, MiningInfo, Party, TxCredit, TxDebit, TxStatus, WalletAddr,
WalletCache, WalletDescr, WalletTx,
Expand Down Expand Up @@ -133,64 +132,72 @@ impl Indexer for BlockingClient {
}
}

address_index.insert(script, (derive, txids));
let wallet_addr = WalletAddr::<i64>::from(derive);
address_index.insert(script, (wallet_addr, txids));
}
}

// TODO: Update headers & tip

for (script, (addr_info, txids)) in address_index {
let mut wallet_addr = WalletAddr::<i64>::from(addr_info.clone());
for (script, (wallet_addr, txids)) in &mut address_index {
for txid in txids {
let mut tx = cache.tx.remove(&txid).expect("broken logic");
for (vin, credit) in tx.inputs.iter_mut().enumerate() {
let Party::Unknown(ref s) = credit.payer else {
let mut tx = cache.tx.remove(txid).expect("broken logic");
for debit in &mut tx.outputs {
let Party::Unknown(ref s) = debit.beneficiary else {
continue;
};
if s == &script {
credit.payer = Party::Wallet(addr_info.clone());
if s == script {
cache.utxo.insert(debit.outpoint);
debit.beneficiary = Party::from_wallet_addr(wallet_addr);
wallet_addr.used = wallet_addr.used.saturating_add(1);
wallet_addr.volume.saturating_add_assign(debit.value);
wallet_addr.balance = wallet_addr
.balance
.saturating_sub(credit.value.sats().try_into().expect("sats overflow"));
.saturating_add(debit.value.sats().try_into().expect("sats overflow"));
} else {
Address::with(s, descriptor.chain())
.map(|addr| {
credit.payer = Party::Counterparty(addr);
debit.beneficiary = Party::Counterparty(addr);
})
.ok();
}
if let Some(prev_tx) = cache.tx.get_mut(&credit.outpoint.txid) {
prev_tx
.outputs
.get_mut(credit.outpoint.vout_u32() as usize)
.map(|vout| vout.spent = Some(Inpoint::new(tx.txid, vin as u32)));
}
}
for debit in &mut tx.outputs {
let Party::Unknown(ref s) = debit.beneficiary else {
cache.tx.insert(tx.txid, tx);
}
}

for (script, (wallet_addr, txids)) in &mut address_index {
for txid in txids {
let mut tx = cache.tx.remove(txid).expect("broken logic");
for credit in &mut tx.inputs {
let Party::Unknown(ref s) = credit.payer else {
continue;
};
if s == &script {
cache.utxo.insert(debit.outpoint);
debit.beneficiary = Party::Wallet(addr_info.clone());
wallet_addr.used = wallet_addr.used.saturating_add(1);
wallet_addr.volume.saturating_add_assign(debit.value);
if s == script {
credit.payer = Party::from_wallet_addr(wallet_addr);
wallet_addr.balance = wallet_addr
.balance
.saturating_add(debit.value.sats().try_into().expect("sats overflow"));
.saturating_sub(credit.value.sats().try_into().expect("sats overflow"));
} else {
Address::with(s, descriptor.chain())
.map(|addr| {
debit.beneficiary = Party::Counterparty(addr);
credit.payer = Party::Counterparty(addr);
})
.ok();
}
if let Some(prev_tx) = cache.tx.get_mut(&credit.outpoint.txid) {
prev_tx.outputs.get_mut(credit.outpoint.vout_u32() as usize).map(|txout| {
let outpoint = txout.outpoint;
cache.utxo.remove(&outpoint);
txout.spent = Some(credit.outpoint.into())
});
}
}
cache.tx.insert(tx.txid, tx);
}
cache
.addr
.entry(addr_info.terminal.keychain)
.entry(wallet_addr.terminal.keychain)
.or_default()
.insert(wallet_addr.expect_transmute());
}
Expand Down

0 comments on commit 38d1b63

Please sign in to comment.