-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblockchain.py
More file actions
129 lines (111 loc) · 3.94 KB
/
blockchain.py
File metadata and controls
129 lines (111 loc) · 3.94 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
'''
Simple Blockchain class.
Classes:
Blockchain
'''
from block import Block
from transaction import Transaction
from wallet import Wallet
import utils
class Blockchain:
'''
Complete Blockchain.
Attributes:
chain (list): list of Blocks that make the Blockchain.
difficulty (int): number of zeroes at beginning of hashes to calculate.
pending_transactions (list): transactions that are not yet in the chain.
mining_reward (float): number of coins rewarded for mining a block.
mining_block (Block): Block that it is currently being mined
# TODO: Concurrency will be added here using this attribute
'''
def __init__(self):
self.chain = [Block(b'',[])]
self.difficulty = 1
self.pending_transactions = []
self.mining_reward = 50.0
self.mining_block = None
self.reward_wallet = Wallet('','')
def add_transaction(
self,
send_wallet: Wallet,
recieve_wallet: Wallet,
amount: float,
fee: float,
path: str,
password: str
):
'''
Validates a transaction and adds it to the pending transactions.
Args:
send_wallet (Wallet): wallet sending money.
recieve_wallet (Wallet): wallet receiving money.
amount (float): amount of money sent.
fee (float): fee paid.
path (str): path to private key of sending wallet.
password (str): password of private key.
# TODO: Last two temporary to do tests more quickly
'''
pk = utils.read_private_key(path, password)
transaction = Transaction(send_wallet, recieve_wallet, amount, fee, pk)
if transaction.is_valid():
self.pending_transactions.append(transaction)
def halving(self):
'''
Halves reward for mining.
'''
self.mining_reward /= 2
def new_block(self):
'''
Create a new block to start mining it.
'''
self.mining_block = Block(
self.chain[-1].hash,
self.pending_transactions
)
def mine_pending_transaction(self, wallet: Wallet):
'''
Mine new block to place pending transactions.
Args:
wallet (Wallet): Wallet that mined the coin
'''
# Create a new block at the end of the chain
if not self.mining_block:
self.new_block()
# Block is mineed and added to chain
self.mining_block.mine(self.difficulty)
self.chain.append(self.mining_block)
# First transaction of next block is the reward for mining.
self.pending_transactions = [Transaction(
self.reward_wallet,
wallet,
self.mining_reward,
0,
None
)]
# Empty attribute so transactions can be generated again before mining again.
# This is temporal. In the future it will be async and rewarding wallet pools.
self.mining_block = None
#Increase difficulty with number of blocks
if len(self.chain) % 10 == 0:
self.difficulty += 1
def verify_balance(self, wallet: Wallet) -> bool:
'''
Verify the balance of a wallet.
Args:
wallet (Wallet): wallet to verify the balance.
Returns:
is_valid (bool): boolean if balance is valid according to transactions.
'''
balance = 0
for block in self.chain:
for t in block.transactions:
if t.sending_wallet == wallet:
balance -= (t.amount+t.fee)
if t.receiving_wallet == wallet:
balance += t.amount
return balance == wallet.balance
def verify_blockchain(self):
'''
Verifies the hashes of the blockchain to see if they are correct.
'''
return all((block.hash == block.calculate_hash() for block in self.chain))