Skip to content

Latest commit

 

History

History
259 lines (235 loc) · 23.1 KB

CELLSCRIPT_0_30_CKB_RUNTIME_VIEW_MATRIX.md

File metadata and controls

259 lines (235 loc) · 23.1 KB

CellScript 0.30 CKB Runtime-View Matrix

Status and contract

Status: accepted bounded cellscript-ckb-runtime-view-v1 contract for the 0.30 release candidate. Issue #24 is closed for this scope. Candidate 74cff5fd passed dev, ci (within release), backend, and release; public publication remains separate under #27. Independent review was explicitly waived by the maintainer, not performed or reported as passed.

Compile metadata schema 72 records the view contract name in runtime.ckb_runtime_view_contract and binds cellscript-ckb-runtime-access-provenance-v1 in runtime.ckb_runtime_access_provenance_contract. Metadata validation and the standalone artifact checker reject an absent, older, changed, or internally inconsistent provenance record. Every runtime access identifies the resolved source, source origin, static/dynamic/bounded index and admitted byte range. The legacy numeric index remains a compatibility projection; it is zero for dynamic accesses and the structured index is authoritative. The contract covers typed, read-only views and the bounded CKB runtime operations listed below. It does not grant Cell lifecycle authority and does not turn a value read from a transaction into authorization.

The syscall behavior is based on CKB's VM Syscalls RFC and syscall summary. LOAD_HEADER_BY_FIELD exposes epoch number, epoch start block number, and epoch length. Header timestamp and exact block number require bounded full-header decoding and are not represented as field-syscall values.

The typed temporal subset is defined separately in the 0.30 temporal-domain contract and follows CKB RFC0017 wire semantics.

Classification terms

Status Meaning
Executable Typed source accepted, bounded lowering emitted, and a runtime failure terminates verification.
Executable, limited Executable only for the named fixed-width or bounded shape.
Composition boundary Executable only after an exact external identity and adapter contract is declared.
Builder evidence Supplied or checked outside CKB-VM and never presented as an ambient syscall result.
Deferred Rejected or unavailable in production artifacts until its typed and bounded contract exists.
Outside 0.30 Deliberately excluded from the release portfolio.

Typed read-only handles

Every constructor takes a u64 index. Static literals and dynamic parameter bindings remain distinct in provenance, and every source-view index carries max_inclusive = 4294967295. InputView<T> and OutputView<T> also require a declared cell-backed resource, shared type, or receipt type argument. The runtime representation is a closed source-kind/index pair. An out-of-domain dynamic index or malformed pair fails with ckb-source-view-invalid; a missing indexed item fails through the field-specific terminal error.

