From 95c279325ab45a8a72fb58ec9f86835e4743e1ee Mon Sep 17 00:00:00 2001
From: Roman Khimov <roman@nspcc.ru>
Date: Thu, 25 Mar 2021 21:46:52 +0300
Subject: [PATCH] block: drop Network from the Header

It's not network-tied any more, network is only needed to
sign/verify. Unfortunately we still have to keep network in consensus data
structures because of dbft library interface.
---
 internal/testchain/address.go           |  1 -
 pkg/consensus/block.go                  | 20 +++++++-------
 pkg/consensus/block_test.go             |  9 +++----
 pkg/consensus/consensus.go              |  5 ++--
 pkg/core/block/block.go                 |  9 +++----
 pkg/core/block/block_test.go            | 11 ++++----
 pkg/core/block/header.go                | 35 -------------------------
 pkg/core/block/helper_test.go           |  3 +--
 pkg/core/blockchain_test.go             |  4 +--
 pkg/core/chaindump/dump.go              |  3 +--
 pkg/core/dao/dao.go                     |  4 +--
 pkg/core/helper_test.go                 |  4 +--
 pkg/core/interop/runtime/engine_test.go |  3 +--
 pkg/core/native_designate_test.go       |  3 +--
 pkg/core/native_oracle_test.go          |  3 +--
 pkg/core/util.go                        |  1 -
 pkg/network/message.go                  |  6 ++---
 pkg/network/message_test.go             |  4 +--
 pkg/network/payload/headers.go          |  5 +---
 pkg/network/payload/merkleblock.go      |  4 +--
 pkg/network/server_test.go              |  2 +-
 pkg/rpc/client/rpc.go                   |  4 +--
 pkg/rpc/client/rpc_test.go              |  2 +-
 pkg/rpc/client/wsclient.go              |  2 +-
 pkg/rpc/server/server.go                |  4 +--
 pkg/rpc/server/server_helper_test.go    |  2 +-
 pkg/rpc/server/server_test.go           |  4 ---
 scripts/gendump/main.go                 |  1 -
 28 files changed, 48 insertions(+), 110 deletions(-)

diff --git a/internal/testchain/address.go b/internal/testchain/address.go
index 9be6f2371..8e18f86a1 100644
--- a/internal/testchain/address.go
+++ b/internal/testchain/address.go
@@ -170,7 +170,6 @@ func NewBlock(t *testing.T, bc blockchainer.Blockchainer, offset uint32, primary
 			PrimaryIndex:  byte(primary),
 			NextConsensus: witness.ScriptHash(),
 			Script:        witness,
-			Network:       bc.GetConfig().Magic,
 		},
 		Transactions: txs,
 	}
