Skip to content

all: add debug_syncTarget as an API method #32159

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,14 @@ func makeFullNode(ctx *cli.Context) *node.Node {
if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
}

// Configure full-sync tester service if requested
if ctx.IsSet(utils.SyncTargetFlag.Name) {
hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name))
if len(hex) != common.HashLength {
utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength)
}
utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex), ctx.Bool(utils.ExitWhenSyncedFlag.Name))
eth.SyncOverride().SyncTarget(common.BytesToHash(hex), ctx.Bool(utils.ExitWhenSyncedFlag.Name))
}

if ctx.IsSet(utils.DeveloperFlag.Name) {
Expand Down
7 changes: 0 additions & 7 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"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/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice"
Expand Down Expand Up @@ -1997,12 +1996,6 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
return filterSystem
}

// RegisterFullSyncTester adds the full-sync tester service into node.
func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash, exitWhenSynced bool) {
catalyst.RegisterFullSyncTester(stack, eth, target, exitWhenSynced)
log.Info("Registered full-sync tester", "hash", target, "exitWhenSynced", exitWhenSynced)
}

// SetupMetrics configures the metrics system.
func SetupMetrics(cfg *metrics.Config) {
if !cfg.Enabled {
Expand Down
5 changes: 5 additions & 0 deletions eth/api_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,8 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
}
return api.eth.blockchain.GetTrieFlushInterval().String(), nil
}

// SetSyncTarget initiates a full-sync to the target block hash
func (api *DebugAPI) SyncTarget(target common.Hash) {
api.eth.SyncOverride().SyncTarget(target, false)
}
15 changes: 15 additions & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ type Ethereum struct {
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)

shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully

syncOverride SyncOverride // allows the sync target to be overridden
}

// New creates a new Ethereum object (including the initialisation of the common Ethereum object),
Expand Down Expand Up @@ -202,6 +204,11 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
discmix: enode.NewFairMix(discmixTimeout),
shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb),
}
eth.syncOverride = SyncOverride{
stack: stack,
backend: eth,
closed: make(chan struct{}),
}
bcVersion := rawdb.ReadDatabaseVersion(chainDb)
var dbVer = "<nil>"
if bcVersion != nil {
Expand Down Expand Up @@ -576,6 +583,8 @@ func (s *Ethereum) Stop() error {
s.chainDb.Close()
s.eventMux.Stop()

s.syncOverride.Stop()

return nil
}

Expand Down Expand Up @@ -604,3 +613,9 @@ func (s *Ethereum) SyncMode() ethconfig.SyncMode {
// Nope, we're really full syncing
return ethconfig.FullSync
}

// SyncOverride returns a SyncOverride instance which is used to force the node
// to sync to a target block hash.
func (s *Ethereum) SyncOverride() *SyncOverride {
return &s.syncOverride
}
57 changes: 16 additions & 41 deletions eth/catalyst/tester.go → eth/sync_override.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,35 @@
// 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 catalyst
package eth

import (
"sync"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
)

// FullSyncTester is an auxiliary service that allows Geth to perform full sync
// SyncOverride is an auxiliary service that allows Geth to perform full sync
// alone without consensus-layer attached. Users must specify a valid block hash
// as the sync target.
//
// This tester can be applied to different networks, no matter it's pre-merge or
// post-merge, but only for full-sync.
type FullSyncTester struct {
stack *node.Node
backend *eth.Ethereum
target common.Hash
closed chan struct{}
wg sync.WaitGroup
exitWhenSynced bool
type SyncOverride struct {
stack *node.Node
backend *Ethereum
closed chan struct{}
}

// RegisterFullSyncTester registers the full-sync tester service into the node
// stack for launching and stopping the service controlled by node.
func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash, exitWhenSynced bool) (*FullSyncTester, error) {
cl := &FullSyncTester{
stack: stack,
backend: backend,
target: target,
closed: make(chan struct{}),
exitWhenSynced: exitWhenSynced,
}
stack.RegisterLifecycle(cl)
return cl, nil
}

// Start launches the beacon sync with provided sync target.
func (tester *FullSyncTester) Start() error {
tester.wg.Add(1)
// SyncTarget sets the target of the client sync to the given block hash
func (f *SyncOverride) SyncTarget(target common.Hash, exitWhenSynced bool) {
go func() {
defer tester.wg.Done()

// Trigger beacon sync with the provided block hash as trusted
// chain head.
err := tester.backend.Downloader().BeaconDevSync(ethconfig.FullSync, tester.target, tester.closed)
err := f.backend.Downloader().BeaconDevSync(ethconfig.FullSync, target, f.closed)
if err != nil {
log.Info("Failed to trigger beacon sync", "err", err)
}
Expand All @@ -76,28 +54,25 @@ func (tester *FullSyncTester) Start() error {
select {
case <-ticker.C:
// Stop in case the target block is already stored locally.
if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil {
if block := f.backend.BlockChain().GetBlockByHash(target); block != nil {
log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash())

if tester.exitWhenSynced {
go tester.stack.Close() // async since we need to close ourselves
log.Info("Terminating the node")
if exitWhenSynced {
log.Info("Terminating node")
f.stack.Close()
}
return
}

case <-tester.closed:
case <-f.closed:
return
}
}
}()
return nil
}

// Stop stops the full-sync tester to stop all background activities.
// This function can only be called for one time.
func (tester *FullSyncTester) Stop() error {
close(tester.closed)
tester.wg.Wait()
func (f *SyncOverride) Stop() error {
close(f.closed)
return nil
}
5 changes: 5 additions & 0 deletions internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,11 @@ web3._extend({
call: 'debug_getTrieFlushInterval',
params: 0
}),
new web3._extend.Method({
name: 'syncTarget',
call: 'debug_syncTarget',
params: 1
}),
],
properties: []
});
Expand Down
Loading