Instantly share code, notes, and snippets.

Embed
What would you like to do?
import hashlib as hasher
import datetime as date
# Define what a Snakecoin block is
class Block:
def __init__(self, index, timestamp, data, previous_hash):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.hash = self.hash_block()
def hash_block(self):
sha = hasher.sha256()
sha.update(str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash))
return sha.hexdigest()
# Generate genesis block
def create_genesis_block():
# Manually construct a block with
# index zero and arbitrary previous hash
return Block(0, date.datetime.now(), "Genesis Block", "0")
# Generate all later blocks in the blockchain
def next_block(last_block):
this_index = last_block.index + 1
this_timestamp = date.datetime.now()
this_data = "Hey! I'm block " + str(this_index)
this_hash = last_block.hash
return Block(this_index, this_timestamp, this_data, this_hash)
# Create the blockchain and add the genesis block
blockchain = [create_genesis_block()]
previous_block = blockchain[0]
# How many blocks should we add to the chain
# after the genesis block
num_of_blocks_to_add = 20
# Add blocks to the chain
for i in range(0, num_of_blocks_to_add):
block_to_add = next_block(previous_block)
blockchain.append(block_to_add)
previous_block = block_to_add
# Tell everyone about it!
print "Block #{} has been added to the blockchain!".format(block_to_add.index)
print "Hash: {}\n".format(block_to_add.hash)
@Boom16

This comment has been minimized.

Show comment
Hide comment
@Boom16

Boom16 Jul 18, 2017

I am trying to use/learn this code and I keep getting the error "Unicode-objects must be encoded before hashing". Do you know what needs to be encoded/ how to encode them? Thanks in advance for any help you can offer.

Boom16 commented Jul 18, 2017

I am trying to use/learn this code and I keep getting the error "Unicode-objects must be encoded before hashing". Do you know what needs to be encoded/ how to encode them? Thanks in advance for any help you can offer.

@joeblankenship1

This comment has been minimized.

Show comment
Hide comment
@joeblankenship1

joeblankenship1 Jul 19, 2017

I modified line 15 as below and it worked just fine:

sha.update(str(self.index).encode('utf-8') + str(self.timestamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previous_hash).encode('utf-8'))

joeblankenship1 commented Jul 19, 2017

I modified line 15 as below and it worked just fine:

sha.update(str(self.index).encode('utf-8') + str(self.timestamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previous_hash).encode('utf-8'))

@tbrooke

This comment has been minimized.

Show comment
Hide comment
@tbrooke

tbrooke Jul 19, 2017

I am using Python 3 which may be the problem but I get the following error:

File "/Users/tmb/python/SnakeCoin/Snake.py", line 24, in create_genesis_block
return Block(0, date.datetime.now(), "Genesis Block", "0")
TypeError: object() takes no parameters

This is my Block:

Define what a Snakecoin block is

class Block:
def init(self, index, timestamp, data, previous_hash):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.hash = self.hash_block()

This is my Create Genesis Block:

Generate genesis block

def create_genesis_block():
# Manually construct a block with
# index zero and arbitrary previous hash
return Block(0, date.datetime.now(), "Genesis Block", "0")

tbrooke commented Jul 19, 2017

I am using Python 3 which may be the problem but I get the following error:

File "/Users/tmb/python/SnakeCoin/Snake.py", line 24, in create_genesis_block
return Block(0, date.datetime.now(), "Genesis Block", "0")
TypeError: object() takes no parameters

This is my Block:

Define what a Snakecoin block is

class Block:
def init(self, index, timestamp, data, previous_hash):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.hash = self.hash_block()

This is my Create Genesis Block:

Generate genesis block

def create_genesis_block():
# Manually construct a block with
# index zero and arbitrary previous hash
return Block(0, date.datetime.now(), "Genesis Block", "0")

@rdsteed

This comment has been minimized.

Show comment
Hide comment
@rdsteed

