BitCoin-Minning, What do nonce, POW mean for?πŸ‘·

Once you know the hash function, the most important idea of ​​cryptocurrency, then you need to know about proof of work (POW), which is essential in the mining process. It is the proof that the miner has elaborated this much to find out target hash.



  • In the process of proof-of-work (POW), nonce and difficulty arise. Difficulty is a variable that makes it difficult to mine a block. This is easy to accept, but the concept of nonce is hard to grasp. Let’s make assumption like this.

Picking balls which are numbered upto 100 in a pouch

  • Put 100 numbered balls into an invisible pouch, and three people A, B, and C draw each and each ball. If a number that satisfies the criteria comes out, it passes, but otherwise, put the ball into a pouch again and repeat the drawing. Here, the conditions below are applied to increase the difficulty.

  • A λŠ” 90 보닀 μž‘μ€ 수λ₯Ό λ½‘μœΌλ©΄ 톡과 (μž‘μ—…μ¦λͺ…)을 λ°›μ•„μ€€λ‹€.
  • B λŠ” 50 보닀 μž‘μ€ 수λ₯Ό 뽑아야 톡과 (μž‘μ—…μ¦λͺ…)을 λ°›μ•„μ€€λ‹€.
  • C λŠ” 5 μ΄ν•˜μ˜ 숫자λ₯Ό λ½‘μ•˜μ„ λ•Œλ§Œ ν†΅κ³Όμ‹œμΌœ μ€€λ‹€.

λˆ„κ°€ λΉ λ₯Έμ‹œκ°„ 내에 쑰건을 μΆ©μ‘±ν•˜κ³  μž‘μ—…μ„ 마칠 수 μžˆμ„κΉŒ? λ‹Ήμ—°νžˆ Aκ°€ μ›”λ“±νžˆ 적은 횟수둜 μž‘μ—…μ„ 마칠 수 μžˆλ‹€

예λ₯Ό λ“€μ–΄,

  1. A λŠ” 5번 λ§Œμ— 90보닀 μž‘μ€ 수λ₯Ό 뽑아 ν†΅κ³Όν–ˆλ‹€.
  2. B λŠ” 13번 λ§Œμ— 50보닀 μž‘μ€ 수λ₯Ό 뽑아 ν†΅κ³Όν–ˆλ‹€.
  3. C λŠ” 59번 λ§Œμ— 5보닀 μž‘μ€ 수λ₯Ό 뽑아 ν†΅κ³Όν–ˆλ‹€.

항상 C κ°€ 더 λ§Œμ€ 횟수λ₯Ό μ‹œλ„ν•΄μ•Ό λ˜λŠ” 것은 μ•„λ‹ˆλ‹€. ν•œλ²ˆμ— 톡과할 μˆ˜λ„ μžˆλ‹€.
ν•˜μ§€λ§Œ, ν™•λ₯ μ μœΌλ‘œ C κ°€ 더 많이 고생해야 ν•  것이닀.





μ—¬κΈ°μ„œ,

  1. 90 보닀 μž‘μ€ 수 λΌλŠ” 쑰건은 λ‚œμ΄λ„ (difficulty)
  2. λ°˜λ³΅μž‘μ—… 5번 의 νšŸμˆ˜κ°€ λ…ΌμŠ€(nonce) λ‹€

