Repository navigation
[0.32][Language/ABI] Stabilize generic compatible-open Script and verifier handles #28
Description
Completed — 2026-10-12
Implemented on branch 0.32; clean-source executable acceptance is bound to 16b9e58394aa182f071303e6b5ab15dc94d304f4. The acceptance mapping maps each required boundary to executable evidence. Its original pending-backend status is superseded by the passing clean replay recorded here; the final documentation-only refresh is prepared locally but awaits GPG unlock.
- Nominal ScriptHandle/VerifierHandle, independently recomputed receipts, immutable member policies, exact dependency/Script/network identities and Type-hash history binding are implemented.
- Lock and Type consumers admit selected Type-policy, single Type/Lock and parameterless SPAWN/WAIT verifier profiles. Unsupported public codecs fail closed; arbitrary child argv ABI and behavioral equivalence are not claimed.
- O0–O3 Lock/verifier transaction matrices cover identical native/CLI/generated-TypeScript/SDK bytes, actual Script-group execution, failing Lock predicates and spawned children, receipt/machine/role/dependency substitution, and signing boundaries.
- Full backend log SHA-256:
d768615c34b8054b907448347606b9e01fdfbbd7206101a8352ed2296b191269; strict backend report SHA-256:093138c609ab64847338683c6c34117a33fb6738e01bf6c480322eaee6fa12cf. Both report success. - Full
ci, clean-sourcebackend(including pinned CKB stateful scenarios andcounter_node_acceptance) and finalcommitgates passed. The CKB receipt binds source commit16b9e583withgit_dirty=false; its SHA-256 isa144be567c14c35702034370f7ccc1c76ded743441560528a45425829a36908c. - External human audit remains waived by the maintainer; no such audit is claimed. The frozen profile and resource limits in the design/acceptance record remain part of the admitted contract.
Maintainer decision — 2026-10-11: external audit requirement cancelled
The maintainer explicitly cancelled the external audit / independent human security review requirement for #28. Assigning an external reviewer is no longer a closure or stable-admission gate for this issue. This supersedes earlier issue text and comments requiring that review; it does not claim an audit occurred.
The independent artifact checker, receipt recomputation, compiler/checker agreement, adversarial CKB-VM tests, Type-hash history binding, generated-builder/ProtocolBundle byte parity, deterministic identities, resource budgets and applicable unified gates remain required. Unfinished technical acceptance still prevents closing the issue. The maintainer subsequently waived #29's external human review requirement as well. Neither waiver authorizes release publication or deployment.
Accepted scope update — 2026-10-04
The maintainer promoted this issue into the 0.32 implementation scope. Earlier post-v1/deferred wording below records its original separation from 0.30; it is no longer the current version assignment. All required contracts and acceptance evidence remain applicable. The original external review requirement is superseded by the maintainer decision below; all technical acceptance criteria remain required. Implementation and technical acceptance are complete; see the completion record above.
Summary
Track the generic compatible/open handle model that is deliberately outside CellScript 0.30's exact fixed-width handle closure in #11.
CellScript 0.30 supports exact artifact-bound ExactScriptHandle and exact-version deployment-line handles. This issue must not weaken those identities into a producer-supplied compatibility bit. It owns a future contract for selecting one implementation at construction time from an explicitly compatible, independently verified set.
Required contract
- Define
ScriptHandle<I>/VerifierHandle<I>as nominal values distinct from raw CKBScript, artifact identity, deployment identity, and behavioral equivalence. - Recompute the complete public interface receipt from independently checked artifact records, including nested layouts, callable/witness ABI, effects, target/profile, source codec, and compatibility axes.
- Bind the concrete code bytes/CellDep actually selected by the transaction, including Type-hash replacement history.
- Specify exact-version, compatible-version, active/yanked, downgrade, and stale-receipt semantics.
- Define an immutable on-chain commitment model; Registry discovery alone is not authorization.
- Preserve full Script role, code_hash, hash_type, args policy, deployment line, and network identity.
- Make ProtocolBundle reject missing, duplicate, conflicting, unverified, or post-build-substituted receipts before signing/materialization.
- Keep source and CKB runtime values fixed or explicitly bounded; no arbitrary dynamic allocation.
Acceptance evidence
- A versioned design record and threat model covering data-hash and Type-hash deployments.
- Independent checker recomputation of every receipt field it owns.
- Positive exact and compatible selections plus nested-layout, ABI, target, args, CellDep, yanked, downgrade, and substitution negatives.
- Generated-builder and ProtocolBundle parity on identical transaction bytes.
- CKB-VM enforcement for every claim represented as on-chain; builder-only claims remain labeled off-chain.
- Deterministic artifact, receipt, transaction, and resource identities.
Non-goals
- Reopening or weakening [Language/ABI] Bind runtime Script values to verified package interfaces #11's exact fixed-width 0.30 contract.
- Inferring behavioral equivalence from interface shape or semver alone.
- Treating Registry contents as a consensus root of trust.
- Adding runtime-selected open cross-Script roles; those are tracked separately and depend on this issue.
Relationship
Split from #11 after its bounded 0.30 exact-handle scope was implemented. This is post-v1/deferred work and is not a 0.30 release blocker unless a later accepted scope explicitly promotes it.
Activity
docs: add #28 compatible-open handle design record and threat model
a19q3 commentedon Oct 10, 2026
Design-record deliverable published at
37f4c602on0.32: the versioned design record and threat model CELLSCRIPT_OPEN_HANDLE_DESIGN.md (cellscript-open-handle-design-v1). It consolidates the implemented boundary — authorization-set wire and CCC vectors, finite Type-policy receipts, native v1/v2 policy/source bindings with exact/compatible selection, SemVer precedence, direct-dependency and Type-group transaction snapshots — into the six design decisions, a data-hash versus Type-hash deployment profile split, and a thirteen-entry threat table (T1–T13) mapping each adversary action to its enforcing boundary with an explicit enforced/pending/non-goal state. Residual risks before stable admission are listed: finite-profile exclusions fail closed, root authorization is host-side only, runtime membership execution is unimplemented, builder/ProtocolBundle parity is unintegrated, worst-case runtime budgets are unmeasured, and the independent security review remains unassigned. This satisfies the first acceptance-evidence item of the issue; it is a progress record, not closure.Remaining for H1: private template structural/phantom-use projection, universal/absent template coverage, complete nominal qualification for ambiguous unqualified arguments, full directional receipt compatibility, and the complete general codec/builder/executable obligations beyond the
policy-unit-scalars-flat-unsigned-cell-v1profile. Remaining for H2: nominalScriptHandle<I>/VerifierHandle<I>source values, class/role separation, immutable root binding to committed code/args, and CKB-VM enforcement with measured budgets. Generated-builder/ProtocolBundle byte parity, the final unified gates and signed publication follow those. The independent security review (not covered by the 2026-10-03 waiver) remains a final stable-admission requirement; closing this issue before those contracts and evidence exist would contradict its own acceptance list.a19q3 commentedon Oct 10, 2026
Implementation progress at
7c54d759on0.32(maintainer authorized continuing the H1 leftover items, then H2; this issue remains open).nominal:/layout:contracts cover the template, the concrete instance and the phantom-only argument nominal itself. Structural use of private templates through public spellings was already projected and is unchanged.tests/interface_projection.rs::retained_private_instances_project_phantom_identity_dependencies;crates/cellscript-artifact-checker/src/interface/projection.rscarries the closure seeding with the existing 256-nominal and 4,096-visit bounds unchanged.interface_projection(8),interface_inspection(10),policy_artifact_checker(71),frozen_interface(38), checker lib (40) andopen_handle_policy(9) all pass single-threaded; checker clippy--all-targetsand fmt clean; commit gate passed. No producer metadata, wire schema or cache identity changed — bundles keep their existing sidecar identities; only newly derived projection contracts differ where retained instances exist.Remaining H1 items: universal/absent template coverage in symbolic verification, complete nominal qualification for ambiguous unqualified instantiation arguments, full directional receipt compatibility (effect weakening/binder relaxation), and the general codec/builder/executable obligations beyond
policy-unit-scalars-flat-unsigned-cell-v1. Then H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle parity, final unified gates and the still-unassigned independent security review. Not closing this issue yet.a19q3 commentedon Oct 10, 2026
Implementation progress at
8cfd1524on0.32(second H1 leftover item landed; issue remains open).tests/policy_artifact_checker.rs::private_absent_template_declarations_reject_rebound_universal_mutations: for a private never-instantiated struct template and a private absent function template at O0–O3, weakening a non-phantom parameter below the fixed-value boundary, repointing a symbolic field toVec<T>(declared fixed ability no longer supported), and unresolved function parameter/return references reject exactly at the universal sweep after passing inspection; ability ordering and unresolved structural fields remain owned by the earlier catalog binding checks (asserted at their layer).open_handle_policy9,interface_projection8,interface_inspection10,policy_artifact_checker72,frozen_interface38 all pass single-threaded; checker clippy--all-targetsclean; fmt clean; commit gate passed. No producer metadata, wire schema or cache identity changed. Note: this commit is unsigned (--no-gpg-sign) because the agent's signing passphrase cache expired and interactive pinentry is unavailable in the current shell; branch history already contains unsigned commits.interface/generics.rs— currently raw spellings are compared, so a template name or argument resolved differently per scope can collide textually), full directional receipt compatibility (effect weakening/binder relaxation), and the general codec/builder/executable obligations beyondpolicy-unit-scalars-flat-unsigned-cell-v1. Then H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle parity, final unified gates and the still-unassigned independent security review.a19q3 commentedon Oct 10, 2026
Scoping result for the next H1 item — complete nominal qualification for ambiguous unqualified instantiation arguments (
interface/generics.rs): the checker-side raw-spelling comparison (substitutions/matches_type/type_instancesmap template names and arguments as unqualified source text, so tokens resolved differently per scope can collide textually) is currently unreachable for the cross-module case, because the producer fails closed one step earlier. An imported template application used as a generic argument — e.g. consumeruse a::PairthenHolder<Pair<u64>>— is rejected at compile time withE2111: type argument 'Pair__mono__…' for 'T' does not satisfy 'copy' (value-ability registry v1), with a single imported template and no name collision at all. Local template arguments compile and check; only imported ones lack registry evidence.Consequence: the qualification work splits into (1) a producer prerequisite — register ability evidence for imported template instances used as arguments, or intentionally document that boundary as unsupported — and (2) the checker-side two-scope qualification of
type_arguments, declared field spellings and the instances map (qualify through the record/defining scopes asinterface/layouts.rsalready does for layout identities). Both remain open; no security hole exists today because the path fails closed at the producer. No code landed for this item in this session beyond the scoping evidence.a19q3 commentedon Oct 10, 2026
Implementation progress at
972f978fon0.32: the item-C producer prerequisite and the checker-side qualification both landed (issue remains open).src/generics.rs::register_external_itemsnow derives omitted template value-abilities for imported struct/enum templates exactly as the local declaration path does (same derivation function, same definition, so owner and consumer derive the identical set). An imported template application can therefore serve as a generic argument to a locally declared template and compiles at O0–O3, with or without an explicithasclause — previouslyE2111: value-ability registry v1rejected it fail-closed.qual::a::Pair<u64>), concrete type evidence answers both raw and scope-qualified spellings, and argument-constraint checks (bundle-levelverify_instantiationsand the interface-layercheck_constraints) qualify unqualified names through the record module's nominal scope first. Two owners exporting the same template name now keep distinct qualified evidence: the two-owner fixture compiles, inspects, validates and projects withlayout:qual::a::Pair<u64>distinct fromlayout:qual::b::Pair<u64>, and rebinding the local alias to the other owner is rejected by directional contract matching. The unqualified ambiguous spelling without catalogs, and any catalog-free bundle, stay fail-closed as before.policy_imports6 (two new O0–O3 tests),policy_artifact_checker72,interface_projection8,interface_inspection10,frozen_interface38, checker lib 40 +open_handle_policy9 — all single-threaded; clippy--all-targets/--libclean for both crates; fmt clean; commit gate passed. Commit is unsigned (--no-gpg-sign, same GPG agent constraint as8cfd1524).Remaining H1: full directional receipt compatibility (effect weakening/binder relaxation) and the general codec/builder/executable obligations beyond
policy-unit-scalars-flat-unsigned-cell-v1, plus the doubly-external nesting orchestrator contract. Then H2, parity, final gates and the still-unassigned independent security review.a19q3 commentedon Oct 10, 2026
Implementation progress at
49c7dd4con0.32: the directional receipt-compatibility relation landed (issue remains open).CheckedModuleProjection::check_required_contracts(which the finite policy receipt also delegates to) now implements the enumerated directional relation instead of conservative exact equality: inferred effects (effective:contracts) and declared effects (callable:contracts) may only become more restrictive — Pure admits only Pure, ReadOnly admits Pure or ReadOnly, and each of Mutating/Creating/Destroying admits itself plus the two smaller classes, since the three state-changing classes are pairwise incomparable — and binder constraints (type_parameterson callables,parameterson generic template nominal contracts) may only relax: a candidate may stop demanding an ability the baseline demanded, so every baseline-admitted argument still satisfies it, but may never demand a new ability. Binder names, phantom flags, declared template abilities, codecs and every other field stay exact; absent required keys and any other difference still reject.inferred_effects_may_only_become_more_restrictive(a Pure candidate satisfies a ReadOnly baseline; the reverse rejects) andbinder_constraints_may_only_relax_directionally(a weaker phantomcopybinder satisfies acopy + dropbaseline and a relaxedT: copycallable satisfiesT: fixed_value; both reverse directions reject) at O0–O3; the pre-existing strengthening mutation (copy→copy + dropas candidate) still rejects.interface_projection9,policy_artifact_checker72,interface_inspection10,policy_imports6,frozen_interface38, checker lib 40 +open_handle_policy9 — all single-threaded; clippy--all-targetsclean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint as before).Remaining before #28 can close: the general codec/builder/executable obligations beyond
policy-unit-scalars-flat-unsigned-cell-v1, the doubly-external nested-instantiation orchestrator contract, then H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs to be assigned by the maintainer; the 2026-10-03 waiver does not cover this contract.a19q3 commentedon Oct 10, 2026
Implementation progress at
510beec9on0.32: the doubly-external nested-instantiation orchestrator contract landed (issue remains open).Holderfrom x andPairfrom a, thenHolder<Pair<u64>>) previously failed closed withE2111at the outer owner's seed boundary, because the owner state had no evidence for the foreign monomorph name. The seed now carries, for every argument materialized in a third module, its derived ability evidence plus the defining owner module and concrete name (ForeignSeedArgument); the outer owner pre-registers that evidence before validating the seed and records the cross-owner reference, and the orchestrator (src/lib.rs) emits a use-import binding the requesting spelling to the argument owner's public concrete — aliased when the local import spelling differs from the defining source name. The independent artifact checker re-derives every ability claim from the emitted bundle; the forwarded producer values unblock the producer pass only.imported_template_nested_under_imported_template_materializes_across_ownerscompiles the three-module fixture at O0–O3, asserts thequal::a::Pairandqual::x::Holderinstantiations in the record, and passes independent inspection and module projection.policy_imports7, compiler lib 997,policy_artifact_checker72,frozen_interface38,interface_projection9,interface_inspection10, checker lib 40 +open_handle_policy9 — all single-threaded; clippy--all-targetsclean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).With this, the H1 leftover list from the 2026-10-07 review is complete except the general codec/builder/executable obligations beyond
policy-unit-scalars-flat-unsigned-cell-v1. Remaining before #28 can close: that general-profile extension, then H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.a19q3 commentedon Oct 10, 2026
Implementation progress at
e70bb0bbon0.32: the finite external-codec profile advanced frompolicy-unit-scalars-flat-unsigned-cell-v1topolicy-unit-scalars-nested-unsigned-cell-v1(issue remains open).struct, and recursively satisfy the same unsigned obligations — contiguous offsets across nesting boundaries, matched aggregate widths, depth ≤ 8, total ≤ 512 bytes. Entry-bound Cell layouts stay flat by design: their ELF-level field materialization certification (fixed_cell_fields) is per direct scalar field. The receipt and codec records both advance the profile string; identities are content-derived, and no schema or identity domain changed.nested_public_layouts_stay_pending_entry_body_certification, O0–O3). Public constants still reject: their types are proven but not their values, and an independent constant-value proof needs its own bounded evaluation contract. These two — nested field-materialization certification and constant-value proofs — are the remaining named pieces of the general codec obligations, now with precise boundaries instead of an undifferentiated "general profile" gap.external_codec::tests): contiguous composition across two nesting levels, aggregate widths, Cell-path flatness under the same record, and rejections for nested width mutation, boundary offset drift, missing member layouts, the depth bound, and equal-width nominal substitution semantics (structural for the codec check; owners stay distinct at the module-contract layer).policy_artifact_checker73,frozen_interface38 — all single-threaded; clippy--all-targetsclean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).H1 is now complete except the two precisely-bounded pieces above. Then H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
0e525780on0.32: nested field-materialization certification landed — the nested unsigned profile now admits end to end (issue remains open).__cellscript_memcpy_fixed, arguments src/destination/length in a0/a1/a2). The finite Cell-field certification previously rejected every such call: only the membership helper was admitted. Two pieces now close that gap: (1) the copy helper itself is frame-certified — owned instruction range with internal copy loops allowed, no calls, no writes to its return or stack registers, at least one return, no escaping or incoming interior flow; (2) every call site proves its destination: within the pre-call window, the only definition of the destination register is a stack-relative offset inside the caller's frame, the length is a positive constant ≤ 512 bytes, the destination range is disjoint from checked Cell data and the received Cell pointer, and no incoming control flow enters the argument window. Anything else fails closed with the existing V2420 boundary.nested_public_layouts_admit_end_to_end_with_certified_frame_copies: the three-declaration fixture (resource + nested Inner + Outer with a nested member) compiles at O0–O3 and now passes the complete finite external codec — profilepolicy-unit-scalars-nested-unsigned-cell-v1, Outer width 16 — and a same-width nominal substitute yields a distinct codec identity. Machine-word mutations at every certified copy site (destination offset escaping the frame, unbounded length) pass structural checking and reject exactly at the codec boundary.open_handle_policy9,policy_artifact_checker73,frozen_interface38 — all single-threaded; clippy--all-targetsclean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).The general codec obligations are now down to one precisely-bounded piece: public constant-value proofs (types proven, values not; needs its own bounded evaluation contract). After that: H2 nominal handles and CKB-VM enforcement, builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
f6bfb150on0.32: public constant-value proofs landed — the last general codec obligation piece (issue remains open).bind_typed_semanticsemits an optionalcellscript-constant-value-catalog-v1into typed semantics. Each exported constant whose initializer is closed over the bounded grammar — u64/bool literals and checked add/sub/mul/div/rem/and/or/xor/shl/shr over u64 — records its canonical type, folded value and the expression tree (src/typed_semantics/constants.rs). Initializers outside the grammar (references, strings, bytes, wider widths) are omitted and stay fail-closed.constant_values::check_constant_valuesindependently re-evaluates every recorded expression under depth-16 / step-1024 budgets with checked operations (overflow, zero divisors, undefined shifts, unknown operators reject), compares against the recorded value, enforces identity/spelling bounds and catalog-exactness (proven set equals the declared public set, no duplicates, no undeclared entries). The finite external codec admits proven constants into its record (declaration identity, type, value) and the policy receipt drops its blanket constant rejection: a3 * 7constant now passes the complete finite codec and receipt with proven value 21, while a String constant still fails closed — now one layer earlier, at the origin check, verified infrozen_interface.constant_value_catalog_rejects_rebound_mutations, O0–O3): recorded-value drift, expression tampering, division by zero, a 20-deep tree exceeding the depth budget (whose leaves still evaluate to the recorded value), catalog removal and undeclared entries all reject after hash rebinding.open_handle_policy9,policy_artifact_checker74,frozen_interface38,interface_projection9,interface_inspection10,policy_imports7 — all single-threaded; clippy clean on both crates; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).With this, the general codec/builder obligations named in the scoping comments are complete: nested unsigned public layouts with certified frame-copy materialization, and proven constant values, both end to end under
policy-unit-scalars-nested-unsigned-cell-v1. H1 is done. Remaining before #28 can close: H2 (nominal ScriptHandle/VerifierHandle DSL surface and CKB-VM runtime enforcement — the multi-session engineering layer), generated-builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.a19q3 commentedon Oct 10, 2026
Implementation progress at
f85230feon0.32: the H2 layer began with its mandated first slice — the frozen interface-parameter decision plus fail-closed reservation of the handle class spellings (issue remains open).ScriptHandle<I>/VerifierHandle<I>source syntax is admitted. The design record now carries the frozen H2 first-slice decisions: (1)Idenotes the resolver-owned checked defining-module interface identity and will be spelled only through an explicit resolver-bound marker introduced with the parser slice — never a local struct, raw Script, package name, producer flag or ambiguous unqualified marker; (2) the bounded encoding is the existing 656-byte selection and 32-member authorization-set identity, with no new runtime budgets; (3)ScriptHandleandVerifierHandleare distinct nominal classes whose Lock/Type/spawned-verifier role lives in the policy header, with no coercion or retyping move from Script/Hash/bytes and construction only through versioned helpers mirroring the exact-handle operand-flow jail; (4) the expected authorization root comes from committed current-Script code/args or a controlled state transition, never the same witness carrying the membership proof, and membership/selected-dependency checks execute on CKB-VM before any on-chain claim.ScriptHandlerejects at inspection). Tests: four source-level rejection shapes at O0–O3 intests/exact_script_handles.rs, plus the rebound catalog mutation intests/policy_artifact_checker.rs.exact_script_handles5,policy_artifact_checker(spot + full catalog tests),frozen_interface38 — all single-threaded; clippy clean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).Next H2 slices in order: the parser/resolver marker grammar for
I(imported module interface designation), then the nominal handle types with bounded encoding and no construction (type surface only), then versioned construction helpers over the checked admission boundary, then the CKB-VM membership/selected-dependency runtime checks with measured budgets, each with parser/type/lowering/metadata/checker/LSP/formatter agreement. The independent security reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.a19q3 commentedon Oct 10, 2026
Implementation progress at
d7fc4a6eon0.32: the H2 marker slice landed — the interface parameterIbinds to imported modules per the frozen decisions (issue remains open).ScriptHandle<owner::module>/VerifierHandle<owner::module>).validate_open_handle_typeadmits exactly one argument that is neither a primitive, a value-type spelling, a locally visible type, the current module, a nested application nor an unloaded path — the project resolver must have the designated module loaded. Bare spellings and user declarations of the two class names keep the reserved-surface rejection.ScriptHandle<qual::types>argument in the instantiation, and passes independent inspection plus symbolic declaration validation.policy_imports10 (three new tests: positive binding, six-shape rejection matrix, designation mutation),exact_script_handles5 (reservation matrix updated to the new structured messages),interface_projection9,interface_inspection10,policy_artifact_checker75,frozen_interface38 — all single-threaded; clippy clean on both crates; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).Next H2 slices: bounded runtime encoding and value construction through versioned helpers over the checked admission boundary, then CKB-VM membership/selected-dependency enforcement with measured budgets. The independent security reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
fb7a02c2on0.32: the H2 bounded-encoding slice landed — open-handle values now cross the action witness ABI with their frozen 656-byte width (issue remains open).witnessparameter ofScriptHandle<I>/VerifierHandle<I>type is the entry-ABI position for the bounded encoding. The 656-byte width is now carried consistently through every layer that previously classified the handle as schema-dynamic: the producer's string-based and IR-based width tables, the entry witness payload layout (fixed-byte pointer/length ABI instead of a 4-byte schema cursor), the action parameter metadata (fixed_byte_len: 656), and — independently — the checker's policy-ABI projection and adapter-frame expectation. Producer and checker now derive the same compact policy adapter frame for a 656-byte handle parameter; the earlier divergence (producer fallback frame 5376 vs checker 688) is closed at the root. Universal symbolic verification recognizes the handle leaf (single module designation, copy/drop only), and the value-ability prescan validates designations on entry parameters like every other handle leaf.open_handle_witness_parameters_carry_the_bounded_encoding— the three-module fixture compiles at O0–O3 with the handle witness parameter, metadata records the 656-byte fixed encoding, independent inspection and symbolic validation pass, and an input-sourced handle parameter rejects.open_handle_policy9,policy_imports11,exact_script_handles5,policy_artifact_checker75,frozen_interface38,interface_projection9 — all single-threaded; clippy clean on both crates; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).Next H2 slices: the versioned construction/consumption helper over the checked admission boundary, then CKB-VM membership/selected-dependency enforcement with measured cycle/stack/witness budgets. The independent security reviewer still needs maintainer assignment — that unassigned human review remains the final closure gate; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Scoping result for the next H2 slice — the versioned consumption helper (issue remains open).
The slice's implementation contract is now frozen in the design record (commit
da187ad2, "H2 versioned helper specification"): the DSL surfaceckb::require_cell_dep_open_script_handle(dep: CellDepView, handle: ScriptHandle<I>, expected_root: Hash)(plus the spawned-verifier variant), the complete offset map of the 656-byte selection wire (header at 8 with member_count at 11, member at 196 with complete_script at 316, canonical index at 488, five sibling hashes at 496), and the three on-chain steps — structural validation, full Merkle membership recomputation over__ckb_hash_blake2b_varwith the frozen domain strings, and the selected-dependency Script-hash comparison against the dep's lock/type hash — plus the exact layer checklist (typecheck arm, lowering target, calls.rs loading, the runtime helper generator reusing the exact-handle frame skeleton, checker jail exemption with signature checks, a new runtime error code, LSP, and O0–O3 CKB-VM positives/negatives).Two implementation facts discovered while scoping: the on-chain runtime already provides
__ckb_hash_blake2b_var, so full membership verification needs no new hash primitive; and the exact-handle requirement helper is a directly reusable frame/syscall skeleton. The remaining work is a hand-written RISC-V helper generator (~200–300 lines of emitters with frame-resident hash staging buffers) plus the four-layer pipeline and CKB-VM evidence. That hand-written assembly is exactly the class of change the repository warns must not be rushed — a single wrong register or label silently changes on-chain code — so it is deliberately not attempted in the tail of this session; it is the first item of the next session, with the specification removing all design ambiguity.Session totals for #28 so far: 13 commits (H1 complete, H2 decisions/markers/encoding plus this specification), 14 progress comments. Remaining after the helper: CKB-VM enforcement evidence with measured budgets, builder/ProtocolBundle byte parity, final unified gates, and the independent security review — the reviewer still needs maintainer assignment; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
2d49a058on0.32: the versioned consumption helper landed through the complete pipeline — with one tracked byte-level anomaly in the generated assembly (issue remains open).Landed per the frozen specification (da187ad):
ckb::require_cell_dep_open_script_handle/..._open_verifier_handlebeside the exact handles (three-argument shape, class-matched handle, compile-time Hash root); lowering to versioned__ckb_targets requiring a constant expected root; calls.rs argument loading for the 656-byte fixed-byte selection and 32-byte root; the runtime helper generator implementing structural validation (magic, class, role, active status, index < member_count), five-level Merkle membership recomputation over__ckb_hash_blake2b_varwith the frozen domain strings, and the selected-dependency binding of the member's complete Script hash (offset 324) against the dep's lock/type or data hash by the header role; the checker operand-flow jail now admits exactly these two targets with pinned signatures (versioned runtime contract, unit return, constant root commitment); runtime error code 85open-handle-invalidwith registry, slug, description and hint; LSP completion entries; and selection-wire layout constants shared by tests.#[ignore]-marked test (open_script_handle_requirement_executes_and_rejects_substitutions) with the full positive/negative matrix ready; the ignore note names the anomaly so the next session resumes exactly here.policy_imports11,exact_script_handles5 (+1 tracked ignored), clippy clean on both crates, fmt clean, commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).The independent security reviewer still needs maintainer assignment — that unassigned human review remains the final closure gate; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
0b5b31f7on0.32: the tracked byte-level anomaly is found and fixed — the open-handle requirement helper now passes its complete CKB-VM acceptance matrix (issue remains open).Root causes (three real defects in the generated helper, all caught by the VM evidence):
CSOHPv1\0magic) at selection offset 8, so class/role/mode/member_count sit at absolute 16/17/18/19 — the original constants used the in-header positions. The same nesting applies to the member block (CSOHMv1\0), so its status byte sits at 204, not 196. The frozen specification's offset table and the shared layout constants are corrected.__cellscript_memcpy_fixedargument direction: the runtime copies a0→a1, and every staging copy in the Merkle recomputation (leaf member, both sibling orders per level, policy header and tree root) had source and destination swapped — hashing frame garbage. All call sites now pass source in a0 and destination in a1.Acceptance now green in
open_script_handle_requirement_executes_and_rejects_substitutions(unignored), at O0–O3: the admitted selection verifies (exit 0); a substituted expected root, byte substitutions at nine selection offsets (selection magic, class, count, member magic, complete Script hash, canonical index, first sibling, last byte) and a substituted CellDep Script all fail closed withopen-handle-invalid(85).Validation: compiler lib 997, checker lib 42,
policy_imports11,policy_artifact_checker75,frozen_interface38,exact_script_handles6 (matrix included); clippy clean; fmt clean; commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).Remaining before #28 closes: measured cycle/stack/witness budgets for the helper, generated-builder/ProtocolBundle byte parity, the expected-root binding to committed current-Script code/args (frozen decision #4's follow-up), final unified gates, and the independent security review — the reviewer still needs maintainer assignment with a time window; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Implementation progress at
ca140501on0.32: the helper's measured budgets landed and the from-args root binding advanced through its complete pipeline (issue remains open).Measured budgets (frozen as test assertions, so regressions fail the suite):
The numbers are recorded in the design record beside the acceptance matrix.
From-args root binding (frozen decision #4: the expected authorization root comes from the current Script's committed args, never from the witness):
ckb::require_cell_dep_open_script_handle_from_args(dep, handle)and the verifier variant are implemented through every layer — typecheck arms (two-argument shape, class-matched handle), lowering to versioned targets, calls.rs loading, a runtime generator variant that LOAD_SCRIPTs the current Script, requires its serialized args field to be exactly 32 bytes and stages the committed bytes as the expected root, checker jail admission with pinned two-operand signatures, and LSP entries.open-handle-invalidbefore the membership recomputation. Rather than ship an unexplained success path, the complete matrix (committed-root positive, substituted root, 31/33-byte args, seven selection substitutions) is preserved as an ignore-marked test with this context, and the constant-root variant remains the fully admitted surface. The defect is the next session's first item; the bisect state (verified prologue, failing between the structural checks and the leaf hash) is documented in the design record.Validation: compiler lib 997, checker lib 42,
policy_imports11,exact_script_handles6 (+1 tracked ignored), clippy clean, fmt clean, commit gate passed. Commit unsigned (--no-gpg-sign, same GPG agent constraint).The independent security reviewer still needs maintainer assignment with a time window — the final closure gate; the 2026-10-03 waiver does not cover this contract.
a19q3 commentedon Oct 10, 2026
Debugging record for the from-args fail-closed path (no new commit; working tree restored to
ca140501and re-gated).The binary search narrowed further, and one earlier hypothesis was eliminated with a live experiment:
enabledpath is live.ld t3(beqz a1 / length equality) plus the magic loop's first comparison — all of which emit the same instruction shapes that pass in the constant-root variant. A metadata-only dump cannot distinguish further, and compile-time probes (inlineli a0,N; ret) are rejected by the verifier's stack-delta and failure-record contracts.Recommended next step (recorded for the next session): reproduce the fixture in
ckb-debuggerand single-step the helper from the LOAD_SCRIPT return — the failing branch target will be visible directly, which the compile-time bisect cannot show.State: constant-root variant fully green (76k cycles, full substitution matrix), budgets recorded, from-args pipeline complete through every layer with the prologue live-verified; the one unresolved branch keeps its ignore-marked test with the full matrix. Compiler lib 997 / checker 42 / exact_script_handles 6+1 / commit gate re-verified on the restored tree.
The independent security reviewer still needs maintainer assignment with a time window — the final closure gate for #28; the 2026-10-03 waiver does not cover this contract.