Skip to content

Commit afe82c6

Browse files
committed
Add verified LS-IDL registry workflow
1 parent 89a4206 commit afe82c6

40 files changed

Lines changed: 2083 additions & 20 deletions

‎CHANGELOG.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## Unreleased
44

5+
- Add first-class LS-IDL publication and discovery for CKB Lock Scripts.
6+
`cellc artifact ls-idl` validates the bounded 0.1 schema, appends
7+
`SHA-256(raw idl.json)` to an executable, generates a publish-ready bundle,
8+
and fetches byte-exact IDL by deployed Script identity. Registry admission,
9+
both verifier boundaries, immutable object storage, Postgres lookup,
10+
canonical `/v1/ckb/scripts/:code_hash/interfaces/ls-idl` reads, and the
11+
compatibility `/idl/:code_hash` route all enforce the same schema and
12+
executable-suffix contract. Add curated compatibility vectors, a runnable
13+
Rust example, website lookup/detail surfaces, and VS Code validate/bind/fetch
14+
commands. Keep implementation correctness and security review outside this
15+
byte-identity claim.
516
- Ship the 0.24 package and Registry trust closure, informed by Sui Move's
617
package-alt separation of resolution from compilation. Replace permissive
718
custom version checks with standard SemVer; make `Cell.lock` v3 a

‎README.md‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ CKB cycle/capacity estimates.
641641
|---|---|---|
642642
| **CLI** | `cli/` + `main.rs` | `cellc` binary with all subcommands |
643643
| **LSP** | `lsp/` + `lsp/server.rs` | In-process `LspServer` + `tower-lsp` JSON-RPC over stdio (`cellc --lsp`) |
644-
| **VS Code** | `editors/vscode-cellscript/` | Shells out to `cellc` for LSP startup, reports, action-builder generation, and package/registry verification |
644+
| **VS Code** | `editors/vscode-cellscript/` | Shells out to `cellc` for LSP startup, reports, action-builder generation, package/registry verification, and LS-IDL validate/bind/fetch flows |
645645
| **MCP server** | `cellscript-mcp` (separate bin) | Read-only Model Context Protocol JSON-RPC server that exposes compiler reports and explain commands to MCP-aware agents (Claude Code, Cursor, Aider, Codex, etc.) |
646646
| **Formatter** | `fmt/` | Idempotent formatter for `cellc fmt` and LSP |
647647
| **Doc generator** | `docgen/` | HTML/Markdown/JSON docs from AST + metadata |
@@ -809,6 +809,8 @@ Non-CellScript artifact profiles still fail closed.
809809
test-only dependency, and explicit CKB-environment graph
810810
- `examples/scenario_basics` — runnable positive and exact-negative scenarios
811811
under both simulator and CKB-VM, plus a four-file artifact walkthrough
812+
- `examples/registry_ls_idl` — runnable LS-IDL validation, executable binding,
813+
Registry bundle scaffolding, exact-byte fetch, and compatibility vectors
812814
- `cellc info --json` — exposes package metadata for CI and tooling
813815
- `cellc package verify --json` — fails closed when `Cell.toml`, source hash,
814816
dependency resolution, or build identity disagree with `Cell.lock`; run an
@@ -899,6 +901,13 @@ the manual, CI, recovery, and external-wallet path.
899901
`cellscript_source` dependency-resolving; non-CellScript artifact profiles
900902
remain discoverable through explicit artifact commands and fail closed in
901903
package resolution
904+
- Deployable CKB Lock Scripts may attach the versioned
905+
`cellscript-registry-ls-idl-interface-v1` profile. Registry admission binds
906+
`SHA-256` of the exact IDL bytes to the executable's final 32 bytes, and
907+
public reads resolve those bytes by chain-verified Script identity. This is
908+
an interface-identity check, not proof of implementation correctness or a
909+
security audit. See the
910+
[LS-IDL Registry profile](docs/CELLSCRIPT_LS_IDL_REGISTRY_PROFILE.md).
902911
- Git dependencies are explicit remote source fetches; treat them as
903912
review-required inputs, not the registry production path
904913