rdsteed Jul 21, 2017

@tbrooke
It's hard to tell the problem from the code you included, but your error is often due to Python indentation problems. Because indentation in Python determines block nesting, proper indentation is critical. Even if the indentation looks right, there can be problems if you mix tabs and spaces.

rdsteed commented Jul 21, 2017

@tbrooke
It's hard to tell the problem from the code you included, but your error is often due to Python indentation problems. Because indentation in Python determines block nesting, proper indentation is critical. Even if the indentation looks right, there can be problems if you mix tabs and spaces.

@aunyks

This comment has been minimized.

Show comment
Hide comment
@aunyks

aunyks Jul 23, 2017

@Boom16 See @joeblankenship1 's comment under yours for help

Owner

aunyks commented Jul 23, 2017

@Boom16 See @joeblankenship1 's comment under yours for help

@rogel-appdev

This comment has been minimized.

Show comment
Hide comment
@rogel-appdev

rogel-appdev Aug 6, 2017

Hello there,

I am getting the below error:

blockchain = [create_genesis_block()]

NameError: name 'create_genesis_block' is not defined

I am using Python 3.6.0 and IDLE 3.6.0

Thanks in advance

rogel-appdev commented Aug 6, 2017

Hello there,

I am getting the below error:

blockchain = [create_genesis_block()]

NameError: name 'create_genesis_block' is not defined

I am using Python 3.6.0 and IDLE 3.6.0

Thanks in advance

@thinkholic

This comment has been minimized.

Show comment
Hide comment
@thinkholic

thinkholic Aug 8, 2017

JS/nodejs version

const sha256 = require('js-sha256');

// Define the Block Class
class Block {
  constructor(index, data, previousHash) {
    this.index = index;
    this.timestamp = new Date();
    this.data = data;
    this.previousHash = previousHash;
    this.hash = this.generateHash();

  }

  generateHash() {
    return sha256.hex(`${this.index}${this.timestamp}${this.data}${this.previousHash}`);
  }
}

// Create genesis block
function createGenesisBlock() {
  return new Block(0, 'Genesis Block', '0');
}

// Create all other blocks
function createNextBlock(previousBlock, data=null) {
  const index = previousBlock.index + 1;
  const previousHash = previousBlock.hash;
  return new Block(index, data, previousHash);
}

// Demo
// Create the Blockchain
const blockchain = [createGenesisBlock()];
let previousBlock = blockchain[0];

for (let i=0; i<20; i++) {
  const block = createNextBlock(previousBlock);
  blockchain.push(block);
  previousBlock = block;

  console.log(`Block #${block.index} has been added to the blockchain!.`);
  console.log(`Hash: ${block.hash}\n`);
}

thinkholic commented Aug 8, 2017

JS/nodejs version

const sha256 = require('js-sha256');

// Define the Block Class
class Block {
  constructor(index, data, previousHash) {
    this.index = index;
    this.timestamp = new Date();
    this.data = data;
    this.previousHash = previousHash;
    this.hash = this.generateHash();

  }

  generateHash() {
    return sha256.hex(`${this.index}${this.timestamp}${this.data}${this.previousHash}`);
  }
}

// Create genesis block
function createGenesisBlock() {
  return new Block(0, 'Genesis Block', '0');
}

// Create all other blocks
function createNextBlock(previousBlock, data=null) {
  const index = previousBlock.index + 1;
  const previousHash = previousBlock.hash;
  return new Block(index, data, previousHash);
}

// Demo
// Create the Blockchain
const blockchain = [createGenesisBlock()];
let previousBlock = blockchain[0];

for (let i=0; i<20; i++) {
  const block = createNextBlock(previousBlock);
  blockchain.push(block);
  previousBlock = block;

  console.log(`Block #${block.index} has been added to the blockchain!.`);
  console.log(`Hash: ${block.hash}\n`);
}
@wowkin2

This comment has been minimized.

