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