@@ -951,6 +960,7 @@ the manual, CI, recovery, and external-wallet path.
951960
| `cellc opt-report` | Compare O0..O3 artifact size and constraints status |
952961
| `cellc receipt` / `sign-receipt` / `verify-receipt` | Emit, sign, and verify compile receipts over metadata/artifact hashes |
953962
| `cellc verify-artifact` | Independently check an ELF, metadata, lowering record, and source map; report VM/chain evidence separately; optionally bind a receipt |
963+
| `cellc artifact ls-idl validate\|bind\|fetch\|bundle` | Validate byte-exact LS-IDL, bind its SHA-256 to a CKB executable, resolve it by deployed Script identity, or scaffold a publish-ready Registry bundle |
954964
| `cellc test --backend simulator\|ckb-vm\|all` | Execute fail-closed package scenarios with exact outcomes and evidence tiers (`--no-run` is compile-only) |
955965
| `cellc doc` | Generate API and audit documentation |
956966
| `cellc fmt` | Format `.cell` sources or check formatting |

‎docs/CELLSCRIPT_GATE_POLICY.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ running during locked builds. Registry API checks also validate the complete
3838
`cellscript-registry-profile-catalog-v1` and prove that only CellScript source
3939
profiles are dependency-resolving.
4040

41+
The same Registry matrix covers
42+
`cellscript-registry-ls-idl-interface-v1`: raw ABI schema and size budgets,
43+
SHA-256 binding, executable suffix placement, publish-time rejection cases,
44+
SQL/in-memory Script lookup, byte-preserving canonical and compatibility
45+
responses, ambiguous type-hash rejection, CLI validate/bind/fetch/bundle, and
46+
both compiler-backed and least-privilege verifier outputs. Passing this matrix
47+
does not assert that a Lock Script semantically implements its IDL.
48+
4149
`dev` and `ci` run `cellc fmt --check` against
4250
`examples/language/canonical_style.cell`. The formatter's comma-terminated
4351
field form is the canonical checked-in surface; the parser may continue to
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# LS-IDL Registry Profile
2+
3+
**Status**: CellScript 0.24 protocol and tooling contract
4+
5+
**Profile schema**: `cellscript-registry-ls-idl-interface-v1`
6+
7+
**LS-IDL format version**: `0.1`
8+
9+
This profile lets the CellScript Artifact Registry publish and resolve an
10+
LS-IDL witness interface for a deployed CKB Lock Script. It preserves the
11+
upstream commitment rule exactly:
12+
13+
```text
14+
code Cell data = executable bytes || SHA-256(raw idl.json bytes)
15+
```
16+
17+
The Registry stores the original IDL object bytes in the immutable release
18+
bundle. It never parses and reserialises those bytes on the read path.
19+
20+
## What The Profile Proves
21+
22+
An accepted profile proves all of the following:
23+
24+
- the ABI object is valid JSON within the Registry's size and field budgets;
25+
- the document uses the supported LS-IDL 0.1 schema and witness types;
26+
- the declared digest equals `SHA-256` of the exact ABI object bytes;
27+
- the executable object's final 32 bytes equal that digest;
28+
- the package is a deployable `ckb_executable` with `script_role = "lock"`;
29+
- a lookup result belongs to an active, public, chain-verified deployment on
30+
the requested Registry network.
31+
32+
It does **not** prove that the Lock Script decodes witness data as described,
33+
that every described field is semantically enforced, that a transaction is
34+
valid, or that the Script is secure. Build verification and security review
35+
remain separate evidence.
36+
37+
## Artifact Profile Contract
38+
39+
`profile_contract.interface` is accepted only on deployable CKB executables:
40+
41+
```json
42+
{
43+
"schema": "cellscript-registry-ls-idl-interface-v1",
44+
"format": "ls-idl",
45+
"format_version": "0.1",
46+
"object_role": "abi",
47+
"content_type": "application/vnd.ckb.ls-idl+json",
48+
"encoding": "linear-le-v0",
49+
"commitment": {
50+
"algorithm": "sha256",
51+
"placement": "code-cell-data-suffix-32",
52+
"digest": "<64 lowercase hexadecimal characters>"
53+
}
54+
}
55+
```
56+
57+
Unknown keys, alternate algorithms, alternate commitment placements, missing
58+
ABI objects, digest mismatches, and executable-suffix mismatches fail closed.
59+
The artifact bundle continues to use CKB Blake2b-256 for its executable
60+
`artifact_hash`; LS-IDL's ABI commitment remains SHA-256. These hashes have
61+
different roles and are not interchangeable.
62+
63+
## Accepted IDL Document
64+
65+
The document may contain only these top-level fields:
66+
67+
- `idl_version` (optional string, matching upstream clients that default it);
68+
- `name` (optional string, matching derive output that may omit it);
69+
- `witness` (required array, at most 256 fields);
70+
- `description` (optional string);
71+
- `script_version` (optional string); and
72+
- `signing` (optional object with non-empty string fields `algorithm`,
73+
`message`, and `hasher`).
74+
75+
Each witness field contains only `name`, `type`, `required`, and
76+
`description`. Names must be unique. The supported types are:
77+
78+
| Type | Encoding |
79+
| --- | --- |
80+
| `uint8` | one unsigned byte |
81+
| `uint32` | four-byte little-endian unsigned integer |
82+
| `uint64` | eight-byte little-endian unsigned integer |
83+
| `secp256k1_sig` | 65 bytes |
84+
| `secp256k1_pubkey` | 33 bytes |
85+
| `schnorr_sig` | 64 bytes |
86+
| `bytes` | four-byte little-endian length followed by that many bytes |
87+
88+
The current linear decoder treats `required` as interface metadata. It does
89+
not introduce a presence bitmap or conditional field skipping, so consumers
90+
must not interpret `required: false` as a wire-level omission rule.
91+
92+
## Public Read API
93+
94+
The canonical lookup is:
95+
96+
```text
97+
GET /v1/ckb/scripts/:code_hash/interfaces/ls-idl
98+
?network=mainnet|testnet
99+
&hash_type=data|data1|data2|type
100+
[&data_hash=0x...]
101+
```
102+
103+
`data_hash` is mandatory for `hash_type=type`, where a type hash alone may not
104+
uniquely identify executable data. More than one matching deployment returns
105+
`409` instead of choosing arbitrarily.
106+
107+
The compatibility route is:
108+
109+
```text
110+
GET /idl/:code_hash
111+
```
112+
113+
It is retained for existing LS-IDL clients and returns the same original
114+
bytes. New integrations should use the canonical route so network, hash type,
115+
and data-hash identity are explicit.
116+
117+
Successful responses use
118+
`application/vnd.ckb.ls-idl+json` and expose:
119+
120+
- `ETag`;
121+
- `x-ls-idl-format-version`;
122+
- `x-ls-idl-sha256`;
123+
- `x-ls-idl-coordinate`;
124+
- `x-ls-idl-commitment`; and
125+
- `x-ls-idl-verification`.
126+
127+
Clients must hash the response body directly. JSON-equivalent reformatting is
128+
not byte-equivalent and therefore does not preserve the commitment.
129+
130+
## CLI Workflow
131+
132+
Validate a document and optionally its existing executable binding:
133+
134+
```bash
135+
cellc artifact ls-idl validate --idl idl.json
136+
cellc artifact ls-idl validate --idl idl.json --executable lock
137+
```
138+
139+
Append the raw-byte digest to an executable without silently overwriting it:
140+
141+
```bash
142+
cellc artifact ls-idl bind \
143+
--idl idl.json \
144+
--executable lock \
145+
--output lock.ls-idl
146+
```
147+
148+
Generate a publish-ready artifact bundle and manifest:
149+
150+
```bash
151+
cellc artifact ls-idl bundle \
152+
--idl idl.json \
153+
--executable lock.ls-idl \
154+
--source lock.rs \
155+
--namespace example \
156+
--name example-lock \
157+
--release 0.1.0 \
158+
--language rust \
159+
--hash-type data1 \
160+
--dep-type code \
161+
--toolchain rust-1.97.1 \
162+
--source-revision <40-hex-git-commit> \
163+
--output artifact.bundle.json \
164+
--artifact-manifest-output Artifact.toml
165+
cellc publish --artifact-manifest Artifact.toml --dry-run --json
166+
```
167+
168+
Fetch exact bytes by deployed Script identity:
169+
170+
```bash
171+
cellc artifact ls-idl fetch \
172+
--code-hash 0x<64-hex> \
173+
--hash-type data1 \
174+
--network mainnet \
175+
--output idl.json
176+
```
177+
178+
The VS Code extension exposes the validate, bind, and fetch operations through
179+
the command palette. The Registry website exposes both package-bound interface
180+
facts and a direct Script-identity lookup.
181+
182+
## Storage And Admission
183+
184+
Migration `0010_ls_idl_interfaces.sql` adds a partial lookup index over public,
185+
chain-verified deployed evidence. The API narrows candidates in the database,
186+
then rechecks release identity, immutable bundle identity, one-and-only-one ABI
187+
object, raw-byte digest, and profile contract before returning bytes.
188+
189+
The normal compiler-backed Registry worker and the least-privilege
190+
artifact-only verifier both enforce the same profile. The latter has no
191+
CellScript compiler dependency. A publish that merely labels arbitrary JSON as
192+
LS-IDL, supplies a detached digest, or binds a digest to the wrong executable
193+
is rejected before it can become searchable.
194+
195+
## Compatibility Evidence
196+
197+
CellScript's curated vectors live in
198+
`examples/registry_ls_idl/vectors.json`. The complete upstream client vector
199+
corpus is intentionally referenced rather than copied:
200+
201+
- `ckb-idl-derive` commit
202+
`e7ee35766b9084099e9d840ccd37d2b5d40074a1`;
203+
- `ckb-idl-client` commit
204+
`7d883e0abccba56d423449b673567ee817747936`;
205+
- upstream `test-vectors.json` SHA-256
206+
`a9a6dca4fd0c5fcd2ca7aea6468784be7fdb29d6274049f07090cbab0ce9c1bb`.
207+
208+
The upstream mini Registry example parses and reserialises JSON, so it is not
209+
used as the byte-preserving production storage contract. One upstream property
210+
test also constructs a Blake2b commitment while the production client verifies
211+
SHA-256. CellScript follows the production client and proposal commitment,
212+
records those upstream revisions, and tests SHA-256 end to end.
213+
214+
## Operational Boundary
215+
216+
Deploying the website does not deploy the Registry API. Operators must apply
217+
migration `0010_ls_idl_interfaces.sql`, roll the API and verification worker,
218+
and verify the canonical and compatibility routes before advertising live
219+
lookup availability. Existing artifact records without an interface contract
220+
remain valid and are not returned by LS-IDL lookup.

