Celestia
https://docs.celestia.org/how-to-guides/ibc-relayer
https://github.com/celestiaorg/celestia-node
Celestia 是数据可用层(DataAvailability, DA)项目, 基于 Cosmos 架构, 为其他 Layer1, Layer2 提供数据层, 共识层, 构建模块化区块链, 商业模式 toB, 面向其他公链收费
代币名称: TIA
网络
- Mainnet Beta 主网(也是测试网)
- mocha 测试网
- Arabica Devnet 测试网(一个全新的测试网)
网络节点介绍
分层网络:共识网络 + 数据可用网络
共识网络
-
验证节点:
此类型节点通过产生和投票区块来参与共识过程,主要是维护整体性能和网络安全
-
全共识节点:
用来同步区块链历史的 celestia-app 完整节点。
存储区块链历史的完整副本, 并连接到共识网络, 帮助确认和验证区块和数据
数据可用网络
桥 + 全节点 + 轻节点
bridge 桥接节点
将区块头和块数据从共识层传输到数据可用性层, 为轻节点提供数据采样服务
- 桥节点 同时连接数据可用性网络和共识网络
- 桥节点 同时还可以选择成为共识网络的验证者
- 桥节点实质上运行了两份独立程序 共识节点+可用网络
桥节点向数据可用性网络中的轻节点提供带有数据可用性标头的块共享
full 全存储节点
- 不参与共识
- 存储所有数据, 通过桥节点向轻节点分享数据
- 主要用于交易数据的存储和验证
- 全节点从共识网络获取区块头,从桥节点获取区块body
light 轻节点
- 从共识网络获取区块头, 从桥节点获取区块采样
- 数据校验需要 通过桥节点中转 与全节点产生交互
- 因为自身有区块头,所以可以校验全节点的数据是否准确
- 采样是桥节点进行的, 轻节点只有部分采样数据;
使用数据可用性抽样来验证链, 而无需下载整个区块链
轻节点的数据完整性验证不直接通过共识网络的验证人节点进行, 而是通过全节点
注:使用本地账户对 POB 进行签名后, 提交到共识节点打包并支付 POB 费用
轻节点越多, 网络效率越高,如果全节点丢失, 也可以通过足够多的轻节点恢复出完整的区块body
一些概念
DAS 采样
数据可用性采样(Data Availability Sampling, DAS)
- 区块数据编码: Celestia 使用二维 Reed-Solomon 编码将区块数据分割成多个小块, 并通过 Merkle 树生成区块头中的承诺;
- 轻节点采样: 轻节点随机选择区块数据的一部分进行采样, 并向全节点请求这些数据块及其 Merkle 证明;
- 数据传播: 轻节点在验证数据块的 Merkle 证明后, 会将这些数据块传播到网络中; 通过这种方式, 轻节点可以间接发现其他节点, 并验证数据的可用性
对于轻节点抽样来说, 抽样模型是亚线性的(Sub-linear); 他们仅需下载所需抽样数据量的平方根数量即可; 即, 若有 10,000 个小份 Chunks 数据需要抽样, 仅需要下载并检查其中 100 个
简单理解
块的数据被转换为一个矩阵, 每个轻节点只会保留矩阵中的一小部分数据,
验证时, 轻节点在矩阵内随机选择一组唯一坐标, 并前往全节点验证,
如果本地的这个坐标信息和全节点的坐标信息相同, 说明这个全节点是可信的, 同时这个区块的数据也是可用的;
Bitswap
Celestia Light 节点通过 Bitswap 协议与其他节点进行数据交换;
Bitswap 是一种点对点网络中的数据共享协议, 节点之间通过交换"想获取的数据列表"(want-list)来动态请求和分享数据。
纠删码(Erasure Coding)
二维 RS 纠删码编码方案(2-dimensional Reed-Solomon encoding scheme)
Celestia 使用纠删码, 对原始数据编码, 将原始数据切成若干小份(Chunks)
命名空间默克尔树(NMT)
Celestia 将区块数据分割成多个命名空间, 每个应用程序对应一个命名空间;
这使得应用程序只需下载自己的数据, 而无需下载其他应用程序的数据
数据可用性只能解决数据可用性的验证问题, 而降低执行层和结算层的成本将交给命名空间默克尔树方案
Celestia 将区块当中的数据划分为了多个命名空间, 每个命名空间都对应着正在使用 Celestia 作为数据可用性层的执行层和结算层, 这样每个执行层和结算层仅需下载和自己相关的数据就能够实现网络的功能
事件
挪动节点导致启动失败
节点关闭时如果有块信息在 wal 文件中, 没有及时写库。
如果挪动了节点目录,下次启动时会报错 block 文件找不到, 因为读取的路径是绝对路径。
解决:可以创建一个软链接来临时解决这个问题
数据节点负载较高
数据节点在数据量较大的情况下, cpu使用率偶尔会突增很高;
原因
- cpu核心树太多,使得程序的并线协程数也多
- 缓存区块太少, 频繁进行索引
1
2
3
4
5
6
7
8
9
|
编辑 config.toml 文件:
[Share.EDSStoreParams]
BlockstoreCacheSize = 128 # 修改为 1024 或 2048;
[Header.Store]
StoreCacheSize = 4096 # 8192
IndexCacheSize = 16384 # 32768
WriteBatchSize = 2048 # 4096
|
编译二进制程序
1
2
3
4
5
6
7
8
9
|
# 数据网络节点
git clone https://github.com/celestiaorg/celestia-node.git
make install
# 共识网络节点
https://github.com/celestiaorg/celestia-app.git
make install
|
其它
1
2
3
4
5
6
7
8
|
celestia-appd config keyring-backend test
# 恢复自己的钱包
celestia-appd keys add Ting --recover
# 发起委托质押
celestia-appd tx staking delegate celestiavaloper1msglwkyaxl9zm92tkmve4cgwcanptlexjtzex2 5000000utia --from=Ting --fees 300utia --chain-id=mocha --node https://rpc-mocha.pops.one:443
|
下载区块资源以开始快速同步(直接下载data)
1
2
3
4
5
6
|
rm -rf ~/.celestia-app/data
mkdir -p ~/.celestia-app/data
SNAP_NAME=$(curl -s https://snaps.qubelabs.io/celestia/ | \
egrep -o ">blockspacerace.*tar" | tr -d ">")
wget -O - https://snaps.qubelabs.io/celestia/${SNAP_NAME} | tar xf - \
-C ~/.celestia-app/data/
|
api token 访问
1
2
3
4
5
6
7
8
|
# 查询桥节点token
AUTH_TOKEN=$(celestia bridge auth admin --p2p.network blockspacerace)
curl -X POST \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":0,"method":"p2p.Info","params":[]}' \
http://localhost:26658
|
rpc接口交易
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
轻节点提交一个 PayForBlob 交易
PFB 是一个 PayForBlob 消息;
接入点还需要提供 namespace_id 和 data 值;
Namespace ID 应为 10 字节, 以 0x 为前缀;
Data 应为原始消息的十六进制编码字节;
namespace_id: 0x42690c204d39600fddd3
data: 0xf1f20ca8007e910a3bf8b2e61da0f26bca07ef78717a6ea54165f5
# 生成你自己的 namespace_id 和 data
celestia rpc blob SubmitPayForBlob [namespace in hex] [data in hex]
# 提交交易
celestia rpc blob Submit 0x42690c204d39600fddd3 0xf1f20ca8007e910a3bf8b2e61da0f26bca07ef78717a6ea54165f5
# 提交交易 - 提交文本内容, 会被自动转为 base64 编码
celestia rpc blob Submit 0x42690c204d39600fddd3 '"gmabcderf"'
{"jsonrpc": "2.0","result": 32236,"id": 1}
Namespace ID 可以被编码为十六进制或 Base64 格式;
Blob 可以是十六进制(0x...), Base64 格式("...")或普通字符串(将被编码为 Base64)('"Hello There!"')
# 检索数据
使用提交时响应的区块高度和提交 PFB 交易时使用的 Namespace ID, 来获取返回给你的消息份额(数据)
celestia rpc blob GetAll [block height] [namespace in hex]
celestia rpc blob GetAll 32236 0x42690c204d39600fddd3
celestia rpc blob GetAll 32236 0x42690c204d39600fddd3 --print-request # 输出rpc的curl请求详情
# 查询余额 - 当前用户
celestia rpc state Balance
# 查询余额 - 其他用户
celestia rpc state BalanceForAddress [address]
|
cel-key
钱包管理
1
2
3
4
5
6
7
8
9
10
11
|
# 编译钱包程序
make cel-key
# 创建密钥
cel-key add key_name --keyring-backend test --node.type light --p2p.network <network>
# 创建钱包
cel-key add Ting --keyring-backend test --node.type light
cel-key list --node.type light --keyring-backend test --p2p.network <network>
|
部署
简易例子, 未完
共识网络节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
celestia-appd init node0 --chain-id private
celestia-appd keys add user1 --keyring-backend test
celestia-appd add-genesis-account user1 6000000000utia --keyring-backend test
celestia-appd gentx user1 1000000000utia --chain-id private --keyring-backend test --gas-prices 0.0001utia
celestia-appd collect-gentxs
celestia-appd start --moniker core0 --rpc.laddr tcp://0.0.0.0:26657 --grpc.enable true
celestia-appd tendermint show-node-id > $HOME/.celestia-app/node-id
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
celestia-appd tx staking create-validator --pubkey '{"@type":"/cosmos.crypto.ed25519.PubKey","key":"hBmQ574LhkITEJJ7kRm5jQLXJ4LQ9GKYD4wXPatTvno="}' --moniker node2 \
--from="val2" \
--amount 5000000000utia \
--chain-id="private" \
--commission-rate=0.1 \
--commission-max-rate=0.2 \
--commission-max-change-rate=0.01 \
--min-self-delegation=1000000 \
--keyring-backend=test \
--home /data/celestia-nodes/node1 \
--broadcast-mode=block \
--fees="300000utia" \
--yes
|
数据可用网络-桥节点
1
2
3
4
5
6
7
8
9
10
11
12
|
celestia bridge init --p2p.network private --node.store /data/celestia-bridge-nodes
HAST=$(curl "http://127.0.0.1:26657/block?height=1" |jq .result.block_id.hash)
sed -i "s/TrustedHash = \"\"/TrustedHash = ${HAST}/" /data/celestia-bridge-nodes/config.toml
sed -i "s/SkipAuth = false/SkipAuth = true/" /data/celestia-bridge-nodes/config.toml
sed -i '/^\[Core/,+2 s/IP = \"\"/IP = \"192.168.5.8\"/' config.toml
sed -i '/^\[RPC/,+2 s/Address = \"localhost\"/Address = \"192.168.5.8\"/' config.toml
celestia bridge start --keyring.accname bridge --p2p.network private --node.store /data/celestia-bridge-nodes
|
数据可用网络-light节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
HAST=$(curl "http://192.168.5.8:26657/block?height=1" |jq .result.block_id.hash)
celestia light init --p2p.network private --node.store /data/celestia-light-nodes
peers_id=`celestia p2p info --url "http://192.168.5.8:26658" --token "aa"|jq -r '.result.id'`
peers_ip=`celestia p2p info --url "http://192.168.5.8:26658" --token "aa"|grep -P '/ip4/\d+.\d+.\d+.\d+/tcp/\d+' -o`
peers="${peers_ip}/p2p/$peers_id"
echo $peers > /data/celestia-light-nodes/peer.info
peers=$(sed 's/[]\/$*.^[]/\\&/g' /data/celestia-light-nodes/peer.info)
echo "write peers :$peers"
sed -i "s/TrustedPeers = \[\]/TrustedPeers = \[\"${peers}\"\]/" /data/celestia-light-nodes/config.toml
sed -i "s/TrustedHash = \"\"/TrustedHash = ${HASH}/" /data/celestia-light-nodes/config.toml
sed -i "s/SkipAuth = false/SkipAuth = true/" /data/celestia-light-nodes/config.toml
sed -i '/^\[Core/,+2 s/IP = \"\"/IP = \"192.168.5.7\"/' /data/celestia-light-nodes/config.toml
sed -i '/^\[RPC/,+2 s/Address = \"localhost\"/Address = \"192.168.5.8\"/' /data/celestia-light-nodes/config.toml
celestia light start --keyring.accname light --p2p.network private --node.store /data/celestia-light-nodes
|
节点管理
相关指令
常用命令
1
2
3
|
celestia rpc node Info # 查询节点信息
celestia rpc p2p Info # 节点 peerId 信息的 RPC 调用
|
不常用命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 重置节点
celestia-appd tendermint unsafe-reset-all --home xxx
# 获取当前节点的账户地址
celestia rpc state AccountAddress
# 获取指定高度的区块头
celestia rpc header GetByHeight [height]
# 获取数据可用性采样相关的统计
celestia rpc das SamplingStats
# 初始化节点时设置配置信息
celestia bridge init --core.ip localhost --core.rpc.port 26657 --core.grpc.port 9090 --p2p.network blockspacerace
|
交易
1
2
|
# 转账
celestia rpc state Transfer $TO_ADDRESS [amount in utia] [gas fee in utia] [gas fee in utia]
|
token 认证
1
2
3
4
5
6
7
8
|
# 方法一: 配置跳过认证则不需要 token
skipAuth=True
# 方法二: 创建 token
celestia light auth --node.store /home/user1/celestia/node/nodes/light admin
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBbGxvdyI6WyJwdWJsaWMiLCJyZWFkIiwid3JpdGUiLCJhZG1pbiJdfQ.OG5ptA9d6Dn4V4qRiRttX0_yUDHWk5wqZtoy18b2lIM
|
搭建轻节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 轻节点也可以质押
# 先启动轻节点, 然后用共识客户端进行质押
celestia light init
celestia light init --p2p.network blockspacerace # 初始化时选择节点
# 编译钱包程序
make cel-key
# 创建钱包 - Ting 是钱包名称
./cel-key add Ting --keyring-backend test --node.type light
# 启动轻节点
celestia light start --core.ip https://rpc-mocha.pops.one --core.grpc.port 9090
celestia light start --core.ip <ip-address> --p2p.network blockspacerace
|
轻节点管理
1
2
3
4
5
6
7
8
9
10
11
|
# 初始化轻节点
celestia light init --p2p.network arabica
celestia light init --p2p.network mocha
# run
celestia light start --core.ip <> --p2p.network <network>
celestia light start --p2p.network mocha --core.ip rpc-mocha.pops.one --core.port 9090
# 创建密钥
cel-key add key_name --keyring-backend test --node.type light --p2p.network <network>
|
全节点
1
2
3
4
5
|
# 创建全节点
celestia full init
# run
celestia full start --core.ip <>
|
配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
[Node]
StartupTimeout = "2m0s"
ShutdownTimeout = "2m0s"
[Core]
IP = "172.28.10.101"
RPCPort = "26657"
GRPCPort = "9090"
[State]
DefaultKeyName = "full"
DefaultBackendName = "test"
[P2P]
ListenAddresses =["/ip4/0.0.0.0/udp/2121/quic-v1/webtransport", "/ip4/0.0.0.0/udp/2121/quic-v1", "/ip4/0.0.0.0/udp/2121/webrtc-direct", "/ip4/0.0.0.0/tcp/2121"]
AnnounceAddresses = []
NoAnnounceAddresses = ["/ip4/127.0.0.1/udp/2121/quic-v1/webtransport", "/ip4/0.0.0.0/udp/2121/quic-v1/webtransport", "/ip6/::/udp/2121/quic-v1/webtransport", "/ip4/0.0.0.0/udp/2121/quic-v1", "/ip4/127.0.0.1/udp/2121/quic-v1", "/ip6/::/udp/2121/quic-v1", "/ip4/0.0.0.0/udp/2121/webrtc-direct", "/ip4/127.0.0.1/udp/2121/webrtc-direct", "/ip6/::/udp/2121/webrtc-direct", "/ip4/0.0.0.0/tcp/2121", "/ip4/127.0.0.1/tcp/2121", "/ip6/::/tcp/2121"]
MutualPeers = []
PeerExchange = true
RoutingTableRefreshPeriod = "1m0s"
[P2P.ConnManager]
Low = 800
High = 1000
GracePeriod = "1m0s"
[RPC]
Address = "localhost"
Port = "26658"
SkipAuth = false
[Gateway]
Address = "localhost"
Port = "26659"
Enabled = false
# Share 模块参数主要用于配置数据可用性(Data Availability, DA)层的共享存储和交换机制
[Share]
# 是否启用共享交换(Share Exchange); 如果设置为 true, 节点将参与共享数据的交换, 这有助于提高数据可用性和网络的去中心化程度
UseShareExchange = true
[Share.EDSStoreParams]
# 垃圾回收间隔时间; 设置为 "0s" 表示禁用垃圾回收, 这可能导致存储空间的持续增长, 但可以提高性能
GCInterval = "0s"
# 最近区块的缓存大小; 这个参数决定了缓存中保留的最近区块数量, 有助于快速访问最新的区块数据
RecentBlocksCacheSize = 10
# 区块存储的缓存大小; 这个参数决定了缓存中保留的区块存储数据的大小, 可以提高数据读取的效率
BlockstoreCacheSize = 128
[Share.ShrExEDSParams]
ServerReadTimeout = "5s"
ServerWriteTimeout = "1m0s"
# 处理请求的超时时间
HandleRequestTimeout = "1m0s"
# 并发限制; 这个参数决定了服务器同时处理的最大请求数量
ConcurrencyLimit = 10
# 缓冲区大小; 这个参数决定了每个请求的缓冲区大小, 每个请求的缓冲区大小为 32KB
BufferSize = 32768
# 共享交换的网络数据
[Share.ShrExNDParams]
ServerReadTimeout = "5s"
ServerWriteTimeout = "1m0s"
HandleRequestTimeout = "1m0s"
ConcurrencyLimit = 10
# 对等节点(Peer)管理相关
[Share.PeerManagerParams]
PoolValidationTimeout = "2m0s"
PeerCooldown = "3s"
GcInterval = "30s"
EnableBlackListing = false
# 节点发现机制相关
[Share.Discovery]
PeersLimit = 5
AdvertiseInterval = "1h0m0s"
[Header]
TrustedHash = "DC14F2924439C7DFB6994AB461EAD1C18D80918FC77B0768F3443FED9AB9E8FD"
TrustedPeers = ["/ip4/172.28.10.1/tcp/2121/p2p/12D3KooWKFt3QjmSxxuSA3Cf3qRuaDpKewhryYsnkqVWKJah1Wfz"]
[Header.Store]
StoreCacheSize = 4096
IndexCacheSize = 16384
WriteBatchSize = 2048
[Header.Syncer]
TrustingPeriod = "336h0m0s"
[Header.Server]
WriteDeadline = "8s"
ReadDeadline = "1m0s"
RangeRequestTimeout = "10s"
[Header.Client]
MaxHeadersPerRangeRequest = 64
RangeRequestTimeout = "8s"
[DASer]
SamplingRange = 100
ConcurrencyLimit = 6
BackgroundStoreInterval = "10m0s"
SampleFrom = 1
SampleTimeout = "2m0s"
[Pruner]
EnableService = false
|