Skip to content

Instantly share code, notes, and snippets.

@ljlabs
Last active May 11, 2018 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljlabs/529e943688e9dfeb6c9f63d10e5f8f27 to your computer and use it in GitHub Desktop.
Save ljlabs/529e943688e9dfeb6c9f63d10e5f8f27 to your computer and use it in GitHub Desktop.
tangle pow explanation
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)
@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
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
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
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