‎docs/CELLSCRIPT_REGISTRY_PHASE1.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,20 @@ build is marked `evidence_required` until
254254
appropriate build evidence exists; merely uploading output bytes does not prove
255255
reproducibility.
256256

257+
### LS-IDL Lock Script interface
258+
259+
A deployable `ckb_executable` with `ckb.script_role = "lock"` may add a
260+
`cellscript-registry-ls-idl-interface-v1` contract. The ABI object is the exact
261+
LS-IDL JSON byte sequence; its SHA-256 must match the contract and the
262+
executable's final 32 bytes. Use `cellc artifact ls-idl validate`, `bind`, and
263+
`bundle` to construct this relationship. The normal and least-privilege
264+
verifiers independently enforce it.
265+
266+
This adds a discoverable interface identity, not a semantic implementation or
267+
security claim. The full schema, supported field encodings, compatibility
268+
vectors, and operator boundary are in
269+
[`CELLSCRIPT_LS_IDL_REGISTRY_PROFILE.md`](CELLSCRIPT_LS_IDL_REGISTRY_PROFILE.md).
270+
257271
## Accepting Reproduction Evidence
258272

259273
The Registry never executes an arbitrary publisher build recipe in its API
@@ -422,6 +436,8 @@ GET /v1/artifacts
422436
GET /v1/artifacts/:namespace/:name
423437
GET /v1/artifacts/:namespace/:name/releases/:release/evidence
424438
GET /v1/artifacts/:namespace/:name/releases/:release/commitment
439+
GET /v1/ckb/scripts/:code_hash/interfaces/ls-idl?network=:network&hash_type=:hash_type[&data_hash=:data_hash]
440+
GET /idl/:code_hash
425441
GET /artifacts/:namespace/:name/releases/:release.json
426442
POST /v1/artifacts/:namespace/:name/releases
427443
POST /v1/artifacts/:namespace/:name/releases/:release/deployments
@@ -454,6 +470,9 @@ that every artifact is installable.
454470
## Fail-Closed Rules
455471

