Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Update bdk_wallet to v3.0.0 and refactor test helpers by HARSHVARANDANI · Pull Request #907 · lightningdevkit/ldk-node · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,7 +56,7 @@ lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightn
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
bdk_wallet = { version = "3.0.0", default-features = false, features = ["std", "keys-bip39"]}

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
158 changes: 25 additions & 133 deletions src/wallet/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,10 +13,9 @@ use std::sync::{Arc, Mutex};
use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_wallet::descriptor::ExtendedDescriptor;
use bdk_wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk_wallet::event::WalletEvent;
#[allow(deprecated)]
use bdk_wallet::SignOptions;
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update};
use bdk_wallet::{Balance, KeychainKind, PersistedWallet, Update, WalletEvent};
use bitcoin::address::NetworkUnchecked;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::locktime::absolute::LockTime;
Expand DownExpand Up@@ -181,30 +180,13 @@ impl Wallet {
}

let mut locked_wallet = self.inner.lock().expect("lock");

let chain_tip1 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs1 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

locked_wallet.apply_unconfirmed_txs(unconfirmed_txs);
locked_wallet.apply_evicted_txs(evicted_txids);

let chain_tip2 = locked_wallet.latest_checkpoint().block_id();
let wallet_txs2 = locked_wallet
.transactions()
.map(|wtx| (wtx.tx_node.txid, (wtx.tx_node.tx.clone(), wtx.chain_position)))
.collect::<std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>>();

let events =
wallet_events(&mut *locked_wallet, chain_tip1, chain_tip2, wallet_txs1, wallet_txs2);
let events = locked_wallet
.events_helper(|wallet| {
wallet.apply_unconfirmed_txs(unconfirmed_txs);
wallet.apply_evicted_txs(evicted_txids);
Ok::<(), std::convert::Infallible>(())
})
.expect("infallible");

self.update_payment_store(&mut *locked_wallet, events).map_err(|e| {
log_error!(self.logger, "Failed to update payment store: {}", e);
Expand DownExpand Up@@ -504,7 +486,7 @@ impl Wallet {
let mut locked_wallet = self.inner.lock().expect("lock");
let mut locked_persister = self.persister.lock().expect("lock");

locked_wallet.cancel_tx(tx);
reclaim_tx_outputs(&mut locked_wallet, tx);
locked_wallet.persist(&mut locked_persister).map_err(|e| {
log_error!(self.logger, "Failed to persist wallet: {}", e);
Error::PersistenceFailed
Expand DownExpand Up@@ -593,7 +575,7 @@ impl Wallet {
/// Builds a temporary drain transaction and returns the maximum amount that would be sent to
/// the drain output, along with the PSBT for further inspection.
///
/// The caller is responsible for cancelling the PSBT via `locked_wallet.cancel_tx()`.
/// The caller is responsible for reclaiming any used addresses from the PSBT.
fn get_max_drain_amount(
&self, locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>,
drain_script: ScriptBuf, cur_anchor_reserve_sats: u64, fee_rate: FeeRate,
Expand DownExpand Up@@ -665,7 +647,7 @@ impl Wallet {
None,
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(max_amount)
}
Expand DownExpand Up@@ -695,7 +677,7 @@ impl Wallet {
Some(&shared_input),
)?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

Ok(splice_amount)
}
Expand DownExpand Up@@ -751,7 +733,7 @@ impl Wallet {
e
})?;

locked_wallet.cancel_tx(&tmp_psbt.unsigned_tx);
reclaim_tx_outputs(&mut locked_wallet, &tmp_psbt.unsigned_tx);

let mut tx_builder = locked_wallet.build_tx();
tx_builder
Expand DownExpand Up@@ -1427,6 +1409,18 @@ impl Wallet {
}
}

fn reclaim_tx_outputs(
locked_wallet: &mut PersistedWallet<KVStoreWalletPersister>, tx: &Transaction,
) {
for output in &tx.output {
if let Some((keychain, index)) =
locked_wallet.derivation_of_spk(output.script_pubkey.clone())
{
locked_wallet.unmark_used(keychain, index);
}
}
}

impl Listen for Wallet {
fn filtered_block_connected(
&self, _header: &bitcoin::block::Header,
Expand DownExpand Up@@ -1716,105 +1710,3 @@ impl ChangeDestinationSource for WalletKeysManager {
}
}
}

// FIXME/TODO: This is copied-over from bdk_wallet and only used to generate `WalletEvent`s after
// applying mempool transactions. We should drop this when BDK offers to generate events for
// mempool transactions natively.
pub(crate) fn wallet_events(
wallet: &mut bdk_wallet::Wallet, chain_tip1: bdk_chain::BlockId,
chain_tip2: bdk_chain::BlockId,
wallet_txs1: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
wallet_txs2: std::collections::BTreeMap<
Txid,
(Arc<Transaction>, bdk_chain::ChainPosition<bdk_chain::ConfirmationBlockTime>),
>,
) -> Vec<WalletEvent> {
let mut events: Vec<WalletEvent> = Vec::new();

if chain_tip1 != chain_tip2 {
events.push(WalletEvent::ChainTipChanged { old_tip: chain_tip1, new_tip: chain_tip2 });
}

wallet_txs2.iter().for_each(|(txid2, (tx2, cp2))| {
if let Some((tx1, cp1)) = wallet_txs1.get(txid2) {
assert_eq!(tx1.compute_txid(), *txid2);
match (cp1, cp2) {
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Confirmed { anchor, .. },
) => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor, .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: Some(*anchor),
});
},
(
bdk_chain::ChainPosition::Confirmed { anchor: anchor1, .. },
bdk_chain::ChainPosition::Confirmed { anchor: anchor2, .. },
) => {
if *anchor1 != *anchor2 {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor2,
old_block_time: Some(*anchor1),
});
}
},
(
bdk_chain::ChainPosition::Unconfirmed { .. },
bdk_chain::ChainPosition::Unconfirmed { .. },
) => {
// do nothing if still unconfirmed
},
}
} else {
match cp2 {
bdk_chain::ChainPosition::Confirmed { anchor, .. } => {
events.push(WalletEvent::TxConfirmed {
txid: *txid2,
tx: tx2.clone(),
block_time: *anchor,
old_block_time: None,
});
},
bdk_chain::ChainPosition::Unconfirmed { .. } => {
events.push(WalletEvent::TxUnconfirmed {
txid: *txid2,
tx: tx2.clone(),
old_block_time: None,
});
},
}
}
});

