Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fiber-devnet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@offckb/cli': minor
---

Add Fiber (FNN) support to the local devnet. The devnet genesis now carries the Fiber contracts `auth`, `funding_lock` and `commitment_lock` (pinned to the FNN v0.9.0-rc7 source), and a new `offckb fiber` command family manages a local Fiber environment: `offckb node --fiber` starts CKB, miner, RPC proxy and FNN nodes in one go, while `offckb fiber start` adds FNN nodes to an already-running devnet (with `--daemon`/`offckb fiber stop` for background operation). Each node gets its own built-in CKB account (node N → account N+2), network identity, RPC port 21713+N, P2P port 8343+N and a `fnn.log`; `offckb fiber status [--json]` reports live node health, `offckb fiber logs --node <id>` reads node logs, and `offckb fiber clean [--data]` removes stores or the whole fiber environment. Startup verifies the devnet spec, CKB and every FNN agree on the same chain and checks node identity keys, funding accounts and balances. Plain local devnet only — mainnet/testnet and forked devnets are rejected. `offckb clean` now also removes fiber stores with `--data` and refuses to delete data while a CKB/fiber daemon or a live FNN store lock can be confirmed. New devnets only: devnets initialized by earlier offckb versions lack the Fiber contracts and must be rebuilt (`offckb clean`) to use Fiber, which changes the genesis hash.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@
[submodule "ckb/ckb-system-scripts"]
path = ckb/ckb-system-scripts
url = https://github.com/nervosnetwork/ckb-system-scripts.git
[submodule "ckb/fiber"]
path = ckb/fiber
url = https://github.com/nervosnetwork/fiber.git
22 changes: 20 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: all omnilock anyone-can-pay xudt spore ckb-js-vm nostr-lock ckb-debugger apply-debugger-patches clean-debugger-patches
.PHONY: all omnilock anyone-can-pay xudt spore ckb-js-vm nostr-lock fiber ckb-debugger apply-debugger-patches clean-debugger-patches

all: omnilock anyone-can-pay xudt spore ckb-js-vm nostr-lock pw-lock secp256k1_multisig_v2 ckb-debugger
all: omnilock anyone-can-pay xudt spore ckb-js-vm nostr-lock pw-lock secp256k1_multisig_v2 fiber ckb-debugger

omnilock:
@echo "Building omnilock via submodule"
Expand Down Expand Up @@ -53,6 +53,24 @@ secp256k1_multisig_v2:
cd ckb/ckb-system-scripts/ && make all-via-docker
cp ckb/ckb-system-scripts/specs/cells/secp256k1_blake160_multisig_all ckb/devnet/specs/secp256k1_blake160_multisig_all_v2

# Fiber contracts are copied (not rebuilt) from the pinned ckb/fiber submodule
# (FNN v0.9.0-rc7, fiber commit bc361aa) and committed under
# ckb/devnet/specs/fiber/ so published packages work offline; re-run this
# target after re-pinning the submodule. The upstream binaries embed the
# builder's home directory in panic metadata, so the copies are sanitized
# below with equal-length replacements (contract logic is untouched).
fiber:
@echo "Copying Fiber contracts via submodule"
@test -d ckb/fiber/tests/deploy/contracts || \
(echo "ckb/fiber submodule is missing. Run: git submodule update --init ckb/fiber" && exit 1)
mkdir -p ckb/devnet/specs/fiber
cp ckb/fiber/tests/deploy/contracts/auth ckb/devnet/specs/fiber/auth
cp ckb/fiber/tests/deploy/contracts/funding-lock ckb/devnet/specs/fiber/funding_lock
cp ckb/fiber/tests/deploy/contracts/commitment-lock ckb/devnet/specs/fiber/commitment_lock
cp ckb/fiber/config/testnet/config.yml ckb/devnet/specs/fiber/testnet-config.yml
perl -pi -e 's{/home/quake/}{/home/fiber/}g' ckb/devnet/specs/fiber/funding_lock
perl -pi -e 's{/Users/quake/}{/Users/fiber/}g' ckb/devnet/specs/fiber/commitment_lock

ckb-debugger:
@echo "Building ckb-debugger via submodule"
@echo "Applying patches to ckb-standalone-debugger..."
Expand Down
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ Options:
Commands:
node [CKB-Version] Use the CKB to start devnet
node stop Stop the running CKB devnet daemon
fiber start [FNN-Version] Start Fiber (FNN) nodes on the running devnet CKB
fiber stop Stop the daemon-managed fiber nodes
fiber status Show the status of the local CKB and all fiber nodes
fiber logs --node <id> Show the log of a fiber node
fiber clean Clean the fiber environment
create [options] [project-name] Create a new CKB Smart Contract project in JavaScript.
deploy [options] Deploy contracts to different networks, only supports devnet and testnet
debug [options] Quickly debug transaction with tx-hash
Expand Down Expand Up @@ -435,6 +440,38 @@ On a forked devnet, `offckb system-scripts`, transfers, deploys and `offckb debu

`offckb transfer` fails closed on a Mainnet fork: non-built-in keys require `--allow-external-key-on-mainnet-fork`, and inputs copied from Mainnet are rejected even with that override. (`--allow-mainnet-replay-risk` from 0.4.9 remains as a deprecated alias.)

### 8. Run a Fiber Devnet {#fiber-devnet}

OffCKB can start and manage a local [Fiber](https://github.com/nervosnetwork/fiber) development environment on top of the devnet: the Fiber contracts (`auth`, `funding_lock`, `commitment_lock`) live in the local chain's genesis block, and each FNN node gets its own CKB account, network identity, ports, data and log file.

```sh
# Start CKB, miner, RPC proxy and 2 FNN nodes in one command
offckb node --fiber

# Or start only the FNN nodes on an already-running devnet
offckb node
offckb fiber start

# Background mode
offckb node --fiber --daemon # one manager for CKB + FNNs, stopped by `offckb node stop`
offckb fiber start --daemon # separate fiber manager, stopped by `offckb fiber stop`

# Inspect
offckb fiber status [--json]
offckb fiber logs --node 1 [-f]

# Clean up
offckb fiber clean --data # delete only the FNN stores (channels/payments)
offckb fiber clean # delete the whole fiber environment
```

- Only the plain local devnet is supported: no mainnet/testnet, and no forked devnet (a `fork.json` present in the devnet directory rejects Fiber startup).
- Node `N` uses built-in CKB account `N+2` (accounts 3-18 are reserved for Fiber), RPC port `21713+N` and P2P port `8343+N`. Up to 16 nodes: `offckb fiber start --nodes 4`.
- `offckb fiber start [FNN-Version]` downloads a tested FNN release (currently `0.9.0-rc7`). Use `--binary-path <fnn>` (or `--fnn-binary-path <fnn>` with `node --fiber`) to run a locally built FNN.
- Every FNN writes its stdout/stderr to `devnet/fiber/nodes/<id>/fnn.log`, never to your terminal. Per-node FNN config overrides live in `devnet/fiber/nodes.yml` (regenerated `config.yml` files do not keep hand edits).
- Startup verifies that the devnet spec, the running CKB and every FNN agree on the same chain (genesis hash), and checks each node's identity key, CKB account and available balance before reporting ready.
- UDT channels: the FNN config whitelists the devnet sUDT and xUDT issued by built-in account 19, so issue test UDTs from that account (`offckb udt issue ... --privkey-file` with account 19's key) to the node accounts before opening UDT channels.

## Config Setting

### List All Settings
Expand Down Expand Up @@ -492,6 +529,8 @@ LOG_LEVEL=debug offckb node
- version: 1.0.0
- [x] Nostr-Lock https://github.com/cryptape/nostr-binding/tree/main/contracts/nostr-lock
- version: 25dd59d
- [x] Fiber (auth / funding-lock / commitment-lock) https://github.com/nervosnetwork/fiber
- commit id: bc361aa (FNN v0.9.0-rc7)
- [x] Type ID built-in

## Accounts
Expand Down
9 changes: 9 additions & 0 deletions ckb/devnet/specs/dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ create_type_id = false
[[genesis.system_cells]]
file = { file = "secp256k1_blake160_multisig_all_v2" }
create_type_id = false
[[genesis.system_cells]]
file = { file = "fiber/auth" }
create_type_id = false
[[genesis.system_cells]]
file = { file = "fiber/funding_lock" }
create_type_id = false
[[genesis.system_cells]]
file = { file = "fiber/commitment_lock" }
create_type_id = false

[genesis.system_cells_lock]
code_hash = "0x0000000000000000000000000000000000000000000000000000000000000000"
Expand Down
Binary file added ckb/devnet/specs/fiber/auth
Binary file not shown.
Binary file added ckb/devnet/specs/fiber/commitment_lock
Binary file not shown.
Binary file added ckb/devnet/specs/fiber/funding_lock
Binary file not shown.
104 changes: 104 additions & 0 deletions ckb/devnet/specs/fiber/testnet-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# This configuration file only contains the necessary configurations for the testnet deployment.
# All options' descriptions can be found via `fnn --help` and be overridden by command line arguments or environment variables.
fiber:
listening_addr: "/ip4/0.0.0.0/tcp/8228"
# Node name announced to the Fiber network. It is shown in RPC responses,
# the TUI header, and the network graph.
# announced_node_name: "my-fiber-node"
# Disable automatic peer reconnect backoff after disconnects.
# enable_peer_reconnect_backoff: true
bootnode_addrs:
- "/ip4/54.179.226.154/tcp/8228/p2p/Qmes1EBD4yNo9Ywkfe6eRw9tG1nVNGLDmMud1xJMsoYFKy"
- "/ip4/16.163.7.105/tcp/8228/p2p/QmdyQWjPtbK4NWWsvy8s69NGJaQULwgeQDT5ZpNDrTNaeV"
announce_listening_addr: true
announced_addrs:
# If you want to announce your fiber node public address to the network, you need to add the address here, please change the ip to your public ip accordingly.
# - "/ip4/YOUR-FIBER-NODE-PUBLIC-IP/tcp/8228"
chain: testnet

## SOCKS5 proxy settings
## Uncomment to route all outbound P2P connections through a SOCKS5 proxy (e.g. Tor).
# proxy:
# proxy_url: "socks5://127.0.0.1:9050"
# ## Use random username/password for each proxy connection to improve Tor stream isolation. [default: true]
# proxy_random_auth: true

## Tor onion hidden service settings
## Uncomment to make this node reachable via a .onion address.
## Requires a running Tor daemon with ControlPort enabled.
# onion:
# listen_on_onion: false
# ## Tor SOCKS5 proxy url for routing .onion address connections. e.g. 127.0.0.1:9050
# onion_server: "127.0.0.1:9050"
# ## The local address that the onion service forwards traffic to.
# ## If not set, it is derived from listening_addr. e.g. "127.0.0.1:8228"
# p2p_listen_address: "127.0.0.1:8228"
# ## Path to store the onion service private key. [default: $BASE_DIR/fiber/onion_private_key]
# onion_private_key_path: ""
# ## Tor controller address. [default: 127.0.0.1:9051]
# tor_controller: "127.0.0.1:9051"
# ## Tor controller hashed password (if HashedControlPassword is set in torrc).
# tor_password: ""
# ## The external port exposed by the onion service. [default: 8228]
# onion_external_port: 8228
# ## Maximum time in seconds to wait for the onion service to register with Tor. [default: 5]
# onion_service_start_timeout: 5
# lock script configurations related to fiber network
# https://github.com/nervosnetwork/fiber-scripts/blob/main/deployment/testnet/migrations/2025-02-28-111246.json
scripts:
- name: FundingLock
script:
code_hash: 0x6c67887fe201ee0c7853f1682c0b77c0e6214044c156c7558269390a8afa6d7c
hash_type: type
args: 0x
cell_deps:
- type_id:
code_hash: 0x00000000000000000000000000000000000000000000000000545950455f4944
hash_type: type
args: 0x3cb7c0304fe53f75bb5727e2484d0beae4bd99d979813c6fc97c3cca569f10f6
- cell_dep:
out_point:
tx_hash: 0x12c569a258dd9c5bd99f632bb8314b1263b90921ba31496467580d6b79dd14a7 # ckb_auth
index: 0x0
dep_type: code
- name: CommitmentLock
script:
code_hash: 0x740dee83f87c6f309824d8fd3fbdd3c8380ee6fc9acc90b1a748438afcdf81d8
hash_type: type
args: 0x
cell_deps:
- type_id:
code_hash: 0x00000000000000000000000000000000000000000000000000545950455f4944
hash_type: type
args: 0xf7e458887495cf70dd30d1543cad47dc1dfe9d874177bf19291e4db478d5751b
- cell_dep:
out_point:
tx_hash: 0x12c569a258dd9c5bd99f632bb8314b1263b90921ba31496467580d6b79dd14a7 #ckb_auth
index: 0x0
dep_type: code

rpc:
# By default RPC only binds to localhost, thus it only allows accessing from the same machine.
# Allowing arbitrary machines to access the JSON-RPC port is dangerous and strongly discouraged.
# Please strictly limit the access to only trusted machines.
listening_addr: "127.0.0.1:8227"

ckb:
rpc_url: "https://testnet.ckbapp.dev/"
udt_whitelist:
- name: RUSD
script:
code_hash: 0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a
hash_type: type
args: 0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b
cell_deps:
- type_id:
code_hash: 0x00000000000000000000000000000000000000000000000000545950455f4944
hash_type: type
args: 0x97d30b723c0b2c66e9cb8d4d0df4ab5d7222cbb00d4a9a2055ce2e5d7f0d8b0f
auto_accept_amount: 1000000000

services:
- fiber
- rpc
- ckb
1 change: 1 addition & 0 deletions ckb/fiber
Submodule fiber added at bc361a
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@types/adm-zip": "^0.5.5",
"@types/blessed": "0.1.27",
"@types/jest": "^30.0.0",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.17.24",
"@types/node-fetch": "^2.6.11",
"@types/semver": "^7.5.7",
Expand Down Expand Up @@ -84,6 +85,7 @@
"commander": "^12.0.0",
"http-proxy": "^1.18.1",
"https-proxy-agent": "^7.0.5",
"js-yaml": "4.3.0",
"node-fetch": "2",
"semver": "^7.6.0",
"tar": "^7.5.19",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/cfg/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface Settings {
bins: {
rootFolder: string;
defaultCKBVersion: string;
defaultFnnVersion: string;
downloadPath: string;
};
devnet: {
Expand Down Expand Up @@ -67,6 +68,7 @@ export const defaultSettings: Settings = {
bins: {
rootFolder: path.resolve(dataPath, 'bins'),
defaultCKBVersion: '0.208.0',
defaultFnnVersion: '0.9.0-rc7',
downloadPath: path.resolve(cachePath, 'download'),
},
devnet: {
Expand Down
Loading
Loading