mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
bitcoind: getchaintips support.
This allows us to sae the block topology in detail. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -453,7 +453,7 @@ void bitcoind_send_tx(struct lightningd_state *dstate,
|
||||
tal_free(raw);
|
||||
}
|
||||
|
||||
static void process_getblock(struct bitcoin_cli *bcli)
|
||||
static void process_getblock_for_mediantime(struct bitcoin_cli *bcli)
|
||||
{
|
||||
const jsmntok_t *tokens, *mediantime;
|
||||
bool valid;
|
||||
@@ -496,10 +496,259 @@ void bitcoind_get_mediantime(struct lightningd_state *dstate,
|
||||
char hex[hex_str_size(sizeof(*blockid))];
|
||||
|
||||
hex_encode(blockid, sizeof(*blockid), hex, sizeof(hex));
|
||||
start_bitcoin_cli(dstate, process_getblock, NULL, mediantime,
|
||||
start_bitcoin_cli(dstate, process_getblock_for_mediantime,
|
||||
NULL, mediantime,
|
||||
"getblock", hex, NULL);
|
||||
}
|
||||
|
||||
static void process_chaintips(struct bitcoin_cli *bcli)
|
||||
{
|
||||
const jsmntok_t *tokens, *t, *end;
|
||||
bool valid;
|
||||
size_t i;
|
||||
struct sha256_double *tips;
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
struct sha256_double *blockids,
|
||||
void *arg) = bcli->cb;
|
||||
|
||||
log_debug(bcli->dstate->base_log, "Got getchaintips result");
|
||||
if (!bcli->output)
|
||||
fatal("%s failed", bcli_args(bcli));
|
||||
|
||||
tokens = json_parse_input(bcli->output, bcli->output_bytes, &valid);
|
||||
if (!tokens)
|
||||
fatal("%s: %s response",
|
||||
bcli_args(bcli),
|
||||
valid ? "partial" : "invalid");
|
||||
|
||||
if (tokens[0].type != JSMN_ARRAY)
|
||||
fatal("%s: gave non-array (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
tips = tal_arr(bcli, struct sha256_double, 0);
|
||||
end = json_next(tokens);
|
||||
for (i = 0, t = tokens + 1; t < end; t = json_next(t), i++) {
|
||||
const jsmntok_t *hash = json_get_member(bcli->output, t, "hash");
|
||||
tal_resize(&tips, i+1);
|
||||
if (!hex_decode(bcli->output + hash->start,
|
||||
hash->end - hash->start,
|
||||
&tips[i], sizeof(tips[i])))
|
||||
fatal("%s: gave bad hash for %zu'th tip (%.*s)?",
|
||||
bcli_args(bcli), i,
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
}
|
||||
if (i == 0)
|
||||
fatal("%s: gave empty array (%.*s)?",
|
||||
bcli_args(bcli), (int)bcli->output_bytes, bcli->output);
|
||||
|
||||
cb(bcli->dstate, tips, 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)
|
||||
{
|
||||
start_bitcoin_cli(dstate, process_chaintips, cb, arg,
|
||||
"getchaintips", NULL);
|
||||
}
|
||||
|
||||
static void process_getblock(struct bitcoin_cli *bcli)
|
||||
{
|
||||
const jsmntok_t *tokens, *prevblk_tok, *txs_tok,
|
||||
*mediantime_tok, *blkid_tok, *t, *end;
|
||||
bool valid;
|
||||
u32 mediantime;
|
||||
struct sha256_double *txids;
|
||||
struct sha256_double *prevblk, blkid;
|
||||
size_t i;
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
struct sha256_double *blkid,
|
||||
struct sha256_double *prevblock,
|
||||
struct sha256_double *txids,
|
||||
u32 mediantime,
|
||||
void *arg) = bcli->cb;
|
||||
|
||||
log_debug(bcli->dstate->base_log, "Got getblock result");
|
||||
if (!bcli->output)
|
||||
fatal("%s failed", bcli_args(bcli));
|
||||
|
||||
tokens = json_parse_input(bcli->output, bcli->output_bytes, &valid);
|
||||
if (!tokens)
|
||||
fatal("%s: %s response",
|
||||
bcli_args(bcli),
|
||||
valid ? "partial" : "invalid");
|
||||
|
||||
if (tokens[0].type != JSMN_OBJECT)
|
||||
fatal("%s: gave non-object (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
mediantime_tok = json_get_member(bcli->output, tokens, "mediantime");
|
||||
if (!mediantime_tok)
|
||||
fatal("%s: gave no mediantime field (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
if (!json_tok_number(bcli->output, mediantime_tok, &mediantime))
|
||||
fatal("%s: gave invalid mediantime (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
mediantime_tok->end - mediantime_tok->start,
|
||||
bcli->output + mediantime_tok->start);
|
||||
|
||||
/* Genesis block doesn't have this! */
|
||||
prevblk_tok = json_get_member(bcli->output, tokens, "previousblockhash");
|
||||
if (prevblk_tok) {
|
||||
prevblk = tal(bcli, struct sha256_double);
|
||||
if (!hex_decode(bcli->output + prevblk_tok->start,
|
||||
prevblk_tok->end - prevblk_tok->start,
|
||||
prevblk, sizeof(*prevblk))) {
|
||||
fatal("%s: bad previousblockhash '%.*s'",
|
||||
bcli_args(bcli),
|
||||
(int)(prevblk_tok->end - prevblk_tok->start),
|
||||
bcli->output + prevblk_tok->start);
|
||||
}
|
||||
} else
|
||||
prevblk = NULL;
|
||||
|
||||
blkid_tok = json_get_member(bcli->output, tokens, "hash");
|
||||
if (!blkid_tok)
|
||||
fatal("%s: gave no hash field (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
if (!hex_decode(bcli->output + blkid_tok->start,
|
||||
blkid_tok->end - blkid_tok->start,
|
||||
&blkid, sizeof(blkid))) {
|
||||
fatal("%s: bad hash '%.*s'",
|
||||
bcli_args(bcli),
|
||||
(int)(blkid_tok->end - blkid_tok->start),
|
||||
bcli->output + blkid_tok->start);
|
||||
}
|
||||
|
||||
txs_tok = json_get_member(bcli->output, tokens, "tx");
|
||||
if (!txs_tok)
|
||||
fatal("%s: gave no tx field (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
if (txs_tok->type != JSMN_ARRAY)
|
||||
fatal("%s: gave non-array txs field (%.*s)?",
|
||||
bcli_args(bcli),
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
|
||||
/* It's a flat array of strings, so we can just use tok->size here. */
|
||||
txids = tal_arr(bcli, struct sha256_double, txs_tok->size);
|
||||
end = json_next(txs_tok);
|
||||
for (i = 0, t = txs_tok + 1; t < end; t = json_next(t), i++) {
|
||||
assert(i < txs_tok->size);
|
||||
if (!bitcoin_txid_from_hex(bcli->output + t->start,
|
||||
t->end - t->start,
|
||||
&txids[i]))
|
||||
fatal("%s: gave bad txid for %zu'th tx (%.*s)?",
|
||||
bcli_args(bcli), i,
|
||||
(int)bcli->output_bytes, bcli->output);
|
||||
}
|
||||
/* We must have coinbase, at least! */
|
||||
if (i == 0)
|
||||
fatal("%s: gave empty txids array (%.*s)?",
|
||||
bcli_args(bcli), (int)bcli->output_bytes, bcli->output);
|
||||
|
||||
log_debug(bcli->dstate->base_log,
|
||||
"%.*s: mediantime = %u, prevhash=%.*s, %zu txids",
|
||||
(int)(blkid_tok->end - blkid_tok->start),
|
||||
bcli->output + blkid_tok->start,
|
||||
mediantime,
|
||||
prevblk_tok ? (int)(prevblk_tok->end - prevblk_tok->start) : 0,
|
||||
prevblk_tok ? bcli->output + prevblk_tok->start : NULL,
|
||||
i);
|
||||
|
||||
cb(bcli->dstate, &blkid, prevblk, txids, mediantime, bcli->cb_arg);
|
||||
}
|
||||
|
||||
void bitcoind_getblock_(struct lightningd_state *dstate,
|
||||
const struct sha256_double *blockid,
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
struct sha256_double *blkid,
|
||||
struct sha256_double *prevblock,
|
||||
struct sha256_double *txids,
|
||||
u32 mediantime,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
char hex[hex_str_size(sizeof(*blockid))];
|
||||
|
||||
hex_encode(blockid, sizeof(*blockid), hex, sizeof(hex));
|
||||
start_bitcoin_cli(dstate, process_getblock, cb, arg,
|
||||
"getblock", hex, NULL);
|
||||
}
|
||||
|
||||
static void process_getblockcount(struct bitcoin_cli *bcli)
|
||||
{
|
||||
u32 blockcount;
|
||||
char *p, *end;
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
u32 blockcount,
|
||||
void *arg) = bcli->cb;
|
||||
|
||||
if (!bcli->output)
|
||||
fatal("%s: failed", bcli_args(bcli));
|
||||
|
||||
p = tal_strndup(bcli, bcli->output, bcli->output_bytes);
|
||||
blockcount = strtol(p, &end, 10);
|
||||
if (end == p || *end != '\n')
|
||||
fatal("%s: gave non-numeric blockcount %s",
|
||||
bcli_args(bcli), p);
|
||||
|
||||
cb(bcli->dstate, blockcount, bcli->cb_arg);
|
||||
}
|
||||
|
||||
void bitcoind_getblockcount_(struct lightningd_state *dstate,
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
u32 blockcount,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
start_bitcoin_cli(dstate, process_getblockcount, cb, arg,
|
||||
"getblockcount", NULL);
|
||||
}
|
||||
|
||||
static void process_getblockhash(struct bitcoin_cli *bcli)
|
||||
{
|
||||
struct sha256_double blkid;
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
const struct sha256_double *blkid,
|
||||
void *arg) = bcli->cb;
|
||||
|
||||
if (!bcli->output)
|
||||
fatal("%s: failed", bcli_args(bcli));
|
||||
|
||||
if (bcli->output_bytes == 0
|
||||
|| !hex_decode(bcli->output, bcli->output_bytes-1,
|
||||
&blkid, sizeof(blkid))) {
|
||||
fatal("%s: bad blockid '%.*s'",
|
||||
bcli_args(bcli), (int)bcli->output_bytes, bcli->output);
|
||||
}
|
||||
|
||||
cb(bcli->dstate, &blkid, bcli->cb_arg);
|
||||
}
|
||||
|
||||
void bitcoind_getblockhash_(struct lightningd_state *dstate,
|
||||
u32 height,
|
||||
void (*cb)(struct lightningd_state *dstate,
|
||||
const struct sha256_double *blkid,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
char str[STR_MAX_CHARS(height)];
|
||||
sprintf(str, "%u", height);
|
||||
|
||||
start_bitcoin_cli(dstate, process_getblockhash, cb, arg,
|
||||
"getblockhash", str, NULL);
|
||||
}
|
||||
|
||||
/* Make testnet/regtest status matches us. */
|
||||
void check_bitcoind_config(struct lightningd_state *dstate)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user