Skip to content

[Design][Interop] SSRI / IPC architecture decision: discovery, contract admission, and runtime communication #81

Open

Description

@a19q3

What reviewers are being asked to assess

Status: design proposal. No architecture has been selected, implemented, or assigned a release date. This issue introduces CellScript to reviewers who may not know it and allows the maintainer to invite Hanssen, Retric, Guopeng, and others. Naming them does not imply that they have been invited, agreed, or completed a review.

The decision is which layers of CellScript cross-contract interoperability should reuse SSRI, which should reuse ckb-script-ipc, and which constraints CellScript must own. Review capabilities and trust boundaries before APIs. “IPC” can mean either CKB's process-communication syscalls or XuJiandong's library; do not conflate them.

In one sentence: how a wallet discovers a contract, how a contract admits a counterpart, and how processes exchange arguments and results at runtime are three related but distinct problems. Claims that “IPC is more advanced” need concrete evidence of interoperability, cost, maintenance, and security benefits.

1. CellScript in ten minutes

CellScript compiles .cell source into CKB-VM RISC-V ELF and emits typed interface and execution-boundary descriptions. An independent artefact checker verifies bounded structural contracts between the ELF and those descriptions; it does not establish arbitrary business-logic correctness. CKB still consumes existing Cells and creates new Cells, with each Lock/Type Script validating the same transaction.

Concept Plain-language description Existing boundary
ProtocolBundle Organises a transaction involving separately compiled contracts and checks roles, witnesses, and input/output conflicts Off-chain orchestration; does not link ELFs together or replace execution of all Script groups
Interface receipt Checked result binding code, interface, and compilation evidence Type compatibility is not economic correctness or business equivalence
ScriptHandle / VerifierHandle Selects a Script or child verifier under an authorised policy Bounded profiles from #28/#29, not arbitrary function calls
InstanceScriptHandle Constrains full Script args and concrete instances beyond implementation admission #80; identical code can have different instances, and an allowed B cannot impersonate the selected A
Foreign view Reads transaction Cells belonging to another contract Observation confers neither spending permission nor proof that the other Script passed

Foundational issues #9/#10/#11/#28/#29/#80 were closed (checked 18 October 2026). The code baseline is 602795b3, a bounded accepted state on the 0.32 development branch, not a new stable release or claim of public deployment.

Starting points: end-to-end tutorial, open-handle contract, and instance contract and real example.

2. One example, three distinct needs

Suppose an institution issues document credentials. Alice wants to revoke one credential and unlock an observer Lock that references it, in the same transaction.

  1. The wallet needs to discover the credential type, available methods, and how to construct a transaction: discovery and off-chain construction.
  2. The observer Lock must establish that the actual input credential comes from an approved implementation, belongs to the right namespace, has a permitted category, and matches the instance selected for this operation: identity and authorisation.
  3. The credential Type must actually validate the issuance/revocation rules, and the issuer Lock must check the signature: complete transaction execution.
  4. Only if the application additionally needs an independent algorithmic verifier must a parent Script launch it, transmit data, read its result, and handle failures: process communication. The first three steps do not themselves require general-purpose IPC.
---
config:
  flowchart:
    subGraphTitleMargin:
      top: 10
      bottom: 20
---
flowchart TB
  subgraph Tool["Off-chain · Discovery and construction"]
    D["SSRI / other discovery entry"] --> B["Construct candidate transaction"]
    B --> P["ProtocolBundle · Check identity and roles"]
  end
  subgraph Chain["On-chain · Same transaction"]
    P --> L["Issuer Lock · Check signature"]
    P --> T["Credential Type · Validate revocation"]
    P --> O["Observer Lock · Instance policy"]
    O -. "Only if extra computation is required" .-> C["Parent process ⇄ Child verifier"]
    L --> A["All required groups pass"]
    T --> A
    O --> A
  end
  classDef tools fill:#e8f1ff,stroke:#4267a8,color:#132e53;
  classDef checks fill:#e5f6ee,stroke:#27835d,color:#133d2e;
  classDef optional fill:#fff3d9,stroke:#aa791c,color:#513a12;
  class D,B,P tools;
  class L,T,O,A checks;
  class C optional;
Loading

3. Research evidence: distinguish concepts, implementations, and unknowns

