cardano-foundation / cardano-foundation/cardano-rosetta-java
Implement `other_transactions` in `/block` ahead of Leios-scale blocks
- Dominant language
- Java
- Stars
- 26
- Forks
- 15
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 2
Description
# Implement `other_transactions` in `/block` ahead of Leios-scale blocks
## Summary
`/block` always inlines every transaction of a block, fully populated with operations. The optional `BlockResponse.other_transactions` field — the spec's escape hatch for blocks too large to serve in one response — is never populated.
That is fine at today's block sizes but does not survive Leios. Ouroboros Leios ([CIP-0164](https://cips.cardano.org/cip/CIP-0164)) targets a **30–65x throughput increase** (~4,500 TxB/s today → 140,000–300,000 TxB/s, roughly 100–200 TPS), and certified endorser-block transactions are to be served merged into the ranking block over LocalChainSync — so **a single block, as an indexer sees it, will carry one to two orders of magnitude more transactions than today**. The CIP's own worked example is a 10,000-transaction endorser block.
Proposal: above a configurable threshold, return the block with `transactions: []` and **all** of the block's transaction hashes in `other_transactions`, letting clients fetch detail via `/block/transaction`. (The threshold is a trigger, not a page length)
## Response shape: all-or-nothing, not a partial page
Worth stating explicitly, because the name `PAGE_SIZE` misleads: the threshold is a **trigger**, not a page length. Once tripped, the response carries **all** of the block's hashes and **none** of its transactions inline.
That is what the TS implementation did — `mapToRosettaBlock(block, [], poolDeposit)` passes an empty transaction list, and `other_transactions` maps over the full `transactionsFound` rather than a slice past `PAGE_SIZE`. Its fixture shows the resulting wire format, with the true count preserved in metadata:
```json
{
"block": {
"transactions": [],
"metadata": { "transactionsCount": 8, "size": 2845, "epochNo": 1, "slotNo": 23725 }
},
"other_transactions": [
{ "hash": "e1c3e53ff15df4b3f477284fcf971618ec30f2a70209ddb0bc2f0c6e0d90665d" },
{ "hash": "a9c267305af2cabb9c54c929dad82afd8b61d5e49045efc80e2d664c98f3190d" }
]
}
```
Below the threshold, nothing changes on the wire: `other_transactions` is optional (`BlockResponse` declares no `required` properties), the generated field stays null, and `spring.jackson.default-property-inclusion: NON_NULL` in `application.yaml` omits it from the JSON entirely — the key is **absent**, not `null` and not `[]`. That is already today's behaviour, so existing integrators see no diff.
| block size | `block.transactions` | `other_transactions` |
|---|---|---|
| ≤ threshold | all transactions, fully populated | key absent |
| > threshold | `[]` | all of the block's hashes |
## Threshold (page-size)
Rosetta TS had this value set to 25. Currently the largest block on mainnet has 385 txns and that is fetched in 2 secs. So we can keep this fairly large (maybe 400~500). Up for discussion later on during implementaion.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the `/block` endpoint and trace construction of `BlockResponse`, including `mapToRosettaBlock`; inspect `application.yaml` for the existing NON_NULL Jackson behavior. Done means blocks at or below the configured threshold keep all inline transactions with no `other_transactions` key, while larger blocks return no inline transactions and all hashes in `other_transactions`; verify the related block response behavior and `/block/transaction` flow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, blockchain
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100