[Chronik] Fix: Race condition when re-orging a block with txs
Summary:
The current built-in node crashes with a Couldn't find coin for input error when a block containing txs gets reorged in some situations.
Here's what happened (with the bug-relevant bits bold):
- Connected block A, which contained tx T
- Received block B, which also contained T
- Avalanche selected block B to be finalized
- Node disconnected block A (Chronik didn't receive this yet)
- Node added T back to the mempool (due to the re-org)
- Node connected block B, removing T and marking its coins as spent
- Only now Chronik disconnects block A
- Chronik adds T back to the mempool (due to the re-org), however, FindCoins can't find the coins anymore, as they've been spent in step 6.
To fix this, we thread the spent_coins from the node to the validation interface queue, by adding spent_coins to TransactionAddedToMempool. This way Chronik is guaranteed to have the spent coins ready without having to query them from the node.
We use a std::shared_ptr<const std::vector<Coin>>, to ensure coins aren't freed and reused before they're used by the indexer. The interfaces take an owned shared_ptr, to make sure the memory isn't freed too early. In the (relatively far) future, we might move spent_coins into CTransaction, which would manage the memory for us.
List of changes:
- Add (Rust) CCoin to the FFI pointing to C++'s Coin.
- Change bridge_tx to take a vector of spent coins instead of ChronikBridge (and fix the bug).
- Thread the spent coins to handle_tx_added_to_mempool and feed them to bridge_tx.
Depends on D14386.
Test Plan: ninja check-functional
Reviewers: Fabien, #bitcoin_abc
Reviewed By: Fabien, #bitcoin_abc
Differential Revision: https://reviews.bitcoinabc.org/D14361