Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/geth: implement dev mode for post-merge #27327

Merged
merged 49 commits into from
Jul 6, 2023
Merged
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
667a585
devmode (rebased again)
jwasinger Jun 12, 2023
b4d5583
break withdrawal logic into separate structure
jwasinger Jun 12, 2023
e5ca14a
fix/add comments
jwasinger Jun 12, 2023
59850ce
rename clmock->simulated_beacon
jwasinger Jun 12, 2023
797494a
remove unused file. remove unused code from node.go. move mutex ope…
jwasinger Jun 13, 2023
a33ad4a
move feeRecipient access into private function. remove some empty lines
jwasinger Jun 13, 2023
3d7dc00
use shutdown channel instead of context and cancel function
jwasinger Jun 13, 2023
fe5db72
check if we have any transactions, without relying on the pending block
jwasinger Jun 13, 2023
c32fc8d
use Sign instead of Bitlen to check if big.Int == 0
jwasinger Jun 13, 2023
fa9267d
simulated_beacon: fixes
holiman Jun 13, 2023
8d91eaa
don't validate withdrawal indices
jwasinger Jun 13, 2023
5f04806
rename simulated_beacon package to simulatedbeacon. move under cmd/geth
jwasinger Jun 13, 2023
650374a
lint
jwasinger Jun 13, 2023
92441a1
cmd/geth/simulatedbeacon: refactorings
holiman Jun 14, 2023
942a841
rename withdrawals->withdrawalQueue. re-include withdrawals in blocks
jwasinger Jun 14, 2023
a0938fb
remove usage of log.Crit
jwasinger Jun 14, 2023
434cc20
fix withdrawals not being included when dev period is 0
jwasinger Jun 15, 2023
b7408af
don't register catalyst service twice in dev mode.
jwasinger Jun 19, 2023
c8c920d
rename simulatedbeacon files to reflect package name
jwasinger Jun 19, 2023
59df562
Update cmd/geth/config.go
jwasinger Jun 19, 2023
9c91d84
Update cmd/geth/simulatedbeacon/simulatedbeacon.go
jwasinger Jun 19, 2023
cca59ec
Update cmd/geth/simulatedbeacon/simulatedbeacon.go
jwasinger Jun 19, 2023
06213ac
goimports
jwasinger Jun 19, 2023
12b410a
add license
jwasinger Jun 20, 2023
7d4d5cf
use common.Hash instead of *common.Hash for feeRecipient apis
jwasinger Jun 20, 2023
30ca6f5
instantiate withdrawalQueue with new(...)
jwasinger Jun 20, 2023
f59982e
move withdrawals into single array in withdrawalQueue. rename getQue…
jwasinger Jun 20, 2023
7c98200
remove uneccesary calls to engineAPI.ExchangeTransitionConfigurationV1
jwasinger Jun 20, 2023
f687ee4
move SimulatedBeacon.shutdownCh initialization into constructor
jwasinger Jun 20, 2023
1bb92db
move simulatedbeacon package contents under eth/catalyst
jwasinger Jun 20, 2023
be5e29e
rename getFeeRecipient() -> feeRecipient
jwasinger Jun 20, 2023
c8d9ef3
Update eth/catalyst/simulated_beacon.go
jwasinger Jun 20, 2023
bb7b0cd
Update eth/catalyst/simulated_beacon.go
jwasinger Jun 20, 2023
402ac2e
Update eth/catalyst/simulated_beacon.go
jwasinger Jun 20, 2023
27f0bb0
move beginSealing and finalizeSealing out of loop
jwasinger Jun 20, 2023
8d3330a
cmd/geth: prefer utils.Fatalf over returning an error object in makeF…
jwasinger Jun 21, 2023
e21dc29
only clear as many pending withdrawals from the queue as were include…
jwasinger Jun 25, 2023
e3ab2db
change dev.period flag to uint64 flag type
jwasinger Jun 26, 2023
714bf98
don't register catalyst service if in light sync mode
jwasinger Jun 27, 2023
4fd9197
better naming for feeRecipientMutex. move initialization of Simulate…
jwasinger Jun 27, 2023
5eac860
Update eth/catalyst/simulated_beacon.go
jwasinger Jun 27, 2023
1340352
wip: prepare for using new miner GetFullPayload api
jwasinger Jun 27, 2023
c6b50e9
eth/catalyst, miner: add GetFullPayload API
rjl493456442 Jun 26, 2023
e83d22d
somewhat works... but is mistakenly tracking multiple payloads simult…
jwasinger Jun 27, 2023
68608ca
refactor simulated_beacon based on miner API changes
jwasinger Jun 28, 2023
3a16d22
remove logging. add comment
jwasinger Jun 28, 2023
c592736
remove period from developer genesis configuration
jwasinger Jun 28, 2023
a504a80
comments
jwasinger Jun 28, 2023
ba286e5
cmd, eth/catalyst, miner: terminate block building by ResolveFull
rjl493456442 Jun 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cmd/geth/simulatedbeacon: refactorings
  • Loading branch information
