diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 8c52df76952..a50473d5cd5 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -611,14 +611,13 @@ where /// Waits for the UTXOs that are being spent by the given transaction to arrive in /// the state for [`Block`](Request::Block) requests. /// - /// `known_utxos` are additional UTXOs known at the time of validation (i.e. - /// from previous transactions in the block). - /// /// Looks up UTXOs that are being spent by the given transaction in the state or waits /// for them to be added to the mempool for [`Mempool`](Request::Mempool) requests. /// - /// Returns a tuple with a OutPoint -> Utxo map, and a vector of Outputs - /// in the same order as the matching inputs in the transaction. + /// Returns a triple containing: + /// - `OutPoint` -> `Utxo` map, + /// - vec of `Output`s in the same order as the matching inputs in the `tx`, + /// - vec of `Outpoint`s spent by a mempool `tx` that were not found in the best chain's utxo set. async fn spent_utxos( tx: Arc, req: Request, @@ -633,6 +632,8 @@ where TransactionError, > { let is_mempool = req.is_mempool(); + // Additional UTXOs known at the time of validation, + // i.e., from previous transactions in the block. let known_utxos = req.known_utxos(); let inputs = tx.inputs(); diff --git a/zebra-node-services/src/mempool/transaction_dependencies.rs b/zebra-node-services/src/mempool/transaction_dependencies.rs index 6a6999ae44c..4b5e747a58d 100644 --- a/zebra-node-services/src/mempool/transaction_dependencies.rs +++ b/zebra-node-services/src/mempool/transaction_dependencies.rs @@ -7,7 +7,7 @@ use zebra_chain::{transaction, transparent}; /// Representation of mempool transactions' dependencies on other transactions in the mempool. #[derive(Default, Debug, Clone)] pub struct TransactionDependencies { - /// Lists of mempool transactions that create UTXOs spent by + /// Lists of mempool transaction ids that create UTXOs spent by /// a mempool transaction. Used during block template construction /// to exclude transactions from block templates unless all of the /// transactions they depend on have been included. diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/zip317.rs b/zebra-rpc/src/methods/get_block_template_rpcs/zip317.rs index 710d15f8958..fbb9283154e 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs/zip317.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs/zip317.rs @@ -198,6 +198,10 @@ fn has_direct_dependencies( return true; }; +if selected_txs.len() < deps.len() { + return false; +} + let mut num_available_deps = 0; for tx in selected_txs { #[cfg(test)] @@ -291,6 +295,12 @@ fn checked_add_transaction_weighted_random( let mut next_level_dependents = HashSet::new(); for dependent_tx_id in ¤t_level_dependents { + // ## Note + // + // A necessary condition for adding the dependent tx is that it spends unmined outputs coming only from + // the selected txs, which come from the mempool. If the tx also spends in-chain outputs, it won't + // be added. This behavior is not specified by consensus rules and can be changed at any time, + // meaning that such txs could be added. if has_direct_dependencies(tx_dependencies.get(dependent_tx_id), selected_txs) { let Some(candidate_tx) = dependent_txs.remove(dependent_tx_id) else { continue;