Merge bitcoindevkit/bdk#1506: Standardize API ownership in KeychainTxOutIndex
79262185d556009c3d3e918f886ba4a51a262351 refactor(chain)!: update KeychainTxOutIndex methods to use owned ScriptBuf (Steve Myers) 7c07b9de02edf9f2c2b8a153f7bc4c0ca0823b02 refactor(chain)!: update KeychainTxOutIndex methods to use owned K (Rob N) Pull request description: ### Description Make all method signatures of `KeychainTxOutIndex` take owned `K` and use `ScriptBuf` instead of its borrowed counterpart `&Script`. Fixes #1482 ### Notes to the reviewers Steve also added a CI fix as well ### Changelog notice - Make all method signatures of `KeychainTxOutIndex` take owned `K` - Update `KeychainTxOutIndex` methods to use `ScriptBuf` ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [ ] I've added tests for the new feature * [ ] I've added docs for the new feature #### Bugfixes: * [x] This pull request breaks the existing API * [ ] I've added tests to reproduce the issue which are now passing * [x] I'm linking the issue being fixed by this PR Top commit has no ACKs. Tree-SHA512: 3cb7d627ef6f38e1eaf6b88174f143c42dfc4d34e3d3d56cc843c256b2f32360fd00fa9ee328d0a41dac1f46771ccae797a96d9e3cee6f5ac4ef63e27cf6b7b7
This commit is contained in:
commit
5478bb1ebb
@ -9,7 +9,7 @@ use crate::{
|
|||||||
DescriptorExt, DescriptorId, Indexed, Indexer, KeychainIndexed, SpkIterator,
|
DescriptorExt, DescriptorId, Indexed, Indexer, KeychainIndexed, SpkIterator,
|
||||||
};
|
};
|
||||||
use alloc::{borrow::ToOwned, vec::Vec};
|
use alloc::{borrow::ToOwned, vec::Vec};
|
||||||
use bitcoin::{Amount, OutPoint, Script, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
|
use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
|
||||||
use core::{
|
use core::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
ops::{Bound, RangeBounds},
|
ops::{Bound, RangeBounds},
|
||||||
@ -99,7 +99,7 @@ pub const DEFAULT_LOOKAHEAD: u32 = 25;
|
|||||||
/// let _ = txout_index.insert_descriptor(MyKeychain::Internal, internal_descriptor)?;
|
/// let _ = txout_index.insert_descriptor(MyKeychain::Internal, internal_descriptor)?;
|
||||||
/// let _ = txout_index.insert_descriptor(MyKeychain::MyAppUser { user_id: 42 }, descriptor_42)?;
|
/// let _ = txout_index.insert_descriptor(MyKeychain::MyAppUser { user_id: 42 }, descriptor_42)?;
|
||||||
///
|
///
|
||||||
/// let new_spk_for_user = txout_index.reveal_next_spk(&MyKeychain::MyAppUser{ user_id: 42 });
|
/// let new_spk_for_user = txout_index.reveal_next_spk(MyKeychain::MyAppUser{ user_id: 42 });
|
||||||
/// # Ok::<_, bdk_chain::indexer::keychain_txout::InsertDescriptorError<_>>(())
|
/// # Ok::<_, bdk_chain::indexer::keychain_txout::InsertDescriptorError<_>>(())
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -251,14 +251,14 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// Return the script that exists under the given `keychain`'s `index`.
|
/// Return the script that exists under the given `keychain`'s `index`.
|
||||||
///
|
///
|
||||||
/// This calls [`SpkTxOutIndex::spk_at_index`] internally.
|
/// This calls [`SpkTxOutIndex::spk_at_index`] internally.
|
||||||
pub fn spk_at_index(&self, keychain: K, index: u32) -> Option<&Script> {
|
pub fn spk_at_index(&self, keychain: K, index: u32) -> Option<ScriptBuf> {
|
||||||
self.inner.spk_at_index(&(keychain.clone(), index))
|
self.inner.spk_at_index(&(keychain.clone(), index))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the keychain and keychain index associated with the spk.
|
/// Returns the keychain and keychain index associated with the spk.
|
||||||
///
|
///
|
||||||
/// This calls [`SpkTxOutIndex::index_of_spk`] internally.
|
/// This calls [`SpkTxOutIndex::index_of_spk`] internally.
|
||||||
pub fn index_of_spk(&self, script: &Script) -> Option<&(K, u32)> {
|
pub fn index_of_spk(&self, script: ScriptBuf) -> Option<&(K, u32)> {
|
||||||
self.inner.index_of_spk(script)
|
self.inner.index_of_spk(script)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,11 +335,11 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// Return all keychains and their corresponding descriptors.
|
/// Return all keychains and their corresponding descriptors.
|
||||||
pub fn keychains(
|
pub fn keychains(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = (&K, &Descriptor<DescriptorPublicKey>)> + ExactSizeIterator + '_
|
) -> impl DoubleEndedIterator<Item = (K, &Descriptor<DescriptorPublicKey>)> + ExactSizeIterator + '_
|
||||||
{
|
{
|
||||||
self.keychain_to_descriptor_id
|
self.keychain_to_descriptor_id
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, did)| (k, self.descriptors.get(did).expect("invariant")))
|
.map(|(k, did)| (k.clone(), self.descriptors.get(did).expect("invariant")))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a descriptor with a keychain associated to it.
|
/// Insert a descriptor with a keychain associated to it.
|
||||||
@ -399,8 +399,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
|
|
||||||
/// Gets the descriptor associated with the keychain. Returns `None` if the keychain doesn't
|
/// Gets the descriptor associated with the keychain. Returns `None` if the keychain doesn't
|
||||||
/// have a descriptor associated with it.
|
/// have a descriptor associated with it.
|
||||||
pub fn get_descriptor(&self, keychain: &K) -> Option<&Descriptor<DescriptorPublicKey>> {
|
pub fn get_descriptor(&self, keychain: K) -> Option<&Descriptor<DescriptorPublicKey>> {
|
||||||
let did = self.keychain_to_descriptor_id.get(keychain)?;
|
let did = self.keychain_to_descriptor_id.get(&keychain)?;
|
||||||
self.descriptors.get(did)
|
self.descriptors.get(did)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +416,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// Store lookahead scripts until `target_index` (inclusive).
|
/// Store lookahead scripts until `target_index` (inclusive).
|
||||||
///
|
///
|
||||||
/// This does not change the global `lookahead` setting.
|
/// This does not change the global `lookahead` setting.
|
||||||
pub fn lookahead_to_target(&mut self, keychain: &K, target_index: u32) {
|
pub fn lookahead_to_target(&mut self, keychain: K, target_index: u32) {
|
||||||
if let Some((next_index, _)) = self.next_index(keychain) {
|
if let Some((next_index, _)) = self.next_index(keychain.clone()) {
|
||||||
let temp_lookahead = (target_index + 1)
|
let temp_lookahead = (target_index + 1)
|
||||||
.checked_sub(next_index)
|
.checked_sub(next_index)
|
||||||
.filter(|&index| index > 0);
|
.filter(|&index| index > 0);
|
||||||
@ -434,9 +434,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replenish_inner_index_keychain(&mut self, keychain: &K, lookahead: u32) {
|
fn replenish_inner_index_keychain(&mut self, keychain: K, lookahead: u32) {
|
||||||
if let Some(did) = self.keychain_to_descriptor_id.get(keychain) {
|
if let Some(did) = self.keychain_to_descriptor_id.get(&keychain) {
|
||||||
self.replenish_inner_index(*did, keychain, lookahead);
|
self.replenish_inner_index(*did, &keychain, lookahead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,7 +464,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// keychain doesn't exist
|
/// keychain doesn't exist
|
||||||
pub fn unbounded_spk_iter(
|
pub fn unbounded_spk_iter(
|
||||||
&self,
|
&self,
|
||||||
keychain: &K,
|
keychain: K,
|
||||||
) -> Option<SpkIterator<Descriptor<DescriptorPublicKey>>> {
|
) -> Option<SpkIterator<Descriptor<DescriptorPublicKey>>> {
|
||||||
let descriptor = self.get_descriptor(keychain)?.clone();
|
let descriptor = self.get_descriptor(keychain)?.clone();
|
||||||
Some(SpkIterator::new(descriptor))
|
Some(SpkIterator::new(descriptor))
|
||||||
@ -489,7 +489,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
pub fn revealed_spks(
|
pub fn revealed_spks(
|
||||||
&self,
|
&self,
|
||||||
range: impl RangeBounds<K>,
|
range: impl RangeBounds<K>,
|
||||||
) -> impl Iterator<Item = KeychainIndexed<K, &Script>> {
|
) -> impl Iterator<Item = KeychainIndexed<K, ScriptBuf>> + '_ {
|
||||||
let start = range.start_bound();
|
let start = range.start_bound();
|
||||||
let end = range.end_bound();
|
let end = range.end_bound();
|
||||||
let mut iter_last_revealed = self
|
let mut iter_last_revealed = self
|
||||||
@ -516,7 +516,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
let (current_keychain, last_revealed) = current_keychain?;
|
let (current_keychain, last_revealed) = current_keychain?;
|
||||||
|
|
||||||
if current_keychain == keychain && Some(*index) <= last_revealed {
|
if current_keychain == keychain && Some(*index) <= last_revealed {
|
||||||
break Some(((keychain.clone(), *index), spk.as_script()));
|
break Some(((keychain.clone(), *index), spk.clone()));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -525,27 +525,27 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
///
|
///
|
||||||
/// This is a double ended iterator so you can easily reverse it to get an iterator where
|
/// This is a double ended iterator so you can easily reverse it to get an iterator where
|
||||||
/// the script pubkeys that were most recently revealed are first.
|
/// the script pubkeys that were most recently revealed are first.
|
||||||
pub fn revealed_keychain_spks<'a>(
|
pub fn revealed_keychain_spks(
|
||||||
&'a self,
|
&self,
|
||||||
keychain: &'a K,
|
keychain: K,
|
||||||
) -> impl DoubleEndedIterator<Item = Indexed<&Script>> + 'a {
|
) -> impl DoubleEndedIterator<Item = Indexed<ScriptBuf>> + '_ {
|
||||||
let end = self
|
let end = self
|
||||||
.last_revealed_index(keychain)
|
.last_revealed_index(keychain.clone())
|
||||||
.map(|v| v + 1)
|
.map(|v| v + 1)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
self.inner
|
self.inner
|
||||||
.all_spks()
|
.all_spks()
|
||||||
.range((keychain.clone(), 0)..(keychain.clone(), end))
|
.range((keychain.clone(), 0)..(keychain.clone(), end))
|
||||||
.map(|((_, index), spk)| (*index, spk.as_script()))
|
.map(|((_, index), spk)| (*index, spk.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over revealed, but unused, spks of all keychains.
|
/// Iterate over revealed, but unused, spks of all keychains.
|
||||||
pub fn unused_spks(
|
pub fn unused_spks(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = KeychainIndexed<K, &Script>> + Clone {
|
) -> impl DoubleEndedIterator<Item = KeychainIndexed<K, ScriptBuf>> + Clone + '_ {
|
||||||
self.keychain_to_descriptor_id.keys().flat_map(|keychain| {
|
self.keychain_to_descriptor_id.keys().flat_map(|keychain| {
|
||||||
self.unused_keychain_spks(keychain)
|
self.unused_keychain_spks(keychain.clone())
|
||||||
.map(|(i, spk)| ((keychain.clone(), i), spk))
|
.map(|(i, spk)| ((keychain.clone(), i), spk.clone()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,9 +553,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// Returns an empty iterator if the provided keychain doesn't exist.
|
/// Returns an empty iterator if the provided keychain doesn't exist.
|
||||||
pub fn unused_keychain_spks(
|
pub fn unused_keychain_spks(
|
||||||
&self,
|
&self,
|
||||||
keychain: &K,
|
keychain: K,
|
||||||
) -> impl DoubleEndedIterator<Item = Indexed<&Script>> + Clone {
|
) -> impl DoubleEndedIterator<Item = Indexed<ScriptBuf>> + Clone + '_ {
|
||||||
let end = match self.keychain_to_descriptor_id.get(keychain) {
|
let end = match self.keychain_to_descriptor_id.get(&keychain) {
|
||||||
Some(did) => self.last_revealed.get(did).map(|v| *v + 1).unwrap_or(0),
|
Some(did) => self.last_revealed.get(did).map(|v| *v + 1).unwrap_or(0),
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
@ -577,8 +577,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// Not checking the second field of the tuple may result in address reuse.
|
/// Not checking the second field of the tuple may result in address reuse.
|
||||||
///
|
///
|
||||||
/// Returns None if the provided `keychain` doesn't exist.
|
/// Returns None if the provided `keychain` doesn't exist.
|
||||||
pub fn next_index(&self, keychain: &K) -> Option<(u32, bool)> {
|
pub fn next_index(&self, keychain: K) -> Option<(u32, bool)> {
|
||||||
let did = self.keychain_to_descriptor_id.get(keychain)?;
|
let did = self.keychain_to_descriptor_id.get(&keychain)?;
|
||||||
let last_index = self.last_revealed.get(did).cloned();
|
let last_index = self.last_revealed.get(did).cloned();
|
||||||
let descriptor = self.descriptors.get(did).expect("invariant");
|
let descriptor = self.descriptors.get(did).expect("invariant");
|
||||||
|
|
||||||
@ -615,8 +615,8 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
|
|
||||||
/// Get the last derivation index revealed for `keychain`. Returns None if the keychain doesn't
|
/// Get the last derivation index revealed for `keychain`. Returns None if the keychain doesn't
|
||||||
/// exist, or if the keychain doesn't have any revealed scripts.
|
/// exist, or if the keychain doesn't have any revealed scripts.
|
||||||
pub fn last_revealed_index(&self, keychain: &K) -> Option<u32> {
|
pub fn last_revealed_index(&self, keychain: K) -> Option<u32> {
|
||||||
let descriptor_id = self.keychain_to_descriptor_id.get(keychain)?;
|
let descriptor_id = self.keychain_to_descriptor_id.get(&keychain)?;
|
||||||
self.last_revealed.get(descriptor_id).cloned()
|
self.last_revealed.get(descriptor_id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +625,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
let mut changeset = ChangeSet::default();
|
let mut changeset = ChangeSet::default();
|
||||||
|
|
||||||
for (keychain, &index) in keychains {
|
for (keychain, &index) in keychains {
|
||||||
if let Some((_, new_changeset)) = self.reveal_to_target(keychain, index) {
|
if let Some((_, new_changeset)) = self.reveal_to_target(keychain.clone(), index) {
|
||||||
changeset.merge(new_changeset);
|
changeset.merge(new_changeset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -648,16 +648,16 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn reveal_to_target(
|
pub fn reveal_to_target(
|
||||||
&mut self,
|
&mut self,
|
||||||
keychain: &K,
|
keychain: K,
|
||||||
target_index: u32,
|
target_index: u32,
|
||||||
) -> Option<(Vec<Indexed<ScriptBuf>>, ChangeSet)> {
|
) -> Option<(Vec<Indexed<ScriptBuf>>, ChangeSet)> {
|
||||||
let mut changeset = ChangeSet::default();
|
let mut changeset = ChangeSet::default();
|
||||||
let mut spks: Vec<Indexed<ScriptBuf>> = vec![];
|
let mut spks: Vec<Indexed<ScriptBuf>> = vec![];
|
||||||
while let Some((i, new)) = self.next_index(keychain) {
|
while let Some((i, new)) = self.next_index(keychain.clone()) {
|
||||||
if !new || i > target_index {
|
if !new || i > target_index {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match self.reveal_next_spk(keychain) {
|
match self.reveal_next_spk(keychain.clone()) {
|
||||||
Some(((i, spk), change)) => {
|
Some(((i, spk), change)) => {
|
||||||
spks.push((i, spk));
|
spks.push((i, spk));
|
||||||
changeset.merge(change);
|
changeset.merge(change);
|
||||||
@ -681,21 +681,21 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// 1. The descriptor has no wildcard and already has one script revealed.
|
/// 1. The descriptor has no wildcard and already has one script revealed.
|
||||||
/// 2. The descriptor has already revealed scripts up to the numeric bound.
|
/// 2. The descriptor has already revealed scripts up to the numeric bound.
|
||||||
/// 3. There is no descriptor associated with the given keychain.
|
/// 3. There is no descriptor associated with the given keychain.
|
||||||
pub fn reveal_next_spk(&mut self, keychain: &K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
|
pub fn reveal_next_spk(&mut self, keychain: K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
|
||||||
let (next_index, new) = self.next_index(keychain)?;
|
let (next_index, new) = self.next_index(keychain.clone())?;
|
||||||
let mut changeset = ChangeSet::default();
|
let mut changeset = ChangeSet::default();
|
||||||
|
|
||||||
if new {
|
if new {
|
||||||
let did = self.keychain_to_descriptor_id.get(keychain)?;
|
let did = self.keychain_to_descriptor_id.get(&keychain)?;
|
||||||
self.last_revealed.insert(*did, next_index);
|
self.last_revealed.insert(*did, next_index);
|
||||||
changeset.last_revealed.insert(*did, next_index);
|
changeset.last_revealed.insert(*did, next_index);
|
||||||
self.replenish_inner_index(*did, keychain, self.lookahead);
|
self.replenish_inner_index(*did, &keychain, self.lookahead);
|
||||||
}
|
}
|
||||||
let script = self
|
let script = self
|
||||||
.inner
|
.inner
|
||||||
.spk_at_index(&(keychain.clone(), next_index))
|
.spk_at_index(&(keychain.clone(), next_index))
|
||||||
.expect("we just inserted it");
|
.expect("we just inserted it");
|
||||||
Some(((next_index, script.into()), changeset))
|
Some(((next_index, script), changeset))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the next unused script pubkey in the keychain. I.e., the script pubkey with the lowest
|
/// Gets the next unused script pubkey in the keychain. I.e., the script pubkey with the lowest
|
||||||
@ -711,9 +711,9 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
/// could be revealed (see [`reveal_next_spk`] for when this happens).
|
/// could be revealed (see [`reveal_next_spk`] for when this happens).
|
||||||
///
|
///
|
||||||
/// [`reveal_next_spk`]: Self::reveal_next_spk
|
/// [`reveal_next_spk`]: Self::reveal_next_spk
|
||||||
pub fn next_unused_spk(&mut self, keychain: &K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
|
pub fn next_unused_spk(&mut self, keychain: K) -> Option<(Indexed<ScriptBuf>, ChangeSet)> {
|
||||||
let next_unused = self
|
let next_unused = self
|
||||||
.unused_keychain_spks(keychain)
|
.unused_keychain_spks(keychain.clone())
|
||||||
.next()
|
.next()
|
||||||
.map(|(i, spk)| ((i, spk.to_owned()), ChangeSet::default()));
|
.map(|(i, spk)| ((i, spk.to_owned()), ChangeSet::default()));
|
||||||
|
|
||||||
@ -722,11 +722,11 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
|
|
||||||
/// Iterate over all [`OutPoint`]s that have `TxOut`s with script pubkeys derived from
|
/// Iterate over all [`OutPoint`]s that have `TxOut`s with script pubkeys derived from
|
||||||
/// `keychain`.
|
/// `keychain`.
|
||||||
pub fn keychain_outpoints<'a>(
|
pub fn keychain_outpoints(
|
||||||
&'a self,
|
&self,
|
||||||
keychain: &'a K,
|
keychain: K,
|
||||||
) -> impl DoubleEndedIterator<Item = Indexed<OutPoint>> + 'a {
|
) -> impl DoubleEndedIterator<Item = Indexed<OutPoint>> + '_ {
|
||||||
self.keychain_outpoints_in_range(keychain..=keychain)
|
self.keychain_outpoints_in_range(keychain.clone()..=keychain)
|
||||||
.map(|((_, i), op)| (i, op))
|
.map(|((_, i), op)| (i, op))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +757,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
|
|
||||||
/// Returns the highest derivation index of the `keychain` where [`KeychainTxOutIndex`] has
|
/// Returns the highest derivation index of the `keychain` where [`KeychainTxOutIndex`] has
|
||||||
/// found a [`TxOut`] with it's script pubkey.
|
/// found a [`TxOut`] with it's script pubkey.
|
||||||
pub fn last_used_index(&self, keychain: &K) -> Option<u32> {
|
pub fn last_used_index(&self, keychain: K) -> Option<u32> {
|
||||||
self.keychain_outpoints(keychain).last().map(|(i, _)| i)
|
self.keychain_outpoints(keychain).last().map(|(i, _)| i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,7 +767,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
|
|||||||
self.keychain_to_descriptor_id
|
self.keychain_to_descriptor_id
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(keychain, _)| {
|
.filter_map(|(keychain, _)| {
|
||||||
self.last_used_index(keychain)
|
self.last_used_index(keychain.clone())
|
||||||
.map(|index| (keychain.clone(), index))
|
.map(|index| (keychain.clone(), index))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap},
|
collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap},
|
||||||
Indexer,
|
Indexer,
|
||||||
};
|
};
|
||||||
use bitcoin::{Amount, OutPoint, Script, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
|
use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
|
||||||
|
|
||||||
/// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
|
/// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
|
||||||
///
|
///
|
||||||
@ -176,8 +176,8 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
|
|||||||
/// Returns the script that has been inserted at the `index`.
|
/// Returns the script that has been inserted at the `index`.
|
||||||
///
|
///
|
||||||
/// If that index hasn't been inserted yet, it will return `None`.
|
/// If that index hasn't been inserted yet, it will return `None`.
|
||||||
pub fn spk_at_index(&self, index: &I) -> Option<&Script> {
|
pub fn spk_at_index(&self, index: &I) -> Option<ScriptBuf> {
|
||||||
self.spks.get(index).map(|s| s.as_script())
|
self.spks.get(index).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The script pubkeys that are being tracked by the index.
|
/// The script pubkeys that are being tracked by the index.
|
||||||
@ -217,7 +217,10 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
|
|||||||
/// let unused_change_spks =
|
/// let unused_change_spks =
|
||||||
/// txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
|
/// txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn unused_spks<R>(&self, range: R) -> impl DoubleEndedIterator<Item = (&I, &Script)> + Clone
|
pub fn unused_spks<R>(
|
||||||
|
&self,
|
||||||
|
range: R,
|
||||||
|
) -> impl DoubleEndedIterator<Item = (&I, ScriptBuf)> + Clone + '_
|
||||||
where
|
where
|
||||||
R: RangeBounds<I>,
|
R: RangeBounds<I>,
|
||||||
{
|
{
|
||||||
@ -268,8 +271,8 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the index associated with the script pubkey.
|
/// Returns the index associated with the script pubkey.
|
||||||
pub fn index_of_spk(&self, script: &Script) -> Option<&I> {
|
pub fn index_of_spk(&self, script: ScriptBuf) -> Option<&I> {
|
||||||
self.spk_indices.get(script)
|
self.spk_indices.get(script.as_script())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the total value transfer effect `tx` has on the script pubkeys in `range`. Value is
|
/// Computes the total value transfer effect `tx` has on the script pubkeys in `range`. Value is
|
||||||
@ -293,7 +296,7 @@ impl<I: Clone + Ord + core::fmt::Debug> SpkTxOutIndex<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for txout in &tx.output {
|
for txout in &tx.output {
|
||||||
if let Some(index) = self.index_of_spk(&txout.script_pubkey) {
|
if let Some(index) = self.index_of_spk(txout.script_pubkey.clone()) {
|
||||||
if range.contains(index) {
|
if range.contains(index) {
|
||||||
received += txout.value;
|
received += txout.value;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ use crate::{
|
|||||||
use alloc::collections::vec_deque::VecDeque;
|
use alloc::collections::vec_deque::VecDeque;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use bitcoin::{Amount, OutPoint, Script, SignedAmount, Transaction, TxOut, Txid};
|
use bitcoin::{Amount, OutPoint, ScriptBuf, SignedAmount, Transaction, TxOut, Txid};
|
||||||
use core::fmt::{self, Formatter};
|
use core::fmt::{self, Formatter};
|
||||||
use core::{
|
use core::{
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
@ -1163,7 +1163,7 @@ impl<A: Anchor> TxGraph<A> {
|
|||||||
chain: &C,
|
chain: &C,
|
||||||
chain_tip: BlockId,
|
chain_tip: BlockId,
|
||||||
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
|
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
|
||||||
mut trust_predicate: impl FnMut(&OI, &Script) -> bool,
|
mut trust_predicate: impl FnMut(&OI, ScriptBuf) -> bool,
|
||||||
) -> Result<Balance, C::Error> {
|
) -> Result<Balance, C::Error> {
|
||||||
let mut immature = Amount::ZERO;
|
let mut immature = Amount::ZERO;
|
||||||
let mut trusted_pending = Amount::ZERO;
|
let mut trusted_pending = Amount::ZERO;
|
||||||
@ -1182,7 +1182,7 @@ impl<A: Anchor> TxGraph<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChainPosition::Unconfirmed(_) => {
|
ChainPosition::Unconfirmed(_) => {
|
||||||
if trust_predicate(&spk_i, &txout.txout.script_pubkey) {
|
if trust_predicate(&spk_i, txout.txout.script_pubkey) {
|
||||||
trusted_pending += txout.txout.value;
|
trusted_pending += txout.txout.value;
|
||||||
} else {
|
} else {
|
||||||
untrusted_pending += txout.txout.value;
|
untrusted_pending += txout.txout.value;
|
||||||
@ -1209,7 +1209,7 @@ impl<A: Anchor> TxGraph<A> {
|
|||||||
chain: &C,
|
chain: &C,
|
||||||
chain_tip: BlockId,
|
chain_tip: BlockId,
|
||||||
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
|
outpoints: impl IntoIterator<Item = (OI, OutPoint)>,
|
||||||
trust_predicate: impl FnMut(&OI, &Script) -> bool,
|
trust_predicate: impl FnMut(&OI, ScriptBuf) -> bool,
|
||||||
) -> Balance {
|
) -> Balance {
|
||||||
self.try_balance(chain, chain_tip, outpoints, trust_predicate)
|
self.try_balance(chain, chain_tip, outpoints, trust_predicate)
|
||||||
.expect("oracle is infallible")
|
.expect("oracle is infallible")
|
||||||
|
@ -119,7 +119,7 @@ pub fn init_graph<'a, A: Anchor + Clone + 'a>(
|
|||||||
},
|
},
|
||||||
Some(index) => TxOut {
|
Some(index) => TxOut {
|
||||||
value: Amount::from_sat(output.value),
|
value: Amount::from_sat(output.value),
|
||||||
script_pubkey: spk_index.spk_at_index(index).unwrap().to_owned(),
|
script_pubkey: spk_index.spk_at_index(index).unwrap(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -12,9 +12,7 @@ use bdk_chain::{
|
|||||||
local_chain::LocalChain,
|
local_chain::LocalChain,
|
||||||
tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt,
|
tx_graph, Balance, ChainPosition, ConfirmationBlockTime, DescriptorExt,
|
||||||
};
|
};
|
||||||
use bitcoin::{
|
use bitcoin::{secp256k1::Secp256k1, Amount, OutPoint, ScriptBuf, Transaction, TxIn, TxOut};
|
||||||
secp256k1::Secp256k1, Amount, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut,
|
|
||||||
};
|
|
||||||
use miniscript::Descriptor;
|
use miniscript::Descriptor;
|
||||||
|
|
||||||
/// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented
|
/// Ensure [`IndexedTxGraph::insert_relevant_txs`] can successfully index transactions NOT presented
|
||||||
@ -161,7 +159,7 @@ fn test_list_owned_txouts() {
|
|||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let ((_, script), _) = graph
|
let ((_, script), _) = graph
|
||||||
.index
|
.index
|
||||||
.reveal_next_spk(&"keychain_1".to_string())
|
.reveal_next_spk("keychain_1".to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// TODO Assert indexes
|
// TODO Assert indexes
|
||||||
trusted_spks.push(script.to_owned());
|
trusted_spks.push(script.to_owned());
|
||||||
@ -171,7 +169,7 @@ fn test_list_owned_txouts() {
|
|||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let ((_, script), _) = graph
|
let ((_, script), _) = graph
|
||||||
.index
|
.index
|
||||||
.reveal_next_spk(&"keychain_2".to_string())
|
.reveal_next_spk("keychain_2".to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
untrusted_spks.push(script.to_owned());
|
untrusted_spks.push(script.to_owned());
|
||||||
}
|
}
|
||||||
@ -284,7 +282,7 @@ fn test_list_owned_txouts() {
|
|||||||
&local_chain,
|
&local_chain,
|
||||||
chain_tip,
|
chain_tip,
|
||||||
graph.index.outpoints().iter().cloned(),
|
graph.index.outpoints().iter().cloned(),
|
||||||
|_, spk: &Script| trusted_spks.contains(&spk.to_owned()),
|
|_, spk: ScriptBuf| trusted_spks.contains(&spk),
|
||||||
);
|
);
|
||||||
|
|
||||||
let confirmed_txouts_txid = txouts
|
let confirmed_txouts_txid = txouts
|
||||||
|
@ -142,7 +142,7 @@ fn test_lookahead() {
|
|||||||
// - stored scripts of external keychain should be of expected counts
|
// - stored scripts of external keychain should be of expected counts
|
||||||
for index in (0..20).skip_while(|i| i % 2 == 1) {
|
for index in (0..20).skip_while(|i| i % 2 == 1) {
|
||||||
let (revealed_spks, revealed_changeset) = txout_index
|
let (revealed_spks, revealed_changeset) = txout_index
|
||||||
.reveal_to_target(&TestKeychain::External, index)
|
.reveal_to_target(TestKeychain::External, index)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
revealed_spks,
|
revealed_spks,
|
||||||
@ -161,25 +161,25 @@ fn test_lookahead() {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::External)
|
.revealed_keychain_spks(TestKeychain::External)
|
||||||
.count(),
|
.count(),
|
||||||
index as usize + 1,
|
index as usize + 1,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::Internal)
|
.revealed_keychain_spks(TestKeychain::Internal)
|
||||||
.count(),
|
.count(),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.unused_keychain_spks(&TestKeychain::External)
|
.unused_keychain_spks(TestKeychain::External)
|
||||||
.count(),
|
.count(),
|
||||||
index as usize + 1,
|
index as usize + 1,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.unused_keychain_spks(&TestKeychain::Internal)
|
.unused_keychain_spks(TestKeychain::Internal)
|
||||||
.count(),
|
.count(),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
@ -193,7 +193,7 @@ fn test_lookahead() {
|
|||||||
// expect:
|
// expect:
|
||||||
// - scripts cached in spk_txout_index should increase correctly, a.k.a. no scripts are skipped
|
// - scripts cached in spk_txout_index should increase correctly, a.k.a. no scripts are skipped
|
||||||
let (revealed_spks, revealed_changeset) = txout_index
|
let (revealed_spks, revealed_changeset) = txout_index
|
||||||
.reveal_to_target(&TestKeychain::Internal, 24)
|
.reveal_to_target(TestKeychain::Internal, 24)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
revealed_spks,
|
revealed_spks,
|
||||||
@ -214,17 +214,17 @@ fn test_lookahead() {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::Internal)
|
.revealed_keychain_spks(TestKeychain::Internal)
|
||||||
.count(),
|
.count(),
|
||||||
25,
|
25,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ensure derivation indices are expected for each keychain
|
// ensure derivation indices are expected for each keychain
|
||||||
let last_external_index = txout_index
|
let last_external_index = txout_index
|
||||||
.last_revealed_index(&TestKeychain::External)
|
.last_revealed_index(TestKeychain::External)
|
||||||
.expect("already derived");
|
.expect("already derived");
|
||||||
let last_internal_index = txout_index
|
let last_internal_index = txout_index
|
||||||
.last_revealed_index(&TestKeychain::Internal)
|
.last_revealed_index(TestKeychain::Internal)
|
||||||
.expect("already derived");
|
.expect("already derived");
|
||||||
assert_eq!(last_external_index, 19);
|
assert_eq!(last_external_index, 19);
|
||||||
assert_eq!(last_internal_index, 24);
|
assert_eq!(last_internal_index, 24);
|
||||||
@ -257,22 +257,22 @@ fn test_lookahead() {
|
|||||||
};
|
};
|
||||||
assert_eq!(txout_index.index_tx(&tx), ChangeSet::default());
|
assert_eq!(txout_index.index_tx(&tx), ChangeSet::default());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.last_revealed_index(&TestKeychain::External),
|
txout_index.last_revealed_index(TestKeychain::External),
|
||||||
Some(last_external_index)
|
Some(last_external_index)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.last_revealed_index(&TestKeychain::Internal),
|
txout_index.last_revealed_index(TestKeychain::Internal),
|
||||||
Some(last_internal_index)
|
Some(last_internal_index)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::External)
|
.revealed_keychain_spks(TestKeychain::External)
|
||||||
.count(),
|
.count(),
|
||||||
last_external_index as usize + 1,
|
last_external_index as usize + 1,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::Internal)
|
.revealed_keychain_spks(TestKeychain::Internal)
|
||||||
.count(),
|
.count(),
|
||||||
last_internal_index as usize + 1,
|
last_internal_index as usize + 1,
|
||||||
);
|
);
|
||||||
@ -317,11 +317,11 @@ fn test_scan_with_lookahead() {
|
|||||||
&[(external_descriptor.descriptor_id(), spk_i)].into()
|
&[(external_descriptor.descriptor_id(), spk_i)].into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.last_revealed_index(&TestKeychain::External),
|
txout_index.last_revealed_index(TestKeychain::External),
|
||||||
Some(spk_i)
|
Some(spk_i)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.last_used_index(&TestKeychain::External),
|
txout_index.last_used_index(TestKeychain::External),
|
||||||
Some(spk_i)
|
Some(spk_i)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -357,11 +357,11 @@ fn test_wildcard_derivations() {
|
|||||||
// - next_derivation_index() == (0, true)
|
// - next_derivation_index() == (0, true)
|
||||||
// - derive_new() == ((0, <spk>), keychain::ChangeSet)
|
// - derive_new() == ((0, <spk>), keychain::ChangeSet)
|
||||||
// - next_unused() == ((0, <spk>), keychain::ChangeSet:is_empty())
|
// - next_unused() == ((0, <spk>), keychain::ChangeSet:is_empty())
|
||||||
assert_eq!(txout_index.next_index(&TestKeychain::External).unwrap(), (0, true));
|
assert_eq!(txout_index.next_index(TestKeychain::External).unwrap(), (0, true));
|
||||||
let (spk, changeset) = txout_index.reveal_next_spk(&TestKeychain::External).unwrap();
|
let (spk, changeset) = txout_index.reveal_next_spk(TestKeychain::External).unwrap();
|
||||||
assert_eq!(spk, (0_u32, external_spk_0.clone()));
|
assert_eq!(spk, (0_u32, external_spk_0.clone()));
|
||||||
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 0)].into());
|
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 0)].into());
|
||||||
let (spk, changeset) = txout_index.next_unused_spk(&TestKeychain::External).unwrap();
|
let (spk, changeset) = txout_index.next_unused_spk(TestKeychain::External).unwrap();
|
||||||
assert_eq!(spk, (0_u32, external_spk_0.clone()));
|
assert_eq!(spk, (0_u32, external_spk_0.clone()));
|
||||||
assert_eq!(&changeset.last_revealed, &[].into());
|
assert_eq!(&changeset.last_revealed, &[].into());
|
||||||
|
|
||||||
@ -373,20 +373,20 @@ fn test_wildcard_derivations() {
|
|||||||
// - next_derivation_index() = (26, true)
|
// - next_derivation_index() = (26, true)
|
||||||
// - derive_new() = ((26, <spk>), keychain::ChangeSet)
|
// - derive_new() = ((26, <spk>), keychain::ChangeSet)
|
||||||
// - next_unused() == ((16, <spk>), keychain::ChangeSet::is_empty())
|
// - next_unused() == ((16, <spk>), keychain::ChangeSet::is_empty())
|
||||||
let _ = txout_index.reveal_to_target(&TestKeychain::External, 25);
|
let _ = txout_index.reveal_to_target(TestKeychain::External, 25);
|
||||||
|
|
||||||
(0..=15)
|
(0..=15)
|
||||||
.chain([17, 20, 23])
|
.chain([17, 20, 23])
|
||||||
.for_each(|index| assert!(txout_index.mark_used(TestKeychain::External, index)));
|
.for_each(|index| assert!(txout_index.mark_used(TestKeychain::External, index)));
|
||||||
|
|
||||||
assert_eq!(txout_index.next_index(&TestKeychain::External).unwrap(), (26, true));
|
assert_eq!(txout_index.next_index(TestKeychain::External).unwrap(), (26, true));
|
||||||
|
|
||||||
let (spk, changeset) = txout_index.reveal_next_spk(&TestKeychain::External).unwrap();
|
let (spk, changeset) = txout_index.reveal_next_spk(TestKeychain::External).unwrap();
|
||||||
assert_eq!(spk, (26, external_spk_26));
|
assert_eq!(spk, (26, external_spk_26));
|
||||||
|
|
||||||
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 26)].into());
|
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 26)].into());
|
||||||
|
|
||||||
let (spk, changeset) = txout_index.next_unused_spk(&TestKeychain::External).unwrap();
|
let (spk, changeset) = txout_index.next_unused_spk(TestKeychain::External).unwrap();
|
||||||
assert_eq!(spk, (16, external_spk_16));
|
assert_eq!(spk, (16, external_spk_16));
|
||||||
assert_eq!(&changeset.last_revealed, &[].into());
|
assert_eq!(&changeset.last_revealed, &[].into());
|
||||||
|
|
||||||
@ -396,7 +396,7 @@ fn test_wildcard_derivations() {
|
|||||||
txout_index.mark_used(TestKeychain::External, index);
|
txout_index.mark_used(TestKeychain::External, index);
|
||||||
});
|
});
|
||||||
|
|
||||||
let (spk, changeset) = txout_index.next_unused_spk(&TestKeychain::External).unwrap();
|
let (spk, changeset) = txout_index.next_unused_spk(TestKeychain::External).unwrap();
|
||||||
assert_eq!(spk, (27, external_spk_27));
|
assert_eq!(spk, (27, external_spk_27));
|
||||||
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 27)].into());
|
assert_eq!(&changeset.last_revealed, &[(external_descriptor.descriptor_id(), 27)].into());
|
||||||
}
|
}
|
||||||
@ -424,21 +424,17 @@ fn test_non_wildcard_derivations() {
|
|||||||
// - when we derive a new script, script @ index 0
|
// - when we derive a new script, script @ index 0
|
||||||
// - when we get the next unused script, script @ index 0
|
// - when we get the next unused script, script @ index 0
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.next_index(&TestKeychain::External).unwrap(),
|
txout_index.next_index(TestKeychain::External).unwrap(),
|
||||||
(0, true)
|
(0, true)
|
||||||
);
|
);
|
||||||
let (spk, changeset) = txout_index
|
let (spk, changeset) = txout_index.reveal_next_spk(TestKeychain::External).unwrap();
|
||||||
.reveal_next_spk(&TestKeychain::External)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(spk, (0, external_spk.clone()));
|
assert_eq!(spk, (0, external_spk.clone()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&changeset.last_revealed,
|
&changeset.last_revealed,
|
||||||
&[(no_wildcard_descriptor.descriptor_id(), 0)].into()
|
&[(no_wildcard_descriptor.descriptor_id(), 0)].into()
|
||||||
);
|
);
|
||||||
|
|
||||||
let (spk, changeset) = txout_index
|
let (spk, changeset) = txout_index.next_unused_spk(TestKeychain::External).unwrap();
|
||||||
.next_unused_spk(&TestKeychain::External)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(spk, (0, external_spk.clone()));
|
assert_eq!(spk, (0, external_spk.clone()));
|
||||||
assert_eq!(&changeset.last_revealed, &[].into());
|
assert_eq!(&changeset.last_revealed, &[].into());
|
||||||
|
|
||||||
@ -449,24 +445,20 @@ fn test_non_wildcard_derivations() {
|
|||||||
// - derive new and next unused should return the old script
|
// - derive new and next unused should return the old script
|
||||||
// - store_up_to should not panic and return empty changeset
|
// - store_up_to should not panic and return empty changeset
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index.next_index(&TestKeychain::External).unwrap(),
|
txout_index.next_index(TestKeychain::External).unwrap(),
|
||||||
(0, false)
|
(0, false)
|
||||||
);
|
);
|
||||||
txout_index.mark_used(TestKeychain::External, 0);
|
txout_index.mark_used(TestKeychain::External, 0);
|
||||||
|
|
||||||
let (spk, changeset) = txout_index
|
let (spk, changeset) = txout_index.reveal_next_spk(TestKeychain::External).unwrap();
|
||||||
.reveal_next_spk(&TestKeychain::External)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(spk, (0, external_spk.clone()));
|
assert_eq!(spk, (0, external_spk.clone()));
|
||||||
assert_eq!(&changeset.last_revealed, &[].into());
|
assert_eq!(&changeset.last_revealed, &[].into());
|
||||||
|
|
||||||
let (spk, changeset) = txout_index
|
let (spk, changeset) = txout_index.next_unused_spk(TestKeychain::External).unwrap();
|
||||||
.next_unused_spk(&TestKeychain::External)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(spk, (0, external_spk.clone()));
|
assert_eq!(spk, (0, external_spk.clone()));
|
||||||
assert_eq!(&changeset.last_revealed, &[].into());
|
assert_eq!(&changeset.last_revealed, &[].into());
|
||||||
let (revealed_spks, revealed_changeset) = txout_index
|
let (revealed_spks, revealed_changeset) = txout_index
|
||||||
.reveal_to_target(&TestKeychain::External, 200)
|
.reveal_to_target(TestKeychain::External, 200)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(revealed_spks.len(), 0);
|
assert_eq!(revealed_spks.len(), 0);
|
||||||
assert!(revealed_changeset.is_empty());
|
assert!(revealed_changeset.is_empty());
|
||||||
@ -474,7 +466,7 @@ fn test_non_wildcard_derivations() {
|
|||||||
// we check that spks_of_keychain returns a SpkIterator with just one element
|
// we check that spks_of_keychain returns a SpkIterator with just one element
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
txout_index
|
txout_index
|
||||||
.revealed_keychain_spks(&TestKeychain::External)
|
.revealed_keychain_spks(TestKeychain::External)
|
||||||
.count(),
|
.count(),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
@ -540,10 +532,10 @@ fn lookahead_to_target() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some(last_revealed) = t.external_last_revealed {
|
if let Some(last_revealed) = t.external_last_revealed {
|
||||||
let _ = index.reveal_to_target(&TestKeychain::External, last_revealed);
|
let _ = index.reveal_to_target(TestKeychain::External, last_revealed);
|
||||||
}
|
}
|
||||||
if let Some(last_revealed) = t.internal_last_revealed {
|
if let Some(last_revealed) = t.internal_last_revealed {
|
||||||
let _ = index.reveal_to_target(&TestKeychain::Internal, last_revealed);
|
let _ = index.reveal_to_target(TestKeychain::Internal, last_revealed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let keychain_test_cases = [
|
let keychain_test_cases = [
|
||||||
@ -570,7 +562,7 @@ fn lookahead_to_target() {
|
|||||||
}
|
}
|
||||||
None => target,
|
None => target,
|
||||||
};
|
};
|
||||||
index.lookahead_to_target(&keychain, target);
|
index.lookahead_to_target(keychain.clone(), target);
|
||||||
let keys = index
|
let keys = index
|
||||||
.inner()
|
.inner()
|
||||||
.all_spks()
|
.all_spks()
|
||||||
@ -671,7 +663,7 @@ fn when_querying_over_a_range_of_keychains_the_utxos_should_show_up() {
|
|||||||
let _ = indexer.insert_descriptor(i, descriptor.clone()).unwrap();
|
let _ = indexer.insert_descriptor(i, descriptor.clone()).unwrap();
|
||||||
if i != 4 {
|
if i != 4 {
|
||||||
// skip one in the middle to see if uncovers any bugs
|
// skip one in the middle to see if uncovers any bugs
|
||||||
indexer.reveal_next_spk(&i);
|
indexer.reveal_next_spk(i);
|
||||||
}
|
}
|
||||||
tx.output.push(TxOut {
|
tx.output.push(TxOut {
|
||||||
script_pubkey: descriptor.at_derivation_index(0).unwrap().script_pubkey(),
|
script_pubkey: descriptor.at_derivation_index(0).unwrap().script_pubkey(),
|
||||||
|
@ -6,7 +6,7 @@ mod common;
|
|||||||
use std::collections::{BTreeSet, HashSet};
|
use std::collections::{BTreeSet, HashSet};
|
||||||
|
|
||||||
use bdk_chain::{Balance, BlockId};
|
use bdk_chain::{Balance, BlockId};
|
||||||
use bitcoin::{Amount, OutPoint, Script};
|
use bitcoin::{Amount, OutPoint, ScriptBuf};
|
||||||
use common::*;
|
use common::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -659,7 +659,7 @@ fn test_tx_conflict_handling() {
|
|||||||
&local_chain,
|
&local_chain,
|
||||||
chain_tip,
|
chain_tip,
|
||||||
spk_index.outpoints().iter().cloned(),
|
spk_index.outpoints().iter().cloned(),
|
||||||
|_, spk: &Script| spk_index.index_of_spk(spk).is_some(),
|
|_, spk: ScriptBuf| spk_index.index_of_spk(spk).is_some(),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
balance, scenario.exp_balance,
|
balance, scenario.exp_balance,
|
||||||
|
@ -36,8 +36,8 @@ use bdk_chain::{
|
|||||||
};
|
};
|
||||||
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
|
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
|
||||||
use bitcoin::{
|
use bitcoin::{
|
||||||
absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
|
absolute, psbt, Address, Block, FeeRate, Network, OutPoint, ScriptBuf, Sequence, Transaction,
|
||||||
Transaction, TxOut, Txid, Witness,
|
TxOut, Txid, Witness,
|
||||||
};
|
};
|
||||||
use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
|
use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
|
||||||
use bitcoin::{constants::genesis_block, Amount};
|
use bitcoin::{constants::genesis_block, Amount};
|
||||||
@ -363,8 +363,8 @@ impl Wallet {
|
|||||||
));
|
));
|
||||||
let index = create_indexer(descriptor, change_descriptor, params.lookahead)?;
|
let index = create_indexer(descriptor, change_descriptor, params.lookahead)?;
|
||||||
|
|
||||||
let descriptor = index.get_descriptor(&KeychainKind::External).cloned();
|
let descriptor = index.get_descriptor(KeychainKind::External).cloned();
|
||||||
let change_descriptor = index.get_descriptor(&KeychainKind::Internal).cloned();
|
let change_descriptor = index.get_descriptor(KeychainKind::Internal).cloned();
|
||||||
let indexed_graph = IndexedTxGraph::new(index);
|
let indexed_graph = IndexedTxGraph::new(index);
|
||||||
let indexed_graph_changeset = indexed_graph.initial_changeset();
|
let indexed_graph_changeset = indexed_graph.initial_changeset();
|
||||||
|
|
||||||
@ -542,7 +542,7 @@ impl Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over all keychains in this wallet
|
/// Iterator over all keychains in this wallet
|
||||||
pub fn keychains(&self) -> impl Iterator<Item = (&KeychainKind, &ExtendedDescriptor)> {
|
pub fn keychains(&self) -> impl Iterator<Item = (KeychainKind, &ExtendedDescriptor)> {
|
||||||
self.indexed_graph.index.keychains()
|
self.indexed_graph.index.keychains()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,7 +558,7 @@ impl Wallet {
|
|||||||
let mut spk_iter = self
|
let mut spk_iter = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.unbounded_spk_iter(&keychain)
|
.unbounded_spk_iter(keychain)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
if !spk_iter.descriptor().has_wildcard() {
|
if !spk_iter.descriptor().has_wildcard() {
|
||||||
index = 0;
|
index = 0;
|
||||||
@ -604,7 +604,7 @@ impl Wallet {
|
|||||||
let stage = &mut self.stage;
|
let stage = &mut self.stage;
|
||||||
|
|
||||||
let ((index, spk), index_changeset) = index
|
let ((index, spk), index_changeset) = index
|
||||||
.reveal_next_spk(&keychain)
|
.reveal_next_spk(keychain)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
|
|
||||||
stage.merge(index_changeset.into());
|
stage.merge(index_changeset.into());
|
||||||
@ -634,7 +634,7 @@ impl Wallet {
|
|||||||
let (spks, index_changeset) = self
|
let (spks, index_changeset) = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.reveal_to_target(&keychain, index)
|
.reveal_to_target(keychain, index)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
|
|
||||||
self.stage.merge(index_changeset.into());
|
self.stage.merge(index_changeset.into());
|
||||||
@ -658,7 +658,7 @@ impl Wallet {
|
|||||||
let index = &mut self.indexed_graph.index;
|
let index = &mut self.indexed_graph.index;
|
||||||
|
|
||||||
let ((index, spk), index_changeset) = index
|
let ((index, spk), index_changeset) = index
|
||||||
.next_unused_spk(&keychain)
|
.next_unused_spk(keychain)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
|
|
||||||
self.stage
|
self.stage
|
||||||
@ -702,23 +702,24 @@ impl Wallet {
|
|||||||
) -> impl DoubleEndedIterator<Item = AddressInfo> + '_ {
|
) -> impl DoubleEndedIterator<Item = AddressInfo> + '_ {
|
||||||
self.indexed_graph
|
self.indexed_graph
|
||||||
.index
|
.index
|
||||||
.unused_keychain_spks(&keychain)
|
.unused_keychain_spks(keychain)
|
||||||
.map(move |(index, spk)| AddressInfo {
|
.map(move |(index, spk)| AddressInfo {
|
||||||
index,
|
index,
|
||||||
address: Address::from_script(spk, self.network).expect("must have address form"),
|
address: Address::from_script(spk.as_script(), self.network)
|
||||||
|
.expect("must have address form"),
|
||||||
keychain,
|
keychain,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether or not a `script` is part of this wallet (either internal or external)
|
/// Return whether or not a `script` is part of this wallet (either internal or external)
|
||||||
pub fn is_mine(&self, script: &Script) -> bool {
|
pub fn is_mine(&self, script: ScriptBuf) -> bool {
|
||||||
self.indexed_graph.index.index_of_spk(script).is_some()
|
self.indexed_graph.index.index_of_spk(script).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds how the wallet derived the script pubkey `spk`.
|
/// Finds how the wallet derived the script pubkey `spk`.
|
||||||
///
|
///
|
||||||
/// Will only return `Some(_)` if the wallet has given out the spk.
|
/// Will only return `Some(_)` if the wallet has given out the spk.
|
||||||
pub fn derivation_of_spk(&self, spk: &Script) -> Option<(KeychainKind, u32)> {
|
pub fn derivation_of_spk(&self, spk: ScriptBuf) -> Option<(KeychainKind, u32)> {
|
||||||
self.indexed_graph.index.index_of_spk(spk).cloned()
|
self.indexed_graph.index.index_of_spk(spk).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,7 +784,7 @@ impl Wallet {
|
|||||||
) -> impl Iterator<Item = Indexed<ScriptBuf>> + Clone {
|
) -> impl Iterator<Item = Indexed<ScriptBuf>> + Clone {
|
||||||
self.indexed_graph
|
self.indexed_graph
|
||||||
.index
|
.index
|
||||||
.unbounded_spk_iter(&keychain)
|
.unbounded_spk_iter(keychain)
|
||||||
.expect("keychain must exist")
|
.expect("keychain must exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,7 +1061,7 @@ impl Wallet {
|
|||||||
let descriptor = self
|
let descriptor = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.get_descriptor(&keychain)
|
.get_descriptor(keychain)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
*wallet_signers = SignersContainer::build(keymap, descriptor, &self.secp);
|
*wallet_signers = SignersContainer::build(keymap, descriptor, &self.secp);
|
||||||
}
|
}
|
||||||
@ -1327,7 +1328,7 @@ impl Wallet {
|
|||||||
return Err(CreateTxError::OutputBelowDustLimit(index));
|
return Err(CreateTxError::OutputBelowDustLimit(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_mine(script_pubkey) {
|
if self.is_mine(script_pubkey.clone()) {
|
||||||
received += Amount::from_sat(value);
|
received += Amount::from_sat(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1354,7 +1355,7 @@ impl Wallet {
|
|||||||
let ((index, spk), index_changeset) = self
|
let ((index, spk), index_changeset) = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.next_unused_spk(&change_keychain)
|
.next_unused_spk(change_keychain)
|
||||||
.expect("keychain must exist");
|
.expect("keychain must exist");
|
||||||
self.indexed_graph.index.mark_used(change_keychain, index);
|
self.indexed_graph.index.mark_used(change_keychain, index);
|
||||||
self.stage.merge(index_changeset.into());
|
self.stage.merge(index_changeset.into());
|
||||||
@ -1434,7 +1435,7 @@ impl Wallet {
|
|||||||
remaining_amount, ..
|
remaining_amount, ..
|
||||||
} => fee_amount += remaining_amount,
|
} => fee_amount += remaining_amount,
|
||||||
Change { amount, fee } => {
|
Change { amount, fee } => {
|
||||||
if self.is_mine(&drain_script) {
|
if self.is_mine(drain_script.clone()) {
|
||||||
received += Amount::from_sat(*amount);
|
received += Amount::from_sat(*amount);
|
||||||
}
|
}
|
||||||
fee_amount += fee;
|
fee_amount += fee;
|
||||||
@ -1555,7 +1556,7 @@ impl Wallet {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let weighted_utxo = match txout_index.index_of_spk(&txout.script_pubkey) {
|
let weighted_utxo = match txout_index.index_of_spk(txout.script_pubkey.clone()) {
|
||||||
Some(&(keychain, derivation_index)) => {
|
Some(&(keychain, derivation_index)) => {
|
||||||
let satisfaction_weight = self
|
let satisfaction_weight = self
|
||||||
.public_descriptor(keychain)
|
.public_descriptor(keychain)
|
||||||
@ -1600,7 +1601,7 @@ impl Wallet {
|
|||||||
let mut change_index = None;
|
let mut change_index = None;
|
||||||
for (index, txout) in tx.output.iter().enumerate() {
|
for (index, txout) in tx.output.iter().enumerate() {
|
||||||
let change_keychain = KeychainKind::Internal;
|
let change_keychain = KeychainKind::Internal;
|
||||||
match txout_index.index_of_spk(&txout.script_pubkey) {
|
match txout_index.index_of_spk(txout.script_pubkey.clone()) {
|
||||||
Some((keychain, _)) if *keychain == change_keychain => {
|
Some((keychain, _)) if *keychain == change_keychain => {
|
||||||
change_index = Some(index)
|
change_index = Some(index)
|
||||||
}
|
}
|
||||||
@ -1734,7 +1735,7 @@ impl Wallet {
|
|||||||
pub fn public_descriptor(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
|
pub fn public_descriptor(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
|
||||||
self.indexed_graph
|
self.indexed_graph
|
||||||
.index
|
.index
|
||||||
.get_descriptor(&keychain)
|
.get_descriptor(keychain)
|
||||||
.expect("keychain must exist")
|
.expect("keychain must exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1843,14 +1844,14 @@ impl Wallet {
|
|||||||
/// The derivation index of this wallet. It will return `None` if it has not derived any addresses.
|
/// The derivation index of this wallet. It will return `None` if it has not derived any addresses.
|
||||||
/// Otherwise, it will return the index of the highest address it has derived.
|
/// Otherwise, it will return the index of the highest address it has derived.
|
||||||
pub fn derivation_index(&self, keychain: KeychainKind) -> Option<u32> {
|
pub fn derivation_index(&self, keychain: KeychainKind) -> Option<u32> {
|
||||||
self.indexed_graph.index.last_revealed_index(&keychain)
|
self.indexed_graph.index.last_revealed_index(keychain)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The index of the next address that you would get if you were to ask the wallet for a new address
|
/// The index of the next address that you would get if you were to ask the wallet for a new address
|
||||||
pub fn next_derivation_index(&self, keychain: KeychainKind) -> u32 {
|
pub fn next_derivation_index(&self, keychain: KeychainKind) -> u32 {
|
||||||
self.indexed_graph
|
self.indexed_graph
|
||||||
.index
|
.index
|
||||||
.next_index(&keychain)
|
.next_index(keychain)
|
||||||
.expect("keychain must exist")
|
.expect("keychain must exist")
|
||||||
.0
|
.0
|
||||||
}
|
}
|
||||||
@ -1862,7 +1863,7 @@ impl Wallet {
|
|||||||
pub fn cancel_tx(&mut self, tx: &Transaction) {
|
pub fn cancel_tx(&mut self, tx: &Transaction) {
|
||||||
let txout_index = &mut self.indexed_graph.index;
|
let txout_index = &mut self.indexed_graph.index;
|
||||||
for txout in &tx.output {
|
for txout in &tx.output {
|
||||||
if let Some((keychain, index)) = txout_index.index_of_spk(&txout.script_pubkey) {
|
if let Some((keychain, index)) = txout_index.index_of_spk(txout.script_pubkey.clone()) {
|
||||||
// NOTE: unmark_used will **not** make something unused if it has actually been used
|
// NOTE: unmark_used will **not** make something unused if it has actually been used
|
||||||
// by a tx in the tracker. It only removes the superficial marking.
|
// by a tx in the tracker. It only removes the superficial marking.
|
||||||
txout_index.unmark_used(*keychain, *index);
|
txout_index.unmark_used(*keychain, *index);
|
||||||
@ -1874,7 +1875,7 @@ impl Wallet {
|
|||||||
let &(keychain, child) = self
|
let &(keychain, child) = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.index_of_spk(&txout.script_pubkey)?;
|
.index_of_spk(txout.script_pubkey.clone())?;
|
||||||
let descriptor = self.public_descriptor(keychain);
|
let descriptor = self.public_descriptor(keychain);
|
||||||
descriptor.at_derivation_index(child).ok()
|
descriptor.at_derivation_index(child).ok()
|
||||||
}
|
}
|
||||||
@ -2089,7 +2090,7 @@ impl Wallet {
|
|||||||
let &(keychain, child) = self
|
let &(keychain, child) = self
|
||||||
.indexed_graph
|
.indexed_graph
|
||||||
.index
|
.index
|
||||||
.index_of_spk(&utxo.txout.script_pubkey)
|
.index_of_spk(utxo.txout.script_pubkey)
|
||||||
.ok_or(CreateTxError::UnknownUtxo)?;
|
.ok_or(CreateTxError::UnknownUtxo)?;
|
||||||
|
|
||||||
let mut psbt_input = psbt::Input {
|
let mut psbt_input = psbt::Input {
|
||||||
@ -2135,7 +2136,7 @@ impl Wallet {
|
|||||||
// Try to figure out the keychain and derivation for every input and output
|
// Try to figure out the keychain and derivation for every input and output
|
||||||
for (is_input, index, out) in utxos.into_iter() {
|
for (is_input, index, out) in utxos.into_iter() {
|
||||||
if let Some(&(keychain, child)) =
|
if let Some(&(keychain, child)) =
|
||||||
self.indexed_graph.index.index_of_spk(&out.script_pubkey)
|
self.indexed_graph.index.index_of_spk(out.script_pubkey)
|
||||||
{
|
{
|
||||||
let desc = self.public_descriptor(keychain);
|
let desc = self.public_descriptor(keychain);
|
||||||
let desc = desc
|
let desc = desc
|
||||||
|
@ -4023,7 +4023,7 @@ fn test_tx_cancellation() {
|
|||||||
.unsigned_tx
|
.unsigned_tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
|
.find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(change_derivation_1, (KeychainKind::Internal, 0));
|
assert_eq!(change_derivation_1, (KeychainKind::Internal, 0));
|
||||||
|
|
||||||
@ -4033,7 +4033,7 @@ fn test_tx_cancellation() {
|
|||||||
.unsigned_tx
|
.unsigned_tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
|
.find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(change_derivation_2, (KeychainKind::Internal, 1));
|
assert_eq!(change_derivation_2, (KeychainKind::Internal, 1));
|
||||||
|
|
||||||
@ -4044,7 +4044,7 @@ fn test_tx_cancellation() {
|
|||||||
.unsigned_tx
|
.unsigned_tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
|
.find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(change_derivation_3, (KeychainKind::Internal, 0));
|
assert_eq!(change_derivation_3, (KeychainKind::Internal, 0));
|
||||||
|
|
||||||
@ -4053,7 +4053,7 @@ fn test_tx_cancellation() {
|
|||||||
.unsigned_tx
|
.unsigned_tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
|
.find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(change_derivation_3, (KeychainKind::Internal, 2));
|
assert_eq!(change_derivation_3, (KeychainKind::Internal, 2));
|
||||||
|
|
||||||
@ -4064,7 +4064,7 @@ fn test_tx_cancellation() {
|
|||||||
.unsigned_tx
|
.unsigned_tx
|
||||||
.output
|
.output
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
|
.find_map(|txout| wallet.derivation_of_spk(txout.script_pubkey.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(change_derivation_4, (KeychainKind::Internal, 2));
|
assert_eq!(change_derivation_4, (KeychainKind::Internal, 2));
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ where
|
|||||||
let internal_keychain = if graph
|
let internal_keychain = if graph
|
||||||
.index
|
.index
|
||||||
.keychains()
|
.keychains()
|
||||||
.any(|(k, _)| *k == Keychain::Internal)
|
.any(|(k, _)| k == Keychain::Internal)
|
||||||
{
|
{
|
||||||
Keychain::Internal
|
Keychain::Internal
|
||||||
} else {
|
} else {
|
||||||
@ -261,7 +261,7 @@ where
|
|||||||
|
|
||||||
let ((change_index, change_script), change_changeset) = graph
|
let ((change_index, change_script), change_changeset) = graph
|
||||||
.index
|
.index
|
||||||
.next_unused_spk(&internal_keychain)
|
.next_unused_spk(internal_keychain)
|
||||||
.expect("Must exist");
|
.expect("Must exist");
|
||||||
changeset.merge(change_changeset);
|
changeset.merge(change_changeset);
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ where
|
|||||||
&graph
|
&graph
|
||||||
.index
|
.index
|
||||||
.keychains()
|
.keychains()
|
||||||
.find(|(k, _)| *k == &internal_keychain)
|
.find(|(k, _)| *k == internal_keychain)
|
||||||
.expect("must exist")
|
.expect("must exist")
|
||||||
.1
|
.1
|
||||||
.at_derivation_index(change_index)
|
.at_derivation_index(change_index)
|
||||||
@ -288,7 +288,7 @@ where
|
|||||||
min_drain_value: graph
|
min_drain_value: graph
|
||||||
.index
|
.index
|
||||||
.keychains()
|
.keychains()
|
||||||
.find(|(k, _)| *k == &internal_keychain)
|
.find(|(k, _)| *k == internal_keychain)
|
||||||
.expect("must exist")
|
.expect("must exist")
|
||||||
.1
|
.1
|
||||||
.dust_value(),
|
.dust_value(),
|
||||||
@ -433,7 +433,7 @@ pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + bdk_tmp_plan::CanDeri
|
|||||||
let desc = graph
|
let desc = graph
|
||||||
.index
|
.index
|
||||||
.keychains()
|
.keychains()
|
||||||
.find(|(keychain, _)| *keychain == &k)
|
.find(|(keychain, _)| *keychain == k)
|
||||||
.expect("keychain must exist")
|
.expect("keychain must exist")
|
||||||
.1
|
.1
|
||||||
.at_derivation_index(i)
|
.at_derivation_index(i)
|
||||||
@ -479,7 +479,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ((spk_i, spk), index_changeset) =
|
let ((spk_i, spk), index_changeset) =
|
||||||
spk_chooser(index, &Keychain::External).expect("Must exist");
|
spk_chooser(index, Keychain::External).expect("Must exist");
|
||||||
let db = &mut *db.lock().unwrap();
|
let db = &mut *db.lock().unwrap();
|
||||||
db.append_changeset(&C::from((
|
db.append_changeset(&C::from((
|
||||||
local_chain::ChangeSet::default(),
|
local_chain::ChangeSet::default(),
|
||||||
@ -501,8 +501,8 @@ where
|
|||||||
true => Keychain::Internal,
|
true => Keychain::Internal,
|
||||||
false => Keychain::External,
|
false => Keychain::External,
|
||||||
};
|
};
|
||||||
for (spk_i, spk) in index.revealed_keychain_spks(&target_keychain) {
|
for (spk_i, spk) in index.revealed_keychain_spks(target_keychain) {
|
||||||
let address = Address::from_script(spk, network)
|
let address = Address::from_script(spk.as_script(), network)
|
||||||
.expect("should always be able to derive address");
|
.expect("should always be able to derive address");
|
||||||
println!(
|
println!(
|
||||||
"{:?} {} used:{}",
|
"{:?} {} used:{}",
|
||||||
|
@ -166,7 +166,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
Keychain::External,
|
Keychain::External,
|
||||||
graph
|
graph
|
||||||
.index
|
.index
|
||||||
.unbounded_spk_iter(&Keychain::External)
|
.unbounded_spk_iter(Keychain::External)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
@ -174,7 +174,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
Keychain::Internal,
|
Keychain::Internal,
|
||||||
graph
|
graph
|
||||||
.index
|
.index
|
||||||
.unbounded_spk_iter(&Keychain::Internal)
|
.unbounded_spk_iter(Keychain::Internal)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user