Skip to content

Instantly share code, notes, and snippets.

@alairock
Created January 7, 2019 02:46
Show Gist options
  • Save alairock/e4ba6a20b796611f1638796952fd005e to your computer and use it in GitHub Desktop.
Save alairock/e4ba6a20b796611f1638796952fd005e to your computer and use it in GitHub Desktop.
Simple Python Decentralized Ledger
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 hash_block(self):
sha = hasher.sha256()
sha.update(self.attributes())
return sha.hexdigest()
def attributes(self):
return str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)
#!/usr/bin/env python
import datetime as date
import json
import requests
import sys
from flask import Flask
from flask import request
from block import Block
node = Flask(__name__)
# Define what a Snakecoin block is.
def create_genesis_block():
return Block(0, date.datetime.now(), {
"proof-of-work": 9,
"transactions": None,
}, "0")
miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"
blockchain = []
peer_nodes = []
mining = True
# Transaction submit.
transactions = []
@node.route('/transaction', methods=['POST'])
def transaction():
if request.method == 'POST':
_transaction = request.get_json()
transactions.append(_transaction)
print("New transaction")
print("FROM: {}".format(_transaction['from']))
print("TO: {}".format(_transaction['to']))
print("AMOUNT: {}\n".format(_transaction['amount']))
return "Transaction submission successful\n"
@node.route('/blocks', methods=['GET'])
def get_blocks():
ret = []
for block in consensus():
ret.append({
"index": str(block.index),
"timestamp": str(block.timestamp),
"data": str(block.data),
"hash": block.hash,
})
return json.dumps(ret)
def consensus():
global blockchain
longest_chain = blockchain
for chain in find_other_chains():
if len(longest_chain) < len(chain):
longest_chain = chain
return update_blockchain(longest_chain)
def update_blockchain(src):
if len(src) <= len(blockchain):
return blockchain
ret = []
for b in src:
ret.append(Block(b['index'], b['timestamp'], b['data'], b['hash']))
return ret
def find_other_chains():
ret = []
for peer in peer_nodes:
response = requests.get('http://%s/blocks' % peer)
if response.status_code == 200:
print("blocks from peer: " + response.content)
ret.append(json.loads(response.content))
return ret
@node.route('/add_peer', methods=['GET'])
def add_peer():
host = request.args['host'] if 'host' in request.args else 'localhost'
port = request.args['port']
peer = host + ':' + port
peer_nodes.append(peer)
print("Peer added: %s" % peer)
return ""
@node.route('/mine', methods=['GET'])
def mine():
last_block = blockchain[len(blockchain) - 1]
last_proof = last_block.data['proof-of-work']
proof = proof_of_work(last_proof)
transactions.append(
{"from": "network", "to": miner_address, "amount": 1}
)
data = {
"proof-of-work": proof,
"transactions": list(transactions)
}
index = last_block.index + 1
timestamp = date.datetime.now()
# Empty transactions list.
transactions[:] = []
# Create a mined block.
block = Block(index, timestamp, data, last_block.hash)
blockchain.append(block)
return json.dumps({
"index": index,
"timestamp": str(timestamp),
"data": data,
"hash": last_block.hash
}) + "\n"
def proof_of_work(last_proof):
incrementor = last_proof + 1
while not (incrementor % 9 == 0 and incrementor % last_proof == 0):
incrementor += 1
return incrementor
def main():
port = 5000
if len(sys.argv) > 1:
port = sys.argv[1]
blockchain.append(create_genesis_block())
node.run(port=port)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment