keychain::ChangeSet includes the descriptor

- The KeychainTxOutIndex's internal SpkIterator now uses DescriptorId
  instead of K. The DescriptorId -> K translation is made at the
  KeychainTxOutIndex level.
- The keychain::Changeset is now a struct, which includes a map for last
  revealed indexes, and one for newly added keychains and their
  descriptor.

API changes in bdk:
- Wallet::keychains returns a `impl Iterator` instead of `BTreeMap`
- Wallet::load doesn't take descriptors anymore, since they're stored in
  the db
- Wallet::new_or_load checks if the loaded descriptor from db is the
  same as the provided one

API changes in bdk_chain:
- `ChangeSet` is now a struct, which includes a map for last revealed
  indexes, and one for keychains and descriptors.
- `KeychainTxOutIndex::inner` returns a `SpkIterator<(DescriptorId, u32)>`
- `KeychainTxOutIndex::outpoints` returns a `impl Iterator` instead of `&BTreeSet`
- `KeychainTxOutIndex::keychains` returns a `impl Iterator` instead of
  `&BTreeMap`
- `KeychainTxOutIndex::txouts` doesn't return a ExactSizeIterator
  anymore
- `KeychainTxOutIndex::unbounded_spk_iter` returns an `Option`
- `KeychainTxOutIndex::next_index` returns an `Option`
- `KeychainTxOutIndex::last_revealed_indices` returns a `BTreeMap`
  instead of `&BTreeMap`
- `KeychainTxOutIndex::reveal_to_target` returns an `Option`
- `KeychainTxOutIndex::reveal_next_spk` returns an `Option`
- `KeychainTxOutIndex::next_unused_spk` returns an `Option`
- `KeychainTxOutIndex::add_keychain` has been renamed to
  `KeychainTxOutIndex::insert_descriptor`, and now it returns a
  ChangeSet
This commit is contained in:
Daniela Brozzoni
2024-01-15 18:52:03 +01:00
parent 8ff99f27df
commit 4f05441a00
15 changed files with 979 additions and 432 deletions

View File

@@ -249,14 +249,20 @@ where
script_pubkey: address.script_pubkey(),
}];
let internal_keychain = if graph.index.keychains().get(&Keychain::Internal).is_some() {
let internal_keychain = if graph
.index
.keychains()
.any(|(k, _)| *k == Keychain::Internal)
{
Keychain::Internal
} else {
Keychain::External
};
let ((change_index, change_script), change_changeset) =
graph.index.next_unused_spk(&internal_keychain);
let ((change_index, change_script), change_changeset) = graph
.index
.next_unused_spk(&internal_keychain)
.expect("Must exist");
changeset.append(change_changeset);
// Clone to drop the immutable reference.
@@ -266,8 +272,9 @@ where
&graph
.index
.keychains()
.get(&internal_keychain)
.find(|(k, _)| *k == &internal_keychain)
.expect("must exist")
.1
.at_derivation_index(change_index)
.expect("change_index can't be hardened"),
&assets,
@@ -284,8 +291,9 @@ where
min_drain_value: graph
.index
.keychains()
.get(&internal_keychain)
.find(|(k, _)| *k == &internal_keychain)
.expect("must exist")
.1
.dust_value(),
..CoinSelectorOpt::fund_outputs(
&outputs,
@@ -416,7 +424,7 @@ pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + bdk_tmp_plan::CanDeri
assets: &bdk_tmp_plan::Assets<K>,
) -> Result<Vec<PlannedUtxo<K, A>>, O::Error> {
let chain_tip = chain.get_chain_tip()?;
let outpoints = graph.index.outpoints().iter().cloned();
let outpoints = graph.index.outpoints();
graph
.graph()
.try_filter_chain_unspents(chain, chain_tip, outpoints)
@@ -428,8 +436,9 @@ pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + bdk_tmp_plan::CanDeri
let desc = graph
.index
.keychains()
.get(&k)
.find(|(keychain, _)| *keychain == &k)
.expect("keychain must exist")
.1
.at_derivation_index(i)
.expect("i can't be hardened");
let plan = bdk_tmp_plan::plan_satisfaction(&desc, assets)?;
@@ -465,7 +474,8 @@ where
_ => unreachable!("only these two variants exist in match arm"),
};
let ((spk_i, spk), index_changeset) = spk_chooser(index, &Keychain::External);
let ((spk_i, spk), index_changeset) =
spk_chooser(index, &Keychain::External).expect("Must exist");
let db = &mut *db.lock().unwrap();
db.stage_and_commit(C::from((
local_chain::ChangeSet::default(),
@@ -517,7 +527,7 @@ where
let balance = graph.graph().try_balance(
chain,
chain.get_chain_tip()?,
graph.index.outpoints().iter().cloned(),
graph.index.outpoints(),
|(k, _), _| k == &Keychain::Internal,
)?;
@@ -547,7 +557,7 @@ where
let graph = &*graph.lock().unwrap();
let chain = &*chain.lock().unwrap();
let chain_tip = chain.get_chain_tip()?;
let outpoints = graph.index.outpoints().iter().cloned();
let outpoints = graph.index.outpoints();
match txout_cmd {
TxOutCmd::List {
@@ -695,9 +705,11 @@ where
let mut index = KeychainTxOutIndex::<Keychain>::default();
// TODO: descriptors are already stored in the db, so we shouldn't re-insert
// them in the index here. However, the keymap is not stored in the database.
let (descriptor, mut keymap) =
Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &args.descriptor)?;
index.add_keychain(Keychain::External, descriptor);
let _ = index.insert_descriptor(Keychain::External, descriptor);
if let Some((internal_descriptor, internal_keymap)) = args
.change_descriptor
@@ -706,7 +718,7 @@ where
.transpose()?
{
keymap.extend(internal_keymap);
index.add_keychain(Keychain::Internal, internal_descriptor);
let _ = index.insert_descriptor(Keychain::Internal, internal_descriptor);
}
let mut db_backend = match Store::<C>::open_or_create_new(db_magic, &args.db_path) {