Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions bitcoin/feerate.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ u32 feerate_from_style(u32 feerate, enum feerate_style style)
abort();
}

u32 feerate_relay_floor(u32 floor_perkw)
{
u64 rate;

if (floor_perkw <= BITCOIND_MINRELAYTXFEE_PER_KW)
return FEERATE_FLOOR;

rate = ((u64)floor_perkw * (MINIMUM_TX_WEIGHT + 3)
+ MINIMUM_TX_WEIGHT - 1) / MINIMUM_TX_WEIGHT
+ (2000 + MINIMUM_TX_WEIGHT - 1) / MINIMUM_TX_WEIGHT;
if (rate > UINT_MAX)
return UINT_MAX;
return rate;
}

u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style)
{
switch (style) {
Expand Down
10 changes: 10 additions & 0 deletions bitcoin/feerate.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ static inline u32 feerate_floor_check(void)
return FEERATE_FLOOR;
}

/* The lowest feerate we should pay ourselves, given bitcoind's floor in
* perkw (ie. a minimum of at most 4 * floor_perkw sat/kvB).
*
* At 1 sat/vB this is FEERATE_FLOOR. Above it FEERATE_FLOOR's slack no
* longer covers the rounding, so we use the worst case: bitcoind needs
* ceil(minimum * ceil(weight / 4) / 1000), we pay (feerate * weight) // 1000,
* and feerate * weight / 1000 - 1 >= minimum * (weight + 3) / 4000 + 1 is
* hardest to satisfy at MINIMUM_TX_WEIGHT. */
u32 feerate_relay_floor(u32 floor_perkw);

u32 feerate_from_style(u32 feerate, enum feerate_style style);
u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style);
const char *feerate_style_name(enum feerate_style style);
Expand Down
49 changes: 49 additions & 0 deletions bitcoin/test/run-feerate_relay_floor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "config.h"
#include <assert.h>
#include <bitcoin/feerate.c>
#include <common/setup.h>
#include <stdio.h>

/* AUTOGENERATED MOCKS START */
/* AUTOGENERATED MOCKS END */

/* What bitcoind charges at a minimum of perkvb sat/kvB. */
static u64 bitcoind_min_fee(u64 perkvb, u64 weight)
{
u64 vsize = (weight + 3) / 4;
return (perkvb * vsize + 999) / 1000;
}

static bool relays(u64 perkvb, u32 feerate, u64 weight)
{
return (u64)feerate * weight / 1000 >= bitcoind_min_fee(perkvb, weight);
}

