From 7c6cdcbcc92e8ee03c2e8e6d637dba98bec75112 Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Mon, 3 Aug 2020 13:30:51 +0300
Subject: [PATCH 1/7] core: fix bug with policy.MaxVerificationGas

In 121c9664b we should take into account isValid flag of
NativePolicy contract while retrieving MaxVerificationGas native
policy value. Otherwise we won't be able to get MaxVerificationGas
after the node was restarted, because this value is not truly
stored along with the other native policy values.

This commit fixes bug with headers verification after the  node
restarting with an existing storage:

```
2020-08-03T12:52:56.158+0300	WARN	failed processing headers	{"error": "vm failed to execute the script with error: error encountered at instruction 0 (PUSHDATA1): gas limit is exceeded", "errorVerbose": "vm failed to execute the script with error: error encountered at instruction 0 (PUSHDATA1): gas limit is exceeded\ngithub.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).verifyHashAgainstScript\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/core/blockchain.go:1454\ngithub.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).verifyHeaderWitnesses\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/core/blockchain.go:1517\ngithub.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).verifyHeader\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/core/blockchain.go:1175\ngithub.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).addHeaders\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/core/blockchain.go:484\ngithub.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).AddHeaders\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/core/blockchain.go:453\ngithub.com/nspcc-dev/neo-go/pkg/network.(*Server).handleHeadersCmd\n\t/home/neospcc/Documents/GitProjects/nspcc-dev/neo-go/pkg/network/server.go:454\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1373"}
```
---
 pkg/core/native/policy.go | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go
index 9d7c31cad..2cd090bbe 100644
--- a/pkg/core/native/policy.go
+++ b/pkg/core/native/policy.go
@@ -203,6 +203,8 @@ func (p *Policy) OnPersistEnd(dao dao.DAO) {
 	maxBlockSystemFee := p.getInt64WithKey(dao, maxBlockSystemFeeKey)
 	p.maxBlockSystemFee = maxBlockSystemFee
 
+	p.maxVerificationGas = defaultMaxVerificationGas
+
 	p.isValid = true
 }
 
@@ -256,7 +258,10 @@ func (p *Policy) GetFeePerByteInternal(dao dao.DAO) int64 {
 
 // GetMaxVerificationGas returns maximum gas allowed to be burned during verificaion.
 func (p *Policy) GetMaxVerificationGas(_ dao.DAO) int64 {
-	return p.maxVerificationGas
+	if p.isValid {
+		return p.maxVerificationGas
+	}
+	return defaultMaxVerificationGas
 }
 
 // getMaxBlockSystemFee is Policy contract method and returns the maximum overall

From 737ba700e9d44aed1be4bb2474a0014901813772 Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 13:58:22 +0300
Subject: [PATCH 2/7] network: rename GetBlockData command

GetBlockData -> GetBlockByIndex
---
 pkg/network/message.go                        | 28 +++++++++----------
 pkg/network/message_string.go                 |  6 ++--
 .../{getblockdata.go => getblockbyindex.go}   | 14 +++++-----
 ...ckdata_test.go => getblockbyindex_test.go} | 12 ++++----
 pkg/network/server.go                         | 10 +++----
 5 files changed, 35 insertions(+), 35 deletions(-)
 rename pkg/network/payload/{getblockdata.go => getblockbyindex.go} (60%)
 rename pkg/network/payload/{getblockdata_test.go => getblockbyindex_test.go} (54%)

diff --git a/pkg/network/message.go b/pkg/network/message.go
index 1fee8e24f..d336bd5ad 100644
--- a/pkg/network/message.go
+++ b/pkg/network/message.go
@@ -61,18 +61,18 @@ const (
 	CMDPong    CommandType = 0x19
 
 	// synchronization
-	CMDGetHeaders   CommandType = 0x20
-	CMDHeaders      CommandType = 0x21
-	CMDGetBlocks    CommandType = 0x24
-	CMDMempool      CommandType = 0x25
-	CMDInv          CommandType = 0x27
-	CMDGetData      CommandType = 0x28
-	CMDGetBlockData CommandType = 0x29
-	CMDNotFound     CommandType = 0x2a
-	CMDTX                       = CommandType(payload.TXType)
-	CMDBlock                    = CommandType(payload.BlockType)
-	CMDConsensus                = CommandType(payload.ConsensusType)
-	CMDReject       CommandType = 0x2f
+	CMDGetHeaders      CommandType = 0x20
+	CMDHeaders         CommandType = 0x21
+	CMDGetBlocks       CommandType = 0x24
+	CMDMempool         CommandType = 0x25
+	CMDInv             CommandType = 0x27
+	CMDGetData         CommandType = 0x28
+	CMDGetBlockByIndex CommandType = 0x29
+	CMDNotFound        CommandType = 0x2a
+	CMDTX                          = CommandType(payload.TXType)
+	CMDBlock                       = CommandType(payload.BlockType)
+	CMDConsensus                   = CommandType(payload.ConsensusType)
+	CMDReject          CommandType = 0x2f
 
 	// SPV protocol
 	CMDFilterLoad  CommandType = 0x30
@@ -149,8 +149,8 @@ func (m *Message) decodePayload() error {
 		fallthrough
 	case CMDGetHeaders:
 		p = &payload.GetBlocks{}
-	case CMDGetBlockData:
-		p = &payload.GetBlockData{}
+	case CMDGetBlockByIndex:
+		p = &payload.GetBlockByIndex{}
 	case CMDHeaders:
 		p = &payload.Headers{Network: m.Network}
 	case CMDTX:
diff --git a/pkg/network/message_string.go b/pkg/network/message_string.go
index d505f9696..233c9084b 100644
--- a/pkg/network/message_string.go
+++ b/pkg/network/message_string.go
@@ -20,7 +20,7 @@ func _() {
 	_ = x[CMDMempool-37]
 	_ = x[CMDInv-39]
 	_ = x[CMDGetData-40]
-	_ = x[CMDGetBlockData-41]
+	_ = x[CMDGetBlockByIndex-41]
 	_ = x[CMDNotFound-42]
 	_ = x[CMDTX-43]
 	_ = x[CMDBlock-44]
@@ -39,7 +39,7 @@ const (
 	_CommandType_name_2 = "CMDPingCMDPong"
 	_CommandType_name_3 = "CMDGetHeadersCMDHeaders"
 	_CommandType_name_4 = "CMDGetBlocksCMDMempool"
-	_CommandType_name_5 = "CMDInvCMDGetDataCMDGetBlockDataCMDNotFoundCMDTXCMDBlockCMDConsensus"
+	_CommandType_name_5 = "CMDInvCMDGetDataCMDGetBlockByIndexCMDNotFoundCMDTXCMDBlockCMDConsensus"
 	_CommandType_name_6 = "CMDRejectCMDFilterLoadCMDFilterAddCMDFilterClear"
 	_CommandType_name_7 = "CMDMerkleBlock"
 	_CommandType_name_8 = "CMDAlert"
@@ -51,7 +51,7 @@ var (
 	_CommandType_index_2 = [...]uint8{0, 7, 14}
 	_CommandType_index_3 = [...]uint8{0, 13, 23}
 	_CommandType_index_4 = [...]uint8{0, 12, 22}
-	_CommandType_index_5 = [...]uint8{0, 6, 16, 31, 42, 47, 55, 67}
+	_CommandType_index_5 = [...]uint8{0, 6, 16, 34, 45, 50, 58, 70}
 	_CommandType_index_6 = [...]uint8{0, 9, 22, 34, 48}
 )
 
diff --git a/pkg/network/payload/getblockdata.go b/pkg/network/payload/getblockbyindex.go
similarity index 60%
rename from pkg/network/payload/getblockdata.go
rename to pkg/network/payload/getblockbyindex.go
index 2ed9c0d9f..bd7688abe 100644
--- a/pkg/network/payload/getblockdata.go
+++ b/pkg/network/payload/getblockbyindex.go
@@ -9,22 +9,22 @@ import (
 // maximum number of blocks to query about
 const maxBlockCount = 500
 
-// GetBlockData payload
-type GetBlockData struct {
+// GetBlockByIndex payload
+type GetBlockByIndex struct {
 	IndexStart uint32
 	Count      uint16
 }
 
-// NewGetBlockData returns GetBlockData payload with specified start index and count
-func NewGetBlockData(indexStart uint32, count uint16) *GetBlockData {
-	return &GetBlockData{
+// NewGetBlockByIndex returns GetBlockByIndex payload with specified start index and count
+func NewGetBlockByIndex(indexStart uint32, count uint16) *GetBlockByIndex {
+	return &GetBlockByIndex{
 		IndexStart: indexStart,
 		Count:      count,
 	}
 }
 
 // DecodeBinary implements Serializable interface.
-func (d *GetBlockData) DecodeBinary(br *io.BinReader) {
+func (d *GetBlockByIndex) DecodeBinary(br *io.BinReader) {
 	d.IndexStart = br.ReadU32LE()
 	d.Count = br.ReadU16LE()
 	if d.Count == 0 || d.Count > maxBlockCount {
@@ -33,7 +33,7 @@ func (d *GetBlockData) DecodeBinary(br *io.BinReader) {
 }
 
 // EncodeBinary implements Serializable interface.
-func (d *GetBlockData) EncodeBinary(bw *io.BinWriter) {
+func (d *GetBlockByIndex) EncodeBinary(bw *io.BinWriter) {
 	bw.WriteU32LE(d.IndexStart)
 	bw.WriteU16LE(d.Count)
 }
diff --git a/pkg/network/payload/getblockdata_test.go b/pkg/network/payload/getblockbyindex_test.go
similarity index 54%
rename from pkg/network/payload/getblockdata_test.go
rename to pkg/network/payload/getblockbyindex_test.go
index 6704af858..e02dfafa2 100644
--- a/pkg/network/payload/getblockdata_test.go
+++ b/pkg/network/payload/getblockbyindex_test.go
@@ -8,18 +8,18 @@ import (
 )
 
 func TestGetBlockDataEncodeDecode(t *testing.T) {
-	d := NewGetBlockData(123, 100)
-	testserdes.EncodeDecodeBinary(t, d, new(GetBlockData))
+	d := NewGetBlockByIndex(123, 100)
+	testserdes.EncodeDecodeBinary(t, d, new(GetBlockByIndex))
 
 	// invalid block count
-	d = NewGetBlockData(5, 0)
+	d = NewGetBlockByIndex(5, 0)
 	data, err := testserdes.EncodeBinary(d)
 	require.NoError(t, err)
-	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockData)))
+	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockByIndex)))
 
 	// invalid block count
-	d = NewGetBlockData(5, maxBlockCount+1)
+	d = NewGetBlockByIndex(5, maxBlockCount+1)
 	data, err = testserdes.EncodeBinary(d)
 	require.NoError(t, err)
-	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockData)))
+	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockByIndex)))
 }
diff --git a/pkg/network/server.go b/pkg/network/server.go
index 7ea3f2f3b..874642588 100644
--- a/pkg/network/server.go
+++ b/pkg/network/server.go
@@ -609,8 +609,8 @@ func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error {
 	return p.EnqueueP2PMessage(msg)
 }
 
-// handleGetBlockDataCmd processes the getblockdata request.
-func (s *Server) handleGetBlockDataCmd(p Peer, gbd *payload.GetBlockData) error {
+// handleGetBlockByIndexCmd processes the getblockbyindex request.
+func (s *Server) handleGetBlockByIndexCmd(p Peer, gbd *payload.GetBlockByIndex) error {
 	for i := gbd.IndexStart; i < gbd.IndexStart+uint32(gbd.Count); i++ {
 		b, err := s.chain.GetBlock(s.chain.GetHeaderHash(int(i)))
 		if err != nil {
@@ -750,9 +750,9 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error {
 		case CMDGetBlocks:
 			gb := msg.Payload.(*payload.GetBlocks)
 			return s.handleGetBlocksCmd(peer, gb)
-		case CMDGetBlockData:
-			gbd := msg.Payload.(*payload.GetBlockData)
-			return s.handleGetBlockDataCmd(peer, gbd)
+		case CMDGetBlockByIndex:
+			gbd := msg.Payload.(*payload.GetBlockByIndex)
+			return s.handleGetBlockByIndexCmd(peer, gbd)
 		case CMDGetData:
 			inv := msg.Payload.(*payload.Inventory)
 			return s.handleGetDataCmd(peer, inv)

From 0b856033b0f6c6e0e5ee9690b2e1bca41c2a1317 Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 14:03:35 +0300
Subject: [PATCH 3/7] network: use MaxHeadersAllowed to restrict
 GetBlockByIndex

---
 pkg/network/payload/getblockbyindex.go      | 5 +----
 pkg/network/payload/getblockbyindex_test.go | 2 +-
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/pkg/network/payload/getblockbyindex.go b/pkg/network/payload/getblockbyindex.go
index bd7688abe..450dd4503 100644
--- a/pkg/network/payload/getblockbyindex.go
+++ b/pkg/network/payload/getblockbyindex.go
@@ -6,9 +6,6 @@ import (
 	"github.com/nspcc-dev/neo-go/pkg/io"
 )
 
-// maximum number of blocks to query about
-const maxBlockCount = 500
-
 // GetBlockByIndex payload
 type GetBlockByIndex struct {
 	IndexStart uint32
@@ -27,7 +24,7 @@ func NewGetBlockByIndex(indexStart uint32, count uint16) *GetBlockByIndex {
 func (d *GetBlockByIndex) DecodeBinary(br *io.BinReader) {
 	d.IndexStart = br.ReadU32LE()
 	d.Count = br.ReadU16LE()
-	if d.Count == 0 || d.Count > maxBlockCount {
+	if d.Count == 0 || d.Count > MaxHeadersAllowed {
 		br.Err = errors.New("invalid block count")
 	}
 }
diff --git a/pkg/network/payload/getblockbyindex_test.go b/pkg/network/payload/getblockbyindex_test.go
index e02dfafa2..1bd2f3452 100644
--- a/pkg/network/payload/getblockbyindex_test.go
+++ b/pkg/network/payload/getblockbyindex_test.go
@@ -18,7 +18,7 @@ func TestGetBlockDataEncodeDecode(t *testing.T) {
 	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockByIndex)))
 
 	// invalid block count
-	d = NewGetBlockByIndex(5, maxBlockCount+1)
+	d = NewGetBlockByIndex(5, MaxHeadersAllowed+1)
 	data, err = testserdes.EncodeBinary(d)
 	require.NoError(t, err)
 	require.Error(t, testserdes.DecodeBinary(data, new(GetBlockByIndex)))

From 0b0591fc34a36d6fa227ec95be42535423f574d1 Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 14:17:14 +0300
Subject: [PATCH 4/7] network: allow to use -1 to specify GetBlockByIndex.Count

---
 pkg/network/payload/getblockbyindex.go | 10 +++++-----
 pkg/network/server.go                  |  6 +++++-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/pkg/network/payload/getblockbyindex.go b/pkg/network/payload/getblockbyindex.go
index 450dd4503..a4e59db1d 100644
--- a/pkg/network/payload/getblockbyindex.go
+++ b/pkg/network/payload/getblockbyindex.go
@@ -9,11 +9,11 @@ import (
 // GetBlockByIndex payload
 type GetBlockByIndex struct {
 	IndexStart uint32
-	Count      uint16
+	Count      int16
 }
 
 // NewGetBlockByIndex returns GetBlockByIndex payload with specified start index and count
-func NewGetBlockByIndex(indexStart uint32, count uint16) *GetBlockByIndex {
+func NewGetBlockByIndex(indexStart uint32, count int16) *GetBlockByIndex {
 	return &GetBlockByIndex{
 		IndexStart: indexStart,
 		Count:      count,
@@ -23,8 +23,8 @@ func NewGetBlockByIndex(indexStart uint32, count uint16) *GetBlockByIndex {
 // DecodeBinary implements Serializable interface.
 func (d *GetBlockByIndex) DecodeBinary(br *io.BinReader) {
 	d.IndexStart = br.ReadU32LE()
-	d.Count = br.ReadU16LE()
-	if d.Count == 0 || d.Count > MaxHeadersAllowed {
+	d.Count = int16(br.ReadU16LE())
+	if d.Count < -1 || d.Count == 0 || d.Count > MaxHeadersAllowed {
 		br.Err = errors.New("invalid block count")
 	}
 }
@@ -32,5 +32,5 @@ func (d *GetBlockByIndex) DecodeBinary(br *io.BinReader) {
 // EncodeBinary implements Serializable interface.
 func (d *GetBlockByIndex) EncodeBinary(bw *io.BinWriter) {
 	bw.WriteU32LE(d.IndexStart)
-	bw.WriteU16LE(d.Count)
+	bw.WriteU16LE(uint16(d.Count))
 }
diff --git a/pkg/network/server.go b/pkg/network/server.go
index 874642588..6df448d27 100644
--- a/pkg/network/server.go
+++ b/pkg/network/server.go
@@ -611,7 +611,11 @@ func (s *Server) handleGetBlocksCmd(p Peer, gb *payload.GetBlocks) error {
 
 // handleGetBlockByIndexCmd processes the getblockbyindex request.
 func (s *Server) handleGetBlockByIndexCmd(p Peer, gbd *payload.GetBlockByIndex) error {
-	for i := gbd.IndexStart; i < gbd.IndexStart+uint32(gbd.Count); i++ {
+	count := gbd.Count
+	if gbd.Count < 0 || gbd.Count > payload.MaxHashesCount {
+		count = payload.MaxHashesCount
+	}
+	for i := gbd.IndexStart; i < gbd.IndexStart+uint32(count); i++ {
 		b, err := s.chain.GetBlock(s.chain.GetHeaderHash(int(i)))
 		if err != nil {
 			return err

From 7b1c3050002441f42fff7b74aca5512de88e7c18 Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 14:51:51 +0300
Subject: [PATCH 5/7] network: fix handleGetBlockByIndexCmd method

It returned an error in case if block wasn't found (it might be when our
chain is lower). Fixed. It also should return all requested blocks, not
the first one.
---
 pkg/network/server.go | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/pkg/network/server.go b/pkg/network/server.go
index 6df448d27..e681f335d 100644
--- a/pkg/network/server.go
+++ b/pkg/network/server.go
@@ -616,12 +616,18 @@ func (s *Server) handleGetBlockByIndexCmd(p Peer, gbd *payload.GetBlockByIndex)
 		count = payload.MaxHashesCount
 	}
 	for i := gbd.IndexStart; i < gbd.IndexStart+uint32(count); i++ {
-		b, err := s.chain.GetBlock(s.chain.GetHeaderHash(int(i)))
+		hash := s.chain.GetHeaderHash(int(i))
+		if hash.Equals(util.Uint256{}) {
+			break
+		}
+		b, err := s.chain.GetBlock(hash)
 		if err != nil {
-			return err
+			break
 		}
 		msg := NewMessage(CMDBlock, b)
-		return p.EnqueueP2PMessage(msg)
+		if err = p.EnqueueP2PMessage(msg); err != nil {
+			return err
+		}
 	}
 	return nil
 }

From f6f3863e0ef2b74811d66d1652b0e9c90fe504dc Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 14:47:42 +0300
Subject: [PATCH 6/7] network: allow to GetHeaders by index

Use GetBlockByIndex payload for GetHeaders command instead of GetBlocks
payload.
---
 pkg/network/message.go     |  4 ++--
 pkg/network/server.go      | 23 +++++++++++------------
 pkg/network/server_test.go |  2 +-
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/pkg/network/message.go b/pkg/network/message.go
index d336bd5ad..502ebbaed 100644
--- a/pkg/network/message.go
+++ b/pkg/network/message.go
@@ -146,9 +146,9 @@ func (m *Message) decodePayload() error {
 	case CMDConsensus:
 		p = consensus.NewPayload(m.Network)
 	case CMDGetBlocks:
-		fallthrough
-	case CMDGetHeaders:
 		p = &payload.GetBlocks{}
+	case CMDGetHeaders:
+		fallthrough
 	case CMDGetBlockByIndex:
 		p = &payload.GetBlockByIndex{}
 	case CMDHeaders:
diff --git a/pkg/network/server.go b/pkg/network/server.go
index e681f335d..cba5b4976 100644
--- a/pkg/network/server.go
+++ b/pkg/network/server.go
@@ -633,18 +633,17 @@ func (s *Server) handleGetBlockByIndexCmd(p Peer, gbd *payload.GetBlockByIndex)
 }
 
 // handleGetHeadersCmd processes the getheaders request.
-func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlocks) error {
-	count := gh.Count
-	if gh.Count < 0 || gh.Count > payload.MaxHashesCount {
-		count = payload.MaxHashesCount
+func (s *Server) handleGetHeadersCmd(p Peer, gh *payload.GetBlockByIndex) error {
+	if gh.IndexStart > s.chain.HeaderHeight() {
+		return nil
 	}
-	start, err := s.chain.GetHeader(gh.HashStart)
-	if err != nil {
-		return err
+	count := gh.Count
+	if gh.Count < 0 || gh.Count > payload.MaxHeadersAllowed {
+		count = payload.MaxHeadersAllowed
 	}
 	resp := payload.Headers{}
-	resp.Hdrs = make([]*block.Header, 0, payload.MaxHeadersAllowed)
-	for i := start.Index + 1; i < start.Index+uint32(count); i++ {
+	resp.Hdrs = make([]*block.Header, 0, count)
+	for i := gh.IndexStart; i < gh.IndexStart+uint32(count); i++ {
 		hash := s.chain.GetHeaderHash(int(i))
 		if hash.Equals(util.Uint256{}) {
 			break
@@ -709,9 +708,9 @@ func (s *Server) handleGetAddrCmd(p Peer) error {
 }
 
 // requestHeaders sends a getheaders message to the peer.
-// The peer will respond with headers op to a count of 500.
+// The peer will respond with headers op to a count of 2000.
 func (s *Server) requestHeaders(p Peer) error {
-	payload := payload.NewGetBlocks(s.chain.CurrentHeaderHash(), -1)
+	payload := payload.NewGetBlockByIndex(s.chain.HeaderHeight(), -1)
 	return p.EnqueueP2PMessage(NewMessage(CMDGetHeaders, payload))
 }
 
@@ -767,7 +766,7 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error {
 			inv := msg.Payload.(*payload.Inventory)
 			return s.handleGetDataCmd(peer, inv)
 		case CMDGetHeaders:
-			gh := msg.Payload.(*payload.GetBlocks)
+			gh := msg.Payload.(*payload.GetBlockByIndex)
 			return s.handleGetHeadersCmd(peer, gh)
 		case CMDHeaders:
 			headers := msg.Payload.(*payload.Headers)
diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go
index 6c783f53f..dddd19a77 100644
--- a/pkg/network/server_test.go
+++ b/pkg/network/server_test.go
@@ -149,7 +149,7 @@ func TestRequestHeaders(t *testing.T) {
 		p = newLocalPeer(t, s)
 	)
 	p.messageHandler = func(t *testing.T, msg *Message) {
-		assert.IsType(t, &payload.GetBlocks{}, msg.Payload)
+		assert.IsType(t, &payload.GetBlockByIndex{}, msg.Payload)
 		assert.Equal(t, CMDGetHeaders, msg.Command)
 	}
 	s.requestHeaders(p)

From 6c8accf18c02ad676806cca686f8b93fd2d48eee Mon Sep 17 00:00:00 2001
From: Anna Shaleva <shaleva.ann@nspcc.ru>
Date: Fri, 31 Jul 2020 17:12:13 +0300
Subject: [PATCH 7/7] core, network: request blocks instead of headers

Closes #1192

1. We now have CMDGetBlockByIndex, so there's no need to request headers
   first when we can just ask for blocks.
2. We don't ask for headers (i.e. we don't send CMDGetHeaders),
   consequently, we shouldn't react on CMDHeaders.
3. But we still keep on reacting on CMDGetHeaders command as
   there could be a node which needs headers.
---
 pkg/network/server.go      | 52 ++++----------------------------------
 pkg/network/server_test.go | 12 ---------
 pkg/network/tcp_peer.go    |  4 +--
 3 files changed, 7 insertions(+), 61 deletions(-)

diff --git a/pkg/network/server.go b/pkg/network/server.go
index cba5b4976..562908eaa 100644
--- a/pkg/network/server.go
+++ b/pkg/network/server.go
@@ -446,23 +446,6 @@ func (s *Server) handleVersionCmd(p Peer, version *payload.Version) error {
 	return p.SendVersionAck(NewMessage(CMDVerack, nil))
 }
 
-// handleHeadersCmd processes the headers received from its peer.
-// If the headerHeight of the blockchain still smaller then the peer
-// the server will request more headers.
-// This method could best be called in a separate routine.
-func (s *Server) handleHeadersCmd(p Peer, headers *payload.Headers) {
-	if err := s.chain.AddHeaders(headers.Hdrs...); err != nil {
-		s.log.Warn("failed processing headers", zap.Error(err))
-		return
-	}
-	// The peer will respond with a maximum of 2000 headers in one batch.
-	// We will ask one more batch here if needed. Eventually we will get synced
-	// due to the startProtocol routine that will ask headers every protoTick.
-	if s.chain.HeaderHeight() < p.LastBlockIndex() {
-		s.requestHeaders(p)
-	}
-}
-
 // handleBlockCmd processes the received block received from its peer.
 func (s *Server) handleBlockCmd(p Peer, block *block.Block) error {
 	return s.bQueue.putBlock(block)
@@ -479,8 +462,8 @@ func (s *Server) handlePong(p Peer, pong *payload.Ping) error {
 	if err != nil {
 		return err
 	}
-	if s.chain.HeaderHeight() < pong.LastBlockIndex {
-		return s.requestHeaders(p)
+	if s.chain.BlockHeight() < pong.LastBlockIndex {
+		return s.requestBlocks(p)
 	}
 	return nil
 }
@@ -707,34 +690,12 @@ func (s *Server) handleGetAddrCmd(p Peer) error {
 	return p.EnqueueP2PMessage(NewMessage(CMDAddr, alist))
 }
 
-// requestHeaders sends a getheaders message to the peer.
-// The peer will respond with headers op to a count of 2000.
-func (s *Server) requestHeaders(p Peer) error {
-	payload := payload.NewGetBlockByIndex(s.chain.HeaderHeight(), -1)
-	return p.EnqueueP2PMessage(NewMessage(CMDGetHeaders, payload))
-}
-
-// requestBlocks sends a getdata message to the peer
+// requestBlocks sends a CMDGetBlockByIndex message to the peer
 // to sync up in blocks. A maximum of maxBlockBatch will
 // send at once.
 func (s *Server) requestBlocks(p Peer) error {
-	var (
-		hashes       []util.Uint256
-		hashStart    = s.chain.BlockHeight() + 1
-		headerHeight = s.chain.HeaderHeight()
-	)
-	for hashStart <= headerHeight && len(hashes) < maxBlockBatch {
-		hash := s.chain.GetHeaderHash(int(hashStart))
-		hashes = append(hashes, hash)
-		hashStart++
-	}
-	if len(hashes) > 0 {
-		payload := payload.NewInventory(payload.BlockType, hashes)
-		return p.EnqueueP2PMessage(NewMessage(CMDGetData, payload))
-	} else if s.chain.HeaderHeight() < p.LastBlockIndex() {
-		return s.requestHeaders(p)
-	}
-	return nil
+	payload := payload.NewGetBlockByIndex(s.chain.BlockHeight(), -1)
+	return p.EnqueueP2PMessage(NewMessage(CMDGetBlockByIndex, payload))
 }
 
 // handleMessage processes the given message.
@@ -768,9 +729,6 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error {
 		case CMDGetHeaders:
 			gh := msg.Payload.(*payload.GetBlockByIndex)
 			return s.handleGetHeadersCmd(peer, gh)
-		case CMDHeaders:
-			headers := msg.Payload.(*payload.Headers)
-			go s.handleHeadersCmd(peer, headers)
 		case CMDInv:
 			inventory := msg.Payload.(*payload.Inventory)
 			return s.handleInvCmd(peer, inventory)
diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go
index dddd19a77..30f18942d 100644
--- a/pkg/network/server_test.go
+++ b/pkg/network/server_test.go
@@ -142,15 +142,3 @@ func TestServerNotSendsVerack(t *testing.T) {
 	assert.NotNil(t, err)
 	require.Equal(t, errAlreadyConnected, err)
 }
-
-func TestRequestHeaders(t *testing.T) {
-	var (
-		s = newTestServer(t, ServerConfig{})
-		p = newLocalPeer(t, s)
-	)
-	p.messageHandler = func(t *testing.T, msg *Message) {
-		assert.IsType(t, &payload.GetBlockByIndex{}, msg.Payload)
-		assert.Equal(t, CMDGetHeaders, msg.Command)
-	}
-	s.requestHeaders(p)
-}
diff --git a/pkg/network/tcp_peer.go b/pkg/network/tcp_peer.go
index 29cd71d94..664089bdf 100644
--- a/pkg/network/tcp_peer.go
+++ b/pkg/network/tcp_peer.go
@@ -235,8 +235,8 @@ func (p *TCPPeer) StartProtocol() {
 		zap.Uint32("id", p.Version().Nonce))
 
 	p.server.discovery.RegisterGoodAddr(p.PeerAddr().String(), p.version.Capabilities)
-	if p.server.chain.HeaderHeight() < p.LastBlockIndex() {
-		err = p.server.requestHeaders(p)
+	if p.server.chain.BlockHeight() < p.LastBlockIndex() {
+		err = p.server.requestBlocks(p)
 		if err != nil {
 			p.Disconnect(err)
 			return