mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-02 23:22:49 +00:00
capability: add ArchivalNode, fix #3776
This will be used to differentiate full history nodes from state only. Currently it's just a definition, we can not use it safely on current networks because nodes will refuse this Version, so actual code using the attribute will be added in newer versions. Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
parent
4720727bf5
commit
82b400700f
4 changed files with 66 additions and 1 deletions
|
@ -31,9 +31,14 @@ func (cs *Capabilities) EncodeBinary(br *io.BinWriter) {
|
|||
// checkUniqueCapabilities checks whether payload capabilities have a unique type.
|
||||
func (cs Capabilities) checkUniqueCapabilities() error {
|
||||
err := errors.New("capabilities with the same type are not allowed")
|
||||
var isFullNode, isTCP, isWS bool
|
||||
var isFullNode, isArchived, isTCP, isWS bool
|
||||
for _, cap := range cs {
|
||||
switch cap.Type {
|
||||
case ArchivalNode:
|
||||
if isArchived {
|
||||
return err
|
||||
}
|
||||
isArchived = true
|
||||
case FullNode:
|
||||
if isFullNode {
|
||||
return err
|
||||
|
@ -65,6 +70,8 @@ type Capability struct {
|
|||
func (c *Capability) DecodeBinary(br *io.BinReader) {
|
||||
c.Type = Type(br.ReadB())
|
||||
switch c.Type {
|
||||
case ArchivalNode:
|
||||
c.Data = &Archival{}
|
||||
case FullNode:
|
||||
c.Data = &Node{}
|
||||
case TCPServer, WSServer:
|
||||
|
@ -116,6 +123,22 @@ func (s *Server) EncodeBinary(bw *io.BinWriter) {
|
|||
bw.WriteU16LE(s.Port)
|
||||
}
|
||||
|
||||
// Archival represents an archival node that stores all blocks.
|
||||
type Archival struct{}
|
||||
|
||||
// DecodeBinary implements io.Serializable.
|
||||
func (a *Archival) DecodeBinary(br *io.BinReader) {
|
||||
var zero = br.ReadB() // Zero-length byte array as per Unknown.
|
||||
if zero != 0 {
|
||||
br.Err = errors.New("archival capability with non-zero data")
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeBinary implements io.Serializable.
|
||||
func (a *Archival) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteB(0)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUnknownEncodeDecode(t *testing.T) {
|
||||
|
@ -13,3 +14,35 @@ func TestUnknownEncodeDecode(t *testing.T) {
|
|||
)
|
||||
testserdes.EncodeDecodeBinary(t, &u, &ud)
|
||||
}
|
||||
|
||||
func TestArchivalEncodeDecode(t *testing.T) {
|
||||
var (
|
||||
a = Archival{}
|
||||
ad Archival
|
||||
)
|
||||
testserdes.EncodeDecodeBinary(t, &a, &ad)
|
||||
|
||||
var bad = []byte{0x02, 0x55, 0xaa} // Two-byte var-encoded string.
|
||||
require.Error(t, testserdes.DecodeBinary(bad, &ad))
|
||||
}
|
||||
|
||||
func TestCheckUniqueError(t *testing.T) {
|
||||
// Successful cases are already checked in Version payload test.
|
||||
var caps Capabilities
|
||||
|
||||
for _, bad := range [][]byte{
|
||||
{0x02, 0x11, 0x00, 0x11, 0x00}, // 2 Archival
|
||||
{0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, // 2 FullNode
|
||||
{0x02, 0x01, 0x55, 0xaa, 0x01, 0x55, 0xaa}, // 2 TCPServer
|
||||
{0x02, 0x02, 0x55, 0xaa, 0x02, 0x55, 0xaa}, // 2 WSServer
|
||||
} {
|
||||
require.Error(t, testserdes.DecodeBinary(bad, &caps))
|
||||
}
|
||||
for _, good := range [][]byte{
|
||||
{0x02, 0x11, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, // Archival + FullNode
|
||||
{0x02, 0x01, 0x55, 0xaa, 0x02, 0x55, 0xaa}, // TCPServer + WSServer
|
||||
{0x02, 0xf0, 0x00, 0xf0, 0x00}, // 2 Reserved 0xf0
|
||||
} {
|
||||
require.NoError(t, testserdes.DecodeBinary(good, &caps))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@ const (
|
|||
WSServer Type = 0x02
|
||||
// FullNode represents a node that has complete current state.
|
||||
FullNode Type = 0x10
|
||||
// ArchivalNode represents a node that stores full block history.
|
||||
// These nodes can be used for P2P synchronization from genesis
|
||||
// (FullNode can cut the tail and may not respond to requests for
|
||||
// old (wrt MaxTraceableBlocks) blocks).
|
||||
ArchivalNode Type = 0x11
|
||||
|
||||
// 0xf0-0xff are reserved for private experiments.
|
||||
ReservedFirst Type = 0xf0
|
||||
|
|
|
@ -29,6 +29,10 @@ func TestVersionEncodeDecode(t *testing.T) {
|
|||
Port: wsPort,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: capability.ArchivalNode,
|
||||
Data: &capability.Archival{},
|
||||
},
|
||||
{
|
||||
Type: 0xff,
|
||||
Data: &capability.Unknown{},
|
||||
|
|
Loading…
Reference in a new issue