diff --git a/server.py b/server.py index 0a78f57c897ac77f7e1b2bf5825629aa7642d0dc..e2ed9250c4cc73dc5d0c09e9638ff0852420190e 100644 --- a/server.py +++ b/server.py @@ -28,6 +28,7 @@ import duniterpy.api.bma as bma from duniterpy.api.client import Client from duniterpy.key import SigningKey, PublicKey import utils +import nest_asyncio """ Used terms: @@ -201,6 +202,7 @@ def read_config(cdir, conf_overwrite={}): conf["mix"].setdefault("mix_min_txs", MIX_MIN_TXS) conf["mix"].setdefault("mix_req_age_max", MIX_REQ_AGE_MAX) conf.setdefault("idty", {}) + conf["idty"].setdefault("needed", True) conf["idty"].setdefault("sig", "") conf["idty"].setdefault("pubkey", "") @@ -585,6 +587,7 @@ class ClientThread(Thread): new_peer = utils.Peer(self.conf, data["info"]) except Exception as e: print("Peer detection: info: "+str(e)) + continue new_peers.setdefault(new_peer.hash, []) new_peers[new_peer.hash].append(new_peer) @@ -601,7 +604,7 @@ class ClientThread(Thread): answered += 1 except (ConnectionRefusedError, socks.GeneralProxyError, socket.gaierror, socket.timeout): - utils.logprint("Peer detection: Network error: "+peer.to_human_str(), utils.LOG_WARN) + utils.logprint("Peer detection: Network error: "+peer.to_human_str(), utils.LOG_WARN) # Choose the more recent peer infos added_peers = False @@ -714,7 +717,9 @@ class ClientThread(Thread): utils.logprint("All BMA endpoints down: cannot mix!", utils.LOG_ERROR) def run(self): - asyncio.new_event_loop().run_until_complete(self.start_client()) + loop = asyncio.new_event_loop() + nest_asyncio.apply(loop) + loop.run_until_complete(self.start_client()) async def start_client(self): t = time.time() diff --git a/utils.py b/utils.py index 0ee0ca18b42c5296f03f242204b9802182194a5f..de4e5db1c71834430fe44b3bbb3c5854fb41276c 100644 --- a/utils.py +++ b/utils.py @@ -17,12 +17,15 @@ along with ÄžMixer-py. If not, see <https://www.gnu.org/licenses/>. """ -import sys, os, re, socket, time, secrets, hashlib, base64 +import sys, os, re, socket, time, secrets, hashlib, base64, asyncio import socks import ubjson import libnacl.sign import plyvel from duniterpy.key import SigningKey, PublicKey +import duniterpy.api.bma as bma +from duniterpy.api.client import Client +from duniterpy.api.errors import DuniterError import silkaj.money, silkaj.tx VERSION = "0.2.0" @@ -121,6 +124,11 @@ def getargv(arg:str, default:str="", n:int=1, args:list=sys.argv) -> str: else: return default +def run_async(coro): + try: + return asyncio.get_event_loop().run_until_complete(coro) + except RuntimeError: + return asyncio.new_event_loop().run_until_complete(coro) #-------- ÄžMixer @@ -137,6 +145,8 @@ class Peer: # TODO tests assert data["currency"] == conf["currency"] , "Not the same currency" + if conf["idty"]["needed"]: + assert run_async(check_idty(conf["client"]["bma_hosts"], data["idty"])) self.doctype = data["doctype"] self.docver = data["docver"] @@ -170,7 +180,10 @@ class Peer: "raw": raw } raw = ubjson.dumpb(data) - return Peer(conf, raw) + try: + return Peer(conf, raw) + except AssertionError: + return None def load_peers(conf:dict, db_peers:plyvel.DB, peers:dict): for _, data in db_peers: @@ -181,6 +194,32 @@ def save_peers(db_peers:plyvel.DB, peers:dict): for peer in peers: db_peers.put(peers[peer].hash, peers[peer].raw) +async def bma_client(bma_endpoints:list): + client = None + for bma_endpoint in bma_endpoints: + client = Client("BMAS "+bma_endpoint) + try: + await client(bma.node.summary) + break + except: + logprint("BMA down: "+bma_endpoint, utils.LOG_WARN) + await client.close() + client = None + return client + +#async def check_idty(client:Client, pubkey:str): +# print( await client(bma.wot.lookup, pubkey)) + +async def check_idty(bma_endpoints:list, pubkey:str): + client = await bma_client(bma_endpoints) + try: + result = await client(bma.wot.requirements, pubkey) + except DuniterError: + result = {} + finally: + await client.close() + return "identities" in result and len(result["identities"]) > 0 and result["identities"][0]["pubkey"] == pubkey and result["identities"][0]["membershipExpiresIn"] > 0 + async def send_transaction(sender_keys:SigningKey, receiver_pubkey:str, amount:int, comment:str): #sender_amount = silkaj.money.get_amount_from_pubkey(sender_keys.pubkey)[0] #assert sender_amount >= amount, "not enough money"