Repository navigation
[Architecture][Builder] Add an artifact-only multi-Script ProtocolBundle #9
Description
Summary
Add an artifact-only ProtocolBundle that composes multiple independently compiled CellScript artifacts into one CKB transaction plan, validates their combined builder contracts, runs every relevant Script Group against the same candidate transaction, and emits one evidence bundle.
This is intentionally an off-chain composition layer first. It must not add an ELF linker, merge executable business logic, or imply runtime calls between CKB Scripts.
Problem
CellScript currently has strong per-entry artifacts:
- typed metadata and ProofPlan;
- entry witness ABI;
- generated builder contracts;
- deployment and resource-identity manifests;
cellc tx validate;- CKB-VM and stateful evidence.
However, realistic protocols often require several independent Lock and Type Scripts to accept the same atomic transaction. Today, applications must manually reconcile their input/output indexes, witnesses, CellDeps, HeaderDeps, capacities, identity policies, and dry-run evidence.
The compiler documentation correctly states that each CKB Script remains an independent artifact. The missing feature is not runtime linkage; it is a typed, verifiable composition object above those artifacts.
Argent's ArtifactBundle and unified transaction context are useful product-design signals. CellScript needs a CKB-native version based on Script Groups, Molecule witnesses, exact deployments, occupied capacity, and per-artifact evidence.
Target architecture
flowchart TB
A1["Artifact A<br/>metadata + ELF + deployment"] --> PB["ProtocolBundle resolver"]
A2["Artifact B<br/>metadata + ELF + deployment"] --> PB
A3["Artifact C<br/>metadata + ELF + deployment"] --> PB
PB --> MERGE["Merge transaction roles and constraints"]
MERGE --> CONFLICT{"Index / witness / identity<br/>conflicts?"}
CONFLICT -- "yes" --> FAIL["Fail before signing"]
CONFLICT -- "no" --> TX["One candidate CKB transaction"]
TX --> VM1["Run Script Group A"]
TX --> VM2["Run Script Group B"]
TX --> VM3["Run Script Group C"]
VM1 --> EVID["Combined evidence bundle"]
VM2 --> EVID
VM3 --> EVID
The bundle is valid only if every selected artifact accepts the exact same serialized transaction.
Proposed bundle contract
A canonical cellscript-protocol-bundle-v1 should include:
Artifact identity
For every participating artifact:
- package coordinate and
Cell.lockidentity; - entry/action/lock identity;
- deployable ELF hash;
- metadata, typed-semantics, lowering-record, and source-map hashes;
- public interface and
interface_hash; - target/profile/VM/ABI versions;
- deployment identity and network;
- code CellDep identity;
- selected Script role: Lock, Type, or spawned verifier.
Transaction-role bindings
- named inputs, outputs, CellDeps, HeaderDeps, and witnesses;
- global and Script Group-relative indexes;
- expected Lock and Type Script identities;
- resource/schema identities;
- entry witness ABI placement;
- required output construction and input consumption;
- capacity, fee, change, and signature policies;
- builder-assumption evidence requirements.
Composition result
- deterministic merged transaction plan;
- explicit conflict report;
- resolved indexes and witness ownership;
- per-Script-Group dry-run/CKB-VM result;
- serialized transaction hash and size;
- occupied-capacity report;
- aggregate cycle report without erasing per-group cycles;
- complete evidence identities.
Conflict classes
The resolver must reject rather than guess:
| Conflict | Example |
|---|---|
| input ownership | two roles claim exclusive control of the same input |
| output placement | two artifacts require different values at the same output index |
| witness ABI | incompatible payloads claim the same WitnessArgs field |
| CellDep ordering | positional ABI assumptions disagree |
| Script identity | one role expects data hash X while another expects type hash Y |
| resource identity | incompatible Type ID or logical identity requirements |
| capacity | one artifact's floor exceeds the selected output capacity |
| fee/change | two manifests assign the same capacity remainder differently |
| network/deployment | artifacts resolve against different CKB networks |
| profile/version | incompatible VM, source encoding, or ABI profiles |
| signature policy | conflicting sighash or witness-lock ownership |
A bundle may share a resource only when the participating artifact contracts explicitly permit compatible observation.
CLI shape to design
The exact command names require an accepted design, but the workflow should support:
protocol bundle create -> canonical unresolved bundle
protocol bundle resolve -> concrete live Cells and deployment facts
protocol bundle check -> structural + identity + builder validation
protocol bundle dry-run -> run every relevant Script Group
protocol bundle submit -> dry-run first, then delegate signing/submission
protocol bundle inspect -> human and JSON evidence report
The runtime adapter remains responsible for live-cell resolution, signing, submission, and RPC interaction. The compiler and bundle checker must remain deterministic and usable offline with supplied facts.
Implementation phases
Phase 0 — format and threat model
- define the canonical bundle schema and hash;
- enumerate trust boundaries and conflict classes;
- define artifact admission and exact deployment requirements;
- specify global versus group-relative indexes;
- define shared versus exclusive role ownership;
- specify evidence tiers and failure behavior.
Phase 1 — offline composition
- ingest existing builder manifests and metadata;
- verify all artifact identities with the standalone checker;
- merge role/index/witness/CellDep constraints;
- reject all unresolved conflicts;
- emit a deterministic transaction skeleton and evidence template.
No new CellScript syntax is required in this phase.
Phase 2 — runtime adapter integration
- resolve live Cells and named deployments;
- compute occupied capacity, fees, change, and transaction size;
- build one concrete transaction;
- dry-run every selected Script Group;
- return per-artifact errors with source and role attribution.
Phase 3 — generated SDK and ecosystem closure
- generate a typed TypeScript/Rust-facing bundle API;
- support resumable signing without exposing private keys;
- emit one audit bundle that preserves each artifact's evidence level;
- integrate VS Code and Registry discovery after the format is stable.
End-to-end example
A useful acceptance fixture should contain at least three independent artifacts:
flowchart LR
ORDER_IN["Order input<br/>Order Type Script"] --> TX["Atomic settlement transaction"]
TOKEN_IN["Token input<br/>Token Type Script"] --> TX
AUTH_IN["Authorization input<br/>Lock Script"] --> TX
TX --> ORDER_OUT["Updated/closed order"]
TX --> TOKEN_OUT["Transferred token"]
TX --> CHANGE["Capacity change"]
ORDER["Order verifier"] -. "accepts same tx" .-> TX
TOKEN["Token verifier"] -. "accepts same tx" .-> TX
AUTH["Authorization verifier"] -. "accepts same tx" .-> TX
The fixture must demonstrate both a successful composition and adversarial conflicts in witness placement, Script identity, output indexing, capacity, and deployment network.
Completion criteria
- A versioned canonical ProtocolBundle schema and hash are documented.
- Multiple independently checked artifacts can be composed without recompilation.
- The resolver detects every documented conflict class deterministically.
- One concrete transaction is validated against every participating artifact.
- Every selected Script Group is dry-run against byte-identical transaction bytes.
- Per-artifact and combined evidence levels remain distinct.
- The runtime adapter, not generated code, owns RPC/signing/submission.
- A three-artifact positive fixture and adversarial matrix pass.
- Bundle validation is available in JSON and human-readable forms.
- No claim of ELF linking or cross-Script runtime calls is introduced.
- Package, website, Registry, docs, and generated SDK surfaces agree on the schema version.
Non-goals
- an ELF linker;
- in-VM calls between independent CKB Scripts;
- merging multiple artifacts into one trust boundary;
- accepting Registry metadata as on-chain identity proof;
- automatic conflict resolution;
- hiding fee, capacity, signature, or change policies;
- source-level cross-Script role syntax in the first phase.
Relationship to other work
- [Candidate][Consensus runtime] Implement executable bounded Cell-group consumption #7 and [Candidate][Consensus runtime] Implement executable bounded output-plan correspondence #8 define bounded per-group lifecycle operations; ProtocolBundle must be able to carry their builder/evidence contracts once they are executable.
- [Toolchain][CKB environment][P0] Make transitive dependency selection chain-identity-safe #17, then [Toolchain][Workspace][P1] Replace member-loop builds and synthetic workspace locks with a canonical graph #15/[Toolchain][Resolver][P1] Define and enforce package instance, version, source, and feature unification #16/[Toolchain][Compatibility][P1] Enforce package-declared CellScript compiler requirements #18, must close environment, workspace, package-instance, and compiler-compatibility semantics before production bundle resolution depends on them.
- [Toolchain][Introspection] Expose a stable package resolve graph and build-unit plan #19 should expose the corrected resolve graph and build-unit plan; ProtocolBundle remains a distinct artifact/evidence graph.
- [Toolchain][Upgrade] Add a transactional package, interface, and deployment upgrade plan #20 should consume bundle impact during transactional upgrades.
- A later source-level typed role system should build on this artifact boundary rather than inventing a parallel transaction builder.
Activity
a19q3 commentedon Aug 27, 2026
Research update: define ProtocolBundle as an evidence closure, not another package format
Comment audit
There were no prior comments on this issue at the time of review.
The relevant Argent work—portable artifacts/builder in PR #4, ArtifactBundle in PR #8, unified TxContext in PR #20, and artifact validation in PR #21—has little or no substantive review discussion. It should therefore be treated as product-design evidence, not a validated security specification.
Existing CellScript boundary
The audit confirms that CellScript is not missing the per-artifact foundations. It already has:
The missing abstraction is the closure over several already-verified artifacts.
That distinction matters because ProtocolBundle should not re-resolve source packages, recompile them, or silently change their target/profile. It should consume immutable artifact descriptors and exact deployment facts.
Two graphs must remain separate
ProtocolBundle needs two linked graphs:
The package resolve/build graph proposed in #19 can help locate and build artifacts, but it is not the ProtocolBundle evidence graph. Likewise the workspace correction in #15 must not turn Cell.lock into a bundle manifest.
Merge semantics need a field taxonomy
A generic JSON merge is unsafe. Every bundle field should have one of these merge classes:
Conflicts must name both producing artifacts and source obligations. First-writer-wins is not acceptable.
Same transaction bytes is the key invariant
Every CKB-VM run in the bundle must receive the exact same serialized RawTransaction and witnesses. It is insufficient to run each artifact against a separately synthesized transaction that merely has equivalent roles.
The combined evidence should bind:
CKB consensus executes all Script Groups independently. ProtocolBundle demonstrates that the candidate transaction satisfied each selected artifact; it does not create runtime calls between them.
Recommended v1
Start with an artifact-only JSON schema and CLI library API:
Do not add source syntax in v1. #10 can later compile typed role declarations into this same schema.
Acceptance additions
Dependency refinement
Schema design can proceed in parallel, but production implementation should follow this order:
Conclusion
ProtocolBundle is a high-value tooling feature and can begin without consensus-language changes. Its security property is evidence closure over immutable artifacts and one exact transaction, not “multi-contract linking.” This is the most useful part of Argent's ArtifactBundle direction to adopt, while keeping CKB Script Groups and CellDep/deployment identity explicit.
a19q3 commentedon Sep 11, 2026
Completed for the bounded 0.30 artifact-only scope. The implementation spans offline deterministic conflict checking (
c75cb113), builder contracts, exact CKB transaction materialization, live input/dependency checks, node dry-run/signing gates, typed clients, Registry/website surfaces, and the four-artifact ProtocolBundle business anchor (d6e49cf7,a2ee77aa). The bundle binds independently checked artifacts to one byte-identical transaction and does not introduce a source-language transaction DSL. The product capability ledger recordsremaining_work=[]andclose-after-mergeatcdc5b53c. No TAC or release workflow was invoked.