456472
- Unknown kinds, profiles, languages, object roles, and state values fail.
473+
- LS-IDL lookup returns only an active, public, chain-verified deployable Lock
474+
Script with a schema-valid, raw-byte SHA-256/suffix-bound interface; type-hash
475+
lookup requires `data_hash`, and ambiguous candidates fail.
457476
- Identifiers are 1–64 lowercase letters or digits; `_` and `-` are allowed
458477
only between characters.
459478
- A source dependency resolver rejects every non-CellScript profile.

‎docs/CELLSCRIPT_REGISTRY_PRODUCTION_BOUNDARY_ADR.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ CKB/ABI, verifier IPC, reproducibility, or copy semantics to the immutable
140140
objects. The bundle is bounded to 5 MiB. Unknown fields and unknown or duplicate
141141
roles fail closed in admission, publisher CLI, and isolated verifier.
142142

143+
Deployable Lock Scripts may attach
144+
`cellscript-registry-ls-idl-interface-v1`. It binds SHA-256 of the exact ABI
145+
object bytes to the executable's final 32 bytes. The read API resolves those
146+
bytes only from active chain-verified deployment evidence and preserves them
147+
without JSON reserialisation. This is interface identity evidence, not proof of
148+
implementation correctness or a security audit.
149+
143150
## Verification Boundary
144151

