Browse Source

fee estimates: use median if auto-connect

master
ThomasV 6 years ago
parent
commit
133d74adfb
  1. 18
      electrum/interface.py
  2. 39
      electrum/network.py

18
electrum/interface.py

@ -36,6 +36,7 @@ import itertools
import logging import logging
import aiorpcx import aiorpcx
from aiorpcx import TaskGroup
from aiorpcx import RPCSession, Notification, NetAddress, NewlineFramer from aiorpcx import RPCSession, Notification, NetAddress, NewlineFramer
from aiorpcx.curio import timeout_after, TaskTimeout from aiorpcx.curio import timeout_after, TaskTimeout
from aiorpcx.jsonrpc import JSONRPC, CodeMessageError from aiorpcx.jsonrpc import JSONRPC, CodeMessageError
@ -249,6 +250,7 @@ class Interface(Logger):
self.tip_header = None self.tip_header = None
self.tip = 0 self.tip = 0
self.fee_estimates_eta = {}
# Dump network messages (only for this interface). Set at runtime from the console. # Dump network messages (only for this interface). Set at runtime from the console.
self.debug = False self.debug = False
@ -491,6 +493,7 @@ class Interface(Logger):
try: try:
async with self.taskgroup as group: async with self.taskgroup as group:
await group.spawn(self.ping) await group.spawn(self.ping)
await group.spawn(self.request_fee_estimates)
await group.spawn(self.run_fetch_blocks) await group.spawn(self.run_fetch_blocks)
await group.spawn(self.monitor_connection) await group.spawn(self.monitor_connection)
except aiorpcx.jsonrpc.RPCError as e: except aiorpcx.jsonrpc.RPCError as e:
@ -511,6 +514,21 @@ class Interface(Logger):
await asyncio.sleep(300) await asyncio.sleep(300)
await self.session.send_request('server.ping') 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): async def close(self):
if self.session: if self.session:
await self.session.close() await self.session.close()

39
electrum/network.py

@ -458,24 +458,11 @@ class Network(Logger):
async def _request_fee_estimates(self, interface): async def _request_fee_estimates(self, interface):
session = interface.session session = interface.session
from .simple_config import FEE_ETA_TARGETS
self.config.requested_fee_estimates() self.config.requested_fee_estimates()
async with TaskGroup() as group: histogram = await session.send_request('mempool.get_fee_histogram')
histogram_task = await group.spawn(session.send_request('mempool.get_fee_histogram')) self.config.mempool_fees = 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()
self.logger.info(f'fee_histogram {histogram}') self.logger.info(f'fee_histogram {histogram}')
self.notify('fee_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): def get_status_value(self, key):
if key == 'status': if key == 'status':
@ -516,6 +503,28 @@ class Network(Logger):
with self.interfaces_lock: with self.interfaces_lock:
return list(self.interfaces) 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 @with_recent_servers_lock
def get_servers(self): def get_servers(self):
# note: order of sources when adding servers here is crucial! # note: order of sources when adding servers here is crucial!

Loading…
Cancel
Save