Skip to content

Commit 8b85380

Browse files
cdeckerrustyrussell
authored andcommitted
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 <[email protected]>
1 parent 187e493 commit 8b85380

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

lightningd/bitcoind.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ struct filteredblock_call {
795795
struct filteredblock_outpoint **outpoints;
796796
size_t current_outpoint;
797797
struct timeabs start_time;
798+
u32 height;
798799
};
799800

800801
/* Declaration for recursion in process_getfilteredblock_step1 */
@@ -831,6 +832,12 @@ static void process_getfilteredblock_step2(struct bitcoind *bitcoind,
831832
{
832833
struct filteredblock_outpoint *o;
833834
struct bitcoin_tx *tx;
835+
836+
/* If for some reason we couldn't get the block, just report a
837+
* failure. */
838+
if (block == NULL)
839+
return process_getfiltered_block_final(bitcoind, call);
840+
834841
call->result->prev_hash = block->hdr.prev_hash;
835842

836843
/* Allocate an array containing all the potentially interesting
@@ -876,7 +883,16 @@ static void process_getfilteredblock_step1(struct bitcoind *bitcoind,
876883
const struct bitcoin_blkid *blkid,
877884
struct filteredblock_call *call)
878885
{
886+
/* If we were unable to fetch the block hash (bitcoind doesn't know
887+
* about a block at that height), we can short-circuit and just call
888+
* the callback. */
889+
if (!blkid)
890+
return process_getfiltered_block_final(bitcoind, call);
891+
879892
/* So we have the first piece of the puzzle, the block hash */
893+
call->result = tal(call, struct filteredblock);
894+
call->result->height = call->height;
895+
call->result->outpoints = tal_arr(call->result, struct filteredblock_outpoint *, 0);
880896
call->result->id = *blkid;
881897

882898
/* Now get the raw block to get all outpoints that were created in
@@ -891,24 +907,29 @@ process_getfiltered_block_final(struct bitcoind *bitcoind,
891907
const struct filteredblock_call *call)
892908
{
893909
struct filteredblock_call *c, *next;
894-
u32 height = call->result->height;
910+
u32 height = call->height;
911+
912+
if (call->result == NULL)
913+
goto next;
914+
895915
/* Need to steal so we don't accidentally free it while iterating through the list below. */
896916
struct filteredblock *fb = tal_steal(NULL, call->result);
897917
list_for_each_safe(&bitcoind->pending_getfilteredblock, c, next, list) {
898-
if (c->result->height == height) {
918+
if (c->height == height) {
899919
c->cb(bitcoind, fb, c->arg);
900920
list_del(&c->list);
901921
tal_free(c);
902922
}
903923
}
904924
tal_free(fb);
905925

926+
next:
906927
/* Nothing to free here, since `*call` was already deleted during the
907928
* iteration above. It was also removed from the list, so no need to
908929
* pop here. */
909930
if (!list_empty(&bitcoind->pending_getfilteredblock)) {
910931
c = list_top(&bitcoind->pending_getfilteredblock, struct filteredblock_call, list);
911-
bitcoind_getblockhash(bitcoind, c->result->height, process_getfilteredblock_step1, c);
932+
bitcoind_getblockhash(bitcoind, c->height, process_getfilteredblock_step1, c);
912933
}
913934
}
914935

@@ -925,11 +946,10 @@ void bitcoind_getfilteredblock_(struct bitcoind *bitcoind, u32 height,
925946
bool start = list_empty(&bitcoind->pending_getfilteredblock);
926947
call->cb = cb;
927948
call->arg = arg;
928-
call->result = tal(call, struct filteredblock);
949+
call->height = height;
929950
assert(call->cb != NULL);
930951
call->start_time = time_now();
931-
call->result->height = height;
932-
call->result->outpoints = tal_arr(call->result, struct filteredblock_outpoint *, 0);
952+
call->result = NULL;
933953
call->current_outpoint = 0;
934954

935955
list_add_tail(&bitcoind->pending_getfilteredblock, &call->list);

lightningd/gossip_control.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ static void got_filteredblock(struct bitcoind *bitcoind,
6666
struct filteredblock_outpoint *fbo = NULL, *o;
6767
struct bitcoin_tx_output txo;
6868

69+
/* If we failed to the filtered block we report the failure to
70+
* got_txout. */
71+
if (fb == NULL)
72+
return got_txout(bitcoind, NULL, scid);
73+
6974
/* Only fill in blocks that we are not going to scan later. */
7075
if (bitcoind->ld->topology->max_blockheight > fb->height)
7176
wallet_filteredblock_add(bitcoind->ld->wallet, fb);

tests/test_gossip.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,6 @@ def test_gossip_store_compact_on_load(node_factory, bitcoind):
13191319
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'))
13201320

13211321

1322-
@pytest.mark.xfail(strict=True)
13231322
def test_gossip_announce_invalid_block(node_factory, bitcoind):
13241323
"""bitcoind lags and we might get an announcement for a block we don't have.
13251324

0 commit comments

Comments
 (0)