mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
Synchronize miner gas tip updates across subsystems when RPC updates gas price. - update eth miner API to apply gas tip changes to both txpool and miner - add miner/worker SetGasTip path and initialize worker tip from config - adjust bind util test to use params.GWei over base fee Ref: #28933
174 lines
4.9 KiB
Go
174 lines
4.9 KiB
Go
// Copyright 2026 The XDPoSChain Authors
|
|
// This file is part of the XDPoSChain library.
|
|
//
|
|
// The XDPoSChain 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 XDPoSChain 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 XDPoSChain library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package miner
|
|
|
|
import (
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
|
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
|
"github.com/XinFinOrg/XDPoSChain/core"
|
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
|
"github.com/XinFinOrg/XDPoSChain/event"
|
|
"github.com/XinFinOrg/XDPoSChain/params"
|
|
)
|
|
|
|
func newBlockingSubscription() event.Subscription {
|
|
return event.NewSubscription(func(unsub <-chan struct{}) error {
|
|
<-unsub
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func TestWorkerUpdateNonXDPoSStaysRunning(t *testing.T) {
|
|
worker := &worker{
|
|
engine: ethash.NewFaker(),
|
|
chainHeadSub: newBlockingSubscription(),
|
|
chainSideSub: newBlockingSubscription(),
|
|
resetCh: make(chan time.Duration, 1),
|
|
}
|
|
|
|
done := make(chan struct{})
|
|
started := make(chan struct{})
|
|
go func() {
|
|
close(started)
|
|
worker.update()
|
|
close(done)
|
|
}()
|
|
select {
|
|
case <-started:
|
|
// worker.update has started; proceed with timing checks.
|
|
case <-time.After(time.Second):
|
|
t.Fatal("worker.update did not start in time")
|
|
}
|
|
|
|
select {
|
|
case <-done:
|
|
t.Fatal("worker.update returned before unsubscribe")
|
|
default:
|
|
// Expected: update is still running until subscription error.
|
|
}
|
|
worker.chainHeadSub.Unsubscribe()
|
|
|
|
select {
|
|
case <-done:
|
|
// Expected: update exits after subscription error.
|
|
case <-time.After(time.Second):
|
|
t.Fatal("worker.update did not return after unsubscribe")
|
|
}
|
|
}
|
|
|
|
func TestWorkerCheckPreCommitXDPoSMismatch(t *testing.T) {
|
|
config := ¶ms.ChainConfig{
|
|
ChainID: big.NewInt(1),
|
|
XDPoS: ¶ms.XDPoSConfig{
|
|
V2: ¶ms.V2{
|
|
SwitchBlock: big.NewInt(0),
|
|
AllConfigs: map[uint64]*params.V2Config{
|
|
0: {MinePeriod: 2},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
signer := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
extraData := make([]byte, 0, utils.ExtraVanity+common.AddressLength+utils.ExtraSeal)
|
|
extraData = append(extraData, make([]byte, utils.ExtraVanity)...)
|
|
extraData = append(extraData, signer.Bytes()...)
|
|
extraData = append(extraData, make([]byte, utils.ExtraSeal)...)
|
|
genesis := &core.Genesis{
|
|
Config: config,
|
|
GasLimit: params.XDCGenesisGasLimit,
|
|
Difficulty: big.NewInt(1),
|
|
Alloc: types.GenesisAlloc{},
|
|
ExtraData: extraData,
|
|
}
|
|
db := rawdb.NewMemoryDatabase()
|
|
if _, err := genesis.Commit(db); err != nil {
|
|
t.Fatalf("failed to commit genesis: %v", err)
|
|
}
|
|
engine := ethash.NewFaker()
|
|
chain, err := core.NewBlockChain(db, nil, genesis, engine, vm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("failed to create blockchain: %v", err)
|
|
}
|
|
defer chain.Stop()
|
|
|
|
worker := &worker{
|
|
chainConfig: config,
|
|
engine: engine,
|
|
chain: chain,
|
|
announceTxs: true,
|
|
}
|
|
|
|
parent, shouldReturn := worker.checkPreCommitWithLock()
|
|
if parent == nil {
|
|
t.Fatal("expected parent block, got nil")
|
|
}
|
|
if !shouldReturn {
|
|
t.Fatal("expected checkPreCommitWithLock to skip when XDPoS config is enabled but engine is not XDPoS")
|
|
}
|
|
if parent.Number().Sign() != 0 {
|
|
t.Fatalf("expected genesis parent, got number %v", parent.Number())
|
|
}
|
|
}
|
|
|
|
func TestWorkerSetGasTipValidation(t *testing.T) {
|
|
w := &worker{tip: big.NewInt(1)}
|
|
old := new(big.Int).Set(w.tip)
|
|
|
|
tests := []struct {
|
|
name string
|
|
tip *big.Int
|
|
}{
|
|
{name: "nil", tip: nil},
|
|
{name: "negative", tip: big.NewInt(-1)},
|
|
{name: "too high", tip: new(big.Int).Add(maxGasTip, big.NewInt(1))},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if err := w.setGasTip(tc.tip); err == nil {
|
|
t.Fatalf("expected error for %s tip", tc.name)
|
|
}
|
|
if w.tip.Cmp(old) != 0 {
|
|
t.Fatalf("tip changed on invalid input: have %v want %v", w.tip, old)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWorkerSetGasTipCopiesValue(t *testing.T) {
|
|
w := &worker{}
|
|
input := big.NewInt(2 * params.GWei)
|
|
|
|
if err := w.setGasTip(input); err != nil {
|
|
t.Fatalf("setGasTip failed: %v", err)
|
|
}
|
|
if w.tip == input {
|
|
t.Fatal("worker tip shares pointer with input")
|
|
}
|
|
|
|
input.Add(input, big.NewInt(1))
|
|
if w.tip.Cmp(big.NewInt(2*params.GWei)) != 0 {
|
|
t.Fatalf("worker tip mutated via input pointer: have %v", w.tip)
|
|
}
|
|
}
|