1
0

fee estimates: use median if auto-connect

This commit is contained in:
ThomasV
2020-03-12 14:38:35 +01:00
parent 5bac2fea98
commit 133d74adfb
2 changed files with 42 additions and 15 deletions

View File

@@ -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()

View File

@@ -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!