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 = ¶ms.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: ¶ms.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 }