Verified on 18 October 2026. DeepWiki was used only for navigation; conclusions here rely on original proposals and pinned source.

  • Hanssen's original SSRI proposal: Script-Sourced Rich Information, method paths, off-chain execution contexts, and information/logic provided by Scripts.
  • ckb-ssri-std @ 93f3a779: its README still lists TODOs such as a unified entry and attribute macros; ssri_methods! already provides discovery/dispatch. Conceptual soundness does not imply that every proposed feature is implemented.
  • ckb-script-ipc @ 4044faee: procedural macros generate client/server code; runtime provides spawn/pipe, framing, and native execution. It is not exclusively on-chain.
  • RFC 0050: underlying spawn/wait/read/write/pipe semantics. Experiments must additionally pin node/VM/ckb-std versions, rather than relying solely on a moving RFC.
Dimension Inspected SSRI design/implementation Inspected ckb-script-ipc CellScript's own responsibility
Primary value Script self-description, shared query/construction logic, conventional public methods Rust trait → generated requests, responses, and communication code Bind interface to actual code, instance, and permissions
Execution Off-chain extended-VM contexts/queries must be explicitly marked On-chain parent/child processes and a native host entry Prevent off-chain results becoming on-chain authorisation
Methods and encoding Short method paths, argv, Molecule convention; pin exact version VLQ framing; default Channel uses serde_json; macro generates request/response enums Full type/codec identity, bounds, errors, version migration
Discovery vs authorisation Method presence indicates a claimed capability Receiving a reply indicates receipt of data Reject wrong code, instance, context, or forbidden operation
Resources Server/VM budgets, pagination, return sizes Repeated-request server loop, dynamic buffers, pipe lifecycle Measured byte/request/memory/cycle ceilings and deterministic failure
Existing capabilities Optional wallet/builder entry Candidate transport for parameterised child verifiers Preserve exact/open/instance ABIs and all peer checks

These are source observations, not a security audit or performance ranking. Default JSON does not mean IPC framing can only carry JSON. Replacing it with Molecule requires an explicit negotiated interoperable profile or an honestly named new protocol incompatible with the default upstream client.

4. Compare four routes fairly

Route Expected advantage Cost to demonstrate
A. Retain metadata and fixed verifiers; adopt neither for now Minimum change; existing behaviour intact Actual missed wallet interoperability and duplicated work
B. SSRI adapter; retain existing on-chain verifier path Address discovery/transaction construction first Same-ELF dispatch versus companion binding; extra VM/SDK maintenance
C. ckb-script-ipc as the primary service protocol, including discovery One client/server mechanism across use cases Whether SSRI/CCC consumers can use it directly; additional discovery conventions
D. Layered: SSRI discovery + bounded IPC Potential integration with both ecosystems Two protocol versions, adapters, duplicated encoding and tests

A small independent protocol remains a possible implementation variant of A/C/D, but requires precise justification for not reusing upstream contracts, disclosure of shared wire semantics, and a long-term maintainer. “More secure” or “more advanced” alone is inadequate. The current preference is to experiment by layer, not to commit to D or any new dependency.

5. Comparable experiments and decision process

  1. Pin problems and samples: credential discovery/construction, one fixed-size pure verifier call, and two ordered calls. All routes use the same code identity, requests, context, expected success/failure. Do not compare an unauthenticated demo against fully checked CellScript.
  2. Freeze interface semantics: target identity, full signature/codec hash, method number, read permissions, effects, input/output bounds, and error classes. Short-ID collisions must fail or have verifiable disambiguation; method number alone is not interface identity.
  3. Native Rust baseline: implement equivalent checks with a pinned ckb-std; measure application-specific code, reusable libraries, SDK construction, and testing. Compare complete implementations, not one DSL helper against all transitive Rust dependencies.
  4. Disposable adapters: test SSRI, default upstream IPC, candidate bounded IPC, and existing fixed path. Mark unimplemented cases as missing, not zero-cost. Pseudocode must not be presented as a working API.
  5. Reproducible evidence: record exact source/lock/compiler/ELF/network/VM versions, raw transactions/witnesses, code and transport sizes, memory, single/repeated call cycles, maximum-success and latest-failure cases. Report off-chain cold/warm latency separately. Mark unobservable memory as unavailable.
  6. Architecture decision record (ADR): document decisions to adopt, reject, or defer, with reasons and reconsideration triggers. Address external review disagreements individually; the maintainer assigns ownership and implementation scope before development.

Authoring direction — 2026-10-19

The authoring requirements adopted in #47/#48/#49 also apply to this decision. Treat application-facing declarations and transport bindings as separate design decisions: choosing SSRI, IPC, both, or neither must not automatically freeze the upstream library's plumbing as CellScript syntax. Any shared interface description must preserve the different context, authority, error, and lifecycle contracts; a pleasant call expression is not evidence that these contracts are interchangeable.

Compare all four routes using complete author-written examples: credential discovery and candidate construction, one checked verifier request, and two ordered requests. Show the declarations, reusable helpers, caller, generated client/builder, and rejection paths. Evaluate named business roles and methods, structurally resolved typed fields and policies, and named resource limits declared once at the relevant interface or scope. Avoid repeated positional budgets, numeric role ordinals, duplicate type/role declarations, and hand-written transport details at ordinary use sites. A declaration must still resolve to exact checked identities, codec bounds, and execution obligations.

Use the same borrowing direction as #47–#49: ordinary direct reads should stay direct; an explicit borrow scope should express a real retained-view lifetime. Bounded non-escaping helper composition is a target for review, not an already implemented capability. Local read-only views, owned collections, off-chain query results, and child-process messages retain different authority and lifetime rules. Borrowed pointers are not a cross-process wire format, and a decoded response does not acquire authority over foreign Cells.

Authoring review is part of architecture acceptance before a stable API is frozen. Record which repetition the compiler or generated adapters remove, which limits and failure decisions the author must still state, and which helper shapes remain unsupported. Compare equivalent reusable Rust libraries fairly. Preserve exact/open/instance admission, complete Script-group validation, numeric resource evidence, and independent checking; concise syntax cannot waive any of them. Exact grammar and protocol selection remain undecided.

6. Actual dependencies on #47/#48/#49

7. Deliverables, review, and closure criteria

This issue owns architecture selection. Two companion issues cover SSRI integration and bounded IPC ABI/lifecycle design; see Design workstreams.

  • Review complete authoring examples for all four routes against the [0.33][Runtime] Add bounded allocation-backed value collections and deterministic Map/Set #47/[0.33][ABI] Support bounded nested dynamic values with canonical codecs #48/[0.33][Runtime] Extend bounded Cell selection and correspondence for heterogeneous and dynamic data #49 direction: named roles/methods and limits, typed fields/policies, helper composition, and visible authority/lifecycle boundaries. Record remaining gaps before stable API freeze.
  • Pin all three upstream source revisions and document discrepancies between SSRI concepts, inspected implementation, and server versions.
  • Compare all four routes on equivalent scenarios; mark unexecuted measurements as absent, never pretend they are performance results.
  • Complete the responsibility matrix for identity, instance, context, permissions, codec, lifecycle, resources, and errors.
  • Supply comparable Rust and CellScript examples, clearly separating executable code, proposed APIs, and pseudocode.
  • Give both companion designs executable implementation slices, threat cases, methods for freezing numeric budgets, and acceptance owners.
  • Record actual invited reviewers' feedback and maintainer decisions. Silence is not endorsement; review waivers for earlier issues do not automatically carry over.
  • Record written accept/reject/defer decisions and reopening conditions. Closing the design issue is not equivalent to implementation or deployment.

Questions for reviewers: Have we defined SSRI's scope too narrowly? Does the IPC library's actual evolution change these observations? Which existing external consumers are mandatory interoperability targets? Can we share interface descriptions while retaining distinct transports? Which state or permission decisions must never depend on a service return value? Is maintaining two protocols worthwhile for v1? Please provide concrete calls and failure cases.

Design workstreams

All three are open designs. Small experiments in #82/#83 may run in parallel to produce evidence; #81 owns the final architecture decision. These are references, not claims that GitHub blocking dependencies have been configured.

Further reading

ProtocolBundle end-to-end tutorial.

Activity

  1. changed the title [-][Design][Interop] SSRI / IPC 分层选型:发现、合约准入与运行时通信[/-] [+][Design][Interop] SSRI / IPC architecture decision: discovery, contract admission, and runtime communication[/+] on Oct 18, 2026
  2. a19q3 commented on Oct 18, 2026

    @a19q3
    CollaboratorAuthor

    考虑到本议题涉及的主要开发者和评审者中有不少以中文交流,为方便大家阅读与讨论,也出于对不同语言使用习惯的尊重,特在此附上中文版。英文正文仍作为当前 issue 的主要描述;以下中文内容供对照参考。


    SSRI / IPC 分层架构选型:发现、合约准入与运行时通信

    状态:设计提案。尚未完成选型、实现,也没有承诺发布日期。 本议题面向未必熟悉 CellScript 的评审者,欢迎 Hanssen、Retric、Guopeng 等参与讨论;提及姓名不代表已邀请、已同意或已完成审核。

    核心问题是:CellScript 的跨合约互操作,哪些层适合复用 SSRI,哪些适合复用 ckb-script-ipc,哪些安全约束必须由 CellScript 自己承担?请先审能力与信任边界,再审 API。“IPC”可能指 CKB 的进程通信 syscall,也可能指 XuJiandong 的库,不应混淆。

    钱包如何认识合约、合约如何选择合作对象、运行时如何交换参数与结果,是三个相关但不同的问题。

    1. CellScript 背景

    CellScript 将 .cell 编译为 CKB-VM RISC-V ELF,同时生成类型接口和执行边界描述。独立 artifact checker 检查 ELF 与这些描述之间有界的结构性契约,不证明任意业务逻辑正确。CKB 仍按 Cell 模型运行,同一交易的 Lock/Type Script group 各自执行验证。

    概念 含义 边界
    ProtocolBundle 组织多个独立合约参与的交易,检查角色、witness 和输入输出冲突 链下编排,不链接 ELF,也不替代 Script group 执行
    接口 receipt 将代码、接口与编译证据绑定的检查结果 类型兼容不等于经济或业务等价
    ScriptHandle / VerifierHandle 按授权策略选择 Script 或子验证器 #28/#29 的有界 profile,非任意函数调用
    InstanceScriptHandle 进一步约束完整 Script args 和具体实例 #80;被允许的 B 不能冒充本次选定的 A
    foreign view 读取交易中其他合约的 Cell 观察不赋予花费权限,也不证明对方通过验证

    基础 issue #9/#10/#11/#28/#29/#80 已关闭(2026-10-18 核验);开发基线为 602795b3,属于 0.32 开发分支的有界接受状态,并非新的稳定版本或公开部署声明。

    阅读材料:端到端教程、开放 handle 设计、实例策略及案例。

    2. 用凭证注销说明不同层

    设某机构签发文件凭证,Alice 希望在一笔交易中注销凭证,并解锁引用该凭证的观察 Lock:

    1. 钱包需要发现凭证类型、可用方法和交易构造方式:发现与链下构造。
    2. 观察 Lock 需要确认实际输入凭证来自允许实现,namespace 正确、类别合规,而且是本次明确选定的实例:身份与授权。
    3. 凭证 Type 必须实际验证注销规则,发行者 Lock 必须验签:完整交易执行。
    4. 只有额外需要独立算法验证器时,父 Script 才需要 spawn、传参、读取结果并处理失败:进程通信。前三项并不必然需要通用 IPC。
    flowchart TB
      subgraph Tool["链下:发现与构造"]
        D["SSRI / 其他发现入口"] --> B["构造候选交易"]
        B --> P["ProtocolBundle:身份及角色检查"]
      end
      subgraph Chain["链上:同一笔交易"]
        P --> L["发行者 Lock:验签"]
        P --> T["凭证 Type:注销规则"]
        P --> O["观察 Lock:实例策略"]
        O -. "仅在需要额外计算时" .-> C["父进程 ⇄ 子验证器"]
        L --> A["全部必要 Script group 通过"]
        T --> A
        O --> A
      end
    
    Loading

    3. 调研来源和实现边界

    2026-10-18 的核验以原始设计及固定源码为依据,DeepWiki 仅用于导航:

    • Hanssen 的 SSRI 原始设计:Script 自描述、方法路径、链下执行环境和查询。
    • ckb-ssri-std @ 93f3a779:已有 ssri_methods! 分发,但 README 对 unified entry、属性宏等仍列有 TODO;不能将设计概念等同于全部实现。
    • ckb-script-ipc @ 4044faee:宏生成客户端和服务端代码;运行时支持 spawn/pipe、framing 与 native 运行,并非仅限链上。
    • RFC 0050:底层 spawn/wait/read/write/pipe 规范;实验仍须单独固定 node/VM/ckb-std 版本。
    维度 SSRI ckb-script-ipc CellScript 的责任
    价值 Script 自描述、共享查询/构造逻辑 通过 Rust trait 生成通信代码 绑定真实代码、接口、实例与权限
    环境 链下扩展 VM 和查询上下文 链上父子进程及 native 入口 不把链下结果升级成链上授权
    方法/编码 短路径、argv、Molecule 约定,版本待锁定 VLQ frame;默认 Channel 为 serde_json 完整类型/codec 身份、上限、错误和升级
    身份 方法存在只是能力声明 收到响应只说明通信成功 拒绝错误代码、实例、上下文和调用
    资源 执行预算、分页、结果大小 服务循环、buffer、pipe 生命周期 可测字节/次数/内存/cycles 限额
    现有能力 钱包/builder 的可选入口 参数化子验证器的候选 transport 保留已有 ABI 和 peer 验证

    这是源码观察,不是安全审计或性能排行。IPC 默认使用 JSON 不代表 framing 只能支持 JSON;若改用 Molecule,必须明确互通协商 profile,或将不兼容方案标记为新协议。

    4. 公平比较四条路线

    路线 预期收益 必须证明的成本或问题
    A:保持现有元数据与固定验证器 改动最少、行为稳定 是否错失钱包互通、重复开发代价
    B:SSRI adapter,链上保留旧路径 优先解决发现和构造 同 ELF/伴随 ELF 的绑定及 SDK/VM 维护
    C:主要使用 ckb-script-ipc,包括发现 一套服务协议 SSRI/CCC 客户端能否直接互通,缺哪些约定
    D:SSRI 发现 + 有界 IPC 通信 接入两个生态 双版本、adapter、重复编码与测试成本

    也可以考虑小型独立协议作为 A/C/D 的实现变体,但需证明为何不能复用上游、明确 wire 契约与维护者。当前只倾向按层分别试验,没有预选 D,也未承诺增加依赖。

    5. 同题实验与 ADR

    1. 固定样例:凭证发现/构造、一次固定长度纯验证调用、同一 child 上连续两次调用。各方案使用相同身份、请求、上下文及预期结果。
    2. 固定目标、完整签名和 codec hash、方法 ID、读取权限、效果、输入输出上限、错误分类。短 ID 冲突必须拒绝或可验证消歧。
    3. 用固定 ckb-std 做原生 Rust 对照,统计实际业务代码、可复用库、SDK 构造及测试,不拿 DSL 的一行调用与 Rust 全部依赖源码比较。
    4. 对 SSRI、上游默认 IPC、有界 IPC 候选、现有固定调用做可丢弃实验。未实现的项目标记为缺失,不能填成零成本。
    5. 记录可复现的 source/lock/compiler/ELF/network/VM 版本、原始交易及 witness、大小、内存、单次和连续调用 cycles、最大成功及最晚失败。链下冷/热启动另计;不可观察的指标标 unavailable。
    6. 形成 Architecture Decision Record(ADR,架构决策记录),逐项记载接受、拒绝、延期、复议条件与外部评审分歧;维护者再确定实施人及范围。

    作者接口方向 — 2026-10-19

    #47/#48/#49 已采用的作者接口要求同样适用于本次选型。面向业务作者的声明方式与 transport 绑定应分别决策:选择 SSRI、IPC、两者结合或暂不引入,都不能自动把上游库的底层操作冻结为 CellScript 语法。共享接口描述仍须保留各自的上下文、权限、错误与生命周期契约;调用写法简洁不代表这些契约可以互换。

    四条路线应使用完整的作者代码比较:凭证发现与候选交易构造、一次受检查的验证请求、两次有序请求。展示声明、可复用 helper、调用方、生成的客户端/builder 及拒绝路径。评估具名业务角色和方法、结构化解析的类型字段及策略,以及在对应接口或作用域集中声明的具名资源上限。普通使用处应避免重复位置参数预算、数字角色序号、重复类型/角色声明和手写 transport 细节;声明仍须解析为受检查的精确身份、codec 上限与执行义务。

    借用方向与 #47–#49 一致:普通直接读取保持直接;显式 borrow 作用域应表达实际保留 view 的生命周期。有界且不逃逸的 helper 组合是待评审目标,不能写成已实现能力。本地只读 view、owned 集合、链下查询结果和子进程消息仍有不同权限与生命周期。借用指针不是跨进程 wire 格式,解码后的响应也不会取得外部 Cell 的权限。

    作者接口评审属于稳定 API 冻结前的架构验收。记录编译器或生成的 adapter 消除了哪些重复、作者仍须明确哪些上限和失败决策、哪些 helper 形态尚不支持,并公平对照可复用 Rust 库。精确/开放/实例准入、全部必要 Script group 验证、数值资源证据和独立检查必须保留,不能因语法简化而豁免。具体语法和协议选型仍未决定。

    6. 与 #47/#48/#49 的关系

    7. 交付与关闭标准

    请评审者讨论: SSRI 范围是否界定得过窄?IPC 库的实际演进是否改变比较基础?哪些外部消费者是必须兼容的目标?能否共享接口描述而保留不同 transport?哪些状态与权限绝不可交由服务返回值决定?v1 是否值得承担双协议维护?请尽量给出具体调用和失败实例。

    Design workstreams

    总选型与决策:#81;SSRI 入口和链下上下文:#82;有界 IPC ABI、生命周期和互通:#83。三个 issue 均为开放设计;#82/#83 可以并行开展小实验,由 #81 汇总选型。这只是引用关系,不表示设置了 GitHub 自动阻塞依赖。

    延伸阅读:端到端教程。

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions