Skip to content

Commit

Permalink
fix(manager): re-use submitted DA batches on SL failure (#708)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtsitrin authored Apr 19, 2024
1 parent c9d6171 commit d71f4e2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 13 deletions.
10 changes: 8 additions & 2 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,17 @@ type Manager struct {
// Block production
shouldProduceBlocksCh chan bool
produceEmptyBlockCh chan bool
lastSubmissionTime atomic.Int64
batchInProcess sync.Mutex
produceBlockMutex sync.Mutex
applyCachedBlockMutex sync.Mutex

// batch submission
batchInProcess sync.Mutex
lastSubmissionTime atomic.Int64
// pendingBatch is the result of the last DA submission
// that is pending settlement layer submission.
// It is used to avoid double submission of the same batch.
pendingBatch *PendingBatch

// Logging
logger types.Logger

Expand Down
59 changes: 48 additions & 11 deletions block/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,62 @@ func (m *Manager) handleSubmissionTrigger(ctx context.Context) {
m.logger.Error("produce empty block", "error", err)
}

syncHeight, err := m.submitNextBatch()
if m.pendingBatch != nil {
m.logger.Info("pending batch exists", "startHeight", m.pendingBatch.batch.StartHeight, "endHeight", m.pendingBatch.batch.EndHeight)
} else {
nextBatch, err := m.createNextBatch()
if err != nil {
m.logger.Error("get next batch", "error", err)
return
}

resultSubmitToDA, err := m.submitNextBatchToDA(nextBatch)
if err != nil {
m.logger.Error("submit next batch", "error", err)
return
}

m.pendingBatch = &PendingBatch{
daResult: resultSubmitToDA,
batch: nextBatch,
}
}

syncHeight, err := m.submitPendingBatchToSL()
if err != nil {
m.logger.Error("submit next batch", "error", err)
m.logger.Error("submit next batch to SL", "error", err)
return
}

// Update the syncTarget to the height of the last block in the last batch as seen by this node.
m.updateSyncParams(syncHeight)
}

func (m *Manager) submitNextBatch() (uint64, error) {
// Get the batch start and end height
func (m *Manager) createNextBatch() (*types.Batch, error) {
// Create the batch
startHeight := m.syncTarget.Load() + 1
endHeight := m.store.Height()

// Create the batch
nextBatch, err := m.createNextDABatch(startHeight, endHeight)
if err != nil {
m.logger.Error("create next batch", "startHeight", startHeight, "endHeight", endHeight, "error", err)
return 0, err
return nil, err
}

if err := m.validateBatch(nextBatch); err != nil {
return 0, err
return nil, err
}

return nextBatch, nil
}

func (m *Manager) submitNextBatchToDA(nextBatch *types.Batch) (*da.ResultSubmitBatch, error) {
startHeight := nextBatch.StartHeight
actualEndHeight := nextBatch.EndHeight

isLastBlockEmpty, err := m.isBlockEmpty(actualEndHeight)
if err != nil {
m.logger.Error("validate last block in batch is empty", "startHeight", startHeight, "endHeight", actualEndHeight, "error", err)
return 0, err
return nil, err
}
// Verify the last block in the batch is an empty block and that no ibc messages has accidentially passed through.
// This block may not be empty if another block has passed it in line. If that's the case our empty block request will
Expand All @@ -94,16 +119,28 @@ func (m *Manager) submitNextBatch() (uint64, error) {
resultSubmitToDA := m.dalc.SubmitBatch(nextBatch)
if resultSubmitToDA.Code != da.StatusSuccess {
err = fmt.Errorf("submit next batch to DA Layer: %s", resultSubmitToDA.Message)
return 0, err
return nil, err
}
return &resultSubmitToDA, nil
}

func (m *Manager) submitPendingBatchToSL() (uint64, error) {
if m.pendingBatch == nil {
return 0, fmt.Errorf("no pending batch to submit")
}

// Submit batch to SL
err = m.settlementClient.SubmitBatch(nextBatch, m.dalc.GetClientType(), &resultSubmitToDA)
startHeight := m.pendingBatch.batch.StartHeight
actualEndHeight := m.pendingBatch.batch.EndHeight
err := m.settlementClient.SubmitBatch(m.pendingBatch.batch, m.dalc.GetClientType(), m.pendingBatch.daResult)
if err != nil {
m.logger.Error("submit batch to SL", "startHeight", startHeight, "endHeight", actualEndHeight, "error", err)
return 0, err
}

// Clear pending batch
m.pendingBatch = nil

return actualEndHeight, nil
}

Expand Down
10 changes: 10 additions & 0 deletions block/types.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package block

import (
"github.com/dymensionxyz/dymint/da"
"github.com/dymensionxyz/dymint/types"
)

// TODO: move to types package
type blockSource string

Expand All @@ -13,3 +18,8 @@ type blockMetaData struct {
source blockSource
daHeight uint64
}

type PendingBatch struct {
daResult *da.ResultSubmitBatch
batch *types.Batch
}

0 comments on commit d71f4e2

Please sign in to comment.