-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
executable file
·209 lines (167 loc) · 5.86 KB
/
app.py
File metadata and controls
executable file
·209 lines (167 loc) · 5.86 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
from flask import jsonify, request, Flask, render_template
from myblockchain import BlockChain
from concurrent.futures import ThreadPoolExecutor
from utils import build_sig, get_pk_sk_map, hash_256, build_simple_vin
app = Flask(__name__)
@app.route("/", methods=["POST", "GET"])
def home():
if request.method == "POST":
address = request.form.get("address")
in_logs, out_logs = blockchain.get_addr_in_out_logs(address)
return render_template(
"index.html", out_logs=out_logs, in_logs=in_logs, address=address
)
if request.method == "GET":
return render_template("index.html")
@app.route("/utxo/find", methods=["POST"])
def get_utxo():
address = request.form.get("address")
utxo_logs, balance = blockchain.get_utxo_balance_out_logs(address)
return render_template(
"index.html", utxo_logs=utxo_logs, utxo_balance=balance, utxo_addr=address
)
@app.route("/utxo", methods=["GET"])
def get_all_utxo():
return jsonify(blockchain.UTXO), 200
@app.route("/addr/<address>", methods=["GET"])
def address_info(address):
pk_sk_map = get_pk_sk_map()
if address in pk_sk_map:
pk_hash = address
pk, sk = pk_sk_map.get(address)
else:
pk_hash = hash_256(address)
pk, sk = pk_sk_map.get(pk_hash)
balance, utxo_logs = blockchain.get_utxo_balance_out_logs(address)
in_logs, out_logs = blockchain.get_addr_in_out_logs(address)
data = {
"pk_hash": pk_hash,
"pk": pk,
"sk": sk,
"balance": balance,
"utxo_logs": utxo_logs,
"out_logs": out_logs,
"in_logs": in_logs,
}
return render_template("addr.html", data=data)
@app.route("/gen_sig", methods=["POST"])
def gen_sig():
data = request.form
sk, pk, txid, vout = data["sk"], data["pk"], data["txid"], int(data["vout"])
script_type = blockchain.UTXO[txid][vout]["script_type"]
if script_type == "P2PK":
pk = ""
to_sig_data = build_simple_vin(txid, vout)
sig = build_sig(to_sig_data, [sk], pk)
return render_template("index.html", sig=sig, txid=txid, vout=vout)
@app.route("/mine", methods=["GET"])
def mine():
"""
建立新区块
:return:
"""
# 挖矿获得一个数字货币奖励,将奖励的交易记录添加到账本中,其他的交易记录通过new_transaction接口添加
block = blockchain.new_block()
response = {
"message": "新区块建立",
"index": block["index"],
"transactions": block["transactions"],
"proof": block["proof"],
"previous_hash": block["previous_hash"],
}
return jsonify(response), 200
@app.route("/trans/sync_trans", methods=["POST"])
def sync_one_trans():
trans = request.get_json()
blockchain.add_trans_and_utxo(trans)
resp = {"message": f"添加 {trans['txid']} 成功"}
return jsonify(resp)
@app.route("/trans/new", methods=["POST"])
def new_transaction():
"""
将新的交易添加到最新的区块中
:return:
"""
values = request.get_json()
required = ["txid_in_list", "out_list"]
if not all(k in values for k in required):
return "缺失必要字段", 400
blockchain.new_transaction(values["txid_in_list"], values["out_list"])
response = {"message": f"交易账本被添加到新的区块 {len(blockchain.chain)} 中"}
return jsonify(response), 200
@app.route("/trans/form", methods=["POST"])
def new_transaction_by_form():
"""
将新的交易添加到最新的区块中
:return:
"""
data = request.form
txid_in_list = [(data["txid"], int(data["vout"]), data["sig"])]
out_list = [(data["addr"], float(data["value"]), "P2PKH")]
blockchain.new_transaction(txid_in_list, out_list)
response = {"message": f"交易账本被添加到新的区块中{len(blockchain.chain)}"}
return jsonify(response), 200
@app.route("/chain", methods=["GET"])
def full_chain():
"""
获得完整的区块链
:return: 整份区块链
"""
response = {
"length": len(blockchain.chain),
"chain": blockchain.chain,
}
return jsonify(response), 200
@app.route("/chain/last", methods=["GET"])
def last_block():
"""
获得完整的区块链
:return: 整份区块链
"""
response = {
"chain": blockchain.last_block,
}
return jsonify(response), 200
@app.route("/nodes/register", methods=["POST"])
def register_nodes():
values = request.get_json()
nodes = values.get("nodes")
if nodes is None:
return "Error:提供有效节点列表", 400
for node in nodes:
blockchain.register_node(node)
response = {
"message": "新节点加入区块链网络",
"total_nodes": list(blockchain.nodes),
}
return jsonify(response), 200
@app.route("/nodes", methods=["GET"])
def nodes():
response = {
"nodes": list(blockchain.nodes),
}
return jsonify(response), 200
@app.route("/node/resolve", methods=["GET"])
def consensus():
replaced = blockchain.resolve_conflicts()
if replaced:
response = {"message": "本节点区块链被替换", "new_cha n": blockchain.chain}
else:
response = {"message": "本节点区块链是权威的(区块链网络中最长的)", "chain": blockchain.chain}
return jsonify(response), 200
if __name__ == "__main__":
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-p", "--port", default=5000, type=int, help="服务启动时对应的端口")
args = parser.parse_args()
port = args.port
host = f'{"127.0.0.1"}:{port}'
blockchain = BlockChain(host)
blockchain.reload_by_file()
blockchain.init_nodes(host)
with ThreadPoolExecutor(
max_workers=3,
) as executor:
executor.submit(blockchain.file_sync)
executor.submit(blockchain.timing_sync)
executor.submit(app.run, host="localhost", port=port)