nonce λŠ” λͺ‡ λ²ˆμ„ λ°˜λ³΅ν•΄μ„œ μ‹œλ„ ν–ˆλŠ”μ§€, 횟수이며, 이 νšŸμˆ˜κ°€ μ–Όλ§ŒνΌ κ³ μƒν–ˆλŠ”μ§€λ₯Ό μž…μ¦ν•˜λŠ” μž‘μ—…μ¦λͺ… (proof_of_work)이닀. λ…ΌμŠ€λ₯Ό ν¬ν•¨ν•΄μ„œ, ν˜„μž¬μ˜ Hash 값이 κ³„μ‚°λ˜μ•Ό ν•˜λ©°, μœ μΌν•˜κ²Œ λ³€κ²½ν•  수 μžˆλŠ” ν•΄μ‰¬μž…λ ₯κ°’ ν†΅λ‘œ NONCE λ³€κ²½ μ‹œμΌœ κ°€λ©΄μ„œ 해쉬값을 반볡적으둜 κ³„μ‚°ν•˜λ‹€ 보면 μš°μ—°ν•˜κ²Œ 쑰건을 λ§Œμ‘±ν•˜λŠ” 해쉬값을 μ°Ύμ•„λ‚Έλ‹€. λΉ λ₯΄κ²Œ κ³„μ‚°ν• μˆ˜ μžˆλŠ” λŠ₯λ ₯을 κ°€μ§„μ‚¬λžŒμ—κ²Œ κΈ°νšŒκ°€ 더 λ§Žμ§€λ§Œ, 찾을 ν™•λ₯ μ€ μš°μ—° 에 κΈ°λ°˜ν•˜κΈ° λ•Œλ¬Έμ— μ ˆλŒ€μ μΈ 것은 μ•„λ‹ˆλ‹€ ..이거, λ‹€ μƒˆλΉ¨κ°„ 거짓말인거 λ‹€ μ•„μ‹œμ£ ? μ—¬λŸ¬λΆ„!..



μ•„λž˜ λΈ”λŸ­κ²°κ³Όλ₯Ό 비ꡐ해 보자

λ‚œμ΄λ„μ— λ”°λΌμ„œ, 기쀀보닀 μž‘μ€ 해쉬λ₯Ό κ³„μ‚°ν–ˆμ„ λ•Œ μ‹œλ„ν•œ 횟수, λ…ΌμŠ€(nonce) λ₯Ό 보여쀀닀, 일정크기 μ΄ν•˜μ˜ 해쉬λ₯Ό 뽑아내기가 μ–΄λ €μš΄ 만큼 μ‹œλ„νšŸμˆ˜ λ…ΌμŠ€κ°€ 증가 ν–ˆλ‹€.



1
2
3
4
5
6
7
8
9
10
11
{'difficulty': '000',
 'hash_present': '000107d0d540f0edf7eb0af657840b51',
 'hash_previous': '000005fa8482b821aff9b2ce6103f69e',
 'index': 1,
 'nonce': 7725,
 'timestamp': 1539440895.4122593,
 'transaction': [{'amount': 1000, 'recipient': 'Bob', 'sender': 'Alice'},
                 {'amount': 800, 'recipient': 'Alice', 'sender': 'Scrouge'},
                 {'amount': 200,
                  'recipient': 'node_identifier_uid',
                  'sender': 'coinbase_reward'}]}
  • μ‹œλ„νšŸμˆ˜(λ…ΌμŠ€) = 7,725회
  • λ§Œμ‘±ν•˜λŠ” present_hash 값을 μ°Ύμ•˜μ„ λ•Œ,
  • νƒ€μž„μŠ€νƒ¬ν”„λ₯Ό 찍고, ν˜„μž¬ν•΄μ‰¬κ°’μ„ μΆ”κ°€ν–ˆλ‹€
  • 즉, νƒ€μž„μŠ€νƒ¬ν”„μ™€ ν˜„μž¬ν•΄μ‰¬κ°’μ„ λΊ€ λΈ”λŸ­μ„ 해쉬256 ν•¨μˆ˜μ—, λ…ΌμŠ€κ°’κ³Ό 같이 λ„£μœΌλ©΄
  • ν˜„μž¬μ˜ 쑰건에 λ§Œμ‘±ν•˜λŠ” 해쉬값이 λ‚˜μ˜¨λ‹€.
  • 해쉬 μž…λ ₯κ°’μ—μ„œ λ…ΌμŠ€λ₯Ό ν¬ν•¨ν•œ κ·Έ μ–΄λ–€κΈ€μžκ°€ ν•œκΈ€μžλ§Œ λ°”λ€Œμ–΄λ„,
  • 해쉬값은 μ‘°κ±΄μ—μ„œ λ²—μ–΄λ‚œλ‹€.
  • 즉, νŠΉμ • λ…ΌμŠ€κ°’μ„ μ°Ύμ•„μ•Όλ§Œ, 쑰건에 λ§žλŠ” 해쉬값 μž‘μ—…μ¦λͺ…을 이뀄낸닀.
  • 해쉬값은 λ¬΄μž‘μœ„μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, λ…ΌμŠ€λ₯Ό 1μ”© μ¦κ°€μ‹œν‚€λ©°, 반볡 κ³„μ‚°ν•œλ‹€
  • 이 과정이 λžœλ€ν”Όν‚Ήκ³Ό 같은 λ™μž‘μ΄λ‹€.



