-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrpc.py
More file actions
169 lines (143 loc) · 5.26 KB
/
rpc.py
File metadata and controls
169 lines (143 loc) · 5.26 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
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.client import ServerProxy
from pymongo.errors import DuplicateKeyError
from node import get_nodes, add_node
from Database.mongoDB import MongoDB
from lib.common import cprint
from utils.crypto import Crypto
from Wallet.p2pkh import P2pkh
server = None
PORT = 8301
p = P2pkh()
class RpcServer():
def __init__(self, server):
self.server = server
def ping(self):
return True
def get_blockchain(self) -> list:
bclist = []
bcdb = MongoDB()
# Validation
for x in bcdb.getAll('blockchain'):
header_bin = str(x['index']) + str(x['timestamp']) + str(x['prevHash']) +\
str(x['difficulty']) + str(x['nonce']) + str(x['data']) + str(x['merkleroot'])
if x['hash'] == Crypto().sha256(Crypto().sha256(header_bin)):
bclist.append(x)
MongoDB().close_connect()
return bclist
def new_block(self, block):
# Validation
header_bin = str(block['index']) + str(block['timestamp']) + str(block['prevHash']) + \
str(block['difficulty']) + str(block['nonce']) + str(block['data']) + str(block['merkleroot'])
if block['hash'] != Crypto().sha256(Crypto().sha256(header_bin)):
return False
try:
cprint('RPC', block)
MongoDB().insertOne('blockchain', block)
cprint('INFO', "Receive new block.")
MongoDB().close_connect()
return True
except DuplicateKeyError:
print('Existed block, skipped')
return False
def get_transactions(self) -> list:
tdb = MongoDB()
txs = []
for x in tdb.getAll("transactions"):
txs.append(x)
MongoDB().close_connect()
return txs
def new_untransaction(self, untx):
cprint(__name__, untx)
'''
verify(self, utxoHash, pack, address) -> bool
'''
txid = untx['hash']
unLockSig = []
signature = []
spublickey = []
address = []
# get signature and public key from utxo input
for x in untx['vin']:
unLockSig.append(x['unLockSig'])
signature.append(x['unLockSig']['signature'])
spublickey.append(x['unLockSig']['publickey'])
for x in untx['vout']:
address.append(x['lockSig']['senderAddress'])
# Normal check
# whether it has a signature
if len(set(signature)) != 1:
print('Signature is not correct')
return False
# whether it has a public key
if len(set(spublickey)) != 1:
print('Signature is not correct')
return False
# whether it has an address
if len(set(address)) != 1:
print('Signature is not correct')
return False
# use public key and transaction id to verify signature
if not p.verify(txid, unLockSig[0], address[0]):
print('Signature is not correct')
return False
print('Signature is correct')
# try to store pending transactions, if they exist, then just skip
try:
MongoDB().insertOne('ptransactions', untx)
except DuplicateKeyError:
print('Existed pending transactions, skipped')
cprint('INFO', "Receive new unchecked transaction.")
MongoDB().close_connect()
return True
def blocked_transactions(self, txs):
try:
for x in txs:
MongoDB().insertOne('transactions', x)
cprint('INFO', "Receive new blocked transactions.")
MongoDB().close_connect()
return True
except DuplicateKeyError:
print('Existed transactions, skipped')
return False
def add_node(self, address):
add_node(address)
return True
class RpcClient():
ALLOW_METHOD = ['get_transactions', 'get_blockchain', 'new_block', 'new_untransaction', 'blocked_transactions',
'ping', 'add_node']
def __init__(self, node):
self.node = node
self.client = ServerProxy(node)
def __getattr__(self, name):
def noname(*args, **kw):
if name in self.ALLOW_METHOD:
return getattr(self.client, name)(*args, **kw)
return noname
class BroadCast():
# Calling all functions in RpcServer
def __getattr__(self, name):
def processes(*args, **kw):
nodes = get_clients()
result = []
for x in nodes:
try:
result.append(getattr(x, name)(*args, **kw))
print(result)
except ConnectionRefusedError:
cprint('WARNNING', 'Failed to connect %s when invoking %s ' % (x.node, name))
else:
cprint('INFOMATION', 'Connect to %s successful invoking %s .' % (x.node, name))
return result
return processes
def start_server(ip, port=8301):
server = SimpleXMLRPCServer((ip, port))
rpc = RpcServer(server)
server.register_instance(rpc)
server.serve_forever()
def get_clients():
clients = []
nodes = get_nodes()
for node in nodes:
clients.append(RpcClient(node))
return clients