Building a Simple, Local, Python Blockchain – Part 1

It’s one thing to understand the concept of a blockchain, but it’s an entirely new level of understanding to be able to implement one. In the following series of tutorials, you will learn how to develop a very simple blockchain using Python 3.

This tutorial is for people who are fairly familiar with blockchains. If you need assistance with some of the technical aspects of a blockchain, I suggest this coursera course.

A good portion of the blockchain outline came from this article by Lauri Hartikka. If you’re JavaScript literate, I suggest checking it out.

The Genesis Block

Before we build the first block, we need to create a class for all of blocks to abide by. It should have the attributes:

  • Index – it’s position in the blockchain
  • Previous Hash – the hash of the block that came before the current block
  • Timestamp – the time the block was created
  • Data – the information (e.g. transactions) that the block carries
  • Hash – the hash of the block itself.

We implement it like this:

class Block:
    def __init__(self, index, previousHash, timestamp, data, currentHash):
        self.index = index
        self.previousHash = previousHash
        self.timestamp = timestamp
        self.data = data
        self.currentHash = currentHash

Now we can create our first block! This is commonly referred to as the genesis block:

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

blockchain = [getGenesisBlock()]

Your genesis block doesn’t have to be exactly like this. The only requirements are that the genesis has index of 0 and the timestamp is less than the current time. The previous has doesn’t matter, data can be anything you want, and we’ll learn about hashing next!

Hashing Blocks

Now that we have our first block, how do we get a hash for it? Python has a library which includes SHA256 – the hashing algorithm that Bitcoin and others use. To install this package, go to the command line and enter:

pip install hashlib

We will create two functions for ease of use, but only the first is actually necessary – calculateHash and calculateHashForBlock. The second function depends on the first, but sometimes it’s easier to enter a block and get the hash.

def calculateHash(index, previousHash, timestamp, data):
    value = str(index) + str(previousHash) + str(timestamp) + str(data)
    sha = hashlib.sha256(value.encode('utf-8'))
    return str(sha.hexdigest())

def calculateHashForBlock(block):
    return calculateHash(block.index, block.previousHash, block.timestamp, block.data)

We essentially convert all of the block information into one large string. Then we encode it, and finally hash it with hashlib.sha256(). 

Creating New Blocks

Now that we have our first block and can hash blocks, we need a function to add blocks to the blockchain. This will incorporate a function that can retrieve our latest block.

import time

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

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

Validation

So far we can:

  1. Create a genesis block
  2. Hash blocks
  3. Create additional blocks

But how can we be sure these blocks are legitimate? And what about checking the entire chain? Let’s start with a function that checks if two blocks are the same (to make sure no one alters the genesis block):

def isSameBlock(block1, block2):
    if block1.index != block2.index:
        return False
    elif block1.previousHash != block2.previousHash:
        return False
    elif block1.timestamp != block2.timestamp:
        return False
    elif block1.data != block2.data:
        return False
    elif block1.currentHash != block2.currentHash:
        return False
    return True

Now we can write a function that takes the previous block and the new block as inputs. It determines if the block is valid based on hashes and indices matching up:

def isValidNewBlock(newBlock, previousBlock):
    if previousBlock.index + 1 != newBlock.index:
        print('Indices Do Not Match Up')
        return False
    elif previousBlock.currentHash != newBlock.previousHash:
        print("Previous hash does not match")
        return False
    elif calculateHashForBlock(newBlock) != newBlock.hash:
        print("Hash is invalid")
        return False
    return True

Using the two functions above, we can check the validity of an entire chain by iterating over the entire list in a for loop:

def isValidChain(bcToValidate):
    if not isSameBlock(bcToValidate[0], getGenesisBlock()):
        print('Genesis Block Incorrect')
        return False
    
    tempBlocks = [bcToValidate[0]]
    for i in range(1, len(bcToValidate)):
        if isValidNewBlock(bcToValidate[i], tempBlocks[i-1]):
            tempBlocks.append(bcToValidate[i])
        else:
            return False
    return True

Now we can check our chain!

Putting it together

All the code together looks like:

 
import hashlib
import time

class Block:
    def __init__(self, index, previousHash, timestamp, data, currentHash):
        self.index = index
        self.previousHash = previousHash
        self.timestamp = timestamp
        self.data = data
        self.currentHash = currentHash

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

blockchain = [getGenesisBlock()]

def calculateHash(index, previousHash, timestamp, data):
    value = str(index) + str(previousHash) + str(timestamp) + str(data)
    sha = hashlib.sha256(value.encode('utf-8'))
    return str(sha.hexdigest())

def calculateHashForBlock(block):
    return calculateHash(block.index, block.previousHash, block.timestamp, block.data)

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

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

def isSameBlock(block1, block2):
    if block1.index != block2.index:
        return False
    elif block1.previousHash != block2.previousHash:
        return False
    elif block1.timestamp != block2.timestamp:
        return False
    elif block1.data != block2.data:
        return False
    elif block1.currentHash != block2.currentHash:
        return False
    return True

def isValidNewBlock(newBlock, previousBlock):
    if previousBlock.index + 1 != newBlock.index:
        print('Indices Do Not Match Up')
        return False
    elif previousBlock.currentHash != newBlock.previousHash:
        print("Previous hash does not match")
        return False
    elif calculateHashForBlock(newBlock) != newBlock.hash:
        print("Hash is invalid")
        return False
    return True

def isValidChain(bcToValidate):
    if not isSameBlock(bcToValidate[0], getGenesisBlock()):
        print('Genesis Block Incorrect')
        return False
    
    tempBlocks = [bcToValidate[0]]
    for i in range(1, len(bcToValidate)):
        if isValidNewBlock(bcToValidate[i], tempBlocks[i-1]):
            tempBlocks.append(bcToValidate[i])
        else:
            return False
    return True

Now you have to ability to independently manage a blockchain.

http://blockxchain.org/2017/06/04/simple-local-python-blockchain-pt1/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值