Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/mining/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use std::sync::Arc;
use std::vec::Vec;

use bitcoin_rs_mempool::SnapshotEntry;
use bitcoin_rs_primitives::{Block, BlockHash, Header, Network, Tx, Txid};
use compact_str::CompactString;

Expand Down Expand Up @@ -216,6 +217,8 @@ pub enum MiningControlError {
pub enum GenerateTx {
/// Include this currently-pooled transaction, looked up by txid.
Mempool(Txid),
/// Include this transaction resolved from the mempool at parse time.
ResolvedMempool(SnapshotEntry),
Comment on lines +220 to +221

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. resolvedmempool breaks compatibility tests 📘 Rule violation ≡ Correctness

GenerateTx derives Eq and PartialEq, but the new ResolvedMempool(SnapshotEntry) payload
implements neither trait, causing trait-bound compilation failures; after restoring comparability,
generateblock_keeps_raw_transactions must also be updated because it still expects the obsolete
GenerateTx::Mempool variant instead of the newly emitted ResolvedMempool variant.
Agent Prompt
## Issue description
The new `ResolvedMempool(SnapshotEntry)` variant is incompatible with `GenerateTx`'s derived `Eq` and `PartialEq` traits, and the existing request assertion still expects the old `GenerateTx::Mempool` variant. Restore compilation by making the payload comparable or changing the surrounding equality implementation without weakening required test behavior, then update the test for the resolved mempool entry produced by parsing.

## Issue Context
API-24 compatibility must be verified by executable tests. `SnapshotEntry` contains equality-compatible scalar fields, a transaction `Arc`, and an ancestor vector, so deriving the missing traits is likely sufficient; once `GenerateTx` remains comparable, the observable-behavior test must assert the newly emitted `ResolvedMempool` variant.

## Fix Focus Areas
- crates/mining/src/control.rs[215-223]
- crates/mempool/src/pool.rs[189-230]
- crates/rpc/src/handlers/mining.rs[2108-2116]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

/// Include this decoded raw transaction even if it is not in the mempool.
Raw(Tx),
}
Expand Down
6 changes: 5 additions & 1 deletion crates/node/src/mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,11 @@ fn snapshot_for_selection(
let old_usize = usize::try_from(old).unwrap_or(usize::MAX);
selected.push(full.entries[old_usize].clone());
}
GenerateTx::Raw(tx) => selected.push(snapshot_entry_from_raw(tx)),
GenerateTx::ResolvedMempool(mut entry) => {
entry.ancestors.clear();
selected.push(entry);
}
GenerateTx::Raw(tx) => selected.push(snapshot_entry_from_raw(tx)),
}
}
for entry in &mut selected {
Expand Down
87 changes: 76 additions & 11 deletions crates/rpc/src/handlers/mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ pub(crate) fn generateblock(ctx: &Arc<Context>, params: &Value) -> Result<Value,
.ok_or(RpcError::MethodDisabled("mining is unavailable"))?;
let output = required_str(params, 0, "output is required")?;
let payout = generateblock_payout_script(output, convert::bitcoin_network(ctx.chain_network))?;
let transactions = parse_generateblock_transactions(params)?;
let transactions = parse_generateblock_transactions(ctx, params)?;
let submit = optional_bool(params, 2, true)?;
let generated = control
.generate(GenerateRequest {
Expand Down Expand Up @@ -362,7 +362,10 @@ fn optional_u64(params: &Value, index: usize, default: u64) -> Result<u64, RpcEr
.ok_or(RpcError::InvalidType("parameter must be an integer"))
}

fn parse_generateblock_transactions(params: &Value) -> Result<Vec<GenerateTx>, RpcError> {
fn parse_generateblock_transactions(
ctx: &Context,
params: &Value,
) -> Result<Vec<GenerateTx>, RpcError> {
let array = params_array(params)?;
let Some(value) = array.get(1) else {
return Err(RpcError::InvalidParams("transactions is required"));
Expand All @@ -380,19 +383,32 @@ fn parse_generateblock_transactions(params: &Value) -> Result<Vec<GenerateTx>, R
"transactions must be an array of hex strings",
));
};
// CONTRACT: docs/contracts/external-api.md#API-24
if let Ok(txid) = Txid::from_str(text) {
transactions.push(GenerateTx::Mempool(txid));
let snapshot = ctx.mempool.read().mining_snapshot();
let Some(entry) = snapshot.entries.into_iter().find(|entry| entry.txid == txid) else {
Comment on lines +388 to +389

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Snapshot rebuilt per txid 🐞 Bug ➹ Performance

Each txid-shaped array entry rebuilds and scans a complete mempool mining snapshot, making parsing
O(requested txids × mempool size) with repeated allocations and ancestor-topology reconstruction.
Large valid generateblock requests can therefore hold the mempool read path and consume
substantially more CPU than necessary.
Agent Prompt
## Issue description
`parse_generateblock_transactions` calls `mining_snapshot()` inside the transactions loop and linearly scans every resulting snapshot. Capture one snapshot for the request and index its entries by txid, preferably lazily so raw-only requests do not copy the mempool.

## Issue Context
`mining_snapshot()` copies every mempool entry and reconstructs priority ordering, a position map, and ancestor vectors. Reusing one snapshot also gives all txid resolutions a coherent view.

## Fix Focus Areas
- crates/rpc/src/handlers/mining.rs[379-392]
- crates/mempool/src/pool.rs[715-767]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

return Err(generateblock_unknown_txid(text));
};
transactions.push(GenerateTx::ResolvedMempool(entry));
continue;
}
let bytes = from_hex(text)
.map_err(|()| RpcError::InvalidParams("transaction hex is not valid hexadecimal"))?;
let tx: Tx = deserialize(&bytes)
.map_err(|_| RpcError::InvalidParams("transaction hex could not be decoded"))?;
let bytes = from_hex(text).map_err(|()| generateblock_tx_decode_failed(text))?;
let tx: Tx = deserialize(&bytes).map_err(|_| generateblock_tx_decode_failed(text))?;
transactions.push(GenerateTx::Raw(tx));
}
Ok(transactions)
}

