github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/block/block_test.go (about)

     1  package block
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    11  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    12  	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
    13  	"github.com/nspcc-dev/neo-go/pkg/encoding/address"
    14  	"github.com/nspcc-dev/neo-go/pkg/io"
    15  	"github.com/nspcc-dev/neo-go/pkg/util"
    16  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func trim0x(value any) string {
    22  	s := value.(string)
    23  	return strings.TrimPrefix(s, "0x")
    24  }
    25  
    26  // Test blocks are blocks from testnet with their corresponding indices.
    27  func TestDecodeBlock1(t *testing.T) {
    28  	data, err := getBlockData(1)
    29  	require.NoError(t, err)
    30  
    31  	b, err := hex.DecodeString(data["raw"].(string))
    32  	require.NoError(t, err)
    33  
    34  	block := New(false)
    35  	assert.NoError(t, testserdes.DecodeBinary(b, block))
    36  
    37  	assert.Equal(t, uint32(data["index"].(float64)), block.Index)
    38  	assert.Equal(t, uint32(data["version"].(float64)), block.Version)
    39  	assert.Equal(t, trim0x(data["hash"]), block.Hash().StringLE())
    40  	assert.Equal(t, trim0x(data["previousblockhash"]), block.PrevHash.StringLE())
    41  	assert.Equal(t, trim0x(data["merkleroot"]), block.MerkleRoot.StringLE())
    42  	assert.Equal(t, trim0x(data["nextconsensus"]), address.Uint160ToString(block.NextConsensus))
    43  
    44  	scripts := data["witnesses"].([]any)
    45  	script := scripts[0].(map[string]any)
    46  	assert.Equal(t, script["invocation"].(string), base64.StdEncoding.EncodeToString(block.Script.InvocationScript))
    47  	assert.Equal(t, script["verification"].(string), base64.StdEncoding.EncodeToString(block.Script.VerificationScript))
    48  
    49  	tx := data["tx"].([]any)
    50  	tx0 := tx[0].(map[string]any)
    51  	assert.Equal(t, len(tx), len(block.Transactions))
    52  	assert.Equal(t, len(tx0["attributes"].([]any)), len(block.Transactions[0].Attributes))
    53  }
    54  
    55  func TestTrimmedBlock(t *testing.T) {
    56  	block := getDecodedBlock(t, 1)
    57  
    58  	buf := io.NewBufBinWriter()
    59  	block.EncodeTrimmed(buf.BinWriter)
    60  	require.NoError(t, buf.Err)
    61  
    62  	r := io.NewBinReaderFromBuf(buf.Bytes())
    63  	trimmedBlock, err := NewTrimmedFromReader(false, r)
    64  	require.NoError(t, err)
    65  
    66  	assert.True(t, trimmedBlock.Trimmed)
    67  	assert.Equal(t, block.Version, trimmedBlock.Version)
    68  	assert.Equal(t, block.PrevHash, trimmedBlock.PrevHash)
    69  	assert.Equal(t, block.MerkleRoot, trimmedBlock.MerkleRoot)
    70  	assert.Equal(t, block.Timestamp, trimmedBlock.Timestamp)
    71  	assert.Equal(t, block.Index, trimmedBlock.Index)
    72  	assert.Equal(t, block.NextConsensus, trimmedBlock.NextConsensus)
    73  
    74  	assert.Equal(t, block.Script, trimmedBlock.Script)
    75  	assert.Equal(t, len(block.Transactions), len(trimmedBlock.Transactions))
    76  	for i := 0; i < len(block.Transactions); i++ {
    77  		assert.Equal(t, block.Transactions[i].Hash(), trimmedBlock.Transactions[i].Hash())
    78  		assert.True(t, trimmedBlock.Transactions[i].Trimmed)
    79  	}
    80  }
    81  
    82  func newDumbBlock() *Block {
    83  	return &Block{
    84  		Header: Header{
    85  			Version:       0,
    86  			PrevHash:      hash.Sha256([]byte("a")),
    87  			MerkleRoot:    hash.Sha256([]byte("b")),
    88  			Timestamp:     100500,
    89  			Index:         1,
    90  			NextConsensus: hash.Hash160([]byte("a")),
    91  			Script: transaction.Witness{
    92  				VerificationScript: []byte{0x51}, // PUSH1
    93  				InvocationScript:   []byte{0x61}, // NOP
    94  			},
    95  		},
    96  		Transactions: []*transaction.Transaction{
    97  			transaction.New([]byte{byte(opcode.PUSH1)}, 0),
    98  		},
    99  	}
   100  }
   101  
   102  func TestHashBlockEqualsHashHeader(t *testing.T) {
   103  	block := newDumbBlock()
   104  
   105  	assert.Equal(t, block.Hash(), block.Header.Hash())
   106  }
   107  
   108  func TestBinBlockDecodeEncode(t *testing.T) {
   109  	// block with two transfer transactions taken from C# privnet
   110  	rawblock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAAAAAAAAAAAAQAAAADe7nnBifMAmLC6ai65CzqSWKbH/wHGDEDgwCcXkcaFw5MGOp1cpkgApzDTX2/RxKlmPeXTgWYtfEA8g9svUSbZA4TeoGyWvX8LiN0tJKrzajdMGvTVGqVmDEDp6PBmZmRx9CxswtLht6oWa2Uq4rl5diPsLtqXZeZepMlxUSbaCdlFTB7iWQG9yKXWR5hc0sScevvuVwwsUYdlDEDwlhwZrP07E5fEQKttVMYAiL7edd/eW2yoMGZe6Q95g7yXQ69edVHfQb61fBw3DjCpMDZ5lsxp3BgzXglJwMSKkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQIAWNC7C8DYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBbCwIA4fUFDBSAzse29bVvUFePc38WLTqxTUZlDQwU3u55wYnzAJiwumouuQs6klimx/8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQHGDEC4UIzT61GYPx0LdksrF6C2ioYai6fbwpjv3BGAqiyagxiomYGZRLeXZyD67O5FJ86pXRFtSbVYu2YDG+T5ICIgDEDzm/wl+BnHvQXaHQ1rGLtdUMc41wN6I48kPPM7F23gL9sVxGziQIMRLnpTbWHrnzaU9Sy0fXkvIrdJy1KABkSQDEDBwuBuVK+nsZvn1oAscPj6d3FJiUGK9xiHpX9Ipp/5jTnXRBAyzyGc8IZMBVql4WS8kwFe6ojA/9BvFb5eWXnEkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQDYJLwZwNinAAAAAAAgqkQAAAAAAOgDAAAB3u55wYnzAJiwumouuQs6klimx/8BAF8LAwBA2d2ITQoADBSAzse29bVvUFePc38WLTqxTUZlDQwU3u55wYnzAJiwumouuQs6klimx/8UwB8MCHRyYW5zZmVyDBTPduKL0AYsSkeO41VhARMZ88+k0kFifVtSOQHGDEDWn0D7z2ELqpN8ghcM/PtfFwo56/BfEasfHuSKECJMYxvU47r2ZtSihg59lGxSZzHsvxTy6nsyvJ22ycNhINdJDECl61cg937N/HujKsLMu2wJMS7C54bzJ3q22Czqllvw3Yp809USgKDs+W+3QD7rI+SFs0OhIn0gooCUU6f/13WjDEDr9XdeT5CGTO8CL0JigzcTcucs0GBcqHs8fToO6zPuuCfS7Wh6dyxSCijT4A4S+7BUdW3dsO7828ke1fj8oNxmkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQ=="
   111  	rawblockBytes, _ := base64.StdEncoding.DecodeString(rawblock)
   112  
   113  	b := New(false)
   114  
   115  	assert.NoError(t, testserdes.DecodeBinary(rawblockBytes, b))
   116  	expected := map[string]bool{ // 1 trans
   117  		"5a30127b16a628de6aa6823418d76214b97a0fc6db865024d3d2c6e939ce3433": false,
   118  		"25426643feed564cd3e57f346d6c68692f5622b3063da11c5572d99ee1a5b49a": false,
   119  	}
   120  
   121  	var hashes []string
   122  
   123  	for _, tx := range b.Transactions {
   124  		hashes = append(hashes, tx.Hash().StringLE())
   125  	}
   126  
   127  	assert.Equal(t, len(expected), len(hashes))
   128  
   129  	// changes value in map to true, if hash is found
   130  	for _, hash := range hashes {
   131  		expected[hash] = true
   132  	}
   133  
   134  	// iterate map; all values should be true
   135  	val := true
   136  	for _, v := range expected {
   137  		if v == false {
   138  			val = false
   139  		}
   140  	}
   141  	assert.Equal(t, true, val)
   142  
   143  	data, err := testserdes.EncodeBinary(b)
   144  	assert.NoError(t, err)
   145  	assert.Equal(t, rawblock, base64.StdEncoding.EncodeToString(data))
   146  
   147  	testserdes.MarshalUnmarshalJSON(t, b, New(false))
   148  }
   149  
   150  func TestJSONEmptyTx(t *testing.T) {
   151  	jblock := `{"hash":"0x5f3fbb43d1e516fe07771e2e873ebc9e2810662401acf603a775aace486220bd","version":0,"previousblockhash":"0x1f4d1defa46faa5e7b9b8d3f79a06bec777d7c26c4aa5f6f5899a291daa87c15","merkleroot":"0x0000000000000000000000000000000000000000000000000000000000000000","time":1627894840919,"nonce":"BA8E021F1AEEA3F6","index":1,"nextconsensus":"NVg7LjGcUSrgxgjX3zEgqaksfMaiS8Z6e1","primary":0,"witnesses":[{"invocation":"DEAq7W/jUhpMon1t9muqXKfBvNyGwLfFFM1vAxrMKvUl6MqK+LL/lJAJP9uAk/cberIWWhSsdcxUtltkBLemg/VuDECQZGuvP93JlZga2ml8cnbe5cNiGgO0EMrbGYyzvgr8calP5SwMNPSYms10gIHxlsuXDU++EQpZu/vKxfHoxdC5DEDgsA3POVZdfN+i5+ekvtsaIvif42n0GC+dZi3Rp37ETmt4NtkoK2I2UXi+WIjm5yXLJsPhAvEV6cJSrvqBdsQBDEDTS6NU+kB+tgeBe9lWv+6y0L2qcUBIaUxiTCaNWZtLPghQICBvjDz1/9ttJRXG3I5N9CFDjjLKCpdIY842HW4/DEC+wlWjkCzVqzKslvpCKZbEPUGIf87CFAD88xqzl26m/TpTUcT0+D5oI2bVzAk0mcdBTPnyjcNbv17BFmr63+09","verification":"FQwhAkhv0VcCxEkKJnAxEqXMHQkj/Wl6M0Br1aHADgATsJpwDCECTHt/tsMQ/M8bozsIJRnYKWTqk4aNZ2Zi1KWa1UjfDn0MIQKq7DhHD2qtAELG6HfP2Ah9Jnaw9Rb93TYoAbm9OTY5ngwhA7IJ/U9TpxcOpERODLCmu2pTwr0BaSaYnPhfmw+6F6cMDCEDuNnVdx2PUTqghpucyNUJhkA7eMbaNokGOMPUalrc4EoMIQLKDidpe5wkj28W4IX9AGHib0TahbWO6DXBEMql7DulVAwhAt9I9g6PPgHEj/QLm38TENeosqGTGIvv4cLj33QOiVCTF0Ge0Nw6"}],"tx":[]}`
   152  	b := New(false)
   153  	require.NoError(t, json.Unmarshal([]byte(jblock), b))
   154  	s, err := json.Marshal(b)
   155  	require.NoError(t, err)
   156  	require.JSONEq(t, jblock, string(s))
   157  }
   158  
   159  func TestBlockSizeCalculation(t *testing.T) {
   160  	// block taken from C# privnet: 02d7c7801742cd404eb178780c840477f1eef4a771ecc8cc9434640fe8f2bb09
   161  	// The Size in golang is given by counting the number of bytes of an object. (len(Bytes))
   162  	// its implementation is different from the corresponding C# and python implementations. But the result should
   163  	// be the same. In this test we provide more details then necessary because in case of failure we can easily debug the
   164  	// root cause of the size calculation missmatch.
   165  
   166  	rawBlock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAAAAAAAAAAAAQAAAADe7nnBifMAmLC6ai65CzqSWKbH/wHGDEDgwCcXkcaFw5MGOp1cpkgApzDTX2/RxKlmPeXTgWYtfEA8g9svUSbZA4TeoGyWvX8LiN0tJKrzajdMGvTVGqVmDEDp6PBmZmRx9CxswtLht6oWa2Uq4rl5diPsLtqXZeZepMlxUSbaCdlFTB7iWQG9yKXWR5hc0sScevvuVwwsUYdlDEDwlhwZrP07E5fEQKttVMYAiL7edd/eW2yoMGZe6Q95g7yXQ69edVHfQb61fBw3DjCpMDZ5lsxp3BgzXglJwMSKkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQIAWNC7C8DYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBbCwIA4fUFDBSAzse29bVvUFePc38WLTqxTUZlDQwU3u55wYnzAJiwumouuQs6klimx/8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQHGDEC4UIzT61GYPx0LdksrF6C2ioYai6fbwpjv3BGAqiyagxiomYGZRLeXZyD67O5FJ86pXRFtSbVYu2YDG+T5ICIgDEDzm/wl+BnHvQXaHQ1rGLtdUMc41wN6I48kPPM7F23gL9sVxGziQIMRLnpTbWHrnzaU9Sy0fXkvIrdJy1KABkSQDEDBwuBuVK+nsZvn1oAscPj6d3FJiUGK9xiHpX9Ipp/5jTnXRBAyzyGc8IZMBVql4WS8kwFe6ojA/9BvFb5eWXnEkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQDYJLwZwNinAAAAAAAgqkQAAAAAAOgDAAAB3u55wYnzAJiwumouuQs6klimx/8BAF8LAwBA2d2ITQoADBSAzse29bVvUFePc38WLTqxTUZlDQwU3u55wYnzAJiwumouuQs6klimx/8UwB8MCHRyYW5zZmVyDBTPduKL0AYsSkeO41VhARMZ88+k0kFifVtSOQHGDEDWn0D7z2ELqpN8ghcM/PtfFwo56/BfEasfHuSKECJMYxvU47r2ZtSihg59lGxSZzHsvxTy6nsyvJ22ycNhINdJDECl61cg937N/HujKsLMu2wJMS7C54bzJ3q22Czqllvw3Yp809USgKDs+W+3QD7rI+SFs0OhIn0gooCUU6f/13WjDEDr9XdeT5CGTO8CL0JigzcTcucs0GBcqHs8fToO6zPuuCfS7Wh6dyxSCijT4A4S+7BUdW3dsO7828ke1fj8oNxmkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBe85spQ=="
   167  	rawBlockBytes, _ := base64.StdEncoding.DecodeString(rawBlock)
   168  
   169  	b := New(false)
   170  	assert.NoError(t, testserdes.DecodeBinary(rawBlockBytes, b))
   171  
   172  	expected := []struct {
   173  		ID            string
   174  		Size          int
   175  		Version       int
   176  		SignersLen    int
   177  		AttributesLen int
   178  		WitnessesLen  int
   179  	}{ // 2 transactions
   180  		{ID: "5a30127b16a628de6aa6823418d76214b97a0fc6db865024d3d2c6e939ce3433", Size: 488, Version: 0, SignersLen: 1, AttributesLen: 0, WitnessesLen: 1},
   181  		{ID: "25426643feed564cd3e57f346d6c68692f5622b3063da11c5572d99ee1a5b49a", Size: 492, Version: 0, SignersLen: 1, AttributesLen: 0, WitnessesLen: 1},
   182  	}
   183  
   184  	for i, tx := range b.Transactions {
   185  		txID := tx.Hash()
   186  		assert.Equal(t, expected[i].ID, txID.StringLE())
   187  
   188  		assert.Equal(t, expected[i].Size, io.GetVarSize(tx))
   189  		assert.Equal(t, expected[i].Version, int(tx.Version))
   190  		assert.Equal(t, expected[i].SignersLen, len(tx.Signers))
   191  		assert.Equal(t, expected[i].AttributesLen, len(tx.Attributes))
   192  		assert.Equal(t, expected[i].WitnessesLen, len(tx.Scripts))
   193  	}
   194  
   195  	assert.Equal(t, len(expected), len(b.Transactions))
   196  
   197  	// Block specific tests
   198  	assert.Equal(t, 0, int(b.Version))
   199  	assert.Equal(t, "5b60644c6c6f58faca72c70689d7ed1f40c2e795772bd0de5a88e983ad55080c", b.PrevHash.StringLE())
   200  	assert.Equal(t, "95c4d3ef673a732bf399459c7949d0f6e774ecf8c50f282bedad1f0b1c0de590", b.MerkleRoot.StringLE())
   201  	assert.Equal(t, 1616078164001, int(b.Timestamp))
   202  	assert.Equal(t, 1, int(b.Index))
   203  
   204  	nextConsensus := address.Uint160ToString(b.NextConsensus)
   205  	assert.Equal(t, "NgEisvCqr2h8wpRxQb7bVPWUZdbVCY8Uo6", nextConsensus)
   206  
   207  	assert.Equal(t, "DEDgwCcXkcaFw5MGOp1cpkgApzDTX2/RxKlmPeXTgWYtfEA8g9svUSbZA4TeoGyWvX8LiN0tJKrzajdMGvTVGqVmDEDp6PBmZmRx9CxswtLht6oWa2Uq4rl5diPsLtqXZeZepMlxUSbaCdlFTB7iWQG9yKXWR5hc0sScevvuVwwsUYdlDEDwlhwZrP07E5fEQKttVMYAiL7edd/eW2yoMGZe6Q95g7yXQ69edVHfQb61fBw3DjCpMDZ5lsxp3BgzXglJwMSK", base64.StdEncoding.EncodeToString(b.Script.InvocationScript))
   208  	assert.Equal(t, "EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFEF7zmyl", base64.StdEncoding.EncodeToString(b.Script.VerificationScript))
   209  	assert.Equal(t, "0285238e7b5d3ca50ae8f8636dedb4fa486bc0536016e1f1edfd74442af7412e", b.Hash().StringLE())
   210  
   211  	benc, err := testserdes.EncodeBinary(b)
   212  	assert.NoError(t, err)
   213  	// test size of the block
   214  	assert.Equal(t, 1438, len(benc))
   215  	assert.Equal(t, rawBlock, base64.StdEncoding.EncodeToString(benc))
   216  }
   217  
   218  func TestBlockEncodeDecode(t *testing.T) {
   219  	t.Run("positive", func(t *testing.T) {
   220  		b := newDumbBlock()
   221  		b.Transactions = []*transaction.Transaction{}
   222  		_ = b.Hash()
   223  		testserdes.EncodeDecodeBinary(t, b, new(Block))
   224  	})
   225  
   226  	t.Run("bad contents count", func(t *testing.T) {
   227  		b := newDumbBlock()
   228  		b.Transactions = make([]*transaction.Transaction, MaxTransactionsPerBlock+1)
   229  		for i := range b.Transactions {
   230  			b.Transactions[i] = &transaction.Transaction{
   231  				Script: []byte("my_pretty_script"),
   232  			}
   233  		}
   234  		_ = b.Hash()
   235  		data, err := testserdes.EncodeBinary(b)
   236  		require.NoError(t, err)
   237  
   238  		require.ErrorIs(t, testserdes.DecodeBinary(data, new(Block)), ErrMaxContentsPerBlock)
   239  	})
   240  }
   241  
   242  func TestGetExpectedBlockSize(t *testing.T) {
   243  	check := func(t *testing.T, stateRootEnabled bool) {
   244  		t.Run("without transactions", func(t *testing.T) {
   245  			b := newDumbBlock()
   246  			b.StateRootEnabled = stateRootEnabled
   247  			b.Transactions = []*transaction.Transaction{}
   248  			require.Equal(t, io.GetVarSize(b), b.GetExpectedBlockSize())
   249  			require.Equal(t, io.GetVarSize(b), b.GetExpectedBlockSizeWithoutTransactions(0))
   250  		})
   251  		t.Run("with one transaction", func(t *testing.T) {
   252  			b := newDumbBlock()
   253  			b.StateRootEnabled = stateRootEnabled
   254  			expected := io.GetVarSize(b)
   255  			require.Equal(t, expected, b.GetExpectedBlockSize())
   256  			require.Equal(t, expected-b.Transactions[0].Size(), b.GetExpectedBlockSizeWithoutTransactions(len(b.Transactions)))
   257  		})
   258  		t.Run("with multiple transactions", func(t *testing.T) {
   259  			b := newDumbBlock()
   260  			b.StateRootEnabled = stateRootEnabled
   261  			b.Transactions = make([]*transaction.Transaction, 123)
   262  			for i := range b.Transactions {
   263  				tx := transaction.New([]byte{byte(opcode.RET)}, int64(i))
   264  				tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}
   265  				tx.Scripts = []transaction.Witness{{}}
   266  				b.Transactions[i] = tx
   267  			}
   268  			expected := io.GetVarSize(b)
   269  			require.Equal(t, expected, b.GetExpectedBlockSize())
   270  			for _, tx := range b.Transactions {
   271  				expected -= tx.Size()
   272  			}
   273  			require.Equal(t, expected, b.GetExpectedBlockSizeWithoutTransactions(len(b.Transactions)))
   274  		})
   275  	}
   276  	t.Run("StateRoot enabled", func(t *testing.T) {
   277  		check(t, true)
   278  	})
   279  	t.Run("StateRoot disabled", func(t *testing.T) {
   280  		check(t, false)
   281  	})
   282  }