chaintopology: only report active chaintip.

getchaintips returns tips even if we don't have the body for them, so
we need to look for the active tip, not just the first (most-work) one.

Here's what happens in the log:

	+2849.963414597 lightningd(26779):BROKEN: bitcoin-cli getblock 0000000000000000018626ff7160bdf38a602e6650bd04ec258759ea578b106d false exited 91: 'error code: -32603
	error message:
	Can't read block from disk
	'

And here's an example problematic getchaintips output:

[
  {
    "height": 419635,
    "hash": "0000000000000000000fd32d87fce19efb7ccd07aa4ddaf1b94b9a219deec0f9",
    "branchlen": 1,
    "status": "headers-only"
  }, 
  {
    "height": 419634,
    "hash": "000000000000000002988d6512719697147cf252b2f64d247cf229266615d2bb",
    "branchlen": 0,
    "status": "active"
  }, 
  {
    "height": 416372,
    "hash": "0000000000000000004d0a54341c992ae174a91c8dd3981a9f2b3d3f6221ba59",
    "branchlen": 1,
    "status": "valid-headers"
  }, 
  {
    "height": 416231,
    "hash": "0000000000000000044d0d2c25f33cb48931540366149cde3fb0154f55b58c76",
    "branchlen": 1,
    "status": "headers-only"
  }
]

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-07-07 13:36:39 +09:30
parent 78174a09e2
commit df4df8679d
3 changed files with 51 additions and 33 deletions

View File

@ -248,9 +248,9 @@ static void process_chaintips(struct bitcoin_cli *bcli)
const jsmntok_t *tokens, *t, *end;
bool valid;
size_t i;
struct sha256_double *tips;
struct sha256_double tip;
void (*cb)(struct lightningd_state *dstate,
struct sha256_double *blockids,
struct sha256_double *tipid,
void *arg) = bcli->cb;
log_debug(bcli->dstate->base_log, "Got getchaintips result");
@ -266,30 +266,48 @@ static void process_chaintips(struct bitcoin_cli *bcli)
bcli_args(bcli),
(int)bcli->output_bytes, bcli->output);
tips = tal_arr(bcli, struct sha256_double, 0);
valid = false;
end = json_next(tokens);
for (i = 0, t = tokens + 1; t < end; t = json_next(t), i++) {
const jsmntok_t *status = json_get_member(bcli->output, t, "status");
const jsmntok_t *hash = json_get_member(bcli->output, t, "hash");
tal_resize(&tips, i+1);
if (!json_tok_streq(bcli->output, status, "active")) {
log_debug(bcli->dstate->base_log,
"Ignoring chaintip %.*s status %.*s",
hash->end - hash->start,
bcli->output + hash->start,
status->end - status->start,
bcli->output + status->start);
continue;
}
if (valid) {
log_unusual(bcli->dstate->base_log,
"%s: Two active chaintips? %.*s",
bcli_args(bcli),
(int)bcli->output_bytes, bcli->output);
continue;
}
if (!bitcoin_blkid_from_hex(bcli->output + hash->start,
hash->end - hash->start,
&tips[i]))
&tip))
fatal("%s: gave bad hash for %zu'th tip (%.*s)?",
bcli_args(bcli), i,
(int)bcli->output_bytes, bcli->output);
valid = true;
}
if (i == 0)
fatal("%s: gave empty array (%.*s)?",
if (!valid)
fatal("%s: gave no active chaintips (%.*s)?",
bcli_args(bcli), (int)bcli->output_bytes, bcli->output);
cb(bcli->dstate, tips, bcli->cb_arg);
cb(bcli->dstate, &tip, bcli->cb_arg);
}
void bitcoind_get_chaintips_(struct lightningd_state *dstate,
void (*cb)(struct lightningd_state *dstate,
struct sha256_double *blockids,
void *arg),
void *arg)
void bitcoind_get_chaintip_(struct lightningd_state *dstate,
void (*cb)(struct lightningd_state *dstate,
const struct sha256_double *tipid,
void *arg),
void *arg)
{
start_bitcoin_cli(dstate, process_chaintips, false, cb, arg,
"getchaintips", NULL);

View File

@ -41,19 +41,19 @@ void bitcoind_sendrawtx_(struct lightningd_state *dstate,
const char *), \
(arg))
void bitcoind_get_chaintips_(struct lightningd_state *dstate,
void bitcoind_get_chaintip_(struct lightningd_state *dstate,
void (*cb)(struct lightningd_state *dstate,
struct sha256_double *blockids,
const struct sha256_double *tipid,
void *arg),
void *arg);
#define bitcoind_get_chaintips(dstate, cb, arg) \
bitcoind_get_chaintips_((dstate), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct lightningd_state *, \
struct sha256_double *), \
(arg))
#define bitcoind_get_chaintip(dstate, cb, arg) \
bitcoind_get_chaintip_((dstate), \
typesafe_cb_preargs(void, void *, \
(cb), (arg), \
struct lightningd_state *, \
const struct sha256_double *), \
(arg))
void bitcoind_getblockcount_(struct lightningd_state *dstate,
void (*cb)(struct lightningd_state *dstate,

View File

@ -63,12 +63,12 @@ struct topology {
struct block_map block_map;
};
static void start_poll_chaintips(struct lightningd_state *dstate);
static void start_poll_chaintip(struct lightningd_state *dstate);
static void next_topology_timer(struct lightningd_state *dstate)
{
new_reltimer(dstate, dstate, dstate->config.poll_time,
start_poll_chaintips, dstate);
start_poll_chaintip, dstate);
}
static int cmp_times(const u32 *a, const u32 *b, void *unused)
@ -374,29 +374,29 @@ static void gather_blocks(struct lightningd_state *dstate,
next_topology_timer(dstate);
}
static void check_chaintips(struct lightningd_state *dstate,
struct sha256_double *blockids,
void *arg)
static void check_chaintip(struct lightningd_state *dstate,
const struct sha256_double *tipid,
void *arg)
{
struct topology *topo = dstate->topology;
/* 0 is the main tip. */
if (!topo->tip || !structeq(&blockids[0], &topo->tip->blkid))
bitcoind_getrawblock(dstate, &blockids[0], gather_blocks,
if (!topo->tip || !structeq(tipid, &topo->tip->blkid))
bitcoind_getrawblock(dstate, tipid, gather_blocks,
(struct block *)NULL);
else
/* Next! */
next_topology_timer(dstate);
}
static void start_poll_chaintips(struct lightningd_state *dstate)
static void start_poll_chaintip(struct lightningd_state *dstate)
{
if (!list_empty(&dstate->bitcoin_req)) {
log_unusual(dstate->base_log,
"Delaying start poll: commands in progress");
next_topology_timer(dstate);
} else
bitcoind_get_chaintips(dstate, check_chaintips, NULL);
bitcoind_get_chaintip(dstate, check_chaintip, NULL);
}
static void init_topo(struct lightningd_state *dstate,
@ -409,8 +409,8 @@ static void init_topo(struct lightningd_state *dstate,
topo->root->height = ptr2int(p);
block_map_add(&topo->block_map, topo->root);
/* Now grab chaintips immediately. */
bitcoind_get_chaintips(dstate, check_chaintips, NULL);
/* Now grab chaintip immediately. */
bitcoind_get_chaintip(dstate, check_chaintip, NULL);
}
static void get_init_block(struct lightningd_state *dstate,