cardano-foundation / cardano-foundation/cardano-rosetta-java

Implement `other_transactions` in `/block` ahead of Leios-scale blocks

Open
#776 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.