Skip to content

Commit

Permalink
Get last l2 block in a batch by batch number (#3335)
Browse files Browse the repository at this point in the history
* last l2 block by batch number

* optimization

* change returned err in query
  • Loading branch information
ToniRamirezM authored Feb 21, 2024
1 parent fabe7ee commit f0093b0
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 59 deletions.
3 changes: 1 addition & 2 deletions sequencesender/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
type etherman interface {
BuildSequenceBatchesTxData(sender common.Address, sequences []ethmanTypes.Sequence, maxSequenceTimestamp uint64, initSequenceBatchNumber uint64, l2Coinbase common.Address) (to *common.Address, data []byte, err error)
EstimateGasSequenceBatches(sender common.Address, sequences []ethmanTypes.Sequence, maxSequenceTimestamp uint64, initSequenceBatchNumber uint64, l2Coinbase common.Address) (*types.Transaction, error)
// GetLastBatchTimestamp() (uint64, error)
GetLatestBlockHeader(ctx context.Context) (*types.Header, error)
GetLatestBatchNumber() (uint64, error)
}
Expand All @@ -34,7 +33,7 @@ type stateInterface interface {
GetTimeForLatestBatchVirtualization(ctx context.Context, dbTx pgx.Tx) (time.Time, error)
GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error)
GetLastClosedBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error)
GetL2BlocksByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]state.L2Block, error)
GetLastL2BlockByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.L2Block, error)
GetBlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*state.Block, error)
}

Expand Down
60 changes: 30 additions & 30 deletions sequencesender/mock_state.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 10 additions & 27 deletions sequencesender/sequencesender.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,25 +139,10 @@ func (s *SequenceSender) tryToSendSequence(ctx context.Context) {
metrics.SequencesSentToL1(float64(sequenceCount))

// Check if we need to wait until last L1 block timestamp is L1BlockTimestampMargin seconds above the timestamp of the last L2 block in the sequence
// Get last batch in the sequence
lastSequenceBatchNum := sequences[sequenceCount-1].BatchNumber

// Get L2 blocks for the last batch
lastBatchL2Blocks, err := s.state.GetL2BlocksByBatchNumber(ctx, lastSequenceBatchNum, nil)
if err != nil {
log.Errorf("failed to get L2 blocks for batch %d, err: %v", lastSequenceBatchNum, err)
return
}

// Check there are L2 blocks for the last batch
if len(lastBatchL2Blocks) == 0 {
log.Errorf("no L2 blocks returned from the state for batch %d", lastSequenceBatchNum)
return
}

// Get last sequence
lastSequence := sequences[sequenceCount-1]
// Get timestamp of the last L2 block in the sequence
lastL2Block := lastBatchL2Blocks[len(lastBatchL2Blocks)-1]
lastL2BlockTimestamp := uint64(lastL2Block.ReceivedAt.Unix())
lastL2BlockTimestamp := uint64(lastSequence.LastL2BLockTimestamp)

timeMargin := int64(s.cfg.L1BlockTimestampMargin.Seconds())

Expand All @@ -174,11 +159,11 @@ func (s *SequenceSender) tryToSendSequence(ctx context.Context) {

if !elapsed {
log.Infof("waiting at least %d seconds to send sequences, time difference between last L1 block %d (ts: %d) and last L2 block %d (ts: %d) in the sequence is lower than %d seconds",
waitTime, lastL1BlockHeader.Number, lastL1BlockHeader.Time, lastL2Block.Number(), lastL2BlockTimestamp, timeMargin)
waitTime, lastL1BlockHeader.Number, lastL1BlockHeader.Time, lastSequence.BatchNumber, lastL2BlockTimestamp, timeMargin)
time.Sleep(time.Duration(waitTime) * time.Second)
} else {
log.Infof("continuing, time difference between last L1 block %d (ts: %d) and last L2 block %d (ts: %d) in the sequence is greater than %d seconds",
lastL1BlockHeader.Number, lastL1BlockHeader.Time, lastL2Block.Number(), lastL2BlockTimestamp, timeMargin)
lastL1BlockHeader.Number, lastL1BlockHeader.Time, lastSequence.BatchNumber, lastL2BlockTimestamp, timeMargin)
break
}
}
Expand All @@ -192,18 +177,17 @@ func (s *SequenceSender) tryToSendSequence(ctx context.Context) {
// Wait if the time difference is less than timeMargin (L1BlockTimestampMargin)
if !elapsed {
log.Infof("waiting at least %d seconds to send sequences, time difference between now (ts: %d) and last L2 block %d (ts: %d) in the sequence is lower than %d seconds",
waitTime, currentTime, lastL2Block.Number(), lastL2BlockTimestamp, timeMargin)
waitTime, currentTime, lastSequence.BatchNumber, lastL2BlockTimestamp, timeMargin)
time.Sleep(time.Duration(waitTime) * time.Second)
} else {
log.Infof("sending sequences now, time difference between now (ts: %d) and last L2 block %d (ts: %d) in the sequence is also greater than %d seconds",
currentTime, lastL2Block.Number(), lastL2BlockTimestamp, timeMargin)
currentTime, lastSequence.BatchNumber, lastL2BlockTimestamp, timeMargin)
break
}
}

