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.
This commit is contained in:
Roman Khimov 2019-11-06 18:05:50 +03:00
parent 79d0c7446a
commit d7f747fa9a
2 changed files with 8 additions and 0 deletions

View file

@ -108,6 +108,9 @@ func (p *TCPPeer) SendVersionAck(msg *Message) error {
if p.handShake&versionReceived == 0 { if p.handShake&versionReceived == 0 {
return errors.New("invalid handshake: tried to send VersionAck, but no version received yet") 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 { if p.handShake&verAckSent != 0 {
return errors.New("invalid handshake: already sent VersionAck") return errors.New("invalid handshake: already sent VersionAck")
} }
@ -126,6 +129,9 @@ func (p *TCPPeer) HandleVersionAck() error {
if p.handShake&versionSent == 0 { if p.handShake&versionSent == 0 {
return errors.New("invalid handshake: received VersionAck, but no version sent yet") 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 { if p.handShake&verAckReceived != 0 {
return errors.New("invalid handshake: already received VersionAck") return errors.New("invalid handshake: already received VersionAck")
} }

View file

@ -46,7 +46,9 @@ func TestPeerHandshake(t *testing.T) {
// Now send and handle versions, but in a different order on client and // Now send and handle versions, but in a different order on client and
// server. // server.
require.NoError(t, tcpC.SendVersion(&Message{})) require.NoError(t, tcpC.SendVersion(&Message{}))
require.Error(t, tcpC.HandleVersionAck()) // Didn't receive version yet.
require.NoError(t, tcpS.HandleVersion(&payload.Version{})) 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, tcpC.HandleVersion(&payload.Version{}))
require.NoError(t, tcpS.SendVersion(&Message{})) require.NoError(t, tcpS.SendVersion(&Message{}))