Skip to content

Commit

Permalink
polygon/bridge: Handle overrideStateSyncRecords (#11836)
Browse files Browse the repository at this point in the history
Fixes #11724
  • Loading branch information
shohamc1 authored Sep 3, 2024
1 parent ec99ed8 commit 2e7487b
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 13 deletions.
2 changes: 0 additions & 2 deletions eth/stagedsync/bor_heimdall_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,6 @@ func fetchAndWriteHeimdallStateSyncEvents(
if val, ok := config.OverrideStateSyncRecords[strconv.FormatUint(blockNum, 10)]; ok {
overrideCount = len(eventRecords) - val //nolint
eventRecords = eventRecords[0:val]
overrideCount = len(eventRecords) - val //nolint
eventRecords = eventRecords[0:val]
}
}

Expand Down
13 changes: 12 additions & 1 deletion polygon/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"sync"
"sync/atomic"
"time"
Expand Down Expand Up @@ -265,6 +266,16 @@ func (b *Bridge) ProcessNewBlocks(ctx context.Context, blocks []*types.Block) er
return err
}

if b.borConfig.OverrideStateSyncRecords != nil {
if eventLimit, ok := b.borConfig.OverrideStateSyncRecords[strconv.FormatUint(blockNum, 10)]; ok {
if eventLimit == 0 {
endID = 0
} else {
endID = startID + uint64(eventLimit) - 1
}
}
}

if endID > 0 {
b.logger.Debug(
bridgeLogPrefix("mapping events to block"),
Expand All @@ -273,10 +284,10 @@ func (b *Bridge) ProcessNewBlocks(ctx context.Context, blocks []*types.Block) er
"end", endID,
)

lastProcessedEventID = endID
eventTxnHash := bortypes.ComputeBorTxHash(blockNum, block.Hash())
eventTxnToBlockNum[eventTxnHash] = blockNum
blockNumToEventId[blockNum] = endID
lastProcessedEventID = endID
}

processedBlock = true
Expand Down
150 changes: 140 additions & 10 deletions polygon/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ import (
"github.com/erigontech/erigon/turbo/testlog"
)

func setup(t *testing.T) (*heimdall.MockHeimdallClient, *Bridge) {
var defaultBorConfig = borcfg.BorConfig{
Sprint: map[string]uint64{"0": 2},
StateReceiverContract: "0x0000000000000000000000000000000000001001",
IndoreBlock: big.NewInt(10),
StateSyncConfirmationDelay: map[string]uint64{"0": 1},
}

func setup(t *testing.T, borConfig borcfg.BorConfig) (*heimdall.MockHeimdallClient, *Bridge) {
ctrl := gomock.NewController(t)
logger := testlog.Logger(t, log.LvlDebug)
borConfig := borcfg.BorConfig{
Sprint: map[string]uint64{"0": 2},
StateReceiverContract: "0x0000000000000000000000000000000000001001",
IndoreBlock: big.NewInt(10),
StateSyncConfirmationDelay: map[string]uint64{"0": 1},
}

heimdallClient := heimdall.NewMockHeimdallClient(ctrl)
b := Assemble(t.TempDir(), logger, &borConfig, heimdallClient)
t.Cleanup(b.Close)
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestBridge(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

heimdallClient, b := setup(t)
heimdallClient, b := setup(t, defaultBorConfig)
event1 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 1,
Expand Down Expand Up @@ -193,7 +193,7 @@ func TestBridge_Unwind(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

heimdallClient, b := setup(t)
heimdallClient, b := setup(t, defaultBorConfig)
event1 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 1,
Expand Down Expand Up @@ -292,3 +292,133 @@ func TestBridge_Unwind(t *testing.T) {
cancel()
wg.Wait()
}

func setupOverrideTest(t *testing.T, ctx context.Context, borConfig borcfg.BorConfig, wg *sync.WaitGroup) *Bridge {
heimdallClient, b := setup(t, borConfig)
event1 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 1,
ChainID: "80002",
Data: hexutil.MustDecode("0x01"),
},
// pre-indore: block0Time=1,block2Time=100,block4Time=200 => event1 falls in block4 (toTime=preSprintBlockTime=100)
Time: time.Unix(50, 0),
}
event2 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 2,
ChainID: "80002",
Data: hexutil.MustDecode("0x02"),
},
// pre-indore: block0Time=1,block2Time=100,block4Time=200 => event2 should fall in block4 but skipped and put in block6 (toTime=preSprintBlockTime=100)
Time: time.Unix(99, 0), // block 2
}
event3 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 3,
ChainID: "80002",
Data: hexutil.MustDecode("0x03"),
},
// pre-indore: block4Time=200,block6Time=300 => event3 falls in block6 (toTime=preSprintBlockTime=200)
Time: time.Unix(199, 0),
}
event4 := &heimdall.EventRecordWithTime{
EventRecord: heimdall.EventRecord{
ID: 4,
ChainID: "80002",
Data: hexutil.MustDecode("0x04"),
},
// post-indore: block8Time=400,block10Time=500 => event4 falls in block10 (toTime=currentSprintBlockTime-delay=500-1=499)
Time: time.Unix(498, 0),
}

