Gunakan halaman ini untuk mengetahui kapan sebuah transaksi final, berapa banyak validator yang harus aktif, dan apa arti field blok yang Anda lihat di RPC dan explorer. Konsensusnya adalah HotStuff BFT berantai dengan kuorum berbobot stake; pada chain 20 itu berarti 18 dari 26 validator.
Aturan yang dijalankan node
| aturan | sebagaimana diimplementasikan |
|---|---|
| Kuorum | quorum certificate (QC) adalah himpunan suara Dilithium2 dari validator yang memegang lebih dari 2/3 total stake secara ketat |
| Jadwal leader | round robin murni: leader untuk view v adalah validators[v mod n], dengan himpunan diurutkan menurut alamat. Stake memberi bobot pada suara, bukan pada pemilihan leader |
| Pengusulan | leader untuk view v mengusulkan blok setelah memegang QC untuk v − 1, atau kuorum pesan NewView untuk v. Usulan yang akan menerapkan transaksi tidak valid membuang transaksi tersebut, bukan bloknya |
| Pemungutan suara dan keamanan | validator memberikan suara satu kali per view, dan hanya untuk blok yang aman terhadap lock-nya (justify QC-nya lebih baru daripada QC yang terkunci, atau blok tersebut memperpanjang blok yang terkunci). Status keamanan di-fsync ke RocksDB sebelum suara meninggalkan node |
| Domain penandatanganan | pada genesis dengan consensus_domain: 1 (chain 20, dan setiap chain sejak 15), setiap tanda tangan vote, new-view, dan proposal mencakup hash genesis (rand-vote-2, rand-newview-2, rand-block-2), sehingga tanda tangan untuk satu chain tidak terverifikasi di chain lain mana pun. Chain 14 dan sebelumnya menandatangani tanpa hash tersebut. binding_domain: 1 pada chain 20 memperluas aturan yang sama ke bukti transaksi dan aksi yang ditandatangani (Transaksi) |
| Usulan saudara | sebuah replika memegang satu blok per (view, leader); blok kedua yang berbeda dari leader tersebut untuk view yang sama ditolak sebagai equivocation. Usulan yang melampaui view replika itu sendiri lebih dari 8 view (PROPOSAL_VIEW_WINDOW) ditolak sebelum tanda tangannya diperiksa; pohon spekulatif yang penuh mengeluarkan blok di luar cabang sebelum menolak apa pun |
| Pelepasan lock | lock tidak pernah diturunkan secara otomatis (CON-4, v0.6.8). Lock hanya mengalah pada usulan yang justify QC-nya lebih tinggi darinya, atau pada kedatangan blok yang terkunci. Kuorum jawaban NotHeld yang ditandatangani dicatat dalam log untuk operator dan tidak melepaskan apa pun, dan validator mencatat suaranya sehingga tidak pernah menandatangani NotHeld untuk blok yang telah ia pilih. Setiap blok tersertifikasi di atas head dipersistensikan dan dipulihkan saat restart, sehingga restart seluruh armada tidak membuat QC terlantar pada blok yang tidak dipegang siapa pun. Validator yang blok terkuncinya hilang untuk selamanya dilepaskan secara manual, secara offline: rand-node safety release-lock |
| Perakitan QC | setiap validator merakit QC secara lokal dari suara yang digosipkan, sehingga chain tetap melakukan commit ketika leader berikutnya offline |
| Commit | aturan tiga-QC berantai: sebuah blok di-commit setelah tiga sertifikat berantai di atasnya pada view berurutan v, v+1, v+2 dan rantai itu tersambung kembali ke head yang telah di-commit |
| Timeout dan pergantian view | dasar --view-timeout-ms 3.000 ms, berlipat dua untuk setiap timeout berturut-turut, direset pada setiap kemajuan. Pacemaker timeout-certificate (CH-1, v0.6.8): replika yang timer-nya berbunyi tetap berada di view-nya dan menandatangani NewView yang meminta view berikutnya. Replika memasuki sebuah view berdasarkan QC untuk view sebelumnya, atau ketika validator yang memegang lebih dari 2/3 stake telah meminta view tersebut atau yang lebih baru; replika bergabung (menandatangani permintaannya sendiri) ketika lebih dari 1/3 meminta view di atas view-nya. NewView dari satu validator saja tidak menggerakkan siapa pun. View dibatasi (MAX_VIEW_AHEAD = 10⁶) |
| Pengaturan laju | leader mengusulkan blok kosong ketika tidak ada yang tertunda, paling cepat --block-interval-ms (bawaan 1.000 ms) setelah blok terakhir yang terlihat dari proposer mana pun |
| Batas vote dan gossip | suara yang lebih dari 8 view di depan diabaikan dan satu suara dihitung per (view, pemilih); gossip konsensus diukur per peer peneruus (burst 256, 64/s); usulan yang parent-nya tidak dikenal disimpan sebagai orphan hanya jika proposer-nya memimpin view tersebut dalam himpunan epoch saat ini atau epoch berikutnya, berada dalam batas pohon dari head yang telah di-commit, dan ukuran serta tx root-nya sesuai (kumpulan orphan dibatasi 64 MiB, dan sejak v0.6.1 dibatasi 16 orphan per proposer). Sejak v0.6.8 sebuah usulan diteruskan, dan sebuah orphan disimpan, hanya jika daftar transaksinya di-hash ke root yang di-commit oleh header-nya tanpa ada transaksi yang berulang (GOSSIP-2) |
| Batas blok | max_block_bytes chain berupa byte transaksi (4 MiB secara bawaan, 20 MiB pada genesis chain 20) dan 2.000 transaksi, ditegakkan oleh proposer dan sekali lagi oleh setiap replika dalam Ledger::apply_block |
| Waktu blok | pada chain dengan bagian bridge: timestamp_ms sebuah blok tidak boleh mendahului milik parent-nya (TimestampRewind) maupun melampauinya lebih dari 60 s (TimestampLeap), dan validator menahan suaranya dari blok yang lebih dari 15 s di depan jamnya sendiri; lihat di bawah |
Aturan commit tiga-view berurutan bersifat menopang: melonggarkannya membuka kembali bug finalitas yang saling bertentangan, yang untuknya fullnode memiliki regression test. Segala sesuatu yang dilihat klien melalui RPC sudah di-commit: hanya blok yang di-commit yang disajikan, dan stream WebSocket newHeads mengirim satu notifikasi per blok yang di-commit, secara berurutan.
Tabel ini adalah v0.6.8, rilis yang dijalankan chain 20. Tiga aturannya baru di v0.6.8 (audit v6) dan aktif sejak chain 20 berjalan pada 2026-10-01: pacemaker timeout-certificate (CH-1), tanpa pelepasan lock otomatis (CON-4), dan pemeriksaan daftar transaksi usulan (GOSSIP-2). Pada chain 18 dan 19 (v0.6.7), NewView yang ditandatangani oleh satu validator saja memindahkan setiap replika ke view-nya, dan lock diturunkan berdasarkan jawaban NotHeld yang ditandatangani dari kuorum stake. Pacemaker dan aturan lock mengubah apa yang ditandatangani validator dan kapan, sehingga v0.6.8 diluncurkan dengan all-stop/all-start bersama pemotongan chain 20, tidak pernah node demi node.
Angka-angka testnet
Chain 20 memiliki 26 validator, masing-masing di-stake tepat 1.000 RAND, ke-26-nya ada dalam genesis dengan kunci dan peer id yang dijalankan chain 17 sampai 19. Pada chain 15 delapan belas ada dalam genesis, dengan kunci chain 14, dan delapan lainnya melakukan bond pada 2026-09-27 di bawah registrasi v2 dan aktif sejak epoch 43. Stake seragam, sehingga kuorum adalah soal jumlah kepala: 18 dari 26 harus online untuk meng-commit apa pun. Dengan 17 aktif, view terus maju dan tidak ada yang difinalisasi. Himpunan n validator dengan stake sama membutuhkan lebih dari 2/3 stake: 2 dari 2, 3 dari 4, 5 dari 6, 13 dari 18, 18 dari 26. Batas bobot genesis (3.333 bps per validator) tidak berlaku pada himpunan dengan stake yang sama.
Blok dipacu pada bawaan 1.000 ms. Pada chain 15 blok tiba kira-kira setiap 1,2 s dalam praktik (rata-rata 1,18 s selama 29 jam pertamanya); pada chain 20 explorer melaporkan rata-rata 1,34 s pada tinggi 3.270 (2026-10-01, avg_block_time_ms). Explorer melaporkan rata-rata waktu blok yang diamatinya (avg_block_time_ms di GET /stats). View sebuah validator berjalan mendahului tinggi blok setiap kali view mengalami timeout, itulah sebabnya rand_getHead melaporkan keduanya.
Epoch
Himpunan validator diturunkan ulang dari register setiap epoch_blocks = 1.000 blok (parameter genesis). epoch(h) = h / 1000; himpunan untuk epoch e ≥ 1 diturunkan dari register per blok terakhir epoch e − 1: setiap baris dengan stake ≥ 1,000 RAND, 100 teratas menurut stake, diurutkan menurut alamat. Pada chain tanpa bagian staking, sebuah bond menjadi bobot pada batas berikutnya. Pada chain 20 bond menunggu dua epoch lagi dan anggaran masuk per epoch sebesar 2.500 bps dari bobot bond aktif pada batas tersebut (6.500 RAND selama himpunan memegang 26.000), dan bond yang mendaftarkan validator baru ditolak kecuali himpunan terlebih dahulu memilih kunci tersebut masuk dengan AdmitValidator (staking.admission_by_vote). Anggaran chain 19 adalah tetap 10.000 RAND per epoch, dan tidak ada pemungutan suara penerimaan. Unbond mengurangi bobot pada batas berikutnya, sedangkan jumlahnya menunggu dua epoch untuk dapat ditarik. rand_getEpoch mengembalikan epoch, panjang epoch, dan proyeksi himpunan berikutnya. Lihat Staking.
Apa yang dibawa sebuah blok
{
"hash": "647b…", "height": 50, "view": 92, "parent": "2d41…",
"proposer": "3v3VBJ…", "timestamp_ms": 1788000123456,
"tx_root": "0000…", "state_root": "a1b2…", "justify_view": 91,
"tx_count": 0, "transactions": []
}
view adalah view tempat blok diusulkan dan justify_view adalah view dari QC yang dibawanya untuk parent-nya. timestamp_ms ditetapkan oleh proposer, dalam batas yang dijelaskan di bagian berikutnya. state_root meng-commit ledger setelah blok. Pada chain 20:
inner = blake3("rand-state-8" || tree_root || nullifier_root || validators_root || programs_root
|| bridge_root || tokens_root
|| faucet_epoch || faucet_minted_in_epoch || bond_queue_root
|| gas_price || byte_price
|| program_state_root)
state_root = blake3("rand-state-admitted-1" || inner || admitted_root)
Chain 19 meng-commit field yang sama tanpa program_state_root, di bawah rand-state-7, tanpa pembungkus.
Komponen-komponen tersebut bergantung pada genesis. Rantai tanpa satu pun bagian opsional meng-commit empat komponen pertama di bawah rand-state-2. Bagian bridge menambahkan bridge_root. Bagian tokens menambahkan tokens_root setelahnya dan mengganti domain seluruh hash menjadi rand-state-4; genesis dengan bagian bridge wajib memiliki bagian tokens, sehingga chain 20 memiliki keduanya. Bagian aggregation menambahkan root agregator berikutnya (di bawah rand-state-3 pada rantai tanpa token); chain 20 tidak memilikinya. Bagian staking menambahkan dua penghitung epoch faucet dan root antrean bond (rand-bond-queue-1) di urutan terakhir, serta mengganti domain seluruh hash menjadi rand-state-5, apa pun yang aktif selain itu; chain 14 tidak memiliki bagian tersebut dan melakukan hash di bawah rand-state-4, sedangkan chain 15 hingga 17 melakukan hash di bawah rand-state-5. Bagian vesting menambahkan root register vesting setelah itu dan mengganti domain hash menjadi rand-state-6; chain 20 tidak memilikinya. Bagian gas dengan pengendali dynamic menambahkan gas_price dan byte_price yang berlaku, masing-masing berupa u64 big-endian, setelah semua komponen lain dan mengganti domain hash menjadi rand-state-7. Itulah domain milik chain 19, dan chain 20 tetap menyimpan harga tersebut dalam root-nya: harga berubah sekali per blok, setelah transaksi blok dan sebelum root (Biaya). Bagian gas dengan harga tetap tidak termasuk dalam root. Bagian program_state (RPL-2) menambahkan root dari seluruh cell dan vault setiap program setelah harga-harga tersebut dan mengganti domain hash menjadi rand-state-8: milik chain 20. Status staking dari Audit v6 digabungkan di sekeliling domain tersebut, bukan di dalamnya: pada staking.admission_by_vote (chain 20) root-nya adalah blake3("rand-state-admitted-1" || inner || admitted_root), dan pada staking.slashing (belum ada chain) pembungkus kedua menambahkan himpunan yang di-jail. tokens_root adalah root Merkle dari daun blake3("rand-token-leaf-1" || bincode(TokenInfo)) dalam urutan indeks, sehingga metadata, otoritas, mint_nonce, suplai, dan jumlah locked setiap backing dari setiap token merupakan state konsensus: dua node yang berbeda pendapat tentang satu baris token berbeda pendapat tentang rantai tersebut. Pada chain 20, root token juga memasukkan ekstensi registri (batas max_tokens, biaya registrasi yang dibakar, batas nilai note, dan jendela batas mint bergulir milik bridge) di bawah rand-token-registry-3. Root bridge mencakup emitter, himpunan guardian, digest atestasi yang telah dibelanjakan, urutan burn, kunci guardian PQ, kunci jeda, flag jeda, dan dua nonce tata kelola; registri aset telah dipindahkan dari root tersebut ke tokens_root. Bridge chain 20 memiliki rules_v2, sehingga nonce rotasi dan parameter batas global ditambahkan dan domainnya adalah rand-bridge-state-5 (milik chain 14 adalah rand-bridge-state-4); root tersebut kemudian dibungkus oleh batas bawah replay masuk (rand-bridge-replay-floor-1), dan pada chain 20 juga oleh aturan rotasi dan rotasi tertunda (rand-bridge-rotation-1) serta grup biaya (rand-bridge-fees-1). Register validator di-hash menjadi validators_root (domain daun rand-validator-leaf-4 pada chain 20, dengan activation_epoch setiap baris; rand-validator-leaf-2 pada rantai tanpa bagian staking), sehingga node yang berbeda pendapat tentang satu baris register berbeda pendapat tentang rantai tersebut.
Waktu blok dibatasi (B2)
Pada rantai yang di-bridge, stempel waktu blok menentukan kedaluwarsa himpunan guardian dan hari yang menjadi acuan batas mint harian sebuah backing, sehingga leader yang dapat memajukan jam secara mendadak dapat mengakhiri lebih awal masa tenggang himpunan yang dirotasi atau melompati batas harian. Chain 20 memiliki bagian bridge, sehingga tiga aturan berlaku, semuanya bergantung pada bagian tersebut:
| aturan | batas | jenis |
|---|---|---|
| tanpa mundur | timestamp_ms ≥ parent.timestamp_ms (sama diperbolehkan), jika tidak BlockError::TimestampRewind; proposer mengeluarkan max(now, parent.timestamp_ms) | validitas, diperiksa juga pada replay dan sinkronisasi |
| tanpa lompatan | timestamp_ms ≤ parent.timestamp_ms + MAX_TIMESTAMP_STEP_MS (60.000 ms), jika tidak BlockError::TimestampLeap | validitas, diperiksa juga pada replay dan sinkronisasi |
| selisih jam | validator menolak memberikan suara untuk blok yang lebih dari MAX_CLOCK_DRIFT_MS (15.000 ms) mendahului jamnya sendiri | hanya aturan pemungutan suara: blok tetap berada di pohon spekulatif, kuorum yang jamnya selaras tetap dapat mensertifikasinya, dan replay riwayat yang telah di-commit tidak pernah menerapkannya |
Setiap validator pada rantai yang di-bridge memerlukan NTP. Validator yang jamnya meleset lebih dari 15 detik adalah leader yang bermasalah (proposalnya mungkin tidak mendapat suara) sekaligus pemberi suara yang bermasalah (ia mungkin menolak blok tepat waktu dari leader yang jujur). Keduanya tidak menghentikan rantai selama jam mayoritas yang jujur selaras, tetapi armada yang tidak tersinkronisasi kehilangan margin liveness tanpa alasan.
timestamp_ms genesis harus mendekati waktu peluncuran sebenarnya. Jika terlalu jauh di masa lalu, waktu blok tertinggal dari jam dinding sampai batas langkah memungkinkannya mengejar, paling banyak 60 detik per blok. Jika lebih dari 15 detik di masa depan, blok 1 sama sekali tidak ter-commit: setiap suara, termasuk suara milik leader sendiri, ditahan sampai waktu dinding mencapainya. Setelah halt yang panjang, pengejaran yang sama dapat membuat hari batas mint berganti lebih cepat daripada sekali per hari nyata, dibatasi pada tambahan batas satu hari per hari penuh keterlambatan yang terakumulasi.
Finalitas bagi klien
- Transaksi bersifat final ketika
rand_getTransaction(hash)mengembalikan sebuah blok. Penerimaan olehrand_sendTransactionhanyalah masuknya transaksi ke mempool. - Blok yang disajikan oleh RPC atau diindeks oleh explorer sudah ter-commit. Tidak ada jendela finalitas yang perlu ditunggu; panduan explorer menyatakan hal yang sama.
- Head dari
rand_subscribe["newHeads"]adalah head yang tidak akan hilang dari node: tidak ada yang dikirim sebelum blok ter-commit ke penyimpanan. - Node yang tertinggal memverifikasi ulang segalanya: setiap sertifikat, setiap bundle dan bukti call, setiap receipt, sebelum menerima blok yang disinkronkan. Tanda tangan finalitas tidak pernah dipercaya sebagai pengganti bukti.
Lembar contekan pemulihan, dari dokumen fullnode sendiri: tinggi yang tidak maju dengan peer_count rendah adalah masalah jaringan; tinggi yang tidak maju padahal peer normal berarti kurang dari 2/3 stake yang online; CORRUPT CHAIN saat startup berarti node memotong ekor yang rusak dan sedang melakukan resync.