《区块链编程》第十一章
p180
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 10:43:44 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:00:29 from helper import hash256 def merkle_parent(hash1, hash2): '''Takes the binary hashes and calculates the hash256''' return hash256(hash1 + hash2) hash0 = bytes.fromhex('c117ea8ec828342f4dfb0ad6bd140e03a50720ece40169ee38b\ dc15d9eb64cf5') hash1 = bytes.fromhex('c131474164b412e3406696da1ee20ab0fc9bf41c8f05fa8ceea\ 7a08d672d7cc5') print(merkle_parent(hash0, hash1).hex())
8b30c5ba100f6f2e5ad1e2a742e5020491240f8eb514fe97c713c31718ad7ecd [Finished in 318ms]
p181
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 10:53:22 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:06:46 from helper import merkle_parent def merkel_parent_level(hashes): '''Takes a list of binary hashes and returns a list that's half the length''' if len(hashes) == 1: raise RuntimeError('Cannot take a parent level with only 1 item') if len(hashes) % 2 == 1: hashes.append(hashes[-1]) parent_level = [] for i in range(0, len(hashes), 2): parent = merkle_parent(hashes[i], hashes[i + 1]) parent_level.append(parent) return parent_level hex_hashes = [ 'c117ea8ec828342f4dfb0ad6bd140e03a50720ece40169ee38bdc15d9eb64cf5', 'c131474164b412e3406696da1ee20ab0fc9bf41c8f05fa8ceea7a08d672d7cc5', 'f391da6ecfeed1814efae39e7fcb3838ae0b02c02ae7d0a5848a66947c0727b0', '3d238a92a94532b946c90e19c49351c763696cff3db400485b813aecb8a13181', '10092f2633be5f3ce349bf9ddbde36caa3dd10dfa0ec8106bce23acbff637dae', ] hashes = [bytes.fromhex(h) for h in hex_hashes] level = merkel_parent_level(hashes) for h in level: print(h.hex())
8b30c5ba100f6f2e5ad1e2a742e5020491240f8eb514fe97c713c31718ad7ecd 7f4e6f9e224e20fda0ae4c44114237f97cd35aca38d83081c9bfd41feb907800 3ecf6115380c77e8aae56660f5634982ee897351ba906a6837d15ebc3a225df0 [Finished in 323ms]
p182
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 11:07:52 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:14:24 from helper import merkle_parent_level def merkle_root(hashes): '''Takes a list of binary hashes and returns the merkle root ''' # current level starts as hashes current_level = hashes # loop until there's exactly 1 element while len(current_level) > 1: # current level becomes the merkle parent level current_level = merkle_parent_level(current_level) # return the 1st item of the current level return current_level[0] hex_hashes = [ 'c117ea8ec828342f4dfb0ad6bd140e03a50720ece40169ee38bdc15d9eb64cf5', 'c131474164b412e3406696da1ee20ab0fc9bf41c8f05fa8ceea7a08d672d7cc5', 'f391da6ecfeed1814efae39e7fcb3838ae0b02c02ae7d0a5848a66947c0727b0', '3d238a92a94532b946c90e19c49351c763696cff3db400485b813aecb8a13181', '10092f2633be5f3ce349bf9ddbde36caa3dd10dfa0ec8106bce23acbff637dae', '7d37b3d54fa6a64869084bfd2e831309118b9e833610e6228adacdbd1b4ba161', '8118a77e542892fe15ae3fc771a4abfd2f5d5d5997544c3487ac36b5c85170fc', 'dff6879848c2c9b62fe652720b8df5272093acfaa45a43cdb3696fe2466a3877', 'b825c0745f46ac58f7d3759e6dc535a1fec7820377f24d4c2c6ad2cc55c0cb59', '95513952a04bd8992721e9b7e2937f1c04ba31e0469fbe615a78197f68f52b7c', '2e6d722e5e4dbdf2447ddecc9f7dabb8e299bae921c99ad5b0184cd9eb8e5908', 'b13a750047bc0bdceb2473e5fe488c2596d7a7124b4e716fdd29b046ef99bbf0', ] hashes = [bytes.fromhex(x) for x in hex_hashes] root = merkle_root(hashes) print(root.hex())
acbcab8bcc1af95d8d563b77d24c3d19b18f1486383d75a5085c4e86c86beed6 [Finished in 399ms]
p183
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 11:20:26 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:20:26 class Block: ... def validate_merkle_root(self): '''Gets the merkle root of the tx_hashes and checks that it's the same as the merkle root of this block. ''' # reverse each item in self.tx_hashes hashes = [h[::-1] for h in self.tx_hashes] # compute the Merkle Root and reverse root = merkle_root(hashes) # return whether self.merkle_root is the same return root[::-1] == self.merkle_root
无
p187
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 11:24:09 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:26:48 import math total = 27 max_depth = math.ceil(math.log(total, 2)) merkle_tree = [] for depth in range(max_depth + 1): num_itmes = math.ceil(total / 2 ** (max_depth - depth)) level_hashes = [None] * num_itmes merkle_tree.append(level_hashes) for level in merkle_tree: print(level)
[None] [None, None] [None, None, None, None] [None, None, None, None, None, None, None] [None, None, None, None, None, None, None, None, None, None, None, None, None, None] [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] [Finished in 397ms]
p193
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 11:38:42 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:39:00 class MerkleTree: ... @classmethod def parse(cls, s): '''Takes a byte stream and parses a merkle block. Returns a Merkle Block object''' # version - 4 bytes, Little-Endian integer version = little_endian_to_int(s.read(4)) # prev_block - 32 bytes, Little-Endian (use [::-1]) prev_block = s.read(32)[::-1] # merkle_root - 32 bytes, Little-Endian (use [::-1]) merkle_root = s.read(32)[::-1] # timestamp - 4 bytes, Little-Endian integer timestamp = little_endian_to_int(s.read(4)) # bits - 4 bytes bits = s.read(4) # nonce - 4 bytes nonce = s.read(4) # total transactions in block - 4 bytes, Little-Endian integer total = little_endian_to_int(s.read(4)) # number of transaction hashes - varint num_hashes = read_varint(s) hashes = [] # each transaction is 32 bytes, Little-Endian for _ in range(num_hashes): hashes.append(s.read(32)[::-1]) # length of flags field - varint flags_length = read_varint(s) # read the flags field flags = s.read(flags_length) # initialize class return cls(version, prev_block, merkle_root, timestamp, bits, nonce, total, hashes, flags)
无
p197
# -*- coding: utf-8 -*- # @Author: 从化北(喵星人) # @Date: 2022-01-16 11:45:26 # @Last Modified by: 从化北 # @Last Modified time: 2022-01-16 11:45:26 class MerkleBlock: ... def is_valid(self): '''Verifies whether the merkle tree information validates to the merkle root''' # convert the flags field to a bit field flag_bits = bytes_to_bit_field(self.flags) # reverse self.hashes for the merkle root calculation hashes = [h[::-1] for h in self.hashes] # initialize the merkle tree merkle_tree = MerkleTree(self.total) # populate the tree with flag bits and hashes merkle_tree.populate_tree(flag_bits, hashes) # check if the computed root reversed is the same as the merkle root return merkle_tree.root()[::-1] == self.merkle_root
无