Skip to content

Commit

Permalink
chaintopology: set a fee floor to avoid creating unrelayable txs.
Browse files Browse the repository at this point in the history
Naively, this would be 250 satoshi per sipa, but it's not since bitcoind's
fee calculation was not rewritten to deal with weight, but instead bolted
on using vbytes.

The resulting calculations made me cry; I dried my tears on the thorns
of BUILD_ASSERT (I know that makes no sense, but bear with me here as I'm
trying not to swear at my bitcoind colleagues right now).

Fixes: ElementsProject#1194
Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell authored and cdecker committed Mar 20, 2018
1 parent 044705a commit 2e687b9
Showing 1 changed file with 50 additions and 3 deletions.
53 changes: 50 additions & 3 deletions lightningd/chaintopology.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,48 @@ static const char *feerate_name(enum feerate feerate)
/* Mutual recursion via timer. */
static void next_updatefee_timer(struct chain_topology *topo);

/* bitcoind considers 250 satoshi per kw to be the minimum acceptable fee:
* less than this won't even relay.
*/
#define BITCOIND_MINRELAYTXFEE_PER_KW 250
/*
* But bitcoind uses vbytes (ie. (weight + 3) / 4) for this
* calculation, rather than weight, meaning we can disagree since we do
* it sanely (as specified in BOLT #3).
*/
#define FEERATE_BITCOIND_SEES(feerate, weight) \
(((feerate) * (weight)) / 1000 * 1000 / ((weight) + 3))
/* ie. fee = (feerate * weight) // 1000
* bitcoind needs (worst-case): fee * 1000 / (weight + 3) >= 4000
*
* (feerate * weight) // 1000 * 1000 // (weight + 3) >= 4000
*
* The feerate needs to be higher for lower weight, and our minimum tx weight
* is 464 (version (4) + count_tx_in (1) + tx_in (32 + 4 + 1 + 4) +
* count_tx_out (1) + amount (8) + P2WSH (1 + 1 + 32) + witness 1 + 1 + <sig>
* + 1 + <key>). Assume it's 400 to give a significant safety margin (it
* only makes 1 difference in the result anyway).
*/
#define MINIMUM_TX_WEIGHT 400
/*
* This formula is satisfied by a feerate of 4030 (hand-search).
*/
#define FEERATE_FLOOR 253
static u32 feerate_floor(void)
{
/* Assert that bitcoind will see this as above minRelayTxFee */
BUILD_ASSERT(FEERATE_BITCOIND_SEES(FEERATE_FLOOR, MINIMUM_TX_WEIGHT)
>= BITCOIND_MINRELAYTXFEE_PER_KW);
/* And a lesser value won't do */
BUILD_ASSERT(FEERATE_BITCOIND_SEES(FEERATE_FLOOR-1, MINIMUM_TX_WEIGHT)
< BITCOIND_MINRELAYTXFEE_PER_KW);
/* And I'm right about it being OK for larger txs, too */
BUILD_ASSERT(FEERATE_BITCOIND_SEES(FEERATE_FLOOR, (MINIMUM_TX_WEIGHT*2))
>= BITCOIND_MINRELAYTXFEE_PER_KW);

return FEERATE_FLOOR;
}

/* We sanitize feerates if necessary to put them in descending order. */
static void update_feerates(struct bitcoind *bitcoind,
const u32 *satoshi_per_kw,
Expand All @@ -277,12 +319,17 @@ static void update_feerates(struct bitcoind *bitcoind,
bool changed = false;

for (size_t i = 0; i < NUM_FEERATES; i++) {
if (satoshi_per_kw[i] != topo->feerate[i])
u32 feerate = satoshi_per_kw[i];

if (feerate < feerate_floor())
feerate = feerate_floor();

if (feerate != topo->feerate[i])
log_debug(topo->log, "%s feerate %u (was %u)",
feerate_name(i),
satoshi_per_kw[i], topo->feerate[i]);
feerate, topo->feerate[i]);
old_feerates[i] = topo->feerate[i];
topo->feerate[i] = satoshi_per_kw[i];
topo->feerate[i] = feerate;
}

for (size_t i = 0; i < NUM_FEERATES; i++) {
Expand Down

0 comments on commit 2e687b9

Please sign in to comment.