Previously, I have misunderstood the definition of anchor. If a tx is
anchored in a block, it does not necessarily mean it is confirmed in
that block. The tx can be confirmed in an ancestor block of the anchor
block.
With this new definition, we need a new trait `ConfirmationHeight` that
has one method `confirmation_height`. This trait can be used to extend
`Anchor` for those implementations that can give us the exact
conirmation height of a tx (which is useful in most cases).
Another change is to add another variant to the `ObservedAs` enum;
`ObservedAs::ConfirmedImplicit(A)`. If a tx does not have an anchor, but
another tx that spends it has an anchor that in in the best chain, we
can assume that tx is also in the best chain. The logic of
`TxGraph::try_get_chain_position` is also changed to reflect this.
Some methods from `IndexedTxGraph` have been moved to `TxGraph` as they
do not require the `Indexer`. Some `TxGraph` methods have been renamed
for clarity and consistency.
Also more docs are added.
ebd6103e65 Fix policy condition calculation (Alekos Filini)
Pull request description:
### Description
When constructing the `Condition` struct we recursively call `get_condition` on all the items in a threshold and short-circuit if there's an error somewhere (for example, because the policy-path hasn't been provided for a specific threshold).
This can cause issues when the user doesn't care about a subtree, because we still try to call `get_condition` on all the items and fail if something is missing, even if the specific subtree isn't selected and won't be used later on.
This commit changes the logic so that we first filter only the `selected` items, and then unwrap the error using the question mark. If errors happened somewhere else they will be ignored, as they should.
### Notes to the reviewers
I think it makes sense to backport this to `0.27`: even though it's not a critical issue (and there's a workaround[^1] for the bug) it may be a while before the new `1.0` is released. I wouldn't do a release just for this, but I would just leave it there and maybe in a few weeks if there are other fixes to be backported to pre-1.0 they could all be released.
### Changelog notice
- Fixed a bug in the policy condition calculation
### 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:
* [ ] This pull request breaks the existing API
* [x] I've added tests to reproduce the issue which are now passing
* [ ] I'm linking the issue being fixed by this PR
[^1]: The workaround is to simply set the items in the policy tree even if they won't be used. For example, if the item causing troubles is a `thresh(1, ...)` just set `[0]` in the policy path for that id.
ACKs for top commit:
notmandatory:
ACK ebd6103e65
Tree-SHA512: 1e0c6140e47ead3a518656cab660932b40f9e67425ce144f072267c30fd5cae5923ba943d9682af050c8f314756c522260abb68b104b9eeaae597319612984db
The problem with the previous `ChainOracle` interface is that it had no
guarantee for consistency. For example, a block deemed to be part of the
"best chain" can be reorged out. So when `ChainOracle` is called
multiple times for an operation (such as getting the UTXO set), the
returned result may be inconsistent.
This PR changes `ChainOracle::is_block_in_chain` to take in another
input `static_block`, ensuring `block` is an ancestor of `static_block`.
Thus, if `static_block` is consistent across the operation, the result
will be consistent also.
`is_block_in_chain` now returns `Option<bool>`. The `None` case means
that the oracle implementation cannot determine whether block is an
ancestor of static block. `IndexedTxGraph::list_chain_txouts` handles
this case by checking child spends that are in chain, and if so, the
parent tx must be in chain too.
* Instead of implementing `ChainPosition` for `ObservedIn<BlockId>` to
use `FullTxOut` methods (`is_spendable_at` and `is_mature`), we create
alternative versions of those methods that require bounds with `Anchor`.
This removes all `ObservedIn<A>: ChainPosition` bounds for methods of
`IndexedTxGraph`.
* Various improvements to comments and names.
Introduce `chain_oracle::Cache` which is a cache for requests to the
chain oracle. `ChainOracle` has also been moved to the `chain_oracle`
module.
Introduce `get_tip_in_best_chain` method to the `ChainOracle` trait.
This allows for guaranteeing that chain state can be consistent across
operations with `IndexedTxGraph`.
When constructing the `Condition` struct we recursively call
`get_condition` on all the items in a threshold and short-circuit if
there's an error somewhere (for example, because the policy-path hasn't
been provided for a specific threshold).
This can cause issues when the user doesn't care about a subtree, because
we still try to call `get_condition` on all the items and fail if
something is missing, even if the specific subtree isn't selected and
won't be used later on.
This commit changes the logic so that we first filter only the `selected`
items, and then unwrap the error using the question mark. If errors
happened somewhere else they will be ignored, as it should.
Methods of old structures that return transaction(s) no longer return
`TxNode`, but `Transaction` as done previously.
`TxInGraph` is renamed to `TxNode`, while the internal `TxNode` is
renamed to `TxNodeInternal`.
Methods that list chain data have try and non-try versions. Both of
these versions now return an `Iterator`.
* Try versions return `Iterator<Item = Result>`.
* Non-try versions require the `ChainOracle` implementation to be
`ChainOracle<Error = Infallible>`.
The chain oracle keeps track of the best chain, while the transaction
index indexes transaction data in relation to script pubkeys.
This commit also includes initial work on `IndexedTxGraph`.
* Introduce `GraphedTx` struct to access transaction data of graphed
transactions.
* Ability to insert/access anchors and "seen at" values for graphed
transactions.
* `Additions` now records changes to anchors and last_seen_at.
bc3e05c6c6 Doc fixes (Daniela Brozzoni)
352f95f558 [ci] misc fixes (Daniela Brozzoni)
2fcf9c4adb Make async esplora futures Send (LLFourn)
5dd4ce74cf More documentation improvements (志宇)
ae9b19d84c `bdk` README improvements (志宇)
def0c9ed39 Add `wallet_esplora_async` example and various fixes (志宇)
26ab2e2d6c Implement EsploraExt for Async client (Vladimir Fomene)
ab9242d10d Replace current caching solution with Rust Cache (Vladimir Fomene)
0aaf420f6d examples: exit if balance < SEND_AMOUNT (Daniela Brozzoni)
47faa881fb Fix cargo clippy (Daniela Brozzoni)
9d26121dbc Improve stdout output for wallet esplora/electrum examples (志宇)
eddd748870 Add `wallet_electrum` example (志宇)
0505cd7242 Remove transaction-based type parameters and traits (志宇)
de9457fce6 Changed `inflate_update` logic to not depend on `Cow` (志宇)
69cf6d7924 Use os-specific temp dir for `wallet_esplora` example (志宇)
b3836cb308 Use hardcoded send amount for `wallet_esplora` example (志宇)
b082932268 Add the wallet_esplora example (Daniela Brozzoni)
d267517dbd NewError implements StdError (fix typo) (Daniela Brozzoni)
0c7a0abb19 Disable code coverage (Daniela Brozzoni)
dfcbafd6b1 Use action-rs/toolchain in CI (Daniela Brozzoni)
0ba41c5751 Make bdk_esplora wasm compatible again (Daniela Brozzoni)
a38f63359d Make bdk_file_store use bincode v1 (LLFourn)
38ef170ed1 Make bdk and bdk_chain work under 1.57.0 (Steve Myers)
3a5d727899 Update workspace dependencies to be relative paths (Steve Myers)
96d932c830 Add clippy.toml (Daniela Brozzoni)
5708bf0c8c Fix docs (Daniela Brozzoni)
5acee82496 Update rust stable in CI (1.67.0) (Daniela Brozzoni)
8c9bcebc71 Fix the "repository" field in Cargo.toml (Daniela Brozzoni)
c61b3604e1 Fix cargo clippy warnings (Daniela Brozzoni)
1805bd35c0 Fix clippy (Daniela Brozzoni)
3f5a78ae3b Disable test-hardware-signer (Daniela Brozzoni)
303a1703c9 Rust fmt (Daniela Brozzoni)
b5559767db Rename the stub wallet examples (LLFourn)
2e82cd8c04 Use tempfile for file_store tests (LLFourn)
c069b0fb41 Move everything else over 🎉 (LLFourn)
949608ab1f Move bdk_electrum into the bdk repo 🎉 (Daniela Brozzoni)
03deafb553 Move bdk_file_store into the bdk repo 🎉 (Daniela Brozzoni)
37dfa77d9d Move bdk_chain into the bdk repo 🎉 (Daniela Brozzoni)
f2188f9dcd Make lib.rs's docs be the README.md (LLFourn)
1c970a9295 Fix code coverage CI (Daniela Brozzoni)
94a084aafd Fix doc links (LLFourn)
9edbdf54c9 [ci] Fix feature flags (LLFourn)
20e45b7af0 Add back test-hardware-signer feature (LLFourn)
6d05598407 Remove test-readme-examples (LLFourn)
b60820a7b5 Remove authors.workspace because older cargo don't like (LLFourn)
22bec6d363 Delete unused errors (LLFourn)
8a6de3aa2d Convert to workspace (LLFourn)
fdfc9b9ede Delete unused things (LLFourn)
e1eb0253cf Make doctests work (LLFourn)
3baf9721ec Use bdk_chain Balance (LLFourn)
b310a7afdd Add Wallet::cancel_tx (LLFourn)
5985706c1a Add wallet persistence (LLFourn)
57538e53e4 Move tests to /tests (LLFourn)
a40da9ba6c Make bdk no_std (LLFourn)
aab2b12f7a bdk_core integration initial commit 🔥 (LLFourn)
544c397a38 Modified build, clippy and test steps (志宇)
Pull request description:
We prepare the BDK repo for a major restructuring 🔥. This PR maintains the existing wallet API as much as possible and adds very little.
## Things Done
- database modules removed
- blockchain gutted but new esplora syncing code added (this will be gone soon hopefully).
- minimal API changes.
- Many macros removed.
- no longer applicable examples removed.
- Much conditional compilation removed. Can compile with `--all-features` now.
- All wallet tests passing
- TestClient moved into its own repo
- Example using `esplora`
## APIs changed
- wallet no longer has a `sync` method. This is replaced with `apply_wallet_scan`.
- address "caching" is gone. You can just change the derivation index with `ensure_derived_up_to` which sets your derivation to at least the argument. Unlike `ensure_addresses_cached` used to do this will alter what getting a new address gives you.
- `AddressIndex::Reset` is gone. This thing didn't make much sense and is hard to do with the more sane internals we've established. Changing the derivation index changes what script pubkeys the wallet will search so this is dangerous. We plan to add method like `trim_unused` which lowers the derivation index to the highest unused index. Applications must handle giving out old addresses manually now (which I think is good).
## Unfinished work
- [x] esplora example doesn't work for mempool transactions yet (seems like our esplora in testclient doesn't index mempool??).
- [x] we need to figure out a way to retrieve and store transaction timestamps (we're currently just setting them to `u64::MAX`). In `bdk_core` we never got around to doing this but it needs to be done.
- [x] A few insights we got from doing this PR should be applied to bdk_core first.
- [x] doctests not working.
### Notes to the reviewers
Try not to review the actual changes. This PR will be forced pushed a bit so it will be likely wasted.
I think I did a faithful job of translating the tests. A bit of review here would be helpful.
I *do* think it would be good to merge this PR soon into the v1 branch so we have something to work off once unfinished work is done.
Checking out the branch and poke around and give feedback would be the most helpful thing.
Run the (sort of) working example:
```
cargo run --example esplora --features="bdk_test_client/bitcoind_22_0 bdk_test_client/esplora esplora"
```
### 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
#### Bugfixes:
* [x] This pull request breaks the existing API
* [ ] I'm linking the issue being fixed by this PR (there's too many!)
ACKs for top commit:
danielabrozzoni:
ACK bc3e05c6c6
Tree-SHA512: b5fbfd2263bb2a7cbf7b486530e639683775209bea944b266efd9c0447fb632295f7f5ddbd2e8d79796338415eaca26f1876617c2b66523485167b22e75e449e