github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/miner/payload_building_test.go (about) 1 // Copyright 2022 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 miner 18 19 import ( 20 "math/big" 21 "reflect" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/accounts" 26 "github.com/ethereum/go-ethereum/beacon/engine" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus" 29 "github.com/ethereum/go-ethereum/consensus/clique" 30 "github.com/ethereum/go-ethereum/consensus/ethash" 31 "github.com/ethereum/go-ethereum/core" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/txpool" 34 "github.com/ethereum/go-ethereum/core/txpool/legacypool" 35 "github.com/ethereum/go-ethereum/core/types" 36 "github.com/ethereum/go-ethereum/core/vm" 37 "github.com/ethereum/go-ethereum/crypto" 38 "github.com/ethereum/go-ethereum/ethdb" 39 "github.com/ethereum/go-ethereum/params" 40 ) 41 42 var ( 43 // Test chain configurations 44 testTxPoolConfig legacypool.Config 45 ethashChainConfig *params.ChainConfig 46 cliqueChainConfig *params.ChainConfig 47 48 // Test accounts 49 testBankKey, _ = crypto.GenerateKey() 50 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 51 testBankFunds = big.NewInt(1000000000000000000) 52 53 testUserKey, _ = crypto.GenerateKey() 54 testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) 55 56 // Test transactions 57 pendingTxs []*types.Transaction 58 newTxs []*types.Transaction 59 60 testConfig = Config{ 61 PendingFeeRecipient: testBankAddress, 62 Recommit: time.Second, 63 GasCeil: params.GenesisGasLimit, 64 } 65 ) 66 67 func init() { 68 testTxPoolConfig = legacypool.DefaultConfig 69 testTxPoolConfig.Journal = "" 70 ethashChainConfig = new(params.ChainConfig) 71 *ethashChainConfig = *params.TestChainConfig 72 cliqueChainConfig = new(params.ChainConfig) 73 *cliqueChainConfig = *params.TestChainConfig 74 cliqueChainConfig.Clique = ¶ms.CliqueConfig{ 75 Period: 10, 76 Epoch: 30000, 77 } 78 79 signer := types.LatestSigner(params.TestChainConfig) 80 tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{ 81 ChainID: params.TestChainConfig.ChainID, 82 Nonce: 0, 83 To: &testUserAddress, 84 Value: big.NewInt(1000), 85 Gas: params.TxGas, 86 GasPrice: big.NewInt(params.InitialBaseFee), 87 }) 88 pendingTxs = append(pendingTxs, tx1) 89 90 tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ 91 Nonce: 1, 92 To: &testUserAddress, 93 Value: big.NewInt(1000), 94 Gas: params.TxGas, 95 GasPrice: big.NewInt(params.InitialBaseFee), 96 }) 97 newTxs = append(newTxs, tx2) 98 } 99 100 // testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. 101 type testWorkerBackend struct { 102 db ethdb.Database 103 txPool *txpool.TxPool 104 chain *core.BlockChain 105 genesis *core.Genesis 106 } 107 108 func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend { 109 var gspec = &core.Genesis{ 110 Config: chainConfig, 111 Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, 112 } 113 switch e := engine.(type) { 114 case *clique.Clique: 115 gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) 116 copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes()) 117 e.Authorize(testBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { 118 return crypto.Sign(crypto.Keccak256(data), testBankKey) 119 }) 120 case *ethash.Ethash: 121 default: 122 t.Fatalf("unexpected consensus engine type: %T", engine) 123 } 124 chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil) 125 if err != nil { 126 t.Fatalf("core.NewBlockChain failed: %v", err) 127 } 128 pool := legacypool.New(testTxPoolConfig, chain) 129 txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, chain, []txpool.SubPool{pool}) 130 131 return &testWorkerBackend{ 132 db: db, 133 chain: chain, 134 txPool: txpool, 135 genesis: gspec, 136 } 137 } 138 139 func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } 140 func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool } 141 142 func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int) (*Miner, *testWorkerBackend) { 143 backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) 144 backend.txPool.Add(pendingTxs, true, false) 145 w := New(backend, testConfig, engine) 146 return w, backend 147 } 148 149 func TestBuildPayload(t *testing.T) { 150 var ( 151 db = rawdb.NewMemoryDatabase() 152 recipient = common.HexToAddress("0xdeadbeef") 153 ) 154 w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) 155 156 timestamp := uint64(time.Now().Unix()) 157 args := &BuildPayloadArgs{ 158 Parent: b.chain.CurrentBlock().Hash(), 159 Timestamp: timestamp, 160 Random: common.Hash{}, 161 FeeRecipient: recipient, 162 } 163 payload, err := w.buildPayload(args) 164 if err != nil { 165 t.Fatalf("Failed to build payload %v", err) 166 } 167 verify := func(outer *engine.ExecutionPayloadEnvelope, txs int) { 168 payload := outer.ExecutionPayload 169 if payload.ParentHash != b.chain.CurrentBlock().Hash() { 170 t.Fatal("Unexpected parent hash") 171 } 172 if payload.Random != (common.Hash{}) { 173 t.Fatal("Unexpected random value") 174 } 175 if payload.Timestamp != timestamp { 176 t.Fatal("Unexpected timestamp") 177 } 178 if payload.FeeRecipient != recipient { 179 t.Fatal("Unexpected fee recipient") 180 } 181 if len(payload.Transactions) != txs { 182 t.Fatal("Unexpected transaction set") 183 } 184 } 185 empty := payload.ResolveEmpty() 186 verify(empty, 0) 187 188 full := payload.ResolveFull() 189 verify(full, len(pendingTxs)) 190 191 // Ensure resolve can be called multiple times and the 192 // result should be unchanged 193 dataOne := payload.Resolve() 194 dataTwo := payload.Resolve() 195 if !reflect.DeepEqual(dataOne, dataTwo) { 196 t.Fatal("Unexpected payload data") 197 } 198 } 199 200 func TestPayloadId(t *testing.T) { 201 t.Parallel() 202 ids := make(map[string]int) 203 for i, tt := range []*BuildPayloadArgs{ 204 { 205 Parent: common.Hash{1}, 206 Timestamp: 1, 207 Random: common.Hash{0x1}, 208 FeeRecipient: common.Address{0x1}, 209 }, 210 // Different parent 211 { 212 Parent: common.Hash{2}, 213 Timestamp: 1, 214 Random: common.Hash{0x1}, 215 FeeRecipient: common.Address{0x1}, 216 }, 217 // Different timestamp 218 { 219 Parent: common.Hash{2}, 220 Timestamp: 2, 221 Random: common.Hash{0x1}, 222 FeeRecipient: common.Address{0x1}, 223 }, 224 // Different Random 225 { 226 Parent: common.Hash{2}, 227 Timestamp: 2, 228 Random: common.Hash{0x2}, 229 FeeRecipient: common.Address{0x1}, 230 }, 231 // Different fee-recipient 232 { 233 Parent: common.Hash{2}, 234 Timestamp: 2, 235 Random: common.Hash{0x2}, 236 FeeRecipient: common.Address{0x2}, 237 }, 238 // Different withdrawals (non-empty) 239 { 240 Parent: common.Hash{2}, 241 Timestamp: 2, 242 Random: common.Hash{0x2}, 243 FeeRecipient: common.Address{0x2}, 244 Withdrawals: []*types.Withdrawal{ 245 { 246 Index: 0, 247 Validator: 0, 248 Address: common.Address{}, 249 Amount: 0, 250 }, 251 }, 252 }, 253 // Different withdrawals (non-empty) 254 { 255 Parent: common.Hash{2}, 256 Timestamp: 2, 257 Random: common.Hash{0x2}, 258 FeeRecipient: common.Address{0x2}, 259 Withdrawals: []*types.Withdrawal{ 260 { 261 Index: 2, 262 Validator: 0, 263 Address: common.Address{}, 264 Amount: 0, 265 }, 266 }, 267 }, 268 } { 269 id := tt.Id().String() 270 if prev, exists := ids[id]; exists { 271 t.Errorf("ID collision, case %d and case %d: id %v", prev, i, id) 272 } 273 ids[id] = i 274 } 275 }