1
2
3
4
5
6
7
8
9
10
11
{'difficulty': '00000',
 'hash_present': '00000da730623b47a1e4d39a4d28ccfe',
 'hash_previous': '000005fa8482b821aff9b2ce6103f69e',
 'index': 12,
 'nonce': 52305,
 'timestamp': 1539441010.7054014,
 'transaction': [{'amount': 1000, 'recipient': 'Bob', 'sender': 'Alice'},
                 {'amount': 800, 'recipient': 'Alice', 'sender': 'Scrouge'},
                 {'amount': 200,
                  'recipient': 'node_identifier_uid',
                  'sender': 'coinbase_reward'}]}
  • λ‚œμ΄λ„κ°€ λ‘μžλ¦Ώμˆ˜ μΆ”κ°€λ‘œ λ–¨μ–΄μ§€λ‹ˆκ°€, μ‹œλ„νšŸμˆ˜κ°€ 52,305회 둜 λŠ˜μ–΄λ‚¬λ‹€.
  • 쑰건에 λ§žλŠ” 해쉬값을 κ³„μ‚°ν• μˆ˜ μžˆλŠ” μž…λ ₯κ°‘ λ…ΌμŠ€λ₯Ό μ°Ύμ•„λ‚΄κ³ 
  • 쑰건에 λ§žλŠ” 해쉬값을 μ°Ύμ•„λ‚΄λ©΄ μž‘μ—…μ¦λͺ…이 이루어진닀.
  • 각 λΈ”λŸ­μ˜ μ—°κ²°κ³ λ¦¬λŠ” 쑰건에 λ§žλŠ” 해쉬값을 κΈ°μ€€μœΌλ‘œ μ•žλ’€λ‘œ μ—°κ²°λ˜μ–΄μžˆλ‹€.
  • 쑰건에 λ§žλŠ” 해쉬값λ₯Ό μ°Ύμ•„μ„œ μ•ž/λ’€ λΈ”λŸ­μ„ μž κ·Όκ²ƒμ΄λ‹€.
  • 길이가 κΈ΄, 일련의 블둝듀은 μ•ž/λ’€ 무결성을 ν•΄μ‰¬κ°’μœΌλ‘œ 증λͺ…ν•œλ‹€.
  • λŠ˜μ–΄μ„  λΈ”λŸ­μ˜ λ‚΄μš©μ΄ ν•˜λ‚˜λΌλ„ 바뀐닀면, 뒀에 λΈ”λŸ­μ€ λͺ¨λ‘ λ¬΄νš¨κ°€ λœλ‹€.
  • 해킹을 μœ„ν•΄ 쀑간값을 λ°”κΎΈλ €λ©΄, κ·Έ 이후 λΈ”λŸ­μ˜ μž‘μ—…μ¦λͺ…을 λͺ¨λ‘ λ°”κΏ”μ•Ό ν•œλ‹€.
  • 이 κ³Όμ •μ—μ„œ μž‘μ—…μ¦λͺ…을 ν•˜λŠ”λ°, λ„ˆλ¬΄ λ§Žμ€ μ‹œκ°„μ΄ μ†Œμš”λœλ‹€.



1
2
3
4
5
6
7
8
9
10
11
{'difficulty': '0000000',
 'hash_present': '0000000f8fc7d21dc1a4c67f3ec72ac5',
 'hash_previous': '000005fa8482b821aff9b2ce6103f69e',
 'index': 12,
 'nonce': 19760524,
 'timestamp': 1539441177.5858967,
 'transaction': [{'amount': 1000, 'recipient': 'Bob', 'sender': 'Alice'},
                 {'amount': 800, 'recipient': 'Alice', 'sender': 'Scrouge'},
                 {'amount': 200,
                  'recipient': 'node_identifier_uid',
                  'sender': 'coinbase_reward'}]}
  • λ‚œμ΄λ„κ°€ λ„€μžλ¦¬ μΆ”κ°€λ‘œ λ–¨μ–΄μ Έμ„œ, μ‹œλ„νšŸμˆ˜κ°€ 19,760,524번 으둜 λŠ˜μ–΄λ‚¬λ‹€.
  • λΈ”λŸ­μ΄ λ’€λ‘œ 갈수둝 λ‚œμ΄λ„κ°€ μ¦κ°€ν•˜λ©°, μž‘μ—…μ¦λͺ…에 μ‹œκ°„μ΄ κΈ°ν•˜κΈ‰μˆ˜μ μœΌλ‘œ λŠ˜μ–΄λ‚¨.
  • μ€‘κ°„λΈ”λŸ­ λ‚΄μš©μ„ μœ„μ‘°ν•˜λ©΄, 이후 λΈ”λŸ­μ˜ λͺ¨λ“  μž‘μ—…μ¦λͺ…을 λ°”κΏ”μ•Ό 해킹이 μ™„μ„±λ˜λŠ”λ°,
  • λΈ”λŸ­μ€ 10λΆ„λ§ˆλ‹€ μΆ”κ°€λ‘œ μƒμ„±λœλ‹€.
  • κ²Œλ‹€κ°€, 일련의 λΈ”λŸ­λͺ¨μŒ μ •λ³΄λŠ” λͺ¨λ“  λ…Έλ“œλ“€μ΄ μžλ™μœΌλ‘œ κ³΅μœ ν•˜κ³  μžˆλ‹€.
  • λ”°λΌμ„œ, λ…Έλ“œκ°„μ— κ³΅μœ ν•˜κ³  μžˆλŠ” λͺ¨λ“  λΈ”λŸ­μ„ μΌμˆœκ°„μ— ν•΄ν‚Ή ν•˜λŠ”κ²ƒμ€ λΆˆκ°€λŠ₯ ν•˜λ‹€.



[image ref.]: Understanding How Blockchain Works
  • λΈ”λŸ­ν•΄μ‰¬μ˜ μž…λ ₯ 값을 λ³€κ²½μ‹œν‚¬ 수 μžˆλŠ” μœ μΌν•œ λ³€μˆ˜λŠ” λ…ΌμŠ€(nonce)λ‹€.
  • λ…ΌμŠ€λ₯Ό λ³€κ²½ν•˜λ©°, 해쉬값을 κ³„μ‚°ν•΄μ„œ λ‚œμ΄λ„μ‘°κ±΄μ„ λ§Œμ‘±ν•˜λŠ” 값이 λ‚˜μ˜¬ λ•Œ 반볡
  • λ…ΌμŠ€λŠ” 0 μ—μ„œλΆ€ν„° +1μ”© μ¦κ°€μ‹œν‚€λ©° 반볡 κ³„μ‚°ν•˜κΈ° λ•Œλ¬Έμ— 결과적으둜 계산 νšŸμˆ˜λ‹€.



Result of the Block Hash Calculation, Changing difficulty

  • λ‚œμ΄λ„λ₯Ό λ°”κΏ”μ„œ 계산해 보면, κ³„μ‚°μ‹œκ°„κ³Ό λ°˜λ³΅νšŸμˆ˜μ—μ„œ 큰 차이가 λ‚œλ‹€.
  • Previous hash is β€˜0000…’ pressent hash starts with β€˜000000…’
😒 difficulty related with nonce makes different on execute time. (click to see bigger)



