---
title: Dagger-Hashimoto
description: "Dagger-Hashimoto அல்காரிதம் பற்றிய விரிவான பார்வை."
lang: ta
---

Dagger-Hashimoto என்பது எத்திரியம் சுரங்கப்பணி அல்காரிதத்திற்கான அசல் ஆராய்ச்சி செயலாக்கம் மற்றும் விவரக்குறிப்பாகும். Dagger-Hashimoto-க்கு பதிலாக [எத்ஹாஷ்](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/#ethash) கொண்டுவரப்பட்டது. 15 செப்டம்பர் 2022 அன்று [ஒருங்கிணைப்பு](/roadmap/merge/) நிகழ்வில் சுரங்கப்பணி முற்றிலுமாக நிறுத்தப்பட்டது. அதிலிருந்து, எத்திரியம் அதற்குப் பதிலாக [உரிமைச் சான்று (PoS)](/developers/docs/consensus-mechanisms/pos) பொறிமுறையைப் பயன்படுத்திப் பாதுகாக்கப்படுகிறது. இந்தப் பக்கம் வரலாற்று ஆர்வத்திற்காக மட்டுமே - இங்குள்ள தகவல்கள் ஒருங்கிணைப்புக்குப் பிந்தைய எத்திரியத்திற்கு இனி பொருந்தாது.

## முன்நிபந்தனைகள் {#prerequisites}

இந்தப் பக்கத்தை நன்கு புரிந்துகொள்ள, முதலில் [பணிச் சான்று (PoW) ஒருமித்த கருத்து](/developers/docs/consensus-mechanisms/pow), [சுரங்கப்பணி](/developers/docs/consensus-mechanisms/pow/mining) மற்றும் [சுரங்கப்பணி அல்காரிதங்கள்](/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms) பற்றிப் படிக்குமாறு பரிந்துரைக்கிறோம்.

## Dagger-Hashimoto {#dagger-hashimoto}

Dagger-Hashimoto இரண்டு இலக்குகளைப் பூர்த்தி செய்வதை நோக்கமாகக் கொண்டுள்ளது:

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

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

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

## DAG உருவாக்கம் {#dag-generation}

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

```python
NUM_BITS = 512

def encode_int(x):
    "Encode an integer x as a string of 64 characters using a big-endian scheme"
    o = ''
    for _ in range(NUM_BITS / 8):
        o = chr(x % 256) + o
        x //= 256
    return o

def decode_int(s):
    "Unencode an integer x from a string using a big-endian scheme"
    x = 0
    for c in s:
        x *= 256
        x += ord(c)
    return x
```

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

```python
from pyethereum import utils
def sha3(x):
    if isinstance(x, (int, long)):
        x = encode_int(x)
    return decode_int(utils.sha3(x))

def dbl_sha3(x):
    if isinstance(x, (int, long)):
        x = encode_int(x)
    return decode_int(utils.sha3(utils.sha3(x)))
```

### அளவுருக்கள் {#parameters}

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

```python
SAFE_PRIME_512 = 2**512 - 38117     # 2**512 ஐ விட குறைவான மிகப்பெரிய பாதுகாப்பான பகா எண்

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

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

### Dagger வரைபடம் உருவாக்குதல் {#dagger-graph-building}

Dagger வரைபடம் உருவாக்கும் அடிப்படை பின்வருமாறு வரையறுக்கப்படுகிறது:

```python
def produce_dag(params, seed, length):
    P = params["P"]
    picker = init = pow(sha3(seed), params["w"], P)
    o = [init]
    for i in range(1, length):
        x = picker = (picker * init) % P
        for _ in range(params["k"]):
            x ^= o[x % i]
        o.append(pow(x, params["w"], P))
    return o
```

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

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

## இலகுரக கிளையண்ட் மதிப்பீடு {#light-client-evaluation}

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

DAG-க்கான இலகுரக கிளையண்ட் கணினி செயற்கூறு பின்வருமாறு செயல்படுகிறது:

```python
def quick_calc(params, seed, p):
    w, P = params["w"], params["P"]
    cache = {}

    def quick_calc_cached(p):
        if p in cache:
            pass
        elif p == 0:
            cache[p] = pow(sha3(seed), w, P)
        else:
            x = pow(sha3(seed), (p + 1) * w, P)
            for _ in range(params["k"]):
                x ^= quick_calc_cached(x % p)
            cache[p] = pow(x, w, P)
        return cache[p]

    return quick_calc_cached(p)
```

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

## DAG-களின் இரட்டை பஃபர் {#double-buffer}

ஒரு முழு கிளையண்டில், மேற்கண்ட சூத்திரத்தால் உருவாக்கப்பட்ட 2 DAG-களின் [_இரட்டை பஃபர்_](https://wikipedia.org/wiki/Multiple_buffering) பயன்படுத்தப்படுகிறது. மேலே உள்ள அளவுருக்களின்படி ஒவ்வொரு `epochtime` தொகுதிகளுக்கும் DAG-கள் உருவாக்கப்படுகின்றன என்பதே இதன் கருத்தாகும். கிளையண்ட் உருவாக்கப்பட்ட சமீபத்திய DAG-ஐப் பயன்படுத்துவதற்குப் பதிலாக, முந்தையதைப் பயன்படுத்துகிறது. இதன் நன்மை என்னவென்றால், சுரங்கப்பணியாளர்கள் திடீரென அனைத்துத் தரவையும் மறுகணக்கீடு செய்ய வேண்டிய ஒரு படியைச் சேர்க்க வேண்டிய அவசியமின்றி, காலப்போக்கில் DAG-களை மாற்ற இது அனுமதிக்கிறது. இல்லையெனில், சீரான இடைவெளியில் சங்கிலிச் செயலாக்கத்தில் திடீர் தற்காலிக மந்தநிலை ஏற்படவும், மையப்படுத்தல் வியத்தகு முறையில் அதிகரிக்கவும் வாய்ப்புள்ளது. இதனால் அனைத்துத் தரவும் மறுகணக்கீடு செய்யப்படுவதற்கு முந்தைய அந்தச் சில நிமிடங்களில் 51% தாக்குதல் அபாயங்கள் ஏற்படும்.

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

```python
def get_prevhash(n):
    from pyethereum.blocks import GENESIS_PREVHASH
    from pyethereum import chain_manager
    if n <= 0:
        return hash_to_int(GENESIS_PREVHASH)
    else:
        prevhash = chain_manager.index.get_block_by_number(n - 1)
        return decode_int(prevhash)

def get_seedset(params, block):
    seedset = {}
    seedset["back_number"] = block.number - (block.number % params["epochtime"])
    seedset["back_hash"] = get_prevhash(seedset["back_number"])
    seedset["front_number"] = max(seedset["back_number"] - params["epochtime"], 0)
    seedset["front_hash"] = get_prevhash(seedset["front_number"])
    return seedset

def get_dagsize(params, block):
    return params["n"] + (block.number // params["epochtime"]) * params["n_inc"]

def get_daggerset(params, block):
    dagsz = get_dagsize(params, block)
    seedset = get_seedset(params, block)
    if seedset["front_hash"] <= 0:
        # பின் இடையகம் சாத்தியமில்லை, முன் இடையகத்தை மட்டும் உருவாக்கவும்
        return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
                          "block_number": 0}}
    else:
        return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
                          "block_number": seedset["front_number"]},
                "back": {"dag": produce_dag(params, seedset["back_hash"], dagsz),
                         "block_number": seedset["back_number"]}}
```

## Hashimoto {#hashimoto}

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

```python
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)
```

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

```python
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)
```

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

```python
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)
```

## சுரங்கப்பணி மற்றும் சரிபார்த்தல் {#mining-and-verifying}

இப்போது, இவை அனைத்தையும் சுரங்கப்பணி அல்காரிதத்தில் இணைப்போம்:

```python
def mine(daggerset, params, block):
    from random import randint
    nonce = randint(0, 2**64)
    while 1:
        result = hashimoto(daggerset, get_dagsize(params, block),
                           params, decode_int(block.prevhash), nonce)
        if result * params["diff"] < 2**256:
            break
        nonce += 1
        if nonce >= 2**64:
            nonce = 0
    return nonce
```

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

```python
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
```

இலகுரக கிளையண்ட் நட்பு சரிபார்ப்பு:

```python
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
```

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

- இரண்டு அடுக்கு சரிபார்ப்பு வேலை செய்ய, ஒரு தொகுதித் தலைப்பில் நான்ஸ் மற்றும் நடுத்தர மதிப்பு pre-sha3 ஆகிய இரண்டும் இருக்க வேண்டும்
- எங்காவது, ஒரு தொகுதித் தலைப்பு தற்போதைய விதைத்தொகுப்பின் sha3-ஐச் சேமிக்க வேண்டும்

## மேலும் படிக்க {#further-reading}

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

## பிற்சேர்க்கை {#appendix}

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

### Lehmer சீரற்ற எண் உருவாக்கி {#lehmer-random-number}

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

இதைத் தவிர்க்க, எண் கோட்பாட்டிலிருந்து ஒரு முடிவு பயன்படுத்தப்படுகிறது. ஒரு [_பாதுகாப்பான பகா எண் (Safe Prime)_](https://en.wikipedia.org/wiki/Safe_prime) என்பது `(P-1)/2`-உம் ஒரு பகா எண்ணாக இருக்கும்படியான ஒரு பகா எண் `P` என வரையறுக்கப்படுகிறது. [பெருக்கல் குழுவின்](https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n) `ℤ/nℤ` உறுப்பினர் `x`-இன் _வரிசை_ என்பது <pre>xᵐ mod P ≡ 1</pre> என்றவாறு இருக்கும் குறைந்தபட்ச `m` என வரையறுக்கப்படுகிறது.

இந்த வரையறைகளைக் கொண்டு, நாம் பெறுவது:

> கவனிப்பு 1. `x` என்பது ஒரு பாதுகாப்பான பகா எண் `P`-க்கான பெருக்கல் குழு `ℤ/Pℤ`-இன் உறுப்பினராக இருக்கட்டும். `x mod P ≠ 1 mod P` மற்றும் `x mod P ≠ P-1 mod P` எனில், `x`-இன் வரிசை `P-1` அல்லது `(P-1)/2` ஆக இருக்கும்.

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

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

<pre>x<sup>P-1</sup> mod P ≡ 1</pre>

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

`x = P-1` ஆக இருந்தாலொழிய `x`-இன் வரிசை `2` ஆக இருக்க முடியாது, ஏனெனில் இது `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. `x` என்பது ஒரு பாதுகாப்பான பகா எண் `P`-க்கான பெருக்கல் குழு `ℤ/Pℤ`-இன் உறுப்பினராக இருக்கட்டும், மேலும் `w` ஒரு இயல் எண்ணாக இருக்கட்டும். `x mod P ≠ 1 mod P` மற்றும் `x mod P ≠ P-1 mod P`, அத்துடன் `w mod P ≠ P-1 mod P` மற்றும் `w mod P ≠ 0 mod P` எனில், `xʷ mod P ≠ 1 mod P` மற்றும் `xʷ mod P ≠ P-1 mod P`

