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 diff --git a/pkg/network/message.go b/pkg/network/message.go index 1fee8e24f..502ebbaed 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 @@ -146,11 +146,11 @@ func (m *Message) decodePayload() error { case CMDConsensus: p = consensus.NewPayload(m.Network) case CMDGetBlocks: - fallthrough - case CMDGetHeaders: p = &payload.GetBlocks{} - case CMDGetBlockData: - p = &payload.GetBlockData{} + case CMDGetHeaders: + fallthrough + 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/getblockbyindex.go b/pkg/network/payload/getblockbyindex.go new file mode 100644 index 000000000..a4e59db1d --- /dev/null +++ b/pkg/network/payload/getblockbyindex.go @@ -0,0 +1,36 @@ +package payload + +import ( + "errors" + + "github.com/nspcc-dev/neo-go/pkg/io" +) + +// GetBlockByIndex payload +type GetBlockByIndex struct { + IndexStart uint32 + Count int16 +} + +// NewGetBlockByIndex returns GetBlockByIndex payload with specified start index and count +func NewGetBlockByIndex(indexStart uint32, count int16) *GetBlockByIndex { + return &GetBlockByIndex{ + IndexStart: indexStart, + Count: count, + } +} + +// DecodeBinary implements Serializable interface. +func (d *GetBlockByIndex) DecodeBinary(br *io.BinReader) { + d.IndexStart = br.ReadU32LE() + d.Count = int16(br.ReadU16LE()) + if d.Count < -1 || d.Count == 0 || d.Count > MaxHeadersAllowed { + br.Err = errors.New("invalid block count") + } +} + +// EncodeBinary implements Serializable interface. +func (d *GetBlockByIndex) EncodeBinary(bw *io.BinWriter) { + bw.WriteU32LE(d.IndexStart) + bw.WriteU16LE(uint16(d.Count)) +} diff --git a/pkg/network/payload/getblockdata_test.go b/pkg/network/payload/getblockbyindex_test.go similarity index 53% rename from pkg/network/payload/getblockdata_test.go rename to pkg/network/payload/getblockbyindex_test.go index 6704af858..1bd2f3452 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, MaxHeadersAllowed+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/payload/getblockdata.go b/pkg/network/payload/getblockdata.go deleted file mode 100644 index 2ed9c0d9f..000000000 --- a/pkg/network/payload/getblockdata.go +++ /dev/null @@ -1,39 +0,0 @@ -package payload - -import ( - "errors" - - "github.com/nspcc-dev/neo-go/pkg/io" -) - -// maximum number of blocks to query about -const maxBlockCount = 500 - -// GetBlockData payload -type GetBlockData struct { - IndexStart uint32 - Count uint16 -} - -// NewGetBlockData returns GetBlockData payload with specified start index and count -func NewGetBlockData(indexStart uint32, count uint16) *GetBlockData { - return &GetBlockData{ - IndexStart: indexStart, - Count: count, - } -} - -// DecodeBinary implements Serializable interface. -func (d *GetBlockData) DecodeBinary(br *io.BinReader) { - d.IndexStart = br.ReadU32LE() - d.Count = br.ReadU16LE() - if d.Count == 0 || d.Count > maxBlockCount { - br.Err = errors.New("invalid block count") - } -} - -// EncodeBinary implements Serializable interface. -func (d *GetBlockData) EncodeBinary(bw *io.BinWriter) { - bw.WriteU32LE(d.IndexStart) - bw.WriteU16LE(d.Count) -} diff --git a/pkg/network/server.go b/pkg/network/server.go index 7ea3f2f3b..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 } @@ -609,32 +592,41 @@ 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 { - for i := gbd.IndexStart; i < gbd.IndexStart+uint32(gbd.Count); i++ { - b, err := s.chain.GetBlock(s.chain.GetHeaderHash(int(i))) +// handleGetBlockByIndexCmd processes the getblockbyindex request. +func (s *Server) handleGetBlockByIndexCmd(p Peer, gbd *payload.GetBlockByIndex) error { + count := gbd.Count + if gbd.Count < 0 || gbd.Count > payload.MaxHashesCount { + count = payload.MaxHashesCount + } + for i := gbd.IndexStart; i < gbd.IndexStart+uint32(count); 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 } // 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 @@ -698,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 500. -func (s *Server) requestHeaders(p Peer) error { - payload := payload.NewGetBlocks(s.chain.CurrentHeaderHash(), -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. @@ -750,18 +720,15 @@ 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) case CMDGetHeaders: - gh := msg.Payload.(*payload.GetBlocks) + 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 6c783f53f..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.GetBlocks{}, 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