Building a Simple, Local, Python Blockchain – Part 2

Introduction – Mining Local Blocks in Python

In this guide, we will implement a local proof-of-work mining algorithm in python to illustrate how blocks are mined on a network like Bitcoin. This is a continuation of the original Building a Simple, Local, Python Blockchain – Part 1.

Note: A few tweaks from the Part 1 code will be necessary to implement the local mining functionality we desire. We won’t be as concerned with testing the validity of the blockchain, in order to focus on the new features of our simple blockchain.

If you just want to see the code, it’s hosted here on Github.

Setup & Recap from Part 1

I am running the code on macOS Sierra, using Python 3.X.X. We will be using 4 modules for this tutorial. Hashlib installation is covered in part 1. Time, csv, and random are all native to python, which require no additional installation.

import hashlib
import time
import csv
import random

We will also use several (modified) functions from the code in part 1. The detailed explanations can be found there.

class Block:
    #A basic block contains, index (blockheight), the previous hash, a timestamp, tx information, a nonce, and the current hash
    def __init__(self, index, previousHash, timestamp, data, proof, currentHash):
        self.index = index
        self.previousHash = previousHash
        self.timestamp = timestamp
        self.data = data
        self.currentHash = currentHash
        self.proof = proof

def getGenesisBlock():
    return Block(0, '0', '1496518102.896031', "My very first block :)", 0, '02d779570304667b4c28ba1dbfd4428844a7cab89023205c66858a40937557f8')

#We can calculate the hash for a block providing all information
def calculateHash(index, previousHash, timestamp, data, proof):
    value = str(index) + str(previousHash) + str(timestamp) + str(data) + str(proof)
    sha = hashlib.sha256(value.encode('utf-8'))
    return str(sha.hexdigest())

#Makes it simpler to put a block in a function to calculate hash
def calculateHashForBlock(block):
    return calculateHash(block.index, block.previousHash, block.timestamp, block.data, block.proof)

def getLatestBlock(blockchain):
    return blockchain[len(blockchain)-1]

def generateNextBlock(blockchain, blockData, timestamp, proof):
    previousBlock = getLatestBlock(blockchain)
    nextIndex = int(previousBlock.index) + 1
    nextTimestamp = timestamp
    nextHash = calculateHash(nextIndex, previousBlock.currentHash, nextTimestamp, proof, blockData)
    return Block(nextIndex, previousBlock.currentHash, nextTimestamp, blockData, proof, nextHash)

Basic Proof of Work Implementation

Our mining function leverages a simple generator that creates 5 mock transactions – mimicking the process of taking transactions from a mempool. These randomly generated transactions act as the blockData. We call this function getTxData:

def getTxData():
    txData = ''
    for _ in range(5):
        txTo, txFrom, amount = random.randrange(0, 1000), random.randrange(0, 1000), random.randrange(0, 100)
        transaction = 'User ' + str(txFrom) + " sent " + str(amount) + ' tokens to user ' + str(txTo) + ". "
        txData += transaction
    return txData

This simply creates a long string of 5 transactions with the format: “User <random number> sent <random number> tokens to user <random number>.” all concatenated together. Our function mineNewBlock calls this getTxData function and assigns the string to the variable txData:

def mineNewBlock(difficulty = 5, blockchainPath = 'blockchain.csv'):
    blockchain = readBlockchain(blockchainPath)
    txData = getTxData()
    timestamp = time.time()
    proof = 0
    newBlockFound = False
    print('Mining a block...')
    while not newBlockFound:    
        #print("Trying new block proof...")
        newBlockAttempt = generateNextBlock(blockchain, txData, timestamp, proof)
        if newBlockAttempt.currentHash[0:difficulty] == '0'*difficulty:
            stopTime = time.time()
            timer = stopTime - timestamp
            print('New block found with proof', proof, 'in', round(timer, 2), 'seconds.')
            
            newBlockFound = True
        else:
            proof += 1
    blockchain.append(newBlockAttempt)
    writeBlockchain(blockchain)

Notice that mineNewBlock takes in a difficultly level and a file path for your blockchain .csv, which both are set to defaults. Difficulty is the number of leading 0’s in the hash you are trying to find. (e.g. a difficulty of 5 would have a hash like 00000b4JA7…). Essentially the mining algorithm starts with an attempt to get this hash with proof = 0. If the concatenation of this proof at the end of the block creates a hash with the desired amount of 0’s, this is appended to the end of the blockchain. A message is printed out and a nonce is returned. Let’s run this function several times using a simple ‘mine’ function:

def mine(blocksToMine = 5):
    for _ in range(blocksToMine):
        mineNewBlock()

We run this function and get the following output:

With the .csv blockchain here: Blockchain.csv.

Conclusion

There you have it! A simple, local, functioning blockchain that introduces randomly generated transactions, while mining for hashes of a chosen difficulty. Please feel free to post any comments or questions below!

Cryptocurrency Market News for December 28, 2017

BOOM! Bitcoin is down just like that. The Weak buying power has caused a ralley in the ALTS, but BTC is not out for the count just yet. Where has the top 10 gone? besides ripple, the top 10 have been at a standstill. See more below. Bitcoin Donwfall, ALTS Rise Bitcoin has drastically lost […]

indaHash: A One Stop Shop for Brands, Influencers, and Fans

Social media has become an essential part of everyday life for millions of people as they use it to follow and keep updated on their favorite movies, music, and internet celebrities. The range of influence that these celebrities possess is massive, and many companies and brands pay top dollar for ads and product placement in […]

CoinMarketCal: Scraping Information for Crypto Analysis

Warning: Coinmarketcal.com has changed layouts, thus the code no longer applies – still a great guide & reference.     If you’ve ever been to CoinMarketCal.com, you’ll noticed an abundance of crowd sourced information about cryptocurrency updates, roadmaps, and other changes. I wanted to use the crowdsourced roadmap data to see if it had any […]

Getting Started with the CryptoCompare API in Python

If you’ve ever browsed CryptoCompare.com, you’ll find it to be a wealth of crypto knowledge on anything from mining to ICO’s to exchanges. It’s user friendly website is built to be accessed by anyone regardless of experience, but what many people don’t realize is the vast amount of information that can be used for analytics […]

Researching ICO’s: A Study of Two Initial Coin Offerings

With more ICO’s being released everyday, it’s becoming increasingly difficult to filter out scams and low-potential coins from influential ideas and high-growth coins. This guide serves to analyze the potential of ICO’s in the long term. It is not meant to find coins that will make you lots of money very quickly. Instead, it relies on […]

It’s Time: Moving Bitcoin from Coinbase to Electrum

I’m sure you’ve heard the terms UASF, UAHF, and BIP148 tossed around in the past few weeks, but what’s really going on? and what does that mean for the average Bitcoin user? I would suggest checking out http://www.uasf.co/ for full details, but effectively on August 1st, 2017 we could see the Bitcoin blockchain split into multiple […]

Beginning Solidity: Creating a Cryptocurrency Token on the Ethereum Network

If it seems like there’s a new cryptocurrency being released every day, it’s because there is. Some of the big crypto-players have set up platforms to make the creation of your own ‘cryptocurrency’ simple. For example, Ethereum-based projects like Golem and Augur. These are run on the same blockchain as Ethereum, so they’re typically referred to […]