Ruka hadi kwenye maudhui makuu
Change page

Dagger-Hashimoto

Ukurasa ulisasishwa mwisho: 3 Aprili 2026

Dagger-Hashimoto ilikuwa utekelezaji wa awali wa utafiti na maelezo ya kanuni ya uchimbaji ya Ethereum. Dagger-Hashimoto ilibadilishwa na Ethash. Uchimbaji ulizimwa kabisa wakati wa Muungano mnamo tarehe 15 Septemba 2022. Tangu wakati huo, Ethereum imekuwa ikilindwa kwa kutumia utaratibu wa uthibitisho wa hisa badala yake. Ukurasa huu ni kwa ajili ya maslahi ya kihistoria - maelezo yaliyomo hapa hayahusiani tena na Ethereum ya baada ya Muungano.

Mahitaji ya awali

Ili kuelewa ukurasa huu vizuri zaidi, tunapendekeza kwanza usome kuhusu makubaliano ya uthibitishaji-wa-kazi, uchimbaji, na kanuni za uchimbaji.

Dagger-Hashimoto

Dagger-Hashimoto inalenga kutimiza malengo mawili:

  1. Ukinzani-wa-ASIC: faida ya kutengeneza maunzi maalum kwa ajili ya kanuni inapaswa kuwa ndogo iwezekanavyo
  2. Uthibitisho wa mteja mwepesi: bloku inapaswa kuthibitishwa kwa ufanisi na mteja mwepesi.

Kwa marekebisho ya ziada, pia tunaeleza jinsi ya kutimiza lengo la tatu ikiwa inahitajika, lakini kwa gharama ya utata wa ziada:

Hifadhi kamili ya mnyororo: uchimbaji unapaswa kuhitaji hifadhi ya hali kamili ya mnyororo wa bloku (kutokana na muundo usio wa kawaida wa trie ya hali ya Ethereum, tunatarajia kuwa upunguzaji fulani utawezekana, hasa wa baadhi ya mikataba inayotumiwa mara kwa mara, lakini tunataka kupunguza hili).

Uzazi wa DAG

Msimbo wa kanuni utaelezwa katika Python hapa chini. Kwanza, tunatoa encode_int kwa ajili ya kupanga nambari kamili zisizo na alama za usahihi maalum kuwa mifuatano. Kinyume chake pia kimetolewa:

Ifuatayo, tunadhani kwamba sha3 ni chaguo la kukokotoa linalochukua nambari kamili na kutoa nambari kamili, na dbl_sha3 ni chaguo la kukokotoa la double-sha3; ikiwa unabadilisha msimbo huu wa marejeleo kuwa utekelezaji, tumia:

Vigezo

Vigezo vinavyotumika kwa kanuni ni:

P katika kesi hii ni nambari kuu iliyochaguliwa kiasi kwamba log₂(P) ni chini kidogo ya 512, ambayo inalingana na biti 512 ambazo tumekuwa tukitumia kuwakilisha nambari zetu. Kumbuka kwamba ni nusu ya mwisho tu ya DAG ndiyo inayohitaji kuhifadhiwa, kwa hivyo mahitaji halisi ya RAM huanza kwa GB 1 na kukua kwa MB 441 kwa mwaka.

Uundaji wa grafu ya Dagger

Asili ya uundaji wa grafu ya dagger imefafanuliwa kama ifuatavyo:

Kimsingi, inaanza grafu kama nodi moja, sha3(seed), na kutoka hapo huanza kuongeza kwa mfuatano nodi zingine kulingana na nodi za awali za nasibu. Wakati nodi mpya inaundwa, nguvu ya kimodula ya mbegu huhesabiwa ili kuchagua kwa nasibu fahirisi fulani zilizo chini ya i (kwa kutumia x % i hapo juu), na thamani za nodi kwenye fahirisi hizo hutumiwa katika hesabu ili kuzalisha thamani mpya ya x, ambayo hupelekwa kwenye chaguo dogo la uthibitisho wa kazi (kulingana na XOR) ili hatimaye kuzalisha thamani ya grafu kwenye fahirisi i. Sababu ya muundo huu maalum ni kulazimisha ufikiaji wa mfuatano wa DAG; thamani inayofuata ya DAG itakayofikiwa haiwezi kubainishwa hadi thamani ya sasa ijulikane. Mwishowe, upeo wa kimodula huhasisha matokeo zaidi.

Kanuni hii inategemea matokeo kadhaa kutoka kwa nadharia ya nambari. Tazama kiambatisho hapa chini kwa majadiliano.

Tathmini ya mteja mwepesi

Uundaji wa grafu hapo juu unakusudia kuruhusu kila nodi kwenye grafu kujengwa upya kwa kukokotoa mti mdogo wa idadi ndogo tu ya nodi na kuhitaji kiasi kidogo tu cha kumbukumbu saidizi. Kumbuka kuwa kwa k=1, mti mdogo ni mnyororo tu wa thamani zinazopanda hadi kwenye elementi ya kwanza katika DAG.

Chaguo la kukokotoa la kompyuta ya mteja mwepesi kwa DAG hufanya kazi kama ifuatavyo:

Kimsingi, ni uandishi upya wa kanuni iliyo hapo juu ambao huondoa kitanzi cha kukokotoa thamani za DAG nzima na kubadilisha utafutaji wa nodi ya awali na wito wa kujirudia au utafutaji wa kache. Kumbuka kuwa kwa k=1 kache si lazima, ingawa uboreshaji zaidi kwa kweli huhesabu mapema thamani elfu chache za kwanza za DAG na kuweka hiyo kama kache tuli kwa ajili ya hesabu; tazama kiambatisho kwa utekelezaji wa msimbo wa hili.

Bafa maradufu ya DAGs

Katika mteja kamili, bafa maradufu (opens in a new tab) ya DAGs 2 zinazozalishwa na fomula iliyo hapo juu hutumiwa. Wazo ni kwamba DAGs huzalishwa kila epochtime idadi ya bloku kulingana na vigezo vilivyo hapo juu. Badala ya mteja kutumia DAG ya hivi karibuni iliyozalishwa, hutumia ile ya awali. Faida ya hili ni kwamba inaruhusu DAGs kubadilishwa kwa muda bila kuhitaji kujumuisha hatua ambapo wachimbaji lazima ghafla wahesabu upya data yote. Vinginevyo, kuna uwezekano wa kupungua kwa ghafla kwa muda katika usindikaji wa mnyororo kwa vipindi vya kawaida na kuongezeka kwa kiasi kikubwa kwa umilikishwaji. Hivyo hatari za shambulizi la asilimia 51% ndani ya dakika hizo chache kabla ya data yote kuhesabiwa upya.

Kanuni inayotumika kuzalisha seti ya DAGs zinazotumika kukokotoa kazi kwa ajili ya bloku ni kama ifuatavyo:

Hashimoto

Wazo la awali la Hashimoto ni kutumia mnyororo wa bloku kama seti ya data, kufanya hesabu inayochagua fahirisi za N kutoka kwenye mnyororo wa bloku, kukusanya miamala kwenye fahirisi hizo, kufanya XOR ya data hii, na kurudisha hashi ya matokeo. Kanuni ya awali ya Thaddeus Dryja, iliyotafsiriwa kwa Python kwa ajili ya uwiano, ni kama ifuatavyo:

def orig_hashimoto(prev_hash, merkle_root, list_of_transactions, nonce):
    hash_output_A = sha256(prev_hash + merkle_root + nonce)
    txid_mix = 0
    for i in range(64):
        shifted_A = hash_output_A >> i
        transaction = shifted_A % len(list_of_transactions)
        txid_mix ^= list_of_transactions[transaction] << i
    return txid_mix ^ (nonce << 192)

Kwa bahati mbaya, ingawa Hashimoto inachukuliwa kuwa ngumu kwa RAM, inategemea hesabu za biti 256, ambazo zina gharama kubwa za kikokotozi. Hata hivyo, Dagger-Hashimoto hutumia tu biti 64 za chini kabisa wakati wa kufaharisi seti yake ya data ili kushughulikia suala hili.

def hashimoto(dag, dagsize, params, header, nonce):
    m = dagsize / 2
    mix = sha3(encode_int(nonce) + header)
    for _ in range(params["accesses"]):
        mix ^= dag[m + (mix % 2**64) % m]
    return dbl_sha3(mix)

Matumizi ya SHA3 maradufu huruhusu aina ya uthibitishaji wa awali wa data-sifuri, karibu wa papo hapo, kuthibitisha tu kwamba thamani sahihi ya kati ilitolewa. Safu hii ya nje ya uthibitishaji-wa-kazi inafaa sana kwa ASIC na ni dhaifu kiasi, lakini ipo ili kufanya DDoS iwe ngumu zaidi kwa kuwa kiasi hicho kidogo cha kazi lazima kifanyike ili kuzalisha bloku ambayo haitakataliwa mara moja. Hii ndiyo toleo la mteja-mwepesi:

def quick_hashimoto(seed, dagsize, params, header, nonce):
    m = dagsize // 2
    mix = sha3(nonce + header)
    for _ in range(params["accesses"]):
        mix ^= quick_calc(params, seed, m + (mix % 2**64) % m)
    return dbl_sha3(mix)

Uchimbaji na uthibitishaji

Sasa, hebu tuviweke vyote pamoja katika kanuni ya uchimbaji:

Hii ndiyo kanuni ya uthibitishaji:

def verify(daggerset, params, block, nonce):
    result = hashimoto(daggerset, get_dagsize(params, block),
                       params, decode_int(block.prevhash), nonce)
    return result * params["diff"] < 2**256

Uthibitishaji unaofaa kwa mteja-mwepesi:

def light_verify(params, header, nonce):
    seedset = get_seedset(params, block)
    result = quick_hashimoto(seedset["front_hash"], get_dagsize(params, block),
                             params, decode_int(block.prevhash), nonce)
    return result * params["diff"] < 2**256

Pia, kumbuka kuwa Dagger-Hashimoto inaweka mahitaji ya ziada kwenye kichwa cha bloku:

  • Ili uthibitishaji wa safu-mbili ufanye kazi, kichwa cha bloku lazima kiwe na nonce na thamani ya kati kabla ya sha3
  • Mahali fulani, kichwa cha bloku lazima kihifadhi sha3 ya seti ya mbegu ya sasa

Masomo zaidi

Unajua rasilimali ya jamii iliyokusaidia? Hariri ukurasa huu na uiongeze!_

Kiambatisho

Kama ilivyoelezwa hapo juu, RNG inayotumika kwa uzalishaji wa DAG inategemea matokeo fulani kutoka kwa nadharia ya nambari. Kwanza, tunatoa uhakikisho kwamba Lehmer RNG ambayo ni msingi wa kigezo cha picker ina kipindi kirefu. Pili, tunaonyesha kwamba pow(x,3,P) haitapanga x kwa 1 au P-1 mradi x ∈ [2,P-2] mwanzoni. Mwishowe, tunaonyesha kwamba pow(x,3,P) ina kiwango cha chini cha mgongano inapotumika kama chaguo la kukokotoa la uhasishaji.

Jenereta ya nambari nasibu ya Lehmer

Ingawa chaguo la kukokotoa la produce_dag halihitaji kutoa nambari nasibu zisizo na upendeleo, tishio linalowezekana ni kwamba seed**i % P huchukua thamani chache tu. Hii inaweza kuwapa faida wachimbaji wanaotambua mchoro kuliko wale wasiotambua.

Ili kuepuka hili, matokeo kutoka kwa nadharia ya nambari yanatumika. Nambari Kuu Salama (opens in a new tab) inafafanuliwa kuwa nambari kuu P kiasi kwamba (P-1)/2 pia ni nambari kuu. Mpangilio wa mwanachama x wa kikundi cha kuzidisha (opens in a new tab) ℤ/nℤ unafafanuliwa kuwa m ndogo zaidi kiasi kwamba

xᵐ mod P ≡ 1
Kutokana na ufafanuzi huu, tuna:

Uchunguzi 1. Acha x iwe mwanachama wa kikundi cha kuzidisha ℤ/Pℤ kwa nambari kuu salama P. Ikiwa x mod P ≠ 1 mod P na x mod P ≠ P-1 mod P, basi mpangilio wa x ni P-1 au (P-1)/2.

Uthibitisho. Kwa kuwa P ni nambari kuu salama, basi kwa [Nadharia ya Lagrange][lagrange] tuna kwamba mpangilio wa x ni 1, 2, (P-1)/2, au P-1.

Mpangilio wa x hauwezi kuwa 1, kwa kuwa kwa Nadharia Ndogo ya Fermat tuna:

xP-1 mod P ≡ 1

Kwa hiyo x lazima iwe utambulisho wa kuzidisha wa ℤ/nℤ, ambayo ni ya kipekee. Kwa kuwa tulidhani kwamba x ≠ 1 kwa dhana, hili haliwezekani.

Mpangilio wa x hauwezi kuwa 2 isipokuwa x = P-1, kwa kuwa hili lingekiuka kwamba P ni nambari kuu.

Kutoka kwa pendekezo lililo hapo juu, tunaweza kutambua kwamba kurudia (picker * init) % P kutakuwa na urefu wa mzunguko wa angalau (P-1)/2. Hii ni kwa sababu tulichagua P kuwa nambari kuu salama takriban sawa na kuwa nguvu ya juu ya mbili, na init iko katika muda wa [2,2**256+1]. Kutokana na ukubwa wa P, hatupaswi kamwe kutarajia mzunguko kutoka kwa upeo wa kimodula.

Tunapogawa seli ya kwanza katika DAG (kigezo kilichoandikwa init), tunakokotoa pow(sha3(seed) + 2, 3, P). Kwa mtazamo wa kwanza, hili halihakikishi kwamba matokeo si 1 wala P-1. Hata hivyo, kwa kuwa P-1 ni nambari kuu salama, tuna uhakikisho wa ziada ufuatao, ambao ni matokeo ya Uchunguzi 1:

Uchunguzi 2. Acha x iwe mwanachama wa kikundi cha kuzidisha ℤ/Pℤ kwa nambari kuu salama P, na acha w iwe nambari asilia. Ikiwa x mod P ≠ 1 mod P na x mod P ≠ P-1 mod P, na vile vile w mod P ≠ P-1 mod P na w mod P ≠ 0 mod P, basi xʷ mod P ≠ 1 mod P na xʷ mod P ≠ P-1 mod P

Upeo wa kimodula kama chaguo la kukokotoa la hashi

Kwa thamani fulani za P na w, chaguo la kukokotoa la pow(x, w, P) linaweza kuwa na migongano mingi. Kwa mfano, pow(x,9,19) huchukua tu thamani za {1,18}.

Kwa kuwa P ni nambari kuu, basi w inayofaa kwa chaguo la kukokotoa la uhasishaji wa upeo wa kimodula inaweza kuchaguliwa kwa kutumia matokeo yafuatayo:

Uchunguzi 3. Acha P iwe nambari kuu; w na P-1 ni nambari kuu za jamaa ikiwa na tu ikiwa kwa a na b zote katika ℤ/Pℤ:

aʷ mod P ≡ bʷ mod P ikiwa na tu ikiwa a mod P ≡ b mod P

Hivyo, kwa kuwa P ni nambari kuu na w ni nambari kuu ya jamaa na P-1, tuna |{pow(x, w, P) : x ∈ ℤ}| = P, ikimaanisha kwamba chaguo la kukokotoa la uhasishaji lina kiwango cha chini zaidi cha mgongano kinachowezekana.

Katika kesi maalum ambapo P ni nambari kuu salama kama tulivyochagua, basi P-1 ina vigawanyo 1, 2, (P-1)/2 na P-1 pekee. Kwa kuwa P > 7, tunajua kwamba 3 ni nambari kuu ya jamaa na P-1, kwa hivyo w=3 inakidhi pendekezo lililo hapo juu.

Kanuni ya tathmini yenye ufanisi zaidi inayotegemea kache

Je, makala haya yalikuwa ya msaada?