Handle and constructor Source Executable fields Source type Runtime width and failure
ckb::input<T>(i) Input capacity, occupied_capacity, unoccupied_capacity, data_size, data_hash, lock_hash, type_hash, lock, type_script, out_point, since: EncodedSince InputView<T> Scalars are 8 bytes; hashes are 32 bytes; OutPoint is 36 bytes. Invalid/missing reads terminate.
ckb::group_input<T>(i) GroupInput Same field set as InputView<T> InputView<T> Same fixed widths; current Script-group-relative index.
ckb::output<T>(i) Output capacity, occupied_capacity, unoccupied_capacity, data_size, data_hash, lock_hash, type_hash, lock, type_script, output_index OutputView<T> Same scalar/hash bounds; output index is derived from the closed source view.
ckb::group_output<T>(i) GroupOutput Same field set as OutputView<T> OutputView<T> Same fixed widths; current Script-group-relative index.
ckb::cell_dep(i) CellDep capacity, occupied_capacity, unoccupied_capacity, data_size, data_hash, lock_hash, type_hash, lock, type_script CellDepView Same fixed widths. Resolved dep position is runtime evidence; original DepGroup/OutPoint identity remains builder or manifest evidence.
ckb::header_dep(i) HeaderDep epoch_number: EpochNumber, epoch_start_block_number: BlockNumber, epoch_length: EpochLength, block_number: BlockNumber, timestamp: TimestampMillis HeaderDepView Epoch fields are exact 8-byte LOAD_HEADER_BY_FIELD reads. Block/timestamp fields require an exact 208-byte LOAD_HEADER result and fixed RawHeader offsets. Bad source uses error 44, malformed size uses error 4, and missing/one-past-last HeaderDep uses error 45.
witness::args(i) Witness/Input size, fixed 32-byte lock, input_type, output_type projections WitnessArgsView size is 8 bytes. Field projections stream the selected bytes and are executable only when that Molecule field is exactly 32 bytes, regardless of sibling-field or total WitnessArgs size; absent or non-32-byte values use error 4 and malformed/truncated values use errors 42/43.
witness::bounded_raw(view, max) inherited Input/Output/GroupInput/GroupOutput size, exact byte/u32/u64 reads, full-view CKB Blake2b WitnessBytesView<raw,max> max is a literal in 0..=65536; the logical value is the complete serialized witness. Reads and hashing stream from LOAD_WITNESS without materializing the value.
witness::bounded_lock(view, max) inherited witness source Same bounded operations over WitnessArgs.lock WitnessBytesView<lock,max> Missing differs from Some(empty); absent uses error 67, values above max use 68, and malformed field encoding uses 42/43. This read-only view does not grant signer authority.
witness::bounded_entry(view, max) inherited witness source Same bounded operations over the one WitnessArgs.input_type value WitnessBytesView<entry,max> The logical bytes are the existing CSARGv1 entry envelope when that ABI is used. This is the shared owner for bounded plan, authorization, and entry consumers, not a second payload.
witness::bounded_output_type(view, max) inherited witness source Same bounded operations over WitnessArgs.output_type WitnessBytesView<output_type,max> The owner is distinct from lock and entry; all offsets are relative to the selected field payload.
ckb::input_out_point(input) or input.out_point inherited Input/GroupInput tx_hash, index OutPoint 32-byte transaction hash plus the exact 4-byte CKB u32 index; incompatible source or malformed width terminates.
ckb::lock_script(cell) or cell.lock inherited Cell source hash, code_hash, hash_type, args_empty, args_hash ScriptView Complete hash is ScriptHash; code_hash is raw Hash; args_hash is the exact 32-byte args projection represented as Hash, not a digest over arbitrary args. Scalar fields are bounded and Molecule-checked.
ckb::type_script(cell) or cell.type_script inherited Cell source Same as Lock ScriptView ScriptView An absent Type Script is not fabricated. Use ckb::cell_has_type(cell) before a conditional read.

ScriptHash, Hash, and Address are separate source domains. args_hash requires Script args of exactly 32 bytes and returns error 38 for any other width; args_empty handles the arbitrary-width empty/nonempty distinction. A complete Lock/Type Script hash from a typed view is ScriptHash. A code hash, data hash, transaction hash, or args hash is Hash. ckb::script_hash(hash) is an explicit assertion that already trusted raw bytes represent a complete Script hash; it does not prove existence, deployment, or authorization.

Code that has the Script fields can compute the complete value directly:

let args = script::args(b"owner")
let lock = script::new(code_hash, script::hash_type_data1(), args)
let complete: ScriptHash = script::hash(lock)

script::hash serializes the canonical Molecule Script table with offsets 16, 48, and 49, then applies CKB Blake2b-256. The serialized width is 53 + args.len; the current fixed scratch contract admits args.len <= 459. The hash-type helpers produce exactly the CKB values 0, 1, 2, and 4. A dynamic value outside that set, an invalid pointer, or an over-bound value returns script-construction-invalid (72). This constructs a value for comparison; it does not establish that the Script is deployed or authorized.

Existing bounded runtime families

