Browse Source

Merge #850: Use mempoolminfee instead of minrelaytxfee as tx feerate floor

7bfc758110 Use mempoolminfee instead of minrelaytxfee as tx feerate floor (Kristaps Kaupe)
a982ea0e17 Better tx feerate formatting (Kristaps Kaupe)

Pull request description:

  With the current state of mempool being constantly full, it is better to use `mempoolminfee` as a tx fee rate floor instead of `minrelaytxfee` (which is usually just 1 sat/vB), otherwise your local Bitcoin node may refuse to accept transaction if it's txfee is below certain value (I think it's around 3 sat/vB currently with default config). And this floor should be checked also when `estimatesmartfee` is used, as it can give you values below that.

  Also improved feerate formatting (you don't want gazzilions of digits after decimal point, it's useless) and choosen tx feerate logging.

Top commit has no ACKs.

Tree-SHA512: b5ae53491bc4efa71ceaf5b7bd9955f573f563514bb884b53130ab918fd6a19fce1c0a924ef2c4064ffb57fd869dd9c02f8d683a8c25f825b4dac48f0a6caf1d
master
Kristaps Kaupe 5 years ago
parent
commit
7a95192528
No known key found for this signature in database
GPG Key ID: 33E472FE870C7E5D
  1. 3
      jmbitcoin/jmbitcoin/amount.py
  2. 2
      jmbitcoin/test/test_amounts.py
  3. 57
      jmclient/jmclient/blockchaininterface.py
  4. 2
      jmclient/jmclient/taker_utils.py

3
jmbitcoin/jmbitcoin/amount.py

@ -60,4 +60,5 @@ def sat_to_str_p(sat):
def fee_per_kb_to_str(feerate):
return str(feerate) + " sat/vkB (" + str(feerate / 1000) + " sat/vB)"
return (str(int(feerate)) + " sat/vkB (" +
'%.1f' % (int(feerate / 100) / 10) + " sat/vB)")

2
jmbitcoin/test/test_amounts.py

@ -112,3 +112,5 @@ def test_sat_to_str_p():
def test_fee_per_kb_to_str():
assert(btc.fee_per_kb_to_str(1000) == "1000 sat/vkB (1.0 sat/vB)")
assert(btc.fee_per_kb_to_str(1234) == "1234 sat/vkB (1.2 sat/vB)")
assert(btc.fee_per_kb_to_str(1999) == "1999 sat/vkB (1.9 sat/vB)")

57
jmclient/jmclient/blockchaininterface.py

@ -412,8 +412,8 @@ class BitcoinCoreInterface(BlockchainInterface):
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.
In both cases it is prevented from falling below the current
minimum feerate for tx to be accepted into node's mempool.
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
@ -421,19 +421,27 @@ class BitcoinCoreInterface(BlockchainInterface):
In case of failure to source a feerate estimate for targeted
number of blocks, a default of 10000 is returned.
"""
# use the local bitcoin core minimum mempool fee as floor to avoid
# relay problems
rpc_result = self._rpc('getmempoolinfo', None)
if not rpc_result:
# in case of connection error:
return None
mempoolminfee_in_sat = btc.btc_to_sat(rpc_result['mempoolminfee'])
mempoolminfee_in_sat_randomized = random.uniform(
mempoolminfee_in_sat, mempoolminfee_in_sat * float(1.2))
if super().fee_per_kb_has_been_manually_set(N):
# use the local bitcoin core relay fee as floor to avoid relay
# problems
rpc_result = self._rpc('getnetworkinfo', None)
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))))
N_res = random.uniform(N * float(0.8), N * float(1.2))
if N_res < mempoolminfee_in_sat:
log.info("Using this mempool min fee as tx feerate: " +
btc.fee_per_kb_to_str(mempoolminfee_in_sat) + ".")
return int(mempoolminfee_in_sat_randomized)
else:
log.info("Using this manually set tx feerate (randomized " +
"for privacy): " + btc.fee_per_kb_to_str(N_res) + ".")
return int(N_res)
# Special bitcoin core case: sometimes the highest priority
# cannot be estimated in that case the 2nd highest priority
@ -451,16 +459,25 @@ class BitcoinCoreInterface(BlockchainInterface):
# 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))
estimate_in_sat = btc.btc_to_sat(estimate)
retval = random.uniform(estimate_in_sat * float(0.8),
estimate_in_sat * float(1.2))
break
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
log.warn("Could not source a fee estimate from Core, " +
"falling back to default: " +
btc.fee_per_kb_to_str(retval) + ".")
log.info("Using bitcoin network feerate: " +\
btc.fee_per_kb_to_str(retval))
return retval
if retval < mempoolminfee_in_sat:
log.info("Using this mempool min fee as tx feerate: " +
btc.fee_per_kb_to_str(mempoolminfee_in_sat) + ".")
return int(mempoolminfee_in_sat_randomized)
else:
log.info("Using bitcoin network feerate for " + str(N) +
" block confirmation target (randomized for privacy): " +
btc.fee_per_kb_to_str(retval))
return int(retval)
def get_current_block_height(self):
try:

2
jmclient/jmclient/taker_utils.py

@ -139,7 +139,7 @@ def direct_send(wallet_service, amount, mixdepth, destination, answeryes=False,
#must use unix time as the transaction locktime
#Now ready to construct transaction
log.info("Using a fee of : " + amount_to_str(fee_est) + ".")
log.info("Using a fee of: " + amount_to_str(fee_est) + ".")
if amount != 0:
log.info("Using a change value of: " + amount_to_str(changeval) + ".")
tx = make_shuffled_tx(list(utxos.keys()), outs, 2, tx_locktime)

Loading…
Cancel
Save