-
Notifications
You must be signed in to change notification settings - Fork 1
/
blockchain.py
95 lines (87 loc) · 3.67 KB
/
blockchain.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# -*- coding: utf-8 -*-
import json
import hashlib
import os
class Blockchain:
def __init__(self, logger, txobj):
self.chain = []
# If chain data file exist, load data.
if os.path.exists('.blockchain/chain.json'):
f = open('.blockchain/chain.json', 'r')
chain = json.load(f)
for key in chain.keys():
self.chain.append(chain[key])
f.close()
else:
# Make blockchain include genesis
self.genesis = {"blocknum":0,"tx":[{"id":0, "body":"hello world!"}],"previous_hash":0}
self.chain.append(self.genesis)
self.logger = logger
self.tx = txobj
def generate_block(self, score):
# Make new Block include all tx in txpool
pool = []
for txid in self.tx.txpool.keys():
pool.append(self.tx.txpool[txid])
blocknum = len(self.chain)
previous = json.dumps(self.chain[-1])
previoushash = hashlib.sha256(previous.encode('utf-8')).hexdigest()
block = {"blocknum":blocknum, "tx":pool, "previous_hash":previoushash, "score":score}
self.tx.txpool = {}
print("-----------------------")
print(json.dumps(block,indent=4,
ensure_ascii=False,
sort_keys=True))
print("-----------------------")
self.logger.log(20,"Generate New Block(%s)" % block["blocknum"])
return block
def add_new_block(self, block):
# if pass verify block, add block to chain
res = self.verify_block(block)
if res["code"] == 0:
for tx in block["tx"]:
if tx["id"] in self.tx.txpool.keys():
self.tx.txpool.pop(tx["id"])
self.chain.append(block)
self.logger.log(20,"Append New Block(%s) to my chain" % block["blocknum"])
self.chain_dump()
return True, res
else:
# TODO: resolv confrict of chain -> difine consensus
return False, res
def rm_last_block(self):
for tx in self.chain[-1]["tx"]:
self.tx.add_tx_pool(tx)
rmblocknum = self.chain[-1]["blocknum"]
self.chain.pop(-1)
self.logger.log(20,"Remove Block(%s) from my chain" % rmblocknum)
def verify_block(self, block):
# Verify Block
previous = json.dumps(self.chain[-1])
previoushash = hashlib.sha256(previous.encode('utf-8')).hexdigest()
if block["blocknum"] == self.chain[-1]["blocknum"]+1:
# new block
if block["previous_hash"] == previoushash:
msg = {"result":"Checked Block has been verified","code":0}
else:
msg = {"result":"Checked Block is from different chain","code":1}
elif self.chain[-1]["blocknum"] < block["blocknum"]:
# orphan block
msg = {"result":"Checked Block is orphan","code":2}
else:
# old block
jsonblock = json.dumps(block)
myblock = json.dumps(self.chain[block["blocknum"]])
if hashlib.sha256(jsonblock.encode('utf-8')).hexdigest() == hashlib.sha256(myblock.encode('utf-8')).hexdigest():
msg = {"result":"Checked Block has been in my chain","code":3}
else:
msg = {"result":"Checked Block is old and come from different chain","code":4}
self.logger.log(20, msg["result"])
return msg
def chain_dump(self):
chaindict = {}
for a in range(0,len(self.chain)):
chaindict[a] = self.chain[a]
savepath = '.blockchain/chain.json'
with open(savepath, 'w') as outfile:
json.dump(chaindict, outfile, indent=4)