Ravencoin KAWPOW қатесі: өзінің жұмыс дәлелі тексеруін өзі таңдаған блок тақырыбы
Ravencoin тамыздың екінші аптасын өз желісін шамамен үш күнге кері айналдырумен өткізді. Себебі майнерлер картелі де, әмиянның осалдығы да, бұзылған хеш-функция да емес еді. Себебі блок тақырыбындағы бір өріс болды: нода екі жұмыс дәлелі тексеруінің қайсысын іске қосу керегін соған сеніп шешті. Төменде келтірілген әр код үзіндісі хабарландырудан емес, Ravencoin-нің өз консенсус бастапқы кодынан алынған, ал хабарландыруларда бастапқы код көрсетпейтін нәрсе айтылған жерде бұл мақала болжам жасамай, мұны ашық айтады.
KAWPOW тақырыбында не бар
KAWPOW - Ravencoin-нің жұмыс дәлелі алгоритмі, монетаны қарапайым GPU-да ұстап қалу үшін желі 2020 жылғы мамырда көшкен ProgPoW нұсқасы. Бұл көшу блок тақырыбын өзгертті. Іске қосылу уақытына дейін тақырып Bitcoin-нан тараған әр желі пайдаланатын кәдімгі 32 биттік nonce-пен аяқталады. Одан кейін сериализатор сол орынға үш өрісті мына ретпен жазады: nHeight, содан кейін nNonce64, содан кейін mix_hash.
Олардың екеуінде ерекше ештеңе жоқ. nNonce64 жай ғана кеңірек nonce. mix_hash алгоритмнің жадыны көп қажет ететін бөлігінің аралық нәтижесі, ол тексерушіде есептеуді нөлден қайталаудың орнына салыстыратын мән болуы үшін тақырыпта сақталады. Үшіншісі қызықты. nHeight арқылы блок өз тақырыбының ішінде өзін қай биіктікте деп санайтынын мәлімдейді.
Блоктың желідегі нақты орны пікір мәселесі емес. Оны hashPrevBlock бекітеді: қай блоктың үстіне құрсаңыз, Сіздің қайда түсетініңізді сол шешеді, және бұл туралы өтірік айтып, бәрібір желінің ұшына қосыла алмайсыз. nHeight дәл осы фактінің жазуға болатын екінші көшірмесі, ал фактінің көшірмесі оны түпнұсқамен салыстыратын тексеру қаншалықты құнды болса, сонша ғана құнды.
Екі хеш-функция, біреуі ештеңені тексермейді
Ravencoin-нің hash.cpp файлы KAWPOW-тың екі кіру нүктесін анықтайды, және олардың сигнатуралары екеуінің денесінен бір жол оқымай тұрып-ақ оқиғаның көп бөлігін айтып береді. Біріншісі: uint256 KAWPOWHash(const CBlockHeader& blockHeader, uint256& mix_hash). Екіншісі: uint256 KAWPOWHash_OnlyMix(const CBlockHeader& blockHeader).
Біріншісі mix_hash мәнін шығыс параметрі ретінде алады, өйткені оны өзі жасайды. Ол деректер жиынын ethash::get_epoch_number(blockHeader.nHeight) арқылы таңдайды, сол эпоха контексті әлі жоқ болса, оны құрады, содан кейін оның үстінен progpow::hash іске қосады. Ол қайтаратын mix жұмыстың орындалғанының жанама өнімі. Бұл жадыны көп қажет ететін жол, ал жадыны көп қажет ету KAWPOW-тың қарапайым хеш болмауының бүкіл себебі.
Екіншісі мұндай параметр алмайды, өйткені ештеңе жасамайды. Ол тақырыпта тұрған дайын mix мәнін progpow::hash_no_verify(blockHeader.nHeight, header_hash, to_hash256(blockHeader.mix_hash.GetHex()), blockHeader.nNonce64) арқылы пайдаланады. Бастапқы кітапхана бұл функцияны hash_no_verify деп атаған, және атауы дәл. Ол өзіне берілген мәннің үстінен соңғы араластыру қадамын орындап, жауапты қайтарады. Ол деректер жиынын ешқашан құрмайды, сондықтан өзіне берілген мән тек жұмыс орындалғанда ғана пайда бола алатынын ешқашан анықтамайды.
Екі функцияның ешқайсысы қате емес. Арзанының болуына жақсы себеп бар: кодқа қатаң жазылған бақылау нүктесі әлдеқашан шешкен миллиондаған ескі блокты синхрондайтын нода ешкім дауламайтын тарихты қайта растау үшін әр эпохада бірнеше гигабайттық деректер жиынын қайта құрмауы керек. Мұндай дизайн жауап беруге тиіс жалғыз сұрақ: бұл жолмен қай блоктарға жүруге рұқсат етіледі.
Қақпа және ол неге сенді
Бұл сұраққа validation.cpp ішіндегі CheckBlockHeader жауап береді, ал жауаптың үстіндегі түсініктеме ниетті анық айтады: «If we are checking a KAWPOW block below a know checkpoint height. We can validate the proof of work using the mix_hash». Ниет дұрыс. Іске асыру block.nHeight <= (uint32_t)pcheckpoint->nHeight шартына сүйенеді, ал block.nHeight блоктың өзі туралы өзі жазған саны.
Астындағы жол жалпы CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&) функциясын шақырады. Бұл сигнатурада не жоқ екеніне назар аударыңыз. Онда mix те, nonce те, тақырып та жоқ. Ол дайын хеш пен мақсатты алып, екеуін салыстырады, және өзіне берілген санды екі функцияның қайсысы жасағанын білуге ешқандай мүмкіндігі жоқ. KAWPOW блогы үшін CBlockHeader::GetHash() KAWPOWHash_OnlyMix(*this) қайтарады, сондықтан оған берілетін сан арзан жолдан келеді.
Бәрін қатар қойсақ, жеткілікті төмен nHeight мәлімдеген блок өз mix хешінен алынған мәннің мақсаттан төмен екенін сұрау арқылы валидацияланды. Бұл жолдың ешбір жерінде mix қайдан келгені сұралмады, және ешбір жерінде мәлімделген биіктік блоктың шын мәнінде алған орнымен салыстырылмады.
Қаншалықты төмен болуы жеткілікті екені мүлде нәзік мәселе емес болып шықты. Шығарылған mainnet желі параметрлеріндегі ең жоғары бақылау нүктесі 2 383 550. Алғашқы жалған блок 4 487 776 биіктігінде тұрды. Оның тақырыбы шын мәнінде тұрған жерінен шамамен 2,1 миллион блок артта тұрған орынды мәлімдеуі керек болды, ал осылайша таңдалған тармақ бұл айырмашылыққа ешқашан қарамады.
Қысқа жол не берді және не бермеді
Мұнда дәл болған жөн, өйткені жарияланымдардың көбі бұл жағынан шалағай болды, ал шалағай нұсқа қатені шынайысынан әрі қарапайым, әрі оғаш етіп көрсетеді.
Қысқа жол күрделілікті төмендеткен жоқ. nBits нақты алдыңғы блок талап ететін мәнмен салыстырылып тексеріледі, ал нақты алдыңғы блокты hashPrevBlock таңдайды, оны шабуылдаушы бұрмалап, бәрібір желінің ұшына түсе алмайды. Жалған блок дәл сол минутта майнингтелген адал блоктағыдай дәл сол мақсаттан өтуі керек еді.
Өзгергені бір болжамның бағасы болды. Адал майнер әр әрекет үшін гигабайтпен өлшенетін деректер жиынын толық өтумен төлейді, жадыны көп қажет ететін алгоритмнің бүкіл мәні осында, KAWPOW ASIC құрылғыларын Ravencoin-нен алты жыл бойы аулақ ұстап келгенінің себебі де осы. Қысқа жол тақырыптың бір хешіне және шабуылдаушы еркін таңдаған мәннің үстінен бір соңғы араластыру қадамына ғана түседі. Сол лотерея, әр билеттегі сол мүмкіндік, бірақ билеттер бірнеше шама ретіне арзан. 2Miners нәтижелерді жұмысы нөлге жуық блоктар деп сипаттады, және KAWPOW қанша тұруы тиіс екенімен салыстырғанда бұл әділ сипаттама.
Желіде не болды
Белгілі алғашқы жарамсыз блок 4 487 776 биіктігінде, уақыт белгісі 2026-08-07 15:44:01 UTC. Осалдықты пайдалану 10 тамыздағы шұғыл шығарылымға дейін жалғасты. 2 089 блоктан тұратын бір тексерілген бөлікте 2Miners 96 зардап шеккен блокты санады, яғни жалған блоктар бір тізбекте бірге тұрмай, тармақ бойына шашырап орналасқан, сондықтан шешім нүктелі алып тастау емес, қайта ұйымдастыру болуы керек еді.
Нода операторлары үшін көрінетін белгі жарамсыз блоктың үнсіз қабылдануынан да жаман болды. Нодалар осы блоктарда құлады, ал қайта іске қосылғаннан кейін синхрондауды тоқтатты. Tron Black кейін бұл механизмді сипаттады, және бұл жанама зақымның ұқыпты үлгісі. Блок индексі блок тақырыбы мәлімдеген биіктікті емес, оның шын мәнінде тұрған биіктігін сақтайды. Қайта іске қосылғанда нода әр тақырыпты индекстен қайта құрып, оның хешін қайта есептейді, сондықтан жалған блок үшін ол тақырыпта жалған биіктік тұрған жерде нақты биіктікті хештейді. Хеш енді сәйкес келмейді, жұмыс дәлелі тексеруі өтпейді, және LoadBlockIndexGuts тоқтайды. Блок бір рет қабылданды, содан кейін жүктелмейтін болды, сондықтан екінші белгі біріншісінен ұзақ сақталды.
Тармақ шешілмей тұрғанда бірнеше биржа RVN салу мен шығаруды тоқтата тұрды. Бұл жақын тарихы қайта жазылғалы тұрған желіге кәдімгі әрі дұрыс жауап, оны монета туралы үкім деп оқымай, күтуге болатын нәрсе деп білген жөн.
Түзету және оның қайдан келгені
Алғашқы түзету 10 тамызда 4.6.1.1-hf1 нұсқасы ретінде шықты, және ол Ravencoin жобасынан емес, 2Miners майнинг пулынан келді. Оны орнатқандардың бәрі үшін ол залалды тоқтатты. Бір күннен кейін оны жаңа нұсқа алмастырды.
11 тамызда Ravencoin репозиторийі арқылы жарияланған 4.8.0 нұсқасы іске қосу керек шығарылым. Одан ертерек нұсқамен шектелмеңіз. Ол 4 487 776 биіктігінен бастап тақырыпта мәлімделген биіктігі нақты орнына сәйкес келмейтін блоктарды қабылдамайды, 4 487 775 блогын соңғы таза блок ретінде бақылау нүктесіне алады, бүлінген желі күйін тоқтап қалмай автоматты түрде қайта құрады, және шұғыл түзетуде болмаған актив аударымының толып кетуін түзетуді, сондай-ақ бастапқы жобадағы басқа жұмыстарды қамтиды.
Олардың тек біріншісі ғана жөндеу. Мәлімделген биіктігі шын мәнінде тұрған жеріне сәйкес келмейтін блокты қабылдамасаңыз, қақпа жабылады. Бақылау нүктесі мен автоматты қайта құру қалпына келтіруге жатады, ал бақылау нүктесі әсіресе дөрекі құрал: бұл бір нақты блоктың дұрыс екені туралы кодқа қатаң жазылған тұжырым, ал желі мұндай нәрсені мүмкіндігінше аз қалайды. Ол мұнда адал тармақты тек хешрейт бекітетіннен тезірек бекіту керек болғандықтан тұр.
Қалпына келтіру нүктесінің өзі айқын шешім емес, пайымдау мәселесі болды. Tron Black қайта ұйымдастыруды таязырақ етіп, жалған блоктарды ерекшелік ретінде өңдеу үшін пулдардан жақынырақ кесу нүктесін қарастыруды сұрағанын жазды. Олар бас тартып, мүмкін болатын ең таза сызықты таңдады. Жұмыс дәлелі жүйесінде бұл дау өзінен-өзі шешіледі: адал хешрейттің көпшілігі тарихтан бас тартса, сол тарих жеңіледі, ал екі ең ірі пулдың бірлескен үлесі көпшілікті құрады.
Үш күндік реорг шын мәнінде нені білдіреді
Осал нодалар жалған блоктарды қабылдағандықтан, оларды қамтитын тармақтың үстіне шынайы желі жиналды. Оны тастау қайта ұйымдастыруды білдіреді, ал Ravencoin-нің бір минуттық блок мақсатында 4 487 776 биіктігінен түзетуге дейінгі аралық шамамен үш күндік блоктар.
Егер Сізде RVN болса, іс жүзінде бұл тасталған тармақта расталған транзакциялардың енді расталған болып саналмайтынын білдіреді. Олардың көбі mempool-ға қайтып, сақталған желіде қайта майнингтеледі, бірақ бұған кепілдік жоқ, ал олардың бір түрі мүлде қайта алмайды. Тасталған блоктың coinbase-ін жұмсаған транзакция сақталған желіде енді жоқ монеталарды жұмсайды, оның үстіне құрылған кез келген нәрсе де солай. Олар күтудегі емес, жай ғана жарамсыз. Сондықтан биржалардың тоқтата тұруы асыра сілтеу емес, дұрыс шешім болды, және бір ұш бекітілгенге дейін 4 487 775 биіктігінен кейінгі белсенділікке сақ болу керек еді.
Сол аптада нодаңыз орнынан қозғалмай тұрғанын көрген болсаңыз, бір мәліметті білген жөн. Ravencoin нодаларында терең тарихты кенеттен көпшілік шабуылымен қайта жазуды тоқтату үшін ұзын реоргқа тыйым салатын ереже бар. Үздіксіз жұмыс істеп тұрған ескі нодалардың көбі ақыры бұл ереже сүйенетін пирлер санынан төмен түсіп, жобаланғандай ұзынырақ желіні қабылдады. Кейбіреулері қабылдамады, өйткені олар жеткілікті пирді ешқашан жоғалтпады және жазылған ережелер бойынша ештеңе бұзылмаған еді. Бұл ешқашан арналмаған мәселеде дәл көрсетілгендей жұмыс істеген қорғаныс. Бөліну көпшілікке шабуылдан емес, валидация ақауынан туды, ал ереже оларды ажырата алмайды.
RVN майнингтесеңіз не істеу керек
Өз Ravencoin нодаңызды жүргізсеңіз, 4.8.0 нұсқасын іске қосыңыз, мұның бір бөлігін ғана шешкен ертерек шығарылымдардың бірін емес. Нодаңызды тоқтатып, бинарлық файлды ауыстырып, қайта іске қосыңыз. Reindex жасаудың да, қолмен орындалатын қадамның да қажеті жоқ: бағдарлама қажетін өзі қайта құрады. Шұғыл түзетуден келген нода тез қайта іске қосылады. Түзетілмеген бағдарламадан келген нода желіні қайта ойнатып, қайта құруы керек, бұл қарапайым жабдықта бірнеше сағатқа созылады, ал осы уақыт бойы шығатын bad-blk-height қателері түзетудегі ақау емес, оның жұмыс істеп жатқанының белгісі.
Пул арқылы майнинг жасасаңыз, Сіз тарапынан өзгертетін ештеңе жоқ. Жаңа мекенжай да, жаңа порт та, майнер жаңартуы да қажет емес. Мұнда KAWPOW-тың өзі ешқашан мәселе болған жоқ: алгоритм дәл жобаланған нәрсені істеді, ал ақау оны қашан іске қосу керегін шешетін кодта болды. Ескі тармаққа бағыттаған хешрейтіңіз нақты жұмыс болды. Ол жай ғана арасына жалған блоктар шашыраған, солармен бірге тасталған блоктарға түсті.
Дұрыс желіге түскеніңізді растаудың бір жолдық тәсілі бар, оны болжап қоймай, орындаған жөн. 4 494 143 блогының хешін тексеріңіз. Канондық желіде ол 4c67d6a4 деп аяқталады, және жоба желі қалпына келді деп жариялаған кезде тәуелсіз Ravencoin эксплорерлерінің бәрі дәл осы желіні көрсетіп тұрды.
Қатенің пішіні
Нақты мәліметтерді алып тастасаңыз, желілерде де, олардан тыс жерде де үнемі қайталанатын пішін қалады. Сырттан келген мән дәл сол мәннің қаншалықты мұқият тексерілетінін шешу үшін пайдаланылды. Тақырып өз биіктігін мәлімдеді, ал нода сол мәлімдемені тақырып кейін қай жұмыс дәлелі тексеруінен өтуі керек екенін таңдау үшін пайдаланды.
Дұрыс нұсқасы күрделі емес, ал түзету негізінен оның бір жолы: мәлімделген биіктікке бірдеңе шешуге рұқсат бермес бұрын оны блоктың шын мәнінде алған орнымен салыстыру. Оның неге жоқ болғаны қызықтырақ жартысы. Қысқа жол әлдеқашан сенім артылған блоктар үшін жазылған, және сол болжам ішінде қақпа біреу адал емес жауап беруі мүмкін сұрақ ретінде емес, факт туралы мәлімдеме ретінде оқылады. Сенімсіз блокқа өрісті толтыруға рұқсат етілген сәтте ол олай оқылмайды, ал кодтағы ештеңе бұл өзгерген сәтті белгілемеді.
Оның қалай табылғаны туралы екі нәрсені жазып қойған жөн. Ravencoin коды кәсіби қауіпсіздік аудиттерінен өткен, бірақ олар мұны да, онымен қатар түзетілген актив толып кетуін де анықтамады. Tron Black екеуін де озық AI моделінің қауіпсіздік шолуы тапты деп қатты күдіктенетінін жазды. Құрал қандай болса да, бұл пішінге сәйкес келеді: қысқа жолды өз шарттарымен оқығанда ақау көрінбейді, ол тек қысқа жол сенетін өрісті кім толтыратынын сұрағанда ғана пайда болады.
Соңғы назар аударарлық нәрсе: кім және қандай ретпен әрекет етті. Майнинг пулы валидация жолын оқып, түсініп, үш күн ішінде шұғыл бинарлық файл шығарды. Содан кейін екі ең ірі пул ыңғайлы кесуді таңдамай, бүкіл шабуыл терезесін тастайтын желіні майнингтеуге келісті, ал таязырақ нұсқаны алу сұралғанда бас тартты. Жоба бір күннен кейін шұғыл түзетуді алмастыратын және одан көбірек түзететін шығарылыммен ілесті. Олардың қайсысы бірінші болғаны екеуінің де болғанынан аз маңызды, ал мәселені шын мәнінде шешкен нәрсе ешбір хабарландыру емес, бөлінудің бір жағындағы нақты жұмыстың жинақталған салмағы болды. Орталықсыздандыру ақ қағазда тұрмай, салмақ көтеруге тура келген күні осылай көрінеді.
Бұл сандар қайдан алынған
Біздің сөзімізге сенбей, кез келген адам тексере алуы үшін. Тақырып құрылымы, екі хеш-функция мен олардың сигнатуралары, эпоха таңдау және түсініктемесі бар валидация тармағы Ravencoin-нің өз бастапқы кодынан, src/primitives/block.h, src/primitives/block.cpp, src/hash.cpp, src/hash.h, src/pow.h және src/validation.cpp файлдарынан оқылған. Бақылау нүктелерінің тізімі, соның ішінде mainnet-тегі ең жоғарысы 2 383 550, src/chainparams.cpp файлынан оқылған. Алғашқы жарамсыз биіктік пен оның уақыт белгісі Ravencoin жобасының өз желі хабарламасынан алынған. Блок индексінің құлау жолы, қайта алмайтын coinbase-ке тәуелді транзакциялар, ұзын реоргқа тыйым салу әрекеті, бас тартылған таязырақ қалпына келтіру нүктесі, аудит пен AI шолуы туралы ескертпелер, 4.8.0 нұсқасының құрамы және 4 494 143 тексеруі Tron Black-тің Ravencoin жобасы атынан берген баяндамасынан алынған. Шұғыл түзету нұсқасы мен 2 089 блоктың ішіндегі 96 зардап шеккен блок саны 2Miners шығарылымынан және оның төңірегіндегі жарияланымдардан алынған. Дереккөздерде айтылмаған кез келген нәрсе бұл мақалада толтырылмай, алынып тасталды.