diff --git a/cmd/devp2p/internal/ethtest/suite_test.go b/cmd/devp2p/internal/ethtest/suite_test.go deleted file mode 100644 index c8479fd3aa..0000000000 --- a/cmd/devp2p/internal/ethtest/suite_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see . - -package ethtest // TOFIX - -import ( - crand "crypto/rand" - "fmt" - "os" - "path" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/catalyst" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" -) - -func makeJWTSecret() (string, [32]byte, error) { - var secret [32]byte - if _, err := crand.Read(secret[:]); err != nil { - return "", secret, fmt.Errorf("failed to create jwt secret: %v", err) - } - jwtPath := path.Join(os.TempDir(), "jwt_secret") - if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil { - return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err) - } - return jwtPath, secret, nil -} - -func TestEthSuite(t *testing.T) { - jwtPath, secret, err := makeJWTSecret() - if err != nil { - t.Fatalf("could not make jwt secret: %v", err) - } - geth, err := runGeth("./testdata", jwtPath) - if err != nil { - t.Fatalf("could not run geth: %v", err) - } - defer geth.Close() - - suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:])) - if err != nil { - t.Fatalf("could not create new test suite: %v", err) - } - for _, test := range suite.EthTests() { - t.Run(test.Name, func(t *testing.T) { - if test.Slow && testing.Short() { - t.Skipf("%s: skipping in -short mode", test.Name) - } - result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) - if result[0].Failed { - t.Fatal() - } - }) - } -} - -func TestSnapSuite(t *testing.T) { - jwtPath, secret, err := makeJWTSecret() - if err != nil { - t.Fatalf("could not make jwt secret: %v", err) - } - geth, err := runGeth("./testdata", jwtPath) - if err != nil { - t.Fatalf("could not run geth: %v", err) - } - defer geth.Close() - - suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:])) - if err != nil { - t.Fatalf("could not create new test suite: %v", err) - } - for _, test := range suite.SnapTests() { - t.Run(test.Name, func(t *testing.T) { - result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) - if result[0].Failed { - t.Fatal() - } - }) - } -} - -// runGeth creates and starts a geth node -func runGeth(dir string, jwtPath string) (*node.Node, error) { - stack, err := node.New(&node.Config{ - AuthAddr: "127.0.0.1", - AuthPort: 0, - P2P: p2p.Config{ - ListenAddr: "127.0.0.1:0", - NoDiscovery: true, - MaxPeers: 10, // in case a test requires multiple connections, can be changed in the future - MaxPeersPerIP: 10, - NoDial: true, - }, - JWTSecret: jwtPath, - }) - if err != nil { - return nil, err - } - - err = setupGeth(stack, dir) - if err != nil { - stack.Close() - return nil, err - } - if err = stack.Start(); err != nil { - stack.Close() - return nil, err - } - return stack, nil -} - -func setupGeth(stack *node.Node, dir string) error { - chain, err := NewChain(dir) - if err != nil { - return err - } - backend, err := eth.New(stack, ðconfig.Config{ - Genesis: &chain.genesis, - NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763 - DatabaseCache: 10, - TrieCleanCache: 10, - TrieDirtyCache: 16, - TrieTimeout: 60 * time.Minute, - SnapshotCache: 10, - TriesInMemory: 128, - }) - if err != nil { - return err - } - if err := catalyst.Register(stack, backend); err != nil { - return fmt.Errorf("failed to register catalyst service: %v", err) - } - _, err = backend.BlockChain().InsertChain(chain.blocks[1:]) - return err -} diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go deleted file mode 100644 index 8764f51fb6..0000000000 --- a/internal/ethapi/api_test.go +++ /dev/null @@ -1,2295 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package ethapi - -import ( - "bytes" - "context" - "crypto/ecdsa" - "crypto/sha256" - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - "path/filepath" - "reflect" - "testing" - "time" - - "github.com/holiman/uint256" - "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/blocktest" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -var emptyBlob = kzg4844.Blob{} -var emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) -var emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) -var emptyBlobHash common.Hash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit) - -func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainConfig) { - t.Parallel() - var ( - signer = types.LatestSigner(config) - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - ) - - for i, tt := range tests { - var tx2 types.Transaction - tx, err := types.SignNewTx(key, signer, tt.Tx) - if err != nil { - t.Fatalf("test %d: signing failed: %v", i, err) - } - // Regular transaction - if data, err := json.Marshal(tx); err != nil { - t.Fatalf("test %d: marshalling failed; %v", i, err) - } else if err = tx2.UnmarshalJSON(data); err != nil { - t.Fatalf("test %d: sunmarshal failed: %v", i, err) - } else if want, have := tx.Hash(), tx2.Hash(); want != have { - t.Fatalf("test %d: stx changed, want %x have %x", i, want, have) - } - - // rpcTransaction - rpcTx := newRPCTransaction(tx, common.Hash{}, 0, 0, 0, nil, config) - if data, err := json.Marshal(rpcTx); err != nil { - t.Fatalf("test %d: marshalling failed; %v", i, err) - } else if err = tx2.UnmarshalJSON(data); err != nil { - t.Fatalf("test %d: unmarshal failed: %v", i, err) - } else if want, have := tx.Hash(), tx2.Hash(); want != have { - t.Fatalf("test %d: tx changed, want %x have %x", i, want, have) - } else { - want, have := tt.Want, string(data) - require.JSONEqf(t, want, have, "test %d: rpc json not match, want %s have %s", i, want, have) - } - } -} - -func TestTransaction_RoundTripRpcJSON(t *testing.T) { - var ( - config = params.AllEthashProtocolChanges - tests = allTransactionTypes(common.Address{0xde, 0xad}, config) - ) - testTransactionMarshal(t, tests, config) -} - -func TestTransactionBlobTx(t *testing.T) { - config := *params.TestChainConfig - config.ShanghaiTime = new(uint64) - config.CancunTime = new(uint64) - tests := allBlobTxs(common.Address{0xde, 0xad}, &config) - - testTransactionMarshal(t, tests, &config) -} - -type txData struct { - Tx types.TxData - Want string -} - -func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txData { - return []txData{ - { - Tx: &types.LegacyTx{ - Nonce: 5, - GasPrice: big.NewInt(6), - Gas: 7, - To: &addr, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - V: big.NewInt(9), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x6", - "hash": "0x5f3240454cd09a5d8b1c5d651eefae7a339262875bcd2d0e6676f3d989967008", - "input": "0x0001020304", - "nonce": "0x5", - "to": "0xdead000000000000000000000000000000000000", - "transactionIndex": null, - "value": "0x8", - "type": "0x0", - "chainId": "0x539", - "v": "0xa96", - "r": "0xbc85e96592b95f7160825d837abb407f009df9ebe8f1b9158a4b8dd093377f75", - "s": "0x1b55ea3af5574c536967b039ba6999ef6c89cf22fc04bcb296e0e8b0b9b576f5" - }`, - }, { - Tx: &types.LegacyTx{ - Nonce: 5, - GasPrice: big.NewInt(6), - Gas: 7, - To: nil, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - V: big.NewInt(32), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x6", - "hash": "0x806e97f9d712b6cb7e781122001380a2837531b0fc1e5f5d78174ad4cb699873", - "input": "0x0001020304", - "nonce": "0x5", - "to": null, - "transactionIndex": null, - "value": "0x8", - "type": "0x0", - "chainId": "0x539", - "v": "0xa96", - "r": "0x9dc28b267b6ad4e4af6fe9289668f9305c2eb7a3241567860699e478af06835a", - "s": "0xa0b51a071aa9bed2cd70aedea859779dff039e3630ea38497d95202e9b1fec7" - }`, - }, - { - Tx: &types.AccessListTx{ - ChainID: config.ChainID, - Nonce: 5, - GasPrice: big.NewInt(6), - Gas: 7, - To: &addr, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - AccessList: types.AccessList{ - types.AccessTuple{ - Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, - }, - }, - V: big.NewInt(32), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x6", - "hash": "0x121347468ee5fe0a29f02b49b4ffd1c8342bc4255146bb686cd07117f79e7129", - "input": "0x0001020304", - "nonce": "0x5", - "to": "0xdead000000000000000000000000000000000000", - "transactionIndex": null, - "value": "0x8", - "type": "0x1", - "accessList": [ - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - ] - } - ], - "chainId": "0x539", - "v": "0x0", - "r": "0xf372ad499239ae11d91d34c559ffc5dab4daffc0069e03afcabdcdf231a0c16b", - "s": "0x28573161d1f9472fa0fd4752533609e72f06414f7ab5588699a7141f65d2abf", - "yParity": "0x0" - }`, - }, { - Tx: &types.AccessListTx{ - ChainID: config.ChainID, - Nonce: 5, - GasPrice: big.NewInt(6), - Gas: 7, - To: nil, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - AccessList: types.AccessList{ - types.AccessTuple{ - Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, - }, - }, - V: big.NewInt(32), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x6", - "hash": "0x067c3baebede8027b0f828a9d933be545f7caaec623b00684ac0659726e2055b", - "input": "0x0001020304", - "nonce": "0x5", - "to": null, - "transactionIndex": null, - "value": "0x8", - "type": "0x1", - "accessList": [ - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - ] - } - ], - "chainId": "0x539", - "v": "0x1", - "r": "0x542981b5130d4613897fbab144796cb36d3cb3d7807d47d9c7f89ca7745b085c", - "s": "0x7425b9dd6c5deaa42e4ede35d0c4570c4624f68c28d812c10d806ffdf86ce63", - "yParity": "0x1" - }`, - }, { - Tx: &types.DynamicFeeTx{ - ChainID: config.ChainID, - Nonce: 5, - GasTipCap: big.NewInt(6), - GasFeeCap: big.NewInt(9), - Gas: 7, - To: &addr, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - AccessList: types.AccessList{ - types.AccessTuple{ - Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, - }, - }, - V: big.NewInt(32), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x9", - "maxFeePerGas": "0x9", - "maxPriorityFeePerGas": "0x6", - "hash": "0xb63e0b146b34c3e9cb7fbabb5b3c081254a7ded6f1b65324b5898cc0545d79ff", - "input": "0x0001020304", - "nonce": "0x5", - "to": "0xdead000000000000000000000000000000000000", - "transactionIndex": null, - "value": "0x8", - "type": "0x2", - "accessList": [ - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - ] - } - ], - "chainId": "0x539", - "v": "0x1", - "r": "0x3b167e05418a8932cd53d7578711fe1a76b9b96c48642402bb94978b7a107e80", - "s": "0x22f98a332d15ea2cc80386c1ebaa31b0afebfa79ebc7d039a1e0074418301fef", - "yParity": "0x1" - }`, - }, { - Tx: &types.DynamicFeeTx{ - ChainID: config.ChainID, - Nonce: 5, - GasTipCap: big.NewInt(6), - GasFeeCap: big.NewInt(9), - Gas: 7, - To: nil, - Value: big.NewInt(8), - Data: []byte{0, 1, 2, 3, 4}, - AccessList: types.AccessList{}, - V: big.NewInt(32), - R: big.NewInt(10), - S: big.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x7", - "gasPrice": "0x9", - "maxFeePerGas": "0x9", - "maxPriorityFeePerGas": "0x6", - "hash": "0xcbab17ee031a9d5b5a09dff909f0a28aedb9b295ac0635d8710d11c7b806ec68", - "input": "0x0001020304", - "nonce": "0x5", - "to": null, - "transactionIndex": null, - "value": "0x8", - "type": "0x2", - "accessList": [], - "chainId": "0x539", - "v": "0x0", - "r": "0x6446b8a682db7e619fc6b4f6d1f708f6a17351a41c7fbd63665f469bc78b41b9", - "s": "0x7626abc15834f391a117c63450047309dbf84c5ce3e8e609b607062641e2de43", - "yParity": "0x0" - }`, - }, - } -} - -func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData { - return []txData{ - { - Tx: &types.BlobTx{ - Nonce: 6, - GasTipCap: uint256.NewInt(1), - GasFeeCap: uint256.NewInt(5), - Gas: 6, - To: addr, - BlobFeeCap: uint256.NewInt(1), - BlobHashes: []common.Hash{{1}}, - Value: new(uint256.Int), - V: uint256.NewInt(32), - R: uint256.NewInt(10), - S: uint256.NewInt(11), - }, - Want: `{ - "blockHash": null, - "blockNumber": null, - "from": "0x71562b71999873db5b286df957af199ec94617f7", - "gas": "0x6", - "gasPrice": "0x5", - "maxFeePerGas": "0x5", - "maxPriorityFeePerGas": "0x1", - "maxFeePerBlobGas": "0x1", - "hash": "0x1f2b59a20e61efc615ad0cbe936379d6bbea6f938aafaf35eb1da05d8e7f46a3", - "input": "0x", - "nonce": "0x6", - "to": "0xdead000000000000000000000000000000000000", - "transactionIndex": null, - "value": "0x0", - "type": "0x3", - "accessList": [], - "chainId": "0x1", - "blobVersionedHashes": [ - "0x0100000000000000000000000000000000000000000000000000000000000000" - ], - "v": "0x0", - "r": "0x618be8908e0e5320f8f3b48042a079fe5a335ebd4ed1422a7d2207cd45d872bc", - "s": "0x27b2bc6c80e849a8e8b764d4549d8c2efac3441e73cf37054eb0a9b9f8e89b27", - "yParity": "0x0" - }`, - }, - } -} - -func newTestAccountManager(t *testing.T) (*accounts.Manager, accounts.Account) { - var ( - dir = t.TempDir() - am = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true}) - b = keystore.NewKeyStore(dir, 2, 1) - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - ) - acc, err := b.ImportECDSA(testKey, "") - if err != nil { - t.Fatalf("failed to create test account: %v", err) - } - if err := b.Unlock(acc, ""); err != nil { - t.Fatalf("failed to unlock account: %v\n", err) - } - am.AddBackend(b) - return am, acc -} - -type testBackend struct { - db ethdb.Database - chain *core.BlockChain - pending *types.Block - accman *accounts.Manager - acc accounts.Account -} - -func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend { - var ( - cacheConfig = &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - TrieDirtyDisabled: true, // Archive mode - } - ) - accman, acc := newTestAccountManager(t) - gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)} - // Generate blocks for testing - db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator) - txlookupLimit := uint64(0) - chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, &txlookupLimit) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - backend := &testBackend{db: db, chain: chain, accman: accman, acc: acc} - return backend -} - -// nolint:unused -func (b *testBackend) setPendingBlock(block *types.Block) { - b.pending = block -} - -func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} } -func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - return big.NewInt(0), nil -} - -func (b testBackend) Chain() *core.BlockChain { - return b.chain -} - -func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) { - return nil, nil, nil, nil, nil -} -func (b testBackend) ChainDb() ethdb.Database { return b.db } -func (b testBackend) AccountManager() *accounts.Manager { return b.accman } -func (b testBackend) ExtRPCEnabled() bool { return false } -func (b testBackend) RPCGasCap() uint64 { return 10000000 } -func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second } -func (b testBackend) RPCTxFeeCap() float64 { return 0 } -func (b testBackend) UnprotectedAllowed() bool { return false } -func (b testBackend) SetHead(number uint64) {} -func (b testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { - if number == rpc.LatestBlockNumber { - return b.chain.CurrentBlock(), nil - } - if number == rpc.PendingBlockNumber && b.pending != nil { - return b.pending.Header(), nil - } - return b.chain.GetHeaderByNumber(uint64(number)), nil -} -func (b testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return b.chain.GetHeaderByHash(hash), nil -} -func (b testBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.HeaderByNumber(ctx, blockNr) - } - if blockHash, ok := blockNrOrHash.Hash(); ok { - return b.HeaderByHash(ctx, blockHash) - } - panic("unknown type rpc.BlockNumberOrHash") -} -func (b testBackend) CurrentHeader() *types.Header { return b.chain.CurrentBlock() } -func (b testBackend) CurrentBlock() *types.Header { return b.chain.CurrentBlock() } -func (b testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { - if number == rpc.LatestBlockNumber { - head := b.chain.CurrentBlock() - return b.chain.GetBlock(head.Hash(), head.Number.Uint64()), nil - } - if number == rpc.PendingBlockNumber { - return b.pending, nil - } - return b.chain.GetBlockByNumber(uint64(number)), nil -} -func (b testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return b.chain.GetBlockByHash(hash), nil -} -func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.BlockByNumber(ctx, blockNr) - } - if blockHash, ok := blockNrOrHash.Hash(); ok { - return b.BlockByHash(ctx, blockHash) - } - panic("unknown type rpc.BlockNumberOrHash") -} -func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { - return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil -} -func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { - if number == rpc.PendingBlockNumber { - panic("pending state not implemented") - } - header, err := b.HeaderByNumber(ctx, number) - if err != nil { - return nil, nil, err - } - if header == nil { - return nil, nil, errors.New("header not found") - } - stateDb, err := b.chain.StateAt(header.Root) - return stateDb, header, err -} -func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.StateAndHeaderByNumber(ctx, blockNr) - } - panic("only implemented for number") -} -func (b testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { panic("implement me") } -func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - header, err := b.HeaderByHash(ctx, hash) - if header == nil || err != nil { - return nil, err - } - receipts := rawdb.ReadReceipts(b.db, hash, header.Number.Uint64(), header.Time, b.chain.Config()) - return receipts, nil -} - -func (b testBackend) GetBlobSidecars(ctx context.Context, hash common.Hash) (types.BlobSidecars, error) { - header, err := b.HeaderByHash(ctx, hash) - if header == nil || err != nil { - return nil, err - } - blobSidecars := rawdb.ReadBlobSidecars(b.db, hash, header.Number.Uint64()) - return blobSidecars, nil -} -func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { - if b.pending != nil && hash == b.pending.Hash() { - return nil - } - return big.NewInt(1) -} -func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM { - if vmConfig == nil { - vmConfig = b.chain.GetVMConfig() - } - txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(header, b.chain, nil) - if blockContext != nil { - context = *blockContext - } - return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig) -} -func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { - panic("implement me") -} -func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) { - tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash) - return true, tx, blockHash, blockNumber, index, nil -} -func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") } -func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") } -func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { - return 0, nil -} -func (b testBackend) Stats() (pending int, queued int) { panic("implement me") } -func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { - panic("implement me") -} -func (b testBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { - panic("implement me") -} -func (b testBackend) SubscribeNewTxsEvent(events chan<- core.NewTxsEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) ChainConfig() *params.ChainConfig { return b.chain.Config() } -func (b testBackend) Engine() consensus.Engine { return b.chain.Engine() } -func (b testBackend) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) { - panic("implement me") -} -func (b testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - panic("implement me") -} -func (b testBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { - panic("implement me") -} -func (b testBackend) BloomStatus() (uint64, uint64) { panic("implement me") } -func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { - panic("implement me") -} - -func (b *testBackend) MevRunning() bool { return false } -func (b *testBackend) HasBuilder(builder common.Address) bool { return false } -func (b *testBackend) MevParams() *types.MevParams { - return &types.MevParams{} -} -func (b *testBackend) StartMev() {} -func (b *testBackend) StopMev() {} -func (b *testBackend) AddBuilder(builder common.Address, builderUrl string) error { return nil } -func (b *testBackend) RemoveBuilder(builder common.Address) error { return nil } -func (b *testBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { - panic("implement me") -} -func (b *testBackend) MinerInTurn() bool { return false } -func (b *testBackend) BestBidGasFee(parentHash common.Hash) *big.Int { - //TODO implement me - panic("implement me") -} - -func TestEstimateGas(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - accounts = newAccounts(2) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks = 10 - signer = types.HomesteadSigner{} - randomAccounts = newAccounts(2) - ) - api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key) - b.AddTx(tx) - b.SetPoS() - })) - var testSuite = []struct { - blockNumber rpc.BlockNumber - call TransactionArgs - overrides StateOverride - expectErr error - want uint64 - }{ - // simple transfer on latest block - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: nil, - want: 21000, - }, - // simple transfer with insufficient funds on latest block - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &randomAccounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: core.ErrInsufficientFunds, - want: 21000, - }, - // empty create - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{}, - expectErr: nil, - want: 53000, - }, - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{}, - overrides: StateOverride{ - randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, - }, - expectErr: nil, - want: 53000, - }, - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - overrides: StateOverride{ - randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(big.NewInt(0))}, - }, - expectErr: core.ErrInsufficientFunds, - }, - // Test for a bug where the gas price was set to zero but the basefee non-zero - // - // contract BasefeeChecker { - // constructor() { - // require(tx.gasprice >= block.basefee); - // if (tx.gasprice > 0) { - // require(block.basefee > 0); - // } - // } - //} - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), - GasPrice: (*hexutil.Big)(big.NewInt(1_000_000_000)), // Legacy as pricing - }, - expectErr: nil, - want: 67617, - }, - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), - MaxFeePerGas: (*hexutil.Big)(big.NewInt(1_000_000_000)), // 1559 gas pricing - }, - expectErr: nil, - want: 67617, - }, - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"), - GasPrice: nil, // No legacy gas pricing - MaxFeePerGas: nil, // No 1559 gas pricing - }, - expectErr: nil, - want: 67595, - }, - // Blobs should have no effect on gas estimate - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1)), - BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, - BlobFeeCap: (*hexutil.Big)(big.NewInt(1)), - }, - want: 21000, - }, - } - for i, tc := range testSuite { - result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides) - if tc.expectErr != nil { - if err == nil { - t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) - continue - } - if !errors.Is(err, tc.expectErr) { - t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) - } - continue - } - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - if float64(result) > float64(tc.want)*(1+estimateGasErrorRatio) { - t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, uint64(result), tc.want) - } - } -} - -func TestCall(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - accounts = newAccounts(3) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks = 10 - signer = types.HomesteadSigner{} - ) - api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key) - b.AddTx(tx) - b.SetPoS() - })) - randomAccounts := newAccounts(3) - var testSuite = []struct { - blockNumber rpc.BlockNumber - overrides StateOverride - call TransactionArgs - blockOverrides BlockOverrides - expectErr error - want string - }{ - // transfer on genesis - { - blockNumber: rpc.BlockNumber(0), - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: nil, - want: "0x", - }, - // transfer on the head - { - blockNumber: rpc.BlockNumber(genBlocks), - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: nil, - want: "0x", - }, - // transfer on a non-existent block, error expects - { - blockNumber: rpc.BlockNumber(genBlocks + 1), - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: errors.New("header not found"), - }, - // transfer on the latest block - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: nil, - want: "0x", - }, - // Call which can only succeed if state is state overridden - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - overrides: StateOverride{ - randomAccounts[0].addr: OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, - }, - want: "0x", - }, - // Invalid call without state overriding - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - expectErr: core.ErrInsufficientFunds, - }, - // Successful simple contract call - // - // // SPDX-License-Identifier: GPL-3.0 - // - // pragma solidity >=0.7.0 <0.8.0; - // - // /** - // * @title Storage - // * @dev Store & retrieve value in a variable - // */ - // contract Storage { - // uint256 public number; - // constructor() { - // number = block.number; - // } - // } - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[2].addr, - Data: hex2Bytes("8381f58a"), // call number() - }, - overrides: StateOverride{ - randomAccounts[2].addr: OverrideAccount{ - Code: hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033"), - StateDiff: &map[common.Hash]common.Hash{{}: common.BigToHash(big.NewInt(123))}, - }, - }, - want: "0x000000000000000000000000000000000000000000000000000000000000007b", - }, - // Block overrides should work - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[1].addr, - Input: &hexutil.Bytes{ - 0x43, // NUMBER - 0x60, 0x00, 0x52, // MSTORE offset 0 - 0x60, 0x20, 0x60, 0x00, 0xf3, - }, - }, - blockOverrides: BlockOverrides{Number: (*hexutil.Big)(big.NewInt(11))}, - want: "0x000000000000000000000000000000000000000000000000000000000000000b", - }, - // Invalid blob tx - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[1].addr, - Input: &hexutil.Bytes{0x00}, - BlobHashes: []common.Hash{}, - }, - expectErr: core.ErrBlobTxCreate, - }, - // BLOBHASH opcode - { - blockNumber: rpc.LatestBlockNumber, - call: TransactionArgs{ - From: &accounts[1].addr, - To: &randomAccounts[2].addr, - BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, - BlobFeeCap: (*hexutil.Big)(big.NewInt(1)), - }, - overrides: StateOverride{ - randomAccounts[2].addr: { - Code: hex2Bytes("60004960005260206000f3"), - }, - }, - want: "0x0122000000000000000000000000000000000000000000000000000000000000", - }, - } - for i, tc := range testSuite { - result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides) - if tc.expectErr != nil { - if err == nil { - t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) - continue - } - if !errors.Is(err, tc.expectErr) { - // Second try - if !reflect.DeepEqual(err, tc.expectErr) { - t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) - } - } - continue - } - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - if !reflect.DeepEqual(result.String(), tc.want) { - t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, result.String(), tc.want) - } - } -} - -func TestSignTransaction(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - to = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{}, - } - ) - b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - b.SetPoS() - }) - api := NewTransactionAPI(b, nil) - res, err := api.FillTransaction(context.Background(), TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - }) - if err != nil { - t.Fatalf("failed to fill tx defaults: %v\n", err) - } - - res, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) - if err != nil { - t.Fatalf("failed to sign tx: %v\n", err) - } - tx, err := json.Marshal(res.Tx) - if err != nil { - t.Fatal(err) - } - expect := `{"type":"0x2","chainId":"0x1","nonce":"0x0","to":"0x703c4b2bd70c169f5717101caee543299fc946c7","gas":"0x5208","gasPrice":null,"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x684ee180","value":"0x1","input":"0x","accessList":[],"v":"0x0","r":"0x8fabeb142d585dd9247f459f7e6fe77e2520c88d50ba5d220da1533cea8b34e1","s":"0x582dd68b21aef36ba23f34e49607329c20d981d30404daf749077f5606785ce7","yParity":"0x0","hash":"0x93927839207cfbec395da84b8a2bc38b7b65d2cb2819e9fef1f091f5b1d4cc8f"}` - if !bytes.Equal(tx, []byte(expect)) { - t.Errorf("result mismatch. Have:\n%s\nWant:\n%s\n", tx, expect) - } -} - -func TestSignBlobTransaction(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - to = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{}, - } - ) - b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - b.SetPoS() - }) - api := NewTransactionAPI(b, nil) - res, err := api.FillTransaction(context.Background(), TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - BlobHashes: []common.Hash{{0x01, 0x22}}, - }) - if err != nil { - t.Fatalf("failed to fill tx defaults: %v\n", err) - } - - _, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) - if err == nil { - t.Fatalf("should fail on blob transaction") - } - if !errors.Is(err, errBlobTxNotSupported) { - t.Errorf("error mismatch. Have: %v, want: %v", err, errBlobTxNotSupported) - } -} - -func TestSendBlobTransaction(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - to = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{}, - } - ) - b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - b.SetPoS() - }) - api := NewTransactionAPI(b, nil) - res, err := api.FillTransaction(context.Background(), TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - BlobHashes: []common.Hash{common.Hash{0x01, 0x22}}, - }) - if err != nil { - t.Fatalf("failed to fill tx defaults: %v\n", err) - } - - _, err = api.SendTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address)) - if err == nil { - t.Errorf("sending tx should have failed") - } else if !errors.Is(err, errBlobTxNotSupported) { - t.Errorf("unexpected error. Have %v, want %v\n", err, errBlobTxNotSupported) - } -} - -func TestFillBlobTransaction(t *testing.T) { - t.Parallel() - // Initialize test accounts - var ( - key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - to = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{ - Config: params.MergedTestChainConfig, - Alloc: types.GenesisAlloc{}, - } - ) - b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - b.SetPoS() - }) - api := NewTransactionAPI(b, nil) - type result struct { - Hashes []common.Hash - Sidecar *types.BlobTxSidecar - } - suite := []struct { - name string - args TransactionArgs - err string - want *result - }{ - { - name: "TestInvalidParamsCombination1", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{{}}, - Proofs: []kzg4844.Proof{{}}, - }, - err: `blob proofs provided while commitments were not`, - }, - { - name: "TestInvalidParamsCombination2", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{{}}, - Commitments: []kzg4844.Commitment{{}}, - }, - err: `blob commitments provided while proofs were not`, - }, - { - name: "TestInvalidParamsCount1", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{{}}, - Commitments: []kzg4844.Commitment{{}, {}}, - Proofs: []kzg4844.Proof{{}, {}}, - }, - err: `number of blobs and commitments mismatch (have=2, want=1)`, - }, - { - name: "TestInvalidParamsCount2", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{{}, {}}, - Commitments: []kzg4844.Commitment{{}, {}}, - Proofs: []kzg4844.Proof{{}}, - }, - err: `number of blobs and proofs mismatch (have=1, want=2)`, - }, - { - name: "TestInvalidProofVerification", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{{}, {}}, - Commitments: []kzg4844.Commitment{{}, {}}, - Proofs: []kzg4844.Proof{{}, {}}, - }, - err: `failed to verify blob proof: short buffer`, - }, - { - name: "TestGenerateBlobHashes", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - want: &result{ - Hashes: []common.Hash{emptyBlobHash}, - Sidecar: &types.BlobTxSidecar{ - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - }, - }, - { - name: "TestValidBlobHashes", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - BlobHashes: []common.Hash{emptyBlobHash}, - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - want: &result{ - Hashes: []common.Hash{emptyBlobHash}, - Sidecar: &types.BlobTxSidecar{ - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - }, - }, - { - name: "TestInvalidBlobHashes", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - BlobHashes: []common.Hash{{0x01, 0x22}}, - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - err: fmt.Sprintf("blob hash verification failed (have=%s, want=%s)", common.Hash{0x01, 0x22}, emptyBlobHash), - }, - { - name: "TestGenerateBlobProofs", - args: TransactionArgs{ - From: &b.acc.Address, - To: &to, - Value: (*hexutil.Big)(big.NewInt(1)), - Blobs: []kzg4844.Blob{emptyBlob}, - }, - want: &result{ - Hashes: []common.Hash{emptyBlobHash}, - Sidecar: &types.BlobTxSidecar{ - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - }, - }, - } - for _, tc := range suite { - t.Run(tc.name, func(t *testing.T) { - res, err := api.FillTransaction(context.Background(), tc.args) - if len(tc.err) > 0 { - if err == nil { - t.Fatalf("missing error. want: %s", tc.err) - } else if err != nil && err.Error() != tc.err { - t.Fatalf("error mismatch. want: %s, have: %s", tc.err, err.Error()) - } - return - } - if err != nil && len(tc.err) == 0 { - t.Fatalf("expected no error. have: %s", err) - } - if res == nil { - t.Fatal("result missing") - } - want, err := json.Marshal(tc.want) - if err != nil { - t.Fatalf("failed to encode expected: %v", err) - } - have, err := json.Marshal(result{Hashes: res.Tx.BlobHashes(), Sidecar: res.Tx.BlobTxSidecar()}) - if err != nil { - t.Fatalf("failed to encode computed sidecar: %v", err) - } - if !bytes.Equal(have, want) { - t.Errorf("blob sidecar mismatch. Have: %s, want: %s", have, want) - } - }) - } -} - -func argsFromTransaction(tx *types.Transaction, from common.Address) TransactionArgs { - var ( - gas = tx.Gas() - nonce = tx.Nonce() - input = tx.Data() - ) - return TransactionArgs{ - From: &from, - To: tx.To(), - Gas: (*hexutil.Uint64)(&gas), - MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), - MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()), - Value: (*hexutil.Big)(tx.Value()), - Nonce: (*hexutil.Uint64)(&nonce), - Input: (*hexutil.Bytes)(&input), - ChainID: (*hexutil.Big)(tx.ChainId()), - // TODO: impl accessList conversion - //AccessList: tx.AccessList(), - BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()), - BlobHashes: tx.BlobHashes(), - } -} - -type account struct { - key *ecdsa.PrivateKey - addr common.Address -} - -func newAccounts(n int) (accounts []account) { - for i := 0; i < n; i++ { - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - accounts = append(accounts, account{key: key, addr: addr}) - } - slices.SortFunc(accounts, func(a, b account) int { return a.addr.Cmp(b.addr) }) - return accounts -} - -func newRPCBalance(balance *big.Int) **hexutil.Big { - rpcBalance := (*hexutil.Big)(balance) - return &rpcBalance -} - -func hex2Bytes(str string) *hexutil.Bytes { - rpcBytes := hexutil.Bytes(common.Hex2Bytes(str)) - return &rpcBytes -} - -func TestRPCMarshalBlock(t *testing.T) { - t.Parallel() - var ( - txs []*types.Transaction - to = common.BytesToAddress([]byte{0x11}) - ) - for i := uint64(1); i <= 4; i++ { - var tx *types.Transaction - if i%2 == 0 { - tx = types.NewTx(&types.LegacyTx{ - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } else { - tx = types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1337), - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } - txs = append(txs, tx) - } - block := types.NewBlock(&types.Header{Number: big.NewInt(100)}, txs, nil, nil, blocktest.NewHasher()) - - var testSuite = []struct { - inclTx bool - fullTx bool - want string - }{ - // without txs - { - inclTx: false, - fullTx: false, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x64", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x296", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x0", - "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", - "uncles": [] - }`, - }, - // only tx hashes - { - inclTx: true, - fullTx: false, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x64", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x296", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x0", - "transactions": [ - "0x7d39df979e34172322c64983a9ad48302c2b889e55bda35324afecf043a77605", - "0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4", - "0x98909ea1ff040da6be56bc4231d484de1414b3c1dac372d69293a4beb9032cb5", - "0x12e1f81207b40c3bdcc13c0ee18f5f86af6d31754d57a0ea1b0d4cfef21abef1" - ], - "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", - "uncles": [] - }`, - }, - // full tx details - { - inclTx: true, - fullTx: true, - want: `{ - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x0", - "gasUsed": "0x0", - "hash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0x64", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x296", - "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x0", - "transactions": [ - { - "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "blockNumber": "0x64", - "from": "0x0000000000000000000000000000000000000000", - "gas": "0x457", - "gasPrice": "0x2b67", - "hash": "0x7d39df979e34172322c64983a9ad48302c2b889e55bda35324afecf043a77605", - "input": "0x111111", - "nonce": "0x1", - "to": "0x0000000000000000000000000000000000000011", - "transactionIndex": "0x0", - "value": "0x6f", - "type": "0x1", - "accessList": [], - "chainId": "0x539", - "v": "0x0", - "r": "0x0", - "s": "0x0", - "yParity": "0x0" - }, - { - "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "blockNumber": "0x64", - "from": "0x0000000000000000000000000000000000000000", - "gas": "0x457", - "gasPrice": "0x2b67", - "hash": "0x9bba4c34e57c875ff57ac8d172805a26ae912006985395dc1bdf8f44140a7bf4", - "input": "0x111111", - "nonce": "0x2", - "to": "0x0000000000000000000000000000000000000011", - "transactionIndex": "0x1", - "value": "0x6f", - "type": "0x0", - "chainId": "0x7fffffffffffffee", - "v": "0x0", - "r": "0x0", - "s": "0x0" - }, - { - "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "blockNumber": "0x64", - "from": "0x0000000000000000000000000000000000000000", - "gas": "0x457", - "gasPrice": "0x2b67", - "hash": "0x98909ea1ff040da6be56bc4231d484de1414b3c1dac372d69293a4beb9032cb5", - "input": "0x111111", - "nonce": "0x3", - "to": "0x0000000000000000000000000000000000000011", - "transactionIndex": "0x2", - "value": "0x6f", - "type": "0x1", - "accessList": [], - "chainId": "0x539", - "v": "0x0", - "r": "0x0", - "s": "0x0", - "yParity": "0x0" - }, - { - "blockHash": "0x9b73c83b25d0faf7eab854e3684c7e394336d6e135625aafa5c183f27baa8fee", - "blockNumber": "0x64", - "from": "0x0000000000000000000000000000000000000000", - "gas": "0x457", - "gasPrice": "0x2b67", - "hash": "0x12e1f81207b40c3bdcc13c0ee18f5f86af6d31754d57a0ea1b0d4cfef21abef1", - "input": "0x111111", - "nonce": "0x4", - "to": "0x0000000000000000000000000000000000000011", - "transactionIndex": "0x3", - "value": "0x6f", - "type": "0x0", - "chainId": "0x7fffffffffffffee", - "v": "0x0", - "r": "0x0", - "s": "0x0" - } - ], - "transactionsRoot": "0x661a9febcfa8f1890af549b874faf9fa274aede26ef489d9db0b25daa569450e", - "uncles": [] - }`, - }, - } - - for i, tc := range testSuite { - resp := RPCMarshalBlock(block, tc.inclTx, tc.fullTx, params.MainnetChainConfig) - out, err := json.Marshal(resp) - if err != nil { - t.Errorf("test %d: json marshal error: %v", i, err) - continue - } - require.JSONEqf(t, tc.want, string(out), "test %d", i) - } -} - -func TestRPCGetBlockOrHeader(t *testing.T) { - t.Parallel() - - // Initialize test accounts - var ( - acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) - acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) - genesis = &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - acc1Addr: {Balance: big.NewInt(params.Ether)}, - acc2Addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks = 10 - signer = types.HomesteadSigner{} - tx = types.NewTx(&types.LegacyTx{ - Nonce: 11, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &acc2Addr, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - withdrawal = &types.Withdrawal{ - Index: 0, - Validator: 1, - Address: common.Address{0x12, 0x34}, - Amount: 10, - } - pending = types.NewBlockWithWithdrawals(&types.Header{Number: big.NewInt(11), Time: 42}, []*types.Transaction{tx}, nil, nil, []*types.Withdrawal{withdrawal}, blocktest.NewHasher()) - ) - backend := newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, acc1Key) - b.AddTx(tx) - }) - backend.setPendingBlock(pending) - api := NewBlockChainAPI(backend) - blockHashes := make([]common.Hash, genBlocks+1) - ctx := context.Background() - for i := 0; i <= genBlocks; i++ { - header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) - if err != nil { - t.Errorf("failed to get block: %d err: %v", i, err) - } - blockHashes[i] = header.Hash() - } - pendingHash := pending.Hash() - - var testSuite = []struct { - blockNumber rpc.BlockNumber - blockHash *common.Hash - fullTx bool - reqHeader bool - file string - expectErr error - }{ - // 0. latest header - { - blockNumber: rpc.LatestBlockNumber, - reqHeader: true, - file: "tag-latest", - }, - // 1. genesis header - { - blockNumber: rpc.BlockNumber(0), - reqHeader: true, - file: "number-0", - }, - // 2. #1 header - { - blockNumber: rpc.BlockNumber(1), - reqHeader: true, - file: "number-1", - }, - // 3. latest-1 header - { - blockNumber: rpc.BlockNumber(9), - reqHeader: true, - file: "number-latest-1", - }, - // 4. latest+1 header - { - blockNumber: rpc.BlockNumber(11), - reqHeader: true, - file: "number-latest+1", - }, - // 5. pending header - { - blockNumber: rpc.PendingBlockNumber, - reqHeader: true, - file: "tag-pending", - }, - // 6. latest block - { - blockNumber: rpc.LatestBlockNumber, - file: "tag-latest", - }, - // 7. genesis block - { - blockNumber: rpc.BlockNumber(0), - file: "number-0", - }, - // 8. #1 block - { - blockNumber: rpc.BlockNumber(1), - file: "number-1", - }, - // 9. latest-1 block - { - blockNumber: rpc.BlockNumber(9), - fullTx: true, - file: "number-latest-1", - }, - // 10. latest+1 block - { - blockNumber: rpc.BlockNumber(11), - fullTx: true, - file: "number-latest+1", - }, - // 11. pending block - { - blockNumber: rpc.PendingBlockNumber, - file: "tag-pending", - }, - // 12. pending block + fullTx - { - blockNumber: rpc.PendingBlockNumber, - fullTx: true, - file: "tag-pending-fullTx", - }, - // 13. latest header by hash - { - blockHash: &blockHashes[len(blockHashes)-1], - reqHeader: true, - file: "hash-latest", - }, - // 14. genesis header by hash - { - blockHash: &blockHashes[0], - reqHeader: true, - file: "hash-0", - }, - // 15. #1 header - { - blockHash: &blockHashes[1], - reqHeader: true, - file: "hash-1", - }, - // 16. latest-1 header - { - blockHash: &blockHashes[len(blockHashes)-2], - reqHeader: true, - file: "hash-latest-1", - }, - // 17. empty hash - { - blockHash: &common.Hash{}, - reqHeader: true, - file: "hash-empty", - }, - // 18. pending hash - { - blockHash: &pendingHash, - reqHeader: true, - file: `hash-pending`, - }, - // 19. latest block - { - blockHash: &blockHashes[len(blockHashes)-1], - file: "hash-latest", - }, - // 20. genesis block - { - blockHash: &blockHashes[0], - file: "hash-genesis", - }, - // 21. #1 block - { - blockHash: &blockHashes[1], - file: "hash-1", - }, - // 22. latest-1 block - { - blockHash: &blockHashes[len(blockHashes)-2], - fullTx: true, - file: "hash-latest-1-fullTx", - }, - // 23. empty hash + body - { - blockHash: &common.Hash{}, - fullTx: true, - file: "hash-empty-fullTx", - }, - // 24. pending block - { - blockHash: &pendingHash, - file: `hash-pending`, - }, - // 25. pending block + fullTx - { - blockHash: &pendingHash, - fullTx: true, - file: "hash-pending-fullTx", - }, - } - - for i, tt := range testSuite { - var ( - result map[string]interface{} - err error - rpc string - ) - if tt.blockHash != nil { - if tt.reqHeader { - result = api.GetHeaderByHash(context.Background(), *tt.blockHash) - rpc = "eth_getHeaderByHash" - } else { - result, err = api.GetBlockByHash(context.Background(), *tt.blockHash, tt.fullTx) - rpc = "eth_getBlockByHash" - } - } else { - if tt.reqHeader { - result, err = api.GetHeaderByNumber(context.Background(), tt.blockNumber) - rpc = "eth_getHeaderByNumber" - } else { - result, err = api.GetBlockByNumber(context.Background(), tt.blockNumber, tt.fullTx) - rpc = "eth_getBlockByNumber" - } - } - if tt.expectErr != nil { - if err == nil { - t.Errorf("test %d: want error %v, have nothing", i, tt.expectErr) - continue - } - if !errors.Is(err, tt.expectErr) { - t.Errorf("test %d: error mismatch, want %v, have %v", i, tt.expectErr, err) - } - continue - } - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - - testRPCResponseWithFile(t, i, result, rpc, tt.file) - } -} - -func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) { - config := *params.MergedTestChainConfig - var ( - acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey) - acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey) - contract = common.HexToAddress("0000000000000000000000000000000000031ec7") - genesis = &core.Genesis{ - Config: &config, - ExcessBlobGas: new(uint64), - BlobGasUsed: new(uint64), - Alloc: types.GenesisAlloc{ - acc1Addr: {Balance: big.NewInt(params.Ether)}, - acc2Addr: {Balance: big.NewInt(params.Ether)}, - // // SPDX-License-Identifier: GPL-3.0 - // pragma solidity >=0.7.0 <0.9.0; - // - // contract Token { - // event Transfer(address indexed from, address indexed to, uint256 value); - // function transfer(address to, uint256 value) public returns (bool) { - // emit Transfer(msg.sender, to, value); - // return true; - // } - // } - contract: {Balance: big.NewInt(params.Ether), Code: common.FromHex("0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a9059cbb14610030575b600080fd5b61004a6004803603810190610045919061016a565b610060565b60405161005791906101c5565b60405180910390f35b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516100bf91906101ef565b60405180910390a36001905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610101826100d6565b9050919050565b610111816100f6565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b6000819050919050565b61014781610134565b811461015257600080fd5b50565b6000813590506101648161013e565b92915050565b60008060408385031215610181576101806100d1565b5b600061018f8582860161011f565b92505060206101a085828601610155565b9150509250929050565b60008115159050919050565b6101bf816101aa565b82525050565b60006020820190506101da60008301846101b6565b92915050565b6101e981610134565b82525050565b600060208201905061020460008301846101e0565b9291505056fea2646970667358221220b469033f4b77b9565ee84e0a2f04d496b18160d26034d54f9487e57788fd36d564736f6c63430008120033")}, - }, - } - signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID) - txHashes = make([]common.Hash, genBlocks) - ) - - backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) { - var ( - tx *types.Transaction - err error - ) - b.SetPoS() - switch i { - case 0: - // transfer 1000wei - tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), types.HomesteadSigner{}, acc1Key) - case 1: - // create contract - tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: nil, Gas: 53100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040")}), signer, acc1Key) - case 2: - // with logs - // transfer(address to, uint256 value) - data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:]) - tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &contract, Gas: 60000, GasPrice: b.BaseFee(), Data: common.FromHex(data)}), signer, acc1Key) - case 3: - // dynamic fee with logs - // transfer(address to, uint256 value) - data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:]) - fee := big.NewInt(500) - fee.Add(fee, b.BaseFee()) - tx, err = types.SignTx(types.NewTx(&types.DynamicFeeTx{Nonce: uint64(i), To: &contract, Gas: 60000, Value: big.NewInt(1), GasTipCap: big.NewInt(500), GasFeeCap: fee, Data: common.FromHex(data)}), signer, acc1Key) - case 4: - // access list with contract create - accessList := types.AccessList{{ - Address: contract, - StorageKeys: []common.Hash{{0}}, - }} - tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key) - case 5: - // blob tx - fee := big.NewInt(500) - fee.Add(fee, b.BaseFee()) - tx, err = types.SignTx(types.NewTx(&types.BlobTx{ - Nonce: uint64(i), - GasTipCap: uint256.NewInt(1), - GasFeeCap: uint256.MustFromBig(fee), - Gas: params.TxGas, - To: acc2Addr, - BlobFeeCap: uint256.NewInt(1), - BlobHashes: []common.Hash{{1}}, - Value: new(uint256.Int), - }), signer, acc1Key) - - case 6: - // blob tx with blobSidecar - blobSidecars := makeBlkSidecars(1, 1) - blobHashes := blobSidecars[0].BlobHashes() - fee := big.NewInt(500) - fee.Add(fee, b.BaseFee()) - tx, err = types.SignTx(types.NewTx(&types.BlobTx{ - Nonce: uint64(i), - GasTipCap: uint256.NewInt(1), - GasFeeCap: uint256.MustFromBig(fee), - Gas: params.TxGas, - To: acc2Addr, - BlobFeeCap: uint256.NewInt(1), - BlobHashes: blobHashes, - Value: new(uint256.Int), - }), signer, acc1Key) - b.AddBlobSidecar(&types.BlobSidecar{ - BlobTxSidecar: *blobSidecars[0], - TxHash: tx.Hash(), - TxIndex: 0, - }) - } - if err != nil { - t.Errorf("failed to sign tx: %v", err) - } - if tx != nil { - b.AddTx(tx) - txHashes[i] = tx.Hash() - } - }) - return backend, txHashes -} - -func TestRPCGetTransactionReceipt(t *testing.T) { - t.Parallel() - - var ( - backend, txHashes = setupReceiptBackend(t, 6) - api = NewTransactionAPI(backend, new(AddrLocker)) - ) - - var testSuite = []struct { - txHash common.Hash - file string - }{ - // 0. normal success - { - txHash: txHashes[0], - file: "normal-transfer-tx", - }, - // 1. create contract - { - txHash: txHashes[1], - file: "create-contract-tx", - }, - // 2. with logs success - { - txHash: txHashes[2], - file: "with-logs", - }, - // 3. dynamic tx with logs success - { - txHash: txHashes[3], - file: `dynamic-tx-with-logs`, - }, - // 4. access list tx with create contract - { - txHash: txHashes[4], - file: "create-contract-with-access-list", - }, - // 5. txhash empty - { - txHash: common.Hash{}, - file: "txhash-empty", - }, - // 6. txhash not found - { - txHash: common.HexToHash("deadbeef"), - file: "txhash-notfound", - }, - // 7. blob tx - { - txHash: txHashes[5], - file: "blob-tx", - }, - } - - for i, tt := range testSuite { - var ( - result interface{} - err error - ) - result, err = api.GetTransactionReceipt(context.Background(), tt.txHash) - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - testRPCResponseWithFile(t, i, result, "eth_getTransactionReceipt", tt.file) - } -} - -func TestRPCGetBlockReceipts(t *testing.T) { - t.Parallel() - - var ( - genBlocks = 6 - backend, _ = setupReceiptBackend(t, genBlocks) - api = NewBlockChainAPI(backend) - ) - blockHashes := make([]common.Hash, genBlocks+1) - ctx := context.Background() - for i := 0; i <= genBlocks; i++ { - header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) - if err != nil { - t.Errorf("failed to get block: %d err: %v", i, err) - } - blockHashes[i] = header.Hash() - } - - var testSuite = []struct { - test rpc.BlockNumberOrHash - file string - }{ - // 0. block without any txs(hash) - { - test: rpc.BlockNumberOrHashWithHash(blockHashes[0], false), - file: "number-0", - }, - // 1. block without any txs(number) - { - test: rpc.BlockNumberOrHashWithNumber(0), - file: "number-1", - }, - // 2. earliest tag - { - test: rpc.BlockNumberOrHashWithNumber(rpc.EarliestBlockNumber), - file: "tag-earliest", - }, - // 3. latest tag - { - test: rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber), - file: "tag-latest", - }, - // 4. block with legacy transfer tx(hash) - { - test: rpc.BlockNumberOrHashWithHash(blockHashes[1], false), - file: "block-with-legacy-transfer-tx", - }, - // 5. block with contract create tx(number) - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(2)), - file: "block-with-contract-create-tx", - }, - // 6. block with legacy contract call tx(hash) - { - test: rpc.BlockNumberOrHashWithHash(blockHashes[3], false), - file: "block-with-legacy-contract-call-tx", - }, - // 7. block with dynamic fee tx(number) - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(4)), - file: "block-with-dynamic-fee-tx", - }, - // 8. block is empty - { - test: rpc.BlockNumberOrHashWithHash(common.Hash{}, false), - file: "hash-empty", - }, - // 9. block is not found - { - test: rpc.BlockNumberOrHashWithHash(common.HexToHash("deadbeef"), false), - file: "hash-notfound", - }, - // 10. block is not found - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(genBlocks + 1)), - file: "block-notfound", - }, - // 11. block with blob tx - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(6)), - file: "block-with-blob-tx", - }, - } - - for i, tt := range testSuite { - var ( - result interface{} - err error - ) - result, err = api.GetBlockReceipts(context.Background(), tt.test) - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - testRPCResponseWithFile(t, i, result, "eth_getBlockReceipts", tt.file) - } -} - -func makeBlkSidecars(n, nPerTx int) []*types.BlobTxSidecar { - if n <= 0 { - return nil - } - ret := make([]*types.BlobTxSidecar, n) - for i := 0; i < n; i++ { - blobs := make([]kzg4844.Blob, nPerTx) - commitments := make([]kzg4844.Commitment, nPerTx) - proofs := make([]kzg4844.Proof, nPerTx) - for i := 0; i < nPerTx; i++ { - commitments[i], _ = kzg4844.BlobToCommitment(blobs[i]) - proofs[i], _ = kzg4844.ComputeBlobProof(blobs[i], commitments[i]) - } - ret[i] = &types.BlobTxSidecar{ - Blobs: blobs, - Commitments: commitments, - Proofs: proofs, - } - } - return ret -} - -func TestRPCGetBlobSidecars(t *testing.T) { - t.Parallel() - var ( - genBlocks = 7 - backend, _ = setupReceiptBackend(t, genBlocks) - api = NewBlockChainAPI(backend) - ) - blockHashes := make([]common.Hash, genBlocks+1) - ctx := context.Background() - for i := 0; i <= genBlocks; i++ { - header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(i)) - if err != nil { - t.Errorf("failed to get block: %d err: %v", i, err) - } - blockHashes[i] = header.Hash() - } - - var testSuite = []struct { - test rpc.BlockNumberOrHash - fullBlob bool - file string - }{ - // 1. block without any txs(number) - { - test: rpc.BlockNumberOrHashWithNumber(0), - fullBlob: true, - file: "number-1", - }, - // 2. earliest tag - { - test: rpc.BlockNumberOrHashWithNumber(rpc.EarliestBlockNumber), - fullBlob: true, - file: "tag-earliest", - }, - // 3. latest tag - { - test: rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber), - fullBlob: true, - file: "tag-latest", - }, - // 4. block is empty - { - test: rpc.BlockNumberOrHashWithHash(common.Hash{}, false), - fullBlob: true, - file: "hash-empty", - }, - // 5. block is not found - { - test: rpc.BlockNumberOrHashWithHash(common.HexToHash("deadbeef"), false), - fullBlob: true, - file: "hash-notfound", - }, - // 6. block is not found - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(genBlocks + 1)), - fullBlob: true, - file: "block-notfound", - }, - // 7. block with blob tx - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(6)), - fullBlob: true, - file: "block-with-blob-tx", - }, - // 8. block with sidecar - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(7)), - fullBlob: true, - file: "block-with-blobSidecars", - }, - // 9. block with sidecar but show little - { - test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(7)), - fullBlob: false, - file: "block-with-blobSidecars-show-little", - }, - } - - for i, tt := range testSuite { - var ( - result interface{} - err error - ) - result, err = api.GetBlobSidecars(context.Background(), tt.test, &tt.fullBlob) - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - testRPCResponseWithFile(t, i, result, "eth_getBlobSidecars", tt.file) - } -} - -func TestGetBlobSidecarByTxHash(t *testing.T) { - t.Parallel() - var ( - backend, txHashs = setupReceiptBackend(t, 7) - api = NewBlockChainAPI(backend) - ) - var testSuite = []struct { - test common.Hash - fullBlob bool - file string - }{ - // 0. txHash is empty - { - test: common.Hash{}, - fullBlob: true, - file: "hash-empty", - }, - // 1. txHash is not found - { - test: common.HexToHash("deadbeef"), - fullBlob: true, - file: "hash-notfound", - }, - // 2. txHash is not blob tx - { - test: common.HexToHash("deadbeef"), - fullBlob: true, - file: "not-blob-tx", - }, - // 3. block with blob tx without sidecar - { - test: txHashs[5], - fullBlob: true, - file: "block-with-blob-tx", - }, - // 4. block with sidecar - { - test: txHashs[6], - fullBlob: true, - file: "block-with-blobSidecars", - }, - // 5. block show part blobs - { - test: txHashs[6], - fullBlob: false, - file: "block-with-blobSidecars-show-little", - }, - } - - for i, tt := range testSuite { - var ( - result interface{} - err error - ) - result, err = api.GetBlobSidecarByTxHash(context.Background(), tt.test, &tt.fullBlob) - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - testRPCResponseWithFile(t, i, result, "eth_getBlobSidecarByTxHash", tt.file) - } -} - -func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc string, file string) { - data, err := json.MarshalIndent(result, "", " ") - if err != nil { - t.Errorf("test %d: json marshal error", testid) - return - } - outputFile := filepath.Join("testdata", fmt.Sprintf("%s-%s.json", rpc, file)) - if os.Getenv("WRITE_TEST_FILES") != "" { - os.WriteFile(outputFile, data, 0644) - } - want, err := os.ReadFile(outputFile) - if err != nil { - t.Fatalf("error reading expected test file: %s output: %v", outputFile, err) - } - require.JSONEqf(t, string(want), string(data), "test %d: json not match, want: %s, have: %s", testid, string(want), string(data)) -} diff --git a/miner/worker_test.go b/miner/worker_test.go deleted file mode 100644 index 268f3f69a5..0000000000 --- a/miner/worker_test.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package miner // TOFIX - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -const ( - // testCode is the testing contract binary code which will initialises some - // variables in constructor - testCode = "0x60806040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005534801561003457600080fd5b5060fc806100436000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630c4dae8814603757806398a213cf146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055507fe9e44f9f7da8c559de847a3232b57364adc0354f15a2cd8dc636d54396f9587a6000546040518082815260200191505060405180910390a15056fea265627a7a723058208ae31d9424f2d0bc2a3da1a5dd659db2d71ec322a17db8f87e19e209e3a1ff4a64736f6c634300050a0032" - - // testGas is the gas required for contract deployment. - testGas = 144109 -) - -var ( - // Test chain configurations - testTxPoolConfig legacypool.Config - ethashChainConfig *params.ChainConfig - cliqueChainConfig *params.ChainConfig - - // Test accounts - testBankKey, _ = crypto.GenerateKey() - testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) - testBankFunds = big.NewInt(1000000000000000000) - - testUserKey, _ = crypto.GenerateKey() - testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) - - // Test transactions - pendingTxs []*types.Transaction - newTxs []*types.Transaction - - testConfig = &Config{ - Recommit: time.Second, - GasCeil: params.GenesisGasLimit, - } -) - -func init() { - testTxPoolConfig = legacypool.DefaultConfig - testTxPoolConfig.Journal = "" - ethashChainConfig = new(params.ChainConfig) - *ethashChainConfig = *params.TestChainConfig - cliqueChainConfig = new(params.ChainConfig) - *cliqueChainConfig = *params.TestChainConfig - cliqueChainConfig.Clique = ¶ms.CliqueConfig{ - Period: 10, - Epoch: 30000, - } - - signer := types.LatestSigner(params.TestChainConfig) - tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{ - ChainID: params.TestChainConfig.ChainID, - Nonce: 0, - To: &testUserAddress, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: big.NewInt(params.InitialBaseFee), - }) - pendingTxs = append(pendingTxs, tx1) - - tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ - Nonce: 1, - To: &testUserAddress, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: big.NewInt(params.InitialBaseFee), - }) - newTxs = append(newTxs, tx2) -} - -// testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. -type testWorkerBackend struct { - db ethdb.Database - txPool *txpool.TxPool - chain *core.BlockChain - genesis *core.Genesis -} - -func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend { - var gspec = &core.Genesis{ - Config: chainConfig, - Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, - } - switch e := engine.(type) { - case *clique.Clique: - gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) - copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes()) - e.Authorize(testBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { - return crypto.Sign(crypto.Keccak256(data), testBankKey) - }) - case *ethash.Ethash: - default: - t.Fatalf("unexpected consensus engine type: %T", engine) - } - chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("core.NewBlockChain failed: %v", err) - } - pool := legacypool.New(testTxPoolConfig, chain) - txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, chain, []txpool.SubPool{pool}) - - return &testWorkerBackend{ - db: db, - chain: chain, - txPool: txpool, - genesis: gspec, - } -} - -func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } -func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool } - -func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { - var tx *types.Transaction - gasPrice := big.NewInt(10 * params.InitialBaseFee) - if creation { - tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(testBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey) - } else { - tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey) - } - return tx -} - -func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int) (*worker, *testWorkerBackend) { - backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) - backend.txPool.Add(pendingTxs, true, false) - w := newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) - w.setEtherbase(testBankAddress) - return w, backend -} - -func TestGenerateAndImportBlock(t *testing.T) { - t.Parallel() - var ( - db = rawdb.NewMemoryDatabase() - config = *params.AllCliqueProtocolChanges - ) - config.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} - engine := clique.New(config.Clique, db) - - w, b := newTestWorker(t, &config, engine, db, 0) - defer w.close() - - // This test chain imports the mined blocks. - chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, b.genesis, nil, engine, vm.Config{}, nil, nil) - defer chain.Stop() - - // Ignore empty commit here for less noise. - w.skipSealHook = func(task *task) bool { - return len(task.receipts) == 0 - } - - // Wait for mined blocks. - sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) - defer sub.Unsubscribe() - - // Start mining! - w.start() - - for i := 0; i < 5; i++ { - b.txPool.Add([]*types.Transaction{b.newRandomTx(true)}, true, false) - b.txPool.Add([]*types.Transaction{b.newRandomTx(false)}, true, false) - - select { - case ev := <-sub.Chan(): - block := ev.Data.(core.NewMinedBlockEvent).Block - if _, err := chain.InsertChain([]*types.Block{block}); err != nil { - t.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) - } - case <-time.After(3 * time.Second): // Worker needs 1s to include new changes. - t.Fatalf("timeout") - } - } -} - -func TestEmptyWorkEthash(t *testing.T) { - t.Parallel() - testEmptyWork(t, ethashChainConfig, ethash.NewFaker()) -} -func TestEmptyWorkClique(t *testing.T) { - t.Parallel() - testEmptyWork(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase())) -} - -func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { - defer engine.Close() - - w, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) - defer w.close() - - taskCh := make(chan struct{}, 2) - checkEqual := func(t *testing.T, task *task) { - // The work should contain 1 tx - receiptLen, balance := 1, uint256.NewInt(1000) - if len(task.receipts) != receiptLen { - t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen) - } - if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 { - t.Fatalf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance) - } - } - w.newTaskHook = func(task *task) { - if task.block.NumberU64() == 1 { - checkEqual(t, task) - taskCh <- struct{}{} - } - } - w.skipSealHook = func(task *task) bool { return true } - w.fullTaskHook = func() { - time.Sleep(100 * time.Millisecond) - } - w.start() // Start mining! - select { - case <-taskCh: - case <-time.NewTimer(3 * time.Second).C: - t.Error("new task timeout") - } -} - -func TestGetSealingWorkEthash(t *testing.T) { - t.Parallel() - testGetSealingWork(t, ethashChainConfig, ethash.NewFaker()) -} - -func TestGetSealingWorkClique(t *testing.T) { - t.Parallel() - testGetSealingWork(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase())) -} - -func TestGetSealingWorkPostMerge(t *testing.T) { - t.Parallel() - local := new(params.ChainConfig) - *local = *ethashChainConfig - local.TerminalTotalDifficulty = big.NewInt(0) - testGetSealingWork(t, local, ethash.NewFaker()) -} - -func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { - defer engine.Close() - - w, b := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) - defer w.close() - - w.setExtra([]byte{0x01, 0x02}) - - w.skipSealHook = func(task *task) bool { - return true - } - w.fullTaskHook = func() { - time.Sleep(100 * time.Millisecond) - } - timestamp := uint64(time.Now().Unix()) - assertBlock := func(block *types.Block, number uint64, coinbase common.Address, random common.Hash) { - if block.Time() != timestamp { - // Sometime the timestamp will be mutated if the timestamp - // is even smaller than parent block's. It's OK. - t.Logf("Invalid timestamp, want %d, get %d", timestamp, block.Time()) - } - _, isClique := engine.(*clique.Clique) - if !isClique { - if len(block.Extra()) != 2 { - t.Error("Unexpected extra field") - } - if block.Coinbase() != coinbase { - t.Errorf("Unexpected coinbase got %x want %x", block.Coinbase(), coinbase) - } - } else { - if block.Coinbase() != (common.Address{}) { - t.Error("Unexpected coinbase") - } - } - if !isClique { - if block.MixDigest() != random { - t.Error("Unexpected mix digest") - } - } - if block.Nonce() != 0 { - t.Error("Unexpected block nonce") - } - if block.NumberU64() != number { - t.Errorf("Mismatched block number, want %d got %d", number, block.NumberU64()) - } - } - var cases = []struct { - parent common.Hash - coinbase common.Address - random common.Hash - expectNumber uint64 - expectErr bool - }{ - { - b.chain.Genesis().Hash(), - common.HexToAddress("0xdeadbeef"), - common.HexToHash("0xcafebabe"), - uint64(1), - false, - }, - { - b.chain.CurrentBlock().Hash(), - common.HexToAddress("0xdeadbeef"), - common.HexToHash("0xcafebabe"), - b.chain.CurrentBlock().Number.Uint64() + 1, - false, - }, - { - b.chain.CurrentBlock().Hash(), - common.Address{}, - common.HexToHash("0xcafebabe"), - b.chain.CurrentBlock().Number.Uint64() + 1, - false, - }, - { - b.chain.CurrentBlock().Hash(), - common.Address{}, - common.Hash{}, - b.chain.CurrentBlock().Number.Uint64() + 1, - false, - }, - { - common.HexToHash("0xdeadbeef"), - common.HexToAddress("0xdeadbeef"), - common.HexToHash("0xcafebabe"), - 0, - true, - }, - } - - // This API should work even when the automatic sealing is not enabled - for _, c := range cases { - r := w.getSealingBlock(&generateParams{ - parentHash: c.parent, - timestamp: timestamp, - coinbase: c.coinbase, - random: c.random, - withdrawals: nil, - beaconRoot: nil, - noTxs: false, - forceTime: true, - }) - if c.expectErr { - if r.err == nil { - t.Error("Expect error but get nil") - } - } else { - if r.err != nil { - t.Errorf("Unexpected error %v", r.err) - } - assertBlock(r.block, c.expectNumber, c.coinbase, c.random) - } - } - - // This API should work even when the automatic sealing is enabled - w.start() - for _, c := range cases { - r := w.getSealingBlock(&generateParams{ - parentHash: c.parent, - timestamp: timestamp, - coinbase: c.coinbase, - random: c.random, - withdrawals: nil, - beaconRoot: nil, - noTxs: false, - forceTime: true, - }) - if c.expectErr { - if r.err == nil { - t.Error("Expect error but get nil") - } - } else { - if r.err != nil { - t.Errorf("Unexpected error %v", r.err) - } - assertBlock(r.block, c.expectNumber, c.coinbase, c.random) - } - } -}