Created
January 7, 2019 02:46
-
-
Save alairock/e4ba6a20b796611f1638796952fd005e to your computer and use it in GitHub Desktop.
Simple Python Decentralized Ledger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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