Skip to content

Match Core generateblock txid and raw-tx parse errors - #604

Draft
metaphorics wants to merge 2 commits into
cursor/mining-estimate-mode-1522from
cursor/mining-generateblock-tx-errors-1522
Draft

Match Core generateblock txid and raw-tx parse errors#604
metaphorics wants to merge 2 commits into
cursor/mining-estimate-mode-1522from
cursor/mining-generateblock-tx-errors-1522

Conversation

@metaphorics

Copy link
Copy Markdown
Contributor

Stacked on #602. Core v31 generateblock (src/rpc/mining.cpp) classifies each transactions-array entry before assembling:

  • 64-character hex is Txid::FromHex. A txid missing from the mempool is -5 Transaction {str} not in mempool. using the caller’s string.
  • Anything else is DecodeHexTx. Invalid hex or an incomplete transaction is -22 Transaction decode failed for {str}. Make sure the tx has at least one input.

This node previously treated unknown 64-hex entries as GenerateTx::Mempool and only failed later in the coordinator (RPC mapped that to -32603), and decode/hex failures were JSON-RPC -32602. Parse now looks the txid up at the RPC boundary and emits Core’s codes and text. Assembly still receives GenerateTx::Mempool vs Raw; extra positionals stay rejected (Core 31 has no maxtries on generateblock).

Contract: API-24. Proven by generateblock_rejects_unknown_mempool_txid_like_core, generateblock_rejects_undecodable_raw_tx_like_core, and the updated generateblock_keeps_raw_transactions pool insert.

Does not complete #151. Remaining mining work includes the live Core differential suite (#78), numeric p95 budgets (#158), -acceptnonstdtxn as a real option, and prune BLOCK_HAVE_DATA vs scripts-valid.

Open in Web Open in Cursor 

64-character hex is a mempool txid looked up at parse time; a miss is
Core -5 with the caller's string. Anything else is DecodeHexTx: invalid
hex or an incomplete transaction is Core -22 with Core's decode text.

Co-authored-by: metaphorics <metaphorics@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: e29dff06-f031-4bd6-aab6-43db59081058

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_e17f4581-aa16-4ccc-b7da-d9da53b5ad16)

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Match Core generateblock transaction parse errors

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Validates generateblock mempool txids before assembly and returns Core-compatible -5 errors.
• Maps malformed or incomplete raw transactions to Core-compatible -22 decode errors.
• Adds regression coverage and documents API-24 behavior across RPC references.
Diagram

graph TD
  A["RPC Client"] --> B["Transaction Parser"] --> C{"Txid Parse?"}
  C -->|Txid| D["Mempool Lookup"] --> E{"Entry Found?"}
  E -->|Yes| F["Generate Request"]
  E -->|No, -5| G["Core RPC Error"]
  C -->|Raw| H["Raw Tx Decode"] -->|Valid| F
  H -->|Invalid, -22| G
Loading
High-Level Assessment

Validating transaction IDs and decoding raw transactions at the RPC boundary is the best approach because it preserves the caller's original string and produces Bitcoin Core's method-specific error codes before coordinator execution. Deferring missing-txid handling to the mining coordinator was considered but would continue collapsing the failure into an internal RPC error.

Files changed (5) +102 / -17

Documentation (4) +28 / -7
registry.rsDescribe generateblock transaction error codes +1/-1

Describe generateblock transaction error codes

• Extends the generateblock registry description with the -5 unknown-txid and -22 raw-transaction decode behavior.

crates/rpc/src/registry.rs

README.mdRegister the API-24 compatibility contract +1/-1

Register the API-24 compatibility contract

• Expands the external API contract range through API-24 and identifies generateblock transaction parsing errors as part of the documented RPC compatibility surface.

docs/contracts/README.md

external-api.mdDefine generateblock parsing contract API-24 +25/-4

Define generateblock parsing contract API-24

• Documents Core-compatible classification, codes, and exact messages for missing mempool txids and undecodable raw transactions. Links the contract to its parser owner and regression tests.

docs/contracts/external-api.md

rpc-reference.mdPublish generateblock error semantics +1/-1

Publish generateblock error semantics

• Updates the generated RPC reference to advertise -5 for unknown 64-hex txids and -22 for raw-transaction decode failures.

docs/rpc-reference.md

Other (1) +74 / -10
mining.rsValidate generateblock transactions with Core-compatible errors +74/-10

Validate generateblock transactions with Core-compatible errors

• Passes the RPC context into transaction parsing so 64-character txids can be checked against the mempool before assembly. Missing txids now return Core -5, malformed or incomplete raw transactions return Core -22, and regression tests verify both errors while preserving ordered mempool/raw selections.

crates/rpc/src/handlers/mining.rs

