chain: fix peer selection for the pruned block dispatcher
In this commit, we fix the peer selection for the pruned block dispatcher. Turns out that the bits are actually mutually exclusive: a node can set the network bit _and_ the limited (pruned bit). The prior logic would only seek out "pure" nodes, meaning older nodes that wouldn't set the limited bit when they're a full-full node. We fix this by ignoring the limited bit, and we'll only look at the network and segwit bits. A unit test has also been added to show the issue in the prior filter function.
This commit is contained in:
parent
b4e83b1f8c
commit
6eede89a43
2 changed files with 42 additions and 3 deletions
|
@ -417,10 +417,12 @@ func filterNodeAddrs(nodeAddrs []btcjson.GetNodeAddressesResult) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// satisfiesRequiredServices determines whether the services signaled by a peer
|
// satisfiesRequiredServices determines whether the services signaled by a peer
|
||||||
// satisfy our requirements for retrieving pruned blocks from them.
|
// satisfy our requirements for retrieving pruned blocks from them. We need the
|
||||||
|
// full chain, and witness data as well. Note that we ignore the limited
|
||||||
|
// (pruned bit) as nodes can have the full data and set that as well. Pure
|
||||||
|
// pruned nodes won't set the network bit.
|
||||||
func satisfiesRequiredServices(services wire.ServiceFlag) bool {
|
func satisfiesRequiredServices(services wire.ServiceFlag) bool {
|
||||||
return services&requiredServices == requiredServices &&
|
return services&requiredServices == requiredServices
|
||||||
services&prunedNodeService != prunedNodeService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newQueryPeer creates a new peer instance configured to relay any received
|
// newQueryPeer creates a new peer instance configured to relay any received
|
||||||
|
|
|
@ -620,3 +620,40 @@ func TestPrunedBlockDispatcherInvalidBlock(t *testing.T) {
|
||||||
h.assertPeerQueried()
|
h.assertPeerQueried()
|
||||||
h.assertPeerReplied(blockChan, errChan, true)
|
h.assertPeerReplied(blockChan, errChan, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSatisfiesRequiredServices(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
services wire.ServiceFlag
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "full node, segwit",
|
||||||
|
services: wire.SFNodeWitness | wire.SFNodeNetwork,
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "full node segwit, signals limited",
|
||||||
|
services: wire.SFNodeWitness | wire.SFNodeNetwork | prunedNodeService,
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "full node, no segwit",
|
||||||
|
services: wire.SFNodeNetwork,
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "segwit, pure pruned",
|
||||||
|
services: wire.SFNodeWitness | prunedNodeService,
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
ok := satisfiesRequiredServices(testCase.services)
|
||||||
|
require.Equal(
|
||||||
|
t, testCase.ok, ok, fmt.Sprintf("test case: %v", testCase.name),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue