-
-
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) |
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
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.
@Boom16 See @joeblankenship1 's comment under yours for help
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
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`);
}
I think that index should be autoincremented to avoid case there are blocks with the same index.
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.
@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?
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.
@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
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()
@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?
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
Thanks @JohnStuartRutledge ! Works great!
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
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'))