mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
bitcoind: Defer initialization of filteredblock_call->result
During sync it is highly likely that we can coalesce multiple calls and share results among them. We also report back failures for non-existing blocks early on, so we don't run into issues with blocks that our bitcoind doesn't have yet. Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
187e493ab8
commit
8b8538024d
@ -795,6 +795,7 @@ struct filteredblock_call {
|
|||||||
struct filteredblock_outpoint **outpoints;
|
struct filteredblock_outpoint **outpoints;
|
||||||
size_t current_outpoint;
|
size_t current_outpoint;
|
||||||
struct timeabs start_time;
|
struct timeabs start_time;
|
||||||
|
u32 height;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Declaration for recursion in process_getfilteredblock_step1 */
|
/* Declaration for recursion in process_getfilteredblock_step1 */
|
||||||
@ -831,6 +832,12 @@ static void process_getfilteredblock_step2(struct bitcoind *bitcoind,
|
|||||||
{
|
{
|
||||||
struct filteredblock_outpoint *o;
|
struct filteredblock_outpoint *o;
|
||||||
struct bitcoin_tx *tx;
|
struct bitcoin_tx *tx;
|
||||||
|
|
||||||
|
/* If for some reason we couldn't get the block, just report a
|
||||||
|
* failure. */
|
||||||
|
if (block == NULL)
|
||||||
|
return process_getfiltered_block_final(bitcoind, call);
|
||||||
|
|
||||||
call->result->prev_hash = block->hdr.prev_hash;
|
call->result->prev_hash = block->hdr.prev_hash;
|
||||||
|
|
||||||
/* Allocate an array containing all the potentially interesting
|
/* Allocate an array containing all the potentially interesting
|
||||||
@ -876,7 +883,16 @@ static void process_getfilteredblock_step1(struct bitcoind *bitcoind,
|
|||||||
const struct bitcoin_blkid *blkid,
|
const struct bitcoin_blkid *blkid,
|
||||||
struct filteredblock_call *call)
|
struct filteredblock_call *call)
|
||||||
{
|
{
|
||||||
|
/* If we were unable to fetch the block hash (bitcoind doesn't know
|
||||||
|
* about a block at that height), we can short-circuit and just call
|
||||||
|
* the callback. */
|
||||||
|
if (!blkid)
|
||||||
|
return process_getfiltered_block_final(bitcoind, call);
|
||||||
|
|
||||||
/* So we have the first piece of the puzzle, the block hash */
|
/* So we have the first piece of the puzzle, the block hash */
|
||||||
|
call->result = tal(call, struct filteredblock);
|
||||||
|
call->result->height = call->height;
|
||||||
|
call->result->outpoints = tal_arr(call->result, struct filteredblock_outpoint *, 0);
|
||||||
call->result->id = *blkid;
|
call->result->id = *blkid;
|
||||||
|
|
||||||
/* Now get the raw block to get all outpoints that were created in
|
/* Now get the raw block to get all outpoints that were created in
|
||||||
@ -891,11 +907,15 @@ process_getfiltered_block_final(struct bitcoind *bitcoind,
|
|||||||
const struct filteredblock_call *call)
|
const struct filteredblock_call *call)
|
||||||
{
|
{
|
||||||
struct filteredblock_call *c, *next;
|
struct filteredblock_call *c, *next;
|
||||||
u32 height = call->result->height;
|
u32 height = call->height;
|
||||||
|
|
||||||
|
if (call->result == NULL)
|
||||||
|
goto next;
|
||||||
|
|
||||||
/* Need to steal so we don't accidentally free it while iterating through the list below. */
|
/* Need to steal so we don't accidentally free it while iterating through the list below. */
|
||||||
struct filteredblock *fb = tal_steal(NULL, call->result);
|
struct filteredblock *fb = tal_steal(NULL, call->result);
|
||||||
list_for_each_safe(&bitcoind->pending_getfilteredblock, c, next, list) {
|
list_for_each_safe(&bitcoind->pending_getfilteredblock, c, next, list) {
|
||||||
if (c->result->height == height) {
|
if (c->height == height) {
|
||||||
c->cb(bitcoind, fb, c->arg);
|
c->cb(bitcoind, fb, c->arg);
|
||||||
list_del(&c->list);
|
list_del(&c->list);
|
||||||
tal_free(c);
|
tal_free(c);
|
||||||
@ -903,12 +923,13 @@ process_getfiltered_block_final(struct bitcoind *bitcoind,
|
|||||||
}
|
}
|
||||||
tal_free(fb);
|
tal_free(fb);
|
||||||
|
|
||||||
|
next:
|
||||||
/* Nothing to free here, since `*call` was already deleted during the
|
/* Nothing to free here, since `*call` was already deleted during the
|
||||||
* iteration above. It was also removed from the list, so no need to
|
* iteration above. It was also removed from the list, so no need to
|
||||||
* pop here. */
|
* pop here. */
|
||||||
if (!list_empty(&bitcoind->pending_getfilteredblock)) {
|
if (!list_empty(&bitcoind->pending_getfilteredblock)) {
|
||||||
c = list_top(&bitcoind->pending_getfilteredblock, struct filteredblock_call, list);
|
c = list_top(&bitcoind->pending_getfilteredblock, struct filteredblock_call, list);
|
||||||
bitcoind_getblockhash(bitcoind, c->result->height, process_getfilteredblock_step1, c);
|
bitcoind_getblockhash(bitcoind, c->height, process_getfilteredblock_step1, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,11 +946,10 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
|
|||||||
bool start = list_empty(&bitcoind->pending_getfilteredblock);
|
bool start = list_empty(&bitcoind->pending_getfilteredblock);
|
||||||
call->cb = cb;
|
call->cb = cb;
|
||||||
call->arg = arg;
|
call->arg = arg;
|
||||||
call->result = tal(call, struct filteredblock);
|
call->height = height;
|
||||||
assert(call->cb != NULL);
|
assert(call->cb != NULL);
|
||||||
call->start_time = time_now();
|
call->start_time = time_now();
|
||||||
call->result->height = height;
|
call->result = NULL;
|
||||||
call->result->outpoints = tal_arr(call->result, struct filteredblock_outpoint *, 0);
|
|
||||||
call->current_outpoint = 0;
|
call->current_outpoint = 0;
|
||||||
|
|
||||||
list_add_tail(&bitcoind->pending_getfilteredblock, &call->list);
|
list_add_tail(&bitcoind->pending_getfilteredblock, &call->list);
|
||||||
|
@ -66,6 +66,11 @@ static void got_filteredblock(struct bitcoind *bitcoind,
|
|||||||
struct filteredblock_outpoint *fbo = NULL, *o;
|
struct filteredblock_outpoint *fbo = NULL, *o;
|
||||||
struct bitcoin_tx_output txo;
|
struct bitcoin_tx_output txo;
|
||||||
|
|
||||||
|
/* If we failed to the filtered block we report the failure to
|
||||||
|
* got_txout. */
|
||||||
|
if (fb == NULL)
|
||||||
|
return got_txout(bitcoind, NULL, scid);
|
||||||
|
|
||||||
/* Only fill in blocks that we are not going to scan later. */
|
/* Only fill in blocks that we are not going to scan later. */
|
||||||
if (bitcoind->ld->topology->max_blockheight > fb->height)
|
if (bitcoind->ld->topology->max_blockheight > fb->height)
|
||||||
wallet_filteredblock_add(bitcoind->ld->wallet, fb);
|
wallet_filteredblock_add(bitcoind->ld->wallet, fb);
|
||||||
|
@ -1319,7 +1319,6 @@ def test_gossip_store_compact_on_load(node_factory, bitcoind):
|
|||||||
wait_for(lambda: l2.daemon.is_in_log(r'gossip_store: Read 1/4/2/0 cannounce/cupdate/nannounce/cdelete from store \(0 deleted\) in 1446 bytes'))
|
wait_for(lambda: l2.daemon.is_in_log(r'gossip_store: Read 1/4/2/0 cannounce/cupdate/nannounce/cdelete from store \(0 deleted\) in 1446 bytes'))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(strict=True)
|
|
||||||
def test_gossip_announce_invalid_block(node_factory, bitcoind):
|
def test_gossip_announce_invalid_block(node_factory, bitcoind):
|
||||||
"""bitcoind lags and we might get an announcement for a block we don't have.
|
"""bitcoind lags and we might get an announcement for a block we don't have.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user