Exemplo n.º 1
0
    def estimate_fee_per_kb(self, N):
        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))
                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))))

        # Special bitcoin core case: sometimes the highest priority
        # cannot be estimated in that case the 2nd highest priority
        # 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:
                break
        else:  # estimate <= 0
            retval = 10000

        if retval == -1:
            retval = int(Decimal(1e8) * Decimal(estimate))
        log.info("Using tx fee: " + btc.fee_per_kb_to_str(retval))
        return retval
    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.
        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
            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))))

        # Special bitcoin core case: sometimes the highest priority
        # cannot be estimated in that case the 2nd highest priority
        # should be used instead of falling back to hardcoded values
        tries = 2 if N == 1 else 1

        for i in range(tries):
            rpc_result = self._rpc('estimatesmartfee', [N + i])
            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:  # 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.info("Using bitcoin network feerate: " +\
                 btc.fee_per_kb_to_str(retval))
        return retval
Exemplo n.º 3
0
 def estimate_fee_per_kb(self, N):
     if super().fee_per_kb_has_been_manually_set(N):
         # use a floor of 1000 to not run into node relay problems
         return int(max(1000, random.uniform(N * float(0.8), N * float(1.2))))
     fee = self.wallet.network.synchronous_get(('blockchain.estimatefee', [N]
                                               ))
     fee_per_kb_sat = int(float(fee) * 100000000)
     log.info("Got fee: " + btc.fee_per_kb_to_str(fee_per_kb_sat))
     return fee_per_kb_sat
Exemplo n.º 4
0
 def estimate_fee_per_kb(self, N):
     tx_fees_factor = float(jm_single().config.get('POLICY',
                                                   'tx_fees_factor'))
     if super().fee_per_kb_has_been_manually_set(N):
         # use a floor of 1000 to not run into node relay problems
         return int(
             max(
                 1000,
                 random.uniform(N * float(1 - tx_fees_factor),
                                N * float(1 + tx_fees_factor))))
     fee = self.wallet.network.synchronous_get(
         ('blockchain.estimatefee', [N]))
     fee_per_kb_sat = int(float(fee) * 100000000)
     log.info("Got fee: " + btc.fee_per_kb_to_str(fee_per_kb_sat))
     return fee_per_kb_sat
Exemplo n.º 5
0
    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 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
        is used.
        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))

        tx_fees_factor = float(jm_single().config.get('POLICY',
                                                      'tx_fees_factor'))
        if super().fee_per_kb_has_been_manually_set(N):
            N_res = random.uniform(N * float(1 - tx_fees_factor),
                                   N * float(1 + tx_fees_factor))
            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:
                msg = "Using this manually set tx feerate"
                if tx_fees_factor != 0:
                    msg = msg + " (randomized for privacy)"
                log.info(msg + ": " + 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
        # should be used instead of falling back to hardcoded values
        tries = 2 if N == 1 else 1

        for i in range(tries):
            rpc_result = self._rpc('estimatesmartfee', [N + i])
            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:
                estimate_in_sat = btc.btc_to_sat(estimate)
                retval = random.uniform(
                    estimate_in_sat * float(1 - tx_fees_factor),
                    estimate_in_sat * float(1 + tx_fees_factor))
                break
        else:  # cannot get a valid estimate after `tries` tries:
            retval = 10000
            log.warn("Could not source a fee estimate from Core, " +
                     "falling back to default: " +
                     btc.fee_per_kb_to_str(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:
            msg = "Using bitcoin network feerate for " + str(N) + \
                " block confirmation target"
            if tx_fees_factor != 0:
                msg = msg + " (randomized for privacy)"
            log.info(msg + ": " + btc.fee_per_kb_to_str(retval))
            return int(retval)
Exemplo n.º 6
0
def test_fee_per_kb_to_str():
    assert (btc.fee_per_kb_to_str(1000) == "1000 sat/vkB (1.0 sat/vB)")
Exemplo n.º 7
0
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)")