diff --git a/jmclient/jmclient/blockchaininterface.py b/jmclient/jmclient/blockchaininterface.py index a7536f1..cf1e802 100644 --- a/jmclient/jmclient/blockchaininterface.py +++ b/jmclient/jmclient/blockchaininterface.py @@ -412,19 +412,24 @@ class BitcoinCoreInterface(BlockchainInterface): how this is distinguished). In the latter case, it is prevented from falling below the minimum allowed feerate for relay on the Bitcoin network. + In case of failure to connect, None is returned. + In case of failure to source a specific minimum fee relay rate + (which is used to sanity check user's chosen fee rate), 1000 + is used. + In case of failure to source a feerate estimate for targeted + number of blocks, a default of 10000 is returned. """ if super().fee_per_kb_has_been_manually_set(N): # 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)) - else: # cannot get valid relayfee: fall back to 1000 sat/kbyte - relayfee_in_sat = 1000 - log.debug("Using this min relay fee as tx feerate per kB floor: " + - btc.fee_per_kb_to_str(1000)) + if not rpc_result: + # in case of connection error: + return None + btc_relayfee = rpc_result.get('relayfee', 1000) + relayfee_in_sat = int(Decimal(1e8) * Decimal(btc_relayfee)) + log.debug("Using this min relay fee as tx feerate 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)))) @@ -433,19 +438,25 @@ class BitcoinCoreInterface(BlockchainInterface): # should be used instead of falling back to hardcoded values tries = 2 if N == 1 else 1 - estimate = -1 - retval = -1 for i in range(tries): rpc_result = self._rpc('estimatesmartfee', [N + i]) - estimate = rpc_result.get('feerate', estimate) - if estimate > 0: + if not rpc_result: + # in case of connection error: + return None + estimate = rpc_result.get('feerate') + # `estimatesmartfee` will currently return in the format + # `{'errors': ['Insufficient data or no feerate found'], 'blocks': N}` + # if it is not able to make an estimate. We insist that + # the 'feerate' key is found and contains a positive value: + if estimate and estimate > 0: + retval = int(Decimal(1e8) * Decimal(estimate)) break - else: # estimate <= 0 + else: # cannot get a valid estimate after `tries` tries: + log.warn("Could not source a fee estimate from Core, " + + "falling back to default.") retval = 10000 - if retval == -1: - retval = int(Decimal(1e8) * Decimal(estimate)) - log.info("Using bitcoin network feerate (per kB in sats): " +\ + log.info("Using bitcoin network feerate: " +\ btc.fee_per_kb_to_str(retval)) return retval diff --git a/jmclient/jmclient/wallet.py b/jmclient/jmclient/wallet.py index 2752079..8c7e394 100644 --- a/jmclient/jmclient/wallet.py +++ b/jmclient/jmclient/wallet.py @@ -81,6 +81,9 @@ def estimate_tx_fee(ins, outs, txtype='p2pkh', extra_bytes=0): "without blockchain source.") fee_per_kb = jm_single().bc_interface.estimate_fee_per_kb( jm_single().config.getint("POLICY","tx_fees")) + if fee_per_kb is None: + raise RuntimeError("Cannot estimate fee per kB, possibly" + + " a failure of connection to the blockchain.") absurd_fee = jm_single().config.getint("POLICY", "absurd_fee_per_kb") if fee_per_kb > absurd_fee: #This error is considered critical; for safety reasons, shut down. diff --git a/scripts/sendpayment.py b/scripts/sendpayment.py index 78bb250..d343832 100755 --- a/scripts/sendpayment.py +++ b/scripts/sendpayment.py @@ -178,8 +178,8 @@ def main(): 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)) + log.debug("Estimated miner/tx fee for each cj participant: " + + btc.amount_to_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