import hashlib
import json
from time import time
class Blockchain(object):
def __init__(self):
self.current_transactions = []
self.chain = []
# 創建創世區塊
self.new_block(proof=100, previous_hash=1)
def new_block(self, proof, previous_hash=None):
"""
創建一個新的區塊到區塊鏈中
:param proof: <int> 由工作證明算法生成的證明
:param previous_hash: (Optional) <str> 前一個區塊的 hash 值
:return: <dict> 新區塊
"""
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
# 重置當前交易記錄
self.current_transactions = []
self.chain.append(block)
return block
def new_transaction(self, sender, recipient, amount):
"""
創建一筆新的交易到下一個被挖掘的區塊中
:param sender: <str> 發送人的地址
:param recipient: <str> 接收人的地址
:param amount: <int> 金額
:return: <int> 持有本次交易的區塊索引
"""
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
@property
def last_block(self):
return self.chain[-1]
@staticmethod
def hash(block):
"""
給一個區塊生成 SHA-256 值
:param block: <dict> Block
:return: <str>
"""
# 我們必須確保這個字典(區塊)是經過排序的,否則我們將會得到不一致的散列
block_string = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
def proof_of_work(self, last_proof):
"""
Simple Proof of Work Algorithm:
- Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
- p is the previous proof, and p' is the new proof
:param last_proof: <int>
:return: <int>
"""
proof = 0
while self.valid_proof(last_proof, proof) is False:
proof += 1
return proof
@staticmethod
def valid_proof(last_proof, proof):
"""
Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
:param last_proof: <int> Previous Proof
:param proof: <int> Current Proof
:return: <bool> True if correct, False if not.
"""
guess = '{last_proof}{proof}'.format(last_proof=last_proof, proof=proof).encode()
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == "0000"
def chainIsValid(self):
"""
校驗hash proof
"""
for index in range(1, len(self.chain)):
currentBlock = self.chain[index]
previousBlock = self.chain[index-1]
previous_hash = currentBlock['previous_hash']
current_hash = self.hash(previousBlock)
previous_proof = previousBlock['proof']
current_proof = currentBlock['proof']
if (previous_hash != current_hash) and valid_proof(previous_proof, current_proof):
return False
else:
return True
if __name__=='__main__':
t = Blockchain()
t.new_transaction('a','b',1000)
previous_hash = t.hash(t.last_block)
last_proof = t.last_block['proof']
proof = t.proof_of_work(last_proof)
data = t.new_block(proof, previous_hash)
print(data)
print(t.chain)
t.new_transaction('a','c',80)
t.new_transaction('a','d',980)
previous_hash = t.hash(t.last_block)
last_proof = t.last_block['proof']
proof = t.proof_of_work(last_proof)
data = t.new_block(proof, previous_hash)
print(data)
print(t.chain)
t.new_transaction('a','e',280)
t.new_transaction('b','e',180)
previous_hash = t.hash(t.last_block)
last_proof = t.last_block['proof']
proof = t.proof_of_work(last_proof)
data = t.new_block(proof, previous_hash)
print(data)
print(t.chain)
t.new_transaction('d','e',810)
t.new_transaction('a','e',280)
previous_hash = t.hash(t.last_block)
last_proof = t.last_block['proof']
proof = t.proof_of_work(last_proof)
data = t.new_block(proof, previous_hash)
print(data)
print(t.chain)
t.new_transaction('b','a',2180)
t.new_transaction('c','d',1280)
previous_hash = t.hash(t.last_block)
last_proof = t.last_block['proof']
proof = t.proof_of_work(last_proof)
data = t.new_block(proof, previous_hash)
print(data)
print(t.chain)
print(t.chainIsValid())
for info in t.chain:
print(info['proof'])