From 234d94d27e6f3b5a57e619004ee0e4ede9196f5c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 25 Dec 2019 19:40:18 +0300 Subject: [PATCH] network: implement getblocks command Fixes #577, tested with C# nodes connecting to neo-go privnet. --- pkg/network/payload/getblocks.go | 5 +++++ pkg/network/server.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/pkg/network/payload/getblocks.go b/pkg/network/payload/getblocks.go index 45e567119..98e2a9c47 100644 --- a/pkg/network/payload/getblocks.go +++ b/pkg/network/payload/getblocks.go @@ -5,6 +5,11 @@ import ( "github.com/CityOfZion/neo-go/pkg/util" ) +// Maximum inventory hashes number is limited to 500. +const ( + MaxHashesCount = 500 +) + // GetBlocks contains fields and methods to be shared with the type GetBlocks struct { // hash of latest block that node requests diff --git a/pkg/network/server.go b/pkg/network/server.go index d395ef5a0..a9229d790 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -463,6 +463,35 @@ func (s *Server) handleGetDataCmd(p Peer, inv *payload.Inventory) error { return nil } +// handleGetBlocksCmd processes the getblocks request. +func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error { + if len(gb.HashStart) < 1 { + return errInvalidHashStart + } + startHash := gb.HashStart[0] + if startHash.Equals(gb.HashStop) { + return nil + } + start, err := s.chain.GetHeader(startHash) + if err != nil { + return err + } + blockHashes := make([]util.Uint256, 0) + for i := start.Index + 1; i < start.Index+1+payload.MaxHashesCount; i++ { + hash := s.chain.GetHeaderHash(int(i)) + if hash.Equals(util.Uint256{}) || hash.Equals(gb.HashStop) { + break + } + blockHashes = append(blockHashes, hash) + } + + if len(blockHashes) == 0 { + return nil + } + payload := payload.NewInventory(payload.BlockType, blockHashes) + return p.WriteMsg(NewMessage(s.Net, CMDInv, payload)) +} + // handleGetHeadersCmd processes the getheaders request. func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error { if len(gh.HashStart) < 1 { @@ -585,6 +614,9 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error { case CMDGetAddr: // it has no payload return s.handleGetAddrCmd(peer) + case CMDGetBlocks: + gb := msg.Payload.(*payload.GetBlocks) + return s.handleGetBlocksCmd(peer, gb) case CMDGetData: inv := msg.Payload.(*payload.Inventory) return s.handleGetDataCmd(peer, inv)