holiman authored and jwasinger committed Jul 2, 2023
commit 92441a1ea779b8b265404b63417ef2121562c8bd
138 changes: 79 additions & 59 deletions cmd/geth/simulatedbeacon/simulated_beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"sync"
"time"

"fmt"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -63,6 +64,13 @@ func (w *withdrawals) add(withdrawal *types.Withdrawal) error {
return nil
}

// length returns the length of the pending withdrawals.
func (w *withdrawals) length() int {
w.mu.Lock()
defer w.mu.Unlock()
return len(w.pending)
}

type SimulatedBeacon struct {
shutdownCh chan struct{}
eth *eth.Ethereum
Expand Down Expand Up @@ -118,8 +126,8 @@ func (c *SimulatedBeacon) Stop() error {
// it drives block production, taking the role of a CL client and interacting with Geth via public engine/eth APIs
func (c *SimulatedBeacon) loop() {
var (
ticker = time.NewTicker(time.Millisecond * 100)

ticker = time.NewTimer(time.Second * time.Duration(c.period))
buildWaitTime = time.Millisecond * 100
header = c.eth.BlockChain().CurrentHeader()
lastBlockTime = header.Time
engineAPI = catalyst.NewConsensusAPI(c.eth)
Expand All @@ -128,80 +136,92 @@ func (c *SimulatedBeacon) loop() {
SafeBlockHash: header.Hash(),
FinalizedBlockHash: header.Hash(),
}
buildWaitTime = time.Millisecond * 100
pendingWithdrawals []*types.Withdrawal
)

// if genesis block, send forkchoiceUpdated to trigger transition to PoS
if header.Number.Sign() == 0 {
if _, err := engineAPI.ForkchoiceUpdatedV2(curForkchoiceState, nil); err != nil {
log.Crit("failed to initiate PoS transition for genesis via Forkchoiceupdated", "err", err)
}
}

beginSealing := func() (engine.ForkChoiceResponse, error) {
tstamp := uint64(time.Now().Unix())
if tstamp <= lastBlockTime {
tstamp = lastBlockTime + 1
}
return engineAPI.ForkchoiceUpdatedV2(curForkchoiceState, &engine.PayloadAttributes{
Timestamp: tstamp,
SuggestedFeeRecipient: c.getFeeRecipient(),
Withdrawals: c.withdrawals.pop(),
})
}
finalizeSealing := func(id *engine.PayloadID, onDemand bool) error {
payload, err := engineAPI.GetPayloadV1(*id)
if err != nil {
return fmt.Errorf("error retrieving payload: %v", err)
}

if onDemand && len(payload.Transactions) == 0 && len(payload.Withdrawals) == 0 {
// If the payload is empty, despite there being pending transactions,
// that indicates that we need to give it more time to build the block.
if buildWaitTime < 10*time.Second {
buildWaitTime += buildWaitTime
}
// TODO: don't lose withdrawals
return nil
}
buildWaitTime = 100 * time.Millisecond // Reset it
// mark the payload as canon
if _, err = engineAPI.NewPayloadV2(*payload); err != nil {
return fmt.Errorf("failed to mark payload as canonical: %v", err)
}
curForkchoiceState = engine.ForkchoiceStateV1{
HeadBlockHash: payload.BlockHash,
SafeBlockHash: payload.BlockHash,
FinalizedBlockHash: payload.BlockHash,
}
// mark the block containing the payload as canonical
if _, err = engineAPI.ForkchoiceUpdatedV2(curForkchoiceState, nil); err != nil {
return fmt.Errorf("failed to mark block as canonical: %v", err)
}
lastBlockTime = payload.Timestamp
return nil
}
var fcId *engine.PayloadID
if fc, err := beginSealing(); err != nil {
log.Error("Error starting sealing-work", "err", err)
return
} else {
fcId = fc.PayloadID
}
onDemand := (c.period == 0)
for {
select {
case <-c.shutdownCh:
break
case curTime := <-ticker.C:
if c.period != 0 && uint64(curTime.Unix()) <= lastBlockTime+c.period {
// In period=N, mine every N seconds
continue
}
pendingWithdrawals = c.withdrawals.pop()
if c.period == 0 {
// In period=0, mine whenever we have stuff to mine
if pendingTxs, _ := c.eth.APIBackend.TxPool().Stats(); pendingTxs == 0 && len(pendingWithdrawals) == 0 {
return
case <-ticker.C:
if onDemand {
// Do nothing as long as blocks are empty
if pendingTxs, _ := c.eth.APIBackend.TxPool().Stats(); pendingTxs == 0 && c.withdrawals.length() == 0 {
ticker.Reset(buildWaitTime)
continue
}
}
// Looks like it's time to build us a block!
tstamp := uint64(curTime.Unix())
if tstamp <= lastBlockTime {
tstamp = lastBlockTime + 1
}
fcState, err := engineAPI.ForkchoiceUpdatedV2(curForkchoiceState, &engine.PayloadAttributes{
Timestamp: tstamp,
Random: common.Hash{}, // TODO: make this configurable?
SuggestedFeeRecipient: c.getFeeRecipient(),
Withdrawals: pendingWithdrawals,
})
if err != nil {
log.Crit("failed to trigger block building via forkchoiceupdated", "err", err)
}

time.Sleep(buildWaitTime) // Give it some time to build
var payload *engine.ExecutableData
if payload, err = engineAPI.GetPayloadV1(*fcState.PayloadID); err != nil {
log.Crit("error retrieving payload", "err", err)
}
// Don't accept empty blocks if perdiod == 0
if len(payload.Transactions) == 0 && len(payload.Withdrawals) == 0 && c.period == 0 {
// If the payload is empty, despite there being pending transactions,
// that indicates that we need to give it more time to build the block.
if buildWaitTime < 10*time.Second {
buildWaitTime += buildWaitTime
}
// If we hit here, we will lose the pendingWithdrawals, We either
// need to undo the 'pop', or we need to remember the popped withdrawals
// locally.
continue
}
buildWaitTime = 100 * time.Millisecond // Set back (might have been bumped)
// mark the payload as canon
if _, err = engineAPI.NewPayloadV2(*payload); err != nil {
log.Crit("failed to mark payload as canonical", "err", err)
if err := finalizeSealing(fcId, onDemand); err != nil {
log.Error("Error collecting sealing-work", "err", err)
return
}
curForkchoiceState = engine.ForkchoiceStateV1{
HeadBlockHash: payload.BlockHash,
SafeBlockHash: payload.BlockHash,
FinalizedBlockHash: payload.BlockHash,
if fc, err := beginSealing(); err != nil {
log.Error("Error starting sealing-work", "err", err)
return
} else {
fcId = fc.PayloadID
}
// mark the block containing the payload as canonical
if _, err = engineAPI.ForkchoiceUpdatedV2(curForkchoiceState, nil); err != nil {
log.Crit("failed to mark block as canonical", "err", err)
if !onDemand {
ticker.Reset(time.Second * time.Duration(c.period))
} else {
ticker.Reset(buildWaitTime)
}
lastBlockTime = payload.Timestamp
}
}
}
Expand Down