பிரதான உள்ளடக்கத்திற்குச் செல்
Change page

Dagger-Hashimoto

பக்கத்தின் கடைசி புதுப்பிப்பு: 11 ஏப்ரல், 2024

Dagger-Hashimoto என்பது எத்தீரியத்தின் மைனிங் அல்காரிதமிற்கான முதன்மை ஆராய்ச்சி செயலாக்கம் மற்றும் விவரக்குறிப்பு ஆகும். Dagger-Hashimoto Ethash மூலம் மாற்றப்பட்டது. 15 செப்டம்பர் 2022 அன்று The Merge நிகழ்வில் மைனிங் முழுமையாக நிறுத்தப்பட்டது. அதன் பிறகு, எத்தீரியம் ஒரு ப்ரூஃப்-ஆஃப்-ஸ்டேக் முறைமையைப் பயன்படுத்தி பாதுகாக்கப்படுகிறது. இந்த பக்கம் வரலாற்றுப் பார்வைக்காகவே உள்ளது - இங்கு உள்ள தகவல்கள் Merge பிற எத்தீரியத்திற்கு தொடர்பானவை அல்ல.

முன்னேற்றக் கட்டுரை

இந்தப் பக்கத்தை சிறப்பாகப் புரிந்து கொள்ள, முதலில் ப்ரூஃப்-ஆஃப்-வொர்க் கன்சென்சஸ், மைனிங் மற்றும் மைனிங் அல்காரிதம்களைப் பற்றிப் படிக்குமாறு பரிந்துரைக்கிறோம்.

Dagger-Hashimoto

Dagger-Hashimoto இரண்டு குறிக்கோள்களை நிறைவேற்றுவதற்கான முயற்சியாகும்:

  1. ASIC-எதிர்ப்பு: அல்காரிதமுக்கான சிறப்பு வன்பொருளை உருவாக்குவதன் மூலம் கிடைக்கும் நன்மை முடிந்தவரை சிறியதாக இருக்க வேண்டும்
  2. லைட் கிளையன்ட் சரிபார்ப்புத்தன்மை: ஒரு பிளாக்கை லைட் கிளையன்ட் மூலம் திறமையாகச் சரிபார்க்கக்கூடியதாக இருக்க வேண்டும்.

மேலும் ஒரு திருத்தத்துடன், நாம் விரும்பினால் மூன்றாவது குறிக்கோளை நிறைவேற்றுவதற்கான முறையையும் குறிப்பிடுகிறோம், ஆனால் கூடுதல் சிக்கலின் விலைக்கு:

முழுச் சங்கிலி சேமிப்பு: மைனிங்கிற்கு முழுமையான பிளாக்செயின் நிலையைச் சேமிக்க வேண்டும் (Ethereum நிலை ட்ரை-யின் ஒழுங்கற்ற அமைப்பு காரணமாக, சில கத்தரிப்புகள் சாத்தியமாகும் என்று நாங்கள் எதிர்பார்க்கிறோம், குறிப்பாக சில அடிக்கடி பயன்படுத்தப்படும் ஒப்பந்தங்களில், ஆனால் இதை நாங்கள் குறைக்க விரும்புகிறோம்).

DAG உருவாக்கம்

அல்காரிதமுக்கான குறியீடு பைதானில் கீழே வரையறுக்கப்படும். முதலில், குறிப்பிட்ட துல்லியத்தின் குறியிடப்படாத முழு எண்களை சரங்களாக மார்ஷல் செய்வதற்கு encode_int-ஐ வழங்குகிறோம். இதன் எதிர்மறை குறியீடும் வழங்கப்பட்டுள்ளது:

1NUM_BITS = 512
2
3def encode_int(x):
4 "ஒரு முழு எண் x-ஐ பிக்-எண்டியன் முறையைப் பயன்படுத்தி 64 எழுத்துகள் கொண்ட ஒரு சரமாக குறியாக்கம் செய்யவும்"
5 o = ''
6 for _ in range(NUM_BITS / 8):
7 o = chr(x % 256) + o
8 x //= 256
9 return o
10
11def decode_int(s):
12 "பிக்-எண்டியன் முறையைப் பயன்படுத்தி ஒரு சரத்திலிருந்து ஒரு முழு எண் x-ஐ குறியாக்கம் நீக்கவும்"
13 x = 0
14 for c in s:
15 x *= 256
16 x += ord(c)
17 return x
அனைத்தையும் காட்டு

அடுத்து, sha3 என்பது ஒரு முழு எண்ணை எடுத்து மற்றொரு முழு எண்ணை வெளியிடும் ஒரு செயல்பாடு என்றும், dbl_sha3 என்பது ஒரு இரட்டை-sha3 செயல்பாடு என்றும் நாங்கள் கருதுகிறோம்; இந்த மேற்கோள் குறியீட்டை ஒரு செயல்படுத்தலாக மாற்றினால், இதைப் பயன்படுத்தவும்:

1from pyethereum import utils
2def sha3(x):
3 if isinstance(x, (int, long)):
4 x = encode_int(x)
5 return decode_int(utils.sha3(x))
6
7def dbl_sha3(x):
8 if isinstance(x, (int, long)):
9 x = encode_int(x)
10 return decode_int(utils.sha3(utils.sha3(x)))
அனைத்தையும் காட்டு

அளவுருக்கள்

அல்காரிதத்திற்கு பயன்படுத்தப்படும் அளவீடுகள்:

1SAFE_PRIME_512 = 2**512 - 38117 # 2**512-ஐ விடக் குறைவான மிகப்பெரிய பாதுகாப்பான பகா எண்
2
3params = {
4 "n": 4000055296 * 8 // NUM_BITS, # தரவுத்தொகுப்பின் அளவு (4 ஜிகாபைட்கள்); 65536-இன் பெருக்கலாக இருக்க வேண்டும்
5 "n_inc": 65536, # ஒரு காலப்பகுதிக்கு n மதிப்பின் அதிகரிப்பு; 65536-இன் பெருக்கலாக இருக்க வேண்டும்
6 # epochtime=20000 உடன் வருடத்திற்கு 882 MB வளர்ச்சியை அளிக்கிறது
7 "cache_size": 2500, # லைட் கிளையன்ட்டின் கேச் அளவு (லைட் கிளையன்ட்டால் தேர்ந்தெடுக்கப்படலாம்;
8 # அல்காரிதம் விவரக்குறிப்பின் பகுதியாக இல்லை)
9 "diff": 2**14, # சிரமம் (பிளாக் மதிப்பீட்டின் போது சரிசெய்யப்பட்டது)
10 "epochtime": 100000, # பிளாக்குகளில் ஒரு எபோக்கின் நீளம் (தரவுத்தொகுப்பு எவ்வளவு அடிக்கடி புதுப்பிக்கப்படுகிறது)
11 "k": 1, # ஒரு முனையின் பெற்றோர்களின் எண்ணிக்கை
12 "w": w, # மாடுலர் அடுக்குக்குறி ஹேஷிங்கிற்காகப் பயன்படுத்தப்படுகிறது
13 "accesses": 200, # ஹஷிமோட்டோவின் போது தரவுத்தொகுப்பு அணுகல்களின் எண்ணிக்கை
14 "P": SAFE_PRIME_512 # ஹேஷிங் மற்றும் சீரற்ற எண் உருவாக்கத்திற்கான பாதுகாப்பான பகா எண்
15}
அனைத்தையும் காட்டு

இந்த நேர்வில் P என்பது log₂(P) 512-ஐ விட சற்று குறைவாக இருக்கும்படி தேர்ந்தெடுக்கப்பட்ட ஒரு பகா எண் ஆகும், இது நமது எண்களைக் குறிக்க நாம் பயன்படுத்தும் 512 பிட்களுக்கு ஒத்திருக்கிறது. DAG இன் பின்னணி பாதி மட்டுமே சேமிக்கப்பட வேண்டும், எனவே de-facto RAM தேவைகள் 1 GB இல் தொடங்கி, ஆண்டுக்கு 441 MB ஆக வளர்கின்றன.

டாகர் வரைபட உருவாக்கம்

Dagger கிராப் கட்டமைப்பு அடிப்படை கீழே வரையறுக்கப்பட்டுள்ளது:

