mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-06 07:34:21 +01:00
chaintopology: track three different feerates.
Depending on what we're doing, we can want different ones. So use IMMEDIATE (estimatesmartfee 2 CONSERVATIVE), NORMAL (estimatesmartfee 4 ECONOMICAL) and SLOW (estimatesmartfee 100 ECONOMICAL). If one isn't available, we try making each one half the previous. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
ef4d54df94
commit
7151c65535
@@ -8,6 +8,7 @@
|
||||
#include "watch.h"
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
@@ -291,12 +292,36 @@ static void free_blocks(struct chain_topology *topo, struct block *b)
|
||||
}
|
||||
}
|
||||
|
||||
static void update_fee(struct bitcoind *bitcoind, u64 satoshi_per_kw,
|
||||
struct chain_topology *topo)
|
||||
static const char *feerate_name(enum feerate feerate)
|
||||
{
|
||||
log_debug(topo->log, "Feerate %"PRIu64" (was %"PRIu64")",
|
||||
satoshi_per_kw, topo->feerate);
|
||||
topo->feerate = satoshi_per_kw;
|
||||
return feerate == FEERATE_IMMEDIATE ? "Immediate"
|
||||
: feerate == FEERATE_NORMAL ? "Normal" : "Slow";
|
||||
}
|
||||
|
||||
/* We sanitize feerates if necessary to put them in descending order. */
|
||||
static void update_feerates(struct bitcoind *bitcoind,
|
||||
const u64 *satoshi_per_kw,
|
||||
struct chain_topology *topo)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_FEERATES; i++) {
|
||||
log_debug(topo->log, "%s feerate %"PRIu64" (was %"PRIu64")",
|
||||
feerate_name(i),
|
||||
satoshi_per_kw[i], topo->feerate[i]);
|
||||
topo->feerate[i] = satoshi_per_kw[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NUM_FEERATES; i++) {
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
if (topo->feerate[j] < topo->feerate[i]) {
|
||||
log_unusual(topo->log,
|
||||
"Feerate %s (%"PRIu64") above"
|
||||
" %s (%"PRIu64")",
|
||||
feerate_name(i), topo->feerate[i],
|
||||
feerate_name(j), topo->feerate[j]);
|
||||
topo->feerate[j] = topo->feerate[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* B is the new chain (linked by ->next); update topology */
|
||||
@@ -304,6 +329,12 @@ static void topology_changed(struct chain_topology *topo,
|
||||
struct block *prev,
|
||||
struct block *b)
|
||||
{
|
||||
/* FEERATE_IMMEDIATE, FEERATE_NORMAL, FEERATE_SLOW */
|
||||
const char *estmodes[] = { "CONSERVATIVE", "ECONOMICAL", "ECONOMICAL" };
|
||||
const u32 blocks[] = { 2, 4, 100 };
|
||||
|
||||
BUILD_ASSERT(ARRAY_SIZE(blocks) == NUM_FEERATES);
|
||||
|
||||
/* Eliminate any old chain. */
|
||||
if (prev->next)
|
||||
free_blocks(topo, prev->next);
|
||||
@@ -321,8 +352,9 @@ static void topology_changed(struct chain_topology *topo,
|
||||
/* Maybe need to rebroadcast. */
|
||||
rebroadcast_txs(topo, NULL);
|
||||
|
||||
/* Once per new block head, update fee estimate. */
|
||||
bitcoind_estimate_fee(topo->bitcoind, update_fee, topo);
|
||||
/* Once per new block head, update fee estimates. */
|
||||
bitcoind_estimate_fees(topo->bitcoind, blocks, estmodes, NUM_FEERATES,
|
||||
update_feerates, topo);
|
||||
}
|
||||
|
||||
static struct block *new_block(struct chain_topology *topo,
|
||||
@@ -453,17 +485,43 @@ u32 get_block_height(const struct chain_topology *topo)
|
||||
return topo->tip->height;
|
||||
}
|
||||
|
||||
u64 get_feerate(const struct chain_topology *topo)
|
||||
/* We may only have estimate for 2 blocks, for example. Extrapolate. */
|
||||
static u64 guess_feerate(const struct chain_topology *topo, enum feerate feerate)
|
||||
{
|
||||
size_t i = 0;
|
||||
u64 rate = 0;
|
||||
|
||||
/* We assume each one is half the previous. */
|
||||
for (i = 0; i < feerate; i++) {
|
||||
if (topo->feerate[i]) {
|
||||
log_info(topo->log,
|
||||
"No fee estimate for %s: basing on %s rate",
|
||||
feerate_name(feerate),
|
||||
feerate_name(i));
|
||||
rate = topo->feerate[i];
|
||||
}
|
||||
rate /= 2;
|
||||
}
|
||||
|
||||
if (rate == 0) {
|
||||
rate = topo->default_fee_rate >> feerate;
|
||||
log_info(topo->log,
|
||||
"No fee estimate for %s: basing on default fee rate",
|
||||
feerate_name(feerate));
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
u64 get_feerate(const struct chain_topology *topo, enum feerate feerate)
|
||||
{
|
||||
if (topo->override_fee_rate) {
|
||||
log_debug(topo->log, "Forcing fee rate, ignoring estimate");
|
||||
return topo->override_fee_rate;
|
||||
} else if (topo->feerate[feerate] == 0) {
|
||||
return guess_feerate(topo, feerate);
|
||||
}
|
||||
else if (topo->feerate == 0) {
|
||||
log_info(topo->log, "No fee estimate: using default fee rate");
|
||||
return topo->default_fee_rate;
|
||||
}
|
||||
return topo->feerate;
|
||||
return topo->feerate[feerate];
|
||||
}
|
||||
|
||||
struct txlocator *locate_tx(const void *ctx, const struct chain_topology *topo,
|
||||
@@ -575,7 +633,7 @@ void setup_topology(struct chain_topology *topo,
|
||||
struct timerel poll_time, u32 first_peer_block)
|
||||
{
|
||||
topo->startup = true;
|
||||
topo->feerate = 0;
|
||||
memset(&topo->feerate, 0, sizeof(topo->feerate));
|
||||
topo->timers = timers;
|
||||
topo->poll_time = poll_time;
|
||||
topo->first_blocknum = first_peer_block;
|
||||
|
||||
Reference in New Issue
Block a user