events := []*heimdall.EventRecordWithTime{event1, event2, event3, event4}

heimdallClient.EXPECT().FetchStateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(events, nil).Times(1)
heimdallClient.EXPECT().FetchStateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]*heimdall.EventRecordWithTime{}, nil).AnyTimes()
wg.Add(1)

go func(bridge Service) {
defer wg.Done()

err := bridge.Run(ctx)
if err != nil {
if !errors.Is(err, ctx.Err()) {
t.Error(err)
}

return
}
}(b)

err := b.store.Prepare(ctx)
require.NoError(t, err)

replayBlockNum, replayNeeded, err := b.InitialBlockReplayNeeded(ctx)
require.NoError(t, err)
require.True(t, replayNeeded)
require.Equal(t, uint64(0), replayBlockNum)

genesis := types.NewBlockWithHeader(&types.Header{Time: 1, Number: big.NewInt(0)})
err = b.ReplayInitialBlock(ctx, genesis)
require.NoError(t, err)

blocks := getBlocks(t, 10)
err = b.ProcessNewBlocks(ctx, blocks)
require.NoError(t, err)

err = b.Synchronize(ctx, 10)
require.NoError(t, err)

return b
}

func TestBridge_ProcessNewBlocksWithOverride(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

var wg sync.WaitGroup
borCfg := defaultBorConfig
borCfg.OverrideStateSyncRecords = map[string]int{"4": 1}
b := setupOverrideTest(t, ctx, borCfg, &wg)

res, err := b.Events(ctx, 4) // should only have event1 as event2 is skipped and is present in block 6
require.NoError(t, err)
require.Len(t, res, 1)

res, err = b.Events(ctx, 6)
require.NoError(t, err)
require.Len(t, res, 2)

res, err = b.Events(ctx, 10)
require.NoError(t, err)
require.Len(t, res, 1)

cancel()
wg.Wait()
}

func TestBridge_ProcessNewBlocksWithZeroOverride(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

var wg sync.WaitGroup
borCfg := defaultBorConfig
borCfg.OverrideStateSyncRecords = map[string]int{"4": 0}
b := setupOverrideTest(t, ctx, borCfg, &wg)

res, err := b.Events(ctx, 4) // both event1 and event2 are in block 6
require.NoError(t, err)
require.Len(t, res, 0)

res, err = b.Events(ctx, 6)
require.NoError(t, err)
require.Len(t, res, 3)

res, err = b.Events(ctx, 10)
require.NoError(t, err)
require.Len(t, res, 1)

cancel()
wg.Wait()
}

0 comments on commit 2e7487b

Please sign in to comment.