Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7bc850b
feat(jsonrpc): add support for JSON-RPC 2.0 batch requests
renatomaia Jul 27, 2026
20ec98f
feat(jsonrpc): impose the same response size budget of batch requests…
renatomaia Aug 14, 2026
5718758
refactor(jsonrcp): remove unused field 'data' from error reponses
renatomaia Jul 28, 2026
cee9563
feat(jsonrpc): add operation to get epoch by a virtual contiguous index
renatomaia Jul 28, 2026
ac7e215
feat(jsonrpc): add operation to get Node info like its chain ID, vers…
renatomaia Jul 28, 2026
a61f0d9
feat(jsonrpc): add inclusive index ranges to list epochs, inputs, out…
renatomaia Jul 28, 2026
cb05376
feat(jsonrpc): allows to filter output by execution and multiple sele…
renatomaia Jul 28, 2026
19cfead
perf(repository): add DB index to improve filter output by execution
renatomaia Aug 12, 2026
420f006
feat(cli): allows to filter output by execution and multiple selectors
renatomaia Jul 28, 2026
0979416
feat(jsonrpc): add methods to get the count of executed and pending o…
renatomaia Jul 29, 2026
9026422
feat(jsonrpc): support listing epochs with multiple statuses
renatomaia Jul 29, 2026
5587ddb
feat(cli): support listing epochs with multiple statuses
renatomaia Jul 29, 2026
1c0906c
fix(jsonrpc): report 256-bit integer fields in OpenRPC specification
renatomaia Jul 29, 2026
0bcdab2
refactor(jsonrpc): rename cartesi_getMatchAdvanced as cartesi_getMatc…
renatomaia Jul 30, 2026
bc292ee
test(jsonrpc): add tests for positional decoding of parameters
renatomaia Jul 30, 2026
e937248
fix(repository): avoid invalid SQL when listing outputs with empty ty…
renatomaia Aug 14, 2026
e67bea3
test(jsonrpc): add tests for some use cases of listing operations
renatomaia Aug 14, 2026
c54337c
perf(jsonrpc): parse JSON-RPC API spec on service initialization
renatomaia Aug 14, 2026
b0b83f2
docs(repository): add comment to clarify expected behavior of module API
renatomaia Aug 14, 2026
da23670
docs(jsonrpc): add warnings and recommendations on how to use the API
renatomaia Aug 14, 2026
64d36c6
docs(jsonrpc): improve documentation on response size limit
renatomaia Aug 14, 2026
755a277
fix(jsonrpc): skip ignored fields on positional decoding of parameters
renatomaia Aug 14, 2026
1a635e7
test(jsonrpc): add more tests on parsing parameters
renatomaia Aug 14, 2026
e14b1e6
style(cli): avoid line length violation
renatomaia Aug 14, 2026
7743ea0
test(jsonrpc): add test to enforce log of method call
renatomaia Aug 14, 2026
0b7c0c8
feat(jsonrpc): impose the same listed items limit for all requests in…
renatomaia Aug 15, 2026
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
11 changes: 6 additions & 5 deletions cmd/cartesi-rollups-cli/root/read/epochs/epochs.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@ cartesi-rollups-cli read epochs echo-dapp 10
cartesi-rollups-cli read epochs echo-dapp

# Read all epochs with filter:
cartesi-rollups-cli read epochs echo-dapp --status OPEN
cartesi-rollups-cli read epochs echo-dapp --status OPEN --status CLOSED

