github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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/beacon" 28 "github.com/ethereum/go-ethereum/consensus/ethash" 29 "github.com/ethereum/go-ethereum/consensus/misc/eip1559" 30 "github.com/ethereum/go-ethereum/consensus/misc/eip4844" 31 "github.com/ethereum/go-ethereum/core/rawdb" 32 "github.com/ethereum/go-ethereum/core/types" 33 "github.com/ethereum/go-ethereum/core/vm" 34 "github.com/ethereum/go-ethereum/crypto" 35 "github.com/ethereum/go-ethereum/params" 36 "github.com/ethereum/go-ethereum/trie" 37 "github.com/holiman/uint256" 38 "golang.org/x/crypto/sha3" 39 ) 40 41 func u64(val uint64) *uint64 { return &val } 42 43 // TestStateProcessorErrors tests the output from the 'core' errors 44 // as defined in core/error.go. These errors are generated when the 45 // blockchain imports bad blocks, meaning blocks which have valid headers but 46 // contain invalid transactions 47 func TestStateProcessorErrors(t *testing.T) { 48 var ( 49 config = ¶ms.ChainConfig{ 50 ChainID: big.NewInt(1), 51 HomesteadBlock: big.NewInt(0), 52 EIP150Block: big.NewInt(0), 53 EIP155Block: big.NewInt(0), 54 EIP158Block: big.NewInt(0), 55 ByzantiumBlock: big.NewInt(0), 56 ConstantinopleBlock: big.NewInt(0), 57 PetersburgBlock: big.NewInt(0), 58 IstanbulBlock: big.NewInt(0), 59 MuirGlacierBlock: big.NewInt(0), 60 BerlinBlock: big.NewInt(0), 61 LondonBlock: big.NewInt(0), 62 Ethash: new(params.EthashConfig), 63 TerminalTotalDifficulty: big.NewInt(0), 64 TerminalTotalDifficultyPassed: true, 65 ShanghaiTime: new(uint64), 66 CancunTime: new(uint64), 67 } 68 signer = types.LatestSigner(config) 69 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 70 key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020") 71 ) 72 var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction { 73 tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key) 74 return tx 75 } 76 var mkDynamicTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction { 77 tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ 78 Nonce: nonce, 79 GasTipCap: gasTipCap, 80 GasFeeCap: gasFeeCap, 81 Gas: gasLimit, 82 To: &to, 83 Value: big.NewInt(0), 84 }), signer, key1) 85 return tx 86 } 87 var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction { 88 tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ 89 Nonce: nonce, 90 GasTipCap: gasTipCap, 91 GasFeeCap: gasFeeCap, 92 Gas: gasLimit, 93 Value: big.NewInt(0), 94 Data: data, 95 }), signer, key1) 96 return tx 97 } 98 var mkBlobTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int, hashes []common.Hash) *types.Transaction { 99 tx, err := types.SignTx(types.NewTx(&types.BlobTx{ 100 Nonce: nonce, 101 GasTipCap: uint256.MustFromBig(gasTipCap), 102 GasFeeCap: uint256.MustFromBig(gasFeeCap), 103 Gas: gasLimit, 104 To: to, 105 BlobHashes: hashes, 106 BlobFeeCap: uint256.MustFromBig(blobGasFeeCap), 107 Value: new(uint256.Int), 108 }), signer, key1) 109 if err != nil { 110 t.Fatal(err) 111 } 112 return tx 113 } 114 115 { // Tests against a 'recent' chain definition 116 var ( 117 db = rawdb.NewMemoryDatabase() 118 gspec = &Genesis{ 119 Config: config, 120 Alloc: types.GenesisAlloc{ 121 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ 122 Balance: big.NewInt(1000000000000000000), // 1 ether 123 Nonce: 0, 124 }, 125 common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): types.Account{ 126 Balance: big.NewInt(1000000000000000000), // 1 ether 127 Nonce: math.MaxUint64, 128 }, 129 }, 130 } 131 blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) 132 tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} 133 ) 134 135 defer blockchain.Stop() 136 bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes()) 137 tooBigNumber := new(big.Int).Set(bigNumber) 138 tooBigNumber.Add(tooBigNumber, common.Big1) 139 for i, tt := range []struct { 140 txs []*types.Transaction 141 want string 142 }{ 143 { // ErrNonceTooLow 144 txs: []*types.Transaction{ 145 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 146 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 147 }, 148 want: "could not apply tx 1 [0x0026256b3939ed97e2c4a6f3fce8ecf83bdcfa6d507c47838c308a1fb0436f62]: nonce too low: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 0 state: 1", 149 }, 150 { // ErrNonceTooHigh 151 txs: []*types.Transaction{ 152 makeTx(key1, 100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 153 }, 154 want: "could not apply tx 0 [0xdebad714ca7f363bd0d8121c4518ad48fa469ca81b0a081be3d10c17460f751b]: nonce too high: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 100 state: 0", 155 }, 156 { // ErrNonceMax 157 txs: []*types.Transaction{ 158 makeTx(key2, math.MaxUint64, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), 159 }, 160 want: "could not apply tx 0 [0x84ea18d60eb2bb3b040e3add0eb72f757727122cc257dd858c67cb6591a85986]: nonce has max value: address 0xfd0810DD14796680f72adf1a371963d0745BCc64, nonce: 18446744073709551615", 161 }, 162 { // ErrGasLimitReached 163 txs: []*types.Transaction{ 164 makeTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil), 165 }, 166 want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", 167 }, 168 { // ErrInsufficientFundsForTransfer 169 txs: []*types.Transaction{ 170 makeTx(key1, 0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil), 171 }, 172 want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000", 173 }, 174 { // ErrInsufficientFunds 175 txs: []*types.Transaction{ 176 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(900000000000000000), nil), 177 }, 178 want: "could not apply tx 0 [0x4a69690c4b0cd85e64d0d9ea06302455b01e10a83db964d60281739752003440]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 18900000000000000000000", 179 }, 180 // ErrGasUintOverflow 181 // One missing 'core' error is ErrGasUintOverflow: "gas uint64 overflow", 182 // In order to trigger that one, we'd have to allocate a _huge_ chunk of data, such that the 183 // multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment 184 { // ErrIntrinsicGas 185 txs: []*types.Transaction{ 186 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), nil), 187 }, 188 want: "could not apply tx 0 [0xcf3b049a0b516cb4f9274b3e2a264359e2ba53b2fb64b7bda2c634d5c9d01fca]: intrinsic gas too low: have 20000, want 21000", 189 }, 190 { // ErrGasLimitReached 191 txs: []*types.Transaction{ 192 makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil), 193 }, 194 want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", 195 }, 196 { // ErrFeeCapTooLow 197 txs: []*types.Transaction{ 198 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(0), big.NewInt(0)), 199 }, 200 want: "could not apply tx 0 [0xc4ab868fef0c82ae0387b742aee87907f2d0fc528fc6ea0a021459fb0fc4a4a8]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 0, baseFee: 875000000", 201 }, 202 { // ErrTipVeryHigh 203 txs: []*types.Transaction{ 204 mkDynamicTx(0, common.Address{}, params.TxGas, tooBigNumber, big.NewInt(1)), 205 }, 206 want: "could not apply tx 0 [0x15b8391b9981f266b32f3ab7da564bbeb3d6c21628364ea9b32a21139f89f712]: max priority fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas bit length: 257", 207 }, 208 { // ErrFeeCapVeryHigh 209 txs: []*types.Transaction{ 210 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), tooBigNumber), 211 }, 212 want: "could not apply tx 0 [0x48bc299b83fdb345c57478f239e89814bb3063eb4e4b49f3b6057a69255c16bd]: max fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas bit length: 257", 213 }, 214 { // ErrTipAboveFeeCap 215 txs: []*types.Transaction{ 216 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(2), big.NewInt(1)), 217 }, 218 want: "could not apply tx 0 [0xf987a31ff0c71895780a7612f965a0c8b056deb54e020bb44fa478092f14c9b4]: max priority fee per gas higher than max fee per gas: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas: 2, maxFeePerGas: 1", 219 }, 220 { // ErrInsufficientFunds 221 // Available balance: 1000000000000000000 222 // Effective cost: 18375000021000 223 // FeeCap * gas: 1050000000000000000 224 // This test is designed to have the effective cost be covered by the balance, but 225 // the extended requirement on FeeCap*gas < balance to fail 226 txs: []*types.Transaction{ 227 mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(50000000000000)), 228 }, 229 want: "could not apply tx 0 [0x413603cd096a87f41b1660d3ed3e27d62e1da78eac138961c0a1314ed43bd129]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1050000000000000000", 230 }, 231 { // Another ErrInsufficientFunds, this one to ensure that feecap/tip of max u256 is allowed 232 txs: []*types.Transaction{ 233 mkDynamicTx(0, common.Address{}, params.TxGas, bigNumber, bigNumber), 234 }, 235 want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 required balance exceeds 256 bits", 236 }, 237 { // ErrMaxInitCodeSizeExceeded 238 txs: []*types.Transaction{ 239 mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]), 240 }, 241 want: "could not apply tx 0 [0xd491405f06c92d118dd3208376fcee18a57c54bc52063ee4a26b1cf296857c25]: max initcode size exceeded: code size 49153 limit 49152", 242 }, 243 { // ErrIntrinsicGas: Not enough gas to cover init code 244 txs: []*types.Transaction{ 245 mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFee), make([]byte, 320)), 246 }, 247 want: "could not apply tx 0 [0xfd49536a9b323769d8472fcb3ebb3689b707a349379baee3e2ee3fe7baae06a1]: intrinsic gas too low: have 54299, want 54300", 248 }, 249 { // ErrBlobFeeCapTooLow 250 txs: []*types.Transaction{ 251 mkBlobTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(1), big.NewInt(0), []common.Hash{(common.Hash{1})}), 252 }, 253 want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000", 254 }, 255 } { 256 block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) 257 _, err := blockchain.InsertChain(types.Blocks{block}) 258 if err == nil { 259 t.Fatal("block imported without errors") 260 } 261 if have, want := err.Error(), tt.want; have != want { 262 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 263 } 264 } 265 } 266 267 // ErrTxTypeNotSupported, For this, we need an older chain 268 { 269 var ( 270 db = rawdb.NewMemoryDatabase() 271 gspec = &Genesis{ 272 Config: ¶ms.ChainConfig{ 273 ChainID: big.NewInt(1), 274 HomesteadBlock: big.NewInt(0), 275 EIP150Block: big.NewInt(0), 276 EIP155Block: big.NewInt(0), 277 EIP158Block: big.NewInt(0), 278 ByzantiumBlock: big.NewInt(0), 279 ConstantinopleBlock: big.NewInt(0), 280 PetersburgBlock: big.NewInt(0), 281 IstanbulBlock: big.NewInt(0), 282 MuirGlacierBlock: big.NewInt(0), 283 }, 284 Alloc: types.GenesisAlloc{ 285 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ 286 Balance: big.NewInt(1000000000000000000), // 1 ether 287 Nonce: 0, 288 }, 289 }, 290 } 291 blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) 292 ) 293 defer blockchain.Stop() 294 for i, tt := range []struct { 295 txs []*types.Transaction 296 want string 297 }{ 298 { // ErrTxTypeNotSupported 299 txs: []*types.Transaction{ 300 mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), 301 }, 302 want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported", 303 }, 304 } { 305 block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) 306 _, err := blockchain.InsertChain(types.Blocks{block}) 307 if err == nil { 308 t.Fatal("block imported without errors") 309 } 310 if have, want := err.Error(), tt.want; have != want { 311 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 312 } 313 } 314 } 315 316 // ErrSenderNoEOA, for this we need the sender to have contract code 317 { 318 var ( 319 db = rawdb.NewMemoryDatabase() 320 gspec = &Genesis{ 321 Config: config, 322 Alloc: types.GenesisAlloc{ 323 common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ 324 Balance: big.NewInt(1000000000000000000), // 1 ether 325 Nonce: 0, 326 Code: common.FromHex("0xB0B0FACE"), 327 }, 328 }, 329 } 330 blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) 331 ) 332 defer blockchain.Stop() 333 for i, tt := range []struct { 334 txs []*types.Transaction 335 want string 336 }{ 337 { // ErrSenderNoEOA 338 txs: []*types.Transaction{ 339 mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), 340 }, 341 want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", 342 }, 343 } { 344 block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) 345 _, err := blockchain.InsertChain(types.Blocks{block}) 346 if err == nil { 347 t.Fatal("block imported without errors") 348 } 349 if have, want := err.Error(), tt.want; have != want { 350 t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) 351 } 352 } 353 } 354 } 355 356 // GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be 357 // valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently 358 // valid to be considered for import: 359 // - valid pow (fake), ancestry, difficulty, gaslimit etc 360 func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block { 361 difficulty := big.NewInt(0) 362 if !config.TerminalTotalDifficultyPassed { 363 fakeChainReader := newChainMaker(nil, config, engine) 364 difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{ 365 Number: parent.Number(), 366 Time: parent.Time(), 367 Difficulty: parent.Difficulty(), 368 UncleHash: parent.UncleHash(), 369 }) 370 } 371 372 header := &types.Header{ 373 ParentHash: parent.Hash(), 374 Coinbase: parent.Coinbase(), 375 Difficulty: difficulty, 376 GasLimit: parent.GasLimit(), 377 Number: new(big.Int).Add(parent.Number(), common.Big1), 378 Time: parent.Time() + 10, 379 UncleHash: types.EmptyUncleHash, 380 } 381 if config.IsLondon(header.Number) { 382 header.BaseFee = eip1559.CalcBaseFee(config, parent.Header()) 383 } 384 if config.IsShanghai(header.Number, header.Time) { 385 header.WithdrawalsHash = &types.EmptyWithdrawalsHash 386 } 387 var receipts []*types.Receipt 388 // The post-state result doesn't need to be correct (this is a bad block), but we do need something there 389 // Preferably something unique. So let's use a combo of blocknum + txhash 390 hasher := sha3.NewLegacyKeccak256() 391 hasher.Write(header.Number.Bytes()) 392 var cumulativeGas uint64 393 var nBlobs int 394 for _, tx := range txs { 395 txh := tx.Hash() 396 hasher.Write(txh[:]) 397 receipt := types.NewReceipt(nil, false, cumulativeGas+tx.Gas()) 398 receipt.TxHash = tx.Hash() 399 receipt.GasUsed = tx.Gas() 400 receipts = append(receipts, receipt) 401 cumulativeGas += tx.Gas() 402 nBlobs += len(tx.BlobHashes()) 403 } 404 header.Root = common.BytesToHash(hasher.Sum(nil)) 405 if config.IsCancun(header.Number, header.Time) { 406 var pExcess, pUsed = uint64(0), uint64(0) 407 if parent.ExcessBlobGas() != nil { 408 pExcess = *parent.ExcessBlobGas() 409 pUsed = *parent.BlobGasUsed() 410 } 411 excess := eip4844.CalcExcessBlobGas(pExcess, pUsed) 412 used := uint64(nBlobs * params.BlobTxBlobGasPerBlob) 413 header.ExcessBlobGas = &excess 414 header.BlobGasUsed = &used 415 416 beaconRoot := common.HexToHash("0xbeac00") 417 header.ParentBeaconRoot = &beaconRoot 418 } 419 // Assemble and return the final block for sealing 420 body := &types.Body{Transactions: txs} 421 if config.IsShanghai(header.Number, header.Time) { 422 body.Withdrawals = []*types.Withdrawal{} 423 } 424 return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)) 425 } 426 427 var ( 428 code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`) 429 intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, true, true, true, true) 430 // A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness 431 // will not contain that copied data. 432 // Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985 433 codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`) 434 intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, true, true, true, true) 435 ) 436 437 func TestProcessVerkle(t *testing.T) { 438 var ( 439 config = ¶ms.ChainConfig{ 440 ChainID: big.NewInt(1), 441 HomesteadBlock: big.NewInt(0), 442 EIP150Block: big.NewInt(0), 443 EIP155Block: big.NewInt(0), 444 EIP158Block: big.NewInt(0), 445 ByzantiumBlock: big.NewInt(0), 446 ConstantinopleBlock: big.NewInt(0), 447 PetersburgBlock: big.NewInt(0), 448 IstanbulBlock: big.NewInt(0), 449 MuirGlacierBlock: big.NewInt(0), 450 BerlinBlock: big.NewInt(0), 451 LondonBlock: big.NewInt(0), 452 Ethash: new(params.EthashConfig), 453 ShanghaiTime: u64(0), 454 VerkleTime: u64(0), 455 TerminalTotalDifficulty: common.Big0, 456 TerminalTotalDifficultyPassed: true, 457 // TODO uncomment when proof generation is merged 458 // ProofInBlocks: true, 459 } 460 signer = types.LatestSigner(config) 461 testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 462 bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain 463 coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") 464 gspec = &Genesis{ 465 Config: config, 466 Alloc: GenesisAlloc{ 467 coinbase: GenesisAccount{ 468 Balance: big.NewInt(1000000000000000000), // 1 ether 469 Nonce: 0, 470 }, 471 }, 472 } 473 ) 474 // Verkle trees use the snapshot, which must be enabled before the 475 // data is saved into the tree+database. 476 // genesis := gspec.MustCommit(bcdb, triedb) 477 cacheConfig := DefaultCacheConfigWithScheme("path") 478 cacheConfig.SnapshotLimit = 0 479 blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) 480 defer blockchain.Stop() 481 482 txCost1 := params.TxGas 483 txCost2 := params.TxGas 484 contractCreationCost := intrinsicContractCreationGas + uint64(2039 /* execution costs */) 485 codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas + uint64(293644 /* execution costs */) 486 blockGasUsagesExpected := []uint64{ 487 txCost1*2 + txCost2, 488 txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas, 489 } 490 _, chain, _, _, _ := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) { 491 gen.SetPoS() 492 493 // TODO need to check that the tx cost provided is the exact amount used (no remaining left-over) 494 tx, _ := types.SignTx(types.NewTransaction(uint64(i)*3, common.Address{byte(i), 2, 3}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) 495 gen.AddTx(tx) 496 tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+1, common.Address{}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey) 497 gen.AddTx(tx) 498 tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+2, common.Address{}, big.NewInt(0), txCost2, big.NewInt(875000000), nil), signer, testKey) 499 gen.AddTx(tx) 500 501 // Add two contract creations in block #2 502 if i == 1 { 503 tx, _ = types.SignTx(types.NewContractCreation(6, big.NewInt(16), 3000000, big.NewInt(875000000), code), signer, testKey) 504 gen.AddTx(tx) 505 506 tx, _ = types.SignTx(types.NewContractCreation(7, big.NewInt(0), 3000000, big.NewInt(875000000), codeWithExtCodeCopy), signer, testKey) 507 gen.AddTx(tx) 508 } 509 }) 510 511 t.Log("inserting blocks into the chain") 512 513 endnum, err := blockchain.InsertChain(chain) 514 if err != nil { 515 t.Fatalf("block %d imported with error: %v", endnum, err) 516 } 517 518 for i := 0; i < 2; i++ { 519 b := blockchain.GetBlockByNumber(uint64(i) + 1) 520 if b == nil { 521 t.Fatalf("expected block %d to be present in chain", i+1) 522 } 523 if b.Hash() != chain[i].Hash() { 524 t.Fatalf("block #%d not found at expected height", b.NumberU64()) 525 } 526 if b.GasUsed() != blockGasUsagesExpected[i] { 527 t.Fatalf("expected block #%d txs to use %d, got %d\n", b.NumberU64(), blockGasUsagesExpected[i], b.GasUsed()) 528 } 529 } 530 }