Last active
May 11, 2018 12:24
-
-
Save ljlabs/529e943688e9dfeb6c9f63d10e5f8f27 to your computer and use it in GitHub Desktop.
tangle pow explanation
This file contains 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 | |
import json | |
from textwrap import dedent | |
from time import time | |
from uuid import uuid4 | |
from tangle import Tangle | |
from urllib.parse import urlparse | |
import requests | |
from flask import Flask, jsonify, request | |
# Instantiate our Node | |
app = Flask(__name__) | |
# Instantiate the Blockchain | |
tangle = Tangle() | |
@app.route('/transactions/new', methods=['POST']) | |
def new_transaction(): | |
pass # make a new transaction on the network | |
@app.route('/tangle', methods=['GET']) | |
def full_chain(): | |
pass # returns the current tangle | |
# Consensus | |
@app.route('/peers/register', methods=['POST']) | |
def register_nodes(): | |
pass # add new peers to the network | |
@app.route('/peers/resolve', methods=['GET']) | |
def consensus(): | |
pass # check for other maybe newer tangles on the network | |
@app.route('/peers', methods=['GET']) | |
def list_peers(): | |
pass # return a list of peers | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0', port=5001) |
This file contains 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
@app.route('/transactions/new', methods=['POST']) | |
def new_transaction(): | |
# update tangle | |
tangle.resolve_conflicts() | |
# begin transaction | |
values = request.get_json() | |
# Check that the required fields are in the POST'ed data | |
required = ['sender', 'recipient', 'amount'] | |
if not all(k in values for k in required): | |
return 'Missing values', 400 | |
# Create a new Transaction | |
index = tangle.send_transaction(values) | |
response = {'message': 'Transaction will be added to Block ' + str(index)} | |
# tell peers to update tangle | |
for peer in tangle.peers: | |
requests.get("http://"+str(peer) + "/peers/resolve") | |
return jsonify(response), 201 | |
@app.route('/tangle', methods=['GET']) | |
def full_chain(): | |
response = { | |
'tangle': tangle.nodes, | |
'length': len(tangle.nodes), | |
} | |
return jsonify(response), 200 |
This file contains 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
RequiredProofs = 2 # the number of times a transaction needs to be processed | |
# befor it is seen as valid | |
numberOfValidationNodesNeeded = 2 # the number of nodes needed to connect to when | |
# addeing a new node to the network for the purpose | |
# of validating them when making a transaction |
This file contains 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
class Tangle(object): | |
def __init__(self): | |
self.nodes = [] | |
self.peers = set() | |
for i in range(prop.numberOfValidationNodesNeeded): | |
# Create the genesis block | |
self.nodes.append(self.createNode(None, [], len(self.nodes), validity = prop.RequiredProofs)) | |
@staticmethod | |
def valid_proof(last_proof, last_hash, proof): | |
# ensures that the node has the correct number of zeros | |
guess = (str(last_proof) + str(last_hash) + str(proof)).encode() | |
guess_hash = hashlib.sha256(guess).hexdigest() | |
return guess_hash[:4] == "0000" | |
def proof_of_work(self, last_proof, last_hash): | |
# computes the proof of work | |
proof = 0 | |
while self.valid_proof(last_proof, last_hash, proof) is False: | |
proof += 1 | |
return proof | |
@staticmethod | |
def hash(node): | |
# make a hash of the block | |
# We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes | |
node_string = json.dumps(node, sort_keys=True).encode() | |
return hashlib.sha256(node_string).hexdigest() | |
def validate_node(self, node): | |
if self.nodes[node['index']]['validity'] < prop.RequiredProofs: | |
last_proof = self.nodes[node['index']]['proof'] # this nodes proof | |
last_hash = "" | |
for prevHash in self.nodes[node['index']]['previous_hashs']: | |
last_hash += prevHash # the hashes of the nodes this node connects | |
self.nodes[node['index']]['proof'] = self.proof_of_work(last_proof, last_hash) | |
self.nodes[node['index']]['validity'] += 1 | |
def createNode(self, data, prevNodes, newIndex, validity=0):# these prevNodes are the indexes in the dag that points to the previous nodes | |
prevHashes = [] | |
''' | |
may need to update every node that points to this when sending transaction | |
''' | |
for i in prevNodes: | |
prevHashes.append(self.hash(self.nodes[i])) | |
# now we tell the nodes that we are pointing to that we are poiinting to them | |
self.nodes[i]['next_nodes'].append(newIndex) | |
Node = { | |
'index': newIndex, | |
'timestamp': time(), | |
'data': data, | |
'proof': 0, | |
'previous_hashs': prevHashes, # hashes of the nodes we are connecting to | |
'previous_nodes': prevNodes, # indexes of the nodes we are connecting to | |
'next_nodes': [], # indexes of future nodes that will connect to us | |
'validity': validity, | |
} | |
return Node | |
def send_transaction(self, data): | |
# find 2 nodes in the network that are un proven | |
nodesToattach = [] | |
nodesIndexes = [] | |
newIndex = len(self.nodes) | |
worstCaseScinario = [] | |
worstCaseScinarioindexes = [] | |
''' | |
this function should be changed to search randomly | |
''' | |
for i in range(len(self.nodes)-1, -1, -1): | |
node=self.nodes[i] | |
if node['validity'] < prop.RequiredProofs: | |
nodesToattach.append(node) | |
nodesIndexes.append(node['index']) | |
else: | |
if worstCaseScinario == [] or len(worstCaseScinario) < prop.numberOfValidationNodesNeeded: | |
worstCaseScinario.append(node) | |
worstCaseScinarioindexes.append(node['index']) | |
if len(nodesToattach) == prop.numberOfValidationNodesNeeded: | |
break | |
# if there are not enough un varified transactions then use verified transactions | |
while len(nodesToattach) < prop.numberOfValidationNodesNeeded: | |
nodesToattach.append(worstCaseScinario.pop()) | |
nodesIndexes.append(worstCaseScinarioindexes.pop()) | |
# process nodes to attatch | |
for node in nodesToattach: | |
self.validate_node(node) | |
# now that those nodes are proven | |
# we can now attatch our node to the dag | |
self.nodes.append(self.createNode(data, nodesIndexes, newIndex)) | |
return newIndex |
This file contains 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 properties as prop | |
import json | |
from time import time | |
import hashlib | |
import requests | |
from urllib.parse import urlparse | |
class Tangle(object): | |
def __init__(self): | |
pass # initialize the network | |
@staticmethod | |
def valid_proof(self): | |
pass # used to make sure that the pow was correct | |
def proof_of_work(self): | |
pass # calculate the proof of work | |
@staticmethod | |
def hash(): | |
pass # compute the hash | |
def createNode(self): | |
pass # create a new node | |
def send_transaction(self, data): | |
pass # send a transaction | |
########################################################################### | |
# this is the consensus algorithm | |
########################################################################### | |
def valid_tangle(self, tangle): | |
pass # we will use this to ensure that the tangles we get from peers are correct | |
def register_peer(self, address): | |
pass # we will use this a add new peers to our p2p network | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment