-
-
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) |
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
great
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
Thx to all very good stuff:
Block #20 added to blockchain
Hash: 2c4fd089fd70c17ec4eb73b2555cada39f2d8d98b45e74bc3dea99b550a9c6a4 :-)
@rogel-appdev were you able to resolve the issue? I am facing the same one.
I found the solution.
Add import statements to your files.
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))
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?
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.
Uhh how would I create a wallet for this file
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:
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 !
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}×tamp={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()
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}×tamp={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!
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
Thanks @JohnStuartRutledge ! Works great!