-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblockchain.py
More file actions
121 lines (101 loc) · 3.29 KB
/
Copy pathblockchain.py
File metadata and controls
121 lines (101 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import hashlib
import json
import requests
from time import time
from textwrap import dedent
from uuid import uuid4
from flask import Flask, jsonify, request
class Blockchain(object):
def __init__(self):
self.current_transactions = []
self.chain = []
self.new_block(previous_hash=1, proof=100)
def proof_of_work(self, last_proof):
proof = 0
while self.valid_proof(last_proof, proof) is False:
proof += 1
return proof
@staticmethod
def valid_proof(last_proof, proof):
guess = f'{last_proof}{proof}'.encode()
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == "1111"
@staticmethod
def hash(block):
# Check dictionary is ordered
block_str = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_str).hexdigest()
@property
def last_block(self):
return self.chain[-1]
def new_block(self, proof, previous_hash=None):
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
self.current_transactions = []
self.chain.append(block)
return block
def new_transaction(self, sender, recipient, amount):
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
# Instantiate node
app = Flask(__name__)
# Generate a unique identifier for this node
node_identifier = str(uuid4()).replace('-', '')
# Instantiate the Blockchain
blockchain = Blockchain()
# API methods:
# POST: Create new transaction
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
values = request.get_json()
# Check required fields
required = ['sender', 'recipient', 'amount']
if not all(k in values for k in required):
return 'Missing values', 400
# Create new Transaction
index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
response = {'message': f'Transaction will be added to block {index}'}
return jsonify(response), 201
# GET: display full chain
@app.route('/chain', methods=['GET'])
def full_chain():
response = {
'chain': blockchain.chain,
'length': len(blockchain.chain),
}
return jsonify(response), 200
# GET: mine new block
@app.route('/mine', methods=['GET'])
def mine():
# POW algorithm
last_block = blockchain.last_block
last_proof = last_block['proof']
proof = blockchain.proof_of_work(last_proof)
blockchain.new_transaction(
sender="0",
recipient=node_identifier,
amount=1,
)
# Add the new block to the chain
previous_hash = blockchain.hash(last_block)
block = blockchain.new_block(proof, previous_hash)
response = {
'message': "New Block",
'index': block['index'],
'transactions': block['transactions'],
'proof': block['proof'],
'previous_hash': block['previous_hash'],
}
return jsonify(response), 200
# Run app
if __name__ == '__main__':
app.run(host='127.0.0.1', port=4444)