Skip to content

Instantly share code, notes, and snippets.

@aunyks
Last active April 29, 2024 22:52
Show Gist options
  • Save aunyks/8f2c2fd51cc17f342737917e1c2582e2 to your computer and use it in GitHub Desktop.
Save aunyks/8f2c2fd51cc17f342737917e1c2582e2 to your computer and use it in GitHub Desktop.
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)
@briansb
Copy link

briansb commented Feb 27, 2018

Thanks @JohnStuartRutledge ! Works great!

@rajfal
Copy link

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

@aishoot
Copy link

aishoot commented Feb 28, 2018

great

@koshikraj
Copy link

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
Copy link

Thx to all very good stuff:

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

@AjayZinngg
Copy link

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

@AjayZinngg
Copy link

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

@Gothamv
Copy link

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
Copy link

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
Copy link

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.

@nobody5050
Copy link

Uhh how would I create a wallet for this file

@MALLI7622
Copy link

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'))

:Thank you +1:

@Anas-Aymen
Copy link

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'))

You're right !

@suncle1993
Copy link

worked python3 version:

import hashlib
import time


class Block:
    def __init__(self, index: int, timestamp: int, data: str, previous_hash):
        """
        :param index: block index
        :param timestamp: millisecond
        :param data: block real data
        :param previous_hash: previous block 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 = hashlib.sha256()
        seq = [
            str(x) for x in [self.index, self.timestamp, self.data, self.previous_hash]
        ]
        sha.update("".join(seq).encode("utf8"))
        return sha.hexdigest()

    def __str__(self):
        return f"Block:index={self.index}&timestamp={self.timestamp}&data={self.data}&hash={self.hash}"


def get_cur_millisecond():
    return int(round(time.time() * 1000))


def create_genesis_block():
    return Block(0, get_cur_millisecond(), "snake coin genesis block", "0")


def next_block(previous_block: Block):
    index = previous_block.index + 1
    return Block(
        index=index,
        timestamp=get_cur_millisecond(),
        data=f"this is block #{index}",
        previous_hash=previous_block.hash,
    )


def make_test_block_chain():
    block_chain = [create_genesis_block()]
    previous_block = block_chain[0]
    for _ in range(20):
        block = next_block(previous_block)
        block_chain.append(block)
        previous_block = block
        # broadcast: tell everyone about it!
        print(f"Block #{block.index} has been added to the blockchain! detail: {block}")
        time.sleep(1)


if __name__ == "__main__":
    make_test_block_chain()

@Chike-O-IT
Copy link

worked python3 version:

import hashlib
import time


class Block:
    def __init__(self, index: int, timestamp: int, data: str, previous_hash):
        """
        :param index: block index
        :param timestamp: millisecond
        :param data: block real data
        :param previous_hash: previous block 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 = hashlib.sha256()
        seq = [
            str(x) for x in [self.index, self.timestamp, self.data, self.previous_hash]
        ]
        sha.update("".join(seq).encode("utf8"))
        return sha.hexdigest()

    def __str__(self):
        return f"Block:index={self.index}&timestamp={self.timestamp}&data={self.data}&hash={self.hash}"


def get_cur_millisecond():
    return int(round(time.time() * 1000))


def create_genesis_block():
    return Block(0, get_cur_millisecond(), "snake coin genesis block", "0")


def next_block(previous_block: Block):
    index = previous_block.index + 1
    return Block(
        index=index,
        timestamp=get_cur_millisecond(),
        data=f"this is block #{index}",
        previous_hash=previous_block.hash,
    )


def make_test_block_chain():
    block_chain = [create_genesis_block()]
    previous_block = block_chain[0]
    for _ in range(20):
        block = next_block(previous_block)
        block_chain.append(block)
        previous_block = block
        # broadcast: tell everyone about it!
        print(f"Block #{block.index} has been added to the blockchain! detail: {block}")
        time.sleep(1)


if __name__ == "__main__":
    make_test_block_chain()

Tested this out and it worked great! Thanks!

@goesbyabhi
Copy link

import hashlib as hasher
import datetime as date

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)).encode())   #changed line
        return sha.hexdigest()

def create_genesis_block():
    return Block(0, date.datetime.now(), "Genesis Block", 0)

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)

blockchain = [create_genesis_block()]
previous_block = blockchain[0]

num_of_blocks_to_add = 20

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
    print ("Block #{} has been added to the blockchain!".format(block_to_add.index))
    print ("Hash: {}\n".format(block_to_add.hash))    

For anyone in Python 3, just changed the line 14. Tested and it worked

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