Family Admitted operations Classification and bound
Source views source::{input,output,group_input,group_output,cell_dep,header_dep} Executable closed source-kind/index values. Legacy u64 consumers remain accepted for Edition 2026 compatibility; typed handles are preferred for new authoring.
Cell scalars and fixed bytes capacity/occupied/unoccupied, count, type presence, data size, exact u8/u32/u64 reads, serialized Script byte/size reads Executable or executable limited. Every byte offset is checked; fixed reads never allocate an unbounded buffer.
Cell identities data/lock/type hash reads and requirements, Script code-hash/hash-type/args checks, current Script args checks, canonical bounded script::new/script::hash Executable fixed 32-byte or scalar reads. Constructed Script hashing accepts at most 459 fixed args bytes. Absent Type Script and wrong Script domain fail closed.
Input lineage full OutPoint transaction hash/index requirements and MetaPoint pair helpers Executable fixed-width helpers. Pair scanners are protocol-neutral but have separately documented cardinality bounds.
Temporal and DAO typed HeaderDep epoch fields plus full-header block number and millisecond timestamp; opaque and decoded InputView.since; six absolute/relative block, epoch, and timestamp Since domains; checked narrowing; checked EpochDuration arithmetic; explicit raw conversions; legacy raw constructors; DAO accumulated-rate/header-lineage/maturity helpers The additive temporal subset is executable under the typed temporal contract. Full-header reads require the exact 208-byte Molecule Header; Since decoding validates RFC0017 flags and payloads; same-domain epoch-Since comparisons use canonical fraction ordering; duration construction and EpochNumber add/sub enforce the 24-bit domain.
Witness count/size, legacy exact byte/u32/u64/bytes32 reads, bounded spans, selected gather hashing, exact 32-byte typed WitnessArgs fields, and owner-tagged variable-length raw/lock/entry/output_type views with exact scalar reads and streaming Blake2b Executable limited. Bounded views admit at most 65,536 bytes and do not expose allocation, mutation, slicing as an owned value, or unchecked pointers.
Transaction identity and preimage canonical ckb::transaction_hash() through exact 32-byte LOAD_TX_HASH; bounded env::sighash_all_zero_lock; transaction_u32_le; bounded gather BLAKE2b; raw-transaction hash without CellDeps The raw transaction hash is fixed-width. The zero-lock signing domain is executable only for the current input Script group and its four declared bounds. The generic env::sighash_all(source) spelling remains fail-closed.
Signing-message domain env::sighash_all_zero_lock(max_group_inputs, max_inputs, max_extra_witnesses, max_witness_bytes) -> SighashAllDigest; explicit Hash::from_sighash_all conversion Hashes the exact transaction hash, the first group witness with the complete WitnessArgs.lock payload replaced by equal-length zero bytes, later group witnesses, and witnesses after the transaction input count. Every witness is prefixed by its little-endian u64 byte length. This covers simple all-zero lock placeholders. It does not implement multisig layouts that preserve a nonzero configuration prefix.
Hashing CKB BLAKE2b data/span helpers, fixed SHA-256/SHA256d values and pairs, bounded SHA256d Merkle proofs Executable fixed-width or literal-bounded operations. No allocator-backed streaming hash surface is implied.
CellDep delegation exact-index/literal-bounded data-hash checks; fixed u8/hex4 EXEC; hex4 SPAWN/WAIT Raw adapters remain fail-closed under production policy. trusted_* forms are a composition boundary requiring an exact manifest declaration and data hash; successful delegation does not prove external internals.
Protocol helpers bounded xUDT, DAO, C256, and MetaPoint requirements Executable only for their documented fixed shapes. They do not widen the general transaction-view contract.

Stable failures used by v1

