본문으로 바로가기

비트코인 작업증명은 이전 포스팅에서 설명한것처럼 블록헤더값의 hash한 결과가 계산된 target 값보다 작은 nonce 값을 찾는 과정입니다.

이번 포스팅에서 블록헤더값을 사용하여 블록해쉬를 구하는 코드를 한번 알아보겠습니다.

지난번 머클루트 구하는 것과 마찬가지로 기본적으로 연산을 위해서는 숫자값은 little endian 포맷으로 변환이 되어야 하고, hex 값은 reverse order로 변경이 되어있어야 합니다.  그리고 더블해쉬 연산을 위해서 hex 포맷은 bin 포맷으로 변환이 되어야 합니다.


블록은 이전 작업증명 글에서 예를 든 277316번 블록을 사용하도록 하겠습니다.


https://blockchain.info/block-height/277316?format=json


블록해쉬는 하기와 같이 블록헤더에 포함되는 6가지 값을 사용하여 계산됩니다.

{
    "hash":"0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4",
    "ver":2,
    "prev_block":"0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569",
    "mrkl_root":"c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e",
    "time":1388185914,
    "bits":419668748,
    "fee":9094928,
    "nonce":924591752,
    "n_tx":419,
    "size":218629,
    "block_index":339688,
    "main_chain":true,
    "height":277316,
    "received_time":1388185796,
    "relayed_by":"98.117.76.152",


다음 python 코드는 하기 블로그의 코드를 참조하였습니다.


http://brownbears.tistory.com/373


import hashlib
import struct
little_endian = lambda value: struct.pack('<L', value).hex()
reverse_order_pair = lambda value: ''.join([value[i - 2:i] for i in range(len(value), 0, -2)])
# https://blockchain.info/block-height/277316?format=json
block_info = {
'version' : 2,
'prev_hash' : '0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569',
'merkle_root' : 'c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e',
'time' : 1388185914,
'bits' : 419668748,
'nonce' : 924591752,
}
convert_block_info = {}
# convert version, time, bits, nonce to little endian format
convert_block_info['version'] = little_endian(block_info['version'])
convert_block_info['time'] = little_endian(block_info['time'])
convert_block_info['bits'] = little_endian(block_info['bits'])
convert_block_info['nonce'] = little_endian(block_info['nonce'])
# reverse order of prev block hash, merkle root
convert_block_info['prev_hash'] = reverse_order_pair(block_info['prev_hash'])
convert_block_info['merkle_root'] = reverse_order_pair(block_info['merkle_root'])
# mix 6 block header info to one hex value
header_hex = convert_block_info['version'] + convert_block_info['prev_hash'] + \
convert_block_info['merkle_root'] + convert_block_info['time'] + \
convert_block_info['bits'] + convert_block_info['nonce']
# convert hex value to bin
header_bin = bytes.fromhex(header_hex)
# double hash
hash = hashlib.sha256(hashlib.sha256(header_bin).digest()).digest()
# reverse order and convert to hex
result_header_hex = hash[::-1].hex()
print(result_header_hex)


위의 6개 블록헤더의 값을 사용하여 더블해쉬 한 결과는 다음과 같습니다.



다음과 같이 277316 블록의 block hash 값과 동일한 값이 계산되었음을 확인할수 있습니다.