-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathblock.py
93 lines (79 loc) · 2.92 KB
/
block.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
# coding:utf-8
import json
from pow import ProofOfWork
from block_header import BlockHeader
from transactions import Transaction
from merkle import MerkleTree
from errors import NonceNotFoundError, TransactionVerifyError
class Block(object):
"""A Block
Attributes:
_magic_no (int): Magic number
_block_header (Block): Header of the previous Block.
_transactions (Transaction): transactions of the current Block.
"""
MAGIC_NO = 0xBCBCBCBC
def __init__(self, block_header, transactions):
self._magic_no = self.MAGIC_NO
self._block_header = block_header
self._transactions = transactions
data = []
for tx in self._transactions:
data.append(json.dumps(tx.serialize()))
merkle_tree = MerkleTree(data)
self.set_hash_merkle_root_hash(merkle_tree.root_hash)
def mine(self, bc):
pow = ProofOfWork(self)
for tx in self._transactions:
if not bc.verify_transaction(tx):
raise TransactionVerifyError('transaction verify error')
try:
nonce, _ = pow.run()
except NonceNotFoundError as e:
print(e)
self._block_header.nonce = nonce
def validate(self, bc):
pow = ProofOfWork(self)
for tx in self._transactions:
if not bc.verify_transaction(tx):
raise TransactionVerifyError('transaction verify error')
return pow.validate()
@classmethod
def new_genesis_block(cls, coin_base_tx):
block_header = BlockHeader.new_genesis_block_header()
return cls(block_header, coin_base_tx)
@property
def block_header(self):
return self._block_header
def set_transactions(self, txs):
self._transactions = txs
@property
def transactions(self):
return self._transactions
def set_header_hash(self):
self._block_header.set_hash()
def set_hash_merkle_root_hash(self, merkle_root_hash):
self.block_header.hash_merkle_root = merkle_root_hash
def get_header_hash(self):
return self._block_header.hash
def serialize(self):
return {
"magic_no": self._magic_no,
"block_header": self._block_header.serialize(),
"transactions": [tx.serialize() for tx in self._transactions]
}
@classmethod
def deserialize(cls, data):
block_header_dict = data['block_header']
block_header = BlockHeader.deserialize(block_header_dict)
transactions = data["transactions"]
txs = []
for transaction in transactions:
txs.append(Transaction.deserialize(transaction))
return cls(block_header, txs)
def __eq__(self, other):
if isinstance(other, Block):
return self.block_header.hash == other.block_header.hash
return False
def __repr__(self):
return 'Block(_block_header=%s)' % self._block_header