// add sequence to be monitored
firstSequence := sequences[0]
lastSequence := sequences[len(sequences)-1]

to, data, err := s.etherman.BuildSequenceBatchesTxData(s.cfg.SenderAddress, sequences, uint64(lastSequence.LastL2BLockTimestamp), firstSequence.BatchNumber-1, s.cfg.L2Coinbase)
if err != nil {
Expand Down Expand Up @@ -292,16 +276,15 @@ func (s *SequenceSender) getSequencesToSend(ctx context.Context) ([]types.Sequen
seq.LastL2BLockTimestamp = seq.ForcedBatchTimestamp
} else {
// Set sequence timestamps as the latest l2 block timestamp
l2Blocks, err := s.state.GetL2BlocksByBatchNumber(ctx, currentBatchNumToSequence, nil)
lastL2Block, err := s.state.GetLastL2BlockByBatchNumber(ctx, currentBatchNumToSequence, nil)
if err != nil {
return nil, err
}
if len(l2Blocks) == 0 {
return nil, fmt.Errorf("no L2 blocks returned from the state for batch %d", currentBatchNumToSequence)
if lastL2Block == nil {
return nil, fmt.Errorf("no last L2 block returned from the state for batch %d", currentBatchNumToSequence)
}

// Get timestamp of the last L2 block in the sequence
lastL2Block := l2Blocks[len(l2Blocks)-1]
seq.LastL2BLockTimestamp = lastL2Block.ReceivedAt.Unix()
}

Expand Down
1 change: 1 addition & 0 deletions state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,5 @@ type storage interface {
IsBatchChecked(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (bool, error)
UpdateBatchAsChecked(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error
GetNotCheckedBatches(ctx context.Context, dbTx pgx.Tx) ([]*Batch, error)
GetLastL2BlockByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*L2Block, error)
}
60 changes: 60 additions & 0 deletions state/mocks/mock_storage.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions state/pgstatestorage/l2block.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ func (p *PostgresStorage) GetL2BlocksByBatchNumber(ctx context.Context, batchNum
return l2Blocks, nil
}

// GetLastL2BlockByBatchNumber gets the last l2 block in a batch by batch number
func (p *PostgresStorage) GetLastL2BlockByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.L2Block, error) {
const query = "SELECT block_hash, header, uncles, received_at FROM state.l2block b WHERE batch_num = $1 ORDER BY b.block_num DESC LIMIT 1"

q := p.getExecQuerier(dbTx)
row := q.QueryRow(ctx, query, batchNumber)
header, uncles, receivedAt, err := p.scanL2BlockInfo(ctx, row, dbTx)
if err != nil {
return nil, err
}

transactions, err := p.GetTxsByBlockNumber(ctx, header.Number.Uint64(), dbTx)
if errors.Is(err, pgx.ErrNoRows) {
transactions = []*types.Transaction{}
} else if err != nil {
return nil, err
}

block := buildBlock(header, transactions, uncles, receivedAt)
return block, nil
}

func (p *PostgresStorage) scanL2BlockInfo(ctx context.Context, rows pgx.Row, dbTx pgx.Tx) (header *state.L2Header, uncles []*state.L2Header, receivedAt time.Time, err error) {
header = &state.L2Header{}
uncles = []*state.L2Header{}
Expand Down

0 comments on commit f0093b0

Please sign in to comment.