Pepijat KAWPOW Ravencoin: header blok yang memilih sendiri pemeriksaan proof of work miliknya
Ravencoin menghabiskan minggu kedua bulan Ogos dengan mengundurkan rantaiannya kira-kira tiga hari. Puncanya bukan kartel perlombongan, eksploit dompet atau fungsi hash yang rosak. Puncanya ialah satu medan dalam header blok yang dipercayai oleh nod untuk memberitahunya pemeriksaan proof of work yang mana satu antara dua untuk dijalankan. Setiap serpihan kod yang dipetik di bawah dibaca daripada sumber konsensus Ravencoin sendiri dan bukan daripada pengumuman, dan apabila pengumuman menyatakan sesuatu yang tidak ditunjukkan oleh sumber, artikel ini menyatakannya dan bukan meneka.
Apa yang dibawa oleh header KAWPOW
KAWPOW ialah proof of work Ravencoin, varian ProgPoW yang diguna pakai oleh rantaian itu pada Mei 2020 untuk mengekalkan syiling itu pada GPU biasa. Perpindahan itu mengubah header blok. Sebelum masa pengaktifan, header berakhir dengan nonce 32 bit biasa yang digunakan oleh setiap rantaian terbitan Bitcoin. Selepasnya, pensiri menulis tiga medan ke dalam slot itu, mengikut susunan ini: nHeight, kemudian nNonce64, kemudian mix_hash.
Dua daripadanya tidak luar biasa. nNonce64 hanyalah nonce yang lebih lebar. mix_hash ialah hasil perantaraan bahagian memory hard algoritma itu, dibawa dalam header supaya pengesah mempunyai nilai untuk disemak dan bukan pengiraan untuk diulang dari awal. Yang ketiga ialah yang menarik. nHeight ialah blok itu menyatakan, di dalam header sendiri, ketinggian yang dipercayainya.
Kedudukan sebenar sesuatu blok dalam rantaian bukan soal pendapat. Ia ditetapkan oleh hashPrevBlock: blok mana yang anda bina di atasnya menentukan di mana anda mendarat, dan anda tidak boleh berbohong tentang itu dan masih bersambung ke hujung rantaian. nHeight ialah salinan kedua yang boleh ditulis bagi fakta yang sama, dan salinan sesuatu fakta hanya bernilai setakat pemeriksaan yang membandingkannya dengan yang asal.
Dua fungsi hash, satu daripadanya tidak mengesahkan apa-apa
Fail hash.cpp Ravencoin mentakrifkan dua titik masuk KAWPOW, dan tandatangan kedua-duanya sudah menceritakan sebahagian besar kisahnya sebelum anda membaca satu baris pun badannya. Yang pertama ialah uint256 KAWPOWHash(const CBlockHeader& blockHeader, uint256& mix_hash). Yang kedua ialah uint256 KAWPOWHash_OnlyMix(const CBlockHeader& blockHeader).
Yang pertama mengambil mix_hash sebagai parameter output, kerana ia menghasilkannya. Ia memilih set data dengan ethash::get_epoch_number(blockHeader.nHeight), membina konteks epoch itu jika belum dipegangnya, dan kemudian menjalankan progpow::hash di atasnya. Mix yang dipulangkannya ialah hasil sampingan daripada melakukan kerja itu. Inilah laluan memory hard, dan sifat memory hard itulah satu-satunya sebab KAWPOW wujud dan bukan sekadar hash biasa.
Yang kedua tidak mengambil parameter sedemikian, kerana ia tidak menghasilkan apa-apa. Ia menggunakan mix yang sudah ada dalam header, melalui progpow::hash_no_verify(blockHeader.nHeight, header_hash, to_hash256(blockHeader.mix_hash.GetHex()), blockHeader.nNonce64). Pustaka asal menamakan fungsi itu hash_no_verify dan nama itu tepat. Ia melakukan langkah pencampuran akhir ke atas nilai yang diberikan kepadanya dan memulangkan jawapannya. Ia tidak pernah membina set data, jadi ia tidak pernah membuktikan bahawa nilai yang diberikan kepadanya hanya boleh datang daripada melakukan kerja itu.
Kedua-dua fungsi itu bukan kesilapan. Yang murah wujud atas sebab yang baik: nod yang menyegerakkan berjuta-juta blok lama yang telah diselesaikan oleh titik semak berkod keras tidak sepatutnya perlu membina semula set data berbilang gigabait bagi setiap epoch untuk mengesahkan semula sejarah yang tidak dipertikaikan oleh sesiapa. Satu-satunya soalan yang perlu dijawab oleh reka bentuk sedemikian ialah blok mana yang dibenarkan mengambil laluan itu.
Pintu pagar, dan apa yang dipercayainya
Soalan itu dijawab oleh CheckBlockHeader dalam validation.cpp, dan komen di atas jawapan itu menyatakan niatnya dengan jelas: "If we are checking a KAWPOW block below a know checkpoint height. We can validate the proof of work using the mix_hash". Niatnya betul. Pelaksanaannya membuat pintu pagar pada block.nHeight <= (uint32_t)pcheckpoint->nHeight, dan block.nHeight ialah nombor yang ditulis oleh blok itu tentang dirinya sendiri.
Baris di bawahnya memanggil CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&) yang generik. Lihat apa yang tiada dalam tandatangan itu. Tiada mix, tiada nonce dan tiada header. Ia menerima hash yang sudah siap dan sasaran lalu membandingkan kedua-duanya, dan ia tidak mempunyai cara untuk mengetahui fungsi mana antara dua itu yang menghasilkan nombor yang diberikan kepadanya. Bagi blok KAWPOW, CBlockHeader::GetHash() memulangkan KAWPOWHash_OnlyMix(*this), jadi nombor yang diberikan kepadanya ialah yang murah.
Jika disambung hujung ke hujung, blok yang mengisytiharkan nHeight yang cukup rendah disahkan dengan bertanya sama ada nilai yang diterbitkan daripada mix hash miliknya sendiri berada di bawah sasaran. Tiada apa-apa di sepanjang laluan itu yang bertanya dari mana mix itu datang, dan tiada apa-apa di sepanjang laluan itu yang membandingkan ketinggian yang diisytiharkan dengan kedudukan sebenar blok itu.
Berapa rendah yang cukup rendah ternyata tidak halus. Titik semak tertinggi dalam parameter rantaian mainnet yang dikeluarkan ialah 2,383,550. Blok palsu pertama berada pada 4,487,776. Headernya terpaksa mendakwa kedudukan kira-kira 2.1 juta blok di belakang kedudukan sebenarnya, dan cabang yang dipilihnya tidak pernah melihat perbezaan itu.
Apa yang dibeli oleh jalan pintas itu, dan apa yang tidak
Ketepatan penting di sini, kerana kebanyakan liputan agak longgar tentangnya dan versi longgar itu membuatkan pepijat ini kedengaran lebih mudah dan lebih aneh daripada yang sebenarnya.
Jalan pintas itu tidak menurunkan kesukaran. nBits disahkan berdasarkan apa yang dikehendaki oleh blok sebelumnya yang sebenar, dan blok sebelumnya yang sebenar dipilih oleh hashPrevBlock, yang tidak boleh dipalsukan oleh penyerang jika masih mahu mendarat di hujung rantaian. Blok palsu perlu melepasi sasaran yang sama persis dengan blok jujur yang dilombong pada minit yang sama.
Yang berubah ialah harga satu tekaan. Pelombong yang jujur membayar setiap percubaan dengan satu laluan penuh ke atas set data yang diukur dalam gigabait, yang merupakan inti algoritma memory hard dan sebab KAWPOW telah menghalang ASIC daripada Ravencoin selama enam tahun. Jalan pintas itu hanya memerlukan hash header ditambah satu langkah pencampuran akhir ke atas nilai yang dipilih sesuka hati oleh penyerang. Loteri yang sama, peluang yang sama bagi setiap tiket, tetapi tiket jauh lebih murah dengan beberapa tertib magnitud. 2Miners menggambarkan hasilnya sebagai blok dengan kerja hampir sifar, dan jika diukur dengan kos yang sepatutnya bagi KAWPOW, itu gambaran yang adil.
Apa yang berlaku pada rangkaian
Blok tidak sah pertama yang diketahui ialah ketinggian 4,487,776, dengan cap masa 2026-08-07 15:44:01 UTC. Eksploitasi berterusan sehingga keluaran kecemasan pada 10 Ogos. Dalam satu bahagian 2,089 blok yang diperiksa, 2Miners mengira 96 blok yang terjejas, jadi blok palsu itu bertaburan di seluruh cabang dan bukan berkumpul dalam satu siri, dan itulah sebabnya penyelesaiannya mesti penyusunan semula dan bukan pembuangan secara pembedahan.
Bagi pengendali nod, gejala yang kelihatan lebih teruk daripada blok tidak sah yang diterima secara senyap. Nod ranap pada blok ini, dan selepas dimulakan semula, berhenti menyegerak. Tron Black telah menerangkan mekanisme itu, dan ia satu kerosakan sampingan yang kemas. Indeks blok menyimpan ketinggian sebenar sesuatu blok, bukan ketinggian yang diisytiharkan oleh headernya. Semasa dimulakan semula, nod membina semula setiap header daripada indeks dan mengira semula hashnya, jadi bagi blok palsu ia membuat hash ketinggian sebenar sedangkan header membawa ketinggian palsu. Hash tidak lagi sepadan, pemeriksaan proof of work gagal, dan LoadBlockIndexGuts terhenti. Blok itu diterima sekali dan kemudian tidak boleh dimuatkan, dan itulah sebabnya gejala kedua bertahan lebih lama daripada yang pertama.
Beberapa bursa menggantung deposit dan pengeluaran RVN selagi cabang itu belum diselesaikan. Itu tindak balas yang biasa dan betul terhadap rantaian yang sejarah terkininya akan ditulis semula, dan ia patut dijangka dan bukan dibaca sebagai keputusan terhadap syiling itu.
Tampalan itu, dan dari mana ia datang
Pembaikan pertama dikeluarkan pada 10 Ogos sebagai versi 4.6.1.1-hf1, dan ia datang daripada 2Miners, sebuah kolam perlombongan, dan bukan daripada projek Ravencoin. Ia menghentikan kerosakan bagi sesiapa yang memasangnya. Ia digantikan sehari kemudian.
Versi 4.8.0, diterbitkan pada 11 Ogos melalui repositori Ravencoin, ialah keluaran yang patut dijalankan. Jangan berpuas hati dengan apa-apa yang lebih awal. Ia menolak blok yang ketinggian header yang diisytiharkannya tidak sepadan dengan kedudukan sebenarnya mulai 4,487,776, menetapkan titik semak pada 4,487,775 sebagai blok bersih terakhir, membina semula keadaan rantaian yang rosak secara automatik dan bukan terhenti, serta menggabungkan pembaikan limpahan pemindahan aset yang tidak dibawa oleh hotfix kecemasan, bersama kerja lain dari hulu.
Hanya yang pertama daripada semua itu ialah pembaikannya. Tolak blok yang ketinggian diisytiharkannya tidak sepadan dengan kedudukan sebenarnya, dan pintu pagar itu tertutup. Titik semak dan pembinaan semula automatik ialah pemulihan, dan titik semak khususnya ialah alat yang kasar: ia penegasan berkod keras bahawa satu blok tertentu ialah yang betul, iaitu sesuatu yang rantaian mahu sesedikit mungkin. Ia ada di sini kerana cabang yang jujur perlu dimantapkan lebih cepat daripada yang mampu dilakukan oleh hashrate sahaja.
Titik pemulihan itu sendiri ialah keputusan pertimbangan dan bukan sesuatu yang jelas. Tron Black menulis bahawa beliau meminta kolam mempertimbangkan potongan yang lebih baharu, untuk menjadikan penyusunan semula lebih cetek dan mengendalikan blok palsu sebagai pengecualian. Mereka menolak dan memilih garisan yang paling bersih. Dalam sistem proof of work, hujah itu selesai dengan sendirinya: apabila majoriti hashrate yang jujur menolak sesuatu sejarah, sejarah itu kalah, dan dua kolam terbesar bersama-sama memegang majoriti.
Apa makna sebenar reorg tiga hari
Oleh sebab nod yang terdedah menerima blok palsu itu, cabang yang mengandunginya mengumpul rantaian tulen di atasnya. Membuangnya bermakna penyusunan semula, dan dengan sasaran blok satu minit Ravencoin, tempoh dari 4,487,776 hingga tampalan ialah kira-kira tiga hari blok.
Jika anda memegang RVN, makna praktikalnya ialah transaksi yang disahkan pada cabang yang dibuang tidak lagi disahkan. Kebanyakannya kembali ke mempool dan dilombong semula pada rantaian yang kekal, tetapi itu tidak dijamin, dan satu kelas daripadanya tidak boleh kembali langsung. Transaksi yang membelanjakan coinbase daripada blok yang dibuang sedang membelanjakan syiling yang tidak lagi wujud pada rantaian yang kekal, dan begitu juga apa-apa yang dibina di atasnya. Transaksi itu tidak sah, bukan tertunda. Itulah sebabnya penggantungan oleh bursa ialah keputusan yang betul dan bukan tindak balas berlebihan, dan sebabnya aktiviti selepas 4,487,775 wajar dilayan dengan berhati-hati sehingga satu hujung rantaian dimuktamadkan.
Satu butiran patut diketahui jika anda melihat nod enggan bergerak pada minggu itu. Nod Ravencoin membawa peraturan tiada reorg panjang, yang wujud untuk menghalang serangan majoriti mengejut daripada menulis semula sejarah yang dalam. Kebanyakan nod lama yang berjalan berterusan akhirnya jatuh di bawah bilangan rakan yang diperlukan oleh peraturan itu dan kemudian menerima rantaian yang lebih panjang seperti yang direka. Sebilangan kecil tidak, kerana nod itu tidak pernah kehilangan cukup rakan dan kerana, mengikut peraturan seperti yang ditulis, tiada apa-apa yang dilanggar. Itu perlindungan yang berfungsi tepat seperti yang ditetapkan pada masalah yang tidak pernah direka untuknya. Perpecahan itu datang daripada kecacatan pengesahan, bukan daripada serangan ke atas majoriti, dan peraturan itu tidak dapat membezakan kedua-duanya.
Apa yang perlu dilakukan jika anda melombong RVN
Jika anda menjalankan nod Ravencoin anda sendiri, jalankan 4.8.0, dan khususnya bukan salah satu keluaran lebih awal yang hanya menangani sebahagian daripada masalah ini. Hentikan nod, gantikan binari, mulakannya semula. Tiada reindex untuk dijalankan dan tiada langkah manual: perisian membina semula apa yang diperlukannya sendiri. Nod yang datang daripada hotfix kecemasan dimulakan semula dengan cepat. Nod yang datang daripada perisian yang belum ditampal perlu memainkan semula dan membina semula, yang mengambil beberapa jam pada perkakasan biasa, dan ralat bad-blk-height sepanjang tempoh itu ialah tampalan yang sedang berfungsi, bukan kerosakan padanya.
Jika anda melombong melalui kolam, tiada apa-apa di pihak anda untuk diubah. Tiada alamat baharu, tiada port baharu, tiada kemas kini perisian perlombongan. KAWPOW sendiri tidak pernah menjadi masalah di sini: algoritma itu melakukan tepat apa yang direka untuknya, dan kecacatan itu terletak pada kod yang menentukan bila ia dijalankan. Hashrate yang anda halakan ke cabang lama ialah kerja sebenar. Ia cuma mendarat pada blok yang dibuang bersama blok palsu yang bertaburan di antaranya.
Ada cara satu baris untuk mengesahkan anda berada pada rantaian yang betul, dan ia patut dilakukan dan bukan diandaikan. Semak hash blok 4,494,143. Pada rantaian kanonik ia berakhir dengan 4c67d6a4, dan semua penjelajah Ravencoin yang bebas memaparkan rantaian yang sama itu apabila projek mengisytiharkan rangkaian telah pulih.
Bentuk pepijat ini
Buang butiran khususnya dan yang tinggal ialah bentuk yang sentiasa berulang, dalam rantaian dan jauh di luarnya. Nilai yang datang dari luar digunakan untuk menentukan sejauh mana nilai yang sama itu akan diperiksa dengan teliti. Header menyatakan ketinggiannya sendiri, dan nod menggunakan kenyataan itu untuk memilih pemeriksaan proof of work mana yang kemudian perlu dilepasi oleh header itu.
Versi yang betul tidak rumit, dan tampalan itu pada dasarnya satu baris daripadanya: bandingkan ketinggian yang diisytiharkan dengan kedudukan sebenar blok sebelum membenarkannya menentukan apa-apa pun. Sebab ia tiada ialah separuh yang lebih menarik. Jalan pintas itu ditulis untuk blok yang sudah dipercayai, dan dalam andaian itu pintu pagar tersebut dibaca sebagai kenyataan fakta dan bukan sebagai soalan yang mungkin dijawab secara tidak jujur. Ia berhenti dibaca begitu sebaik sahaja blok yang tidak dipercayai dibenarkan mengisi medan itu, dan tiada apa-apa dalam kod yang menandakan saat perkara itu berubah.
Dua perkara tentang cara ia ditemui patut direkodkan. Ravencoin pernah menjalani audit keselamatan profesional ke atas kodnya, dan audit itu tidak mengesan masalah ini atau limpahan aset yang dibaiki bersamanya. Tron Black menulis bahawa beliau sangat mengesyaki kedua-duanya ditemui oleh semakan keselamatan AI model terkini. Apa pun alatnya, ia sesuai dengan bentuknya: kecacatan itu tidak kelihatan selagi anda membaca jalan pintas itu mengikut syaratnya sendiri, dan hanya muncul apabila anda bertanya siapa yang boleh mengisi medan yang dipercayai oleh jalan pintas itu.
Perkara terakhir yang patut diperhatikan ialah siapa yang bertindak, dan mengikut susunan apa. Sebuah kolam perlombongan membaca laluan pengesahan, memahaminya, dan mengeluarkan binari kecemasan dalam tempoh tiga hari. Dua kolam terbesar kemudian bersetuju untuk melombong rantaian yang membuang keseluruhan tempoh serangan dan bukan mengambil potongan yang mudah, dan apabila diminta mengambil potongan yang lebih cetek, mereka menolak. Projek menyusul sehari kemudian dengan keluaran yang menggantikan hotfix itu dan membaiki lebih banyak daripadanya. Siapa yang pertama kurang penting berbanding hakikat bahawa kedua-duanya berlaku, dan bahawa perkara yang benar-benar menyelesaikannya bukan mana-mana pengumuman tetapi berat terkumpul kerja sebenar di satu pihak perpecahan itu. Begitulah rupa desentralisasi pada hari ia perlu memikul beban dan bukan sekadar tertulis dalam kertas putih.
Dari mana angka ini datang
Supaya sesiapa sahaja boleh menyemak dan bukan sekadar mempercayai kata-kata kami. Susun atur header, dua fungsi hash dan tandatangannya, pemilihan epoch dan cabang pengesahan dengan komennya dibaca daripada sumber Ravencoin sendiri, dalam src/primitives/block.h, src/primitives/block.cpp, src/hash.cpp, src/hash.h, src/pow.h dan src/validation.cpp. Senarai titik semak, termasuk 2,383,550 sebagai yang tertinggi di mainnet, dibaca daripada src/chainparams.cpp. Ketinggian tidak sah pertama dan cap masanya datang daripada notis rangkaian projek Ravencoin sendiri. Laluan ranap indeks blok, transaksi bergantung coinbase yang tidak boleh kembali, tingkah laku tiada reorg panjang, titik pemulihan lebih cetek yang ditolak, kenyataan tentang audit dan semakan AI, kandungan 4.8.0 dan semakan 4,494,143 datang daripada catatan Tron Black untuk projek Ravencoin. Versi hotfix kecemasan dan kiraan 96 blok terjejas dalam 2,089 datang daripada keluaran 2Miners dan laporan berkaitannya. Apa-apa yang tidak dinyatakan oleh sumber telah ditinggalkan daripada artikel ini dan bukan diisi.