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

Add synchronization between preconf task and main sync task #87

Merged
merged 1 commit into from
Oct 30, 2023
Merged
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
30 changes: 30 additions & 0 deletions synchronizer/synchronizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ type ClientSynchronizer struct {
cancelCtx context.CancelFunc
genesis state.Genesis
cfg Config

// Channel for synchronizing reorgs with the asynchronous preconf task.
// The type of the messages sent on this channel is irrelevant. It is used for synchronization
// only, not exchange of data. We usually just send `nil` messages.
preconfReorg chan interface{}
}

// NewSynchronizer creates and initializes an instance of Synchronizer
Expand Down Expand Up @@ -128,11 +133,21 @@ func (s *ClientSynchronizer) Sync() error {
}

if s.usePreconfirmations() {
s.preconfReorg = make(chan interface{})
go func() {
for {
select {
case <-s.ctx.Done():
return
case <-s.preconfReorg:
// There's been a reorg and the main task wants to reset the state. Send it a
// signal to let it know that we are not actively syncing and are ready for the
// state to be reset.
s.preconfReorg <- nil
// Wait for a signal from the main task that the reset is done.
log.Debug("preconf task signaled for reorg, waiting until it is safe to proceed")
<-s.preconfReorg
log.Debug("resuming preconfirmations syncing after reorg")
case <-time.After(s.cfg.PreconfirmationsSyncInterval.Duration):
if err = s.syncPreconfirmations(); err != nil {
log.Warn("error syncing preconfirmations: ", err)
Expand Down Expand Up @@ -464,6 +479,21 @@ func (s *ClientSynchronizer) processBlockRange(blocks []etherman.Block, order ma
// This function allows reset the state until an specific ethereum block
func (s *ClientSynchronizer) resetState(blockNumber uint64) error {
log.Debug("Reverting synchronization to block: ", blockNumber)

if s.preconfReorg != nil {
// We're about to yank the state out from under the asynchronous preconfirmations task.
// Before we do that, we must
// 1. Signal the preconf task that we're about to reset the state.
s.preconfReorg <- nil
// 2. Wait for the preconf task to reach a stable point.
<-s.preconfReorg
// After we reset the task, we must signal the preconf task one more time to let it know
// that it can resume syncing.
defer func() {
s.preconfReorg <- nil
} ()
}

dbTx, err := s.state.BeginStateTransaction(s.ctx)
if err != nil {
log.Error("error starting a db transaction to reset the state. Error: ", err)
Expand Down