Skip to content

[Language/ABI] Bind runtime Script values to verified package interfaces #11

Closed

Description

@a19q3

Summary

Connect CellScript's runtime Script/ScriptRef values with its canonical package-interface and deployment identities.

The desired abstraction is a typed handle such as ScriptHandle<I> or VerifierHandle<I>: a runtime-selected Lock or Type Script whose implementation is proven to satisfy a declared interface contract, while remaining an ordinary non-Cell value that grants no lifecycle authority by itself.

This issue supplies the identity foundation required by the open foreign roles in #10.

Current gap

CellScript already has two strong but disconnected layers:

Runtime Script identity

The language can construct and inspect CKB Scripts:

  • Script and ScriptRef;
  • code_hash, hash_type, and args;
  • exact Lock/Type Script matching;
  • code/data CellDep identities;
  • deployment records.

Compile-time package identity

The compiler emits:

  • cellscript-package-interface-v2;
  • canonical interface_hash;
  • six-dimensional compatibility reports;
  • typed-semantics and lowering identities;
  • generated-builder and deployment contracts;
  • Registry admission checks.

A raw runtime Script does not currently carry or prove a package interface. Conversely, an interface_hash in Registry metadata does not prove which Script bytes are executing in a transaction.

flowchart LR
    RS["Runtime Script<br/>code_hash + hash_type + args"] -. "missing verified link" .- PI["Package interface<br/>interface_hash + schema + effects"]
    ART["Checked artifact"] --> PI
    DEP["Deployment identity"] --> RS
Loading

Required security property

A consumer accepting ScriptHandle<I> must be able to answer all three questions independently:

  1. What Script is present in the transaction?
  2. What exact checked artifact or allowed upgrade line does that Script resolve to?
  3. Why does that artifact satisfy interface contract I?

The answer must not depend on a mutable Registry lookup during consensus execution.

Handle classes

The design should distinguish at least:

Exact artifact handle

Binds one exact checked artifact:

Script identity
+ deployable ELF/data hash
+ typed artifact identity
+ exact interface_hash
+ target/profile/ABI identity

This is the simplest and safest first version.

Deployment-line handle

Binds an upgradeable deployment identity, such as a Type ID code Cell, plus an explicit compatibility/upgrade policy.

The verifier or builder must resolve the actual code bytes used by the transaction and prove that the selected deployment belongs to the allowed line. A Type-hash Script reference alone must not be treated as proof that every future code Cell remains interface-compatible.

Compatible open handle

Accepts one of several implementations satisfying a minimum interface or schema/effect contract.

This requires a versioned compatibility policy and a consensus-verifiable binding from the selected Script to a checked interface receipt. It must not be implemented as “look up the code hash in the Registry and trust the response.”

Candidate receipt model

The exact encoding requires an RFC. A receipt could bind:

receipt_version
interface_hash
typed_semantics_hash
deployable_artifact_hash
target_profile_hash
runtime_abi_hash
deployment_identity
upgrade_policy
flowchart TB
    SRC["Package source"] --> COMP["CellScript compiler"]
    COMP --> IFACE["Canonical interface hash"]
    COMP --> ART["ELF + typed/lowering records"]
    ART --> CHECK["Independent checker"]
    CHECK --> RECEIPT["Verified interface receipt"]
    RECEIPT --> DEPLOY["Deployment record / code Cell"]
    DEPLOY --> HANDLE["Runtime ScriptHandle<I>"]
    HANDLE --> ROLE["Open or closed transaction role"]
Loading

For data-hash code deployment, exact Script code identity can anchor the artifact strongly. For Type-hash/upgradeable deployment, the RFC must define how the concrete code Cell and its upgrade policy are bound and revalidated.

Type-system requirements

A handle type must:

  • be an ordinary fixed-width value, not a Cell-backed resource;
  • carry no implicit create, consume, replace, or authorization capability;
  • encode Lock versus Type Script role explicitly;
  • distinguish exact from compatible/upgradeable policies;
  • preserve target, VM, source-encoding, witness ABI, and Script hash-type identities;
  • prevent implicit conversion from raw Script or Hash;
  • require explicit checked construction;
  • be serializable only through a versioned canonical representation;
  • expose safe equality and exact-preservation operations;
  • remain separate from a peer Cell's decoded state.

The open-role system may state that an output uses the same implementation as an input, but that relation must compare the complete accepted handle identity, not only a code hash or interface name.

Trust boundaries

Evidence What it proves What it does not prove
raw Script fields transaction carries this Script structure the code satisfies interface I
Registry interface record a published package claims this interface the transaction executes that artifact
independent checker artifact records and ELF agree structurally deployment/live-chain identity
deployment record expected artifact was recorded at an outpoint the current transaction resolved the same bytes unless checked
code/data hash check exact code bytes are selected source-level intent unless bound to checked artifact
Type ID unique/upgradable code-cell identity upgrade compatibility
CKB-VM dry-run selected Scripts accept this exact transaction general source equivalence or future upgrades

