Summary
libbitcoin-server duplicates standalone transaction validation and pool context logic across its bitcoind RPC and electrum protocols. Both implement identical get_pool_context, validate_tx, and broadcast_tx helpers. This logic belongs in a shared node side utility, alongside the transaction chaser that will own unconfirmed transaction handling. This issue requests exposing that utility from libbitcoin-node so server protocols can call through instead of reimplementing it, and tracks the node dependency for full transaction submission.
Background
The node already scaffolds a transaction chaser (include/bitcoin/node/chasers/chaser_transaction.hpp, described as "Chase down unconfirmed transactions"), but its methods are stubs. In src/chasers/chaser_transaction.cpp the key methods carry TODOs, including "validate and store transaction" in do_store and "Push new checked tx into store and update DAG. Issue transaction event" in store. Until the chaser owns transaction validation and the unconfirmed pool, server protocols each reimplement the validation pipeline against confirmed chain state.
Current duplication in libbitcoin-server
The same logic exists twice, each with a "move this to node utility and pass through" TODO: in src/protocols/bitcoind/protocol_bitcoind_rpc.cpp and in src/protocols/electrum/protocol_electrum_transactions.cpp (get_pool_context, validate_tx, broadcast_tx).
get_pool_context derives a chain::context from the confirmed tip:
top = query.get_top_confirmed();
state = query.get_chain_state(settings, query.get_header_key(to_confirmed(top)));
pool = chain::chain_state(*state, settings).context();
validate_tx validates a standalone transaction against that context:
tx.check();
tx.check(ctx);
query.populate_with_metadata(tx, true);
tx.accept(ctx);
tx.confirm(ctx);
tx.connect(ctx);
tx.check_guard(); // block consensus guards (DoS guard for a
tx.check_guard(ctx); // transaction validated outside of a block)
tx.accept_guard(ctx);
Separately, transaction submission cannot archive or broadcast in v4. The server's sendrawtransaction validates and broadcasts only, with a comment that archiving must move through the transaction chaser in v5. Full submission (archive so the tx out relay can serve getdata) therefore also depends on the chaser.
Requested change
Provide, from libbitcoin-node, a single entry point that server protocols can call to:
- Obtain the current pool (mempool) context.
- Validate a standalone transaction against that context (the pipeline above), returning a
code.
- Submit a validated transaction: broadcast it and, in v5, archive it via the transaction chaser so the tx out relay can serve getdata.
This gives a single owner for standalone transaction validation and lets both server protocols drop their duplicate helpers.
Downstream follow up (libbitcoin-server)
Once available, replace get_pool_context, validate_tx, and broadcast_tx in protocol_bitcoind_rpc and protocol_electrum with calls to the node utility, removing both "move this to node utility" TODOs. Re-enable archive on submit in sendrawtransaction via the chaser, removing the commented v4 block and its "contextual validation (populate_with_metadata + connect) for policy" TODO.
Scope decision needed
Whether this issue covers only the shared standalone validation and pool context utility (which enables the server dedup immediately), or also the full chaser_transaction implementation (unconfirmed pool, mempool message support). The dedup utility can land first and reuse the existing confirmed chain state; full archive and relay on submit depend on the chaser being implemented.
Summary
libbitcoin-server duplicates standalone transaction validation and pool context logic across its bitcoind RPC and electrum protocols. Both implement identical
get_pool_context,validate_tx, andbroadcast_txhelpers. This logic belongs in a shared node side utility, alongside the transaction chaser that will own unconfirmed transaction handling. This issue requests exposing that utility from libbitcoin-node so server protocols can call through instead of reimplementing it, and tracks the node dependency for full transaction submission.Background
The node already scaffolds a transaction chaser (
include/bitcoin/node/chasers/chaser_transaction.hpp, described as "Chase down unconfirmed transactions"), but its methods are stubs. Insrc/chasers/chaser_transaction.cppthe key methods carry TODOs, including "validate and store transaction" indo_storeand "Push new checked tx into store and update DAG. Issue transaction event" instore. Until the chaser owns transaction validation and the unconfirmed pool, server protocols each reimplement the validation pipeline against confirmed chain state.Current duplication in libbitcoin-server
The same logic exists twice, each with a "move this to node utility and pass through" TODO: in
src/protocols/bitcoind/protocol_bitcoind_rpc.cppand insrc/protocols/electrum/protocol_electrum_transactions.cpp(get_pool_context,validate_tx,broadcast_tx).get_pool_contextderives achain::contextfrom the confirmed tip:validate_txvalidates a standalone transaction against that context:Separately, transaction submission cannot archive or broadcast in v4. The server's
sendrawtransactionvalidates and broadcasts only, with a comment that archiving must move through the transaction chaser in v5. Full submission (archive so the tx out relay can serve getdata) therefore also depends on the chaser.Requested change
Provide, from libbitcoin-node, a single entry point that server protocols can call to:
code.This gives a single owner for standalone transaction validation and lets both server protocols drop their duplicate helpers.
Downstream follow up (libbitcoin-server)
Once available, replace
get_pool_context,validate_tx, andbroadcast_txinprotocol_bitcoind_rpcandprotocol_electrumwith calls to the node utility, removing both "move this to node utility" TODOs. Re-enable archive on submit insendrawtransactionvia the chaser, removing the commented v4 block and its "contextual validation (populate_with_metadata + connect) for policy" TODO.Scope decision needed
Whether this issue covers only the shared standalone validation and pool context utility (which enables the server dedup immediately), or also the full
chaser_transactionimplementation (unconfirmed pool, mempool message support). The dedup utility can land first and reuse the existing confirmed chain state; full archive and relay on submit depend on the chaser being implemented.