github.com/theQRL/go-zond@v0.2.1/core/state_processor_test.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"math"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/theQRL/go-qrllib/dilithium"
    25  	"github.com/theQRL/go-zond/common"
    26  	"github.com/theQRL/go-zond/consensus"
    27  	"github.com/theQRL/go-zond/consensus/beacon"
    28  	"github.com/theQRL/go-zond/consensus/misc/eip1559"
    29  	"github.com/theQRL/go-zond/core/rawdb"
    30  	"github.com/theQRL/go-zond/core/types"
    31  	"github.com/theQRL/go-zond/core/vm"
    32  	"github.com/theQRL/go-zond/crypto/pqcrypto"
    33  	"github.com/theQRL/go-zond/params"
    34  	"github.com/theQRL/go-zond/trie"
    35  	"golang.org/x/crypto/sha3"
    36  )
    37  
    38  // TestStateProcessorErrors tests the output from the 'core' errors
    39  // as defined in core/error.go. These errors are generated when the
    40  // blockchain imports bad blocks, meaning blocks which have valid headers but
    41  // contain invalid transactions
    42  func TestStateProcessorErrors(t *testing.T) {
    43  	var (
    44  		config = &params.ChainConfig{
    45  			ChainID: big.NewInt(1),
    46  		}
    47  		signer  = types.LatestSigner(config)
    48  		key1, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    49  		key2, _ = pqcrypto.HexToDilithium("0202020202020202020202020202020202020202020202020202002020202020")
    50  	)
    51  
    52  	var mkDynamicTx = func(key *dilithium.Dilithium, nonce uint64, to common.Address, value *big.Int, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction {
    53  		tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
    54  			Nonce:     nonce,
    55  			GasTipCap: gasTipCap,
    56  			GasFeeCap: gasFeeCap,
    57  			Gas:       gasLimit,
    58  			To:        &to,
    59  			Value:     value,
    60  		}), signer, key)
    61  		return tx
    62  	}
    63  	var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction {
    64  		tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
    65  			Nonce:     nonce,
    66  			GasTipCap: gasTipCap,
    67  			GasFeeCap: gasFeeCap,
    68  			Gas:       gasLimit,
    69  			Value:     big.NewInt(0),
    70  			Data:      data,
    71  		}), signer, key1)
    72  		return tx
    73  	}
    74  
    75  	{ // Tests against a 'recent' chain definition
    76  		var (
    77  			address0, _ = common.NewAddressFromString("Z20a1A68e6818a1142F85671DB01eF7226debf822")
    78  			address1, _ = common.NewAddressFromString("Z20B045A50E3C97dcf002eeFed02dB2dB22AE92A0")
    79  			db          = rawdb.NewMemoryDatabase()
    80  			gspec       = &Genesis{
    81  				Config: config,
    82  				Alloc: GenesisAlloc{
    83  					address0: GenesisAccount{
    84  						Balance: big.NewInt(1000000000000000000), // 1 ether
    85  						Nonce:   0,
    86  					},
    87  					address1: GenesisAccount{
    88  						Balance: big.NewInt(1000000000000000000), // 1 ether
    89  						Nonce:   math.MaxUint64,
    90  					},
    91  				},
    92  			}
    93  			blockchain, _  = NewBlockChain(db, nil, gspec, beacon.New(), vm.Config{}, nil)
    94  			tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
    95  		)
    96  
    97  		defer blockchain.Stop()
    98  		bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes())
    99  		tooBigNumber := new(big.Int).Set(bigNumber)
   100  		tooBigNumber.Add(tooBigNumber, common.Big1)
   101  		for i, tt := range []struct {
   102  			txs  []*types.Transaction
   103  			want string
   104  		}{
   105  
   106  			{ // ErrNonceTooLow
   107  				txs: []*types.Transaction{
   108  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(875000000)),
   109  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(875000000)),
   110  				},
   111  				want: "could not apply tx 1 [0x37e979de807f646dbe898b578ee15fe4195189c5f0587cc36cd6b7cdc84e0944]: nonce too low: address Z20a1A68e6818a1142F85671DB01eF7226debf822, tx: 0 state: 1",
   112  			},
   113  			{ // ErrNonceTooHigh
   114  				txs: []*types.Transaction{
   115  					mkDynamicTx(key1, 100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(875000000)),
   116  				},
   117  				want: "could not apply tx 0 [0x2c2f1c87166a55de4c74379ef890d519826b9d27ad79f18ee7e9328377ed62f0]: nonce too high: address Z20a1A68e6818a1142F85671DB01eF7226debf822, tx: 100 state: 0",
   118  			},
   119  			{ // ErrNonceMax
   120  				txs: []*types.Transaction{
   121  					mkDynamicTx(key2, math.MaxUint64, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(875000000)),
   122  				},
   123  				want: "could not apply tx 0 [0x2704d4d7e1fc08edbb1ce9db9133ce5e76c5f8d71a328687210e285975de2593]: nonce has max value: address Z20B045A50E3C97dcf002eeFed02dB2dB22AE92A0, nonce: 18446744073709551615",
   124  			},
   125  			{ // ErrGasLimitReached
   126  				txs: []*types.Transaction{
   127  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(0), big.NewInt(875000000)),
   128  				},
   129  				want: "could not apply tx 0 [0x3c21a534e91982a6d6c0a5c4a10ceadd901f2b19efe726e1734e7b20101e5b27]: gas limit reached",
   130  			},
   131  			{ // ErrInsufficientFundsForTransfer
   132  				txs: []*types.Transaction{
   133  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(0), big.NewInt(875000000)),
   134  				},
   135  				want: "could not apply tx 0 [0x6d3d677223a33e0d089d630cd48f1621e016f7751c6387cd2d01ed7d7dad74f6]: insufficient funds for gas * price + value: address Z20a1A68e6818a1142F85671DB01eF7226debf822 have 1000000000000000000 want 1000018375000000000",
   136  			},
   137  			{ // ErrInsufficientFunds
   138  				txs: []*types.Transaction{
   139  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(900000000000000000)),
   140  				},
   141  				want: "could not apply tx 0 [0xf6476efe6d55d950d637ecc1a53a4145f0f1786e31819a005534e7dc7671a784]: insufficient funds for gas * price + value: address Z20a1A68e6818a1142F85671DB01eF7226debf822 have 1000000000000000000 want 18900000000000000000000",
   142  			},
   143  			// ErrGasUintOverflow
   144  			// One missing 'core' error is ErrGasUintOverflow: "gas uint64 overflow",
   145  			// In order to trigger that one, we'd have to allocate a _huge_ chunk of data, such that the
   146  			// multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment
   147  			{ // ErrIntrinsicGas
   148  				txs: []*types.Transaction{
   149  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(0), big.NewInt(875000000)),
   150  				},
   151  				want: "could not apply tx 0 [0xbc6c70ca93ae96103a754d3ea8fb537ccfb17d520326de841a689261df8bfe7c]: intrinsic gas too low: have 20000, want 21000",
   152  			},
   153  			{ // ErrGasLimitReached
   154  				txs: []*types.Transaction{
   155  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(0), big.NewInt(875000000)),
   156  				},
   157  				want: "could not apply tx 0 [0x3c21a534e91982a6d6c0a5c4a10ceadd901f2b19efe726e1734e7b20101e5b27]: gas limit reached",
   158  			},
   159  			{ // ErrFeeCapTooLow
   160  				txs: []*types.Transaction{
   161  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(0), big.NewInt(0)),
   162  				},
   163  				want: "could not apply tx 0 [0x007f4e7fd50040a47f7b751e411599ceec98ee471024ed1bef594b6130077441]: max fee per gas less than block base fee: address Z20a1A68e6818a1142F85671DB01eF7226debf822, maxFeePerGas: 0 baseFee: 875000000",
   164  			},
   165  			{ // ErrTipVeryHigh
   166  				txs: []*types.Transaction{
   167  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, tooBigNumber, big.NewInt(1)),
   168  				},
   169  				want: "could not apply tx 0 [0x0230cba3bea2658e37e2bbb97cefc2db4a978d7f49f53447b478e8da13095530]: max priority fee per gas higher than 2^256-1: address Z20a1A68e6818a1142F85671DB01eF7226debf822, maxPriorityFeePerGas bit length: 257",
   170  			},
   171  			{ // ErrFeeCapVeryHigh
   172  				txs: []*types.Transaction{
   173  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(1), tooBigNumber),
   174  				},
   175  				want: "could not apply tx 0 [0xa951721a193c4f0f9b87440f7055f040ae1c9bdcc628b6b74c2d6cd18932571d]: max fee per gas higher than 2^256-1: address Z20a1A68e6818a1142F85671DB01eF7226debf822, maxFeePerGas bit length: 257",
   176  			},
   177  			{ // ErrTipAboveFeeCap
   178  				txs: []*types.Transaction{
   179  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(2), big.NewInt(1)),
   180  				},
   181  				want: "could not apply tx 0 [0xd1a81127477b4a021839f0bb7d0022f0a9d4b37d80fbc59065cb89e55080f186]: max priority fee per gas higher than max fee per gas: address Z20a1A68e6818a1142F85671DB01eF7226debf822, maxPriorityFeePerGas: 2, maxFeePerGas: 1",
   182  			},
   183  			{ // ErrInsufficientFunds
   184  				// Available balance:           1000000000000000000
   185  				// Effective cost:                   18375000021000
   186  				// FeeCap * gas:                1050000000000000000
   187  				// This test is designed to have the effective cost be covered by the balance, but
   188  				// the extended requirement on FeeCap*gas < balance to fail
   189  				txs: []*types.Transaction{
   190  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(1), big.NewInt(50000000000000)),
   191  				},
   192  				want: "could not apply tx 0 [0x5e8adfe8d09566bea3cc667f31f5e2d1fe163ba5d5f2416fbffe1dc40ee94d3a]: insufficient funds for gas * price + value: address Z20a1A68e6818a1142F85671DB01eF7226debf822 have 1000000000000000000 want 1050000000000000000",
   193  			},
   194  			{ // Another ErrInsufficientFunds, this one to ensure that feecap/tip of max u256 is allowed
   195  				txs: []*types.Transaction{
   196  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, bigNumber, bigNumber),
   197  				},
   198  				want: "could not apply tx 0 [0xb65f01b0664484b32c98ff58b7c1ad7caa273e2f03538fa1d7fa79d50e56a495]: insufficient funds for gas * price + value: address Z20a1A68e6818a1142F85671DB01eF7226debf822 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000",
   199  			},
   200  			{ // ErrMaxInitCodeSizeExceeded
   201  				txs: []*types.Transaction{
   202  					mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]),
   203  				},
   204  				want: "could not apply tx 0 [0x9768e86c54b51fe94a2e8f8e53e2f6413a653e276a967e9ea791c6bb089f4569]: max initcode size exceeded: code size 49153 limit 49152",
   205  			},
   206  			{ // ErrIntrinsicGas: Not enough gas to cover init code
   207  				txs: []*types.Transaction{
   208  					mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFee), make([]byte, 320)),
   209  				},
   210  				want: "could not apply tx 0 [0x03f7383676e51027633080c0210c307f346f57e81561489780004f6b020b4d98]: intrinsic gas too low: have 54299, want 54300",
   211  			},
   212  		} {
   213  			block := GenerateBadBlock(gspec.ToBlock(), beacon.New(), tt.txs, gspec.Config)
   214  			_, err := blockchain.InsertChain(types.Blocks{block})
   215  			if err == nil {
   216  				t.Fatal("block imported without errors")
   217  			}
   218  			if have, want := err.Error(), tt.want; have != want {
   219  				t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want)
   220  			}
   221  		}
   222  	}
   223  
   224  	// NOTE(rgeraldes24): test not valid for now
   225  	/*
   226  		// ErrTxTypeNotSupported, For this, we need an older chain
   227  		{
   228  			var (
   229  				db    = rawdb.NewMemoryDatabase()
   230  				gspec = &Genesis{
   231  					Config: &params.ChainConfig{
   232  						ChainID: big.NewInt(1),
   233  					},
   234  					Alloc: GenesisAlloc{
   235  						common.HexToAddress("Z71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
   236  							Balance: big.NewInt(1000000000000000000), // 1 ether
   237  							Nonce:   0,
   238  						},
   239  					},
   240  				}
   241  				blockchain, _ = NewBlockChain(db, nil, gspec, beacon.NewFaker(), vm.Config{}, nil)
   242  			)
   243  			defer blockchain.Stop()
   244  			for i, tt := range []struct {
   245  				txs  []*types.Transaction
   246  				want string
   247  			}{
   248  				{ // ErrTxTypeNotSupported
   249  					txs: []*types.Transaction{
   250  						mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)),
   251  					},
   252  					want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported",
   253  				},
   254  			} {
   255  				block := GenerateBadBlock(gspec.ToBlock(), beacon.NewFaker(), tt.txs, gspec.Config)
   256  				_, err := blockchain.InsertChain(types.Blocks{block})
   257  				if err == nil {
   258  					t.Fatal("block imported without errors")
   259  				}
   260  				if have, want := err.Error(), tt.want; have != want {
   261  					t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want)
   262  				}
   263  			}
   264  		}
   265  	*/
   266  
   267  	// ErrSenderNoEOA, for this we need the sender to have contract code
   268  	{
   269  		var (
   270  			address, _ = common.NewAddressFromString("Z20a1A68e6818a1142F85671DB01eF7226debf822")
   271  			db         = rawdb.NewMemoryDatabase()
   272  			gspec      = &Genesis{
   273  				Config: config,
   274  				Alloc: GenesisAlloc{
   275  					address: GenesisAccount{
   276  						Balance: big.NewInt(1000000000000000000), // 1 ether
   277  						Nonce:   0,
   278  						Code:    common.FromHex("0xB0B0FACE"),
   279  					},
   280  				},
   281  			}
   282  			blockchain, _ = NewBlockChain(db, nil, gspec, beacon.New(), vm.Config{}, nil)
   283  		)
   284  		defer blockchain.Stop()
   285  		for i, tt := range []struct {
   286  			txs  []*types.Transaction
   287  			want string
   288  		}{
   289  			{ // ErrSenderNoEOA
   290  				txs: []*types.Transaction{
   291  					mkDynamicTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), big.NewInt(0)),
   292  				},
   293  				want: "could not apply tx 0 [0xbdd680bc60f0a72adc477e41ab160216daa660c40e907fa568e1b86952670390]: sender not an eoa: address Z20a1A68e6818a1142F85671DB01eF7226debf822, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1",
   294  			},
   295  		} {
   296  			block := GenerateBadBlock(gspec.ToBlock(), beacon.New(), tt.txs, gspec.Config)
   297  			_, err := blockchain.InsertChain(types.Blocks{block})
   298  			if err == nil {
   299  				t.Fatal("block imported without errors")
   300  			}
   301  			if have, want := err.Error(), tt.want; have != want {
   302  				t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want)
   303  			}
   304  		}
   305  	}
   306  }
   307  
   308  // GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be
   309  // valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently
   310  // valid to be considered for import:
   311  // - valid pow (fake), ancestry, difficulty, gaslimit etc
   312  func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block {
   313  	header := &types.Header{
   314  		ParentHash: parent.Hash(),
   315  		Coinbase:   parent.Coinbase(),
   316  		GasLimit:   parent.GasLimit(),
   317  		Number:     new(big.Int).Add(parent.Number(), common.Big1),
   318  		Time:       parent.Time() + 10,
   319  	}
   320  	header.BaseFee = eip1559.CalcBaseFee(config, parent.Header())
   321  	header.WithdrawalsHash = &types.EmptyWithdrawalsHash
   322  	var receipts []*types.Receipt
   323  	// The post-state result doesn't need to be correct (this is a bad block), but we do need something there
   324  	// Preferably something unique. So let's use a combo of blocknum + txhash
   325  	hasher := sha3.NewLegacyKeccak256()
   326  	hasher.Write(header.Number.Bytes())
   327  	var cumulativeGas uint64
   328  	for _, tx := range txs {
   329  		txh := tx.Hash()
   330  		hasher.Write(txh[:])
   331  		receipt := &types.Receipt{
   332  			Type:              types.DynamicFeeTxType,
   333  			PostState:         common.CopyBytes(nil),
   334  			CumulativeGasUsed: cumulativeGas + tx.Gas(),
   335  			Status:            types.ReceiptStatusSuccessful,
   336  		}
   337  		receipt.TxHash = tx.Hash()
   338  		receipt.GasUsed = tx.Gas()
   339  		receipts = append(receipts, receipt)
   340  		cumulativeGas += tx.Gas()
   341  	}
   342  	header.Root = common.BytesToHash(hasher.Sum(nil))
   343  
   344  	// Assemble and return the final block for sealing
   345  	body := &types.Body{Transactions: txs, Withdrawals: []*types.Withdrawal{}}
   346  	return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
   347  }