Skip to content

Commit b61141e

Browse files
committed
bcli: don't try asking non-full nodes for blocks.
Suggested-by: @NicolasDorier Closes: #8078 Signed-off-by: Rusty Russell <[email protected]> Changelog-Changed: Protocol: we no longer try asking for blocks from bitcoind's peers if they don't store blocks.
1 parent 8e41ee4 commit b61141e

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

plugins/bcli.c

+14-5
Original file line numberDiff line numberDiff line change
@@ -626,11 +626,20 @@ static struct command_result *process_getpeerinfo(struct bitcoin_cli *bcli)
626626
json_for_each_arr(i, t, toks)
627627
{
628628
int id;
629-
if (json_scan(tmpctx, bcli->output, t, "{id:%}",
630-
JSON_SCAN(json_to_int, &id)) == NULL) {
631-
// fixme: future optimization: a) filter for full nodes,
632-
// b) sort by last ping
633-
tal_arr_expand(&stash->peers, id);
629+
u8 *services;
630+
631+
if (json_scan(tmpctx, bcli->output, t, "{id:%,services:%}",
632+
JSON_SCAN(json_to_int, &id),
633+
JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex, &services)) == NULL) {
634+
/* From bitcoin source:
635+
* // NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently
636+
* // set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light clients.
637+
* NODE_NETWORK = (1 << 0)
638+
*/
639+
if (tal_count(services) > 0 && (services[tal_count(services)-1] & (1<<0))) {
640+
// fixme: future optimization: sort by last ping
641+
tal_arr_expand(&stash->peers, id);
642+
}
634643
}
635644
}
636645

tests/test_misc.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,15 @@ def mock_getpeerinfo(r, error=False):
172172
"result": [
173173
{
174174
"id": 1,
175+
"services": "000000000000040d",
175176
},
176177
{
177178
"id": 2,
179+
"services": "0000000000000001",
178180
},
179181
{
180182
"id": 3,
183+
"services": "0000000000000000",
181184
},
182185
],
183186
}
@@ -210,10 +213,10 @@ def mock_getblockfrompeer_inner(r):
210213
l1.daemon.rpcproxy.mock_rpc("getblockfrompeer", mock_getblockfrompeer())
211214
l1.start(wait_for_bitcoind_sync=False)
212215

213-
# check that we fetched a block from a peer (1st peer (from the back) in this case).
216+
# check that we fetched a block from a peer (1st peer (from the back) in this case, but not from 3 which isn't a full node).
214217
pruned_block = bitcoind.rpc.getblockhash(bitcoind.rpc.getblockcount())
215218
l1.daemon.wait_for_log(f"failed to fetch block {pruned_block} from the bitcoin backend")
216-
l1.daemon.wait_for_log(rf"try to fetch block {pruned_block} from peer 3")
219+
l1.daemon.wait_for_log(rf"try to fetch block {pruned_block} from peer 2")
217220
l1.daemon.wait_for_log(rf"Adding block (\d+): {pruned_block}")
218221

219222
# check that we can also fetch from a peer > 1st (from the back).
@@ -222,8 +225,8 @@ def mock_getblockfrompeer_inner(r):
222225

223226
pruned_block = bitcoind.rpc.getblockhash(bitcoind.rpc.getblockcount())
224227
l1.daemon.wait_for_log(f"failed to fetch block {pruned_block} from the bitcoin backend")
225-
l1.daemon.wait_for_log(rf"failed to fetch block {pruned_block} from peer 3")
226-
l1.daemon.wait_for_log(rf"try to fetch block {pruned_block} from peer (\d+)")
228+
l1.daemon.wait_for_log(rf"failed to fetch block {pruned_block} from peer 2")
229+
l1.daemon.wait_for_log(rf"try to fetch block {pruned_block} from peer 1")
227230
l1.daemon.wait_for_log(rf"Adding block (\d+): {pruned_block}")
228231

229232
# check that we retry if we could not fetch any block

0 commit comments

Comments
 (0)