1def produce_dag(params, seed, length):
2 P = params["P"]
3 picker = init = pow(sha3(seed), params["w"], P)
4 o = [init]
5 for i in range(1, length):
6 x = picker = (picker * init) % P
7 for _ in range(params["k"]):
8 x ^= o[x % i]
9 o.append(pow(x, params["w"], P))
10 return o
அனைத்தையும் காட்டு

சாராம்சத்தில், இது ஒரு வரைபடத்தை sha3(seed) என்ற ஒற்றை முனையாகத் தொடங்குகிறது, மேலும் அங்கிருந்து சீரற்ற முந்தைய முனைகளின் அடிப்படையில் மற்ற முனைகளை வரிசையாகச் சேர்க்கத் தொடங்குகிறது. ஒரு புதிய முனை உருவாக்கப்படும் போது, i ஐ விட குறைவான சில குறியீடுகளை சீரற்ற முறையில் தேர்ந்தெடுக்க (மேலே x % i ஐப் பயன்படுத்தி) விதையின் ஒரு மாடுலர் பவர் கணக்கிடப்படுகிறது, மேலும் அந்தக் குறியீடுகளில் உள்ள முனைகளின் மதிப்புகள் x-க்கான புதிய மதிப்பை உருவாக்க ஒரு கணக்கீட்டில் பயன்படுத்தப்படுகின்றன, இது பின்னர் ஒரு சிறிய ப்ரூஃப் ஆஃப் வொர்க் செயல்பாட்டிற்கு (XOR அடிப்படையில்) அளிக்கப்பட்டு, இறுதியில் குறியீடு i-இல் வரைபடத்தின் மதிப்பை உருவாக்குகிறது. இந்த குறிப்பிட்ட வடிவமைப்பின் பின்னணி, DAG இன் தொடர்ச்சியான அணுகுமுறையை கட்டாயமாக்குவதாகும்; அடுத்த DAG மதிப்பு, தற்போதைய மதிப்பு தெரியும் வரை தீர்மானிக்க முடியாது. இறுதியில், மாடுலர் எExponentiation முடிவை மேலும் ஹாஷ் செய்கிறது.

இந்த அல்காரிதம் எண்கணிதத்திலிருந்து பல முடிவுகளைப் பொறுத்ததாக உள்ளது. விவாதத்திற்கான இணைப்பு கீழே உள்ளது.

லைட் கிளையன்ட் மதிப்பீடு

மேலே உள்ள கிராப் கட்டமைப்பு, கிராப் உள்ள ஒவ்வொரு நொடியையும் மீட்டமைக்க, சில நொடிகளை மட்டுமே கணக்கீடு செய்வதன் மூலம் மற்றும் சிறிய அளவிலான உதவியாளர் நினைவகத்தை மட்டுமே தேவைப்படும் வகையில் உருவாக்கப்பட்டுள்ளது. K=1 என்றால், துணை மரம் DAG இல் முதல் உறுப்பிற்கு செல்லும் மதிப்புகளின் சங்கிலியாகவே இருக்கும்.

DAG க்கான லைட் கிளையன்ட் கணக்கீட்டு செயல்முறை இதற்கானது:

1def quick_calc(params, seed, p):
2 w, P = params["w"], params["P"]
3 cache = {}
4
5 def quick_calc_cached(p):
6 if p in cache:
7 pass
8 elif p == 0:
9 cache[p] = pow(sha3(seed), w, P)
10 else:
11 x = pow(sha3(seed), (p + 1) * w, P)
12 for _ in range(params["k"]):
13 x ^= quick_calc_cached(x % p)
14 cache[p] = pow(x, w, P)
15 return cache[p]
16
17 return quick_calc_cached(p)
அனைத்தையும் காட்டு

அதாவது, இது மேலே உள்ள அல்காரிதத்தை மீண்டும் எழுதுவதற்காக, முழு DAG க்கான மதிப்புகளை கணக்கீடு செய்வதற்கான சுற்றத்தை அகற்றுகிறது மற்றும் முந்தைய நொடியின் தேடலை மீண்டும் அழைப்புடன் அல்லது கச்சே தேடலுடன் மாற்றுகிறது. k=1 க்கு கேச் தேவையற்றது என்பதைக் கவனியுங்கள், இருப்பினும் ஒரு மேலதிக மேம்படுத்தல் உண்மையில் DAG-இன் முதல் சில ஆயிரம் மதிப்புகளை முன்கூட்டியே கணக்கிட்டு, அதை கணக்கீடுகளுக்கான ஒரு நிலையான கேச்-ஆக வைத்திருக்கிறது; இதற்கான ஒரு குறியீட்டு செயலாக்கத்திற்கு பின் இணைப்பைப் பார்க்கவும்.

