go-ethereum/miner/payload_building_test.go
Péter Szilágyi 31a6418d77
consensus/clique, miner: remove clique -> accounts dependency (#30642)
Clique currently depends on the `accounts` package. This was a bit of a
big cannon even in the past, just to pass a signer "account" to the
Clique block producer. Either way, nowadays Geth does not support clique
mining any more, so by removing that bit of functionality from our code,
we can also break this dependency.

Clique should ideally be further torn out, but this at least gets us one
step closer to cleanups.
2024-10-21 09:24:28 +03:00

273 lines
7.8 KiB
Go

// Copyright 2022 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 <http://www.gnu.org/licenses/>
package miner
import (
"math/big"
"reflect"
"testing"
"time"
"github.com/ethereum/go-ethereum/beacon/engine"
"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/params"
)
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{
PendingFeeRecipient: testBankAddress,
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 = &params.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)
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)
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 newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int) (*Miner, *testWorkerBackend) {
backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks)
backend.txPool.Add(pendingTxs, true, true)
w := New(backend, testConfig, engine)
return w, backend
}
func TestBuildPayload(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
recipient = common.HexToAddress("0xdeadbeef")
)
w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0)
timestamp := uint64(time.Now().Unix())
args := &BuildPayloadArgs{
Parent: b.chain.CurrentBlock().Hash(),
Timestamp: timestamp,
Random: common.Hash{},
FeeRecipient: recipient,
}
payload, err := w.buildPayload(args, false)
if err != nil {
t.Fatalf("Failed to build payload %v", err)
}
verify := func(outer *engine.ExecutionPayloadEnvelope, txs int) {
payload := outer.ExecutionPayload
if payload.ParentHash != b.chain.CurrentBlock().Hash() {
t.Fatal("Unexpected parent hash")
}
if payload.Random != (common.Hash{}) {
t.Fatal("Unexpected random value")
}
if payload.Timestamp != timestamp {
t.Fatal("Unexpected timestamp")
}
if payload.FeeRecipient != recipient {
t.Fatal("Unexpected fee recipient")
}
if len(payload.Transactions) != txs {
t.Fatal("Unexpected transaction set")
}
}
empty := payload.ResolveEmpty()
verify(empty, 0)
full := payload.ResolveFull()
verify(full, len(pendingTxs))
// Ensure resolve can be called multiple times and the
// result should be unchanged
dataOne := payload.Resolve()
dataTwo := payload.Resolve()
if !reflect.DeepEqual(dataOne, dataTwo) {
t.Fatal("Unexpected payload data")
}
}
func TestPayloadId(t *testing.T) {
t.Parallel()
ids := make(map[string]int)
for i, tt := range []*BuildPayloadArgs{
{
Parent: common.Hash{1},
Timestamp: 1,
Random: common.Hash{0x1},
FeeRecipient: common.Address{0x1},
},
// Different parent
{
Parent: common.Hash{2},
Timestamp: 1,
Random: common.Hash{0x1},
FeeRecipient: common.Address{0x1},
},
// Different timestamp
{
Parent: common.Hash{2},
Timestamp: 2,
Random: common.Hash{0x1},
FeeRecipient: common.Address{0x1},
},
// Different Random
{
Parent: common.Hash{2},
Timestamp: 2,
Random: common.Hash{0x2},
FeeRecipient: common.Address{0x1},
},
// Different fee-recipient
{
Parent: common.Hash{2},
Timestamp: 2,
Random: common.Hash{0x2},
FeeRecipient: common.Address{0x2},
},
// Different withdrawals (non-empty)
{
Parent: common.Hash{2},
Timestamp: 2,
Random: common.Hash{0x2},
FeeRecipient: common.Address{0x2},
Withdrawals: []*types.Withdrawal{
{
Index: 0,
Validator: 0,
Address: common.Address{},
Amount: 0,
},
},
},
// Different withdrawals (non-empty)
{
Parent: common.Hash{2},
Timestamp: 2,
Random: common.Hash{0x2},
FeeRecipient: common.Address{0x2},
Withdrawals: []*types.Withdrawal{
{
Index: 2,
Validator: 0,
Address: common.Address{},
Amount: 0,
},
},
},
} {
id := tt.Id().String()
if prev, exists := ids[id]; exists {
t.Errorf("ID collision, case %d and case %d: id %v", prev, i, id)
}
ids[id] = i
}
}