# Read all epochs with pagination:
cartesi-rollups-cli read epochs echo-dapp --limit 10 --offset 10 --descending
`

var (
status string
statuses []string
limit uint64
offset uint64
descending bool
)

func init() {
Cmd.Flags().StringVar(&status, "status", "",
Cmd.Flags().StringArrayVar(&statuses, "status", nil,
"Filter epochs by status (OPEN, CLOSED, INPUTS_PROCESSED, CLAIM_COMPUTED, CLAIM_SUBMITTED, "+
"CLAIM_STAGED, CLAIM_ACCEPTED, CLAIM_REJECTED, CLAIM_FORECLOSED)")
"CLAIM_STAGED, CLAIM_ACCEPTED, CLAIM_REJECTED, CLAIM_FORECLOSED); may be specified multiple times")
Cmd.Flags().Uint64Var(&limit, "limit", 50, //nolint: mnd
"Maximum number of epochs to return")
Cmd.Flags().Uint64Var(&offset, "offset", 0,
Expand Down Expand Up @@ -106,7 +106,8 @@ func run(cmd *cobra.Command, args []string) {

// Add status filter if provided
if cmd.Flags().Changed("status") {
params.Status = &status
epochStatuses := api.StringOrList(statuses)
params.Status = &epochStatuses
}
params.Limit = limit
params.Offset = offset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func run(cmd *cobra.Command, args []string) {

var result json.RawMessage
if len(args) >= 5 {
var params api.GetMatchAdvancedParams
var params api.GetMatchAdvanceParams
params.Application = args[0]
params.EpochIndex, err = config.AsHexString(args[1])
cobra.CheckErr(err)
Expand Down
21 changes: 15 additions & 6 deletions cmd/cartesi-rollups-cli/root/read/outputs/outputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ cartesi-rollups-cli read outputs echo-dapp 10
# Read all outputs:
cartesi-rollups-cli read outputs echo-dapp

# Read all outputs with filter:
cartesi-rollups-cli read outputs echo-dapp --epoch-index 10 --input-index 10 --output-type 0x237a816f --voucher-address 0x95eac57f9d67c5e0f255d5a19eb5d3fd00cafa73
# Read all outputs with filters:
cartesi-rollups-cli read outputs echo-dapp --epoch-index 10 --input-index 10 --output-type 0x237a816f --output-type 0x10321e8b --executed --voucher-address 0x95eac57f9d67c5e0f255d5a19eb5d3fd00cafa73

# Read all outputs with pagination:
cartesi-rollups-cli read outputs echo-dapp --limit 10 --offset 10 --descending
Expand All @@ -49,7 +49,8 @@ cartesi-rollups-cli read outputs echo-dapp --limit 10 --offset 10 --descending
var (
epochIndex string
inputIndex string
outputType string
outputTypes []string
executed bool
voucherAddress string
limit uint64
offset uint64
Expand All @@ -61,8 +62,10 @@ func init() {
"Filter outputs by epoch index (decimal or hex encoded)")
Cmd.Flags().StringVar(&inputIndex, "input-index", "",
"Filter outputs by input index (decimal or hex encoded)")
Cmd.Flags().StringVar(&outputType, "output-type", "",
"Filter outputs by output type (first 4 bytes of raw data hex encoded)")
Cmd.Flags().StringArrayVar(&outputTypes, "output-type", nil,
"Filter outputs by output type (first 4 bytes of raw data hex encoded); may be specified multiple times")
Cmd.Flags().BoolVar(&executed, "executed", false,
"Filter outputs by execution status")
Cmd.Flags().StringVar(&voucherAddress, "voucher-address", "",
"Filter outputs by voucher address (hex encoded)")
Cmd.Flags().Uint64Var(&limit, "limit", 50, //nolint: mnd
Expand Down Expand Up @@ -128,7 +131,13 @@ func run(cmd *cobra.Command, args []string) {

// Add output type filter if provided
if cmd.Flags().Changed("output-type") {
params.OutputType = &outputType
selectors := api.StringOrList(outputTypes)
params.OutputType = &selectors
}

// Add execution status filter if provided
if cmd.Flags().Changed("executed") {
params.Executed = &executed
}

// Add voucher address filter if provided
Expand Down
20 changes: 12 additions & 8 deletions cmd/cartesi-rollups-cli/root/read/service/jsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ func (s *JsonrpcReadService) ListEpochs(ctx context.Context, params api.ListEpoc
if _, err := config.ToApplicationNameOrAddressFromString(params.Application); err != nil {
return nil, fmt.Errorf("invalid application: %w", err)
}
// Add status filter if provided
// Validate status filter if provided
if params.Status != nil {
var statusVal model.EpochStatus
if err := statusVal.Scan(*params.Status); err != nil {
return nil, fmt.Errorf("invalid status: %w", err)
for i, status := range *params.Status {
var statusVal model.EpochStatus
if err := statusVal.Scan(status); err != nil {
return nil, fmt.Errorf("invalid status #%d: %w", i+1, err)
}
}
}

Expand Down Expand Up @@ -130,8 +132,10 @@ func (s *JsonrpcReadService) ListOutputs(ctx context.Context, params api.ListOut
}
// Add output type filter if provided
if params.OutputType != nil {
if _, err := api.ParseOutputType(*params.OutputType); err != nil {
return nil, fmt.Errorf("invalid output type: %w", err)
for i, selector := range *params.OutputType {
if _, err := api.ParseOutputType(selector); err != nil {
return nil, fmt.Errorf("invalid output type #%d: %w", i+1, err)
}
}
}
// Add voucher address filter if provided
Expand Down Expand Up @@ -338,7 +342,7 @@ func (s *JsonrpcReadService) ListMatches(ctx context.Context, params api.ListMat
return resp, err
}

func (s *JsonrpcReadService) GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvancedParams) (json.RawMessage, error) {
func (s *JsonrpcReadService) GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvanceParams) (json.RawMessage, error) {
if _, err := config.ToApplicationNameOrAddressFromString(params.Application); err != nil {
return nil, fmt.Errorf("invalid application: %w", err)
}
Expand All @@ -356,7 +360,7 @@ func (s *JsonrpcReadService) GetMatchAdvanced(ctx context.Context, params api.Ge
}

var resp json.RawMessage
err := s.Client.Call(ctx, "cartesi_getMatchAdvanced", params, &resp)
err := s.Client.Call(ctx, "cartesi_getMatchAdvance", params, &resp)
return resp, err
}

Expand Down
28 changes: 19 additions & 9 deletions cmd/cartesi-rollups-cli/root/read/service/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,14 @@ func (s *RepositoryReadService) ListEpochs(ctx context.Context, params api.ListE
pagination := repository.Pagination{}
// Add status filter if provided
if params.Status != nil {
var statusVal model.EpochStatus
if err := statusVal.Scan(*params.Status); err != nil {
return nil, fmt.Errorf("invalid status: %w", err)
filter.Status = make([]model.EpochStatus, len(*params.Status))
for i, status := range *params.Status {
var statusVal model.EpochStatus
if err := statusVal.Scan(status); err != nil {
return nil, fmt.Errorf("invalid status #%d: %w", i+1, err)
}
filter.Status[i] = statusVal
}
filter.Status = []model.EpochStatus{statusVal}
}
pagination.Limit = params.Limit
pagination.Offset = params.Offset
Expand Down Expand Up @@ -289,9 +292,13 @@ func (s *RepositoryReadService) ListOutputs(ctx context.Context, params api.List
}
// Add output type filter if provided
if params.OutputType != nil {
outputTypeVal, err := api.ParseOutputType(*params.OutputType)
if err != nil {
return nil, fmt.Errorf("invalid output type: %w", err)
outputTypeVal := make([][]byte, len(*params.OutputType))
for i, selector := range *params.OutputType {
parsed, err := api.ParseOutputType(selector)
if err != nil {
return nil, fmt.Errorf("invalid output type #%d: %w", i+1, err)
}
outputTypeVal[i] = parsed
}
filter.OutputType = &outputTypeVal
}
Expand All @@ -303,6 +310,7 @@ func (s *RepositoryReadService) ListOutputs(ctx context.Context, params api.List
}
filter.VoucherAddress = &voucherAddressVal
}
filter.Executed = params.Executed
pagination.Limit = params.Limit
pagination.Offset = params.Offset

Expand Down Expand Up @@ -782,7 +790,7 @@ func (s *RepositoryReadService) ListMatches(ctx context.Context, params api.List
return json.RawMessage(result), err
}

func (s *RepositoryReadService) GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvancedParams) (json.RawMessage, error) {
func (s *RepositoryReadService) GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvanceParams) (json.RawMessage, error) {
repo := s.Repository
application, err := config.ToApplicationNameOrAddressFromString(params.Application)
if err != nil {
Expand Down Expand Up @@ -839,7 +847,9 @@ func (s *RepositoryReadService) ListMatchAdvances(ctx context.Context, params ap
pagination.Limit = params.Limit
pagination.Offset = params.Offset

data, total, err := repo.ListMatchAdvances(ctx, application, epochIndex, params.TournamentAddress, params.IDHash, pagination, params.Descending)
data, total, err := repo.ListMatchAdvances(
ctx, application, epochIndex, params.TournamentAddress, params.IDHash, pagination, params.Descending,
)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/cartesi-rollups-cli/root/read/service/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type ReadService interface {
ListCommitments(ctx context.Context, params api.ListCommitmentsParams) (json.RawMessage, error)
GetMatch(ctx context.Context, params api.GetMatchParams) (json.RawMessage, error)
ListMatches(ctx context.Context, params api.ListMatchesParams) (json.RawMessage, error)
GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvancedParams) (json.RawMessage, error)
GetMatchAdvanced(ctx context.Context, params api.GetMatchAdvanceParams) (json.RawMessage, error)
ListMatchAdvances(ctx context.Context, params api.ListMatchAdvancesParams) (json.RawMessage, error)
Close()
}
Expand Down
25 changes: 24 additions & 1 deletion docs/http-posture.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ operator-side network policy.
| Surface | Default address | Purpose | Per-request cost |
| --- | --- | --- | --- |
| **Telemetry** (`/livez`, `/readyz`) | `:10000` | Orchestrator health checks | Trivial — a boolean check and a short response |
| **JSON-RPC API** (`/rpc`) | `:10011` | Read-only query interface | Up to 1 MiB body, DB queries, list responses up to 10000 items |
| **JSON-RPC API** (`/rpc`) | `:10011` | Read-only query interface | Up to 1 MiB body; one list operation, or a batch with a cumulative list limit of 10000 items; DB queries |
| **Inspect** (`/inspect/{dapp}`) | `:10012` | Machine state query without advancing | Up to 2 MiB body, Cartesi Machine fork + execution |

Telemetry is cheap by design — orchestrators (Kubernetes, Docker,
Expand Down Expand Up @@ -149,6 +149,29 @@ falls back to:
fail-fast; deeper in the request path).
- JSON-RPC: the PostgreSQL connection pool (blocking).

### JSON-RPC batch work budget

Admission counts HTTP requests, while a JSON-RPC batch can contain up to 100
operations. To keep one admitted batch from buying substantially more row-fetch
work than one maximal list request, the service applies a protocol-level budget
before dispatch:

- The sum of the effective `limit` values across all list entries in a batch
must not exceed 10000.
- An omitted or zero `limit` counts as the default of 50. A value above the
per-list maximum is capped to 10000 before it is added.
- If the sum exceeds 10000, the whole batch is rejected before any handler or
database query runs. The response is one JSON-RPC error object with code
`-31004` and message `Batch list item limit exceeded`.
- Non-list entries do not consume this work budget. A single request retains
the existing per-list maximum of 10000.

This restores the row-fetch bound that existed before batch support: one
admission slot can fetch at most as many rows as one maximal list call. It does
not bound `COUNT(*)` cost, which is independent of `limit`; selective filters,
the pending-output partial index, proxy rate limiting, and PostgreSQL capacity
planning remain important.

### Rejection semantics

When admission rejects a request:
Expand Down
Loading