### ஒரு ஹாஷ் செயற்கூறாக மாடுலர் அடுக்குக்குறி {#modular-exponentiation}

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

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

> கவனிப்பு 3. `P` ஒரு பகா எண்ணாக இருக்கட்டும்; `ℤ/Pℤ`-இல் உள்ள அனைத்து `a` மற்றும் `b`-க்கும்: <center>`a mod P ≡ b mod P` ஆக இருந்தால், இருந்தால் மட்டுமே `aʷ mod P ≡ bʷ mod P` ஆக இருக்கும்</center> என்ற நிபந்தனை பூர்த்தியானால், பூர்த்தியானால் மட்டுமே `w` மற்றும் `P-1` ஆகியவை சார்புப் பகா எண்களாக இருக்கும்.

எனவே, `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` மேற்கண்ட முன்மொழிவைப் பூர்த்தி செய்கிறது.

## மிகவும் திறமையான கேச் அடிப்படையிலான மதிப்பீட்டு அல்காரிதம் {#cache-based-evaluation}

```python
def quick_calc(params, seed, p):
    cache = produce_dag(params, seed, params["cache_size"])
    return quick_calc_cached(cache, params, p)

def quick_calc_cached(cache, params, p):
    P = params["P"]
    if p < len(cache):
        return cache[p]
    else:
        x = pow(cache[0], p + 1, P)
        for _ in range(params["k"]):
            x ^= quick_calc_cached(cache, params, x % p)
        return pow(x, params["w"], P)

def quick_hashimoto(seed, dagsize, params, header, nonce):
    cache = produce_dag(params, seed, params["cache_size"])
    return quick_hashimoto_cached(cache, dagsize, params, header, nonce)

def quick_hashimoto_cached(cache, dagsize, params, header, nonce):
    m = dagsize // 2
    mask = 2**64 - 1
    mix = sha3(encode_int(nonce) + header)
    for _ in range(params["accesses"]):
        mix ^= quick_calc_cached(cache, params, m + (mix & mask) % m)
    return dbl_sha3(mix)
```