-
Notifications
You must be signed in to change notification settings - Fork 0
/
blockchain.py
117 lines (92 loc) · 3.56 KB
/
blockchain.py
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
from hashlib import sha256
import time
import json
from types import MethodDescriptorType
from flask import Flask, app, request
import requests
class Block:
def __init__(self, index, transactions, timestamp, previous_hash):
self.index = index
self.transactions = transactions
self.timestamp = timestamp
self.previous_hash = previous_hash
def compute_hash(self):
block_string = json.dumps(self.__dict__, sort_keys = True)
return sha256(block_string.encode()).hexdigest()
class Blockchain:
difficulty = 2
def __init__(self):
self.unconfirmed_transactions = []
self.chain = []
self.create_genesis_block()
def create_genesis_block(self):
genesis_block = Block(0, [], time.time(), '0'*64)
genesis_block.hash = genesis_block.compute_hash()
self.chain.append(genesis_block)
@property
def last_block(self):
return self.chain[-1]
def print_block(self, n):
if (len(self.chain) < n):
return
else:
block = self.chain[n]
return ' Index {}\n Transactions {}\n Timestamp: {}\n PreviousHash: {}\n'.format(block.index, block.transactions, block.timestamp, block.previous_hash)
def proof_of_work(self, block):
block.nonce = 0
compute_hash = block.compute_hash()
while not compute_hash.startswith('0'*Blockchain.difficulty):
block.nonce += 1
compute_hash = block.compute_hash()
print(compute_hash)
return compute_hash
def add_block(self, block, proof):
previous_hash = self.last_block.hash
if (previous_hash != block.previous_hash):
return False
if not self.is_valid_proof(block, proof):
return False
block.hash = proof
self.chain.append(block)
return True
def is_valid_proof(self, block, block_hash):
return (block_hash.startswith('0' * Blockchain.difficulty) and block_hash == block.compute_hash())
def new_transaction(self, transaction):
self.unconfirmed_transactions.append(transaction)
def mine(self):
if not self.unconfirmed_transactions:
return False
last_block = self.last_block
new_block = Block(index = last_block.index + 1, transactions = self.unconfirmed_transactions, timestamp = time.time(), previous_hash = last_block.hash)
proof = self.proof_of_work(new_block)
self.add_block(new_block, proof)
self.unconfirmed_transactions = []
return new_block.index
# -- TERCERA PARTE --
app = Flask (__name__)
blockchain = Blockchain()
@app.route("/newtransaction", methods = ["POST"])
def new_transaction():
tx_data = request.get_json()
require_fields = ["author", "content"]
for field in require_fields:
if not tx_data.get(field):
return "datos de transacción inválidos", 404
tx_data["timestamp"] = time.time()
blockchain.new_transaction(tx_data)
return "Éxito", 201
@app.route("/mine", methods = ["GET"])
def mine_unconfirmed_transactions():
result = blockchain.mine()
if not result:
return "Nothing to mine"
return "Blocks {} is mined".format(result)
@app.route("/chain", methods=["GET"])
def get_chain():
chain_data = []
for block in blockchain.chain:
chain_data.append(block.__dict__)
return json.dumps({"length": len(chain_data), "chain": chain_data})
@app.route("/pending_tx", methods = ["POST"])
def get_pending_tx():
return json.dumps(blockchain.unconfirmed_transactions)