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