Implementation phases

Phase 0 — threat model and exact handle

  • enumerate substitution, downgrade, stale-deployment, Registry-spoofing, and type-hash upgrade attacks;
  • define an exact artifact receipt and canonical hash;
  • define how the builder and on-chain Script check the selected implementation;
  • keep compatible/open handles out of scope until exact handles are proven.

Phase 1 — exact closed handles

  • add the fixed-width handle/receipt representation;
  • integrate it with public interfaces, deployment manifests, ProtocolBundle, metadata, and tx validate;
  • generate exact Script/data/code identity checks;
  • preserve the handle across declared input/output roles;
  • add independent checker and mutation coverage.

Phase 2 — upgradeable deployment lines

  • define upgrade authorization separately from compatibility;
  • require every selected code version to have a checked receipt;
  • reject stale, yanked, incompatible, or unbound versions according to policy;
  • preserve historical receipt identity in audit evidence.

Phase 3 — compatible open handles

Acceptance matrix

Case Expected
exact checked artifact and exact Script identity pass
same interface name, different interface hash reject
same schema, incompatible effects/ABI reject
valid Registry record but wrong transaction Script reject
exact code hash but receipt for another target/profile reject
Type ID points to unreceipted upgraded code reject
allowed additive upgrade under explicit policy pass only after full receipt verification
compatible interface but state schema mismatch reject
output claims same implementation but changes args/policy reject
removed receipt/Script binding machine block standalone checker rejects

Completion criteria

  • An accepted RFC defines exact, upgradeable, and compatible handle classes.
  • Exact artifact handles ship before compatible open handles.
  • The handle representation is canonical, versioned, fixed-width, and non-linear.
  • Raw Script identity, artifact identity, interface identity, and deployment identity remain separate fields.
  • No Registry lookup is treated as consensus proof.
  • Data-hash and Type-hash deployment paths have explicit, different security contracts.
  • ProtocolBundle and tx validate resolve and verify handles.
  • Typed semantics, ProofPlan, lowering records, standalone checker, and CKB-VM fixtures cover the binding.
  • Negative tests cover substitution, downgrade, stale deployments, wrong profile/ABI, changed args, and unreceipted upgrades.
  • Open cross-Script roles in [Language design] Model typed cross-Script transaction roles without runtime linkage #10 cannot stabilize without this contract.

Non-goals

  • treating interface compatibility as behavioral equivalence;
  • dynamically downloading or executing package metadata on chain;
  • granting Cell lifecycle authority through a handle value;
  • making Registry availability a consensus dependency;
  • hiding upgrade authorization inside compatibility checks;
  • accepting a Type ID as automatic proof of compatible code;
  • generic dynamic dispatch unrelated to CKB Scripts.

Dependencies

References

Activity

  1. a19q3 commented on Aug 27, 2026

    @a19q3
    CollaboratorAuthor

    Research update: Argent's own follow-up document validates the receipt concern

    Comment audit

    There were no prior comments on this issue at the time of review.

    The most important upstream evidence is not the open-ICC feature itself, but Argent's explicit list of unresolved app-linking problems:

    https://github.com/argent-lang/argent/blob/6a627da4abdd53e71fdb71da0f711ccc96424eb6/docs/app-linking-followups.md

    Argent records that its current imported interface fingerprint includes only the actor name, state name, and top-level Sil state fields. It does not include nested layouts, Argent source types, state expansions, or the actor handle, and artifact verification does not recompute exported fingerprints. The proposed follow-up is a complete receipt binding app, actor, source-state interface, all used layouts, and the exact actor handle, recomputed during verification.

    That is strong confirmation that CellScript should not stabilize an interface-bound Script handle around a shallow or producer-supplied fingerprint.

    What CellScript already has

    CellScript starts from a stronger per-package base:

    • canonical public interface;
    • nested fields/variants/layout identity;
    • callable ABI and witness ABI;
    • effects and lifecycle capabilities;
    • builder and deployment dimensions;
    • target/profile and compatibility identity;
    • typed semantics, verified lowering, source map, and independent checker.

    The gap is narrower but still security-critical: there is no verified link from a runtime CKB Script to the exact checked artifact and interface record.

    A complete receipt must be recomputed from the exported artifact boundary, not copied from Registry metadata or trusted from the importing package.

    Exact handle verification flow

    For the first exact handle, the RFC should specify this complete chain:

    1. Match the runtime Script's code_hash, hash_type, and args policy.
    2. Resolve the actual code CellDep under CKB's hash_type rules.
    3. Hash or otherwise identify the actual executable bytes selected by the transaction.
    4. Verify the artifact's lowering/source-map/metadata boundary independently.
    5. Recompute the canonical public interface and receipt identity from the verified records.
    6. Compare the recomputed receipt with the handle's exact requirement.
    7. Bind target profile, VM ABI, witness ABI, source codec, and deployment identity.
    8. Only then expose ScriptHandle as checked.

    The runtime value itself should remain non-authoritative: it does not grant consume/create/replace capabilities and does not prove peer behavior.

    Data-hash and Type-hash are different security contracts

    The official CKB transaction specification explains that code_hash/hash_type locates code through CellDeps:

    https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md

    For a data-hash deployment, exact code bytes can be bound directly.

    For a Type-hash deployment, the Script identifies a code Cell by its Type Script hash. That supports code-cell replacement/upgrades, but it does not prove that the currently selected code bytes remain interface-compatible. An exact handle must therefore bind the concrete code bytes used in the current transaction, while an upgrade-line handle additionally needs:

    • immutable lineage identity;
    • authorized upgrade policy;
    • a receipt for every admitted concrete artifact;
    • downgrade/stale receipt rules;
    • a way for the verifier/bundle to prove the selected concrete version.

    TYPE_ID or Type hash alone is not an interface receipt.

    Where can the receipt commitment live?

    The RFC should compare explicit trust models rather than assuming one:

    • Artifact-embedded commitment: the code/data bytes include a canonical receipt hash. Exact data-hash deployment is simple, but upgradeable code still needs new receipt validation.
    • Companion receipt CellDep: a versioned, independently governed Type Script binds artifact hash plus interface receipt. The verifier must bind the exact receipt Cell and its authorization policy.
    • Compile-time allowlist/commitment root: the consumer artifact commits to admitted exact receipts. This is consensus-simple but requires consumer upgrades to add implementations.
    • ProtocolBundle-only receipt: useful for off-chain closed composition, but insufficient if the current Script must enforce runtime-selected implementation identity on chain.

    The issue should not promise compatible open handles until one model has an end-to-end CKB threat analysis.

    Receipt content

    At minimum, preserve distinct fields for:

    • receipt schema/profile;
    • package/interface hash;
    • typed-semantics hash;
    • deployable artifact hash;
    • verified lowering and source-map hashes;
    • target/profile/VM/witness/source-codec identities;
    • Script role and full Script identity policy;
    • deployment/code CellDep identity;
    • state schema/layout identities used by I;
    • effects/capabilities;
    • exact versus upgrade-line policy.

    Do not replace this with one opaque “compatible” bit. Interface compatibility is not behavioral equivalence.

    Independent verification requirement

    Argent's follow-up specifically calls for recomputing exported receipts and comparing imports with verified exports. CellScript should require the same:

    • producer emits a draft receipt;
    • independent checker recomputes all fields it owns from canonical artifact records;
    • ProtocolBundle compares a consumer requirement to the verified export;
    • duplicate/conflicting receipt IDs fail;
    • Registry storage is an availability/discovery layer, not the root of trust;
    • on-chain enforcement uses an immutable commitment model, not a live Registry lookup.

    Acceptance additions

    • Nested state layout changes while the top-level field names remain unchanged: reject.
    • Same interface hash text supplied by producer but recomputation differs: reject.
    • Same source interface under a different target/witness ABI: reject.
    • Same code_hash with changed args policy: reject.
    • Type-hash code Cell resolves to an unreceipted new binary: reject.
    • Receipt exists but is for another code CellDep/outpoint/data hash: reject.
    • Duplicate receipt IDs for different artifacts: reject.
    • Runtime app/package name normalization collision: reject exact identity collision, echoing Argent's documented problem.
    • Imported receipt references an export not present in ProtocolBundle: reject.
    • Checker block that binds executable bytes to receipt is removed: independent mutation failure.

    Relationship to the new toolchain issues

    Conclusion

    The issue is well-founded and should start with exact artifact handles only. Argent's own app-linking follow-up is a useful negative design result: a receipt that omits nested layouts, source type identity, exact runtime handle, or independent recomputation is not a safe interface binding.

  2. a19q3 commented on Sep 11, 2026

    @a19q3
    CollaboratorAuthor

    Completed for the exact fixed-width 0.30 handle scope. Exact artifact receipts and CSHDLv1 values landed in a9311bdb; source/runtime CKB checks in 130f7078; pre-signing validation in 019d1c05; and exact-version Type-hash deployment-line admission/liveness/runtime evidence in e5dbf3ec through 6d768372. Generic compatible-open Script/verifier handles are explicitly split into post-v1 issue #28, with open roles in #29. Ledger/docs record remaining_work=[] at cdc5b53c. No TAC or release workflow was invoked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions