-
Notifications
You must be signed in to change notification settings - Fork 0
/
Blockchain.py
114 lines (98 loc) · 4.06 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import json
import rsa
from rsa import VerificationError
from Block import Block
from Transaction import Transaction
from hashlib import sha256
class Blockchain:
def __init__(self):
self.currBlock = Block(0, [], 0)
self.firstBlock = self.currBlock
self.pendingTransactions = []
self.blocks = {}
self.balances = {}
self.calculateBalances()
def addblock(self, block):
self.blocks[block.prev_hash] = self.currBlock
self.currBlock = block
def readchain(self):
readBlock = self.currBlock
chainedblocks = []
while readBlock != self.firstBlock:
chainedblocks.append(readBlock.to_dict())
readBlock = self.blocks[readBlock.prev_hash]
chainedblocks.append(self.firstBlock.to_dict())
blocksDict = {"Blocks": chainedblocks}
return json.dumps(blocksDict,separators=(',', ':'), indent=2)
def viewpendingtransactions(self):
transactionslist = []
for item in self.pendingTransactions:
transactionslist.append(item.to_dict())
transactions = {"Pending_transactions": transactionslist}
return json.dumps(transactions,separators=(',', ':'), indent=2)
def addtransaction(self, to, amount, signature, publicKeyN):
if publicKeyN not in self.balances:
self.balances[publicKeyN] = 0
if to not in self.balances:
self.balances[to] = 0
if self.balances[publicKeyN] < int(amount):
print("Inadequate payment attempt")
return False
self.balances[publicKeyN] -= int(amount)
publicKey = rsa.PublicKey(int(publicKeyN, base=16), 65537)
message = (publicKeyN + to + amount).encode('utf8')
try:
rsa.verify(message, bytes.fromhex(signature), publicKey)
except VerificationError:
print("False signature attempt")
return False
transaction_to_add = Transaction(publicKeyN, to, amount)
self.pendingTransactions.append(transaction_to_add)
return True
def removetransactions(self):
self.pendingTransactions.clear()
def verifyblock(self, proof, publicKeyN):
if publicKeyN not in self.balances:
self.balances[publicKeyN] = 0
if len(self.pendingTransactions) == 0:
print("Nothing to mine")
return "NO TRANSACTIONS TO MINE"
transactions = []
for t in self.pendingTransactions:
transactions.append(t)
transactions.append(Transaction("0", publicKeyN, 1))
newBlock = Block(sha256(self.currBlock.to_json().encode()).hexdigest(), transactions, proof)
hash = sha256(newBlock.to_json().encode()).hexdigest()
if hash[:4] == "0000":
self.addblock(newBlock)
self.removetransactions()
self.calculateBalances()
return "BLOCK MINED SUCCESSFULLY"
else:
print("INVALID BLOCK")
return "INVALID BLOCK - MINE FAILED"
def calculateBalances(self):
readBlock = self.currBlock
for key in self.balances.keys():
self.balances[key] = 0
while readBlock != self.firstBlock:
for t in readBlock.transactions:
if t.source != '0':
self.balances[t.source] -= int(t.amount)
self.balances[t.destination] += int(t.amount)
readBlock = self.blocks[readBlock.prev_hash]
balancesDict = {}
balanceNameList = []
for key in self.balances.keys():
accountDict = {}
accountDict['user'] = key
accountDict['balance'] = self.balances[key]
balanceNameList.append(accountDict)
balancesDict["Balances"] = balanceNameList
self.jsonBalString = json.dumps(balancesDict,separators=(',', ':'), indent=2)
def jsonBalances(self):
return self.jsonBalString
def getBalance(self, publicKeyN):
balanceDict = {}
balanceDict["Balance"] = self.balances[publicKeyN]
return json.dumps(balanceDict,separators=(',', ':'), indent=2)