The Cell Model — Why CKB Is Different
CKB uses a UTXO-based Cell model, not accounts. Every piece of on-chain state is a Cell:No Separate Announcer
On EVM chains, stealth payments require two operations: transfer funds and emit an announcement event. On CKB, the Cell itself is the announcement. The lock script args contain both the ephemeral public key and the stealth address hash:Scanning = Querying Cells
CKB has a built-in indexer with an RPC methodget_cells that filters by lock script code hash. To scan for incoming payments, query all live Cells using the stealth-lock code hash. Each Cell’s args contains the ephemeral key needed for the ECDH check.
Spending = Consuming Cells
To withdraw funds, build a transaction that:- Inputs: The stealth Cell being consumed
- Outputs: A new Cell at the destination address
- Witness: secp256k1 signature with the stealth private key
Script Set
| Script | Type | Purpose |
|---|---|---|
| wraith-stealth-lock | Lock Script | Verifies secp256k1 signatures for stealth Cells |
| wraith-names-type | Type Script | .wraith name registration (future) |
wraith-stealth-lock is required for stealth payments. Names are a secondary priority.
wraith-stealth-lock
A lock script that verifies secp256k1 signatures against the stealth public key hash embedded in the script args.Args Format
53 bytes total:Verification Flow
ckb-std crypto syscalls or ckb-auth for secp256k1 signature recovery and verification.
blake160
CKB’s standard address hashing:"ckb-default-hash" personalization is required. Without it, hashes won’t match CKB’s standard address format.
How It Differs from Standard CKB Locks
CKB’s default lock script (secp256k1-blake160-sighash-all) uses 20-byte blake160 args containing the owner’s pubkey hash. The stealth lock extends this to 53 bytes by prepending the ephemeral public key. The verification logic is the same — recover the public key from the signature and check the blake160 hash.
Usage
wraith-names-type (future)
A Type Script for.wraith name registration on CKB. Each name is a Cell with:
| Field | Content |
|---|---|
data | 66 bytes of meta-address (spending_pub + viewing_pub) |
type.args | blake2b hash of the name string |
lock | Owner’s lock script |
- Name is 3-32 characters, lowercase alphanumeric and hyphens
- No duplicate names (no other live Cell has the same type args)
- Updates require the current owner’s signature
Project Structure
Deployment
Build
Compile to RISC-V binary:Deploy
Deploy the compiled binary as a Cell on CKB testnet. The Cell’s data hash becomes thecode_hash used in stealth lock scripts.
Record Deployment Info
After deployment, record:- Code hash: The blake2b hash of the deployed binary (used as
lock.code_hashin stealth Cells) - Cell dep: The transaction hash and index where the script binary Cell lives (required in every transaction that uses the lock)
deployments.ts:
Testing
Tests use CKB’s native testing framework withckb-testtool:
- Args validation — rejects args that aren’t exactly 53 bytes
- Signature verification — valid stealth key signature passes
- Wrong key rejection — signature from a different key fails
- blake160 correctness — hash matches CKB’s standard implementation
Differences from Other Chains
| Aspect | EVM (Solidity) | Stellar (Soroban) | Solana (Anchor) | CKB |
|---|---|---|---|---|
| Model | Account | Account | Account | UTXO (Cell) |
| Language | Solidity | Rust | Rust (Anchor) | Rust (RISC-V) |
| Announcement | Separate event | Separate event | Separate event | Embedded in Cell |
| Scanning source | Subgraph | Soroban RPC | Program logs | get_cells RPC |
| Script count | 4 contracts | 4 contracts | 3 programs | 1 lock script |
| Address hash | keccak256 | N/A | N/A | blake2b (“ckb-default-hash”) |
| Shared secret hash | keccak256 | SHA-256 | SHA-256 | SHA-256 |
| Min balance | None | 1 XLM | ~0.00089 SOL | 61 CKB |
| Names | On-chain contract | On-chain contract | On-chain program | Future (Type Script) |