DAG-களின் இரட்டை இடையகம்

ஒரு முழு கிளையன்டில், மேலே உள்ள சூத்திரத்தால் உருவாக்கப்பட்ட 2 DAG-களின் ஒரு இரட்டை இடையகம் (opens in a new tab) பயன்படுத்தப்படுகிறது. மேலே உள்ள அளவுருக்களின்படி ஒவ்வொரு epochtime எண்ணிக்கை பிளாக்குகளுக்கும் DAG-கள் உருவாக்கப்படுகின்றன என்பதே இதன் யோசனை. கிளையன்ட் சமீபத்திய DAG ஐப் பயன்படுத்துவதற்குப் பதிலாக, முந்தையதைப் பயன்படுத்துகிறது. இதன் நன்மை, மைனர்கள் திடீரென அனைத்து தரவுகளையும் மீண்டும் கணக்கீடு செய்ய வேண்டிய படி, காலப்போக்கில் DAG களை மாற்ற அனுமதிக்கிறது. இல்லையெனில், அடிக்கடி சங்கிலி செயலாக்கத்தில் திடீர் தாமதம் ஏற்படுவதற்கான வாய்ப்பு உள்ளது, மேலும் மையமாக்கலை அதிகரிக்கும். எனவே, அனைத்து தரவுகளும் மீண்டும் கணக்கீடு செய்யும் முன் அந்த சில நிமிடங்களில் 51% தாக்குதல்களின் ஆபத்து உள்ளது.

ஒரு பிளாக்குக்கான வேலை கணக்கீடு செய்ய பயன்படுத்தப்படும் DAG களின் தொகுப்பை உருவாக்குவதற்கான அல்காரிதம் கீழே உள்ளது:

1def get_prevhash(n):
2 from pyethereum.blocks import GENESIS_PREVHASH
3 from pyethereum import chain_manager
4 if n <= 0:
5 return hash_to_int(GENESIS_PREVHASH)
6 else:
7 prevhash = chain_manager.index.get_block_by_number(n - 1)
8 return decode_int(prevhash)
9
10def get_seedset(params, block):
11 seedset = {}
12 seedset["back_number"] = block.number - (block.number % params["epochtime"])
13 seedset["back_hash"] = get_prevhash(seedset["back_number"])
14 seedset["front_number"] = max(seedset["back_number"] - params["epochtime"], 0)
15 seedset["front_hash"] = get_prevhash(seedset["front_number"])
16 return seedset
17
18def get_dagsize(params, block):
19 return params["n"] + (block.number // params["epochtime"]) * params["n_inc"]
20
21def get_daggerset(params, block):
22 dagsz = get_dagsize(params, block)
23 seedset = get_seedset(params, block)
24 if seedset["front_hash"] <= 0:
25 # பின்புல இடையகம் சாத்தியமில்லை, முன்பக்க இடையகத்தை மட்டும் உருவாக்கவும்
26 return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
27 "block_number": 0}}
28 else:
29 return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
30 "block_number": seedset["front_number"]},
31 "back": {"dag": produce_dag(params, seedset["back_hash"], dagsz),
32 "block_number": seedset["back_number"]}}
அனைத்தையும் காட்டு

ஹஷிமோட்டோ

முதன்மை ஹாஷிமோட்டோவின் யோசனை, பிளாக்செயினை ஒரு தரவுத்தொகுப்பாகப் பயன்படுத்துவது, பிளாக்செயினில் இருந்து N குறியீடுகளைத் தேர்ந்தெடுக்க, அந்த குறியீடுகளில் உள்ள பரிமாற்றங்களைப் சேகரித்து, இந்த தரவின் XOR ஐச் செய்யும் கணக்கீட்டைச் செய்வது, மற்றும் முடிவின் ஹாஷை திரும்ப அளிப்பதாகும். Thaddeus Dryja இன் முதன்மை அல்காரிதம், ஒத்திகைக்காக பைதானில் மொழிபெயர்க்கப்பட்டுள்ளது:

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

