Verwenden Sie diese Seite, um einen eigenen rand-node gegen das testnet zu betreiben. Das ist zugleich der empfohlene Weg, eine Wallet privat zu nutzen: Ein Node, den Sie selbst betreiben, erfährt von niemandem außer Ihnen, welches Blatt Sie gleich ausgeben werden. Ein Observer synchronisiert, verifiziert jeden Beweis erneut und stellt die JSON-RPC bereit; ein Validator tut dasselbe und nimmt am Konsens teil, sobald sein Schlüssel in der Menge einer Epoche steht.
Build
Voraussetzungen: Rust 1.98.1 (festgelegt in rust-toolchain.toml; rustup installiert es), ein C++-Compiler und cmake für RocksDB. Die zkVM-Crate hat Pfadabhängigkeiten auf ein danebenliegendes circuits/-Checkout des Repositorys des Beweissystems (randprotocol/zkp-circuits), das neben fullnode/ liegen muss, und zwar an dem Commit, aus dem das Release vendored wurde: die Zeile circuits: in crates/randprotocol-zkvm/guests-compiled/PROVENANCE.md (aeacf31 für v0.6.8, wie für v0.6.7). Der erste Build dauert 10 bis 20 Minuten.
git clone https://github.com/randprotocol/fullnode
cargo build --release # target/release/rand-node, target/release/rand, target/release/rand-prover
Betreiben Sie v0.6.8 (git checkout v0.6.8, Commit c9c9bd3c, ist das Release, das die Flotte betreibt; rand_getVersion meldet den sha eines Nodes). Das zugehörige GitHub-Release enthält rand-node, rand, rand-prover und SHA256SUMS, auf einem Flotten-Host gebaut und unsigniert. Chain 20 setzt es voraus: Ihr Genesis enthält Felder, die kein früherer Build liest (testnet, binding_domain, proof_window_blocks, program_state, die Bridge-Gruppen rotation und fees, die Gas-Obergrenzen und die Staking-Zulassung per Abstimmung), und v0.6.8 bringt Konsensänderungen mit, die ein älterer Node nicht ausführt. Beweise werden weiterhin unter Constraint-Set 8 erzeugt, wie auf den Chains 18 und 19, und jedes Bundle trägt weiterhin neben seinem Bundle-Beweis einen Autorisierungsbeweis (geteilte Autorisierung, seit Chain 17); das Genesis legt daher dieselben zwei Guests fest: Bundle-Guest v3 (hc_bundle 60af094a…) und den Auth-Guest (hc_auth 1e4e347f…). Das Genesis enthält außerdem einen Abschnitt gas, hardening_v6 und envelope_bytes. Ein v0.6.8-Build weist die Genesis der Chains 14, 15, 16 und 17 bei run und bei verify anhand des Hashs ab; die von Chain 19 kann er noch ausführen. Jeder Node nutzt den Build der Flotte.
Chain 20: ein Hard Fork mit Gesamtstopp
Chain 20 ging am 2026-10-01 um 06:17 UTC live. Sie wurde aus einem Snapshot von Chain 19 geschnitten und als Gesamtstopp mit Gesamtstart eingeführt: Jeder Node von Chain 19 wurde bei Höhe 7.700 angehalten, und jeder Node wurde mit v0.6.8 auf Chain 20 gestartet. Es war kein rollierendes Update, aus zwei Gründen. Chain 20 ist ein neues Genesis, es gibt also keinen Block, den sie mit Chain 19 teilt. Und v0.6.8 bringt Konsensänderungen aus Audit v6 mit, die niemals Node für Node ausgerollt werden dürfen: CON-4 entfernt die automatische Freigabe der Sperre eines Validators, und CH-1 fügt einen Pacemaker mit Timeout-Zertifikaten hinzu. Alle 26 Validatoren, ihre Schlüssel, Peer-IDs und Bootstraps wurden übernommen; ein Quorum bleibt 18 von 26. Die Chains 19 und 18 sind stillgelegt.
Einen Node von Chain 19 auf Chain 20 umzustellen erfordert daher die neue Binärdatei, die neue Genesis-Datei und ein frisches Datenverzeichnis, wie unten beschrieben. Wallets benötigen v0.6.8, um auf Chain 20 zu senden: Ihr Genesis bindet jeden Beweis und jede signierte Nachricht an seinen Hash (binding_domain: 1), was eine ältere Wallet nicht tut.
Schlüssel
rand-node keygen --out node.key.json # prints the address
rand-node address --key node.key.json # address, public key, libp2p peer id
Die Datei hat die Form { "seed", "address", "public_key" }, Modus 0600; nur der Seed ist geheim. Auch ein Observer braucht einen Schlüssel – er ist die p2p-Identität. Ein Node-Schlüssel ist kein Wallet-Schlüssel: Verwenden Sie für eine Wallet rand keygen.
Erzeugen Sie Ihren eigenen Schlüssel und bewahren Sie ihn außerhalb des Checkouts auf. Das Fullnode-Repository enthält keinen Schlüssel mehr (Audit v3, OPS-1): Die Dateien deploy/node-*.key.json und deploy/payout/*.key.json, die für die Chains 8 bis 13 eingecheckt waren, sind veröffentlichte Seeds und dürfen nicht verwendet werden. Die Validator-Schlüssel von Chain 20 wurden außerhalb des Repositorys erzeugt und waren nie darin: Ihre 26 Genesis-Validatoren sind die achtzehn für Chain 14 erzeugten Schlüssel und die acht, die auf Chain 15 gebondet wurden, bei jedem Schnitt seither übernommen.
Seit v0.6.8 verweigert rand-node keygen eine --out-Datei, die bereits existiert; v0.6.7 überschrieb sie ohne Rückfrage. Die Datei ist die einzige Kopie des Seeds. Sichern Sie sie, bevor ein Bond von ihr abhängt.
Aus dem Genesis initialisieren
Jeder Node einer Chain braucht die byte-identische Genesis-Datei; rand-node init kopiert sie in das Datenverzeichnis und gibt ihren Hash aus, der für Chain 20 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135 lauten muss. Die Datei ist deploy/genesis-chain20.json (sha256 0020247a…3a21). Sie wurde zusammen mit dem Launch-Protokoll (Commit 74cfaca0) nach dem Tag in den main des Fullnodes committet, ein Checkout von v0.6.8 enthält sie daher nicht: Holen Sie sie aus main.
git -C fullnode show origin/main:deploy/genesis-chain20.json > genesis-chain20.json
rand-node init --datadir ./data-6210cf07 --genesis genesis-chain20.json
Dies legt <datadir>/db (RocksDB) an, mit Block 0, den neun Genesis-Notes als ersten Blättern des Baums (sieben RAND-Notes mit 5.184,243719258 RAND an Operator-Wallets aus Chain 19 und zwei zUSD-Notes über 10 und 89 zUSD, die 99 zUSD, die in der Verwahrung der Bridge gesperrt sind) und dem Validator-Register. Ein erneuter Lauf mit demselben Genesis bewirkt nichts; ein abweichendes Genesis wird abgelehnt (already initialized with a different genesis bedeutet, dass das Datenverzeichnis zu einer anderen Chain gehört). Benennen Sie das Datenverzeichnis nach den ersten acht Zeichen des Genesis-Hashs, wie es die Flotte tut (data-<name>-6210cf07), damit es nie mit dem von Chain 19 (-a3defc93) kollidiert.
Die Form der Genesis-Datei:
{
"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 }
}
Jedes Feld fließt in den Genesis-Hash ein. hc_bundle legt den Bundle-Guest fest, gegen den jeder Bundle-Beweis geprüft wird, und hc_auth den Auth-Guest, gegen den jeder Autorisierungsbeweis geprüft wird; ein Node, dessen Build einen anderen Guest zusammensetzt, startet nicht und nennt beide Digests. Die fünf max_*-Felder sind optional und werden nur dann in den Hash einbezogen, wenn sie vorhanden sind; Chain 20 setzt alle fünf. max_proof_bytes beträgt 4 MiB, wo die Chains 13 bis 16 8 MiB hatten: Seit Chain 17 kann eine Transaktion drei Beweise tragen (Bundle, Autorisierung, Call), und ein Genesis mit hc_auth muss für max_block_bytes mindestens das Dreifache von max_proof_bytes plus 1 MiB haben. Jede Alloc-Note trägt ihr opening (pk, time, r und bei einer Token-Note asset), sodass Eigentümer und Betrag einer Genesis-Note absichtlich öffentlich sind. Chain 20 hat:
- einen Abschnitt
bridge: Guardian-Set 1 bei Index 1 mit acht Guardians, Emittenten für die Quellchains 2, 3, 4 und 5 (die von Chain 19), acht Dilithium2-pq_guardians, einenpause_key,burn_sequence13, einemin_inbound_sequencevon 3 für die Quellchains 2, 3 und 4 und von 7 für die Quellchain 5 sowierules_v2(eine globale Mint-Obergrenze von 4.000 zUSD je 24-h-Fenster). Neu auf Chain 20:rotation, wonach eine Rotation von PQ-Guardians oder Pause-Key einen Besitznachweis der neuen Schlüssel erfordert und 86.400 s nach ihrem Commit wirksam wird; undfees, wonach die Chain 10 bps jeder Einzahlung und 10 bps jeder Burn-Transaktion als zUSD-Note an eine Treasury-Adresse behält, sodass eine Einzahlung den Bruttobetrag abzüglich der Gebühr gutschreibt und ein Burn seinen Betrag abzüglich der Gebühr freigibt; - einen Abschnitt
tokens: eine Registrierungsgebühr von 1 RAND, die verbrannt statt an den Proposer gezahlt wird; einmint_cap_per_dayvon 100.000 Token je Backing bei acht Dezimalstellen; eine Registry-Obergrenze von 4.096 Token; die Wertgrenze von 2^63 für Notes; und zUSD, zum Genesis gelistet mit seinen sieben Backings, 99 zUSD gesperrt (Ethereum USDT 22, BSC USDT 22, Tron USDT 30, Solana USDT 25) gegen die beiden zUSD-Genesis-Notes; consensus_domain: 1: Jede Konsenssignatur ist an dieses Genesis gebunden (Consensus);- einen Abschnitt
staking: der Faucet ist auf 16 Wallets und auf 18 minting-fähige Validator-Schlüssel auf der Allowlist, mit einem Budget von 10.000 RAND je Epoche, einer Bond-Verzögerung von zwei Epochen, einer Gewichtsobergrenze von 3.333 bps und v2-Registrierungen, wie auf Chain 19; neu auf Chain 20:admission_by_vote(ein neuer Validator-Schlüssel registriert sich erst, nachdem die Validator-Menge ihn hineingewählt hat) und ein Eintrittsbudget von 2.500 bps des aktiven Gewichts je Epochengrenze, wo Chain 19 feste 10.000 RAND hatte (Staking). Es gibt keinslashing; - einen Abschnitt
gas: Ein Call zahlt für das Gas-Limit, das sein Beweis deklariert, und für seine Bytes, zu Preisen, die bei 100 Einheiten je Gas und 800 Einheiten je KiB beginnen und sich nach jedem Block mit seiner Auslastung gegenüber einem Ziel von 10.485.760 Bytes und 262.144 Gas bewegen, um höchstens 1.250 bps je Block, nie unter die Startpreise und, neu auf Chain 20, nie über 10.000 und 80.000. Nur die Bytes, die einen Byte-Preis zahlen, also der Beweis und die Eingabe-Envelope eines Calls, zählen zur Last des Byte-Preises (byte_load: "paying"). Jeder Bundle-Beweis deklariert dasselbe Limit, 20.479 (Fees); envelope_bytes: 1860: Jede Note-Envelope ist genau 1.860 Bytes groß und enthält ein verschlüsseltes Memo-Feld;hardening_v6: true, den Schalter für die Härtung v0.6, von jeder Chain seit Chain 16 gesetzt;testnet: true, die Markierung, die einen Faucet neben einem Bridge-Abschnitt zulässt;binding_domain: 1: Die Beweise jeder Transaktion und jede signierte Aktionsnachricht enthalten den Genesis-Hash, sodass nichts, was für eine Chain bewiesen oder signiert wurde, auf einer anderen verifiziert;proof_window_blocks: 1024: Der Anker eines Bundles darf eine der letzten 1.024 Block-End-Roots sein und seintimebis zu 1.024 Blöcke hinter der Höhe liegen (256 auf Chain 19), was einem langsamen oder delegierten Prover etwa zwanzig Minuten verschafft;program_state, RPL-2: Programm-Zellen, Programm-Vaults und die AktionInvoke, mit einer Zellgebühr von 0,1 RAND je Zelle, die ein Invoke anlegt (JSON-RPC nennt die Limits).
Es hat keinen Abschnitt aggregation, und der Build startet nicht auf einem Genesis, das einen solchen enthält.
timestamp_ms ist der Nullpunkt der Uhr der Chain. Wenn Sie ein eigenes Genesis erzeugen, setzen Sie ihn nahe an den tatsächlichen Startzeitpunkt und nie davor in der Zukunft. Liegt er zu weit in der Vergangenheit, hinkt die Blockzeit der Wanduhr hinterher, bis die Schranke von 60 s pro Blockschritt sie wieder aufholen lässt. Liegt er mehr als 15 Sekunden in der Zukunft, wird Block 1 überhaupt nicht committet: Jede Stimme, auch die des Leaders, wird zurückgehalten, bis die Wanduhrzeit den Genesis-Zeitstempel erreicht. Prüfen Sie ihn gegen die Uhr der Maschine, die die Flotte startet, nicht gegen die, die die Datei erzeugt hat.
Ausführen
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
| Argument | Standard | Bedeutung |
|---|---|---|
--datadir | erforderlich | das initialisierte Datenverzeichnis |
--key | erforderlich | Schlüsseldatei: Validator-Identität, p2p-Identität, Gebührenempfänger |
--listen | /ip4/0.0.0.0/tcp/30303 | libp2p-Listen-Multiaddr, wiederholbar |
--bootstrap | keiner | Peer, der beim Start und danach alle 30 s im getrennten Zustand angewählt wird, wiederholbar |
--rpc | 127.0.0.1:8545 | der JSON-RPC- und WebSocket-Listener des Betreibers: jede Methode, und er vertraut Loopback. Lassen Sie ihn auf Loopback und leiten Sie nie einen öffentlichen Endpunkt auf ihn weiter |
--public-rpc <ADDR> | aus | v0.6.8: ein zweiter, öffentlicher Listener, auf den ein Reverse-Proxy oder eine SSH-Weiterleitung zeigen kann: ein fester Methodensatz ohne die Viewing-Key-Methoden, rand_mint oder rand_getPeers, keine Batches, kein WebSocket, ein gemeinsames Limit für alle Aufrufer (JSON-RPC) |
--rpc-viewing-token-file <PATH> | aus | v0.6.8: verlangt ein Bearer-Token (die erste Zeile der Datei, mindestens 32 Zeichen) bei den Viewing-Key-Methoden von --rpc |
--reserved-peer <PEER_ID> | keiner | v0.6.8, wiederholbar: ein Peer, der über das Limit für eingehende Verbindungen hinaus zugelassen wird; siehe Reservierte Peers |
--strict-gossip | aus | v0.6.8: akzeptiert nur Gossip mit gültiger Autorensignatur, Sequenznummer und Quelle; wird Node für Node ausgerollt |
--validator | aus | dieser Node hält einen Validator-Schlüssel und nimmt am Konsens teil, sobald sein Schlüssel in der aktuellen Menge steht |
--no-mdns | aus | deaktiviert die LAN-Erkennung; auf Servern empfohlen |
--block-interval-ms | 1000 | Mindestabstand zwischen Vorschlägen |
--view-timeout-ms | 3000 | Basis-View-Timeout, verdoppelt sich je aufeinanderfolgendem Timeout bis auf das 8-Fache |
--verify-chain | quick | Integritätsprüfung beim Start: off, quick (Struktur und Ledger-Replay), full (zusätzlich jede Signatur und jedes QC) |
--keep-raw-proofs | aus | Archivmodus für die Blockaggregation; ohne Wirkung auf Chain 20 |
--prune-history | aus (alles behalten) | behält das Ledger und nur so viel Blockhistorie: <n>m, <n>h oder <n>d, mindestens 1h. Die Validatoren des Testnets laufen mit 24h, außer den beiden Archiven; siehe History-Pruning |
--min-free-disk-mb | 1024 | verweigert den Start bei weniger freiem Speicher im Dateisystem des Datenverzeichnisses; rand_getHealth antwortet disk_low unterhalb des Vierfachen. 0 deaktiviert die Prüfung |
--prover <ADDR> | aus | betreibt einen delegierten Prover unter dieser Adresse, ein eigener Listener und nie der RPC; siehe unten |
--gas-price, --byte-price | 100, 800 | die Preisuntergrenze des Pools für einen Aufruf auf einer Chain ohne gas-Abschnitt. Das Genesis von Chain 20 legt eigene Preise fest, daher ignoriert der Node beide Flags dort und protokolliert eine Warnung |
--prover-accept-spend-key ist abgeschafft: Ein v0.6.8-Node, dem es übergeben wird, verweigert den Start. Entfernen Sie es daher aus jeder Unit-Datei, die von v0.6.7 übernommen wurde.
Die drei oben genannten Bootstraps sind die Validatoren C, D und E, unverändert gegenüber Chain 19. Chain 20 läuft auf den für Chain 14 erzeugten Validator-Schlüsseln, daher sind ihre Peer-IDs dieselben wie auf Chain 14; eine p2p-Identität wird aus dem Validator-Schlüssel abgeleitet. Die meisten Validatoren halten nur einen Tag an Blöcken vor, deshalb braucht ein Node, der ab Genesis synchronisiert oder mehr als einen Tag zurückliegt, zusätzlich einen Peer mit vollständiger Historie. Fügen Sie eines der beiden Archive hinzu:
--bootstrap /ip4/168.144.46.203/tcp/30303/p2p/12D3KooWS5usdMPvsbaWSaT2xtKndHvDYurwmueoNvaRRarb2wRf # obs1
--bootstrap /ip4/206.81.29.236/tcp/30303/p2p/12D3KooWPocyZGcNB9Vp68VSfgVvNXhSzBBoJa4h9R1yMkp71XHh # rand-archive-2
Lassen Sie --validator weg, um einen Observer zu betreiben. Ablauf beim Start: Speicher öffnen, die Guests dieses Builds gegen hc_bundle und hc_auth des Genesis prüfen, die Integritätsprüfung ausführen (ein beschädigtes Ende wird abgeschnitten, der Vote-Safety-Zustand bleibt erhalten), den Konsens ab dem persistierten Head fortsetzen, Netzwerk und RPC starten und dann von jedem Peer synchronisieren, der voraus ist. RUST_LOG ist standardmäßig info,libp2p=warn,libp2p_mdns=off; Strg-C oder SIGTERM, das Stoppsignal von systemd, fährt den Node sauber herunter. Ein Neustart mit demselben --datadir setzt beim persistierten Head fort.
Topologieregeln aus dem Fullnode: Nodes hinter NAT wählen Nodes mit öffentlichen Adressen an; öffnen Sie TCP 30303 eingehend auf öffentlichen Nodes; binden Sie den RPC an 127.0.0.1, sofern er nicht durch eine Firewall geschützt ist — er nimmt Transaktionen von jedem an, der ihn erreicht, und sobald ein Viewing Key in ihn importiert wurde, behandeln Sie den Port als schlüsselführend. Halten Sie --block-interval-ms bei 1000 oder langsamer: Ein Bundle-Proof braucht etwa zwei Minuten, und sein Anchor ist auf Chain 20 für 1.024 Blöcke gültig (auf Chain 19 für 256).
Ein Validator braucht eine synchronisierte Uhr. Seit Chain 14 ist die Wanduhrzeit Teil des Konsenses (Bridge-Hardening B2). Ein Block, dessen Zeitstempel mehr als 60 s nach dem seines Vorgängers liegt, ist ungültig, und ein Validator hält seine Stimme für einen Block zurück, dessen Zeitstempel mehr als 15 s vor der eigenen Uhr liegt. Ein Validator mit zu langsam laufender Uhr hört daher auf zu stimmen, ohne einen Fehler zu protokollieren, und auf Chain 20 müssen sechsundzwanzig Validatoren achtzehn Stimmen für einen Commit abgeben. Betreiben Sie NTP auf jedem Validator und prüfen Sie es, bevor Sie den Node starten:
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
Reservierte Peers
Seit v0.6.8 akzeptiert ein Node höchstens 256 aufgebaute und 64 halboffene eingehende Verbindungen, und eine libp2p-Identität zu erzeugen kostet nichts, sodass Fremde jeden Platz belegen könnten. Drei Arten von Peers sind reserviert, werden über das Limit hinaus zugelassen und aus dem Anteil der Validatoren am Sync-Budget bedient: jeder --bootstrap-Peer, jeder --reserved-peer und jede Validator-Identität, die aus einer signierten Peer-Bindung bekannt ist. Jeder --validator-Node signiert seine libp2p-Identität mit seinem Validator-Schlüssel und verbreitet sie per Gossip; ein Node, der den Schlüssel aus einer Validatormenge kennt, reserviert diesen Peer und behält den Eintrag über Neustarts hinweg. Der Store einer frisch erzeugten Chain enthält keine Bindungen, daher sind bis zum Eintreffen der ersten Ankündigungen nur die ersten beiden Arten reserviert: Übergeben Sie bei einem Cut die Peer-IDs der Validatoren der Flotte mit --reserved-peer oder behalten Sie sie in der Bootstrap-Liste (rand-node address --key <file> gibt die Peer-ID eines Schlüssels aus). rand_status.reserved_peers zählt sie; auf einem Node der Flotte sollte der Wert innerhalb einer Minute nach dem Start die Anzahl der Validatoren erreichen.
Prüfen
rand-node status # rand_status verbatim
rand --rpc http://127.0.0.1:8545 status
rand peers
rand_status meldet 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, die address und peer_id des Nodes sowie die Sync-Diagnose (sync_inflight_age_ms, sync_failures, sync_late_batches), den Datenträger (disk_free_bytes, disk_low) und die Aufbewahrungsuntergrenze (prune_floor, 0 auf einem Node, der alles behält; prune_history_secs, null, wenn nicht gesetzt). Auf Chain 20 erwarten Sie hc_bundle 60af094a…, hc_auth 1e4e347f…, faucet true, confidential true, testnet true, binding_domain 1, fri_profile "production" und gas_prices zwischen 100 und 10.000 pro Gas sowie 800 und 80.000 pro KiB. rand_getGenesisHash muss 6210cf07…5135 antworten und rand_getVersion 0.6.8.
rand_getHealth antwortet disk_low (mit free_bytes) vor ok, syncing oder behind, wenn der freie Speicher unter dem Vierfachen von --min-free-disk-mb liegt.
History-Pruning
Ein Node, der mit --prune-history 24h gestartet wird, behält das Ledger (Notes, Nullifier, Anchors, das Validatorenregister, Programme) vollständig und löscht ältere Blöcke, ihre Zertifikate, Transaktionen und Quittungen. Ein Durchlauf erfolgt bei jedem 16. committeten Block und löscht bis zu 512 Blöcke, die älter sind als der Zeitstempel des Heads abzüglich des Fensters; Genesis, der Head und sein Vorgänger werden nie gelöscht, und die Untergrenze steigt nur. Der Speicherplatz kommt zurück, nachdem RocksDB kompaktiert hat. Auf Chain 20 laufen wie auf Chain 19 24 der 26 Validatoren mit 24h und halten etwa einen Tag an Blöcken vor. Als das Pruning für Chain 14 eingeschaltet wurde (2026-09-25), fielen die Blocktabellen jedes Validators von 19 GB auf 3,3–4,4 GB, sobald der Rückstand abgearbeitet war; die anderen beiden, obs1 und rand-archive-2, seit 2026-09-27 ebenfalls Validatoren, laufen ohne das Flag und behalten alles. Ein Mainnet-Node übergibt das Flag nie.
Auf einem gepruneten Node antwortet eine höhenadressierte Abfrage unterhalb der Untergrenze (rand_getBlockByHeight, rand_getFinality nach Höhe, ein rand_getBlocks- oder rand_getCompactBlocks-Bereich, der sie erreicht) mit dem Fehler -32010 samt data.floor: Fragen Sie ein Archiv. Eine hashadressierte Abfrage antwortet null für einen Block, den der Node nicht mehr hält, genau wie für einen, den es nie gab. Das Wallet-Scanning ist davon nicht betroffen, da Notes und Nullifier nie gepruned werden.
Die Startprüfung eines gepruneten Nodes ist strukturell (Block 0 und die behaltenen Blöcke, ihre QCs, Parent-Links und Leader), kein Replay ab Genesis, und sie repariert sich nicht selbst: Schlägt sie fehl, synchronisieren Sie erneut von einem Archiv. Öffnen Sie ein gepruntes Datenverzeichnis nicht mit einem Build, der älter als v0.5.7 ist, es sei denn, er läuft mit --verify-chain off: Seine Standardprüfung spielt ab Genesis nach, findet Block 1 fehlend und kürzt das Ledger auf Genesis.
Einen Prover betreiben
Auf Chain 20 erzeugt ein Wallet zwei Proofs für jedes Bundle, und der größere braucht etwa 6 GB Speicher. Ein Wallet, das ihn nicht halten kann, kann diesen Proof an einen delegierten Prover übergeben, mit dem es gekoppelt ist: das separate rand-prover-Binary oder denselben Dienst, den ein Node betreibt.
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 gibt einen randprover:-Link aus. Die Wallet übernimmt ihn mit rand prover pair <link> und beweist anschließend über ihn mit der globalen Option --prover. Der Listener des Provers ist ein eigener und niemals eine Methode des RPC: Eine Adresse, die --rpc entspricht, wird abgelehnt. Mit --prover weigert sich der Node zu starten, sofern nicht <prover-home>/prover.key.json existiert (Standard <datadir>/prover) und pro Proving-Slot 5.74 GB plus 1 GiB Arbeitsspeicher verfügbar sind; --prover-max-parallel legt die Slots fest, standardmäßig einen.
Auf chain 20 erhält der Prover den Viewing Key der Wallet und ein frisches Salt, nicht den Spend Key. Den Autorisierungsbeweis über den Spend Key erstellt die Wallet selbst; ein gekoppelter Prover kann daher die gesamte Historie dieser Wallet lesen, aber nichts ausgeben. Belassen Sie den Listener auf Loopback, sofern ihm nicht ein TLS-terminierender Proxy vorgeschaltet ist, und betreiben Sie ihn nicht auf einer Maschine, die einen öffentlichen RPC bereitstellt. Ein Stopp wartet auf den laufenden Beweis; setzen Sie daher bei einer systemd-Unit TimeoutStopSec=180.
Verify and repair
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
Stoppen Sie zuerst den Node. Exit-Code 0 bei Konsistenz, 2, wenn ein Problem gefunden und --repair nicht angegeben wurde. Das Replay verifiziert jeden Bundle-Beweis erneut, sodass ein Build, dessen Constraint-Menge von der abweicht, mit der die Chain erzeugt wurde, beim ersten Bundle stoppt.
Becoming a validator
Ein Validator tritt einer laufenden Chain durch Bonding bei, nicht durch ein neues Genesis: Starten Sie den Node mit --validator, geben Sie eine Registrierung mit rand-node register --key node.key.json --payout <rand1…> --v2 aus (chain 20 lehnt eine v1-Registrierung ab), lassen Sie eine Wallet mindestens 1,000 RAND mit rand bond <address> 1000 --registration <hex> binden, und der Node schlägt Blöcke vor, sobald das Bond aktiv wird: auf chain 20 frühestens drei 1,000-Block-Epochengrenzen nach dem Bond. Auf chain 20 kommt das Bond an zweiter Stelle. Sein Genesis setzt staking.admission_by_vote, sodass ein Bond, der einen neuen Schlüssel registriert, abgelehnt wird, bis Validatoren, die mehr als zwei Drittel des Stimmgewichts halten, den Schlüssel aufgenommen haben: Jeder signiert mit rand-node admit sign --candidate <key or registration> --key <validator key> --genesis-hash 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135, und einer von ihnen reicht die Stimmen mit rand-node admit submit ein (Command line). rand_getAdmitted listet die Schlüssel auf, die aufgenommen, aber noch nicht registriert sind. An einer Epochengrenze darf höchstens 2,500 bps des aktiven Gewichts zu neuem Gewicht werden. Staking führt Schritt für Schritt durch den Ablauf. Für eine private Test-Chain erzeugt rand-node genesis eine:
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
und scripts/local-testnet.sh startet zwei Validatoren auf einer Maschine mit RPC auf 8545 und 8546. Ohne weitere Flags enthält das Genesis weder hc_auth noch einen gas-Abschnitt noch ein Memo. Chain 20 wurde zusätzlich mit --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 erzeugt (chains 18 und 19 hatten die Flags bis einschließlich --envelope-bytes); ihre Abschnitte bridge und staking sowie consensus_domain fügte das Cut-Skript nachträglich ein. Eine eigene neue Chain sollte --binding-domain 1 übergeben: Eine Wallet der Version v0.6.8 beweist auf jeder Chain-ID außerhalb von 14 bis 19 die an das Genesis gebundene Form.
Deploying on a server
Das Verzeichnis deploy/ des Repositorys enthält die Skripte, die die Flotte verwendet: deploy/push-to-vps.sh <ip> <letter> "<bootstraps>" [validator|observer] richtet einen Linux-Server ein (Quellcode per rsync übertragen, bauen, /usr/local/bin/{rand-node,rand} installieren, ein am Genesis-Hash ausgerichtetes Datadir initialisieren, einen systemd-Dienst rand-node installieren), und deploy/rebuild-vps.sh <ip> baut bei einem neuen Commit neu und startet unter Beibehaltung der Daten neu. Zwei Warnungen. Das Provisioning-Skript initialisiert aus deploy/genesis.json, das nicht die Datei von chain 20 ist; ein Node für das testnet wird daher von Hand aus deploy/genesis-chain20.json aufgesetzt (auf main, siehe oben). Und beide Skripte übertragen /root/fullnode per rsync mit --delete, sodass ein Schlüssel innerhalb dieses Baums beim nächsten Rebuild gelöscht wird: Bewahren Sie ihn in /root/keys auf, wie es die Flotte tut und wie es das Provisioning-Skript von v0.6.8 jetzt standardmäßig tut (das von v0.6.7 legte den Schlüssel unter /root/fullnode/deploy/ ab). Die Dienstverwaltung erfolgt mit systemctl status rand-node und journalctl -u rand-node -f. Der Server benötigt build-essential clang cmake pkg-config libssl-dev und eine Rust-Toolchain. Ein Server mit 1 vCPU und 2 GB kann die Binärdateien nicht bauen; bauen Sie andernorts und kopieren Sie sie hinein. Running a validator and an aggregator nennt die Größen und die schrittweise Einrichtung.
The explorer
randscan.org läuft neben Validator E und indiziert chain 20; seine REST-API und sein WebSocket-Feed sind der einfachste Weg, die Chain ohne Node zu lesen (Explorer API). Der Explorer ist Open Source (randprotocol/randscan), und sein Indexer benötigt nur die rand_*-JSON-RPC eines Nodes und eine PostgreSQL-Datenbank, sodass er gegen Ihren eigenen Node betrieben werden kann.