Code Name Runtime-view use
1 syscall-failed CKB syscall returned an unsupported nonzero status where no narrower error applies.
2 bounds-check-failed Requested byte range is outside the admitted source length.
3 cell-load-failed Required Cell bytes or fields could not be loaded.
4 exact-size-mismatch Fixed-width syscall result did not have the exact required size.
20 numeric-or-discriminant-invalid EpochDuration construction or EpochNumber arithmetic exceeded the 24-bit domain or underflowed.
33 out-point-mismatch Input lineage differs from the required OutPoint.
34 script-field-malformed Serialized Script field is absent or malformed for the requested projection.
37 ckb-since-malformed Since flags, metric, scalar bound, timestamp conversion, epoch-fraction components, or requested narrowing violate the admitted encoding.
38 script-args-mismatch Script args violate the declared exact/empty rule.
41 script-identity-mismatch Script code hash or hash type differs from the required identity.
42 witness-malformed WitnessArgs or entry envelope is not canonical Molecule data.
43 witness-field-truncated WitnessArgs offset/length exceeds the loaded witness.
44 ckb-source-view-invalid Closed source kind and consumer are incompatible or the encoded view is malformed.
45 header-dep-missing HeaderDep index is missing, including one-past-last.
46 dao-field-malformed DAO header or cell field has the wrong fixed layout.
63 bounded-cell-dep-not-found Literal-bounded CellDep scan reached its maximum without an exact data hash.
66 sighash-all-unsupported Deferred canonical signing-message construction was requested.
67 witness-field-absent A bounded WitnessArgs field is absent; Some(empty) remains a present zero-length value.
68 witness-bound-exceeded The selected raw witness or field is larger than its compile-time declared maximum.
69 sighash-bound-exceeded A group/input/extra-witness count or included witness exceeds the signing-domain literals.
70 exact-script-handle-invalid An exact handle encoding, commitment, class, role, selected Script, or verifier code identity differs.
71 deployment-line-handle-invalid An exact active line, admission CellDep, code CellDep, or selected Script identity differs.
72 script-construction-invalid A constructed Script has an invalid pointer, args width, or CKB hash type.

Current executable evidence

tests/typed_runtime_views.rs executes the new Cell, input, CellDep, and HeaderDep fields and bounded witness views in CKB-VM. It covers a nonzero header epoch at index zero, the derived epoch-start block number, a one-past-last HeaderDep, exact absolute and relative wire vectors for all six Since domains, checked decoding and narrowing, canonical epoch-fraction comparisons, malformed flags/fractions and scalar bounds, checked epoch-duration arithmetic and its overflow/underflow boundaries, exact full-header block/timestamp reads, the exact 32-byte CKB raw transaction hash, an exact CellDep data hash, a substituted hash, successful dynamic Input/CellDep/Witness index zero, and a dynamic index above the 32-bit view domain. The bounded witness cases cover all four owners, 700/900/1024-byte fields, the complete serialized witness, exact scalar reads, streaming hashes, Some(empty), absent and over-bound values, malformed/truncated Molecule data, and GroupOutput provenance. tests/sighash_zero_lock.rs differentially compares the emitted digest with the pinned ckb-sdk-rust message generator across a non-contiguous two-input Script group, an unrelated input witness, and a transaction-level extra witness. It also proves post-message witness mutation changes verification and all four declared bounds terminate with error 69. Metadata schema 72 records the exact transform, order, digest domain, scope, and limits; the independent checker binds those records to runtime access provenance and typed call operands after outer hashes are rebound. Generated TypeScript builder manifests and plans preserve the same domain and require pre-signing witness placement; the metadata-only browser summary exposes it as well. tests/artifact_checker.rs changes source, index bound, range, contract, transaction-hash operation/syscall/binding/width, bounded owner/maximum, handle, and module/entry copies after outer hash rebinding and requires independent V2410 rejection. HeaderDep-specific cases additionally change each access record, typed result, declared syscall contract, CKB syscall number, field selector, SourceView kind/index, 8/208-byte request and response width, RawHeader offset, return-code branch, and errors 44/45/4 in the final RISC-V instructions. Lowering record v8 rejects those rebound record or machine mutations. Generated TypeScript builder tests retain the same dynamic parameter bound. The four-artifact business anchor additionally passes its exact WitnessArgs.input_type Plan bytes, current Type Script hash, ordered GroupOutput indexes, Cell scripts, and capacities through ProtocolBundle's per-artifact metadata validation. Adapter materialization must then reproduce the CKB-VM transaction byte for byte before aggregate cycle evidence is bound to its direct CellScript groups. tests/authoring_replace.rs exercises the ScriptHash domain against real output Lock Script hashes. Existing tests/ickb_diff.rs, tests/crypto_primitives.rs, and artifact-checker mutation suites retain the older bounded helper families. tests/script_hash.rs differentially compares all four hash types, empty and maximum args, and substituted results with ckb-types::Script::calc_script_hash inside CKB-VM. Lowering record v8 binds that typed call and its exact Molecule serialization, 459/512-byte bounds, Blake2b target, and error 72 to the final machine code. tests/artifact_checker.rs mutates each of those boundaries after recomputing outer hashes and requires independent rejection. The non-cryptographic fixed transaction/header/temporal path now freezes exact cycles, ELF bytes, maximum stack frame, witness bytes, transaction bytes, and dependency bytes in tests/fixtures/runtime_view_resource_budgets.json and reproduces them in tests/typed_runtime_views.rs. A second exact profile binds global Output and current-group GroupOutput fields, an absent input Type Script, complete Lock/Type Script projections, exact 32-byte args, the maximum 459-byte Script-args boundary, one-past-last indexes, artifact and sidecar hashes, and raw and serialized transaction hashes. Its measured maximum stack frame is 11,344 bytes under an explicit 16,384-byte profile budget. Cryptographic and bounded witness maxima remain owned by the separate cryptographic resource manifest. The four-artifact business anchor separately executes GroupInput data_size and capacity reads in all three actions of its persistent order policy. That exact policy artifact passes policy-witness dispatch, generated-builder and ProtocolBundle materialization of the byte-identical transaction, same- transaction CKB-VM composition, and stateful partial_fill then settle plus cancel execution. The anchor pins the policy artifact and sidecar identities, 41,822 cycles, 16,424 combined ELF bytes, and the transaction and bundle hashes. The same stateful test supplies the third exact non-cryptographic resource profile in runtime_view_resource_budgets.json: fixed fixture OutPoints bind all three transaction identities, and the maximum action records 17,341 cycles, a 7,040-byte ELF, 5,376-byte stack frame, 145 witness bytes, 493 transaction bytes, and 14,224 dependency bytes under explicit ceilings. A fourth exact profile covers every field of global Input, current-group GroupInput, and CellDep views together with complete Lock/Type Script, OutPoint, Since, and exact 32-byte WitnessArgs.lock/input_type/output_type projections. It also closes the independent checker's previously missing InputView<T> to internal OutPoint-reference type binding. The profile pins artifact and sidecar identities plus raw and serialized transaction hashes; its maximum is 92,896 cycles, 16,208 ELF bytes, a 22,880-byte checked stack frame, 124 witness bytes, a 597-byte transaction, and 73 dependency bytes. A fifth exact profile proves the same closed runtime-view surface behind a real PolicyWitnessV1 Type-group dispatcher. Its witness is produced through the generated action-record encoder and canonical policy-bundle adapter, while the entry exercises complete GroupInput/GroupOutput, CellDep and HeaderDep fields, OutPoint, Since, bounded entry bytes, and raw transaction hash before a checked one-input/one-output resource transition. It pins all artifact/sidecar and transaction identities at 96,109 cycles, 21,368 ELF bytes, a 20,000-byte checked stack frame, 145 witness bytes, a 594-byte transaction, and 73 dependency bytes.

