Skip to content

Commit 5ec3f51

Browse files
committed
Improve mine_block
1 parent ec9c153 commit 5ec3f51

3 files changed

Lines changed: 44 additions & 12 deletions

File tree

backend/blockchain/block.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
import time
22

33
from backend.util.crypto_hash import crypto_hash
4+
from backend.config import MINE_RATE
45

56
GENESIS_DATA = {
67
'timestamp': 1,
78
'last_hash': 'genesis_last_hash',
89
'hash': 'genesis_hash',
9-
'data': []
10+
'data': [],
11+
'difficulty': 3,
12+
'nonce': 'genesis_nonce'
1013
}
1114

1215
class Block:
1316
"""
1417
Block: a unit of storage.
1518
Store transactions in a blockchain that supports a cryptocurrency.
1619
"""
17-
def __init__(self, timestamp, last_hash, hash, data):
20+
def __init__(self, timestamp, last_hash, hash, data, difficulty, nonce):
1821
self.timestamp = timestamp
1922
self.last_hash = last_hash
2023
self.hash = hash
2124
self.data = data
25+
self.difficulty = difficulty
26+
self.nonce = nonce
2227

2328
def add_block(self, data):
2429
self.chain.append(Block(data))
@@ -29,33 +34,53 @@ def __repr__(self):
2934
f'timestamp: {self.timestamp}, '
3035
f'last_hash: {self.last_hash}, '
3136
f'hash: {self.hash}, '
32-
f'data: {self.data})'
37+
f'data: {self.data}, '
38+
f'difficulty: {self.difficulty}, '
39+
f'nonce: {self.nonce})'
3340
)
3441

3542
@staticmethod
3643
def mine_block(last_block, data):
3744
"""
38-
Mine a block based on the given last_block and data.
45+
Mine a block based on the given last_block and data, until a block hash
46+
is found that meets the leading 0's proof of work requirement.
3947
"""
4048
timestamp = time.time_ns()
4149
last_hash = last_block.hash
42-
hash = crypto_hash(timestamp, last_hash, data)
50+
difficulty = Block.adjust_difficulty(last_block, timestamp)
51+
nonce = 0
52+
hash = crypto_hash(timestamp, last_hash, data, difficulty, nonce)
4353

44-
return Block(timestamp, last_hash, hash, data)
54+
while hash[0:difficulty] != '0' * difficulty:
55+
nonce += 1
56+
timestamp = time.time_ns()
57+
difficulty = Block.adjust_difficulty(last_block, timestamp)
58+
hash = crypto_hash(timestamp, last_hash, data, difficulty, nonce)
59+
60+
return Block(timestamp, last_hash, hash, data, difficulty, nonce)
4561

4662
@staticmethod
4763
def genesis():
4864
"""
4965
Generate the genesis block.
5066
"""
51-
# return Block(
52-
# timestamp=GENESIS_DATA['timestamp'],
53-
# last_hash=GENESIS_DATA['last_hash'],
54-
# hash=GENESIS_DATA['hash'],
55-
# data=GENESIS_DATA['data']
56-
# )
5767
return Block(**GENESIS_DATA)
5868

69+
@staticmethod
70+
def adjust_difficulty(last_block, new_timestamp):
71+
"""
72+
Calculate the adjusted difficulty according to the MINE_RATE.
73+
Increase the difficulty for slowly mined blocks.
74+
Decrease the difficulty for slowly mined blocks.
75+
"""
76+
if (new_timestamp - last_block.timestamp) < MINE_RATE:
77+
return last_block.difficulty + 1
78+
79+
if (last_block.difficulty - 1) > 0:
80+
return last_block.difficulty - 1
81+
82+
return 1
83+
5984
def main():
6085
genesis_block = Block.genesis()
6186
block = Block.mine_block(genesis_block, 'foo')

backend/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
NANOSECONDS = 1
2+
MICROSECONDS = 1000 * NANOSECONDS
3+
MILLISECONDS = 1000 * MICROSECONDS
4+
SECONDS = 1000 * MILLISECONDS
5+
6+
MINE_RATE = 4 * SECONDS

backend/tests/blockchain/test_block.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ def test_mine_block():
88
assert isinstance(block, Block)
99
assert block.data == data
1010
assert block.last_hash == last_block.hash
11+
assert block.hash[0:block.difficulty] == '0' * block.difficulty
1112

1213
def test_genesis():
1314
genesis = Block.genesis()

0 commit comments

Comments
 (0)