2020-02-02 16:31:01 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
from base64 import b64decode
|
|
|
|
|
|
|
|
from flask import Flask, jsonify, request, abort, Response, make_response
|
|
|
|
from nacl import signing
|
|
|
|
from nacl import encoding
|
|
|
|
|
|
|
|
class SVCNode:
|
|
|
|
"""
|
|
|
|
info on a service node
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
self._seed = os.urandom(32)
|
|
|
|
self._ed25519_secret = signing.SigningKey(self._seed)
|
|
|
|
|
|
|
|
def seed(self):
|
|
|
|
"""
|
|
|
|
return hex seed
|
|
|
|
"""
|
|
|
|
return self._ed25519_secret.encode(encoding.HexEncoder).decode('ascii') + self.pubkey()
|
|
|
|
|
|
|
|
def pubkey(self):
|
|
|
|
"""
|
|
|
|
make hex public key
|
|
|
|
"""
|
|
|
|
return self._ed25519_secret.verify_key.encode(encoding.HexEncoder).decode('ascii')
|
|
|
|
|
|
|
|
def toJson(self):
|
|
|
|
"""
|
|
|
|
make the snode a json object for jsonrpc
|
|
|
|
"""
|
2020-02-02 17:44:56 +00:00
|
|
|
return {'pubkey_ed25519': self.pubkey(), 'active': True, 'funded': True}
|
2020-02-02 16:31:01 +00:00
|
|
|
|
|
|
|
class MockServer:
|
|
|
|
|
|
|
|
def __init__(self, numServiceNodes):
|
|
|
|
self.app = Flask('lokid-rpc-mock')
|
|
|
|
#self.app.config['SECRET_KEY'] = os.urandom(16)
|
|
|
|
# populate service nodes
|
|
|
|
self._serviceNodes = dict()
|
|
|
|
for n in range(numServiceNodes):
|
|
|
|
self.makeSNode("svc-%03d" % n)
|
|
|
|
|
|
|
|
self._handlers = {
|
|
|
|
'lokinet_ping': self._lokinet_ping,
|
|
|
|
'get_n_service_nodes' : self._get_n_service_nodes,
|
|
|
|
'get_service_node_privkey' : self._get_service_node_privkey
|
|
|
|
}
|
|
|
|
#digest = HTTPDigestAuth(realm='lokid')
|
|
|
|
|
|
|
|
@self.app.route('/json_rpc', methods=["POST"])
|
|
|
|
def _jsonRPC():
|
|
|
|
j = request.get_json()
|
|
|
|
method = j['method']
|
|
|
|
snode = None
|
|
|
|
if 'authorization' in request.headers:
|
|
|
|
user = b64decode(request.headers['authorization'][6:].encode('ascii')).decode('ascii').split(':')[0]
|
|
|
|
self.app.logger.error(user)
|
|
|
|
if len(user) > 0:
|
|
|
|
snode = self._serviceNodes[user]
|
|
|
|
result = self._handlers[method](snode)
|
|
|
|
if result:
|
|
|
|
resp = {'jsonrpc': '2.0', 'id': j['id'], 'result': result}
|
|
|
|
return jsonify(resp)
|
|
|
|
else:
|
|
|
|
r = make_response('nope', 401)
|
|
|
|
r.headers['www-authenticate'] = 'basic'
|
|
|
|
return r
|
|
|
|
def after(req):
|
|
|
|
req.content_type = "application/json"
|
|
|
|
return req
|
|
|
|
self.app.after_request(after)
|
|
|
|
|
|
|
|
def _get_n_service_nodes(self, our_snode):
|
|
|
|
return {
|
|
|
|
'block_hash' : 'mock',
|
|
|
|
'service_node_states' : self.getSNodeList()
|
|
|
|
}
|
|
|
|
|
|
|
|
def _get_service_node_privkey(self, our_snode):
|
|
|
|
if our_snode is None:
|
|
|
|
return None
|
|
|
|
return {
|
|
|
|
'service_node_ed25519_privkey': our_snode.seed()
|
|
|
|
}
|
|
|
|
|
|
|
|
def _lokinet_ping(self, snode):
|
|
|
|
return {
|
|
|
|
'status' : "OK"
|
|
|
|
}
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
"""
|
|
|
|
run mainloop and serve jsonrpc server
|
|
|
|
"""
|
|
|
|
self.app.run()
|
|
|
|
|
|
|
|
def makeSNode(self, name):
|
|
|
|
"""
|
|
|
|
make service node entry
|
|
|
|
"""
|
|
|
|
self._serviceNodes[name] = SVCNode()
|
|
|
|
|
|
|
|
|
|
|
|
def getSNodeList(self):
|
|
|
|
l = list()
|
|
|
|
for name in self._serviceNodes:
|
|
|
|
l.append(self._serviceNodes[name].toJson())
|
|
|
|
return l
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
import sys
|
|
|
|
serv = MockServer(int(sys.argv[1]))
|
|
|
|
serv.run()
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|