int main(int argc, const char *argv[])
{
common_setup(argv[0]);

assert(feerate_relay_floor(0) == FEERATE_FLOOR);
assert(feerate_relay_floor(BITCOIND_MINRELAYTXFEE_PER_KW) == FEERATE_FLOOR);
assert(feerate_relay_floor(UINT32_MAX) == UINT32_MAX);

/* Floors as bitcoind reports them (sat/kvB), converted as we do:
* every one up to 20 sat/vB, then a sample up to FEERATE_CEILING.
* Small weights are the hard case. */
for (u64 perkvb = 1; perkvb < 4000000; perkvb += perkvb < 20000 ? 1 : 997) {
u32 floor = feerate_from_style(perkvb, FEERATE_PER_KBYTE);
u32 rate = feerate_relay_floor(floor);

/* Never much more than bitcoind's own floor. */
assert(perkvb <= 1000
|| (u64)rate * 4 <= perkvb + perkvb / 100 + 40);

for (u64 weight = MINIMUM_TX_WEIGHT; weight < 800; weight++)
assert(relays(perkvb, rate, weight));
for (u64 weight = 800; weight < 400000; weight += 9973)
assert(relays(perkvb, rate, weight));
}

common_shutdown();
return 0;
}
21 changes: 15 additions & 6 deletions lightningd/bitcoind.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ static void bitcoin_plugin_send(struct bitcoind *bitcoind,
struct estimatefee_call {
struct bitcoind *bitcoind;
void (*cb)(struct lightningd *ld, u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *rates, void *);
void *cb_arg;
};
Expand Down Expand Up @@ -254,7 +255,7 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
{
const jsmntok_t *resulttok, *floortok;
struct feerate_est *feerates;
u32 floor;
u32 floor, relay_floor;

resulttok = get_bitcoin_result(call->bitcoind, buf, toks, "estimatefees");

Expand All @@ -274,8 +275,6 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,

/* Convert to perkw */
floor = feerate_from_style(floor, FEERATE_PER_KBYTE);
if (floor < FEERATE_FLOOR)
floor = FEERATE_FLOOR;

/* Anything this high is a broken fee source, not a busy mempool:
* clamp it rather than let it loose on the rest of lightningd. */
Expand All @@ -287,6 +286,14 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
floor = FEERATE_CEILING;
}

/* Before raising floor to FEERATE_FLOOR, which would hide whether
* bitcoind's minimum is above 1 sat/vB. */
relay_floor = feerate_relay_floor(floor);
if (relay_floor > FEERATE_CEILING)
relay_floor = FEERATE_CEILING;
if (floor < FEERATE_FLOOR)
floor = FEERATE_FLOOR;

/* FIXME: We could let this go below the dynamic floor, but we'd
* need to know if the floor is because of their node's policy
* (minrelaytxfee) or mempool conditions (mempoolminfee). */
Expand All @@ -301,18 +308,20 @@ static void estimatefees_callback(const char *buf, const jsmntok_t *toks,
(u32)FEERATE_CEILING);
feerates[i].rate = FEERATE_CEILING;
}
if (feerates[i].rate < floor)
feerates[i].rate = floor;
if (feerates[i].rate < relay_floor)
feerates[i].rate = relay_floor;
}

call->cb(call->bitcoind->ld, floor, feerates, call->cb_arg);
call->cb(call->bitcoind->ld, floor, relay_floor, feerates,
call->cb_arg);
tal_free(call);
}

void bitcoind_estimate_fees_(const tal_t *ctx,
struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *feerates,
void *arg),
void *cb_arg)
Expand Down
2 changes: 2 additions & 0 deletions lightningd/bitcoind.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ struct bitcoind *new_bitcoind(const tal_t *ctx,
(cb), (arg), \
struct lightningd *, \
u32, \
u32, \
const struct feerate_est *), \
(arg))

void bitcoind_estimate_fees_(const tal_t *ctx,
struct bitcoind *bitcoind,
void (*cb)(struct lightningd *ld,
u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *feerates,
void *arg),
void *cb_arg);
Expand Down
30 changes: 19 additions & 11 deletions lightningd/chaintopology.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ u32 feerate_for_deadline(const struct chain_topology *topo, u32 blockcount)
u32 rate = interp_feerate(topo->feerates[0], blockcount);

/* 0 is a special value, meaning "don't know" */
if (rate && rate < topo->feerate_floor)
rate = topo->feerate_floor;
if (rate && rate < topo->relay_feerate_floor)
rate = topo->relay_feerate_floor;
return rate;
}

Expand All @@ -460,12 +460,9 @@ u32 feerate_for_target(const struct chain_topology *topo, u64 deadline)

blocks = deadline - blockheight;

/* Over 200 blocks, we *always* use min fee! */
if (blocks > 200)
return FEERATE_FLOOR;
/* Over 100 blocks, use min fee bitcoind will accept */
if (blocks > 100)
return get_feerate_floor(topo);
return get_relay_feerate_floor(topo);

return feerate_for_deadline(topo, blocks);
}
Expand All @@ -492,8 +489,8 @@ static void smooth_one_feerate(const struct chain_topology *topo,
if (abs((int)rate->rate - (int)feerate_smooth) > (0.1 * rate->rate))
rate->rate = feerate_smooth;

if (rate->rate < get_feerate_floor(topo))
rate->rate = get_feerate_floor(topo);
if (rate->rate < get_relay_feerate_floor(topo))
rate->rate = get_relay_feerate_floor(topo);

if (rate->rate != feerate_smooth)
log_debug(topo->log,
Expand Down Expand Up @@ -540,6 +537,7 @@ static bool different_blockcounts(struct chain_topology *topo,

static void update_feerates(struct lightningd *ld,
u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *rates TAKES,
void *arg UNUSED)
{
Expand All @@ -548,6 +546,7 @@ static void update_feerates(struct lightningd *ld,
struct chain_topology *topo = ld->topology;

topo->feerate_floor = feerate_floor;
topo->relay_feerate_floor = relay_feerate_floor;

/* Don't bother updating if we got no feerates; we'd rather have
* historical ones, if any. */
Expand Down Expand Up @@ -587,10 +586,11 @@ static void update_feerates(struct lightningd *ld,

static void update_feerates_repeat(struct lightningd *ld,
u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *rates TAKES,
void *unused)
{
update_feerates(ld, feerate_floor, rates, unused);
update_feerates(ld, feerate_floor, relay_feerate_floor, rates, unused);
next_updatefee_timer(ld->topology);
}

Expand Down Expand Up @@ -701,6 +701,11 @@ u32 get_feerate_floor(const struct chain_topology *topo)
return topo->feerate_floor;
}

u32 get_relay_feerate_floor(const struct chain_topology *topo)
{
return topo->relay_feerate_floor;
}

static struct command_result *json_feerates(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
Expand Down Expand Up @@ -1407,16 +1412,18 @@ static void get_chaininfo_once(struct bitcoind *bitcoind, const char *chain,
}

struct feerates_once {
u32 feerate_floor;
u32 feerate_floor, relay_feerate_floor;
struct feerate_est *rates;
};

static void get_feerates_once(struct lightningd *ld,
u32 feerate_floor,
u32 relay_feerate_floor,
const struct feerate_est *rates TAKES,
struct feerates_once *once)
{
once->feerate_floor = feerate_floor;
once->relay_feerate_floor = relay_feerate_floor;
once->rates = tal_dup_talarr(once, struct feerate_est, rates);
io_break(ld->topology);
}
Expand Down Expand Up @@ -1572,7 +1579,8 @@ void setup_topology(struct chain_topology *topo)
chaininfo->ibd, topo, true);

/* It's very useful to have feerates early */
update_feerates(topo->ld, feerates->feerate_floor, feerates->rates, NULL);
update_feerates(topo->ld, feerates->feerate_floor,
feerates->relay_feerate_floor, feerates->rates, NULL);

/* Get the first block, so we can initialize topography. */
bitcoind_getrawblockbyheight(topo, topo->bitcoind, blockscan_start,
Expand Down
8 changes: 8 additions & 0 deletions lightningd/chaintopology.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ struct chain_topology {

/* This is the lowest feerate that bitcoind is saying will broadcast. */
u32 feerate_floor;
/* And the lowest we pay ourselves, so our rounding doesn't fall
* short of it (see feerate_relay_floor). */
u32 relay_feerate_floor;

/* We keep last three feerates we got: this is useful for min/max. */
struct feerate_est *feerates[FEE_HISTORY_NUM];
Expand Down Expand Up @@ -164,6 +167,11 @@ struct txlocator {
/* Get the minimum feerate that bitcoind will accept */
u32 get_feerate_floor(const struct chain_topology *topo);

/* Get the minimum feerate we use for our own transactions: a little above
* get_feerate_floor() when that is above 1 sat/vB. Use get_feerate_floor()
* for what we accept from a peer. */
u32 get_relay_feerate_floor(const struct chain_topology *topo);

/* This is the number of blocks which would have to be mined to invalidate
* the tx */
size_t get_tx_depth(const struct chain_topology *topo,
Expand Down
4 changes: 2 additions & 2 deletions lightningd/closing_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,8 +575,8 @@ void peer_start_closingd(struct channel *channel, struct peer_fd *peer_fd)
feerate = mutual_close_feerate(ld->topology);
if (!feerate) {
feerate = final_commit_feerate / 2;
if (feerate < get_feerate_floor(ld->topology))
feerate = get_feerate_floor(ld->topology);
if (feerate < get_relay_feerate_floor(ld->topology))
feerate = get_relay_feerate_floor(ld->topology);
}

max_feerate = calc_max_close_feerate(ld, channel);
Expand Down
4 changes: 2 additions & 2 deletions lightningd/dual_open_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -3357,7 +3357,7 @@ static struct command_result *openchannel_init(struct command *cmd,
/* 0 from this means "unknown" */
anchor_feerate = unilateral_feerate(cmd->ld->topology, true);
if (anchor_feerate == 0) {
anchor_feerate = get_feerate_floor(cmd->ld->topology);
anchor_feerate = get_relay_feerate_floor(cmd->ld->topology);
assert(anchor_feerate);
}

Expand Down Expand Up @@ -4227,7 +4227,7 @@ static struct command_result *json_queryrates(struct command *cmd,
/* 0 from this means "unknown" */
anchor_feerate = unilateral_feerate(cmd->ld->topology, true);
if (anchor_feerate == 0) {
anchor_feerate = get_feerate_floor(cmd->ld->topology);
anchor_feerate = get_relay_feerate_floor(cmd->ld->topology);
assert(anchor_feerate);
}

Expand Down
2 changes: 1 addition & 1 deletion lightningd/feerate.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static struct command_result *param_feerate_unchecked(struct command *cmd,
**feerate = feerate_for_deadline(cmd->ld->topology, 6);
return NULL;
} else if (json_tok_streq(buffer, tok, "minimum")) {
**feerate = get_feerate_floor(cmd->ld->topology);
**feerate = get_relay_feerate_floor(cmd->ld->topology);
return NULL;
}

Expand Down
4 changes: 2 additions & 2 deletions lightningd/onchain_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,8 +1014,8 @@ static struct bitcoin_tx *onchaind_tx_unsigned(const tal_t *ctx,
/* Hmm, can't afford with recommended fee. Try increasing deadline! */
block_target++;

/* If we can't even afford at FEERATE_FLOOR, something is wrong! */
if (feerate == FEERATE_FLOOR) {
/* If we can't even afford the floor, something is wrong! */
if (feerate == get_relay_feerate_floor(ld->topology)) {
amt = channel->our_config.dust_limit;
/* Not quite true, but Never Happens */
*fee = AMOUNT_SAT(0);
Expand Down
4 changes: 2 additions & 2 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1392,10 +1392,10 @@ static struct command_result *json_fundchannel_start(struct command *cmd,
"Cannot estimate fees");
}

if (*feerate_non_anchor < get_feerate_floor(cmd->ld->topology)) {
if (*feerate_non_anchor < get_relay_feerate_floor(cmd->ld->topology)) {
return command_fail(cmd, LIGHTNINGD,
"Feerate for non-anchor (%u perkw) below feerate floor %u perkw",
*feerate_non_anchor, get_feerate_floor(cmd->ld->topology));
*feerate_non_anchor, get_relay_feerate_floor(cmd->ld->topology));
}

peer = peer_by_id(cmd->ld, id);
Expand Down
6 changes: 3 additions & 3 deletions lightningd/test/run-jsonrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ void fatal(const char *fmt UNNEEDED, ...)
/* Generated stub for feerate_for_deadline */
u32 feerate_for_deadline(const struct chain_topology *topo UNNEEDED, u32 blockcount UNNEEDED)
{ fprintf(stderr, "feerate_for_deadline called!\n"); abort(); }
/* Generated stub for get_feerate_floor */
u32 get_feerate_floor(const struct chain_topology *topo UNNEEDED)
{ fprintf(stderr, "get_feerate_floor called!\n"); abort(); }
/* Generated stub for get_relay_feerate_floor */
u32 get_relay_feerate_floor(const struct chain_topology *topo UNNEEDED)
{ fprintf(stderr, "get_relay_feerate_floor called!\n"); abort(); }
/* Generated stub for hsm_secret_arg */
char *hsm_secret_arg(const tal_t *ctx UNNEEDED,
const char *arg UNNEEDED,
Expand Down
Loading
Loading