Introduce redesigned bdk_chain structures#926
Introduce redesigned bdk_chain structures#926danielabrozzoni merged 48 commits intobitcoindevkit:masterfrom
bdk_chain structures#926Conversation
7685ca2 to
b9277fe
Compare
2f2278b to
9d4f0ca
Compare
* 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.
aecc8f2 to
56bb46e
Compare
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`.
da62bbb to
a038c00
Compare
Add methods to `TxGraph` and `IndexedTxGraph` that gets in-best-chain data (such as transactions, txouts, unspent txouts).
a038c00 to
43b648f
Compare
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>`.
* Get mutable index from `IndexedChainGraph`. * Also add `apply_additions` method to `TxIndex` trait.
…height This is important as a `ChainOracle` implementation is updated separately to an `IndexedTxGraph`.
|
@rajarshimaitra will be working on adding unit tests for |
There was a problem hiding this comment.
Overall this looks good to me; two final nonblocking comments. The resolution for where to put the confirmation height should ideally be included in this PR. But if not can be done later. Tracking issue here #951
I am covering on the remaining tests for IndexedTxGraph. Need OwnedIndexer on SpkTxOutIndex for that. Will do it myself on my branch. If included in this PR anyway, would rebase on it.
LLFourn
left a comment
There was a problem hiding this comment.
I'm approving this pending @evanlinjin addressing my comments in whatever way he wants. Thanks for all the work put into this @evanlinjin. It's sooooooo much better now. Looking forward to using this.
* `Additions` now implements `Append` and uses `Append` to implement `append()`. * `append()` logic enforces that `last_seen` values should only increase. * Test written for `append()` with `last_seen` behaviour.
* `IndexedTxGraph::try_balance` should include "confirmed and spendable" into `confirmed` balance. * `TxGraph::try_list_chain_unspents` filter logic should be reversed.
`SpkTxOutIndex` and `KeychainTxOutIndex` now both implement `OwnedIndexer`.
These tests cover list_txout, list_utxo and balance methods.
|
ACK b799a57 I had some clean-up pushes for the tests. Should I push them here? (I don't have push access in your branch). |
rajarshimaitra
left a comment
There was a problem hiding this comment.
ACK b799a57
I will push cleanups in a separate PR..
IndexedTxGraphbdk_chain structures
danielabrozzoni
left a comment
There was a problem hiding this comment.
Partial ACK b799a57 - good job! I haven't looked at the tests or at the methods implementations in depth, but I have reviewed the architecture and it looks good. I have a few non-blocking questions.
Let's goo 🚀
| /// Trait that "anchors" blockchain data to a specific block of height and hash. | ||
| /// | ||
| /// I.e. If transaction A is anchored in block B, then if block B is in the best chain, we can | ||
| /// assume that transaction A is also confirmed in the best chain. This does not necessarily mean | ||
| /// that transaction A is confirmed in block B. It could also mean transaction A is confirmed in a | ||
| /// parent block of B. |
There was a problem hiding this comment.
Looking at Anchor's definition, I'm wondering if there's something else it could make sense to implement it on, other than BlockId.
I'm not saying that Anchor shouldn't be a generic, I'm just wondering if you thought of any other structure that could be used as a anchor :)
There was a problem hiding this comment.
Anchor implementations can be a lot more expressive. For example, Anchor with the exact confirmation height and/or time of the transaction. Or an Anchor with the exact merkle proof.
There was a problem hiding this comment.
FWIW I think anchor should not be implemented on BlockId. The semantics of it are ambiguous. Does it imply that the transaction is anchored to that block because the transaction is in the block or does that block merely imply that the transaction is in the block? I didn't mention this because I thought the discussion would come up later anyway.
| } | ||
|
|
||
| /// A trait that extends [`Indexer`] to also index "owned" script pubkeys. | ||
| pub trait OwnedIndexer: Indexer { |
There was a problem hiding this comment.
(nit: this is not a super explicative name)
There was a problem hiding this comment.
This is a side note, but I've actually started doubting whether we need this trait. It is basically used for filtering only (which can be done in layers above).
There was a problem hiding this comment.
I'm not sure but I think I mentioned that this trait has the wrong name in my mind. It should at least have Spk in the name because it can only answer queries about owning spks. It can just be called SpkOwner. There's also no need to require it implements Indexer. I would define it as:
pub trait TxoOwner {
pub fn owns(&self, tx: &Transaction, vout: u32) -> bool;
}because this is strictly more general and covers silent payments.
| pub struct LocalChain { | ||
| blocks: BTreeMap<u32, BlockHash>, | ||
| } |
There was a problem hiding this comment.
Is the LocalChain sparse, or does it have all the blocks?
Description
This is part of #895
The initial
bdk_chainstructures allowed updating to be done without blocking IO (alongside many other benefits). However, the requirement to have transactions "perfectly positioned" in ourSparseChainincreased complexity of the syncing API. Updates needed to be meticulously crafted to properly connect with the originalSparseChain. Additionally, it forced us to keep a local copy of the "best chain" data (which may not always be needed depending on the chain source).The redesigned structures, as introduced by this PR, fixes these shortcomings.
SparseChain, we introduce the ability toAnchora transaction to multiple blocks that may or may not be in the same chain history. We expandTxGraphto records these anchors (while still maintaining the monotone nature ofTxGraph). When updating our newTxGraph, we don't need to complicated are-we-connected checks that we need forSparseChain.TxGraphis all that we need to determine the "chain position" of a transaction. The chain source only needs to implement a single traitChainOracle. This typically does not need to be updated (as it is remote), although we can have a specialChainOracleimplementation that is stored locally. This only needs block height and hash information, reducing the scope of non-monotine structures that need to be updated.What is done:
TxGraphincludes anchors (ids of blocks that the tx is seen in) and last-seem unix timestamp (for determining which non-confirmed tx we should consider as part of "best chain" if there are conflicts). This structure continues to be fully "monotone"; we can introduce data in any manner and not risk resulting in an inconsistent state.LocalChainincludes the "checkpoint" logic ofSparseChainbut removes thetxiddata.LocalChainimplements theChainOracletrait. Any blockchain-source can also implement theChainOracletrait.IndexedTxGraphis introduced and contains two fields; an internalTxGraphstruct and aTxIndeximplementation. These two fields will be updated atomically and can replace the functionality ofkeychain::Tracker.What is in-progress:
@evanlinjin: TheTxIndextrait should not haveis_{}_relevantmethods as we cannot guarantee this across all transaction indexes. We should introduce extension traits for these (Introduce redesignedbdk_chainstructures #926 (comment)).@evanlinjin:BlockAnchorshould be defined as "if this block is in chain, then this tx must be in chain". Therefore, the anchor does not provide us with the exact confirmation height of the tx. We need to introduce an extension traitExactConfirmationHeightAnchorfor certain operations (Introduce redesignedbdk_chainstructures #926 (comment)).What will be done external to this PR:
indexed_tx_graph::Additions(Update persistance With newIndexedTxGraph#937).bdk::Walletto use the redesigned structures.Changelog notice
bdk_chainredesign (as mentioned in Redesigning bdk_chain around a "ChainOracle" #895). Currently, only thebdk_chaincore structures are implemented. Persistence and updates to the current examples andbdk::Walletwill be done in separate PRs.Checklists
All Submissions:
cargo fmtandcargo clippybefore committingNew Features: