Build a Blockchain in Python, Part 3: Mining Rewards and Transaction Integration

in #python6 years ago (edited)

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!