Build a Blockchain in Python, Part 3: Mining Rewards and Transaction Integration
Welcome!
Today, we're going to implement some other features of mining and integrate transactions into our blockchain. If you look back at the code from the first article, you can see that the mine_block() function doesn't include a reward transaction for the miner, as it should.
It also has no way to get the balance of an address or to add transactions to the pending transactions pool.
We can implement this adding an add_transaction function to the Blockchain object and modifying init():
def __init__(self, difficulty):
self.difficulty = difficulty
self.chain = [self.create_genesis_block()]
self.pending_transactions = [] #change here
Now to add the add_transaction function:
def add_transaction(self, transaction):
if transaction.verify():
if transaction.amount + transaction.fee <= self.balanceOf(transaction._from):
for pending_tx in self.pending_transactions:
if pending_tx.hash == transaction.hash:
return
self.pending_transactions.append(transaction)
This function first verifies the signature, then checks if the address has enough funds. Notice that it references a balanceOf function that we will add next.
It then checks if the transaction is already in the pending_transactions pool, and if not, it appends itself to the pending_transactions pool, as well as collect if included.
balanceOf function:
def balanceOf(self, address):
balance = 0
for block in self.blockchain[1:]:
for transaction in block.transactions:
if transaction._from == address:
balance -= transaction.amount
balance -= transaction.fee
if transaction._to == address:
balance += transaction.amount
return balance
Now, we can add transactions and check balances of addresses, but how do coins come about in the first place? That's right, mining rewards:
Let's modify the existing mine_block to take a 'reward_address' parameter and include a reward transaction as well as any other pending transactions.
def mine_block(self, reward_address):
nonce = 0
fees = 0
for transaction in self.pending_transactions:
fees += transaction.fee
reward_transaction = Transaction(reward_address, 'New Coins and Fees', self.coins_per_block + fees, 0, time.time())
CandidateBlock = Block(len(self.blockchain), self.blockchain[-1].hash, int(
time.time()), [reward_transaction] + self.pending_transactions, nonce)
while not CandidateBlock.calculateHash().startswith('0' * round(self.hash_difficulty)):
fees = 0
for transaction in self.pending_transactions:
fees += transaction.fee
nonce += 1
reward_transaction = Transaction(reward_address, 'New Coins and Fees', self.coins_per_block + fees, 0, time.time())
CandidateBlock = Block(len(self.blockchain), self.blockchain[-1].hash, int(
time.time()), [reward_transaction] + self.pending_transactions, nonce)
return CandidateBlock
That's all for today, I hope you enjoyed! Comment any problems you're having below and upvote if you liked it!