使用本頁可在 testnet 上運行你自己的 rand-node。這也是私密使用錢包的建議做法:由你自己運行的節點,除了你之外不會從任何人處得知你即將花費哪個葉子。觀察節點負責同步、重新驗證每個證明並提供 JSON-RPC 服務;驗證者執行相同工作,並在其密鑰列入某個 epoch 的驗證者集合後參與共識。
構建
要求:Rust 1.98.1(已在 rust-toolchain.toml 中鎖定,由 rustup 安裝)、C++ 編譯器,以及供 RocksDB 使用的 cmake。zkVM crate 以路徑依賴方式引用證明系統倉庫(randprotocol/zkp-circuits)中與之並列的 circuits/ 檢出副本;該副本必須與 fullnode/ 並列放置,並位於該版本引入(vendor)時所依據的提交:即 crates/randprotocol-zkvm/guests-compiled/PROVENANCE.md 中 circuits: 一行所載的提交(v0.6.8 為 aeacf31,與 v0.6.7 相同)。首次構建需時 10 至 20 分鐘。
git clone https://github.com/randprotocol/fullnode
cargo build --release # target/release/rand-node, target/release/rand, target/release/rand-prover
請運行 v0.6.8(git checkout v0.6.8,提交 c9c9bd3c,即機群所運行的版本;rand_getVersion 會報告節點的 sha)。其 GitHub 發佈版本附帶 rand-node、rand、rand-prover 及 SHA256SUMS,均在一台機群主機上構建,未經簽署。Chain 20 必須使用此版本:其創世文件包含任何較早構建都無法讀取的欄位(testnet、binding_domain、proof_window_blocks、program_state、橋接的 rotation 與 fees 組別、gas 上限,以及由投票決定的質押准入),而且 v0.6.8 帶有舊版節點未有運行的共識變更。證明仍然在約束集 8 下生成,與 chain 18 和 19 相同;每個 bundle 仍然在其 bundle 證明之外附帶一個授權證明(自 chain 17 起採用拆分授權),因此創世文件鎖定相同的兩個 guest:bundle guest v3(hc_bundle 60af094a…)與 auth guest(hc_auth 1e4e347f…)。創世文件亦包含 gas 部分、hardening_v6 與 envelope_bytes。v0.6.8 構建會在 run 與 verify 時按哈希拒絕 chain 14、15、16 和 17 的創世文件;它仍可運行 chain 19 的創世文件。每個節點均須使用機群的構建版本。
Chain 20:全停式硬分叉
Chain 20 於 2026-10-01 06:17 UTC 上線。它取自 chain 19 的快照,並以全停全啟方式推出:每個 chain-19 節點均在區塊高度 7,700 停止,所有節點隨後以 v0.6.8 在 chain 20 上啟動。這並非滾動更新,原因有二。其一,chain 20 是新的創世,與 chain 19 沒有任何共用區塊。其二,v0.6.8 帶有來自審計 v6 的共識變更,絕不可逐個節點滾動升級:CON-4 取消驗證者鎖定的自動釋放,CH-1 則加入超時證書 pacemaker。全部 26 名驗證者、其密鑰、peer id 與 bootstrap 均已沿用;法定人數仍為 26 個中的 18 個。Chain 19 與 18 已停用。
因此,將節點由 chain 19 遷移至 chain 20,需要新的二進制文件、新的創世文件及全新的數據目錄,步驟如下。錢包需要 v0.6.8 才能在 chain 20 上發送交易:其創世文件將每個證明和每條已簽署訊息綁定至其哈希(binding_domain: 1),而舊版錢包並不這樣做。
密鑰
rand-node keygen --out node.key.json # prints the address
rand-node address --key node.key.json # address, public key, libp2p peer id
該文件的格式為 { "seed", "address", "public_key" },權限為 0600;只有 seed 屬機密。觀察節點同樣需要密鑰,它是 p2p 身份。節點密鑰不是錢包密鑰:錢包請使用 rand keygen。
請自行生成密鑰,並將其存放在檢出目錄之外。fullnode 倉庫已不再追蹤任何密鑰(審計 v3,OPS-1):曾為 chain 8 至 13 提交的 deploy/node-*.key.json 與 deploy/payout/*.key.json 文件,其 seed 已屬公開,切勿使用。Chain 20 的驗證者密鑰是在倉庫以外生成的,從未存在於倉庫之中:其 26 名創世驗證者,是為 chain 14 生成的十八個密鑰,加上在 chain 15 上綁定質押的八個,並於其後每次切換中沿用。
自 v0.6.8 起,rand-node keygen 會拒絕已存在的 --out 文件;v0.6.7 則會不經詢問直接覆寫。該文件是 seed 的唯一副本。請在任何綁定質押依賴它之前先作備份。
由創世文件初始化
同一條鏈上的每個節點都需要字節完全相同的創世文件;rand-node init 會將其複製到數據目錄並印出其哈希,chain 20 的哈希必須為 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135。該文件為 deploy/genesis-chain20.json(sha256 0020247a…3a21)。它隨啟動記錄一同提交至 fullnode 的 main(提交 74cfaca0),時間在標籤之後,因此檢出 v0.6.8 時並不包含它:請由 main 取得。
git -C fullnode show origin/main:deploy/genesis-chain20.json > genesis-chain20.json
rand-node init --datadir ./data-6210cf07 --genesis genesis-chain20.json
這會建立 <datadir>/db(RocksDB),內含區塊 0、作為樹的首批葉子的九張創世票據(七張 RAND 票據,載有 chain 19 的營運方錢包共 5,184.243719258 RAND;以及兩張 zUSD 票據,分別為 10 與 89 zUSD,即鎖定於橋接託管中的 99 zUSD),以及驗證者登記冊。以相同創世文件重新運行不會有任何影響;不同的創世文件則會被拒絕(already initialized with a different genesis 表示該 datadir 屬於另一條鏈)。請按機群的做法,以創世哈希的前八個字符為數據目錄命名(data-<name>-6210cf07),以免與 chain 19 的(-a3defc93)相沖突。
創世文件的結構如下:
{
"chain_id": 20,
"timestamp_ms": 1790835251661,
"validators": [ { "public_key": "<hex>", "stake": 1000000000000, "payout": "rand1…" } ],
"alloc": [ { "cm": "<64 hex>", "envelope": { "kem_ct": "…", "to_receiver": "…", "to_sender": "…", "body": "…" }, "amount": 1000000000000,
"opening": { "pk": "<64 hex>", "time": 0, "r": "<64 hex>" } },
{ "cm": "…", "envelope": { … }, "amount": 1000000000,
"opening": { "pk": "<64 hex>", "time": 0, "r": "<64 hex>", "asset": 1 } } ],
"faucet": true,
"confidential": true,
"fri_profile": "production",
"hc_bundle": "60af094acfe65d85fdb18fb3d06cf9085dcf28c96e59e87f1ee527226e6e3fce",
"bridge": { "emitter": "<64 hex>", "guardians": [ "<40 hex>" ], "emitters": { "2": "<64 hex>", "3": "…", "4": "…", "5": "…" },
"pq_guardians": [ "<hex>" ], "pause_key": "<hex>",
"rules_v2": { "global_mint_cap_per_window": 400000000000, "cap_window_secs": 86400 },
"guardian_set_index": 1, "burn_sequence": 13,
"min_inbound_sequence": { "2": 3, "3": 3, "4": 3, "5": 7 },
"rotation": { "delay_secs": 86400, "needs_possession": true },
"fees": { "mint_bps": 10, "burn_bps": 10, "recipient": "rand1…" } },
"tokens": { "registration_fee": 1000000000, "mint_cap_per_day": 10000000000000,
"tokens": [ { "name": "Shielded USD", "symbol": "zUSD", "salt": "<64 hex>",
"backings": [ { "chain": 2, "token": "<64 hex>", "decimals": 6 }, … ] } ],
"max_tokens": 4096, "burn_registration_fee": true, "bound_note_value": true },
"consensus_domain": 1,
"staking": { "faucet_budget_per_epoch": "10000000000000", "bond_activation_epochs": 2,
"max_weight_bps": 3333, "registration_v2": true,
"faucet_recipients": [ "rand1…" ], "faucet_minters": [ "<validator address>" ],
"max_stake_entry_bps_per_epoch": 2500, "admission_by_vote": true },
"epoch_blocks": 1000,
"max_program_words": 65535,
"max_proof_bytes": 4194304,
"max_block_bytes": 20971520,
"max_call_envelope_bytes": 65536,
"max_program_public_words": 32768,
"envelope_bytes": 1860,
"hardening_v6": true,
"hc_auth": "1e4e347f44cf86750b30a9a4bdf9ec9256efe353d4ff8017451eca7d195639c1",
"gas": { "gas_price": "100", "byte_price": "800", "bundle_gas_limit": 20479, "metering": "circuit",
"dynamic": { "target_block_bytes": 10485760, "target_block_gas": 262144,
"adjust_bps": 1250, "min_gas_price": "100", "min_byte_price": "800",
"max_gas_price": "10000", "max_byte_price": "80000", "byte_load": "paying" } },
"testnet": true,
"binding_domain": 1,
"proof_window_blocks": 1024,
"program_state": { "cell_fee": 10000000 }
}
每個欄位都包含在創世哈希之內。hc_bundle 鎖定每個 bundle 證明所對照檢驗的 bundle guest,hc_auth 則鎖定每個授權證明所對照檢驗的 auth guest;若節點的構建所組裝的 guest 不同,它會拒絕啟動,並列出兩個摘要。五個 max_* 欄位為可選,僅在存在時才會納入哈希;chain 20 五個全部設定。max_proof_bytes 為 4 MiB,而 chain 13 至 16 為 8 MiB:自 chain 17 起,一筆交易可攜帶三個證明(bundle、授權、call),而帶有 hc_auth 的創世文件,其 max_block_bytes 必須至少為 max_proof_bytes 的三倍加 1 MiB。每張 alloc 票據都附有其 opening(pk、time、r,代幣票據另有 asset),因此創世票據的擁有者與數額按設計是公開的。Chain 20 包含:
bridge部分:索引 1 的守護者集合 1,共八名守護者;來源鏈 2、3、4 和 5 的 emitter(沿用 chain 19);八個 Dilithium2pq_guardians;一個pause_key;burn_sequence為 13;min_inbound_sequence對來源鏈 2、3 和 4 為 3,對來源鏈 5 為 7;以及rules_v2(每 24 小時窗口全局鑄造上限為 4,000 zUSD)。Chain 20 的新增項目:rotation,據此 PQ 守護者或 pause-key 的輪換須由新密鑰提供持有證明,並在提交後 86,400 秒生效;以及fees,據此鏈會將每筆存入的 10 bps 及每筆銷毀的 10 bps,以 zUSD 票據形式收取至一個國庫地址,因此存入會記入扣除費用後的數額,而銷毀則釋出扣除費用後的數額;tokens部分:1 RAND 的登記費,予以銷毀而非支付予提議者;每個支持資產每日 100,000 枚代幣的mint_cap_per_day(八位小數);4,096 枚代幣的登記冊上限;2^63 的票據價值上限;以及在創世時列出的 zUSD,連同其七個支持資產,鎖定 99 zUSD(Ethereum USDT 22、BSC USDT 22、Tron USDT 30、Solana USDT 25),對應兩張創世 zUSD 票據;consensus_domain: 1:每個共識簽名都綁定至此創世文件(共識);staking部分:水龍頭許可名單涵蓋 16 個錢包及 18 個鑄造驗證者密鑰,每個 epoch 預算為 10,000 RAND,兩個 epoch 的綁定質押延遲,3,333 bps 的權重上限,以及 v2 登記,與 chain 19 相同;chain 20 的新增項目為admission_by_vote(新的驗證者密鑰須待驗證者集合投票通過後才可登記),以及每個 epoch 邊界按活躍權重 2,500 bps 計算的准入預算,而 chain 19 為固定的 10,000 RAND(質押)。沒有slashing;gas部分:call 須為其證明所聲明的 gas 上限及其字節付費,價格起步為每 gas 100 單位及每 KiB 800 單位,並在每個區塊後按其飽和度相對於 10,485,760 字節和 262,144 gas 的目標而調整,每個區塊最多調整 1,250 bps,不會低於起步價格,而 chain 20 新增的是不會高於 10,000 與 80,000。只有需要支付字節價格的字節,即 call 的證明與輸入信封,才計入字節價格的負載(byte_load: "paying")。每個 bundle 證明都聲明相同的上限 20,479(費用);envelope_bytes: 1860:每個票據信封恰好為 1,860 字節,並載有加密備註欄位;hardening_v6: true,即 v0.6 加固開關,自 chain 16 起每條鏈均已設定;testnet: true,此標記讓水龍頭得以與橋接部分並存;binding_domain: 1:每筆交易的證明及每條已簽署的操作訊息都包含創世哈希,因此為某條鏈所證明或簽署的內容,不會在另一條鏈上通過驗證;proof_window_blocks: 1024:bundle 的錨點可以是最近 1,024 個區塊結尾根之一,其time可落後於區塊高度最多 1,024 個區塊(chain 19 為 256),讓緩慢或受委託的證明者有約二十分鐘的時間;program_state,RPL-2:程序 cell、程序保險庫及Invoke操作,每次 invoke 所建立的每個 cell 收取 0.1 RAND 的 cell 費用(上限請見 JSON-RPC)。
它沒有 aggregation 部分,而若創世文件包含該部分,構建版本會拒絕啟動。
timestamp_ms 是鏈的時鐘起點。自行製作創世區塊時,請把該值設定為接近實際啟動的時間,且切勿晚於啟動時間。若設得過早,區塊時間會落後於實際時間,直至每區塊 60 秒的步進上限讓它追上為止。若比實際時間晚超過 15 秒,區塊 1 根本無法提交:包括領導者在內,所有投票都會被扣起,直至實際時間到達創世時間戳為止。請以啟動節點集群的那部機器的時鐘為準進行核對,而非以製作該檔案的機器為準。
運行
rand-node run --datadir ./data --key node.key.json \
--listen /ip4/0.0.0.0/tcp/30303 --rpc 127.0.0.1:8545 --no-mdns \
--bootstrap /ip4/164.90.239.200/tcp/30303/p2p/12D3KooWEQEbUwZRgqhDPXhW7vNBmcRcnhUDGUADe81VFdv3ALYe \
--bootstrap /ip4/165.245.173.74/tcp/30303/p2p/12D3KooWJyc5oDHggAr89e9QrRFBy9Tg8TxXh18yzrb1SM6KKLYw \
--bootstrap /ip4/188.166.235.187/tcp/30303/p2p/12D3KooWSyX84P1DAbWByLHpRBMLRWD53r3Jj4aqVt6tHoF8B2ZQ
| 參數 | 預設值 | 含義 |
|---|---|---|
--datadir | 必填 | 已初始化的資料目錄 |
--key | 必填 | 密鑰檔案:驗證者身份、p2p 身份、費用收款方 |
--listen | /ip4/0.0.0.0/tcp/30303 | libp2p 監聽 multiaddr,可重複指定 |
--bootstrap | 無 | 啟動時以及斷線期間每 30 秒撥接一次的對等節點,可重複指定 |
--rpc | 127.0.0.1:8545 | 營運者的 JSON-RPC 與 WebSocket 監聽器:支援所有方法,並信任迴環位址。請保持綁定在迴環位址,切勿把公開端點轉發至此 |
--public-rpc <ADDR> | 關閉 | v0.6.8:供反向代理或 SSH 轉發指向的第二個公開監聽器:方法集固定,不含檢視密鑰方法、rand_mint 或 rand_getPeers,不支援批次請求與 WebSocket,所有調用者共用同一計量器(JSON-RPC) |
--rpc-viewing-token-file <PATH> | 關閉 | v0.6.8:要求 --rpc 的檢視密鑰方法須附帶 bearer 令牌(檔案首行,32 個字元或以上) |
--reserved-peer <PEER_ID> | 無 | v0.6.8,可重複指定:獲准越過入站連線上限的對等節點;參閱保留對等節點 |
--strict-gossip | 關閉 | v0.6.8:只接受附有效作者簽名、序號及來源的 gossip;可逐個節點滾動啟用 |
--validator | 關閉 | 此節點持有驗證者密鑰,而當其密鑰在現行驗證者集合內時參與共識 |
--no-mdns | 關閉 | 停用區域網絡發現;建議在伺服器上使用 |
--block-interval-ms | 1000 | 兩次提案之間的最短間隔 |
--view-timeout-ms | 3000 | 基本視圖逾時,每連續逾時一次即加倍,上限為 8 倍 |
--verify-chain | quick | 啟動時的完整性檢查:off、quick(結構與賬本重放)、full(另加每個簽名與 QC) |
--keep-raw-proofs | 關閉 | 區塊聚合的存檔模式;對鏈 20 無效 |
--prune-history | 關閉(保留全部) | 保留賬本,並只保留這段時間內的區塊歷史:<n>m、<n>h 或 <n>d,至少 1h。testnet 的驗證者均以 24h 運行,兩個存檔節點除外;參閱歷史修剪 |
--min-free-disk-mb | 1024 | 資料目錄所在檔案系統的可用空間少於此值時拒絕啟動;可用空間低於此值的四倍時,rand_getHealth 回應 disk_low。0 表示停用此保護 |
--prover <ADDR> | 關閉 | 在此地址上託管委託 prover,屬獨立的監聽器,絕非 RPC;參閱下文 |
--gas-price, --byte-price | 100, 800 | 在沒有 gas 區段的鏈上,交易池對一次調用所設的價格下限。鏈 20 的創世區塊自行設定價格,因此節點在該鏈上會忽略這兩個旗標並記錄一則警告 |
--prover-accept-spend-key 已停用:v0.6.8 節點若獲傳入此參數便會拒絕啟動,因此請從沿用自 v0.6.7 的任何 unit 檔案中移除。
上述三個 bootstrap 是驗證者 C、D 和 E,與鏈 19 相同。鏈 20 使用為鏈 14 生成的驗證者密鑰運行,因此其 peer id 與鏈 14 所用的相同;p2p 身份由驗證者密鑰推導而來。大部分驗證者只保留一日的區塊,因此從創世區塊開始同步的節點,或落後超過一日的節點,同樣需要一個保存完整歷史的對等節點。請加入兩個存檔節點其中之一:
--bootstrap /ip4/168.144.46.203/tcp/30303/p2p/12D3KooWS5usdMPvsbaWSaT2xtKndHvDYurwmueoNvaRRarb2wRf # obs1
--bootstrap /ip4/206.81.29.236/tcp/30303/p2p/12D3KooWPocyZGcNB9Vp68VSfgVvNXhSzBBoJa4h9R1yMkp71XHh # rand-archive-2
省略 --validator 即以觀察者身份運行。啟動流程:開啟儲存、對照創世區塊的 hc_bundle 與 hc_auth 檢查此版本的 guest、執行完整性檢查(截去受損的尾部並保留投票安全狀態)、由已持久化的鏈頭恢復共識、啟動網絡與 RPC,然後向任何領先的對等節點同步。RUST_LOG 預設為 info,libp2p=warn,libp2p_mdns=off;Ctrl-C 或 SIGTERM(systemd 的停止信號)會令節點正常關閉。以同一個 --datadir 重新啟動,會由已持久化的鏈頭繼續。
來自 fullnode 的拓撲規則:位於 NAT 後的節點向擁有公開地址的節點主動撥接;公開節點須開放 TCP 30303 入站;除非已設防火牆,否則請把 RPC 綁定到 127.0.0.1——任何能連到它的人都可以向它提交交易,而一旦把檢視密鑰匯入其中,便應將該埠視為持有密鑰。請把 --block-interval-ms 維持在 1000 或更慢:一個 bundle 證明約需兩分鐘,而其錨點在鏈 20 上的有效期為 1,024 個區塊(鏈 19 為 256 個)。
驗證者需要同步的時鐘。 自鏈 14 起,實際時間已成為共識的一部分(橋接加固 B2)。區塊的時間戳若比其父區塊晚超過 60 秒即屬無效,而當區塊的時間戳比驗證者自身時鐘快超過 15 秒時,該驗證者會扣起其投票。因此,時鐘走慢的驗證者會停止投票,而且不會記錄任何錯誤;在鏈 20 上,26 個驗證者中須有 18 個投票才能提交。請在每個驗證者上運行 NTP,並在啟動節點前先行檢查:
timedatectl # want "System clock synchronized: yes" and "NTP service: active"
chronyc tracking
apt-get install -y chrony && systemctl enable --now chrony # if it is not synchronised
保留對等節點
自 v0.6.8 起,節點最多接受 256 個已建立及 64 個半開的入站連線,而生成 libp2p 身份毫無成本,因此陌生人可佔滿所有名額。三類對等節點屬保留:它們獲准越過上限,並由驗證者所佔的同步預算提供服務,分別是每個 --bootstrap 對等節點、每個 --reserved-peer,以及從已簽署的 peer 綁定中得知的每個驗證者身份。每個 --validator 節點以其驗證者密鑰為 libp2p 身份簽名並以 gossip 廣播;節點若從驗證者集合中得知該密鑰,便會保留該對等節點,並在重新啟動後保留這項記錄。新製作的鏈,其儲存不含任何綁定,因此在首批公告抵達之前,只有前兩類屬保留:製作新鏈時,請以 --reserved-peer 傳入集群的驗證者 peer id,或把它們保留在 bootstrap 列表中(rand-node address --key <file> 會印出某密鑰的 peer id)。rand_status.reserved_peers 會統計它們;在集群節點上,它應於啟動後一分鐘內達到驗證者數目。
檢查
rand-node status # rand_status verbatim
rand --rpc http://127.0.0.1:8545 status
rand peers
rand_status 會回報 height、view、syncing、sync_target、peer_count、connected_peers、reserved_peers、mempool_size、is_validator、active_validator、faucet、confidential、testnet、fri_profile、programs、notes、nullifiers、tree_root、hc_bundle、hc_auth、binding_domain、gas_prices、節點的 address 和 peer_id,以及同步診斷資料(sync_inflight_age_ms、sync_failures、sync_late_batches)、磁碟狀況(disk_free_bytes、disk_low)和保留下限(prune_floor,保留全部歷史的節點為 0;prune_history_secs,未設定時為 null)。在鏈 20 上,預期 hc_bundle 60af094a…、hc_auth 1e4e347f…、faucet true、confidential true、testnet true、binding_domain 1、fri_profile "production",而 gas_prices 介乎每 gas 100 至 10,000,以及每 KiB 800 至 80,000。rand_getGenesisHash 必須回應 6210cf07…5135,rand_getVersion 則回應 0.6.8。
當可用空間低於 --min-free-disk-mb 的四倍時,rand_getHealth 會在 ok、syncing 或 behind 之前先回應 disk_low(連同 free_bytes)。
歷史修剪
以 --prune-history 24h 啟動的節點會完整保留賬本(note、nullifier、錨點、驗證者登記冊、程式),並刪除較舊的區塊、其證書、交易及收據。每提交 16 個區塊執行一次修剪,每次最多刪除 512 個早於「鏈頭時間戳減去時間窗口」的區塊;創世區塊、鏈頭及其父區塊絕不會被刪除,而下限只會上升。待 RocksDB 壓縮後,磁碟空間才會釋出。在鏈 20 上,一如鏈 19,26 個驗證者中有 24 個以 24h 運行,保存約一日的區塊。鏈 14 於 2026-09-25 啟用修剪時,待積壓清理完畢,每個驗證者的區塊表由 19 GB 降至 3.3–4.4 GB;另外兩個節點 obs1 和 rand-archive-2 自 2026-09-27 起亦是驗證者,它們不帶此旗標運行,保留全部歷史。mainnet 節點絕不可傳入此旗標。
在已修剪的節點上,以高度尋址、且低於下限的查詢(rand_getBlockByHeight、按高度查詢的 rand_getFinality,或範圍觸及下限的 rand_getBlocks 或 rand_getCompactBlocks)會回應錯誤 -32010 及 data.floor:請向存檔節點查詢。以雜湊尋址的查詢,若節點已不再持有該區塊,則回應 null,與從未存在過的區塊相同。錢包掃描不受影響,因為 note 和 nullifier 絕不會被修剪。
已修剪節點的啟動檢查屬結構性檢查(區塊 0 與保留的區塊、其 QC、父區塊連結及領導者),而非由創世區塊起重放,並且不會自行修復:若檢查失敗,請從存檔節點重新同步。除非以 --verify-chain off 運行,否則切勿用早於 v0.5.7 的版本開啟已修剪的資料目錄:其預設檢查會由創世區塊起重放,發現區塊 1 缺失,並把賬本截斷至創世區塊。
託管 prover
在鏈 20 上,錢包為每個 bundle 製作兩個證明,較大的一個需要約 6 GB 記憶體。無法容納該證明的錢包,可把它交給與之配對的委託 prover:獨立的 rand-prover 二進位檔,或由節點託管的同一項服務。
rand-prover --home /root/prover keygen
rand-prover --home /root/prover pair --name laptop --url https://prover.example.net
rand-node run --datadir ./data --key node.key.json --prover 127.0.0.1:8600 --prover-home /root/prover
pair 會列印一條 randprover: 連結。錢包以 rand prover pair <link> 接收該連結,其後透過全域選項 --prover 經由該 prover 進行證明。prover 的監聽器是獨立的,絕不屬於 RPC 的方法:位址與 --rpc 相同者會被拒絕。使用 --prover 時,除非 <prover-home>/prover.key.json 存在(預設為 <datadir>/prover),並且每個證明槽位有 5.74 GB 加上 1 GiB 的可用記憶體,否則節點拒絕啟動;--prover-max-parallel 設定槽位數目,預設為一個。
在 chain 20 上,prover 收到的是錢包的 viewing key 和一個全新的 salt,而不是 spend key。授權證明由錢包自行以 spend key 生成,因此已配對的 prover 可以讀取該錢包的全部歷史,卻無法花費。除非前面設有終結 TLS 的代理,否則請讓監聽器保持在 loopback;亦不要把它部署在提供公共 RPC 的機器上。停止時會等待正在進行的證明完成,因此請為 systemd unit 設定 TimeoutStopSec=180。
驗證與修復
rand-node verify --datadir ./data # full: hashes, QCs, signatures, proofs, ledger replay, the supply counters
rand-node verify --datadir ./data --mode quick # structure and ledger replay
rand-node verify --datadir ./data --repair # truncate a damaged tail; peers resync the rest
請先停止節點。若狀態一致,結束碼為 0;若發現問題而未指定 --repair,結束碼為 2。重放會重新驗證每個 bundle 的證明,因此若某個構建的約束集與產生該鏈的約束集不同,便會在第一個 bundle 停下。
成為驗證者
驗證者透過綁定質押加入運行中的鏈,而不是透過新的創世區塊:以 --validator 啟動節點,用 rand-node register --key node.key.json --payout <rand1…> --v2 列印註冊資料(chain 20 拒絕 v1 註冊),由錢包以 rand bond <address> 1000 --registration <hex> 綁定至少 1,000 RAND,待綁定生效後節點便會提出區塊:在 chain 20 上,最早要在綁定後經過三個 1,000 個區塊的 epoch 邊界。在 chain 20 上,綁定是第二步。其創世區塊設定了 staking.admission_by_vote,因此註冊新密鑰的綁定會被拒絕,直至持有超過三分之二投票權重的驗證者投票接納該密鑰:每位驗證者以 rand-node admit sign --candidate <key or registration> --key <validator key> --genesis-hash 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135 簽署,其中一位再以 rand-node admit submit 提交投票(Command line)。rand_getAdmitted 會列出已獲投票接納但尚未註冊的密鑰。在同一個 epoch 邊界,新增的權重不得超過活躍權重的 2,500 bps。Staking 有完整的逐步說明。若要建立私人測試鏈,可用 rand-node genesis 生成:
rand-node genesis --chain-id 88 \
--validator a.key.json,1000,rand1<a's payout address> \
--validator <hex public key of b>,1000,rand1<b's payout address> \
--alloc rand1<address>=1000 \
--epoch-blocks 1000 --faucet --fri-profile production \
--out genesis.json
而 scripts/local-testnet.sh 會在同一部機器上運行兩個驗證者,RPC 分別在 8545 和 8546。若不加其他旗標,創世區塊不含 hc_auth、gas 區段和 memo。Chain 20 是在此基礎上加上 --hardening-v6 --bundle-guest v3 --auth-guest --gas-price 100 --byte-price 800 --bundle-gas-limit 20479 --gas-dynamic 10485760,262144,1250 --max-gas-price 10000 --max-byte-price 80000 --gas-byte-load paying --envelope-bytes 1860 --testnet --binding-domain 1 --proof-window-blocks 1024 --program-state-cell-fee 10000000 生成的(chain 18 和 19 的旗標只到 --envelope-bytes),其 bridge 和 staking 區段以及 consensus_domain 由切鏈腳本拼接而成。你自己的新鏈應傳入 --binding-domain 1:v0.6.8 錢包會在 14 至 19 以外的每個 chain id 上生成與創世區塊綁定的形式。
在伺服器上部署
儲存庫的 deploy/ 目錄存放著機群所用的腳本:deploy/push-to-vps.sh <ip> <letter> "<bootstraps>" [validator|observer] 會佈建一部 Linux 伺服器(以 rsync 同步源碼、構建、安裝 /usr/local/bin/{rand-node,rand}、以創世區塊哈希為鍵初始化 datadir、安裝 rand-node systemd 服務),而 deploy/rebuild-vps.sh <ip> 會在有新提交時重新構建並重啟,資料保持不變。有兩點須留意。佈建腳本以 deploy/genesis.json 初始化,而它並非 chain 20 的檔案,因此測試網的節點須以 deploy/genesis-chain20.json 手動設置(在 main 上,見上文)。此外,兩個腳本都以 --delete 對 /root/fullnode 執行 rsync,因此存放在該目錄樹內的密鑰會在下次重新構建時被刪除:請把它存放在 /root/keys,一如機群的做法,v0.6.8 的佈建腳本現在也預設如此(v0.6.7 的會把密鑰寫到 /root/fullnode/deploy/ 之下)。服務管理使用 systemctl status rand-node 和 journalctl -u rand-node -f。伺服器需要 build-essential clang cmake pkg-config libssl-dev 和 Rust 工具鏈。1 vCPU、2 GB 的伺服器無法構建這些二進位檔;請在別處構建再複製過去。Running a validator and an aggregator 載有規格和逐步設置說明。
瀏覽器
randscan.org 與驗證者 E 並行運作,並為 chain 20 建立索引;其 REST API 和 WebSocket 推送是無須節點即可讀取鏈上資料的最簡便方法(Explorer API)。該瀏覽器為開源項目(randprotocol/randscan),其索引器只需要節點的 rand_* JSON-RPC 和 PostgreSQL 資料庫,因此可以針對你自己的節點運行。