diff --git a/pkg/network/capability/capability.go b/pkg/network/capability/capability.go index 0aa34ca350..7484ffbe7e 100644 --- a/pkg/network/capability/capability.go +++ b/pkg/network/capability/capability.go @@ -6,8 +6,13 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" ) -// MaxCapabilities is the maximum number of capabilities per payload. -const MaxCapabilities = 32 +const ( + // MaxCapabilities is the maximum number of capabilities per payload. + MaxCapabilities = 32 + + // MaxDataSize is the maximum size of capability payload. + MaxDataSize = 1024 +) // Capabilities is a list of Capability. type Capabilities []Capability @@ -65,8 +70,7 @@ func (c *Capability) DecodeBinary(br *io.BinReader) { case TCPServer, WSServer: c.Data = &Server{} default: - br.Err = errors.New("unknown node capability type") - return + c.Data = &Unknown{} } c.Data.DecodeBinary(br) } @@ -111,3 +115,19 @@ func (s *Server) DecodeBinary(br *io.BinReader) { func (s *Server) EncodeBinary(bw *io.BinWriter) { bw.WriteU16LE(s.Port) } + +// Unknown represents an unknown capability with some data. Other nodes can +// decode it even if they can't interpret it. This is not expected to be used +// for sending data directly (proper new types should be used), but it allows +// for easier protocol extensibility (old nodes won't reject new capabilities). +type Unknown []byte + +// DecodeBinary implements io.Serializable. +func (u *Unknown) DecodeBinary(br *io.BinReader) { + *u = br.ReadVarBytes() +} + +// EncodeBinary implements io.Serializable. +func (u *Unknown) EncodeBinary(bw *io.BinWriter) { + bw.WriteVarBytes(*u) +} diff --git a/pkg/network/capability/capability_test.go b/pkg/network/capability/capability_test.go new file mode 100644 index 0000000000..52649f9a84 --- /dev/null +++ b/pkg/network/capability/capability_test.go @@ -0,0 +1,15 @@ +package capability + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/internal/testserdes" +) + +func TestUnknownEncodeDecode(t *testing.T) { + var ( + u = Unknown{0x55, 0xaa} + ud Unknown + ) + testserdes.EncodeDecodeBinary(t, &u, &ud) +} diff --git a/pkg/network/payload/version_test.go b/pkg/network/payload/version_test.go index e0bac25389..a18ac3d329 100644 --- a/pkg/network/payload/version_test.go +++ b/pkg/network/payload/version_test.go @@ -29,12 +29,20 @@ func TestVersionEncodeDecode(t *testing.T) { Port: wsPort, }, }, + { + Type: 0xff, + Data: &capability.Unknown{}, + }, { Type: capability.FullNode, Data: &capability.Node{ StartHeight: height, }, }, + { + Type: 0xf0, + Data: &capability.Unknown{0x55, 0xaa}, + }, } version := NewVersion(magic, id, useragent, capabilities)