Show comment
Hide comment
@wowkin2

wowkin2 Aug 8, 2017

I think that index should be autoincremented to avoid case there are blocks with the same index.

wowkin2 commented Aug 8, 2017

I think that index should be autoincremented to avoid case there are blocks with the same index.

@wowkin2

This comment has been minimized.

Show comment
Hide comment
@wowkin2

wowkin2 Aug 8, 2017

Made some updates (see my gist).
Created separate class for blockchain, as result got simple interface to create blocks and retrieve information about them.
In future, we can add there more functionality there.

wowkin2 commented Aug 8, 2017

Made some updates (see my gist).
Created separate class for blockchain, as result got simple interface to create blocks and retrieve information about them.
In future, we can add there more functionality there.

@wowkin2

This comment has been minimized.

Show comment
Hide comment
@wowkin2

wowkin2 Aug 8, 2017

@aunyks, found other gist-files about Snakecoin, maybe it is good idea to join them in a single gist or create a repo for that?

wowkin2 commented Aug 8, 2017

@aunyks, found other gist-files about Snakecoin, maybe it is good idea to join them in a single gist or create a repo for that?

@ssabat

This comment has been minimized.

Show comment
Hide comment
@ssabat

ssabat Sep 14, 2017

I tried js/nodejs version on my Mac.

I saved code in a file called snakecoin.js. Then, I did following.

brew install node ( it will install dependency icu4c )
npm install js-sha256
node snakecoin.js

20 blocks were created and added. Last few lines of output are:

..............
...................
Block #18 has been added to the blockchain!.
Hash: af71818c33d461d5ccb58902df4ac56b5774ebf533e43fd3fe18d66a44073f8c

Block #19 has been added to the blockchain!.
Hash: 650fedbb88c13e3a2cb45e5a35b08c8d4ac907137cd8d810a09a2c53815943b8

Block #20 has been added to the blockchain!.
Hash: 7317a8c58a031c23e032e947c54f28dcac9b076274992d7b486d6558d35ff86f

Thanks @thinkholic for sharing the code.

ssabat commented Sep 14, 2017

I tried js/nodejs version on my Mac.

I saved code in a file called snakecoin.js. Then, I did following.

brew install node ( it will install dependency icu4c )
npm install js-sha256
node snakecoin.js

20 blocks were created and added. Last few lines of output are:

..............
...................
Block #18 has been added to the blockchain!.
Hash: af71818c33d461d5ccb58902df4ac56b5774ebf533e43fd3fe18d66a44073f8c

Block #19 has been added to the blockchain!.
Hash: 650fedbb88c13e3a2cb45e5a35b08c8d4ac907137cd8d810a09a2c53815943b8

Block #20 has been added to the blockchain!.
Hash: 7317a8c58a031c23e032e947c54f28dcac9b076274992d7b486d6558d35ff86f

Thanks @thinkholic for sharing the code.

@Winand

This comment has been minimized.

Show comment
Hide comment
@Winand

Winand Oct 30, 2017

@joeblankenship1 you can encode all data at once to utf-8 like this:

sha.update((str(self.index) + 
            str(self.timestamp) + 
            str(self.data) + 
            str(self.previous_hash)).encode())

Or we can append data chunks separately: https://docs.python.org/3/library/hashlib.html#hashlib.hash.update

sha.update(str(self.index).encode())
sha.update(str(self.timestamp).encode())
sha.update(str(self.data).encode())
sha.update(str(self.previous_hash).encode())

----Python 3

Winand commented Oct 30, 2017

@joeblankenship1 you can encode all data at once to utf-8 like this:

sha.update((str(self.index) + 
            str(self.timestamp) + 
            str(self.data) + 
            str(self.previous_hash)).encode())

Or we can append data chunks separately: https://docs.python.org/3/library/hashlib.html#hashlib.hash.update

sha.update(str(self.index).encode())
sha.update(str(self.timestamp).encode())
sha.update(str(self.data).encode())
sha.update(str(self.previous_hash).encode())

----Python 3

@JohnStuartRutledge

This comment has been minimized.

Show comment
Hide comment
@JohnStuartRutledge

JohnStuartRutledge Nov 7, 2017

In case it helps anyone, here is the working Python 3 version I got working that includes a few tweaks like encoding the class attributes to utf-8.

Thanks to OP for the tutorial!

from datetime import datetime
import hashlib as hasher


class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.hash = self.hash_block()

    def __str__(self):
        return 'Block #{}'.format(self.index)

    def hash_block(self):
        sha = hasher.sha256()
        seq = (str(x) for x in (
               self.index, self.timestamp, self.data, self.previous_hash))
        sha.update(''.join(seq).encode('utf-8'))
        return sha.hexdigest()


def make_genesis_block():
    """Make the first block in a block-chain."""
    block = Block(index=0,
                  timestamp=datetime.now(),
                  data="Genesis Block",
                  previous_hash="0")
    return block


def next_block(last_block, data=''):
    """Return next block in a block chain."""
    idx = last_block.index + 1
    block = Block(index=idx,
                  timestamp=datetime.now(),
                  data='{}{}'.format(data, idx),
                  previous_hash=last_block.hash)
    return block


def test_code():
    """Test creating chain of 20 blocks."""
    blockchain = [make_genesis_block()]
    prev_block = blockchain[0]
    for _ in range(0, 20):
        block = next_block(prev_block, data='some data here')
        blockchain.append(block)
        prev_block = block
        print('{} added to blockchain'.format(block))
        print('Hash: {}\n'.format(block.hash))


# run the test code
test_code()

JohnStuartRutledge commented Nov 7, 2017

In case it helps anyone, here is the working Python 3 version I got working that includes a few tweaks like encoding the class attributes to utf-8.

Thanks to OP for the tutorial!

from datetime import datetime
import hashlib as hasher


class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.hash = self.hash_block()

    def __str__(self):
        return 'Block #{}'.format(self.index)

    def hash_block(self):
        sha = hasher.sha256()
        seq = (str(x) for x in (
               self.index, self.timestamp, self.data, self.previous_hash))
        sha.update(''.join(seq).encode('utf-8'))
        return sha.hexdigest()


def make_genesis_block():
    """Make the first block in a block-chain."""
    block = Block(index=0,
                  timestamp=datetime.now(),
                  data="Genesis Block",
                  previous_hash="0")
    return block


def next_block(last_block, data=''):
    """Return next block in a block chain."""
    idx = last_block.index + 1
    block = Block(index=idx,
                  timestamp=datetime.now(),
                  data='{}{}'.format(data, idx),
                  previous_hash=last_block.hash)
    return block


def test_code():
    """Test creating chain of 20 blocks."""
    blockchain = [make_genesis_block()]
    prev_block = blockchain[0]
    for _ in range(0, 20):
        block = next_block(prev_block, data='some data here')
        blockchain.append(block)
        prev_block = block
        print('{} added to blockchain'.format(block))
        print('Hash: {}\n'.format(block.hash))


# run the test code
test_code()
@cleverlight

This comment has been minimized.

Show comment
Hide comment
@cleverlight

cleverlight Nov 13, 2017

@aunyks please could you include a licence in your code because I'd like to reuse it? Alternatively might you consider putting a default licence on all your gists (e.g. https://gist.github.com/rwaldron/1056460) please?

cleverlight commented Nov 13, 2017

@aunyks please could you include a licence in your code because I'd like to reuse it? Alternatively might you consider putting a default licence on all your gists (e.g. https://gist.github.com/rwaldron/1056460) please?

@benrhine

This comment has been minimized.

Show comment
Hide comment
@benrhine

benrhine Dec 15, 2017

I have ported this code to both Java and Groovy. Additionally if you want to change block implementation you can edit the code to choose between a pure Java implementation or the preferred Guava implementation.

