Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/stupid-pears-cough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/l2geth': patch
---

Patch for L1 syncing nodes that got stuck after DTL batch sync errors
12 changes: 11 additions & 1 deletion l2geth/rollup/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type RollupClient interface {
GetEnqueue(index uint64) (*types.Transaction, error)
GetLatestEnqueue() (*types.Transaction, error)
GetLatestEnqueueIndex() (*uint64, error)
GetRawTransaction(uint64, Backend) (*TransactionResponse, error)
GetTransaction(uint64, Backend) (*types.Transaction, error)
GetLatestTransaction(Backend) (*types.Transaction, error)
GetLatestTransactionIndex(Backend) (*uint64, error)
Expand Down Expand Up @@ -419,7 +420,7 @@ func batchedTransactionToTransaction(res *transaction, chainID *big.Int) (*types
}

// GetTransaction will get a transaction by Canonical Transaction Chain index
func (c *Client) GetTransaction(index uint64, backend Backend) (*types.Transaction, error) {
func (c *Client) GetRawTransaction(index uint64, backend Backend) (*TransactionResponse, error) {
str := strconv.FormatUint(index, 10)
response, err := c.client.R().
SetPathParams(map[string]string{
Expand All @@ -438,6 +439,15 @@ func (c *Client) GetTransaction(index uint64, backend Backend) (*types.Transacti
if !ok {
return nil, fmt.Errorf("could not get tx with index %d", index)
}
return res, nil
}

// GetTransaction will get a transaction by Canonical Transaction Chain index
func (c *Client) GetTransaction(index uint64, backend Backend) (*types.Transaction, error) {
res, err := c.GetRawTransaction(index, backend)
if err != nil {
return nil, err
}
return batchedTransactionToTransaction(res.Transaction, c.chainID)
}

Expand Down
17 changes: 17 additions & 0 deletions l2geth/rollup/sync_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,23 @@ func (s *SyncService) initializeLatestL1(ctcDeployHeight *big.Int) error {
s.SetLatestL1Timestamp(context.Timestamp)
s.SetLatestL1BlockNumber(context.BlockNumber)
} else {
// Recover from accidentally skipped batches if necessary.
if s.verifier && s.backend == BackendL1 {
tx, err := s.client.GetRawTransaction(*index, s.backend)
if err != nil {
return fmt.Errorf("Cannot fetch transaction from dtl at index %d: %w", *index, err)
}

oldbatchIndex := s.GetLatestBatchIndex()
newBatchIndex := tx.Transaction.BatchIndex
if tx.Transaction.BatchIndex > 0 {
newBatchIndex -= 1
}

log.Info("Updating batch index", "old", oldbatchIndex, "new", newBatchIndex)
s.SetLatestBatchIndex(&newBatchIndex)
}

log.Info("Found latest index", "index", *index)
block := s.bc.GetBlockByNumber(*index + 1)
if block == nil {
Expand Down
17 changes: 17 additions & 0 deletions l2geth/rollup/sync_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,8 @@ func newTestSyncService(isVerifier bool, alloc *common.Address) (*SyncService, c
type mockClient struct {
getEnqueueCallCount int
getEnqueue []*types.Transaction
getRawTransactionCallCount int
getRawTransaction []*TransactionResponse
getTransactionCallCount int
getTransaction []*types.Transaction
getEthContextCallCount int
Expand All @@ -974,6 +976,7 @@ func setupMockClient(service *SyncService, responses map[string]interface{}) {

func newMockClient(responses map[string]interface{}) *mockClient {
getEnqueueResponses := []*types.Transaction{}
getRawTransactionResponses := []*TransactionResponse{}
getTransactionResponses := []*types.Transaction{}
getEthContextResponses := []*EthContext{}
getLatestEthContextResponse := &EthContext{}
Expand All @@ -983,6 +986,10 @@ func newMockClient(responses map[string]interface{}) *mockClient {
if ok {
getEnqueueResponses = enqueue.([]*types.Transaction)
}
getRawTx, ok := responses["GetRawTransaction"]
if ok {
getRawTransactionResponses = getRawTx.([]*TransactionResponse)
}
getTx, ok := responses["GetTransaction"]
if ok {
getTransactionResponses = getTx.([]*types.Transaction)
Expand All @@ -1002,6 +1009,7 @@ func newMockClient(responses map[string]interface{}) *mockClient {

return &mockClient{
getEnqueue: getEnqueueResponses,
getRawTransaction: getRawTransactionResponses,
getTransaction: getTransactionResponses,
getEthContext: getEthContextResponses,
getLatestEthContext: getLatestEthContextResponse,
Expand All @@ -1025,6 +1033,15 @@ func (m *mockClient) GetLatestEnqueue() (*types.Transaction, error) {
return m.getEnqueue[len(m.getEnqueue)-1], nil
}

func (m *mockClient) GetRawTransaction(index uint64, backend Backend) (*TransactionResponse, error) {
if m.getRawTransactionCallCount < len(m.getRawTransaction) {
tx := m.getRawTransaction[m.getRawTransactionCallCount]
m.getRawTransactionCallCount++
return tx, nil
}
return nil, fmt.Errorf("Cannot get raw transaction: mocks (%d), call count (%d)", len(m.getRawTransaction), m.getRawTransactionCallCount)
}

func (m *mockClient) GetTransaction(index uint64, backend Backend) (*types.Transaction, error) {
if m.getTransactionCallCount < len(m.getTransaction) {
tx := m.getTransaction[m.getTransactionCallCount]
Expand Down