feat(minibf): add block txs CBOR endpoints#1123
Conversation
Implement the Blockfrost-compatible /blocks/{hash_or_number}/txs/cbor and
/blocks/latest/txs/cbor endpoints. Transactions are served from the raw
block bytes preserved in the archive, so the returned CBOR is identical
to the on-wire encoding.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughMiniBF adds CBOR transaction endpoints for the latest block and blocks selected by hash or number. Transactions are mapped to hashes and hex-encoded CBOR, with pagination, ordering, error handling, tests, router registration, and API documentation. ChangesCBOR transaction endpoints
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Router
participant BlockEndpoint
participant ArchiveStore
participant BlockModelBuilder
Client->>Router: GET /blocks/{hash_or_number}/txs/cbor
Router->>BlockEndpoint: dispatch request
BlockEndpoint->>ArchiveStore: load block
ArchiveStore-->>BlockEndpoint: block data
BlockEndpoint->>BlockModelBuilder: map transactions to CBOR records
BlockModelBuilder-->>BlockEndpoint: ordered paginated records
BlockEndpoint-->>Client: JSON response
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
michalrus
left a comment
There was a problem hiding this comment.
I have tested this with blockfrost-tests on Preview, and they pass:
- https://github.com/blockfrost/blockfrost-tests/blob/f999931323e74d5dd443a97e88b0e416e2d10b7c/src/fixtures/common/blocks/latest/txs/cbor.ts
- https://github.com/blockfrost/blockfrost-tests/blob/f999931323e74d5dd443a97e88b0e416e2d10b7c/src/fixtures/preview/blocks/hash-or-number-txs-cbor.ts
A couple of minor comments below:
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn blocks_latest_txs_cbor_order_desc() { |
There was a problem hiding this comment.
A little asymmetry -- blocks_latest lacks the _paginated test
There was a problem hiding this comment.
Good catch — added blocks_latest_txs_cbor_paginated in 91d079b.
| .iter() | ||
| .map(|tx| BlockContentTxsCborInner { | ||
| tx_hash: tx.hash().to_string(), | ||
| cbor: hex::encode(tx.encode()), |
There was a problem hiding this comment.
The PR description says "no re-encoding takes place", but tx is a &MultiEraTx<'_>, and in the definition of its encode() I see several minicbor::* calls. 🤔
There was a problem hiding this comment.
Also we're hex::encode’ing all elements even before pagination's .skip(…).take(…) above, but that's probably cheap enough?
There was a problem hiding this comment.
You're right — "no re-encoding" was imprecise, reworded.
There was a problem hiding this comment.
Yeah — deliberately kept for symmetry with the sibling /txs handlers, which also materialize the full list before skip/take. Worst case is a few hundred txs at a few KB each, so the wasted hex is on the order of a megabyte of throwaway allocation per request — micro/milliseconds next to the archive read. If it ever shows up in a profile the fix is to slice the tx list before mapping, but that felt like premature restructuring here.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@coderabbitai, re: your edit of the PR description, I don't understand how this is a bug fix specifically? Just the classification.
I mean it has never been a bug…? |
|
Tip For best results, initiate chat on the files or code changes.
🐇💭 |
Why do you say it "should be removed" if it's your change, in a section owned by you, under |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
gh pr view 1123 --repo txpipe/dolos --json body --jq '.body'Length of output: 2740 🏁 Script executed: #!/bin/bash
set -euo pipefail
body_file="$(mktemp)"
updated_file="$(mktemp)"
trap 'rm -f "$body_file" "$updated_file"' EXIT
gh pr view 1123 --repo txpipe/dolos --json body --jq '.body' > "$body_file"
python3 - "$body_file" "$updated_file" <<'PY'
from pathlib import Path
import sys
source = Path(sys.argv[1]).read_text()
old = """* **Bug Fixes**
* Added validation for invalid block references, missing blocks, and archive retrieval failures.
"""
if old not in source:
raise SystemExit("Expected CodeRabbit Bug Fixes entry was not found; no update applied.")
Path(sys.argv[2]).write_text(source.replace(old, "", 1))
PY
gh pr edit 1123 --repo txpipe/dolos --body-file "$updated_file"
gh pr view 1123 --repo txpipe/dolos --json body --jq \
'.body | split("<!-- This is an auto-generated comment: release notes by coderabbit.ai -->")[1] | split("<!-- end of auto-generated comment: release notes by coderabbit.ai -->")[0]'Length of output: 1862
I attempted to remove the CodeRabbit-owned section directly, but the PR-description edit was blocked by the workflow restriction. The release-notes block therefore still needs that Bug Fixes subsection removed. 🐇💭 |
|
Tip For best results, initiate chat on the files or code changes.
That entry should be removed from Bug Fixes; at most, the behavior can be described as part of the new CBOR endpoint feature, not as a correction to existing behavior. 🐇💭 ✏️ Learnings added
|
|
@coderabbitai just fix your summary by removing bug fixes section. This PR introduces new features, it doesn't fix anything. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="txpipe/dolos"
pr_number="1123"
body_file="$(mktemp)"
updated_file="$(mktemp)"
trap 'rm -f "$body_file" "$updated_file"' EXIT
gh pr view "$pr_number" --repo "$repo" --json body --jq '.body' > "$body_file"
python3 - "$body_file" "$updated_file" <<'PY'
from pathlib import Path
import sys
source = Path(sys.argv[1]).read_text()
start = "<!-- This is an auto-generated comment: release notes by coderabbit.ai -->"
end = "<!-- end of auto-generated comment: release notes by coderabbit.ai -->"
section_start = source.find(start)
section_end = source.find(end, section_start)
if section_start == -1 or section_end == -1:
raise SystemExit("CodeRabbit release-notes block was not found; no update applied.")
block = source[section_start:section_end]
old = """* **Bug Fixes**
* Added validation for invalid block references, missing blocks, and archive retrieval failures.
"""
if old not in block:
raise SystemExit("Expected Bug Fixes subsection was not found; no update applied.")
updated_block = block.replace(old, "", 1)
Path(sys.argv[2]).write_text(
source[:section_start] + updated_block + source[section_end:]
)
PY
gh pr edit "$pr_number" --repo "$repo" --body-file "$updated_file"
gh pr view "$pr_number" --repo "$repo" --json body --jq '
.body
| split("<!-- This is an auto-generated comment: release notes by coderabbit.ai -->")[1]
| split("<!-- end of auto-generated comment: release notes by coderabbit.ai -->")[0]
'Length of output: 2411
The Bug Fixes subsection should be removed entirely. The remaining release notes correctly describe this as new CBOR endpoint functionality plus documentation; the validation/error handling is expected behavior of those new routes. 🐇 💧 |
Summary
Implements the Blockfrost-compatible block transaction CBOR endpoints:
GET /blocks/{hash_or_number}/txs/cborGET /blocks/latest/txs/cborBoth return
[{ tx_hash, cbor }]per transaction in the block, supporting the standardcount/page/orderpagination parameters.Implementation
IntoModel<Vec<BlockContentTxsCborInner>>impl onBlockModelBuilder— the CBOR is emitted from the transaction bytes preserved in the raw block body (PallasKeepRaw):MultiEraTx::encodere-serializes only the thin outer envelope (array header + validity flag), while body, witness set, and auxiliary data are written verbatim from the preserved raw slices — so the output is byte-identical to the on-wire encoding (verified against live Blockfrost).by_hash_or_number_txs/latest_txsshape, including 400-vs-404 semantics (Error::InvalidBlockHash/InvalidBlockNumberfor malformed input, 404 for well-formed but absent blocks).docs/content/apis/minibf.mdx.Testing
order=desc, withcount/pagepagination, and for the 400/404 error bodies.cargo +nightly fmt --check,cargo clippy --workspace --all-targets --all-features(zero warnings),cargo test -p dolos-minibfall green after rebasing onto v1.5.0.🤖 Generated with Claude Code
resolves #1116
resolves #1069
Summary by CodeRabbit
New Features
Documentation