borheimdall: add tests for state sync events persistence (#8989)

- adds a test for persisting state sync events at the beginning of every
sprint
This commit is contained in:
milen 2023-12-15 15:07:39 +02:00 committed by GitHub
parent 9ccd8a1f91
commit d23f306fc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 18 deletions

View File

@ -281,7 +281,7 @@ func BorHeimdallForward(
}
}
if blockNum%cfg.chainConfig.Bor.CalculateSprint(blockNum) == 0 {
if blockNum > 0 && blockNum%cfg.chainConfig.Bor.CalculateSprint(blockNum) == 0 {
var callTime time.Duration
var records int
if lastEventId, records, callTime, err = fetchAndWriteBorEvents(ctx, cfg.blockReader, cfg.chainConfig.Bor, header, lastEventId, cfg.chainConfig.ChainID.String(), tx, cfg.heimdallClient, cfg.stateReceiverABI, s.LogPrefix(), logger); err != nil {

View File

@ -42,3 +42,36 @@ func TestBorHeimdallForwardPersistsSpans(t *testing.T) {
require.Equal(t, uint64(6656), spans[2].StartBlock)
require.Equal(t, uint64(13055), spans[2].EndBlock)
}
func TestBorHeimdallForwardPersistsStateSyncEvents(t *testing.T) {
t.Parallel()
ctx := context.Background()
logger := testlog.Logger(t, log.LvlInfo)
numBlocks := 96
testHarness := test.InitHarness(ctx, t, logger, test.HarnessCfg{
ChainConfig: test.BorDevnetChainConfigWithNoBlockSealDelays(),
GenerateChainNumBlocks: numBlocks,
})
// pretend-update previous stage progress
testHarness.SaveStageProgress(ctx, t, stages.Headers, uint64(numBlocks))
// run stage under test
testHarness.RunStageForward(t, stages.BorHeimdall)
// asserts
// 1 event per sprint expected
events, err := testHarness.ReadStateSyncEventsFromDb(ctx)
require.NoError(t, err)
require.Len(t, events, 6)
firstEventNumPerBlock, err := testHarness.ReadFirstStateSyncEventNumPerBlockFromDb(ctx)
require.NoError(t, err)
require.Len(t, firstEventNumPerBlock, 6)
require.Equal(t, uint64(1), firstEventNumPerBlock[16])
require.Equal(t, uint64(2), firstEventNumPerBlock[32])
require.Equal(t, uint64(3), firstEventNumPerBlock[48])
require.Equal(t, uint64(4), firstEventNumPerBlock[64])
require.Equal(t, uint64(5), firstEventNumPerBlock[80])
require.Equal(t, uint64(6), firstEventNumPerBlock[96])
}

View File

@ -8,6 +8,7 @@ import (
"fmt"
"math/big"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/holiman/uint256"
@ -122,21 +123,23 @@ type HarnessCfg struct {
}
type Harness struct {
logger log.Logger
chainDataDb kv.RwDB
borConsensusDb kv.RwDB
chainConfig *chain.Config
blockReader *freezeblocks.BlockReader
stateSyncStages []*stagedsync.Stage
stateSync *stagedsync.Sync
bhCfg stagedsync.BorHeimdallCfg
heimdallClient *heimdallmock.MockIHeimdallClient
heimdallNextMockSpan *span.HeimdallSpan
sealedHeaders map[uint64]*types.Header
borSpanner *bormock.MockSpanner
validatorAddress libcommon.Address
validatorKey *ecdsa.PrivateKey
genesisInitData *genesisInitData
logger log.Logger
chainDataDb kv.RwDB
borConsensusDb kv.RwDB
chainConfig *chain.Config
blockReader *freezeblocks.BlockReader
stateSyncStages []*stagedsync.Stage
stateSync *stagedsync.Sync
bhCfg stagedsync.BorHeimdallCfg
heimdallClient *heimdallmock.MockIHeimdallClient
heimdallNextMockSpan *span.HeimdallSpan
heimdallLastEventId uint64
heimdallLastEventHeaderNum uint64
sealedHeaders map[uint64]*types.Header
borSpanner *bormock.MockSpanner
validatorAddress libcommon.Address
validatorKey *ecdsa.PrivateKey
genesisInitData *genesisInitData
}
func (h *Harness) SaveStageProgress(ctx context.Context, t *testing.T, stageId stages.SyncStage, progress uint64) {
@ -199,6 +202,59 @@ func (h *Harness) ReadSpansFromDb(ctx context.Context) (spans []*span.HeimdallSp
return spans, nil
}
func (h *Harness) ReadStateSyncEventsFromDb(ctx context.Context) (eventIds []uint64, err error) {
err = h.chainDataDb.View(ctx, func(tx kv.Tx) error {
eventsIter, err := tx.Range(kv.BorEvents, nil, nil)
if err != nil {
return err
}
for eventsIter.HasNext() {
keyBytes, _, err := eventsIter.Next()
if err != nil {
return err
}
eventIds = append(eventIds, binary.BigEndian.Uint64(keyBytes))
}
return nil
})
if err != nil {
return nil, err
}
return eventIds, nil
}
func (h *Harness) ReadFirstStateSyncEventNumPerBlockFromDb(ctx context.Context) (nums map[uint64]uint64, err error) {
nums = map[uint64]uint64{}
err = h.chainDataDb.View(ctx, func(tx kv.Tx) error {
eventNumsIter, err := tx.Range(kv.BorEventNums, nil, nil)
if err != nil {
return err
}
for eventNumsIter.HasNext() {
blockNumBytes, firstEventNumBytes, err := eventNumsIter.Next()
if err != nil {
return err
}
blockNum := binary.BigEndian.Uint64(blockNumBytes)
firstEventNum := binary.BigEndian.Uint64(firstEventNumBytes)
nums[blockNum] = firstEventNum
}
return nil
})
if err != nil {
return nil, err
}
return nums, nil
}
func (h *Harness) createGenesisInitData(t *testing.T) *genesisInitData {
accountPrivateKey, err := crypto.GenerateKey()
require.NoError(t, err)
@ -442,8 +498,20 @@ func (h *Harness) mockHeimdallClient() {
h.heimdallClient.
EXPECT().
StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
return nil, nil
DoAndReturn(func(_ context.Context, _ uint64, _ int64) ([]*clerk.EventRecordWithTime, error) {
h.heimdallLastEventId++
h.heimdallLastEventHeaderNum += h.chainConfig.Bor.CalculateSprint(h.heimdallLastEventHeaderNum)
stateSyncDelay := h.chainConfig.Bor.CalculateStateSyncDelay(h.heimdallLastEventHeaderNum)
newEvent := clerk.EventRecordWithTime{
EventRecord: clerk.EventRecord{
ID: h.heimdallLastEventId,
ChainID: h.chainConfig.ChainID.String(),
},
Time: time.Unix(int64(h.sealedHeaders[h.heimdallLastEventHeaderNum].Time-stateSyncDelay-1), 0),
}
// 1 per sprint
return []*clerk.EventRecordWithTime{&newEvent}, nil
}).
AnyTimes()
}