Changelog#
User-observable changes to the specification, grouped by executor line (see Executor Versioning). Internal refactors are omitted; see the repository history for those
v0.2#
Breaking#
LeaderPublicDatauses calldata{"nd_outs": bytes[]}instead of an RLP list with a trailingpaddedsentinel. Its gas accounting uses a conservative 64-byte frame plus a 64-byte header and 32-byte-padded data for each outputFee-bucket references are human-readable names. The execution request’s
bucket_totalsand result’sdata_fees_remainingfields are maps keyed by bucket name, and executor fee rules usebucketswith 1 name or an array of names. Numeric bucket arrays and the formerbucket_noconfig field are rejected
v0.3#
Breaking#
ZIP runner loads charge per-entry metadata in addition to the raw archive size and base load cost (see runner load charges)
RAM overheads increase for runner loads, emissions, message-fee rotations and nondeterministic outputs
Each sub-VM is limited to max_runners loaded runners; exceeding the cap exits with out_of memory
VFS paths are limited to vfs_path_len UTF-8 octets
LeaderPublicDatauses calldata{"nd_outs": bytes[]}instead of an RLP list with a trailingpaddedsentinel. Its fee and output-cap accounting uses a conservative 64-byte frame plus a 64-byte header and 32-byte-padded data for each outputEach outbound message consumes 1 unit from the
submitted_messages_countbucket in addition to its byte and gas charges. Submitted-message byte accounting includes the canonical ABI array frame, struct head, fee parameters, payload, and allocation subtree. Receipt-gas accounting includes the host-providedreceiptWrapperBytesgovernance valueMessage-reveal gas and ABI-array overhead are charged on the first successfully emitted message rather than at execution startup. Message-free executions do not consume that reveal allowance
Fee-bucket references are human-readable names. The execution request’s
bucket_totalsand result’sdata_fees_remainingfields are maps keyed by bucket name, and executor fee rules usebucketswith 1 name or an array of names. Numeric bucket arrays and the formerbucket_noconfig field are rejectedThe pre-finalization state is spelled decided everywhere it is named. storage_view reads
latest_finalized(1) andlatest_decided(2) instead oflatest_finalandlatest_non_final, theonfield of theEmitInternalMessageandEmitInternalDeployMessagegl_callpayloads (gl_call Messages) takes"decided"instead of"accepted", and achain:runner id selects it withdrather thana(see chain: State Visibility). Numeric enum values are unchanged; none of the old spellings is acceptedA
chain:runner id resolved while a contract is being deployed canonicalizes toi, which previously spelled the deploy state asdThe
Whenaction’scondfield spells the non-deterministic mode!det; the previousnondetspelling is rejected, with no back-compat alias. See theWhenaction in Runnersrunner.jsonrejects unknown top-level and nested fields; a runner that relied on an extra field being silently ignored fails to load. The single top-level$schemastring annotation is still accepted. See runner.json JSON Schema and the action definitions in RunnersZIP-packaged runners are accepted under narrower rules; an archive that previously loaded despite violating one of them now fails. See the “ZIP Archive” layout in Runners:
Compression must read
storedin both the central directory and the entry’s local headerA stored entry’s compressed and uncompressed sizes must be equal
Every entry’s CRC-32 is validated against its declared value
A directory entry must carry no contents; it is skipped rather than added to the file list
Entry names are validated at parse time: no empty name, no leading
/, no backslash, no empty,.or..path component, no trailing/on a fileEntries sharing a name resolve to the last of them
Hosts must provide separate
minProposeTimeout,maxProposeTimeout,minCommitTimeoutandmaxCommitTimeoutgas-data values. The formerminTimeUnitsPerPhasevalue is no longer read
Changed#
Every internal message declares its minimum primary fee plus its direct child allocation budgets, independent of whether it is emitted on acceptance or finalization. Balance-funded messages have no allocation subtree and declare only the primary fee; external messages declare zero
Unless both time-unit allocations are zero, internal message emission checks leader units against propose bounds and validator units against commit bounds; violations report fee below_minimum
A missing or malformed runner archive/comment header is now reported as invalid_contract runner absent or invalid_contract runner malformed respectively, instead of the former
invalid_contract absent_runner_commentandinvalid_contract malformed_runnercodes. A malformed runner archive also now reports the precise invalid_contract runner malformed code where it previously surfaced a bareinvalid_contractA RunNondet Message block starts on a budget seeded with its caller’s remaining RAM instead of a fresh 4 GiB one, so it can no longer use more RAM than the deterministic caller had left. See Resource Limiting
Emitted messages, events, and leader nondeterministic outputs consume RAM for their retained representations. Their charges, like storage write charges, remain until execution ends and transfer to a caller that adopts a sandbox child’s retained data. See Resource Limiting
A resource error raised while a module is being instantiated keeps its own code — e.g. exhausting the memory budget there reports out_of memory wasm_memory — instead of being reported as a bare
invalid_contractstorage_readandstorage_writebound an access by the Storage Slot length instead of byu32overflow, so a slot’s final octet is addressable; every access naming it was previously refused. See Functions