Compare commits
16
Commits
healthcheck
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7247aa966e | ||
|
|
269658d9d8 | ||
|
|
a458dc64ee | ||
|
|
6f9191fd38 | ||
|
|
d5dfe96b81 | ||
|
|
5e8a2d80c4 | ||
|
|
b44c72f30e | ||
|
|
e7599ce757 | ||
|
|
9258985a86 | ||
|
|
ac9d8a108b | ||
|
|
ec9f0e1b36 | ||
|
|
f55195618f | ||
|
|
bec6a801bf | ||
|
|
330e709c9a | ||
|
|
fe8edb6a00 | ||
|
|
9de5492201 |
@@ -0,0 +1,5 @@
|
||||
.git
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
README.md
|
||||
test
|
||||
@@ -0,0 +1,9 @@
|
||||
start:
|
||||
./app.py -p 8000
|
||||
update:
|
||||
pipenv update
|
||||
pipenv lock -r > requirements.txt
|
||||
build: update
|
||||
docker-compose build node
|
||||
push: build
|
||||
docker-compose push node
|
||||
@@ -0,0 +1,13 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
requests = "==2.27.1"
|
||||
Flask = "==2.0.2"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.10"
|
||||
Generated
+146
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "3ee84615107062eb60ff41cf23471c62c89af654722d8425b186d1e4bab2afd8"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.10"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
|
||||
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
|
||||
],
|
||||
"version": "==2021.10.8"
|
||||
},
|
||||
"charset-normalizer": {
|
||||
"hashes": [
|
||||
"sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
|
||||
"sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
|
||||
],
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==2.0.12"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1",
|
||||
"sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.0.4"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2",
|
||||
"sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.2"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
|
||||
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
|
||||
],
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==3.3"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:29285842166554469a56d427addc0843914172343784cb909695fdbe90a3e129",
|
||||
"sha256:d848fcb8bc7d507c4546b448574e8a44fc4ea2ba84ebf8d783290d53e81992f5"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8",
|
||||
"sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.3"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3",
|
||||
"sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8",
|
||||
"sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759",
|
||||
"sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed",
|
||||
"sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989",
|
||||
"sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3",
|
||||
"sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a",
|
||||
"sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c",
|
||||
"sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c",
|
||||
"sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8",
|
||||
"sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454",
|
||||
"sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad",
|
||||
"sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d",
|
||||
"sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635",
|
||||
"sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61",
|
||||
"sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea",
|
||||
"sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49",
|
||||
"sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce",
|
||||
"sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e",
|
||||
"sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f",
|
||||
"sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f",
|
||||
"sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f",
|
||||
"sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7",
|
||||
"sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a",
|
||||
"sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7",
|
||||
"sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076",
|
||||
"sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb",
|
||||
"sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7",
|
||||
"sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7",
|
||||
"sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c",
|
||||
"sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26",
|
||||
"sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c",
|
||||
"sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8",
|
||||
"sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448",
|
||||
"sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956",
|
||||
"sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05",
|
||||
"sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1",
|
||||
"sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357",
|
||||
"sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea",
|
||||
"sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.0"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61",
|
||||
"sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.27.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed",
|
||||
"sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
|
||||
"version": "==1.26.8"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8",
|
||||
"sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.3"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
from time import time
|
||||
from flask import Flask, request
|
||||
#!/usr/bin/env python
|
||||
"""Flask server to serve the block API."""
|
||||
|
||||
import json
|
||||
from uuid import uuid4
|
||||
from blockchain import Blockchain, Transaction, Block
|
||||
from time import time
|
||||
import argparse
|
||||
from uuid import uuid4
|
||||
from flask import Flask, request
|
||||
from blockchain import Blockchain, Transaction, Block
|
||||
|
||||
parser = argparse.ArgumentParser(description="A blockchain simulation")
|
||||
parser.add_argument("-p", "--port", type=int, help="Port number", default=80)
|
||||
@@ -13,18 +16,19 @@ port = args.port
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
node_identifier = str(uuid4()).replace("-", "")
|
||||
NODE_IDENTIFIER = str(uuid4()).replace("-", "")
|
||||
|
||||
blockchain = Blockchain()
|
||||
|
||||
|
||||
@app.route("/mine", methods=["GET"])
|
||||
def mine():
|
||||
"""Mine Samycoin."""
|
||||
last_block = blockchain.blocks[-1]
|
||||
last_proof = last_block.proof
|
||||
proof = blockchain.proof_of_work(last_proof)
|
||||
|
||||
transaction = Transaction("Network", node_identifier, 50)
|
||||
transaction = Transaction("Network", NODE_IDENTIFIER, 50)
|
||||
blockchain.new_transaction(transaction)
|
||||
block = Block(
|
||||
len(blockchain.blocks) + 1,
|
||||
@@ -40,6 +44,7 @@ def mine():
|
||||
|
||||
@app.route("/transactions/new", methods=["POST"])
|
||||
def new_transaction():
|
||||
"""Submit a new transaction."""
|
||||
values = request.get_json()
|
||||
transaction = Transaction(values["sender"], values["recipient"], values["amount"])
|
||||
blockchain.new_transaction(transaction)
|
||||
@@ -49,27 +54,29 @@ def new_transaction():
|
||||
|
||||
@app.route("/chain", methods=["GET"])
|
||||
def chain():
|
||||
"""Display the block chain."""
|
||||
return json.dumps([b.__dict__ for b in blockchain.blocks])
|
||||
|
||||
|
||||
@app.route("/nodes", methods=["GET"])
|
||||
def nodes():
|
||||
"""List known nodes."""
|
||||
return json.dumps(list(blockchain.nodes))
|
||||
|
||||
|
||||
@app.route("/register", methods=["POST"])
|
||||
def register_nodes():
|
||||
values = request.get_json()
|
||||
nodes = values["nodes"]
|
||||
|
||||
for node in nodes:
|
||||
"""Register a new node."""
|
||||
json_values = request.get_json()
|
||||
for node in json_values["nodes"]:
|
||||
blockchain.register_node(node)
|
||||
|
||||
return "New node has been added\n"
|
||||
|
||||
|
||||
@app.route("/resolve", methods=["GET"])
|
||||
def consensus():
|
||||
def resolve():
|
||||
"""Resolve the blockchain."""
|
||||
replaced = blockchain.resolve_conflicts()
|
||||
|
||||
if replaced:
|
||||
|
||||
+17
-1
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import hashlib
|
||||
from time import time
|
||||
import json
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
import requests
|
||||
|
||||
DIFFICULTY = 4
|
||||
|
||||
|
||||
class Block:
|
||||
"""Block of the blockkchain."""
|
||||
def __init__(self, index, timestamp, transactions, previous_hash, proof):
|
||||
self.index = index
|
||||
self.timestamp = timestamp
|
||||
@@ -17,6 +20,7 @@ class Block:
|
||||
self.hash = self.hash()
|
||||
|
||||
def hash(self):
|
||||
"""Hash the block using sha256."""
|
||||
data = self.__dict__
|
||||
data["transactions"] = [t.__dict__ for t in self.transactions]
|
||||
block_string = json.dumps(data, sort_keys=True).encode()
|
||||
@@ -27,6 +31,7 @@ class Block:
|
||||
|
||||
|
||||
class Transaction:
|
||||
"""Transaction class."""
|
||||
def __init__(self, sender, recipient, amount):
|
||||
self.sender = sender
|
||||
self.recipient = recipient
|
||||
@@ -37,6 +42,7 @@ class Transaction:
|
||||
|
||||
|
||||
class Blockchain:
|
||||
"""Blockchain class."""
|
||||
def __init__(self):
|
||||
self.blocks = []
|
||||
self.blocks.append(self.create_first_block())
|
||||
@@ -44,20 +50,25 @@ class Blockchain:
|
||||
self.nodes = set()
|
||||
|
||||
def register_node(self, address):
|
||||
"""Register a new node."""
|
||||
parsed_url = urlparse(address).netloc
|
||||
self.nodes.add(parsed_url)
|
||||
|
||||
def create_first_block(self):
|
||||
"""create the initial block."""
|
||||
return Block(1, time(), [], 1, 100)
|
||||
|
||||
def new_transaction(self, transaction):
|
||||
"""Add a new transaction."""
|
||||
self.transactions.append(transaction)
|
||||
|
||||
def new_block(self, block):
|
||||
"""Add a new block."""
|
||||
self.transactions = []
|
||||
self.blocks.append(block)
|
||||
|
||||
def proof_of_work(self, last_proof):
|
||||
"""Computes the proof."""
|
||||
proof = 0
|
||||
while not self.valid_proof(proof, last_proof):
|
||||
proof += 1
|
||||
@@ -65,11 +76,13 @@ class Blockchain:
|
||||
|
||||
@staticmethod
|
||||
def valid_proof(proof, last_proof):
|
||||
"""Tests proof."""
|
||||
guess = f"{last_proof}{proof}".encode()
|
||||
guess_hash = hashlib.sha256(guess).hexdigest()
|
||||
return guess_hash[:DIFFICULTY] == "0" * DIFFICULTY
|
||||
|
||||
def valid_chain(self, chain):
|
||||
"""Tests the validity of a chain."""
|
||||
last_block = chain[0]
|
||||
current_index = 1
|
||||
|
||||
@@ -88,6 +101,7 @@ class Blockchain:
|
||||
return True
|
||||
|
||||
def json_to_transactions(self, transactions_json):
|
||||
"""Converts json to a list of transactions."""
|
||||
transactions = [
|
||||
Transaction(
|
||||
transaction["sender"],
|
||||
@@ -100,6 +114,7 @@ class Blockchain:
|
||||
return transactions
|
||||
|
||||
def json_to_chain(self, chain_json):
|
||||
"""Convert json to a chain."""
|
||||
chain = [
|
||||
Block(
|
||||
block["index"],
|
||||
@@ -114,6 +129,7 @@ class Blockchain:
|
||||
return chain
|
||||
|
||||
def resolve_conflicts(self):
|
||||
"""Resolve conflicts using the consensus algorithm."""
|
||||
neighbours = self.nodes
|
||||
new_chain = None
|
||||
max_lengh = len(self.blocks)
|
||||
|
||||
Reference in New Issue
Block a user