அவசியமாக, ஹாஷிமோட்டோ RAM கடினமாகக் கருதப்படும், ஆனால் இது 256-பிட் கணக்கீட்டில் அதிகமான கணக்கீட்டு சுமையை நம்புகிறது. இருப்பினும், Dagger-Hashimoto தனது தரவுத்தொகுப்பை அடையாளம் காண 64 பிட்ஸ்தான் பயன்படுத்துகிறது.

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

இரட்டை SHA3 பயன்படுத்துவது, ஒரு வகை பூஜ்ஜிய தரவுகளை, உடனடி முன்-சரிபார்ப்பு, சரியான இடைக்கால மதிப்பு வழங்கப்பட்டது என்பதை மட்டும் சரிபார்க்கிறது. இந்த வெளிப்புற ப்ரூஃப்-ஆஃப்-வொர்க் மிகக் குறைவான ASIC-க்கு உகந்தது மற்றும் மிகவும் பலவீனமானது, ஆனால் DDoS ஐ இன்னும் கடினமாக்குவதற்காகவே உள்ளது, ஏனெனில் ஒரு பிளாக்கை உடனடியாக நிராகரிக்கப்படாத வகையில் உருவாக்க, அந்த சிறிய அளவிலான வேலை செய்ய வேண்டும். இங்கு லைட்-கிளையன்ட் பதிப்பு உள்ளது:

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

மைனிங் மற்றும் சரிபார்த்தல்

இப்போது, இதனை மைனிங் அல்காரிதமாக ஒன்றிணைப்போம்:

1def mine(daggerset, params, block):
2 from random import randint
3 nonce = randint(0, 2**64)
4 while 1:
5 result = hashimoto(daggerset, get_dagsize(params, block),
6 params, decode_int(block.prevhash), nonce)
7 if result * params["diff"] < 2**256:
8 break
9 nonce += 1
10 if nonce >= 2**64:
11 nonce = 0
12 return nonce
அனைத்தையும் காட்டு

இங்கு சரிபார்ப்பு அல்காரிதம்:

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

லைட்-கிளையன்ட் நட்பு சரிபார்ப்பு:

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

மேலும், Dagger-Hashimoto பிளாக் தலைப்பில் கூடுதல் தேவைகளை விதிக்கிறது:

  • இரண்டு அடுக்கு சரிபார்ப்பு செயல்பட, ஒரு பிளாக் தலைப்பில் nonce மற்றும் மத்திய மதிப்பு முன்-sha3 இருக்க வேண்டும்
  • எங்கு வேண்டுமானாலும், ஒரு பிளாக் தலைப்பு தற்போதைய seedset இன் sha3 ஐ சேமிக்க வேண்டும்

மேலும் வாசிக்க

உங்களுக்கு உதவிய ஒரு சமூக வளம் பற்றி தெரியுமா? இந்தப் பக்கத்தைத் திருத்தி அதைச் சேர்க்கவும்!_

பின் இணைப்பு

மேலே குறிப்பிடப்பட்டுள்ளது போல, DAG உருவாக்கத்திற்கு பயன்படுத்தப்படும் RNG எண்கணிதத்தின் சில முடிவுகளை நம்புகிறது. முதலில், picker மாறிக்கு அடிப்படையாக இருக்கும் Lehmer RNG ஒரு பரந்த கால அளவைக் கொண்டுள்ளது என்ற உறுதியை நாங்கள் வழங்குகிறோம். இரண்டாவதாக, x ∈ [2,P-2] எனத் தொடங்கினால் pow(x,3,P) ஆனது x-ஐ 1 அல்லது P-1 க்கு மேப் செய்யாது என்பதை நாங்கள் காட்டுகிறோம். இறுதியாக, pow(x,3,P) ஒரு ஹேஷிங் செயல்பாடாகக் கருதப்படும்போது குறைந்த மோதல் விகிதத்தைக் கொண்டுள்ளது என்பதை நாங்கள் காட்டுகிறோம்.

