To be precise, write a program that finds the hash of the block required for mining. It is useless and impossible to mine with the software implemented by myself, so the purpose is to understand the mechanism.
See References.
I will leave the detailed explanation to other articles etc., but it is an act of recording (approving) Bitcoin transactions.
It is an act of searching for a nonce value such that 0s are lined up by a specific number (17 as of January 2016) from the beginning of the hash value that can be calculated from. If you find the nonce of the block for the first time in the world, you will receive 25 BTC (about 1.16 million yen as of January 2016) newly issued coins and a commission for the booked transaction. For this reward, people all over the world are rushing to mine using a large number of machines loaded with special chips. The difficulty of mining is adjusted to take an average of 10 minutes using resources from all over the world, so it gets harder as the number of mining participants increases.
Since it is calculated based on the hash of the previous block, it is connected to the previous block and is the origin of the name "blockchain". In order to tamper with one transaction history, it is necessary to recalculate the hash of the block containing that transaction and all the blocks after that, which is why it is said that tampering is not possible.
It takes a lot of time to really mine, so I just make sure that the nonce of the already approved transaction is really correct. The results of all bitcoin transactions and mining are public, so https://blockchain.info/ja/ You can see it at etc.
This time as a sample https://blockchain.info/ja/block/000000000000000003a0343cc001d21b97d15e97e665b68c790b98c871cf0731 Is used.
The input for hash calculation is
is. Pick up these values from the page above.
version = 4
prev_block = "0000000000000000005629ef6b683f8f6301c7e6f8e796e7c58702a079db14e8"
markle_root = "efb8011cb97b5f1599b2e18f200188f1b8207da2884392672f92ac7985534eeb"
timestamp = "2016-01-30 13:23:09"
bits = 403253488
nonce = 1448681410 #Since it is an approved block, we also know the value of nonce.
Since each cannot be used as it is, convert it to the specified format.
The version should be padded with 0s to 8 digits. Also, as is common with other values, all of these values are used in the calculation in reverse byte order (little endian). There is probably another better way to reverse the byte order, but below I'll format it to a hexadecimal string and then decode it again. (For python3, int has a to_bytes method)
version_h = format(version, "08x").decode("hex")[::-1]
The hash and Merkle root of the previous block are already in hexadecimal form, so decode them and reverse them.
prev_block_h = prev_block.decode("hex")[::-1]
markle_root_h = markle_root.decode("hex")[::-1]
The time converts the number of seconds from Unix standard time to a reverse byte sequence as usual.
from datetime import datetime
timestamp_s = int((datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")-datetime(1970,1,1)).total_seconds())
timestamp_h = format(timestamp_s,"x").decode("hex")[::-1]
bits, nonce Just convert to a reverse byte string.
bits_h = format(bits,"x").decode("hex")[::-1]
nonce_h = format(nonce,"x").decode("hex")[::-1]
Bitcoin hashes use sha256 twice. Also, since the result is also a reverse byte string, convert the order to hexadecimal.
from hashlib import sha256
header = version_h + prev_block_h + markle_root_h + timestamp_h + bits_h + nonce_h
print(sha256(sha256(header).digest()).digest()[::-1].encode("hex"))
output
000000000000000003a0343cc001d21b97d15e97e665b68c790b98c871cf0731
You can see that 17 0s are lined up properly.
Recommended Posts