From d7f747fa9a08524418b67e21603f18411aecb4ab Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 6 Nov 2019 18:05:50 +0300 Subject: [PATCH] network: wait for both Version messages before ACKing Otherwise the node might crash in `startProtocol` because of missing Version field in the peer. And it also keeps the sequence correct, Version MUST be sent first and ACKs can only follow it. --- pkg/network/tcp_peer.go | 6 ++++++ pkg/network/tcp_peer_test.go | 2 ++ 2 files changed, 8 insertions(+) diff --git a/pkg/network/tcp_peer.go b/pkg/network/tcp_peer.go index e1e0923a5..074bf6016 100644 --- a/pkg/network/tcp_peer.go +++ b/pkg/network/tcp_peer.go @@ -108,6 +108,9 @@ func (p *TCPPeer) SendVersionAck(msg *Message) error { if p.handShake&versionReceived == 0 { return errors.New("invalid handshake: tried to send VersionAck, but no version received yet") } + if p.handShake&versionSent == 0 { + return errors.New("invalid handshake: tried to send VersionAck, but didn't send Version yet") + } if p.handShake&verAckSent != 0 { return errors.New("invalid handshake: already sent VersionAck") } @@ -126,6 +129,9 @@ func (p *TCPPeer) HandleVersionAck() error { if p.handShake&versionSent == 0 { return errors.New("invalid handshake: received VersionAck, but no version sent yet") } + if p.handShake&versionReceived == 0 { + return errors.New("invalid handshake: received VersionAck, but no version received yet") + } if p.handShake&verAckReceived != 0 { return errors.New("invalid handshake: already received VersionAck") } diff --git a/pkg/network/tcp_peer_test.go b/pkg/network/tcp_peer_test.go index b4e1bb3c0..5223bf64b 100644 --- a/pkg/network/tcp_peer_test.go +++ b/pkg/network/tcp_peer_test.go @@ -46,7 +46,9 @@ func TestPeerHandshake(t *testing.T) { // Now send and handle versions, but in a different order on client and // server. require.NoError(t, tcpC.SendVersion(&Message{})) + require.Error(t, tcpC.HandleVersionAck()) // Didn't receive version yet. require.NoError(t, tcpS.HandleVersion(&payload.Version{})) + require.Error(t, tcpS.SendVersionAck(&Message{})) // Didn't send version yet. require.NoError(t, tcpC.HandleVersion(&payload.Version{})) require.NoError(t, tcpS.SendVersion(&Message{}))