github.com/mysteriumnetwork/go-ethereum@v1.11.0/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 "crypto/ecdsa" 21 "math/big" 22 "testing" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/math" 26 "github.com/ethereum/go-ethereum/consensus" 27 "github.com/ethereum/go-ethereum/consensus/ethash" 28 "github.com/ethereum/go-ethereum/consensus/misc" 29 "github.com/ethereum/go-ethereum/core/rawdb" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/core/vm" 32 "github.com/ethereum/go-ethereum/crypto" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/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 = ¶ms.ChainConfig{ 45 ChainID: big.NewInt(1), 46 HomesteadBlock: big.NewInt(0), 47 EIP150Block: big.NewInt(0), 48 EIP155Block: big.NewInt(0), 49 EIP158Block: big.NewInt(0), 50 ByzantiumBlock: big.NewInt(0), 51 ConstantinopleBlock: big.NewInt(0), 52 PetersburgBlock: big.NewInt(0), 53 IstanbulBlock: big.NewInt(0), 54 MuirGlacierBlock: big.NewInt(0), 55 BerlinBlock: big.NewInt(0), 56 LondonBlock: big.NewInt(0), 57 Ethash: new(params.EthashConfig), 58 } 59 signer = types.LatestSigner(config) 60 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 61 key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020") 62 ) 63 var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction { 64 tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key) 65 return tx 66 } 67 var mkDynamicTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction { 68 tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ 69 Nonce: nonce, 70 GasTipCap: gasTipCap, 71 GasFeeCap: gasFeeCap, 72 Gas: gasLimit, 73 To: &to, 74 Value: big.NewInt(0), 75 }), signer, key1) 76 return tx 77 } 78 { // Tests against a 'recent' chain definition 79 var ( 80 db = rawdb.NewMemoryDatabase() 81 gspec = &Genesis{ 82 Config: config, 83 Alloc: GenesisAlloc{ 84 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ 85 Balance: big.NewInt(1000000000000000000), // 1 ether 86 Nonce: 0, 87 }, 88 common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{ 89 Balance: big.NewInt(1000000000000000000), // 1 ether 90 Nonce: math.MaxUint64, 91 }, 92 }, 93 } 94 genesis = gspec.MustCommit(db) 95 blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 96 ) 97 defer blockchain.Stop() 98 bigNumber := new(big.Int).SetBytes(common.FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) 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 { // ErrNonceTooLow 106 txs: []*types.Transaction{ 107 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 108 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 109 }, 110 want: "could not apply tx 1 [0x0026256b3939ed97e2c4a6f3fce8ecf83bdcfa6d507c47838c308a1fb0436f62]: nonce too low: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 0 state: 1", 111 }, 112 { // ErrNonceTooHigh 113 txs: []*types.Transaction{ 114 makeTx(key1, 100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 115 }, 116 want: "could not apply tx 0 [0xdebad714ca7f363bd0d8121c4518ad48fa469ca81b0a081be3d10c17460f751b]: nonce too high: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 100 state: 0", 117 }, 118 { // ErrNonceMax 119 txs: []*types.Transaction{ 120 makeTx(key2, math.MaxUint64, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 121 }, 122 want: "could not apply tx 0 [0x84ea18d60eb2bb3b040e3add0eb72f757727122cc257dd858c67cb6591a85986]: nonce has max value: address 0xfd0810DD14796680f72adf1a371963d0745BCc64, nonce: 18446744073709551615", 123 }, 124 { // ErrGasLimitReached 125 txs: []*types.Transaction{ 126 makeTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil), 127 }, 128 want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", 129 }, 130 { // ErrInsufficientFundsForTransfer 131 txs: []*types.Transaction{ 132 makeTx(key1, 0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil), 133 }, 134 want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000", 135 }, 136 { // ErrInsufficientFunds 137 txs: []*types.Transaction{ 138 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(900000000000000000), nil), 139 }, 140 want: "could not apply tx 0 [0x4a69690c4b0cd85e64d0d9ea06302455b01e10a83db964d60281739752003440]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 18900000000000000000000", 141 }, 142 // ErrGasUintOverflow 143 // One missing 'core' error is ErrGasUintOverflow: "gas uint64 overflow", 144 // In order to trigger that one, we'd have to allocate a _huge_ chunk of data, such that the 145 // multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment 146 { // ErrIntrinsicGas 147 txs: []*types.Transaction{ 148 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), nil), 149 }, 150 want: "could not apply tx 0 [0xcf3b049a0b516cb4f9274b3e2a264359e2ba53b2fb64b7bda2c634d5c9d01fca]: intrinsic gas too low: have 20000, want 21000", 151 }, 152 { // ErrGasLimitReached 153 txs: []*types.Transaction{ 154 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil), 155 }, 156 want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", 157 }, 158 { // ErrFeeCapTooLow 159 txs: []*types.Transaction{ 160 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(0), big.NewInt(0)), 161 }, 162 want: "could not apply tx 0 [0xc4ab868fef0c82ae0387b742aee87907f2d0fc528fc6ea0a021459fb0fc4a4a8]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 0 baseFee: 875000000", 163 }, 164 { // ErrTipVeryHigh 165 txs: []*types.Transaction{ 166 mkDynamicTx(0, common.Address{}, params.TxGas, tooBigNumber, big.NewInt(1)), 167 }, 168 want: "could not apply tx 0 [0x15b8391b9981f266b32f3ab7da564bbeb3d6c21628364ea9b32a21139f89f712]: max priority fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas bit length: 257", 169 }, 170 { // ErrFeeCapVeryHigh 171 txs: []*types.Transaction{ 172 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), tooBigNumber), 173 }, 174 want: "could not apply tx 0 [0x48bc299b83fdb345c57478f239e89814bb3063eb4e4b49f3b6057a69255c16bd]: max fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas bit length: 257", 175 }, 176 { // ErrTipAboveFeeCap 177 txs: []*types.Transaction{ 178 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(2), big.NewInt(1)), 179 }, 180 want: "could not apply tx 0 [0xf987a31ff0c71895780a7612f965a0c8b056deb54e020bb44fa478092f14c9b4]: max priority fee per gas higher than max fee per gas: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas: 2, maxFeePerGas: 1", 181 }, 182 { // ErrInsufficientFunds 183 // Available balance: 1000000000000000000 184 // Effective cost: 18375000021000 185 // FeeCap * gas: 1050000000000000000 186 // This test is designed to have the effective cost be covered by the balance, but 187 // the extended requirement on FeeCap*gas < balance to fail 188 txs: []*types.Transaction{ 189 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(50000000000000)), 190 }, 191 want: "could not apply tx 0 [0x413603cd096a87f41b1660d3ed3e27d62e1da78eac138961c0a1314ed43bd129]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1050000000000000000", 192 }, 193 { // Another ErrInsufficientFunds, this one to ensure that feecap/tip of max u256 is allowed 194 txs: []*types.Transaction{ 195 mkDynamicTx(0, common.Address{}, params.TxGas, bigNumber, bigNumber), 196 }, 197 want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000", 198 }, 199 } { 200 block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config) 201 _, err := blockchain.InsertChain(types.Blocks{block}) 202 if err == nil { 203 t.Fatal("block imported without errors") 204 } 205 if have, want := err.Error(), tt.want; have != want { 206 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 207 } 208 } 209 } 210 211 // ErrTxTypeNotSupported, For this, we need an older chain 212 { 213 var ( 214 db = rawdb.NewMemoryDatabase() 215 gspec = &Genesis{ 216 Config: ¶ms.ChainConfig{ 217 ChainID: big.NewInt(1), 218 HomesteadBlock: big.NewInt(0), 219 EIP150Block: big.NewInt(0), 220 EIP155Block: big.NewInt(0), 221 EIP158Block: big.NewInt(0), 222 ByzantiumBlock: big.NewInt(0), 223 ConstantinopleBlock: big.NewInt(0), 224 PetersburgBlock: big.NewInt(0), 225 IstanbulBlock: big.NewInt(0), 226 MuirGlacierBlock: big.NewInt(0), 227 }, 228 Alloc: GenesisAlloc{ 229 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ 230 Balance: big.NewInt(1000000000000000000), // 1 ether 231 Nonce: 0, 232 }, 233 }, 234 } 235 genesis = gspec.MustCommit(db) 236 blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 237 ) 238 defer blockchain.Stop() 239 for i, tt := range []struct { 240 txs []*types.Transaction 241 want string 242 }{ 243 { // ErrTxTypeNotSupported 244 txs: []*types.Transaction{ 245 mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), 246 }, 247 want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported", 248 }, 249 } { 250 block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config) 251 _, err := blockchain.InsertChain(types.Blocks{block}) 252 if err == nil { 253 t.Fatal("block imported without errors") 254 } 255 if have, want := err.Error(), tt.want; have != want { 256 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 257 } 258 } 259 } 260 261 // ErrSenderNoEOA, for this we need the sender to have contract code 262 { 263 var ( 264 db = rawdb.NewMemoryDatabase() 265 gspec = &Genesis{ 266 Config: config, 267 Alloc: GenesisAlloc{ 268 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ 269 Balance: big.NewInt(1000000000000000000), // 1 ether 270 Nonce: 0, 271 Code: common.FromHex("0xB0B0FACE"), 272 }, 273 }, 274 } 275 genesis = gspec.MustCommit(db) 276 blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 277 ) 278 defer blockchain.Stop() 279 for i, tt := range []struct { 280 txs []*types.Transaction 281 want string 282 }{ 283 { // ErrSenderNoEOA 284 txs: []*types.Transaction{ 285 mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), 286 }, 287 want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", 288 }, 289 } { 290 block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config) 291 _, err := blockchain.InsertChain(types.Blocks{block}) 292 if err == nil { 293 t.Fatal("block imported without errors") 294 } 295 if have, want := err.Error(), tt.want; have != want { 296 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 297 } 298 } 299 } 300 } 301 302 // GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be 303 // valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently 304 // valid to be considered for import: 305 // - valid pow (fake), ancestry, difficulty, gaslimit etc 306 func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block { 307 header := &types.Header{ 308 ParentHash: parent.Hash(), 309 Coinbase: parent.Coinbase(), 310 Difficulty: engine.CalcDifficulty(&fakeChainReader{config}, parent.Time()+10, &types.Header{ 311 Number: parent.Number(), 312 Time: parent.Time(), 313 Difficulty: parent.Difficulty(), 314 UncleHash: parent.UncleHash(), 315 }), 316 GasLimit: parent.GasLimit(), 317 Number: new(big.Int).Add(parent.Number(), common.Big1), 318 Time: parent.Time() + 10, 319 UncleHash: types.EmptyUncleHash, 320 } 321 if config.IsLondon(header.Number) { 322 header.BaseFee = misc.CalcBaseFee(config, parent.Header()) 323 } 324 var receipts []*types.Receipt 325 // The post-state result doesn't need to be correct (this is a bad block), but we do need something there 326 // Preferably something unique. So let's use a combo of blocknum + txhash 327 hasher := sha3.NewLegacyKeccak256() 328 hasher.Write(header.Number.Bytes()) 329 var cumulativeGas uint64 330 for _, tx := range txs { 331 txh := tx.Hash() 332 hasher.Write(txh[:]) 333 receipt := types.NewReceipt(nil, false, cumulativeGas+tx.Gas()) 334 receipt.TxHash = tx.Hash() 335 receipt.GasUsed = tx.Gas() 336 receipts = append(receipts, receipt) 337 cumulativeGas += tx.Gas() 338 } 339 header.Root = common.BytesToHash(hasher.Sum(nil)) 340 // Assemble and return the final block for sealing 341 return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) 342 }