145152
The worker leases jobs with `FOR UPDATE SKIP LOCKED`, bounded retry, dead-letter
@@ -218,6 +225,11 @@ Static release objects use:
218225
https://registry.cellscript.dev/artifacts/:namespace/:name/releases/:release.json
219226
```
220227

228+
LS-IDL adds a dynamic, chain-identity read at
229+
`/v1/ckb/scripts/:code_hash/interfaces/ls-idl` and the upstream-compatible
230+
`/idl/:code_hash` alias. `hash_type=type` requires a data hash, and ambiguity
231+
fails closed rather than selecting one deployment.
232+
221233
The static origin does not require Postgres. Objects include immutable bundle
222234
identity, artifact descriptor, all state axes, and accepted evidence. Consumers
223235
verify object, file, source, build, and deployment hashes independently.
@@ -274,6 +286,10 @@ Migrations are additive after the frozen `0001` baseline. The artifact-model
274286
migration intentionally refuses to transform non-empty legacy release data
275287
because no released public contract exists that would justify a lossy mapping.
276288

289+
Migration `0010_ls_idl_interfaces.sql` adds only a partial functional index for
290+
eligible deployment evidence; exact release, bundle, ABI, digest, and suffix
291+
checks still run on every response.
292+
277293
Readiness covers database/object access, admin configuration, and the verifier
278294
heartbeat. Backups contain a Postgres custom dump, object archive, image
279295
identity, and checksum manifest; restores are rehearsed into empty volumes

‎docs/README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ High-value active references include:
7272
- `CELLSCRIPT_REGISTRY_PRODUCTION_BOUNDARY_ADR.md` for the accepted production
7373
boundary of the wallet-rooted public registry write/read architecture and
7474
isolated Pudge testnet sandbox
75+
- `CELLSCRIPT_LS_IDL_REGISTRY_PROFILE.md` for byte-exact LS-IDL admission,
76+
executable suffix commitment, Script-identity lookup, tooling, and operator
77+
boundaries
7578
- `../services/registry-api/README.md` for the Cloudflare Workers + R2 + Neon
7679
write API implementation and deployment checklist
7780
- `CELLSCRIPT_COLLECTIONS_SUPPORT_MATRIX.md`
@@ -131,6 +134,8 @@ to current branch-specific evidence or forward design:
131134
governance scope
132135
- `CELLSCRIPT_REGISTRY_PHASE1.md` for the current artifact, verification,
133136
deployment-evidence, and public API contract
137+
- `CELLSCRIPT_LS_IDL_REGISTRY_PROFILE.md` for the 0.24 Lock Script interface
138+
profile and compatibility evidence
134139
- `archive/0.20/CELLSCRIPT_0_20_ROADMAP.md` for generated TypeScript action builders,
135140
live-chain registry verification, stateful flow evidence, and the bounded
136141
CellFabric JSON bridge

0 commit comments

Comments
 (0)