From bb15aa0312b5de0553f798ba038736f5d6c2eff9 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Mon, 30 Nov 2020 16:43:50 +0000 Subject: [PATCH] Quiet/make more accurate fee information in sends Fixes #736. Prior to this commit, the 'relay fee floor' was being shown at INFO level in the command line output, but not the actual feerate paid (in direct send scenarios; the coinjoin scenario is rather more complex since fees are not known before negotiation flow, but estimates are printed). After this commit, the output at INFO level for direct sends shows specifically the feerate and then the actual fee, with min relay feerate relegated to DEBUG messages only, for cases of manual feerate setting. There is also some minor cleanup in comments and coinjoin fee estimate messages are removed for non-coinjoins. --- jmclient/jmclient/blockchaininterface.py | 24 ++++++++++++++++-------- scripts/sendpayment.py | 12 +++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/jmclient/jmclient/blockchaininterface.py b/jmclient/jmclient/blockchaininterface.py index caf67c2..a7536f1 100644 --- a/jmclient/jmclient/blockchaininterface.py +++ b/jmclient/jmclient/blockchaininterface.py @@ -406,20 +406,27 @@ class BitcoinCoreInterface(BlockchainInterface): return result def estimate_fee_per_kb(self, N): + """ The argument N may be either a number of blocks target, + for estimation of feerate by Core, or a number of satoshis + per kilo-vbyte (see `fee_per_kb_has_been_manually_set` for + how this is distinguished). + In the latter case, it is prevented from falling below the + minimum allowed feerate for relay on the Bitcoin network. + """ if super().fee_per_kb_has_been_manually_set(N): - # use the local bitcoin core relay fee as floor to avoid relay problems + # use the local bitcoin core relay fee as floor to avoid relay + # problems btc_relayfee = -1 rpc_result = self._rpc('getnetworkinfo', None) btc_relayfee = rpc_result.get('relayfee', btc_relayfee) if btc_relayfee > 0: relayfee_in_sat = int(Decimal(1e8) * Decimal(btc_relayfee)) - log.info("Using this min relay fee as tx fee floor: " + - btc.fee_per_kb_to_str(relayfee_in_sat)) - return int(max(relayfee_in_sat, random.uniform(N * float(0.8), N * float(1.2)))) else: # cannot get valid relayfee: fall back to 1000 sat/kbyte - log.info("Using this min relay fee as tx fee floor " + - "(fallback): " + btc.fee_per_kb_to_str(1000)) - return int(max(1000, random.uniform(N * float(0.8), N * float(1.2)))) + relayfee_in_sat = 1000 + log.debug("Using this min relay fee as tx feerate per kB floor: " + + btc.fee_per_kb_to_str(1000)) + return int(max(relayfee_in_sat, random.uniform(N * float(0.8), + N * float(1.2)))) # Special bitcoin core case: sometimes the highest priority # cannot be estimated in that case the 2nd highest priority @@ -438,7 +445,8 @@ class BitcoinCoreInterface(BlockchainInterface): if retval == -1: retval = int(Decimal(1e8) * Decimal(estimate)) - log.info("Using tx fee: " + btc.fee_per_kb_to_str(retval)) + log.info("Using bitcoin network feerate (per kB in sats): " +\ + btc.fee_per_kb_to_str(retval)) return retval def get_current_block_height(self): diff --git a/scripts/sendpayment.py b/scripts/sendpayment.py index 285f153..78bb250 100755 --- a/scripts/sendpayment.py +++ b/scripts/sendpayment.py @@ -172,17 +172,19 @@ def main(): # the sync call here will now be a no-op: wallet_service.startService() - # Dynamically estimate a realistic fee. + # Dynamically estimate a realistic fee, for coinjoins. # At this point we do not know even the number of our own inputs, so # we guess conservatively with 2 inputs and 2 outputs each. - fee_per_cp_guess = estimate_tx_fee(2, 2, txtype=wallet_service.get_txtype()) - log.debug("Estimated miner/tx fee for each cj participant: " + str( - fee_per_cp_guess)) + if options.makercount != 0: + fee_per_cp_guess = estimate_tx_fee(2, 2, + txtype=wallet_service.get_txtype()) + log.debug("Estimated miner/tx fee for each cj participant: " + str( + fee_per_cp_guess)) # From the estimated tx fees, check if the expected amount is a # significant value compared the the cj amount; currently enabled # only for single join (the predominant, non-advanced case) - if options.schedule == '': + if options.schedule == '' and options.makercount != 0: total_cj_amount = amount if total_cj_amount == 0: total_cj_amount = wallet_service.get_balance_by_mixdepth()[options.mixdepth]