// find tx that are no longer canonical
wallet_txs1.iter().for_each(|(txid1, (tx1, _))| {
if !wallet_txs2.contains_key(txid1) {
let conflicts = wallet.tx_graph().direct_conflicts(tx1).collect::<Vec<_>>();
if !conflicts.is_empty() {
events.push(WalletEvent::TxReplaced { txid: *txid1, tx: tx1.clone(), conflicts });
} else {
events.push(WalletEvent::TxDropped { txid: *txid1, tx: tx1.clone() });
}
}
});

events
}
9 changes: 9 additions & 0 deletions tests/common/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -115,6 +115,7 @@ macro_rules! expect_channel_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_pending_event;

macro_rules! expect_channel_ready_event {
Expand All@@ -141,8 +142,10 @@ macro_rules! expect_channel_ready_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_event;

#[allow(unused_macros)]
macro_rules! expect_channel_ready_events {
($node:expr, $counterparty_node_id_a:expr, $counterparty_node_id_b:expr) => {{
let mut ids = Vec::new();
Expand DownExpand Up@@ -177,6 +180,7 @@ macro_rules! expect_channel_ready_events {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_channel_ready_events;

macro_rules! expect_splice_pending_event {
Expand All@@ -203,6 +207,7 @@ macro_rules! expect_splice_pending_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_splice_pending_event;

macro_rules! expect_payment_received_event {
Expand DownExpand Up@@ -233,6 +238,7 @@ macro_rules! expect_payment_received_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_received_event;

macro_rules! expect_payment_claimable_event {
Expand DownExpand Up@@ -269,6 +275,7 @@ macro_rules! expect_payment_claimable_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_claimable_event;

macro_rules! expect_payment_successful_event {
Expand DownExpand Up@@ -299,6 +306,7 @@ macro_rules! expect_payment_successful_event {
}};
}

#[allow(unused_imports)]
pub(crate) use expect_payment_successful_event;

pub(crate) fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
Expand DownExpand Up@@ -464,6 +472,7 @@ macro_rules! setup_builder {
};
}

#[allow(unused_imports)]
pub(crate) use setup_builder;

#[cfg(any(cln_test, lnd_test, eclair_test))]
Expand Down
Loading