From 133d74adfb4f5d0401caf50943473b129784b8ae Mon Sep 17 00:00:00 2001 From: ThomasV Date: Thu, 12 Mar 2020 14:38:35 +0100 Subject: [PATCH] fee estimates: use median if auto-connect --- electrum/interface.py | 18 ++++++++++++++++++ electrum/network.py | 39 ++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/electrum/interface.py b/electrum/interface.py index d47b84516..f6f01d064 100644 --- a/electrum/interface.py +++ b/electrum/interface.py @@ -36,6 +36,7 @@ import itertools import logging import aiorpcx +from aiorpcx import TaskGroup from aiorpcx import RPCSession, Notification, NetAddress, NewlineFramer from aiorpcx.curio import timeout_after, TaskTimeout from aiorpcx.jsonrpc import JSONRPC, CodeMessageError @@ -249,6 +250,7 @@ class Interface(Logger): self.tip_header = None self.tip = 0 + self.fee_estimates_eta = {} # Dump network messages (only for this interface). Set at runtime from the console. self.debug = False @@ -491,6 +493,7 @@ class Interface(Logger): try: async with self.taskgroup as group: await group.spawn(self.ping) + await group.spawn(self.request_fee_estimates) await group.spawn(self.run_fetch_blocks) await group.spawn(self.monitor_connection) except aiorpcx.jsonrpc.RPCError as e: @@ -511,6 +514,21 @@ class Interface(Logger): await asyncio.sleep(300) await self.session.send_request('server.ping') + async def request_fee_estimates(self): + from .simple_config import FEE_ETA_TARGETS + from .bitcoin import COIN + while True: + async with TaskGroup() as group: + fee_tasks = [] + for i in FEE_ETA_TARGETS: + fee_tasks.append((i, await group.spawn(self.session.send_request('blockchain.estimatefee', [i])))) + for nblock_target, task in fee_tasks: + fee = int(task.result() * COIN) + if fee < 0: continue + self.fee_estimates_eta[nblock_target] = fee + self.network.update_fee_estimates() + await asyncio.sleep(60) + async def close(self): if self.session: await self.session.close() diff --git a/electrum/network.py b/electrum/network.py index fde0ae8be..b624b49f7 100644 --- a/electrum/network.py +++ b/electrum/network.py @@ -458,24 +458,11 @@ class Network(Logger): async def _request_fee_estimates(self, interface): session = interface.session - from .simple_config import FEE_ETA_TARGETS self.config.requested_fee_estimates() - async with TaskGroup() as group: - histogram_task = await group.spawn(session.send_request('mempool.get_fee_histogram')) - fee_tasks = [] - for i in FEE_ETA_TARGETS: - fee_tasks.append((i, await group.spawn(session.send_request('blockchain.estimatefee', [i])))) - self.config.mempool_fees = histogram = histogram_task.result() + histogram = await session.send_request('mempool.get_fee_histogram') + self.config.mempool_fees = histogram self.logger.info(f'fee_histogram {histogram}') self.notify('fee_histogram') - fee_estimates_eta = {} - for nblock_target, task in fee_tasks: - fee = int(task.result() * COIN) - fee_estimates_eta[nblock_target] = fee - if fee < 0: continue - self.config.update_fee_estimates(nblock_target, fee) - self.logger.info(f'fee_estimates {fee_estimates_eta}') - self.notify('fee') def get_status_value(self, key): if key == 'status': @@ -516,6 +503,28 @@ class Network(Logger): with self.interfaces_lock: return list(self.interfaces) + def get_fee_estimates(self): + from statistics import median + from .simple_config import FEE_ETA_TARGETS + if self.auto_connect: + with self.interfaces_lock: + out = {} + for n in FEE_ETA_TARGETS: + try: + out[n] = int(median(filter(None, [i.fee_estimates_eta.get(n) for i in self.interfaces.values()]))) + except: + continue + return out + else: + return self.interface.fee_estimates_eta + + def update_fee_estimates(self): + e = self.get_fee_estimates() + for nblock_target, fee in e.items(): + self.config.update_fee_estimates(nblock_target, fee) + self.logger.info(f'fee_estimates {e}') + self.notify('fee') + @with_recent_servers_lock def get_servers(self): # note: order of sources when adding servers here is crucial!