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
39 changes: 39 additions & 0 deletions internal/constants/blockchains.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,45 @@ func BlockchainTypeToPB(bt wconstants.BlockchainType) commonv1.Blockchain {
}
}

// rollbackSafeDepth is the number of blocks to roll back when no recent incident is found.
// Used as a fallback when the last rollback incident is older than rollbackIncidentMaxAge.
const rollbackIncidentMaxAge = 2 * time.Hour

var rollbackSafeDepth = map[wconstants.BlockchainType]int64{
// Tron
wconstants.BlockchainTypeTron: 20,

// EVM
wconstants.BlockchainTypeEthereum: 12,
wconstants.BlockchainTypeBinanceSmartChain: 20,
wconstants.BlockchainTypePolygon: 128,
wconstants.BlockchainTypeArbitrum: 20,
wconstants.BlockchainTypeOptimism: 20,
wconstants.BlockchainTypeLinea: 20,

// BTC Like
wconstants.BlockchainTypeBitcoin: 6,
wconstants.BlockchainTypeLitecoin: 6,
wconstants.BlockchainTypeBitcoinCash: 6,
wconstants.BlockchainTypeDogecoin: 6,
}

// RollbackFallbackBlock returns the safe block to revert to when no recent incident is found.
func RollbackFallbackBlock(blockchain wconstants.BlockchainType, currentBlock int64) int64 {
depth, ok := rollbackSafeDepth[blockchain]
if !ok {
depth = 20
}
safe := currentBlock - depth
if safe < 0 {
return 0
}
return safe
}

// RollbackIncidentMaxAge is the maximum age of a rollback incident to be considered relevant.
func RollbackIncidentMaxAge() time.Duration { return rollbackIncidentMaxAge }

var minConfirmations = map[wconstants.BlockchainType]uint64{
// Tron
wconstants.BlockchainTypeTron: 19,
Expand Down
33 changes: 20 additions & 13 deletions internal/eproxy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strings"
"time"

"github.com/dv-net/dv-processing/internal/interceptors"

Expand Down Expand Up @@ -256,23 +257,29 @@ func (s *Service) GetIncidents(ctx context.Context, blockchain wconstants.Blockc
return incidents.Msg.GetItems(), nil
}

// GetRollbackStartingBlock returns the block height to start parsing from after a rollback incident
func (s *Service) GetRollbackStartingBlock(ctx context.Context, blockchain wconstants.BlockchainType) (uint64, error) {
incidents, err := s.GetIncidents(ctx, blockchain, 1)
if err != nil {
return 0, fmt.Errorf("get last incident for rollback recovery: %w", err)
}
// GetRollbackStartingBlock returns the block height to start parsing from after a rollback.
// It looks for a recent rollback incident (within rollbackIncidentMaxAge). If none is found,
// it falls back to currentBlock - safeDepth, where safeDepth is blockchain-specific.
func (s *Service) GetRollbackStartingBlock(ctx context.Context, blockchain wconstants.BlockchainType, currentBlock int64) (uint64, error) {
incidents, _ := s.GetIncidents(ctx, blockchain, 10)

if len(incidents) < 1 {
return 0, fmt.Errorf("no incidents found for blockchain %s", blockchain.String())
}
maxAge := constants.RollbackIncidentMaxAge()

for _, incident := range incidents {
if incident.GetType() != incidentsv2.IncidentType_INCIDENT_TYPE_ROLLBACK {
continue
}

if incident.GetCreatedAt() != nil && time.Since(incident.GetCreatedAt().AsTime()) > maxAge {
break // incidents are ordered newest-first; all further are older
}

incident := incidents[0]
if incident.GetType() != incidentsv2.IncidentType_INCIDENT_TYPE_ROLLBACK {
return 0, fmt.Errorf("last incident is not a rollback incident for blockchain %s", blockchain.String())
return incident.GetDataRollback().GetRevertToBlockHeight(), nil
}

return incident.GetDataRollback().GetRevertToBlockHeight(), nil
// No recent incident or API unavailable — fall back to safe depth per blockchain.
safeBlock := constants.RollbackFallbackBlock(blockchain, currentBlock)
return uint64(safeBlock), nil //nolint:gosec
}

type FindTransactionsParams struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/escanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ func (s *scanner) checksForEvent(event *transactionsv2.Event) []eventCheck {
func (s *scanner) handleRollback(ctx context.Context) error {
s.logger.Infof("Handling rollback incident for blockchain %s", s.blockchain.String())

newStartingBlock, err := s.bs.EProxy().GetRollbackStartingBlock(ctx, s.blockchain)
newStartingBlock, err := s.bs.EProxy().GetRollbackStartingBlock(ctx, s.blockchain, s.lastParsedBlockHeight.Load())
if err != nil {
return fmt.Errorf("get rollback starting block: %w", err)
}
Expand Down
Loading