@qodo-code-review

qodo-code-review Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

Grey Divider


Action required

1. Mempool lookup remains racy ✓ Resolved 🐞 Bug
Description
The parser verifies that a txid exists but passes only the txid onward, so concurrent eviction or
block inclusion between parsing and assembly makes the second lookup fail as internal error -32603
instead of preserving the resolved transaction. This leaves generateblock observably incompatible
with the new -5/resolved-transaction contract during normal mempool mutation.
Code

crates/rpc/src/handlers/mining.rs[R388-391]

+            if ctx.mempool.read().entry_by_txid(&txid).is_none() {
+                return Err(generateblock_unknown_txid(text));
+            }
            transactions.push(GenerateTx::Mempool(txid));
Relevance

●●● Strong

Recent accepted precedent prioritizes authoritative mempool state and retry-safe handling across
concurrent mutations.

PR-#316

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new parser checks membership under a temporary read guard but stores only
GenerateTx::Mempool(txid). Assembly later acquires a fresh mempool view and rejects a now-missing
txid as MiningControlError::InvalidRequest; the RPC mapper converts that variant to
RpcError::Internal, recreating the -32603 outcome this PR is intended to replace.

crates/rpc/src/handlers/mining.rs[387-397]
crates/mining/src/control.rs[214-220]
crates/node/src/mining.rs[1386-1414]
crates/rpc/src/handlers/mining.rs[725-731]
crates/mempool/src/gateway.rs[2-14]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`parse_generateblock_transactions` checks mempool membership but discards the resolved entry and passes only its txid to mining. If the transaction is removed before assembly, mining performs another lookup and returns an internal RPC error, defeating the intended Core-compatible behavior.

## Issue Context
Core-style parsing should retain the resolved transaction body for assembly rather than depending on a later mempool lookup. Preserve any metadata needed by ordered mining selection, or introduce a resolved-mempool selection representation that does not require a second presence check.

## Fix Focus Areas
- crates/rpc/src/handlers/mining.rs[365-398]
- crates/mining/src/control.rs[214-229]
- crates/node/src/mining.rs[1386-1414]

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



Remediation recommended

2. generateblock metadata duplicates API-24 ✓ Resolved 📘 Rule violation
Description
The registry note independently encodes API-24’s transaction classification and error-code mapping
instead of referencing the authoritative contract. This creates a second textual representation that
can drift from the contract and parser implementation.
Code

crates/rpc/src/registry.rs[144]

+    "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. Unknown 64-hex txids are -5; raw-tx decode failures are -22.", "0.4.0", Some(mining::generateblock);
Relevance

●●● Strong

Recent accepted reviews remove duplicated contract prose and prefer authoritative documentation
references.

PR-#353
PR-#391

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 3086175 prohibits new metadata literals that restate an authoritative documented business rule.
API-24 defines the generateblock txid/raw-transaction classification and -5/-22 behavior,
while the changed registry literal independently repeats that mapping without referencing API-24.

Rule 3086175: Avoid duplicating existing documented business rules in code comments or new config structures
docs/contracts/external-api.md[303-313]
crates/rpc/src/registry.rs[144-144]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `generateblock` registry metadata duplicates API-24’s txid and raw-transaction error mapping, creating another source that must be maintained independently.

## Issue Context
`docs/contracts/external-api.md` defines API-24 and names `parse_generateblock_transactions` as its owner. Keep the registry description concise and reference API-24 rather than re-encoding its classification and error codes; then regenerate the derived RPC reference.

## Fix Focus Areas
- crates/rpc/src/registry.rs[144-144]
- docs/rpc-reference.md[78-78]

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


Grey Divider

Context sources
✅ Compliance rules (platform): 18 rules
Review mode: ⚖️ Balanced: This push changes runtime mining/RPC behavior and public generateblock error/transaction-resolution semantics, creating real contract and consistency risk despite its localized scope.
ⓘ  2 issues published inline · 0 in summary

Grey Divider

Previous reviews

Review updated until commit 1fdd20f ⚖️ Balanced

Results up to commit 1d3d777 ⚖️ Balanced



Action required
1. Mempool lookup remains racy ✓ Resolved 🐞 Bug
Description
The parser verifies that a txid exists but passes only the txid onward, so concurrent eviction or
block inclusion between parsing and assembly makes the second lookup fail as internal error -32603
instead of preserving the resolved transaction. This leaves generateblock observably incompatible
with the new -5/resolved-transaction contract during normal mempool mutation.
Code

crates/rpc/src/handlers/mining.rs[R388-391]

+            if ctx.mempool.read().entry_by_txid(&txid).is_none() {
+                return Err(generateblock_unknown_txid(text));
+            }
            transactions.push(GenerateTx::Mempool(txid));