diff --git a/pkg/consensus/block.go b/pkg/consensus/block.go
index dab9c3302..16c7d9ea6 100644
--- a/pkg/consensus/block.go
+++ b/pkg/consensus/block.go
@@ -1,8 +1,11 @@
 package consensus
 
 import (
+	"errors"
+
 	"github.com/nspcc-dev/dbft/block"
 	"github.com/nspcc-dev/dbft/crypto"
+	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	coreb "github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
 	"github.com/nspcc-dev/neo-go/pkg/util"
@@ -13,6 +16,7 @@ import (
 type neoBlock struct {
 	coreb.Block
 
+	network   netmode.Magic
 	signature []byte
 }
 
@@ -20,21 +24,19 @@ var _ block.Block = (*neoBlock)(nil)
 
 // Sign implements block.Block interface.
 func (n *neoBlock) Sign(key crypto.PrivateKey) error {
-	data := n.Header.GetSignedPart()
-	sig, err := key.Sign(data[:])
-	if err != nil {
-		return err
-	}
-
+	k := key.(*privateKey)
+	sig := k.PrivateKey.SignHashable(uint32(n.network), &n.Block)
 	n.signature = sig
-
 	return nil
 }
 
 // Verify implements block.Block interface.
 func (n *neoBlock) Verify(key crypto.PublicKey, sign []byte) error {
-	data := n.Header.GetSignedPart()
-	return key.Verify(data, sign)
+	k := key.(*publicKey)
+	if k.PublicKey.VerifyHashable(sign, uint32(n.network), &n.Block) {
+		return nil
+	}
+	return errors.New("verification failed")
 }
 
 // Transactions implements block.Block interface.
diff --git a/pkg/consensus/block_test.go b/pkg/consensus/block_test.go
index af6d9826f..afa94a711 100644
--- a/pkg/consensus/block_test.go
+++ b/pkg/consensus/block_test.go
@@ -1,12 +1,11 @@
 package consensus
 
 import (
-	"crypto/rand"
 	"testing"
 
 	"github.com/nspcc-dev/dbft/block"
-	"github.com/nspcc-dev/dbft/crypto"
 	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/nspcc-dev/neo-go/pkg/util"
 	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
 	"github.com/stretchr/testify/require"
@@ -14,10 +13,10 @@ import (
 
 func TestNeoBlock_Sign(t *testing.T) {
 	b := new(neoBlock)
-	priv, pub := crypto.Generate(rand.Reader)
+	priv, _ := keys.NewPrivateKey()
 
-	require.NoError(t, b.Sign(priv))
-	require.NoError(t, b.Verify(pub, b.Signature()))
+	require.NoError(t, b.Sign(&privateKey{PrivateKey: priv}))
+	require.NoError(t, b.Verify(&publicKey{PublicKey: priv.PublicKey()}, b.Signature()))
 }
 
 func TestNeoBlock_Setters(t *testing.T) {
diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go
index cff3c95da..f01cdf6a0 100644
--- a/pkg/consensus/consensus.go
+++ b/pkg/consensus/consensus.go
@@ -576,7 +576,7 @@ func (s *service) getBlock(h util.Uint256) block.Block {
 		return nil
 	}
 
-	return &neoBlock{Block: *b}
+	return &neoBlock{network: s.ProtocolConfiguration.Magic, Block: *b}
 }
 
 func (s *service) getVerifiedTx() []block.Transaction {
@@ -647,9 +647,8 @@ func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) {
 }
 
 func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block {
-	block := new(neoBlock)
+	block := &neoBlock{network: s.ProtocolConfiguration.Magic}
 
-	block.Block.Network = s.ProtocolConfiguration.Magic
 	block.Block.Timestamp = ctx.Timestamp / nsInMs
 	block.Block.Index = ctx.BlockIndex
 	if s.ProtocolConfiguration.StateRootInHeader {
diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go
index 45b7651fc..8feff8942 100644
--- a/pkg/core/block/block.go
+++ b/pkg/core/block/block.go
@@ -6,7 +6,6 @@ import (
 	"math"
 
 	"github.com/Workiva/go-datastructures/queue"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
 	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
 	"github.com/nspcc-dev/neo-go/pkg/io"
@@ -68,10 +67,9 @@ func (b *Block) RebuildMerkleRoot() {
 // This is commonly used to create a block from stored data.
 // Blocks created from trimmed data will have their Trimmed field
 // set to true.
-func NewBlockFromTrimmedBytes(network netmode.Magic, stateRootEnabled bool, b []byte) (*Block, error) {
+func NewBlockFromTrimmedBytes(stateRootEnabled bool, b []byte) (*Block, error) {
 	block := &Block{
 		Header: Header{
-			Network:          network,
 			StateRootEnabled: stateRootEnabled,
 		},
 		Trimmed: true,
@@ -95,11 +93,10 @@ func NewBlockFromTrimmedBytes(network netmode.Magic, stateRootEnabled bool, b []
 	return block, br.Err
 }
 
-// New creates a new blank block tied to the specific network.
-func New(network netmode.Magic, stateRootEnabled bool) *Block {
+// New creates a new blank block with proper state root setting.
+func New(stateRootEnabled bool) *Block {
 	return &Block{
 		Header: Header{
-			Network:          network,
 			StateRootEnabled: stateRootEnabled,
 		},
 	}
diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go
index bad0c760f..b8042f3ef 100644
--- a/pkg/core/block/block_test.go
+++ b/pkg/core/block/block_test.go
@@ -8,7 +8,6 @@ import (
 	"testing"
 
 	"github.com/nspcc-dev/neo-go/internal/testserdes"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
 	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
 	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
@@ -32,7 +31,7 @@ func TestDecodeBlock1(t *testing.T) {
 	b, err := hex.DecodeString(data["raw"].(string))
 	require.NoError(t, err)
 
-	block := New(netmode.TestNet, false)
+	block := New(false)
 	assert.NoError(t, testserdes.DecodeBinary(b, block))
 
 	assert.Equal(t, uint32(data["index"].(float64)), block.Index)
@@ -59,7 +58,7 @@ func TestTrimmedBlock(t *testing.T) {
 	b, err := block.Trim()
 	require.NoError(t, err)
 
-	trimmedBlock, err := NewBlockFromTrimmedBytes(netmode.TestNet, false, b)
+	trimmedBlock, err := NewBlockFromTrimmedBytes(false, b)
 	require.NoError(t, err)
 
 	assert.True(t, trimmedBlock.Trimmed)
@@ -109,7 +108,7 @@ func TestBinBlockDecodeEncode(t *testing.T) {
 	rawblock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAEAAAAA3u55wYnzAJiwumouuQs6klimx/8BxgxA4MAnF5HGhcOTBjqdXKZIAKcw019v0cSpZj3l04FmLXxAPIPbL1Em2QOE3qBslr1/C4jdLSSq82o3TBr01RqlZgxA6ejwZmZkcfQsbMLS4beqFmtlKuK5eXYj7C7al2XmXqTJcVEm2gnZRUwe4lkBvcil1keYXNLEnHr77lcMLFGHZQxA8JYcGaz9OxOXxECrbVTGAIi+3nXf3ltsqDBmXukPeYO8l0OvXnVR30G+tXwcNw4wqTA2eZbMadwYM14JScDEipMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUCAFjQuwvA2KcAAAAAACCqRAAAAAAA6AMAAAHe7nnBifMAmLC6ai65CzqSWKbH/wEAWwsCAOH1BQwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjkBxgxAuFCM0+tRmD8dC3ZLKxegtoqGGoun28KY79wRgKosmoMYqJmBmUS3l2cg+uzuRSfOqV0RbUm1WLtmAxvk+SAiIAxA85v8JfgZx70F2h0Naxi7XVDHONcDeiOPJDzzOxdt4C/bFcRs4kCDES56U21h6582lPUstH15LyK3SctSgAZEkAxAwcLgblSvp7Gb59aALHD4+ndxSYlBivcYh6V/SKaf+Y0510QQMs8hnPCGTAVapeFkvJMBXuqIwP/QbxW+Xll5xJMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUA2CS8GcDYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBfCwMAQNndiE0KAAwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjkBxgxA1p9A+89hC6qTfIIXDPz7XxcKOevwXxGrHx7kihAiTGMb1OO69mbUooYOfZRsUmcx7L8U8up7MrydtsnDYSDXSQxApetXIPd+zfx7oyrCzLtsCTEuwueG8yd6ttgs6pZb8N2KfNPVEoCg7Plvt0A+6yPkhbNDoSJ9IKKAlFOn/9d1owxA6/V3Xk+QhkzvAi9CYoM3E3LnLNBgXKh7PH06Dusz7rgn0u1oencsUgoo0+AOEvuwVHVt3bDu/NvJHtX4/KDcZpMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKU="
 	rawblockBytes, _ := base64.StdEncoding.DecodeString(rawblock)
 
-	b := New(netmode.PrivNet, false)
+	b := New(false)
 
 	assert.NoError(t, testserdes.DecodeBinary(rawblockBytes, b))
 	expected := map[string]bool{ // 1 trans
@@ -143,7 +142,7 @@ func TestBinBlockDecodeEncode(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, rawblock, base64.StdEncoding.EncodeToString(data))
 
-	testserdes.MarshalUnmarshalJSON(t, b, New(netmode.PrivNet, false))
+	testserdes.MarshalUnmarshalJSON(t, b, New(false))
 }
 
 func TestBlockSizeCalculation(t *testing.T) {
@@ -156,7 +155,7 @@ func TestBlockSizeCalculation(t *testing.T) {
 	rawBlock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAEAAAAA3u55wYnzAJiwumouuQs6klimx/8BxgxA4MAnF5HGhcOTBjqdXKZIAKcw019v0cSpZj3l04FmLXxAPIPbL1Em2QOE3qBslr1/C4jdLSSq82o3TBr01RqlZgxA6ejwZmZkcfQsbMLS4beqFmtlKuK5eXYj7C7al2XmXqTJcVEm2gnZRUwe4lkBvcil1keYXNLEnHr77lcMLFGHZQxA8JYcGaz9OxOXxECrbVTGAIi+3nXf3ltsqDBmXukPeYO8l0OvXnVR30G+tXwcNw4wqTA2eZbMadwYM14JScDEipMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUCAFjQuwvA2KcAAAAAACCqRAAAAAAA6AMAAAHe7nnBifMAmLC6ai65CzqSWKbH/wEAWwsCAOH1BQwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjkBxgxAuFCM0+tRmD8dC3ZLKxegtoqGGoun28KY79wRgKosmoMYqJmBmUS3l2cg+uzuRSfOqV0RbUm1WLtmAxvk+SAiIAxA85v8JfgZx70F2h0Naxi7XVDHONcDeiOPJDzzOxdt4C/bFcRs4kCDES56U21h6582lPUstH15LyK3SctSgAZEkAxAwcLgblSvp7Gb59aALHD4+ndxSYlBivcYh6V/SKaf+Y0510QQMs8hnPCGTAVapeFkvJMBXuqIwP/QbxW+Xll5xJMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUA2CS8GcDYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBfCwMAQNndiE0KAAwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjkBxgxA1p9A+89hC6qTfIIXDPz7XxcKOevwXxGrHx7kihAiTGMb1OO69mbUooYOfZRsUmcx7L8U8up7MrydtsnDYSDXSQxApetXIPd+zfx7oyrCzLtsCTEuwueG8yd6ttgs6pZb8N2KfNPVEoCg7Plvt0A+6yPkhbNDoSJ9IKKAlFOn/9d1owxA6/V3Xk+QhkzvAi9CYoM3E3LnLNBgXKh7PH06Dusz7rgn0u1oencsUgoo0+AOEvuwVHVt3bDu/NvJHtX4/KDcZpMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKU="
 	rawBlockBytes, _ := base64.StdEncoding.DecodeString(rawBlock)
 
-	b := New(netmode.TestNet, false)
+	b := New(false)
 	assert.NoError(t, testserdes.DecodeBinary(rawBlockBytes, b))
 
 	expected := []struct {
diff --git a/pkg/core/block/header.go b/pkg/core/block/header.go
index 39ecf4b7a..e7515dcab 100644
--- a/pkg/core/block/header.go
+++ b/pkg/core/block/header.go
@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"errors"
 
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
 	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
 	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
@@ -38,11 +37,6 @@ type Header struct {
 	// Script used to validate the block
 	Script transaction.Witness
 
-	// Network magic number this block belongs to. This one actually is not
-	// a part of the wire-representation of Block, but it's absolutely
-	// necessary for correct signing/verification.
-	Network netmode.Magic
-
 	// StateRootEnabled specifies if header contains state root.
 	StateRootEnabled bool
 	// PrevStateRoot is state root of the previous block.
@@ -52,9 +46,6 @@ type Header struct {
 
 	// Hash of this block, created when binary encoded (double SHA256).
 	hash util.Uint256
-
-	// Hash of the block used to verify it (single SHA256).
-	verificationHash util.Uint256
 }
 
 // baseAux is used to marshal/unmarshal to/from JSON, it's almost the same
@@ -81,14 +72,6 @@ func (b *Header) Hash() util.Uint256 {
 	return b.hash
 }
 
-// GetSignedHash returns a hash of the block used to verify it.
-func (b *Header) GetSignedHash() util.Uint256 {
-	if b.verificationHash.Equals(util.Uint256{}) {
-		b.createHash()
-	}
-	return b.verificationHash
-}
-
 // DecodeBinary implements Serializable interface.
 func (b *Header) DecodeBinary(br *io.BinReader) {
 	b.decodeHashableFields(br)
@@ -108,21 +91,6 @@ func (b *Header) EncodeBinary(bw *io.BinWriter) {
 	b.Script.EncodeBinary(bw)
 }
 
-// GetSignedPart returns serialized hashable data of the block.
-func (b *Header) GetSignedPart() []byte {
-	if b.hash.Equals(util.Uint256{}) {
-		b.createHash()
-	}
-	buf := io.NewBufBinWriter()
-	b.writeSignedPart(buf)
-	return buf.Bytes()
-}
-
-func (b *Header) writeSignedPart(buf *io.BufBinWriter) {
-	buf.WriteU32LE(uint32(b.Network))
-	buf.WriteBytes(b.hash[:])
-}
-
 // createHash creates the hash of the block.
 // When calculating the hash value of the block, instead of calculating the entire block,
 // only first seven fields in the block head will be calculated, which are
@@ -135,9 +103,6 @@ func (b *Header) createHash() {
 	b.encodeHashableFields(buf.BinWriter)
 
 	b.hash = hash.Sha256(buf.Bytes())
-	buf.Reset()
-	b.writeSignedPart(buf)
-	b.verificationHash = hash.Sha256(buf.Bytes())
 }
 
 // encodeHashableFields will only encode the fields used for hashing.
diff --git a/pkg/core/block/helper_test.go b/pkg/core/block/helper_test.go
index c52a39a94..b73b50de2 100644
--- a/pkg/core/block/helper_test.go
+++ b/pkg/core/block/helper_test.go
@@ -8,7 +8,6 @@ import (
 	"testing"
 
 	"github.com/nspcc-dev/neo-go/internal/testserdes"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/stretchr/testify/require"
 )
 
@@ -19,7 +18,7 @@ func getDecodedBlock(t *testing.T, i int) *Block {
 	b, err := hex.DecodeString(data["raw"].(string))
 	require.NoError(t, err)
 
-	block := New(netmode.TestNet, false)
+	block := New(false)
 	require.NoError(t, testserdes.DecodeBinary(b, block))
 
 	return block
diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go
index 0e993f179..bec2d4a47 100644
--- a/pkg/core/blockchain_test.go
+++ b/pkg/core/blockchain_test.go
@@ -592,7 +592,7 @@ func TestVerifyTx(t *testing.T) {
 				InvocationScript:   testchain.SignCommittee(txSetOracle),
 				VerificationScript: testchain.CommitteeVerificationScript(),
 			}}
-			bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader)
+			bl := block.New(bc.config.StateRootInHeader)
 			bl.Index = bc.BlockHeight() + 1
 			ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetOracle)
 			ic.SpawnVM()
@@ -800,7 +800,7 @@ func TestVerifyTx(t *testing.T) {
 				InvocationScript:   testchain.SignCommittee(txSetNotary),
 				VerificationScript: testchain.CommitteeVerificationScript(),
 			}}
-			bl := block.New(netmode.UnitTestNet, false)
+			bl := block.New(false)
 			bl.Index = bc.BlockHeight() + 1
 			ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetNotary)
 			ic.SpawnVM()
diff --git a/pkg/core/chaindump/dump.go b/pkg/core/chaindump/dump.go
index 9fc9e6649..6f5cd7259 100644
--- a/pkg/core/chaindump/dump.go
+++ b/pkg/core/chaindump/dump.go
@@ -47,7 +47,6 @@ func Restore(bc blockchainer.Blockchainer, r *io.BinReader, skip, count uint32,
 		}
 	}
 
-	magic := bc.GetConfig().Magic
 	stateRootInHeader := bc.GetConfig().StateRootInHeader
 
 	for ; i < skip+count; i++ {
@@ -55,7 +54,7 @@ func Restore(bc blockchainer.Blockchainer, r *io.BinReader, skip, count uint32,
 		if err != nil {
 			return err
 		}
-		b := block.New(magic, stateRootInHeader)
+		b := block.New(stateRootInHeader)
 		r := io.NewBinReaderFromBuf(buf)
 		b.DecodeBinary(r)
 		if r.Err != nil {
diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go
index ae7f40fe5..48be27b3e 100644
--- a/pkg/core/dao/dao.go
+++ b/pkg/core/dao/dao.go
@@ -363,7 +363,7 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) {
 		return nil, err
 	}
 
-	block, err := block.NewBlockFromTrimmedBytes(dao.network, dao.stateRootInHeader, b)
+	block, err := block.NewBlockFromTrimmedBytes(dao.stateRootInHeader, b)
 	if err != nil {
 		return nil, err
 	}
@@ -530,7 +530,7 @@ func (dao *Simple) DeleteBlock(h util.Uint256, w *io.BufBinWriter) error {
 		return err
 	}
 
-	b, err := block.NewBlockFromTrimmedBytes(dao.network, dao.stateRootInHeader, bs)
+	b, err := block.NewBlockFromTrimmedBytes(dao.stateRootInHeader, bs)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go
index 8fac8554f..447975817 100644
--- a/pkg/core/helper_test.go
+++ b/pkg/core/helper_test.go
@@ -111,7 +111,6 @@ func newBlockCustom(cfg config.ProtocolConfiguration, f func(b *block.Block),
 	}
 	b := &block.Block{
 		Header: block.Header{
-			Network:       testchain.Network(),
 			NextConsensus: witness.ScriptHash(),
 			Script:        witness,
 		},
@@ -187,7 +186,7 @@ func getDecodedBlock(t *testing.T, i int) *block.Block {
 	b, err := hex.DecodeString(data["raw"].(string))
 	require.NoError(t, err)
 
-	block := block.New(testchain.Network(), false)
+	block := block.New(false)
 	require.NoError(t, testserdes.DecodeBinary(b, block))
 
 	return block
@@ -208,7 +207,6 @@ func getBlockData(i int) (map[string]interface{}, error) {
 func newDumbBlock() *block.Block {
 	return &block.Block{
 		Header: block.Header{
-			Network:       testchain.Network(),
 			Version:       0,
 			PrevHash:      hash.Sha256([]byte("a")),
 			MerkleRoot:    hash.Sha256([]byte("b")),
diff --git a/pkg/core/interop/runtime/engine_test.go b/pkg/core/interop/runtime/engine_test.go
index a6a23ae3e..87618e00d 100644
--- a/pkg/core/interop/runtime/engine_test.go
+++ b/pkg/core/interop/runtime/engine_test.go
@@ -7,7 +7,6 @@ import (
 	"testing"
 
 	"github.com/nspcc-dev/neo-go/internal/random"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop"
 	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
@@ -45,7 +44,7 @@ func TestPlatform(t *testing.T) {
 }
 
 func TestGetTime(t *testing.T) {
-	b := block.New(netmode.UnitTestNet, false)
+	b := block.New(false)
 	b.Timestamp = rand.Uint64()
 	ic := &interop.Context{VM: vm.New(), Block: b}
 	require.NoError(t, GetTime(ic))
diff --git a/pkg/core/native_designate_test.go b/pkg/core/native_designate_test.go
index 291457b05..386859359 100644
--- a/pkg/core/native_designate_test.go
+++ b/pkg/core/native_designate_test.go
@@ -5,7 +5,6 @@ import (
 	"testing"
 
 	"github.com/nspcc-dev/neo-go/internal/testchain"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/core/native"
 	"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
@@ -115,7 +114,7 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
 
 	des := bc.contracts.Designate
 	tx := transaction.New([]byte{}, 0)
-	bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader)
+	bl := block.New(bc.config.StateRootInHeader)
 	bl.Index = bc.BlockHeight() + 1
 	ic := bc.newInteropContext(trigger.OnPersist, bc.dao, bl, tx)
 	ic.SpawnVM()
diff --git a/pkg/core/native_oracle_test.go b/pkg/core/native_oracle_test.go
index 496928428..3c56fb00a 100644
--- a/pkg/core/native_oracle_test.go
+++ b/pkg/core/native_oracle_test.go
@@ -7,7 +7,6 @@ import (
 	"testing"
 
 	"github.com/nspcc-dev/neo-go/internal/testchain"
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
 	"github.com/nspcc-dev/neo-go/pkg/core/native"
@@ -149,7 +148,7 @@ func TestOracle_Request(t *testing.T) {
 	pub := priv.PublicKey()
 
 	tx := transaction.New([]byte{}, 0)
-	bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader)
+	bl := block.New(bc.config.StateRootInHeader)
 	bl.Index = bc.BlockHeight() + 1
 	setSigner(tx, testchain.CommitteeScriptHash())
 	ic := bc.newInteropContext(trigger.Application, bc.dao, bl, tx)
diff --git a/pkg/core/util.go b/pkg/core/util.go
index 0d104a0cb..2c1750ab8 100644
--- a/pkg/core/util.go
+++ b/pkg/core/util.go
@@ -48,7 +48,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
 			VerificationScript: []byte{byte(opcode.PUSH1)},
 		},
 		StateRootEnabled: cfg.StateRootInHeader,
-		Network:          cfg.Magic,
 	}
 
 	b := &block.Block{
diff --git a/pkg/network/message.go b/pkg/network/message.go
index 83f7927d3..80fbb68ba 100644
--- a/pkg/network/message.go
+++ b/pkg/network/message.go
@@ -145,7 +145,7 @@ func (m *Message) decodePayload() error {
 	case CMDAddr:
 		p = &payload.AddressList{}
 	case CMDBlock:
-		p = block.New(m.Network, m.StateRootInHeader)
+		p = block.New(m.StateRootInHeader)
 	case CMDExtensible:
 		p = payload.NewExtensible(m.Network)
 	case CMDP2PNotaryRequest:
@@ -157,11 +157,11 @@ func (m *Message) decodePayload() error {
 	case CMDGetBlockByIndex:
 		p = &payload.GetBlockByIndex{}
 	case CMDHeaders:
-		p = &payload.Headers{Network: m.Network, StateRootInHeader: m.StateRootInHeader}
+		p = &payload.Headers{StateRootInHeader: m.StateRootInHeader}
 	case CMDTX:
 		p = &transaction.Transaction{}
 	case CMDMerkleBlock:
-		p = &payload.MerkleBlock{Network: m.Network}
+		p = &payload.MerkleBlock{}
 	case CMDPing, CMDPong:
 		p = &payload.Ping{}
 	case CMDNotFound:
diff --git a/pkg/network/message_test.go b/pkg/network/message_test.go
index 5a6379be3..cc7155e96 100644
--- a/pkg/network/message_test.go
+++ b/pkg/network/message_test.go
@@ -204,12 +204,10 @@ func TestEncodeDecodeMerkleBlock(t *testing.T) {
 			InvocationScript:   random.Bytes(10),
 			VerificationScript: random.Bytes(11),
 		},
-		Network: netmode.UnitTestNet,
 	}
 	base.Hash()
 	t.Run("good", func(t *testing.T) {
 		testEncodeDecode(t, CMDMerkleBlock, &payload.MerkleBlock{
-			Network: netmode.UnitTestNet,
 			Header:  base,
 			TxCount: 1,
 			Hashes:  []util.Uint256{random.Uint256()},
@@ -287,7 +285,7 @@ func (f failSer) EncodeBinary(r *io.BinWriter) {
 func (failSer) DecodeBinary(w *io.BinReader) {}
 
 func newDummyBlock(height uint32, txCount int) *block.Block {
-	b := block.New(netmode.UnitTestNet, false)
+	b := block.New(false)
 	b.Index = height
 	b.PrevHash = random.Uint256()
 	b.Timestamp = rand.Uint64()
diff --git a/pkg/network/payload/headers.go b/pkg/network/payload/headers.go
index 7c8c53d30..b9b21c415 100644
--- a/pkg/network/payload/headers.go
+++ b/pkg/network/payload/headers.go
@@ -4,15 +4,13 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/io"
 )
 
 // Headers payload.
 type Headers struct {
-	Hdrs    []*block.Header
-	Network netmode.Magic
+	Hdrs []*block.Header
 	// StateRootInHeader specifies whether header contains state root.
 	StateRootInHeader bool
 }
@@ -48,7 +46,6 @@ func (p *Headers) DecodeBinary(br *io.BinReader) {
 
 	for i := 0; i < int(lenHeaders); i++ {
 		header := &block.Header{}
-		header.Network = p.Network
 		header.StateRootEnabled = p.StateRootInHeader
 		header.DecodeBinary(br)
 		p.Hdrs[i] = header
diff --git a/pkg/network/payload/merkleblock.go b/pkg/network/payload/merkleblock.go
index ac578523d..888b34e92 100644
--- a/pkg/network/payload/merkleblock.go
+++ b/pkg/network/payload/merkleblock.go
@@ -3,7 +3,6 @@ package payload
 import (
 	"errors"
 
-	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
 	"github.com/nspcc-dev/neo-go/pkg/io"
 	"github.com/nspcc-dev/neo-go/pkg/util"
@@ -12,7 +11,6 @@ import (
 // MerkleBlock represents a merkle block packet payload.
 type MerkleBlock struct {
 	*block.Header
-	Network netmode.Magic
 	TxCount int
 	Hashes  []util.Uint256
 	Flags   []byte
@@ -20,7 +18,7 @@ type MerkleBlock struct {
 
 // DecodeBinary implements Serializable interface.
 func (m *MerkleBlock) DecodeBinary(br *io.BinReader) {
-	m.Header = &block.Header{Network: m.Network}
+	m.Header = &block.Header{}
 	m.Header.DecodeBinary(br)
 
 	txCount := int(br.ReadVarUint())
diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go
index bc5c2f2bf..0f30f8771 100644
--- a/pkg/network/server_test.go
+++ b/pkg/network/server_test.go
@@ -393,7 +393,7 @@ func TestBlock(t *testing.T) {
 	atomic2.StoreUint32(&s.chain.(*fakechain.FakeChain).Blockheight, 12344)
 	require.Equal(t, uint32(12344), s.chain.BlockHeight())
 
-	b := block.New(netmode.UnitTestNet, false)
+	b := block.New(false)
 	b.Index = 12345
 	s.testHandleMessage(t, nil, CMDBlock, b)
 	require.Eventually(t, func() bool { return s.chain.BlockHeight() == 12345 }, time.Second, time.Millisecond*500)
diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go
index 60fe1e872..b2a251b3a 100644
--- a/pkg/rpc/client/rpc.go
+++ b/pkg/rpc/client/rpc.go
@@ -86,7 +86,7 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) {
 		return nil, err
 	}
 	r := io.NewBinReaderFromBuf(resp)
-	b = block.New(c.GetNetwork(), c.StateRootInHeader())
+	b = block.New(c.StateRootInHeader())
 	b.DecodeBinary(r)
 	if r.Err != nil {
 		return nil, r.Err
@@ -115,7 +115,6 @@ func (c *Client) getBlockVerbose(params request.RawParams) (*result.Block, error
 	if !c.initDone {
 		return nil, errNetworkNotInitialized
 	}
-	resp.Network = c.GetNetwork()
 	if err = c.performRequest("getblock", params, resp); err != nil {
 		return nil, err
 	}
@@ -151,7 +150,6 @@ func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) {
 	}
 	r := io.NewBinReaderFromBuf(resp)
 	h = new(block.Header)
-	h.Network = c.GetNetwork()
 	h.DecodeBinary(r)
 	if r.Err != nil {
 		return nil, r.Err
diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go
index 3368ae6f2..9268674a2 100644
--- a/pkg/rpc/client/rpc_test.go
+++ b/pkg/rpc/client/rpc_test.go
@@ -66,7 +66,7 @@ func getResultBlock1() *result.Block {
 	if err != nil {
 		panic(err)
 	}
-	b := block.New(netmode.UnitTestNet, false)
+	b := block.New(false)
 	err = testserdes.DecodeBinary(binB, b)
 	if err != nil {
 		panic(err)
diff --git a/pkg/rpc/client/wsclient.go b/pkg/rpc/client/wsclient.go
index a1a34f964..7ff486246 100644
--- a/pkg/rpc/client/wsclient.go
+++ b/pkg/rpc/client/wsclient.go
@@ -139,7 +139,7 @@ readloop:
 			var val interface{}
 			switch event {
 			case response.BlockEventID:
-				val = block.New(c.GetNetwork(), c.StateRootInHeader())
+				val = block.New(c.StateRootInHeader())
 			case response.TransactionEventID:
 				val = &transaction.Transaction{}
 			case response.NotificationEventID:
diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go
index 40a4b6bd9..57827e056 100644
--- a/pkg/rpc/server/server.go
+++ b/pkg/rpc/server/server.go
@@ -1194,7 +1194,7 @@ func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash
 	// When transferring funds, script execution does no auto GAS claim,
 	// because it depends on persisting tx height.
 	// This is why we provide block here.
-	b := block.New(s.network, s.stateRootEnabled)
+	b := block.New(s.stateRootEnabled)
 	b.Index = s.chain.BlockHeight() + 1
 	hdr, err := s.chain.GetHeader(s.chain.GetHeaderHash(int(s.chain.BlockHeight())))
 	if err != nil {
@@ -1246,7 +1246,7 @@ func (s *Server) submitBlock(reqParams request.Params) (interface{}, *response.E
 	if err != nil {
 		return nil, response.ErrInvalidParams
 	}
-	b := block.New(s.network, s.stateRootEnabled)
+	b := block.New(s.stateRootEnabled)
 	r := io.NewBinReaderFromBuf(blockBytes)
 	b.DecodeBinary(r)
 	if r.Err != nil {
diff --git a/pkg/rpc/server/server_helper_test.go b/pkg/rpc/server/server_helper_test.go
index eb81f31ce..24c18da73 100644
--- a/pkg/rpc/server/server_helper_test.go
+++ b/pkg/rpc/server/server_helper_test.go
@@ -89,7 +89,7 @@ func getTestBlocks(t *testing.T) []*block.Block {
 	blocks := make([]*block.Block, 0, int(nBlocks))
 	for i := 0; i < int(nBlocks); i++ {
 		_ = br.ReadU32LE()
-		b := block.New(netmode.UnitTestNet, false)
+		b := block.New(false)
 		b.DecodeBinary(br)
 		require.Nil(t, br.Err)
 		blocks = append(blocks, b)
diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go
index 97d83d50b..97b4dbdc3 100644
--- a/pkg/rpc/server/server_test.go
+++ b/pkg/rpc/server/server_test.go
@@ -1568,10 +1568,6 @@ func (tc rpcTestCase) getResultPair(e *executor) (expected interface{}, res inte
 	expected = tc.result(e)
 	resVal := reflect.New(reflect.TypeOf(expected).Elem())
 	res = resVal.Interface()
-	switch r := res.(type) {
-	case *result.Block:
-		r.Network = testchain.Network()
-	}
 	return expected, res
 }
 
diff --git a/scripts/gendump/main.go b/scripts/gendump/main.go
index 663d04f91..60a8024bc 100644
--- a/scripts/gendump/main.go
+++ b/scripts/gendump/main.go
@@ -161,7 +161,6 @@ func newBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs ..
 	witness := transaction.Witness{VerificationScript: script}
 	b := &block.Block{
 		Header: block.Header{
-			Network:       netmode.UnitTestNet,
 			PrevHash:      lastBlock.Hash(),
 			Timestamp:     uint64(time.Now().UTC().Unix())*1000 + uint64(lastBlock.Index),
 			Index:         lastBlock.Index + 1,