πŸŽ₯Well-explained VOD about what does nonce mean for.

  • λ…ΌμŠ€(nonce)와 μž‘μ—…μ¦λͺ…(POW)에 λŒ€ν•΄μ„œ μ•„μ£Ό 잘 μ„€λͺ… ν•΄ 놓은 μ˜μƒ

λ”°λΌν•˜κΈ°λ„ κ°€λŠ₯~



CODE REVIEW

λ‚œμ΄λ„(difficulty)λ₯Ό λ°”κΏ”κ°€λ©΄μ„œ, λ…ΌμŠ€(nonce)λ₯Ό λ³€κ²½ ν•΄μ„œ 계산 ν•΄ 보자.

  • 블둝 μ•ˆμ— λͺ¨λ“  κ°’ 듀은 이미 κ²°μ • λ˜μ–΄ μžˆλ‹€ (present hash = 0000 ….)
  • nonce 만이 μœ μΌν•˜κ²Œ minner κ°€ λ°”κΏ€ 수 μžˆλŠ” κ°’ 이닀.
  • λͺ©ν‘œ Present hash λ₯Ό μ°ΎκΈ° μœ„ν•΄ nonceλ₯Ό 1μ”© 증가 μ‹œν‚€λ©° Try & Error둜 μ°ΎλŠ”λ‹€.
  • μš°μ—°νžˆ ν•΄μ‰¬κ°’μ˜ μ²«μžλ¦¬κ°€ β€˜0000β€™μœΌλ‘œ μ‹œμž‘ν•˜λŠ” λͺ©ν‘œ 해쉬λ₯Ό 발견 ν–ˆμ„ λ•Œ,
  • μž‘μ—… 증λͺ…을 μ™„μ„± ν•œλ‹€. μž‘μ—…μ¦λͺ…(Proof of Work) 값은 nonce=7725 이닀.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import time
import pyprnt
from hashlib import sha256

# difficulty λ₯Ό '0000' μ—μ„œ 0 을 ν•˜λ‚˜μ”© 늘렀 μ‹€ν–‰μ‹œκ°„μ„ λΉ„κ΅ν•œλ‹€.
difficulty = '0000'

mining_uid = 'node_identifier_uid'
transactions = [
    {
        'sender': 'Alice',
        'recipient': 'Bob',
        'amount': 1000
    },
    {
        'sender': 'Scrouge',
        'recipient': 'Alice',
        'amount': 800
    },
    {
        'sender': 'coinbase_reward',
        'recipient': mining_uid,
        'amount': 200
    },
]


last_block = {
    'index': 12,
    'difficulty': difficulty,
    'nonce': 0,
    'hash_previous': '000005fa8482b821aff9b2ce6103f69e',
    'transaction': transactions,
}


def get_hash_w_nonce(last_block, nonce):
    """ μ΅œκ·ΌλΈ”λŸ­μ— λ…ΌμŠ€λ₯Ό λŒ€μž…ν•˜μ—¬ 해쉬값을 λ¦¬ν„΄ν•œλ‹€"""
    last_block['nonce'] = nonce
    hash = sha256(str(last_block).encode()).hexdigest()
    return hash

def add_header(last_block, block_hash):
    """ λΈ”λŸ­μ— νƒ€μž„μŠ€νƒ¬ν”„μ™€ ν˜„μž¬ν•΄μ‰¬λ₯Ό μΆ”κ°€ν•œλ‹€"""
    header = {
        'timestamp': time.time(),
        'hash_present': block_hash, }

    for _key, _val in header.items():
        last_block[_key] = _val

    return last_block

def proof_of_work(last_block):
    nonce = 0
    difficulty = last_block['difficulty']

    while True:
        hash = get_hash_w_nonce(last_block, nonce)

        if hash[:len(difficulty)] == difficulty:
            hash_present = hash[:32]
            add_header(last_block, hash_present)
            return last_block

        nonce += 1

if __name__ == '__main__':
    last_block = proof_of_work(last_block)
    pyprnt.prnt(last_block)


Written on ... October 12, 2018