Skip to content

Commit 0d5303f

Browse files
committed
network: don't send VP in MOI messages if unsupposrted by remote peer
1 parent 4cb92b8 commit 0d5303f

File tree

2 files changed

+103
-4
lines changed

2 files changed

+103
-4
lines changed

network/wsNetwork.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,13 +1186,34 @@ func (wn *WebsocketNetwork) maybeSendMessagesOfInterest(peer *wsPeer, messagesOf
11861186
messagesOfInterestGeneration := wn.messagesOfInterestGeneration.Load()
11871187
peerMessagesOfInterestGeneration := peer.messagesOfInterestGeneration.Load()
11881188
if peerMessagesOfInterestGeneration != messagesOfInterestGeneration {
1189-
if messagesOfInterestEnc == nil {
1189+
peerSupportsStatefulCompression := peer.vpackStatefulCompressionSupported()
1190+
sendEnc := messagesOfInterestEnc
1191+
var perPeerTags map[protocol.Tag]bool
1192+
if sendEnc == nil || !peerSupportsStatefulCompression {
11901193
wn.messagesOfInterestMu.Lock()
1191-
messagesOfInterestEnc = wn.messagesOfInterestEnc
1194+
if sendEnc == nil {
1195+
sendEnc = wn.messagesOfInterestEnc
1196+
}
1197+
if !peerSupportsStatefulCompression {
1198+
// Filter VP tag for peers lacking stateful compression support; older nodes (<= v4.3)
1199+
// treat unknown tags as protocol violations and disconnect.
1200+
if wn.messagesOfInterest[protocol.VotePackedTag] {
1201+
perPeerTags = make(map[protocol.Tag]bool, len(wn.messagesOfInterest))
1202+
for tag, flag := range wn.messagesOfInterest {
1203+
if tag == protocol.VotePackedTag {
1204+
continue
1205+
}
1206+
perPeerTags[tag] = flag
1207+
}
1208+
}
1209+
}
11921210
wn.messagesOfInterestMu.Unlock()
11931211
}
1194-
if messagesOfInterestEnc != nil {
1195-
peer.sendMessagesOfInterest(messagesOfInterestGeneration, messagesOfInterestEnc)
1212+
if perPeerTags != nil {
1213+
sendEnc = marshallMessageOfInterestMap(perPeerTags)
1214+
}
1215+
if sendEnc != nil {
1216+
peer.sendMessagesOfInterest(messagesOfInterestGeneration, sendEnc)
11961217
} else {
11971218
wn.log.Infof("msgOfInterest Enc=nil, MOIGen=%d", messagesOfInterestGeneration)
11981219
}

network/wsNetwork_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4773,3 +4773,81 @@ func TestPeerComparisonInBroadcast(t *testing.T) {
47734773
require.Equal(t, 1, len(testPeer.sendBufferBulk))
47744774
require.Equal(t, 0, len(exceptPeer.sendBufferBulk))
47754775
}
4776+
4777+
func TestMaybeSendMessagesOfInterestLegacyPeer(t *testing.T) {
4778+
t.Parallel()
4779+
4780+
wn := &WebsocketNetwork{
4781+
log: logging.TestingLog(t),
4782+
}
4783+
wn.messagesOfInterestGeneration.Store(1)
4784+
wn.messagesOfInterest = map[protocol.Tag]bool{
4785+
protocol.AgreementVoteTag: true,
4786+
protocol.VotePackedTag: true,
4787+
}
4788+
wn.messagesOfInterestEnc = marshallMessageOfInterestMap(wn.messagesOfInterest)
4789+
4790+
makePeer := func(features peerFeatureFlag) (*wsPeer, chan sendMessage) {
4791+
ch := make(chan sendMessage, 1)
4792+
return &wsPeer{
4793+
log: logging.TestingLog(t),
4794+
features: features,
4795+
sendBufferHighPrio: ch,
4796+
sendBufferBulk: make(chan sendMessage, 1),
4797+
closing: make(chan struct{}),
4798+
netCtx: context.Background(),
4799+
}, ch
4800+
}
4801+
4802+
t.Run("drops VP for peers without stateful support", func(t *testing.T) {
4803+
peer, ch := makePeer(pfCompressedProposal | pfCompressedVoteVpack)
4804+
4805+
wn.maybeSendMessagesOfInterest(peer, nil)
4806+
4807+
select {
4808+
case msg := <-ch:
4809+
require.Len(t, msg.data, len(protocol.MsgOfInterestTag)+len(msg.data[2:]))
4810+
require.Equal(t, protocol.MsgOfInterestTag, protocol.Tag(msg.data[:2]))
4811+
4812+
topics, err := UnmarshallTopics(msg.data[2:])
4813+
require.NoError(t, err)
4814+
4815+
tags, ok := topics.GetValue("tags")
4816+
require.True(t, ok)
4817+
4818+
for _, tag := range strings.Split(string(tags), ",") {
4819+
require.NotEqual(t, string(protocol.VotePackedTag), tag)
4820+
}
4821+
default:
4822+
t.Fatal("expected MOI message for legacy peer")
4823+
}
4824+
})
4825+
4826+
t.Run("retains VP for peers with stateful support", func(t *testing.T) {
4827+
peer, ch := makePeer(pfCompressedProposal | pfCompressedVoteVpack | pfCompressedVoteVpackStateful256)
4828+
4829+
wn.maybeSendMessagesOfInterest(peer, nil)
4830+
4831+
select {
4832+
case msg := <-ch:
4833+
require.Equal(t, protocol.MsgOfInterestTag, protocol.Tag(msg.data[:2]))
4834+
4835+
topics, err := UnmarshallTopics(msg.data[2:])
4836+
require.NoError(t, err)
4837+
4838+
tags, ok := topics.GetValue("tags")
4839+
require.True(t, ok)
4840+
4841+
foundVP := false
4842+
for _, tag := range strings.Split(string(tags), ",") {
4843+
if tag == string(protocol.VotePackedTag) {
4844+
foundVP = true
4845+
break
4846+
}
4847+
}
4848+
require.True(t, foundVP, "expected VP tag for peer with stateful support")
4849+
default:
4850+
t.Fatal("expected MOI message for stateful peer")
4851+
}
4852+
})
4853+
}

0 commit comments

Comments
 (0)