Groovy Version:
https://github.com/benrhine/GroovySnakeCoin

Java 8 Version:
https://github.com/benrhine/JavaSnakeCoin

benrhine commented Dec 15, 2017

I have ported this code to both Java and Groovy. Additionally if you want to change block implementation you can edit the code to choose between a pure Java implementation or the preferred Guava implementation.

Groovy Version:
https://github.com/benrhine/GroovySnakeCoin

Java 8 Version:
https://github.com/benrhine/JavaSnakeCoin

@briansb

This comment has been minimized.

Show comment
Hide comment
@briansb

briansb Feb 27, 2018

Thanks @JohnStuartRutledge ! Works great!

briansb commented Feb 27, 2018

Thanks @JohnStuartRutledge ! Works great!

@rajfal

This comment has been minimized.

Show comment
Hide comment
@rajfal

rajfal Feb 28, 2018

Thanks to @aunyks @JohnStuartRutledge
I'm using Python 3.6, however something was not working out and I was getting:
...
Block #5 added to blockchain
Hash: <bound method Block.hash_block of <main.Block object at 0x7efe6c902588>>

It appears that the line:
print('Hash: {}\n'.format(block.hash))

needs to be
print('Hash: {}\n'.format(block.hash()))

in order to obtain:
Block #5 added to blockchain
Hash: 80963e3493ffed59bb9ec6653621328d53dfc81994ae15f2c29b29eb7d0bb1c1

block.hash gives us the method object itself,
whereas, we want to actually call block.hash() instead

rajfal commented Feb 28, 2018

Thanks to @aunyks @JohnStuartRutledge
I'm using Python 3.6, however something was not working out and I was getting:
...
Block #5 added to blockchain
Hash: <bound method Block.hash_block of <main.Block object at 0x7efe6c902588>>

It appears that the line:
print('Hash: {}\n'.format(block.hash))

needs to be
print('Hash: {}\n'.format(block.hash()))

in order to obtain:
Block #5 added to blockchain
Hash: 80963e3493ffed59bb9ec6653621328d53dfc81994ae15f2c29b29eb7d0bb1c1

block.hash gives us the method object itself,
whereas, we want to actually call block.hash() instead

@pchao6

This comment has been minimized.

Show comment
Hide comment
@pchao6

pchao6 commented Feb 28, 2018

great

@koshikraj

This comment has been minimized.

Show comment
Hide comment
@koshikraj

koshikraj Mar 16, 2018

Similar implementation and packaged with tests.
https://github.com/koshikraj/justblockchain

Also, check out the extended implementation with block validation with server interface.
https://github.com/koshikraj/pynaivechain

koshikraj commented Mar 16, 2018

Similar implementation and packaged with tests.
https://github.com/koshikraj/justblockchain

Also, check out the extended implementation with block validation with server interface.
https://github.com/koshikraj/pynaivechain

@mega-byte2600

This comment has been minimized.

Show comment
Hide comment
@mega-byte2600

mega-byte2600 Apr 29, 2018

Thx to all very good stuff:

Block #20 added to blockchain
Hash: 2c4fd089fd70c17ec4eb73b2555cada39f2d8d98b45e74bc3dea99b550a9c6a4 :-)

mega-byte2600 commented Apr 29, 2018

Thx to all very good stuff:

Block #20 added to blockchain
Hash: 2c4fd089fd70c17ec4eb73b2555cada39f2d8d98b45e74bc3dea99b550a9c6a4 :-)

@AjayZinngg

This comment has been minimized.

Show comment
Hide comment
@AjayZinngg

AjayZinngg Jul 18, 2018

@rogel-appdev were you able to resolve the issue? I am facing the same one.

AjayZinngg commented Jul 18, 2018

@rogel-appdev were you able to resolve the issue? I am facing the same one.

@AjayZinngg

This comment has been minimized.

Show comment
Hide comment
@AjayZinngg

AjayZinngg Jul 18, 2018

I found the solution.
Add import statements to your files.

AjayZinngg commented Jul 18, 2018

I found the solution.
Add import statements to your files.

@Gothamv

This comment has been minimized.

Show comment
Hide comment
@Gothamv

Gothamv Aug 1, 2018

Python 3

import hashlib as hasher
import datetime as date

class Block: # Defining what a GitCoin consists of
    def __init__(self,index,timeStamp,data,previousHash):
        self.index = index
        self.timeStamp = timeStamp
        self.data = data
        self.previousHash = previousHash
        self.hash = self.hashBlock()
    
    def hashBlock(self):
        sha = hasher.sha256() # sha256 is a hashing algorithm
        sha.update(str(self.index).encode('utf-8') + str(self.timeStamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previousHash).encode('utf-8'))
        return sha.hexdigest() # returns the combined hash value in Hexadecimals

def createGenesisBlock(): # Pre-Defining a block with index 0 and an arbitrary previous hash 
    return Block(0, date.datetime.now, "Genesis Block", 0)

def createNextBlock(prevBlock): # Creating all the later blocks in the blockchain
    currIndex = prevBlock.index + 1
    currTimeStamp = date.datetime.now()
    currData = "Block" + str(currIndex)
    currHash = prevBlock.hash
    return Block(currIndex, currTimeStamp, currData, currHash)

blockChain = [createGenesisBlock()] # Creating the BlockChain
prevBlock = blockChain[0] # Adding the Genesis block

blocksToCreate = 20 # No. of blocks to be added after the Genesis Block

for i in range(0,blocksToCreate):
    blockToAdd = createNextBlock(prevBlock)
    blockChain.append(blockToAdd)
    prevBlock = blockToAdd
    print("Block %s has been added to the blockchain!" % (blockToAdd.index))
    print("Hash: %s\n" % (blockToAdd.hash))

Gothamv commented Aug 1, 2018

Python 3

import hashlib as hasher
import datetime as date

class Block: # Defining what a GitCoin consists of
    def __init__(self,index,timeStamp,data,previousHash):
        self.index = index
        self.timeStamp = timeStamp
        self.data = data
        self.previousHash = previousHash
        self.hash = self.hashBlock()
    
    def hashBlock(self):
        sha = hasher.sha256() # sha256 is a hashing algorithm
        sha.update(str(self.index).encode('utf-8') + str(self.timeStamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previousHash).encode('utf-8'))
        return sha.hexdigest() # returns the combined hash value in Hexadecimals

def createGenesisBlock(): # Pre-Defining a block with index 0 and an arbitrary previous hash 
    return Block(0, date.datetime.now, "Genesis Block", 0)

def createNextBlock(prevBlock): # Creating all the later blocks in the blockchain
    currIndex = prevBlock.index + 1
    currTimeStamp = date.datetime.now()
    currData = "Block" + str(currIndex)
    currHash = prevBlock.hash
    return Block(currIndex, currTimeStamp, currData, currHash)

blockChain = [createGenesisBlock()] # Creating the BlockChain
prevBlock = blockChain[0] # Adding the Genesis block

blocksToCreate = 20 # No. of blocks to be added after the Genesis Block

for i in range(0,blocksToCreate):
    blockToAdd = createNextBlock(prevBlock)
    blockChain.append(blockToAdd)
    prevBlock = blockToAdd
    print("Block %s has been added to the blockchain!" % (blockToAdd.index))
    print("Hash: %s\n" % (blockToAdd.hash))
@epogrebnyak

This comment has been minimized.

Show comment
Hide comment
@epogrebnyak

epogrebnyak Aug 2, 2018

Can we do better than this? Repeated code is never a good sign.

str(self.index).encode('utf-8') + str(self.timeStamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previousHash).encode('utf-8')

For example:

def encode(x):
     return str(x).encode('utf-8')

def concat(elements: list):
     return ''.join([encode(x) for x in elements])

# the expression above becomes
concat([self.index, self.timeStamp, self.data, self.previousHash])    

Or is this loosing some readbility?

epogrebnyak commented Aug 2, 2018

Can we do better than this? Repeated code is never a good sign.

str(self.index).encode('utf-8') + str(self.timeStamp).encode('utf-8') + str(self.data).encode('utf-8') + str(self.previousHash).encode('utf-8')

For example:

def encode(x):
     return str(x).encode('utf-8')

def concat(elements: list):
     return ''.join([encode(x) for x in elements])

# the expression above becomes
concat([self.index, self.timeStamp, self.data, self.previousHash])    

Or is this loosing some readbility?

@schaefd

This comment has been minimized.

Show comment
Hide comment
@schaefd

schaefd Oct 18, 2018

In case it helps anyone, here is the working Python 3 version I got working that includes a few tweaks like encoding the class attributes to utf-8.

Thanks to OP for the tutorial!

from datetime import datetime
import hashlib as hasher


class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.hash = self.hash_block()

    def __str__(self):
        return 'Block #{}'.format(self.index)

    def hash_block(self):
        sha = hasher.sha256()
        seq = (str(x) for x in (
               self.index, self.timestamp, self.data, self.previous_hash))
        sha.update(''.join(seq).encode('utf-8'))
        return sha.hexdigest()


def make_genesis_block():
    """Make the first block in a block-chain."""
    block = Block(index=0,
                  timestamp=datetime.now(),
                  data="Genesis Block",
                  previous_hash="0")
    return block


def next_block(last_block, data=''):
    """Return next block in a block chain."""
    idx = last_block.index + 1
    block = Block(index=idx,
                  timestamp=datetime.now(),
                  data='{}{}'.format(data, idx),
                  previous_hash=last_block.hash)
    return block


def test_code():
    """Test creating chain of 20 blocks."""
    blockchain = [make_genesis_block()]
    prev_block = blockchain[0]
    for _ in range(0, 20):
        block = next_block(prev_block, data='some data here')
        blockchain.append(block)
        prev_block = block
        print('{} added to blockchain'.format(block))
        print('Hash: {}\n'.format(block.hash))


# run the test code
test_code()

Thanks OP! And to JohnStuartRutledge. This worked for me.

schaefd commented Oct 18, 2018

In case it helps anyone, here is the working Python 3 version I got working that includes a few tweaks like encoding the class attributes to utf-8.

Thanks to OP for the tutorial!

from datetime import datetime
import hashlib as hasher


class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.hash = self.hash_block()

    def __str__(self):
        return 'Block #{}'.format(self.index)

    def hash_block(self):
        sha = hasher.sha256()
        seq = (str(x) for x in (
               self.index, self.timestamp, self.data, self.previous_hash))
        sha.update(''.join(seq).encode('utf-8'))
        return sha.hexdigest()


def make_genesis_block():
    """Make the first block in a block-chain."""
    block = Block(index=0,
                  timestamp=datetime.now(),
                  data="Genesis Block",
                  previous_hash="0")
    return block


def next_block(last_block, data=''):
    """Return next block in a block chain."""
    idx = last_block.index + 1
    block = Block(index=idx,
                  timestamp=datetime.now(),
                  data='{}{}'.format(data, idx),
                  previous_hash=last_block.hash)
    return block


def test_code():
    """Test creating chain of 20 blocks."""
    blockchain = [make_genesis_block()]
    prev_block = blockchain[0]
    for _ in range(0, 20):
        block = next_block(prev_block, data='some data here')
        blockchain.append(block)
        prev_block = block
        print('{} added to blockchain'.format(block))
        print('Hash: {}\n'.format(block.hash))


# run the test code
test_code()

Thanks OP! And to JohnStuartRutledge. This worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment