kernel: Add function to read block undo data from disk to C header

This adds functions for reading the undo data from disk with a retrieved
block tree entry. The undo data of a block contains all the spent
script pubkeys of all the transactions in a block. For ease of
understanding the undo data is renamed to spent outputs with seperate
data structures exposed for a block's and a transaction's spent outputs.

In normal operations undo data is used during re-orgs. This data might
also be useful for building external indexes, or to scan for silent
payment transactions.

Internally the block undo data contains a vector of transaction undo
data which contains a vector of the coins consumed. The coins are all
int the order of the transaction inputs of the consuming transactions.
Each coin can be used to retrieve a transaction output and in turn a
script pubkey and amount.

This translates to the three-level hierarchy the api provides: Block
spent outputs contain transaction spent outputs, which contain
individual coins. Each coin includes the associated output, the height
of the block is contained in, and whether it is from a coinbase
transaction.
This commit is contained in:
TheCharlatan
2024-06-01 14:47:56 +02:00
parent 09d0f62638
commit f5d5d1213c
4 changed files with 420 additions and 4 deletions

View File

@@ -790,6 +790,105 @@ public:
}
};
template <typename Derived>
class CoinApi
{
private:
auto impl() const
{
return static_cast<const Derived*>(this)->get();
}
friend Derived;
CoinApi() = default;
public:
uint32_t GetConfirmationHeight() const { return btck_coin_confirmation_height(impl()); }
bool IsCoinbase() const { return btck_coin_is_coinbase(impl()) == 1; }
TransactionOutputView GetOutput() const
{
return TransactionOutputView{btck_coin_get_output(impl())};
}
};
class CoinView : public View<btck_Coin>, public CoinApi<CoinView>
{
public:
explicit CoinView(const btck_Coin* ptr) : View{ptr} {}
};
class Coin : public Handle<btck_Coin, btck_coin_copy, btck_coin_destroy>, public CoinApi<Coin>
{
public:
Coin(btck_Coin* coin) : Handle{coin} {}
Coin(const CoinView& view) : Handle{view} {}
};
template <typename Derived>
class TransactionSpentOutputsApi
{
private:
auto impl() const
{
return static_cast<const Derived*>(this)->get();
}
friend Derived;
TransactionSpentOutputsApi() = default;
public:
size_t Count() const
{
return btck_transaction_spent_outputs_count(impl());
}
CoinView GetCoin(size_t index) const
{
return CoinView{btck_transaction_spent_outputs_get_coin_at(impl(), index)};
}
MAKE_RANGE_METHOD(Coins, Derived, &TransactionSpentOutputsApi<Derived>::Count, &TransactionSpentOutputsApi<Derived>::GetCoin, *static_cast<const Derived*>(this))
};
class TransactionSpentOutputsView : public View<btck_TransactionSpentOutputs>, public TransactionSpentOutputsApi<TransactionSpentOutputsView>
{
public:
explicit TransactionSpentOutputsView(const btck_TransactionSpentOutputs* ptr) : View{ptr} {}
};
class TransactionSpentOutputs : public Handle<btck_TransactionSpentOutputs, btck_transaction_spent_outputs_copy, btck_transaction_spent_outputs_destroy>,
public TransactionSpentOutputsApi<TransactionSpentOutputs>
{
public:
TransactionSpentOutputs(btck_TransactionSpentOutputs* transaction_spent_outputs) : Handle{transaction_spent_outputs} {}
TransactionSpentOutputs(const TransactionSpentOutputsView& view) : Handle{view} {}
};
class BlockSpentOutputs : public Handle<btck_BlockSpentOutputs, btck_block_spent_outputs_copy, btck_block_spent_outputs_destroy>
{
public:
BlockSpentOutputs(btck_BlockSpentOutputs* block_spent_outputs)
: Handle{block_spent_outputs}
{
}
size_t Count() const
{
return btck_block_spent_outputs_count(get());
}
TransactionSpentOutputsView GetTxSpentOutputs(size_t tx_undo_index) const
{
return TransactionSpentOutputsView{btck_block_spent_outputs_get_transaction_spent_outputs_at(get(), tx_undo_index)};
}
MAKE_RANGE_METHOD(TxsSpentOutputs, BlockSpentOutputs, &BlockSpentOutputs::Count, &BlockSpentOutputs::GetTxSpentOutputs, *this)
};
class ChainMan : UniqueHandle<btck_ChainstateManager, btck_chainstate_manager_destroy>
{
public:
@@ -831,6 +930,11 @@ public:
if (!block) return std::nullopt;
return block;
}
BlockSpentOutputs ReadBlockSpentOutputs(const BlockTreeEntry& entry) const
{
return btck_block_spent_outputs_read(get(), entry.get());
}
};
} // namespace btck