-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.py
303 lines (255 loc) · 9.48 KB
/
api.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
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
import requests
import json
import time
import pickle
import os
from threading import Thread
from flask import Blueprint,Flask, jsonify, request, render_template
from block import Block
from transaction import Transaction
from transactionIn import TransactionInput
from transactionOut import TransactionOutput
from node import Node
#create node instance
node = Node()
#set the subsection we will add later on to the main script
api = Blueprint('api',__name__)
#app functionality
#register node to the network
@api.route('/registration', methods = ['POST'])
def registration():
ip = request.json.get('ip')
port = str(request.json.get('port'))
id = len(node.ring)
pub = request.json.get('pub')
node.register_node_to_ring(ip,id,port,pub,0)
if (node.peers == id + 1):
for peer in node.ring:
node.announce_ring(peer)
node.announce_chain(peer)
if peer['id'] != node.id:
node.create_transaction(peer['id'],peer['pub'],100)
return jsonify({"status":"Registered"}),200
#learn the ring of the bootstrap node and set the id of the node
@api.route('/learn_ring',methods = ['POST'])
def learn_ring():
load = request.json
node.ring = load['data']
#print('passed')
for peer in node.ring:
if peer['pub'] == node.wallet.public_key:
node.id = peer['id']
return jsonify({'status':'SUCCESS'}),200
#learn the chain of bootstrap node and initialize the local blockchain
@api.route('/learn_chain',methods = ['POST'])
def learn_chain():
node.blockchain.chain = pickle.loads(request.get_data())
return jsonify({'status':"ADDED"})
#send local chain to resolve conflicts
@api.route('/conflict_chain', methods = ['GET'])
def conflict_chain():
return pickle.dumps(node.blockchain)
#validate posted transaction
@api.route('/valid_transaction',methods=['POST'])
def valid_transaction():
#get the transaction
transaction = pickle.loads(request.get_data())
if node.validate_transaction(transaction):
return jsonify({'status':'OK'}), 200
else:
return jsonify({'status':'FAILURE'}), 400
#add valid transaction
@api.route('/add_transaction',methods=['POST'])
def add_transaction():
transaction = pickle.loads(request.get_data())
node.add_transaction_to_block(transaction)
return jsonify({'status':'OK'}), 200
#make sure an incoming block is valid and then insert it in the local node
@api.route('/check_block',methods = ['POST'])
def broadcast_block():
block = pickle.loads(request.get_data())
#make sure the chain is not in danger of being changed during the procedure
node.lock_chain.acquire()
if node.validate_block(block):
#make sure mining is stopped
node.mining_flag = True
with node.lock_temp :
node.blockchain.add_block(block)
node.lock_chain.release()
#clean double transactions
node.check_doubles(block)
#we can start mining again
node.mining_flag = False
return jsonify({'status':"SUCCESS"}), 200
else:
#check the validity of the block
if block.previousHash == node.blockchain.chain[-1].hash:
node.lock_chain.release()
return jsonify({'status':'FAILED VALIDATION'}), 400
else:
#there has been some confilct that needs fixing
if node.resolve_conflicts(block):
#if resolved stop minining and add block to the chain
node.mining_flag = True
with node.lock_temp:
node.blockchain.add_block(block)
node.lock_chain.release()
#check double transactions
node.check_doubles(block)
#continue mining
node.mining_flag = False
else:
node.lock_chain.release()
return jsonify({'status':'REJECTED'}), 400
return jsonify({'status':"SUCCESS"}), 200
#show balance of the client in the local node
@api.route('/money',methods = ['GET'])
def money():
return jsonify({"message":str(node.wallet.balance())}), 200
#show local transactions of the last block
@api.route('/last_transactions', methods = ['GET'])
def last_transactions():
latest_block = node.blockchain.chain[-1]
transactions = latest_block.listOfTransactions
export = []
for i in transactions:
b = {'sender':None,'recipient':None,'value':None}
b['sender'] = 'id' + str(i.sender)
b['recipient'] = 'id' + str(i.receiver)
b['value'] = str(i.amount)
export.append(b)
return jsonify(export),200
#make a new transaction
@api.route('/transaction', methods = ['POST'])
def transaction():
#turn the data we received from string to int
recipient_id = str(request.json.get('id'))
#the node should not be able to send money to itself
if recipient_id != str(node.id):
value = request.json.get('amount')
id = None
pub = None
#then we search for info about the node with the
#id that is provided from the client
for peer in node.ring:
if str(peer['id']) == recipient_id:
if (peer['pub']!=None):
id = peer['id']
pub = peer['pub']
check = node.create_transaction(id,pub,int(value))
if (check==True):
return jsonify({"message":"SUCCESS"}),200
else:
return jsonify({'message': 'FAILURE'}),400
else:
return jsonify({"message":'Wrong id'}), 400
@api.route('/five_nodes', methods=['GET'])
def five_nodes():
def dummy(peer,ans):
address = 'http://' + peer['ip'] + ':' + str(peer['port']) + '/init5'
response = requests.get(address)
ans.append(response.status_code)
ans = []
for peer in node.ring:
thread = Thread(target=dummy,args=(peer,ans))
thread.start()
for i in ans:
if i != 200:
return 300
return json.dumps({'ans':ans}) , 200
@api.route('/init5',methods = ['GET'])
def init5():
id = node.id
credentials = None
for cred in node.ring:
if str(cred['id']) == str(id):
credentials = cred
address = 'http://' + credentials['ip'] + ':' + str(credentials['port']) + '/transaction'
file = os.path.join('/home/user/5nodes','transactions'+str(node.id)+'.txt')
with open(file,'r') as text:
for line in text:
line = line.split()
recipient = int(line[0][2])
amount = int(line[1])
string = {'id':recipient,'amount':amount}
response = requests.post(address,json=string)
if response.status_code == 200:
print('Transaction completed')
else:
print('Failure')
return '',200
@api.route('/ten_nodes', methods=['GET'])
def ten_nodes():
def dummy(peer,ans):
address = 'http://' + peer['ip'] + ':' + str(peer['port']) + '/init10'
response = requests.get(address)
ans.append(response.status_code)
ans = []
for peer in node.ring:
thread = Thread(target=dummy,args=(peer,ans))
thread.start()
for i in ans:
if i != 200:
return 300
return json.dumps({'ans':ans}) , 200
@api.route('/init10',methods = ['GET'])
def init10():
id = node.id
credentials = None
for cred in node.ring:
if str(cred['id']) == str(id):
credentials = cred
address = 'http://' + credentials['ip'] + ':' + str(credentials['port']) + '/transaction'
file = os.path.join('/home/user/10nodes','transactions'+str(node.id)+'.txt')
with open(file,'r') as text:
for line in text:
line = line.split()
recipient = int(line[0][2])
amount = int(line[1])
string = {'id':recipient,'amount':amount}
response = requests.post(address,json=string)
if response.status_code == 200:
print('Transaction completed')
else:
print('Failure')
return '',200
@api.route('/temp', methods=['GET'])
def temp():
def dummy(peer,ans):
address = 'http://' + peer['ip'] + ':' + str(peer['port']) + '/temp_init'
response = requests.get(address)
ans.append(response.status_code)
ans = []
for peer in node.ring:
thread = Thread(target=dummy,args=(peer,ans))
thread.start()
for i in ans:
if i != 200:
return 300
return json.dumps({'ans':ans}) , 200
@api.route('/temp_init',methods = ['GET'])
def temp_init():
time_counter = 0
transaction_counter = 0
id = node.id
credentials = None
for cred in node.ring:
if str(cred['id']) == str(id):
credentials = cred
address = 'http://' + credentials['ip'] + ':' + str(credentials['port']) + '/transaction'
file = os.path.join('/home/user/5small','transactions'+str(node.id)+'.txt')
with open(file,'r') as text:
for line in text:
line = line.split()
recipient = int(line[0][2])
amount = int(line[1])
string = {'id':recipient,'amount':amount}
start = time.time()
response = requests.post(address,json=string)
stop_time = time.time() - start
if response.status_code == 200:
time_counter += stop_time
transaction_counter += 1
else:
print('Failure')
return '',200