🚀 Open Source

CKB Script IPC

Make CKB contracts interact like building blocks

A powerful Inter-Process Communication protocol that enables seamless communication between CKB scripts. Build modular, reusable, and composable smart contracts.

Rust & C Multi-Language Support
VLQ Compact Wire Format
Serde JSON Serialization
Script A
📦
IPC
Script B
📦
Script C
📦

Why CKB Script IPC?

Build smarter contracts with modular, reusable components

🧩

Modular Design

Split complex logic into separate scripts that communicate seamlessly. Build once, reuse everywhere.

Automatic Code Generation

Use proc-macros to automatically generate IPC boilerplate code. Focus on your business logic, not plumbing.

🔄

Easy Serialization

Built-in support for serde serialization. Any type that implements Serialize/Deserialize works out of the box.

🛡️

Type Safety

Strong type checking at compile time. Catch errors before deployment, not in production.

📦

Compact Protocol

Uses VLQ (Variable-Length Quantity) encoding for efficient wire format. Minimal overhead, maximum performance.

🌍

Multi-Language Support

Implementations in both Rust and C. Choose the language that fits your project best.

How It Works

Simple concepts, powerful results

Client Script

spawn_server()
WorldClient::new()
client.hello("world")
Request (VLQ) Response (VLQ)

Server Script

impl World for Server
run_server()
fn hello() → "hello, world"

Wire Protocol Format

📤 Request Packet

version VLQ
method_id VLQ
length VLQ
payload bytes

📥 Response Packet

version VLQ
error_code VLQ
length VLQ
payload bytes

Code Examples

See how easy it is to use CKB Script IPC

def.rs Rust
use alloc::string::String;

// Define your IPC interface with a simple trait
#[ckb_script_ipc::service]
pub trait World {
    fn hello(name: String) -> Result<String, u64>;
}

// That's it! The proc-macro generates:
// - WorldClient for calling the service
// - WorldServer trait for implementing the service
// - All serialization/deserialization code
server_entry.rs Rust
use crate::def::World;
use ckb_script_ipc_common::spawn::run_server;

struct WorldServer;

impl World for WorldServer {
    // Implement your method logic
    fn hello(&mut self, name: String) -> Result<String, u64> {
        if name == "error" {
            Err(1)
        } else {
            Ok(format!("hello, {}", name))
        }
    }
}

pub fn server_entry() -> Result<(), Error> {
    let world = WorldServer;
    // Start the server - it runs in an infinite loop
    run_server(world.server())
}
client_entry.rs Rust
use crate::def::WorldClient;
use ckb_script_ipc_common::spawn::spawn_server;
use ckb_std::ckb_constants::Source;

pub fn client_entry() -> Result<(), Error> {
    // 1. Spawn the server process
    let (read_pipe, write_pipe) = spawn_server(
        0,
        Source::CellDep,
        &[CString::new("demo").unwrap().as_ref()],
    )?;

    // 2. Create the client
    let mut client = WorldClient::new(read_pipe, write_pipe);

    // 3. Make IPC calls - just like calling a local function!
    let result = client.hello("world".into())?;
    // result = "hello, world"

    Ok(())
}

Real World Use Cases

See what you can build with CKB Script IPC

🔐

Crypto Services

Build reusable cryptographic services that multiple scripts can share:

  • Blake2b, SHA-256, RIPEMD-160 hashing
  • Secp256k1 signature verification
  • Schnorr and Ed25519 signatures
View Example →
🧮

Complex Computation

Offload heavy computation to specialized scripts:

  • Mathematical operations
  • Data validation logic
  • Protocol-specific calculations
🔗

Composable Contracts

Build contracts that work together like LEGO blocks:

  • Modular authentication
  • Shared state management
  • Plugin architecture

Getting Started

Start building with CKB Script IPC in minutes

1

Add Dependencies

# Cargo.toml
[dependencies]
ckb-script-ipc = "x.x.x"
ckb-script-ipc-common = "x.x.x"
serde = { version = "1.0", default-features = false, features = ["derive"] }
2

Define Your Interface

#[ckb_script_ipc::service]
pub trait MyService {
    fn my_method(arg: String) -> Result<String, u64>;
}
3

Implement & Use

Implement the trait for your server, spawn it from your client, and start making calls!

View Full Demo →

Choose Your Language

🦀

Rust

Full-featured implementation with proc-macros for automatic code generation.

View Rust Crate →
⚙️

C

Core IPC functionality for C projects. Manual serialization required.

View C Library →

Frequently Asked Questions

Any type that implements Serialize and Deserialize from serde can be used. This includes all primitive types, standard library types, and custom structs annotated with #[derive(Serialize, Deserialize)].

CKB Script IPC uses serde_json for message serialization. This provides a good balance between human readability and compatibility.

The code operates within a script process that is part of a transaction, and can only run on the same machine. This is more akin to Inter-Process Communication (IPC) rather than Remote Procedure Call (RPC). RPC typically includes features like encryption, authentication, retries, and scaling that aren't relevant in this context.

Use cargo-expand to view the code generated by the #[ckb_script_ipc::service] macro.

Yes! Enable the std feature in ckb-script-ipc-common and use native::spawn_server to interact with on-chain script services from native code.

Ready to Build?

Start building modular, composable CKB contracts today.