Lehmer சீரற்ற எண் ஜெனரேட்டர்

produce_dag செயல்பாடு சார்பற்ற சீரற்ற எண்களை உருவாக்க வேண்டிய அவசியமில்லை என்றாலும், seed**i % P ஒரு சில மதிப்புகளை மட்டுமே எடுப்பது ஒரு சாத்தியமான அச்சுறுத்தலாகும். இது மைனர்களுக்குப் பயன்பாட்டைப் புரிந்துகொள்ளும் வாய்ப்பு அளிக்கலாம்.

இதிலிருந்து தவிர்க்க, எண்கணிதத்தின் ஒரு முடிவுக்கு கோரப்படுகிறது. ஒரு பாதுகாப்பான பகா எண் (opens in a new tab) என்பது P என்ற ஒரு பகா எண் என வரையறுக்கப்படுகிறது, அதில் (P-1)/2 என்பதும் ஒரு பகா எண்ணாக இருக்கும். பெருக்கல் குலம் (opens in a new tab) ℤ/nℤ-இன் உறுப்பினர் x-இன் வரிசை என்பது

xᵐ mod P ≡ 1
என இருக்கும்படியான குறைந்தபட்ச m என வரையறுக்கப்படுகிறது இந்த வரையறைகளைக் கொண்டு, நாம் பெறுவது:

கவனிப்பு 1. பாதுகாப்பான பகா எண் P-க்கான பெருக்கல் குலம் ℤ/Pℤ-இன் உறுப்பினராக x-ஐக் கொள்வோம். x mod P ≠ 1 mod P மற்றும் x mod P ≠ P-1 mod P எனில், x-இன் வரிசை P-1 அல்லது (P-1)/2 ஆக இருக்கும்.

நிரூபணம். P ஒரு பாதுகாப்பான பகா எண் என்பதால், [லக்ராஞ்சியின் தேற்றத்தின்][lagrange] படி x-இன் வரிசை 1, 2, (P-1)/2, அல்லது P-1 ஆக இருக்கும்.

x-இன் வரிசை 1 ஆக இருக்க முடியாது, ஏனெனில் ஃபெர்மாவின் சிறிய தேற்றத்தின்படி நாம் பெறுவது:

xP-1 mod P ≡ 1

எனவே x ஆனது ℤ/nℤ-இன் பெருக்கல் சமனியாக இருக்க வேண்டும், அது தனித்துவமானது. எடுகோளின்படி x ≠ 1 என நாம் கருதியதால், இது சாத்தியமில்லை.

x-இன் வரிசை 2 ஆக இருக்க முடியாது, x = P-1 ஆக இருந்தாலன்றி, ஏனெனில் இது P ஒரு பகா எண் என்பதை மீறும்.

மேற்கண்ட கூற்றிலிருந்து, (picker * init) % P-ஐ திரும்பத் திரும்பச் செய்வது குறைந்தது (P-1)/2 என்ற சுழற்சி நீளத்தைக் கொண்டிருக்கும் என்பதை நாம் அறியலாம். ஏனெனில், இரண்டின் உயர் அடுக்குக்கு ஏறக்குறைய சமமான ஒரு பாதுகாப்பான பகா எண்ணாக P-ஐ நாங்கள் தேர்ந்தெடுத்துள்ளோம், மற்றும் init என்பது [2,2**256+1] என்ற இடைவெளியில் உள்ளது. P-இன் பருமனைப் பார்க்கும்போது, மாடுலர் அடுக்குக்குறியிலிருந்து ஒரு சுழற்சியை நாம் ஒருபோதும் எதிர்பார்க்கக்கூடாது.

DAG-இல் உள்ள முதல் செல்லுக்கு ( init என பெயரிடப்பட்ட மாறி) மதிப்பை ஒதுக்கும்போது, pow(sha3(seed) + 2, 3, P)-ஐ கணக்கிடுகிறோம். முதல் பார்வையில், இதன் விளைவு 1 ஆகவோ அல்லது P-1 ஆகவோ இருக்காது என்பதற்கு இது உத்தரவாதம் அளிக்காது. இருப்பினும், P-1 ஒரு பாதுகாப்பான பகா எண் என்பதால், எங்களிடம் பின்வரும் கூடுதல் உறுதி உள்ளது, இது கவனிப்பு 1-இன் ஒரு கிளைத்தேற்றம் ஆகும்:

கவனிப்பு 2. பாதுகாப்பான பகா எண் P-க்கான பெருக்கல் குலம் ℤ/Pℤ-இன் உறுப்பினராக x-ஐயும், w ஒரு இயல் எண்ணாகவும் கொள்வோம். If x mod P ≠ 1 mod P and x mod P ≠ P-1 mod P, as well as w mod P ≠ P-1 mod P and w mod P ≠ 0 mod P, then xʷ mod P ≠ 1 mod P and xʷ mod P ≠ P-1 mod P

ஒரு ஹேஷ் செயல்பாடாக மாடுலர் அடுக்குக்குறி

P மற்றும் w-இன் சில மதிப்புகளுக்கு, pow(x, w, P) என்ற செயல்பாட்டில் பல மோதல்கள் இருக்கலாம். உதாரணமாக, pow(x,9,19) ஆனது {1,18} என்ற மதிப்புகளை மட்டுமே எடுக்கும்.

P ஒரு பகா எண் என்பதால், ஒரு மாடுலர் அடுக்குக்குறி ஹேஷிங் செயல்பாட்டிற்கு பொருத்தமான w-ஐ பின்வரும் முடிவைப் பயன்படுத்தித் தேர்ந்தெடுக்கலாம்:

கவனிப்பு 3. P ஒரு பகா எண்ணாக இருக்கட்டும்; ℤ/Pℤ-இல் உள்ள அனைத்து a மற்றும் b-க்கும் பின்வருமாறு இருந்தால், இருந்தால் மட்டுமே w மற்றும் P-1 சார்பகா எண்களாகும்:

aʷ mod P ≡ bʷ mod P என இருந்தால், இருந்தால் மட்டுமே a mod P ≡ b mod P ஆகும்

ஆக, P ஒரு பகா எண் மற்றும் w ஆனது P-1-க்கு சார்பகா எண்ணாக இருப்பதால், |{pow(x, w, P) : x ∈ ℤ}| = P என நாம் பெறுகிறோம், இது ஹேஷிங் செயல்பாடு சாத்தியமான குறைந்தபட்ச மோதல் விகிதத்தைக் கொண்டிருப்பதைக் குறிக்கிறது.

நாம் தேர்ந்தெடுத்தபடி P ஒரு பாதுகாப்பான பகா எண்ணாக இருக்கும் சிறப்பு நேர்வில், P-1 ஆனது 1, 2, (P-1)/2 மற்றும் P-1 ஆகியவற்றை மட்டுமே காரணிகளாகக் கொண்டுள்ளது. P > 7 என்பதால், 3 ஆனது P-1-க்கு சார்பகா எண் என்பதை நாம் அறிவோம், எனவே w=3 மேற்கண்ட கூற்றை நிறைவு செய்கிறது.

மேலும் திறமையான கேச்-அடிப்படையிலான மதிப்பீட்டு அல்காரிதம்

1def quick_calc(params, seed, p):
2 cache = produce_dag(params, seed, params["cache_size"])
3 return quick_calc_cached(cache, params, p)
4
5def quick_calc_cached(cache, params, p):
6 P = params["P"]
7 if p < len(cache):
8 return cache[p]
9 else:
10 x = pow(cache[0], p + 1, P)
11 for _ in range(params["k"]):
12 x ^= quick_calc_cached(cache, params, x % p)
13 return pow(x, params["w"], P)
14
15def quick_hashimoto(seed, dagsize, params, header, nonce):
16 cache = produce_dag(params, seed, params["cache_size"])
17 return quick_hashimoto_cached(cache, dagsize, params, header, nonce)
18
19def quick_hashimoto_cached(cache, dagsize, params, header, nonce):
20 m = dagsize // 2
21 mask = 2**64 - 1
22 mix = sha3(encode_int(nonce) + header)
23 for _ in range(params["accesses"]):
24 mix ^= quick_calc_cached(cache, params, m + (mix & mask) % m)
25 return dbl_sha3(mix)
அனைத்தையும் காட்டு

இந்தக் கட்டுரை உதவியாக இருந்ததா?