protocol: refactor getblocks payload

closes #890
This commit is contained in:
Anna Shaleva 2020-05-22 17:30:56 +03:00
parent 9b2d045a29
commit 2f6a3e9af5
3 changed files with 42 additions and 48 deletions

View file

@ -1,6 +1,8 @@
package payload package payload
import ( import (
"errors"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
) )
@ -13,27 +15,30 @@ const (
// GetBlocks contains fields and methods to be shared with the // GetBlocks contains fields and methods to be shared with the
type GetBlocks struct { type GetBlocks struct {
// hash of latest block that node requests // hash of latest block that node requests
HashStart []util.Uint256 HashStart util.Uint256
// hash of last block that node requests Count int16
HashStop util.Uint256
} }
// NewGetBlocks returns a pointer to a GetBlocks object. // NewGetBlocks returns a pointer to a GetBlocks object.
func NewGetBlocks(start []util.Uint256, stop util.Uint256) *GetBlocks { func NewGetBlocks(start util.Uint256, count int16) *GetBlocks {
return &GetBlocks{ return &GetBlocks{
HashStart: start, HashStart: start,
HashStop: stop, Count: count,
} }
} }
// DecodeBinary implements Serializable interface. // DecodeBinary implements Serializable interface.
func (p *GetBlocks) DecodeBinary(br *io.BinReader) { func (p *GetBlocks) DecodeBinary(br *io.BinReader) {
br.ReadArray(&p.HashStart) p.HashStart.DecodeBinary(br)
br.ReadBytes(p.HashStop[:]) p.Count = int16(br.ReadU16LE())
if p.Count < -1 || p.Count == 0 {
br.Err = errors.New("invalid count")
}
} }
// EncodeBinary implements Serializable interface. // EncodeBinary implements Serializable interface.
func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) { func (p *GetBlocks) EncodeBinary(bw *io.BinWriter) {
bw.WriteArray(p.HashStart) p.HashStart.EncodeBinary(bw)
bw.WriteBytes(p.HashStop[:]) bw.WriteU16LE(uint16(p.Count))
} }

View file

@ -5,31 +5,24 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes" "github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require"
) )
func TestGetBlockEncodeDecode(t *testing.T) { func TestGetBlockEncodeDecode(t *testing.T) {
start := []util.Uint256{ start := hash.Sha256([]byte("a"))
hash.Sha256([]byte("a")),
hash.Sha256([]byte("b")),
hash.Sha256([]byte("c")),
hash.Sha256([]byte("d")),
}
p := NewGetBlocks(start, util.Uint256{}) p := NewGetBlocks(start, 124)
testserdes.EncodeDecodeBinary(t, p, new(GetBlocks)) testserdes.EncodeDecodeBinary(t, p, new(GetBlocks))
}
func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) { // invalid count
var ( p = NewGetBlocks(start, -2)
start = []util.Uint256{ data, err := testserdes.EncodeBinary(p)
hash.Sha256([]byte("a")), require.NoError(t, err)
hash.Sha256([]byte("b")), require.Error(t, testserdes.DecodeBinary(data, new(GetBlocks)))
hash.Sha256([]byte("c")),
hash.Sha256([]byte("d")), // invalid count
} p = NewGetBlocks(start, 0)
stop = hash.Sha256([]byte("e")) data, err = testserdes.EncodeBinary(p)
) require.NoError(t, err)
p := NewGetBlocks(start, stop) require.Error(t, testserdes.DecodeBinary(data, new(GetBlocks)))
testserdes.EncodeDecodeBinary(t, p, new(GetBlocks))
} }

View file

@ -535,21 +535,18 @@ func (s *Server) handleGetDataCmd(p Peer, inv *payload.Inventory) error {
// handleGetBlocksCmd processes the getblocks request. // handleGetBlocksCmd processes the getblocks request.
func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error { func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error {
if len(gb.HashStart) < 1 { count := gb.Count
return errInvalidHashStart if gb.Count < 0 || gb.Count > payload.MaxHashesCount {
count = payload.MaxHashesCount
} }
startHash := gb.HashStart[0] start, err := s.chain.GetHeader(gb.HashStart)
if startHash.Equals(gb.HashStop) {
return nil
}
start, err := s.chain.GetHeader(startHash)
if err != nil { if err != nil {
return err return err
} }
blockHashes := make([]util.Uint256, 0) blockHashes := make([]util.Uint256, 0)
for i := start.Index + 1; i < start.Index+1+payload.MaxHashesCount; i++ { for i := start.Index + 1; i < start.Index+uint32(count); i++ {
hash := s.chain.GetHeaderHash(int(i)) hash := s.chain.GetHeaderHash(int(i))
if hash.Equals(util.Uint256{}) || hash.Equals(gb.HashStop) { if hash.Equals(util.Uint256{}) {
break break
} }
blockHashes = append(blockHashes, hash) blockHashes = append(blockHashes, hash)
@ -565,19 +562,19 @@ func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error {
// handleGetHeadersCmd processes the getheaders request. // handleGetHeadersCmd processes the getheaders request.
func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error { func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error {
if len(gh.HashStart) < 1 { count := gh.Count
return errInvalidHashStart if gh.Count < 0 || gh.Count > payload.MaxHashesCount {
count = payload.MaxHashesCount
} }
startHash := gh.HashStart[0] start, err := s.chain.GetHeader(gh.HashStart)
start, err := s.chain.GetHeader(startHash)
if err != nil { if err != nil {
return err return err
} }
resp := payload.Headers{} resp := payload.Headers{}
resp.Hdrs = make([]*block.Header, 0, payload.MaxHeadersAllowed) resp.Hdrs = make([]*block.Header, 0, payload.MaxHeadersAllowed)
for i := start.Index + 1; i < start.Index+1+payload.MaxHeadersAllowed; i++ { for i := start.Index + 1; i < start.Index+uint32(count); i++ {
hash := s.chain.GetHeaderHash(int(i)) hash := s.chain.GetHeaderHash(int(i))
if hash.Equals(util.Uint256{}) || hash.Equals(gh.HashStop) { if hash.Equals(util.Uint256{}) {
break break
} }
header, err := s.chain.GetHeader(hash) header, err := s.chain.GetHeader(hash)
@ -637,10 +634,9 @@ func (s *Server) handleGetAddrCmd(p Peer) error {
} }
// requestHeaders sends a getheaders message to the peer. // requestHeaders sends a getheaders message to the peer.
// The peer will respond with headers op to a count of 2000. // The peer will respond with headers op to a count of 500.
func (s *Server) requestHeaders(p Peer) error { func (s *Server) requestHeaders(p Peer) error {
start := []util.Uint256{s.chain.CurrentHeaderHash()} payload := payload.NewGetBlocks(s.chain.CurrentHeaderHash(), -1)
payload := payload.NewGetBlocks(start, util.Uint256{})
return p.EnqueueP2PMessage(NewMessage(CMDGetHeaders, payload)) return p.EnqueueP2PMessage(NewMessage(CMDGetHeaders, payload))
} }