The point of this is building an API server that includes some additional data with a name lookup so that it can be verified that the data is original.
Info on how to build the hash chain:
https://en.bitcoin.it/wiki/Merged_mining_specification
https://github.com/namecoin/namecoin/bl ... -mining.md
(block data removed, full version here: https://gist.github.com/phelixbtc/b48b420132c1c1f228ac )
Code: Select all
import hashlib
import struct
####http://python-bitcoinlib.readthedocs.org/en/latest/_modules/bitcoin/core/serialize.html
def uint256_from_str(s):
"""Convert bytes to uint256"""
r = 0
t = struct.unpack(b"<IIIIIIII", s[:32])
for i in range(8):
r += t[i] << (i * 32)
return r
def uint256_from_compact(c):
"""Convert compact encoding to uint256
Used for the nBits compact encoding of the target in the block header. """
nbytes = (c >> 24) & 0xFF
v = (c & 0xFFFFFF) << (8 * (nbytes - 3))
return v
####
def reverse_byte_order(data):
return data[::-1]
def get_merkle_parents(data):
if len(data) % 2:
data.append(data[-1])
hashes = []
half = len(data) / 2
for i in range(half):
hashes.append((dsha256(data[i * 2] + data[i * 2 + 1])))
if len(hashes) == 1:
return hashes
return hashes + get_merkle_parents(hashes)
def get_merkle_tree(txs_data):
"""hex in, hex out"""
if len(txs_data) == 0:
return 0
if len(txs_data) == 1:
#return dsha256(txs_data[0])
return [txs_data[0]]
txs_data_rev = []
for t in txs_data:
txs_data_rev.append(reverse_byte_order(t.decode("hex")))
treeHashed = get_merkle_parents(txs_data_rev)
tree = []
for t in treeHashed:
tree.append(reverse_byte_order(t).encode("hex"))
tree = txs_data + tree
return tree
def get_merkle_root(txs_data):
return get_merkle_tree(txs_data)[-1]
def dsha256(data):
return hashlib.sha256(hashlib.sha256(data).digest()).digest()
def hash_block(B):
blkheader = ""
blkheader += struct.pack('<I', B['version'])
blkheader += B['previousblockhash'].decode("hex")[::-1]
blkheader += B["merkleroot"].decode("hex")[::-1]
blkheader += struct.pack('<I', B['time'])
blkheader += struct.pack('<I', B['bits'])
blkheader += struct.pack('<I', B['nonce'])
h = dsha256(blkheader)[::-1]
return h.encode("hex")
def check_pow(blockHash, bits):
target = uint256_from_compact(bits)
if len(blockHash) == 64:
blockHash = blockHash.decode("hex")
assert(len(blockHash) == 32)
blockHash = reverse_byte_order(blockHash) # why?
nHash = uint256_from_str(blockHash)
#print "target:", target
#print "nHash:", nHash
return nHash <= target
if __name__ == "__main__":
# block data as from client
b10001 = {u'merkleroot': u'41183c608fc0cac556f219330c418cf0381c178d3f25db5b254af204340aa4b8', ...
b19199 = {u'merkleroot': u'0f8e8a23da3c8e53f9ef1f6722d0667e228b9275cd61e9a1460d717763d89894', ...
b200000 = {u'merkleroot': u'ca714d4f72d212bbbb3521886ff2561f54506cdbb2515acb2d26842005fe7744', ...
for b in [b10001, b19199, b200000]:
print "block height:", b["height"]
print "original block hash:", b["hash"]
print "hashed block ok:", hash_block(b) == b["hash"]
print "calculated merkle root ok:", get_merkle_root(b["tx"]) == b["merkleroot"]
print "pow check:", check_pow(b["hash"], b["bits"])
print
block height: 10001
original block hash: 000000000012718050e3537c3c355f3746fc8cd6434d44e79417276d6683b7ab
hashed block ok: True
calculated merkle root ok: True
pow check: True
block height: 19199
original block hash: 000000000000b19f0ad5cd46859fe8c9662e8828d8a75ff6da73167ac09a9036
hashed block ok: True
calculated merkle root ok: True
pow check: True
block height: 200000
original block hash: bdec8422dcad4c6168041068ab8f00d73efb38556cd47cf5af157649ab39855d
hashed block ok: True
calculated merkle root ok: True
pow check: False