Two optional extensions are not required by the frozen 0.30 corpus. No scenario consumes a full Header hash; typed epoch/block/timestamp fields already cover the admitted temporal portfolio. Multisig authorization uses the pinned standard multisig-v2 Lock and its WitnessArgs.lock ownership boundary, so CellScript does not recreate the Lock's prefix-preserving signing-message transform. Adding either operation later requires a separately admitted typed, bounded contract rather than widening v1 implicitly.

The repository-local implementation and executable evidence for the frozen runtime-view v1 table are complete. Any newly admitted adapter row must add its own maximum-bound measurements and independent machine binding rather than inheriting this status. Issue #24 was closed on 2026-09-12 and the final candidate replay passed at 74cff5fd on 2026-09-18. See the issue status audit for the exact candidate and the distinction between completed verification, the explicit review waiver, and outstanding publication.

Deferred and excluded surfaces

Production source does not admit raw numeric syscalls, arbitrary pointers, unbounded transaction/witness/header materialization, an unchecked syscall status, or a generic unsafe escape hatch. CKB2023 process pipes and inherited file descriptors remain fail-closed except for the exact bounded adapters already used by declared external verifiers. Raw extension loading, allocator configuration, dynamic libraries, and general process programming are outside the 0.30 business portfolio unless a later scoped issue changes that decision.