fn generateblock_unknown_txid(text: &str) -> RpcError {
RpcError::InvalidAddressOrKey(format!("Transaction {text} not in mempool."))
}

fn generateblock_tx_decode_failed(text: &str) -> RpcError {
RpcError::Deserialization(format!(
"Transaction decode failed for {text}. Make sure the tx has at least one input."
))
}

fn parse_block_template_request(params: &Value) -> Result<BlockTemplateRequest, RpcError> {
if params.is_null() {
return Ok(BlockTemplateRequest {
Expand Down Expand Up @@ -2073,11 +2089,20 @@ mod tests {
/// API-05: 64-character hex is a mempool txid; longer hex is a raw transaction.
#[test]
fn generateblock_keeps_raw_transactions() {
use bitcoin_rs_mempool::MempoolEntry;

let control = FakeMiningControl::with_template(sample_template());
let ctx = ctx_with_control(control.clone());
let tx = sample_raw_tx();
let raw_hex = to_lower_hex(&consensus_bytes(&tx));
let txid = Txid::from(Hash256::from_le_bytes(&[0xcd; 32]));
let pooled = sample_raw_tx();
let txid = pooled.txid();
{
let mut pool = ctx.mempool.pool().write();
pool.insert_entry(MempoolEntry::new(Arc::new(pooled), 100, 1_000, 1, 7))
.unwrap_or_else(|err| panic!("insert failed: {err}"));
}
let mut raw = sample_raw_tx();
raw.lock_time = 1;
let raw_hex = to_lower_hex(&consensus_bytes(&raw));
generateblock(&ctx, &json!([REGTEST_ADDRESS, [txid.to_string(), raw_hex]]))
.unwrap_or_else(|err| panic!("generateblock failed: {err}"));
let request = control
Expand All @@ -2087,10 +2112,50 @@ mod tests {
.unwrap_or_else(|| panic!("generateblock must call generate"));
assert_eq!(
request.selection,
GenerateSelection::Ordered(vec![GenerateTx::Mempool(txid), GenerateTx::Raw(tx)])
GenerateSelection::Ordered(vec![GenerateTx::Mempool(txid), GenerateTx::Raw(raw)])
);
}

// CONTRACT: docs/contracts/external-api.md#API-24
#[test]
fn generateblock_rejects_unknown_mempool_txid_like_core() {
let control = FakeMiningControl::with_template(sample_template());
let ctx = ctx_with_control(control);
let missing = "CD".repeat(32);
let error = generateblock(&ctx, &json!([REGTEST_ADDRESS, [missing.as_str()]]))
.err()
.unwrap_or_else(|| panic!("unknown mempool txid must fail at parse"));
assert_eq!(error.code(), RpcError::CORE_NOT_FOUND);
assert_eq!(
error.to_string(),
format!("Transaction {missing} not in mempool.")
);
}

// CONTRACT: docs/contracts/external-api.md#API-24
#[test]
fn generateblock_rejects_undecodable_raw_tx_like_core() {
let control = FakeMiningControl::with_template(sample_template());
let ctx = ctx_with_control(control);
for payload in ["00", "zz", "abcd"] {
let error = generateblock(&ctx, &json!([REGTEST_ADDRESS, [payload]]))
.err()
.unwrap_or_else(|| panic!("`{payload}` must fail decode"));
assert_eq!(
error.code(),
RpcError::CORE_DESERIALIZATION_ERROR,
"for `{payload}`"
);
assert_eq!(
error.to_string(),
format!(
"Transaction decode failed for {payload}. Make sure the tx has at least one input."
),
"for `{payload}`"
);
}
}

/// API-05: extra generateblock positionals are rejected, matching Core arity.
#[test]
fn generateblock_rejects_trailing_parameters() {
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ declare_rows! {
"submitheader", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Header-only admission through the same tree path as inbound P2P headers. Decode failures are -22; missing previous or invalid headers are -25.", "0.4.0", Some(mining::submitheader);
"prioritisetransaction", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Dummy (params[1]) must be 0 or null; fee_delta is params[2]. Non-zero dummy is Core -8. Pooled dust outputs are -8 except on regtest.", "0.4.0", Some(mining::prioritisetransaction);
"generatetoaddress", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Assembles, solves, and submits n blocks paying the given address through the mining coordinator.", "0.4.0", Some(mining::generatetoaddress);
"generateblock", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Assembles and solves one block paying an address or descriptor from the listed mempool txids or raw txs in that order; third param is Core's submit flag.", "0.4.0", Some(mining::generateblock);
"generateblock", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "See API-24 (docs/contracts/external-api.md) for transaction parsing and error semantics.", "0.4.0", Some(mining::generateblock);
"getnetworkhashps", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Estimated hashes/s over a caller-chosen lookback ending at a caller-chosen height; default lookback 120, height the applied tip.", "0.4.0", Some(mining::getnetworkhashps);
"getprioritisedtransactions", SurfaceKind::Rpc, Status::Implemented, "", CORE_VERSION, "Projects the mempool's signed fee-delta overlay, including txids not currently pooled.", "0.4.0", Some(mining::getprioritisedtransactions);

Expand Down
2 changes: 1 addition & 1 deletion docs/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ match a regression.
| [chain-events.md](chain-events.md) | `EVT-01`–`EVT-05` | `ChainSnapshot`, `ChainEventHint`, `ChainEventPublisher`, `ConsumerCursor`, `UndoStore`/`DisconnectMarker`, `ChainChangeProof`: the seam between the apply path and reconciliation consumers | `crates/node/src/txindex_worker.rs` (first consumer); any index mirroring the applied chain | `crates/node/src/state.rs` tests `record_publishes_snapshot_and_hints_in_commit_order`, `record_drops_hints_when_channel_full`, `active_chain_snapshot_anchors_at_restored_tip_after_restart`; `crates/node/src/txindex_worker_recovery_tests.rs` tests `shallow_reorg_rewinds_to_common_ancestor_then_replays`, `tip_change_during_rebuild_converges_on_new_tip`; `crates/node/src/apply.rs` tests `a_clean_disconnect_leaves_no_in_flight_marker`, `chain_change_proof_finish_restores_even_generation` |
| [mempool-mutations.md](mempool-mutations.md) | `MPL-01`–`MPL-04` | Gateway ordering invariant, `MutationEnvelope`/`MutationResult` semantics, ZMQ `A`/`R` payload bytes, generation-validated admission and chain-change fencing | apply path (`crates/node/src/apply.rs`), `sendrawtransaction` (`crates/rpc/src/handlers/tx.rs`), ZMQ `sequence` subscribers (enforcer `--enable-mempool`) | `crates/mempool/src/gateway.rs` test `accepted_and_block_inclusion_events_arrive_in_commit_order`; `crates/node/src/zmq_publisher.rs` tests `block_inclusion_suppresses_r_frames` and `mempool_event_payloads_carry_reversed_txid_label_and_le_sequence`; `crates/node/src/apply.rs` test `stable_generation_is_even_before_and_after_connect` |
| [mempool-policy.md](mempool-policy.md) | `POL-01` | Pointer: relay policy contract pinned to Core 31.1 | `sendrawtransaction`/`testmempoolaccept` (`crates/rpc/src/handlers/tx.rs`), P2P relay admission | `crates/mempool/tests/policy_contract.rs` and `crates/rpc/tests/policy_contract.rs` (`cargo test -p bitcoin-rs-mempool --test policy_contract` / `-p bitcoin-rs-rpc --test policy_contract`) |
| [external-api.md](external-api.md) | `API-01`–`API-23` | Pointer: JSON-RPC/REST/ZMQ manifest, generated reference, error code mappings, query budgeting, solo-mining generate, `getnetworkhashps` snapshot behavior, BIP22/BIP23 template extras, mainnet GBT operational gates, `submitheader`, GBT client-rule negotiation, `submitblock` decode, GBT proposal request parsing, `submitblock` uncommitted witness fill, Core v31 submit/proposal duplicate vocabulary, BIP22 reject-reason mapping, GBT `vbrequired` always 0, Core `CheckWitnessMalleation` reject reasons, GBT `coinbaseaux.flags` empty hex, `prioritisetransaction` dummy/`fee_delta` arity, pooled-dust refusal, reorged scripts-valid duplicate, getmininginfo omitted optional fields, and estimatesmartfee Core conf_target/estimate_mode gates | RPC/REST/ZMQ clients; `tools/bip300301-enforcer` | `crates/rpc/tests/manifest_coverage.rs` tests `rpc_rows_and_the_live_registry_agree_both_ways`, `generated_reference_matches_checked_in`; `crates/rpc/src/handlers/mining.rs` generate, GBT extra, GBT gate, `submitheader`, GBT rule-negotiation, `submitblock` decode, GBT proposal-parse, `coinbaseaux`, `prioritisetransaction` dummy/dust, and `getmininginfo` omit-null tests; `crates/node/tests/mining.rs` generate, GBT extra, `submitheader`, uncommitted-witness submit, submit/proposal duplicate, BIP22 reject-reason, `vbrequired`, witness-malleation proposal, and reorged scripts-valid duplicate tests; `crates/mining/src/coinbase.rs` uncommitted-witness tests; `crates/consensus/src/verify_block.rs` CheckWitnessMalleation tests; `crates/node/src/mining.rs` test `hash_ps_at_rejects_a_height_the_tip_cannot_resolve`; `crates/node/tests/mining.rs` test `network_hash_ps_rejects_core_invalid_windows` |
| [external-api.md](external-api.md) | `API-01`–`API-24` | Pointer: JSON-RPC/REST/ZMQ manifest, generated reference, error code mappings, query budgeting, solo-mining generate, `getnetworkhashps` snapshot behavior, BIP22/BIP23 template extras, mainnet GBT operational gates, `submitheader`, GBT client-rule negotiation, `submitblock` decode, GBT proposal request parsing, `submitblock` uncommitted witness fill, Core v31 submit/proposal duplicate vocabulary, BIP22 reject-reason mapping, GBT `vbrequired` always 0, Core `CheckWitnessMalleation` reject reasons, GBT `coinbaseaux.flags` empty hex, `prioritisetransaction` dummy/`fee_delta` arity, pooled-dust refusal, reorged scripts-valid duplicate, getmininginfo omitted optional fields, and estimatesmartfee Core conf_target/estimate_mode gates, and generateblock Core txid/raw-tx parse errors | RPC/REST/ZMQ clients; `tools/bip300301-enforcer` | `crates/rpc/tests/manifest_coverage.rs` tests `rpc_rows_and_the_live_registry_agree_both_ways`, `generated_reference_matches_checked_in`; `crates/rpc/src/handlers/mining.rs` generate, GBT extra, GBT gate, `submitheader`, GBT rule-negotiation, `submitblock` decode, GBT proposal-parse, `coinbaseaux`, `prioritisetransaction` dummy/dust, and `getmininginfo` omit-null tests; `crates/node/tests/mining.rs` generate, GBT extra, `submitheader`, uncommitted-witness submit, submit/proposal duplicate, BIP22 reject-reason, `vbrequired`, witness-malleation proposal, and reorged scripts-valid duplicate tests; `crates/mining/src/coinbase.rs` uncommitted-witness tests; `crates/consensus/src/verify_block.rs` CheckWitnessMalleation tests; `crates/node/src/mining.rs` test `hash_ps_at_rejects_a_height_the_tip_cannot_resolve`; `crates/node/tests/mining.rs` test `network_hash_ps_rejects_core_invalid_windows` |
| [wallet-facing.md](wallet-facing.md) | `WF-01`–`WF-03` | Public Esplora/JSON-RPC surface an external wallet may use; no `NodeState` / `UtxoSet` / index types | [bitcoin-wallet](https://github.com/gosuda/bitcoin-wallet) (`btcw`); any Esplora HTTP client | `bin/bitcoin-rs/tests/wallet_facing.rs` tests `external_wallet_can_scan_estimate_and_broadcast`, `source_does_not_import_node_internals`; `crates/rpc/src/esplora.rs` tests `esplora_lives_only_under_the_api_prefix`, `api_is_the_public_electrs_directory`, `esplora_is_the_mempool_backend_superset` |
| [p2p-wire.md](p2p-wire.md) | `P2P-01`–`P2P-02` | Pointer: command inventory in `crates/p2p/src/compat.rs`, handshake/reject/deviations pinned to Core 31.1 | `crates/p2p` peers; `crates/p2p/src/chain_query.rs` active-chain serving | `crates/p2p/tests/core_compat.rs` (`cargo test -p bitcoin-rs-p2p --test core_compat`); live lane `scripts/run-p2p-core-interop.sh` |
| [qa-corpus.md](qa-corpus.md) | `QAC-01` | Pointer: fuzz seed provenance and refresh rules | `fuzz/fuzz_targets/{p2p_message,block_decode,tx_decode,script_eval}.rs`; CI fuzz lanes | `fuzz/CORPUS_PROVENANCE.md` mapping table; targets run under `cargo fuzz run <target> -- -runs=10000` |
Expand Down
29 changes: 25 additions & 4 deletions docs/contracts/external-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ reject reasons. `API-18` is GBT `coinbaseaux.flags`. `API-19` is
`prioritisetransaction` dust-output refusal. `API-21` is GBT proposal /
`submitblock` duplicate for reorged scripts-valid bodies. `API-22` is
`getmininginfo` omitting unset optional fields. `API-23` is
`estimatesmartfee` Core `conf_target` and `estimate_mode` gates.
`estimatesmartfee` Core `conf_target` and `estimate_mode` gates. `API-24`
is `generateblock` Core txid/raw-tx parse errors.

## Clauses

Expand Down Expand Up @@ -81,7 +82,8 @@ reject reasons. `API-18` is GBT `coinbaseaux.flags`. `API-19` is
The transactions array is required (an explicit `[]` is coinbase-only).
Listed order is kept, those fees are not added to the coinbase, 64-character
hex is a mempool txid, and decoded raw transactions are included without
mempool admission. Extra positional arguments are rejected.
mempool admission. Extra positional arguments are rejected. Transaction
parse errors are `API-24`.

### `API-06`: `getnetworkhashps` snapshot and invalid-height behavior

Expand Down Expand Up @@ -298,6 +300,18 @@ reject reasons. `API-18` is GBT `coinbaseaux.flags`. `API-19` is
this node's estimator has one horizon.
- Trailing parameters are refused.

### `API-24`: `generateblock` txid and raw-tx parse errors

- **Owner**: `parse_generateblock_transactions` in
`crates/rpc/src/handlers/mining.rs`.
- 64-character hex is Core `Txid::FromHex`. A txid missing from the
mempool is `-5` `Transaction {str} not in mempool.` using the caller's
string.
- Anything else is Core `DecodeHexTx`. Invalid hex or a payload that is
not a complete transaction is `-22`
`Transaction decode failed for {str}. Make sure the tx has at least one
input.`

The wallet-facing subset of this surface — tip, fees, address/script
queries, and broadcast over Esplora, plus the key-free node RPCs — is
owned by [wallet-facing.md](wallet-facing.md).
Expand All @@ -320,8 +334,10 @@ owned by [wallet-facing.md](wallet-facing.md).
`generateblock_projects_hash_object`, `generateblock_accepts_addr_descriptor`,
`generateblock_without_submit_includes_hex`,
`generateblock_requires_transactions_array`, `generateblock_keeps_raw_transactions`,
`generateblock_rejects_trailing_parameters`,
`generateblock_rejects_invalid_supplied_checksums`
`generateblock_rejects_trailing_parameters`,
`generateblock_rejects_invalid_supplied_checksums`,
`generateblock_rejects_unknown_mempool_txid_like_core`,
`generateblock_rejects_undecodable_raw_tx_like_core`
- `crates/node/tests/mining.rs` tests `generate_mines_coinbase_only_blocks_to_the_tip`,
`generateblock_rejects_unknown_mempool_txid`,
`generateblock_raw_tx_does_not_require_mempool_admission`,
Expand Down Expand Up @@ -425,3 +441,8 @@ owned by [wallet-facing.md](wallet-facing.md).
`estimatesmartfee_rejects_conf_target_outside_core_range`,
`estimatesmartfee_rejects_unknown_estimate_mode`,
`estimatesmartfee_accepts_core_estimate_modes_and_rejects_trailing`
- `API-24`:
- `crates/rpc/src/handlers/mining.rs` tests
`generateblock_rejects_unknown_mempool_txid_like_core`,
`generateblock_rejects_undecodable_raw_tx_like_core`,
`generateblock_keeps_raw_transactions`
2 changes: 1 addition & 1 deletion docs/rpc-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Unimplemented-set derivation: audited against the Bitcoin Core v31.0 source comm
| `submitheader` | 0.4.0 | Header-only admission through the same tree path as inbound P2P headers. Decode failures are -22; missing previous or invalid headers are -25. |
| `prioritisetransaction` | 0.4.0 | Dummy (params[1]) must be 0 or null; fee_delta is params[2]. Non-zero dummy is Core -8. Pooled dust outputs are -8 except on regtest. |
| `generatetoaddress` | 0.4.0 | Assembles, solves, and submits n blocks paying the given address through the mining coordinator. |
| `generateblock` | 0.4.0 | Assembles and solves one block paying an address or descriptor from the listed mempool txids or raw txs in that order; third param is Core's submit flag. |
| `generateblock` | 0.4.0 | See API-24 (docs/contracts/external-api.md) for transaction parsing and error semantics. |
| `getnetworkhashps` | 0.4.0 | Estimated hashes/s over a caller-chosen lookback ending at a caller-chosen height; default lookback 120, height the applied tip. |
| `getprioritisedtransactions` | 0.4.0 | Projects the mempool's signed fee-delta overlay, including txids not currently pooled. |

Expand Down