Skip to main content

Activation notice — block 17,113,494

info

LIVE since block 17,113,494. Node 0.9.13 swapped in at block 17,113,493 on 2026-09-23, and both changes below turned on one block later. This page is the record of what changed at that boundary.

{"type":"account_state","address":"0x…"} carries the live height if you need to check where the chain is.

Two behaviours move at this height. Anything else in the release changes no request, response, or rejection you can see.

Why one block above the swap. The outgoing node commits block 17,113,493 and only then halts, so that block still ran the old rules. The new rules apply from the first block after it.

The signed action is capped at 1 MiB​

SurfaceBefore the heightNow
/exchange with an action over 1,048,576 bytesAccepted when the whole body is under 2 MiB400 INVALID_REQUEST, message action is N bytes; the limit is 1048576 bytes
node_actions error_codeNo such codeDROPPED_ACTION_TOO_LARGE. Only a faulty proposer produces it
/exchange with an action under the cap that does not fit one blockAcceptedDropped before any block. The synchronous verdict is 200 INVALID_REQUEST, message action too large: its stored form does not fit in one block

Why. Every validator stores the exact action bytes in the block and checks the signature again at commit. The cap bounds the work that one action puts on every validator.

What counts. The cap counts the action bytes as sent, whitespace included. A compact 1,000-leg batch_order is between a quarter and a half of the cap.

The public endpoint refuses first. api.testnet.mtf.exchange refuses a request BODY over 1 MiB with 413 and an HTML page, not the JSON envelope. An action at the cap always makes a body over 1 MiB, so a caller on the public endpoint sees that 413 and never the node's message. Match on the status, not on a body you cannot parse.

Why an action under the cap can still fail. A block holds about 3 MiB. The node stores each action twice: the bytes as sent and the decoded action. A byte outside ASCII takes two bytes in that stored form. So only an action near the cap, made mostly of non-ASCII text, can be too large for one block.

What to do. Send compact JSON. Both client SDKs already do. Nothing else moves: every signing rule stays the same.

A batch_cancel answers for each leg​

SurfaceBefore the heightNow
batch_cancel 200 replyThe admission fields onlyThe admission fields, plus statuses: one canceled or error entry per leg, in request order
order_updatesNo record for any batch_cancel legOne status: "canceled" record per leg that removed its order. A refused leg pushes nothing

Why. The legs run one by one, and a refused leg does not refuse the batch. So before the height a node answered committed: true when a leg named an order that was already gone, and the caller could not tell that leg from one that removed its order. A leg that names the old oid of a modified order is the common case.

What to do. Read statuses[i] for leg i. Match an error entry on statuses[i].error.code: the entry is the flat {code, message, details?} object, read on the running chain on 2026-09-23. Nothing else moves: the request shape, the signed digest and the admission fields stay the same, so a caller that ignores statuses keeps working.