import hashlib
import random
import string
import json
import threading
from decimal import Decimal
from time import time
class MyThread(threading.Thread):
def __init__(self, target, args=()):
super(MyThread, self).__init__()
self.func = target
self.args = args
def run(self):
self.result = self.func(*self.args)
def get_result(self):
try:
return self.result
except Exception:
return None
class BlockChain:
def __init__(self, initialHash):
# init block chain
self.chain = []
# init pitman
self.pitmen = []
for i in range(6):
self.pitmen.append(Pitman)
# collect mine results
self.results = []
# generate GenesisBlock
self.new_block(initialHash)
@property
def last_block(self):
if len(self.chain):
return self.chain[-1]
else:
return None
# 随机生成交易记录
def get_trans(self):
return json.dumps({
'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
'amount': random.randrange(1, 10000)
})
# 添加区块(包含创世区块、普通区块两种)
def new_block(self, initialHash=None):
if initialHash:
# generate Genesis Block
block = Block()
block.index = 0
block.nonce = random.randrange(0, 99999)
block.previousHash = '0'
block.difficulty = 0
block.transactionData = self.get_trans()
guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode()
block.hash = hashlib.sha256(guess).hexdigest()
block.time = time()
self.chain.append(block)
else:
tans_reocrd = self.get_trans() # 假设这是广播的交易记录
for i in range(len(self.pitmen)):
pm = MyThread(target=self.pitmen[i].mine,
args=(self.pitmen[i],
len(self.chain),
self.last_block.get_block()['Hash'],
tans_reocrd))
pm.start()
pm.join()
self.results.append(pm.get_result())
# 这里没有采用通知机制告诉其他矿工停止挖矿,允许它们挖完
# show all blocks
print("All blocks generated by pitmen:")
for result in self.results:
print(result[0].get_block())
# 接受最快挖出的区块
firstblock = self.results[0][0]
mintime = Decimal(self.results[0][1])
for i in range(1, len(self.results)):
if Decimal(self.results[i][1]) < mintime:
firstblock = self.results[i][0]
else:
continue
self.chain.append(firstblock)
self.results = []
def show_chain(self):
print('This is mine first block chain!')
for block in self.chain:
print(block.get_block())
class Block:
def __init__(self):
self.index = None
self.time = None
self.difficulty = None
self.nonce = None
self.hash = None
self.previousHash = None
self.transactionData = None
def get_block(self):
return {
'Index': self.index,
'Time': self.time,
'Difficulty': self.difficulty,
'Hash': self.hash,
'Nonce': self.nonce,
'PreviousHash': self.previousHash,
'TransactionData': self.transactionData
}
class Pitman:
def mine(self, index, previousHash, transactionData):
beginTime = time()
block = Block()
block.index = index
block.previousHash = previousHash
block.transactionData = transactionData
block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData)
block.time = time()
endTime = time()
return block, endTime - beginTime
# 模拟难度较高的 hash 算法,这里认为末尾连续4个0就有效
@staticmethod
def generate_hash(previousHash, transactionData):
difficulty = 0
nonce = random.randrange(0, 99999)
guess = f'{previousHash}{nonce}{transactionData}'.encode()
myhash = hashlib.sha256(guess).hexdigest()
while myhash[-1:-5:-1] != '0000':
difficulty += 1
nonce += difficulty
guess = f'{previousHash}{nonce}{transactionData}'.encode()
myhash = hashlib.sha256(guess).hexdigest()
return difficulty, myhash, nonce
if __name__ == '__main__':
chain = BlockChain(1)
length = 5
for i in range(length):
chain.new_block()
chain.show_chain()
All blocks generated by pitmen:
{'Index': 1, 'Time': 1520946890.0671756, 'Difficulty': 46075, 'Hash': 'f4d4a9138fe827d2b4d54a7042a558464b7f41a3859f0a557b849d8308970000', 'Nonce': 1061476520, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 1, 'Time': 1520946890.1132078, 'Difficulty': 27259, 'Hash': '82997e95b32a4e6634884f4a82b11b9ee6cb1fea9232f1365cff3e0c3bbb0000', 'Nonce': 371608108, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 1, 'Time': 1520946890.1552513, 'Difficulty': 25203, 'Hash': '3a33bb2100762b3af88e2f7d73ec6079fa960707b441738414c1034cb1a00000', 'Nonce': 317634484, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 1, 'Time': 1520946890.339387, 'Difficulty': 109752, 'Hash': '89d89e94505d36a96cf285743298997dbbeaa5f92c6ec8f150de646670e80000', 'Nonce': 6022821169, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 1, 'Time': 1520946890.3774097, 'Difficulty': 22781, 'Hash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'Nonce': 259543941, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 1, 'Time': 1520946890.508489, 'Difficulty': 77100, 'Hash': '4a768d9b44943ca2d0fc1c95f1dfb79c5eaf5029bc877de100d9572148400000', 'Nonce': 2972250851, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
All blocks generated by pitmen:
{'Index': 2, 'Time': 1520946890.5325198, 'Difficulty': 14199, 'Hash': 'b9c998b254d69f2f2507ef01756ea391da4cf44df40429bc3328c76b934f0000', 'Nonce': 100849273, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 2, 'Time': 1520946890.5875456, 'Difficulty': 32647, 'Hash': 'f9431589ceaa5dfa1fae50441cdf408476e5538203e739e7a853dfd412d90000', 'Nonce': 532973064, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 2, 'Time': 1520946890.694623, 'Difficulty': 64602, 'Hash': '8f90a852a555cca6e92a2344e1ee9be91ceabe696503edeaad4b29b071c00000', 'Nonce': 2086755620, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 2, 'Time': 1520946890.713637, 'Difficulty': 10647, 'Hash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'Nonce': 56699515, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 2, 'Time': 1520946890.7506726, 'Difficulty': 22441, 'Hash': 'b23ee841e8975880c535232ace00836cd9d1c9d511e7dfc319271ad5fc6d0000', 'Nonce': 251851011, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 2, 'Time': 1520946890.7826974, 'Difficulty': 19274, 'Hash': 'af9013b09574c943f962314f52d528bcbc01f399e36d6735299caf41efc20000', 'Nonce': 185769145, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
All blocks generated by pitmen:
{'Index': 3, 'Time': 1520946890.9648147, 'Difficulty': 105483, 'Hash': '01e8f01e6d02139f3b875062a2351a52ec4ff4074b1fb9650afae28eeb000000', 'Nonce': 5563453473, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 3, 'Time': 1520946891.0788956, 'Difficulty': 66696, 'Hash': '508be0c3b734f015627e6befb71372f0b4a7d1d42a24a63f6a45d33b56d20000', 'Nonce': 2224248128, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 3, 'Time': 1520946891.0798967, 'Difficulty': 926, 'Hash': 'afacb1d649948e8fed9ec247f5374955ebbfc4efa66d2053df240bc70cc50000', 'Nonce': 525105, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 3, 'Time': 1520946891.3671, 'Difficulty': 167675, 'Hash': 'db56b1f223b5a32dbe232bc37fda81c14297ef1a2badb115679d1eaea7260000', 'Nonce': 14057565273, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 3, 'Time': 1520946891.552231, 'Difficulty': 106760, 'Hash': '4fcc9ab1e45e3f92b80bb86afcba489c0fc9a29768c3e06b82bfc8338a1e0000', 'Nonce': 5698952335, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 3, 'Time': 1520946891.6302867, 'Difficulty': 45103, 'Hash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'Nonce': 1017209586, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
All blocks generated by pitmen:
{'Index': 4, 'Time': 1520946891.656305, 'Difficulty': 15247, 'Hash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'Nonce': 116331987, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 4, 'Time': 1520946892.0025518, 'Difficulty': 196623, 'Hash': 'faa3d5077638742f2b7e1a8c0d23f5d5021da326b12c32a2c570a192d49f0000', 'Nonce': 19330418862, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 4, 'Time': 1520946892.1907036, 'Difficulty': 110576, 'Hash': '351d628ae66859fb3cc4ad1f2299459affe80c5661c4fe6ce64d023df8df0000', 'Nonce': 6113680764, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 4, 'Time': 1520946892.330785, 'Difficulty': 81717, 'Hash': 'cc3dccaaca48ad50e359d6d58633175fb132677e23d94cb2058c533832800000', 'Nonce': 3338906778, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 4, 'Time': 1520946892.390841, 'Difficulty': 34838, 'Hash': 'b3006a5c189d5fe5e9e0f2c856c02ef809bc6a8cfa67cea7767ec6af34fa0000', 'Nonce': 606863416, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 4, 'Time': 1520946892.5429356, 'Difficulty': 89187, 'Hash': 'c00e711e196f3fde027d60d954c223ab5778549839082326fef5ecd99d7a0000', 'Nonce': 3977304488, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
All blocks generated by pitmen:
{'Index': 5, 'Time': 1520946892.5739717, 'Difficulty': 18004, 'Hash': '17593a91870fa755c955bfba518081bb9008c4888a40a79ea49287cf047d0000', 'Nonce': 162150579, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
{'Index': 5, 'Time': 1520946892.5919738, 'Difficulty': 9890, 'Hash': 'fe7c4e5b2e4396c8f8a5a0927d81ccccb4b6df5393d72f79c45daa85db550000', 'Nonce': 48948723, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
{'Index': 5, 'Time': 1520946892.70405, 'Difficulty': 44846, 'Hash': 'd2944b0b5a3cb80f40b3bb2120e97456b5e90b23f922b6d7fa87d74a45ff0000', 'Nonce': 1005669926, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
{'Index': 5, 'Time': 1520946892.8521564, 'Difficulty': 78655, 'Hash': '993f330f852dd4bc76cb8d2f308bc1d8e961920ed2950d614ecfc17823380000', 'Nonce': 3093380308, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
{'Index': 5, 'Time': 1520946893.2294347, 'Difficulty': 212275, 'Hash': '8eec8e8d61b167572dcda1341dcfcf11e25311eb4fe006527b9aa3e4b0600000', 'Nonce': 22530540329, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
{'Index': 5, 'Time': 1520946893.3555145, 'Difficulty': 73524, 'Hash': '9bb971c06d46c8e13f15b3c8eb67bba242f1eaae5e6fc3b46f69c860c87a0000', 'Nonce': 2702995520, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
This is mine first block chain!
{'Index': 0, 'Time': 1520946889.9901314, 'Difficulty': 0, 'Hash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'Nonce': 31826, 'PreviousHash': '0', 'TransactionData': '{"sender": "RhdN7Lis", "recipient": "zaU3CQLx", "amount": 3111}'}
{'Index': 1, 'Time': 1520946890.3774097, 'Difficulty': 22781, 'Hash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'Nonce': 259543941, 'PreviousHash': '573521a64a463f826f44261e46337e256b11c34658a8516534dbbc858f530169', 'TransactionData': '{"sender": "RuJAeWPG", "recipient": "NdIZQoLG", "amount": 852}'}
{'Index': 2, 'Time': 1520946890.713637, 'Difficulty': 10647, 'Hash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'Nonce': 56699515, 'PreviousHash': '4a3226377c70b5b8fa3199ad6ddd06ccacb2ad1cc8764443164d374d3a230000', 'TransactionData': '{"sender": "BEiclDIX", "recipient": "s7wC8uGx", "amount": 2793}'}
{'Index': 3, 'Time': 1520946891.6302867, 'Difficulty': 45103, 'Hash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'Nonce': 1017209586, 'PreviousHash': '583860cab5ae3b817568ae714c449be6e7097cbb4fee5367160ef415fed30000', 'TransactionData': '{"sender": "ORMqK4ZI", "recipient": "2W0iOVmA", "amount": 1191}'}
{'Index': 4, 'Time': 1520946891.656305, 'Difficulty': 15247, 'Hash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'Nonce': 116331987, 'PreviousHash': '1a5da6639e2d04160dbdf7cfcf909115d4d2dd9b17161b573e9e1702e24c0000', 'TransactionData': '{"sender": "BVtcOSnI", "recipient": "PnhZAStw", "amount": 7842}'}
{'Index': 5, 'Time': 1520946892.5919738, 'Difficulty': 9890, 'Hash': 'fe7c4e5b2e4396c8f8a5a0927d81ccccb4b6df5393d72f79c45daa85db550000', 'Nonce': 48948723, 'PreviousHash': '3c5e16da37c43e42e1b8aa88e65595940cde28f2be0b22c6dc6b67f280260000', 'TransactionData': '{"sender": "aHUrknDd", "recipient": "QJpM2gVw", "amount": 993}'}
参考实现 http://blog.youkuaiyun.com/bmwgaara/article/details/79059007