Relevance

●●● Strong

Recent accepted precedent prioritizes authoritative mempool state and retry-safe handling across
concurrent mutations.

PR-#316

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new parser checks membership under a temporary read guard but stores only
GenerateTx::Mempool(txid). Assembly later acquires a fresh mempool view and rejects a now-missing
txid as MiningControlError::InvalidRequest; the RPC mapper converts that variant to
RpcError::Internal, recreating the -32603 outcome this PR is intended to replace.

crates/rpc/src/handlers/mining.rs[387-397]
crates/mining/src/control.rs[214-220]
crates/node/src/mining.rs[1386-1414]
crates/rpc/src/handlers/mining.rs[725-731]
crates/mempool/src/gateway.rs[2-14]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`parse_generateblock_transactions` checks mempool membership but discards the resolved entry and passes only its txid to mining. If the transaction is removed before assembly, mining performs another lookup and returns an internal RPC error, defeating the intended Core-compatible behavior.

## Issue Context
Core-style parsing should retain the resolved transaction body for assembly rather than depending on a later mempool lookup. Preserve any metadata needed by ordered mining selection, or introduce a resolved-mempool selection representation that does not require a second presence check.

## Fix Focus Areas
- crates/rpc/src/handlers/mining.rs[365-398]
- crates/mining/src/control.rs[214-229]
- crates/node/src/mining.rs[1386-1414]

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



Remediation recommended
2. generateblock metadata duplicates API-24 ✓ Resolved 📘 Rule violation
Description
The registry note independently encodes API-24’s transaction classification and error-code mapping
instead of referencing the authoritative contract. This creates a second textual representation that
can drift from the contract and parser implementation.
Code

crates/rpc/src/registry.rs[144]

+    "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. Unknown 64-hex txids are -5; raw-tx decode failures are -22.", "0.4.0", Some(mining::generateblock);
Relevance

●●● Strong

Recent accepted reviews remove duplicated contract prose and prefer authoritative documentation
references.

PR-#353
PR-#391

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 3086175 prohibits new metadata literals that restate an authoritative documented business rule.
API-24 defines the generateblock txid/raw-transaction classification and -5/-22 behavior,
while the changed registry literal independently repeats that mapping without referencing API-24.

Rule 3086175: Avoid duplicating existing documented business rules in code comments or new config structures
docs/contracts/external-api.md[303-313]
crates/rpc/src/registry.rs[144-144]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `generateblock` registry metadata duplicates API-24’s txid and raw-transaction error mapping, creating another source that must be maintained independently.

## Issue Context
`docs/contracts/external-api.md` defines API-24 and names `parse_generateblock_transactions` as its owner. Keep the registry description concise and reference API-24 rather than re-encoding its classification and error codes; then regenerate the derived RPC reference.

## Fix Focus Areas
- crates/rpc/src/registry.rs[144-144]
- docs/rpc-reference.md[78-78]

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


Grey Divider

Comment thread crates/rpc/src/registry.rs Outdated
Comment thread crates/rpc/src/handlers/mining.rs Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo Fixer

🍒 Ready to be cherry-picked — ✅ Merged (0) · ☑ Fixed (2)

Grey Divider

🔗 Fix PR: #606

This fix PR was closed automatically. Its branch is preserved so you can cherry pick the changes into the original PR.

Prompt for coding agent

This is an automated fix prepared on a separate branch (#606). It is NOT applied to this PR.
To use it: review Fix PR #606 (https://github.com/gosuda/bitcoin-rs/pull/606), evaluate each change critically against your local context, and cherry-pick the changes that are correct into this branch. Do not accept them blindly.
Process — 2 fixed
  • ☑ Fixed: Mempool lookup remains racy
  • ☑ Fixed: generateblock metadata duplicates API-24

… a (#606)

## Fixed Findings
- Preserve resolved mempool transactions
- Reference API-24 transaction semantics

Automated fix from agentic review of
#604

<a href="https://www.qodo.ai"><img
src="https://www.qodo.ai/wp-content/uploads/2025/03/qodo-logo.svg"
width="80" alt="Qodo Logo"></a>

---------

Co-authored-by: qodo-code-review[bot] <151058649+qodo-code-review[bot]@users.noreply.github.com>
@cursor

cursor Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_5eb4f36b-591b-406d-b3c6-4870d493d4cb)

Comment on lines +220 to +221
/// Include this transaction resolved from the mempool at parse time.
ResolvedMempool(SnapshotEntry),

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

Comment on lines +388 to +389
let snapshot = ctx.mempool.read().mining_snapshot();
let Some(entry) = snapshot.entries.into_iter().find(|entry| entry.txid == txid) else {

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

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 1fdd20f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants