mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
borheimdall: add test for span persistence (#8988)
1. Adds an eth/stagedsync/test package which provides a test Harness object 2. Adds the first automated test to the bor-heimdall stage regarding span persistence (more to come in subsequent PRs) 3. Fixes a bug in the bor-heimdall stage which was uncovered with the test - we do not fetch span 0 when we sync straight from blockNum=0 without snapshots 4. Reorganises all mocks to be placed under ./mock sub-package within their respective packages
This commit is contained in:
parent
ce57b8f54f
commit
1a6b83b82c
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/ledgerwatch/erigon/rlp"
|
"github.com/ledgerwatch/erigon/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract
|
//go:generate mockgen -destination=./mock/genesis_contract_mock.go -package=mock . GenesisContract
|
||||||
type GenesisContract interface {
|
type GenesisContract interface {
|
||||||
CommitState(event rlp.RawValue, syscall consensus.SystemCall) error
|
CommitState(event rlp.RawValue, syscall consensus.SystemCall) error
|
||||||
LastStateId(syscall consensus.SystemCall) (*big.Int, error)
|
LastStateId(syscall consensus.SystemCall) (*big.Int, error)
|
@ -14,7 +14,7 @@ func MilestoneRewindPending() bool {
|
|||||||
return generics.BorMilestoneRewind.Load() != nil && *generics.BorMilestoneRewind.Load() != 0
|
return generics.BorMilestoneRewind.Load() != nil && *generics.BorMilestoneRewind.Load() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
|
//go:generate mockgen -destination=./mock/heimdall_client_mock.go -package=mock . IHeimdallClient
|
||||||
type IHeimdallClient interface {
|
type IHeimdallClient interface {
|
||||||
StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error)
|
StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error)
|
||||||
Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error)
|
Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: IHeimdallClient)
|
// Source: github.com/ledgerwatch/erigon/consensus/bor/heimdall (interfaces: IHeimdallClient)
|
||||||
|
|
||||||
// Package mocks is a generated GoMock package.
|
// Package mock is a generated GoMock package.
|
||||||
package mocks
|
package mock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
@ -11,6 +11,7 @@ import (
|
|||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
clerk "github.com/ledgerwatch/erigon/consensus/bor/clerk"
|
clerk "github.com/ledgerwatch/erigon/consensus/bor/clerk"
|
||||||
checkpoint "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint"
|
checkpoint "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint"
|
||||||
|
milestone "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone"
|
||||||
span "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span"
|
span "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -79,6 +80,79 @@ func (mr *MockIHeimdallClientMockRecorder) FetchCheckpointCount(arg0 interface{}
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpointCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpointCount), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpointCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpointCount), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchLastNoAckMilestone mocks base method.
|
||||||
|
func (m *MockIHeimdallClient) FetchLastNoAckMilestone(arg0 context.Context) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FetchLastNoAckMilestone", arg0)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchLastNoAckMilestone indicates an expected call of FetchLastNoAckMilestone.
|
||||||
|
func (mr *MockIHeimdallClientMockRecorder) FetchLastNoAckMilestone(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLastNoAckMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLastNoAckMilestone), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestone mocks base method.
|
||||||
|
func (m *MockIHeimdallClient) FetchMilestone(arg0 context.Context) (*milestone.Milestone, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FetchMilestone", arg0)
|
||||||
|
ret0, _ := ret[0].(*milestone.Milestone)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestone indicates an expected call of FetchMilestone.
|
||||||
|
func (mr *MockIHeimdallClientMockRecorder) FetchMilestone(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestone), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneCount mocks base method.
|
||||||
|
func (m *MockIHeimdallClient) FetchMilestoneCount(arg0 context.Context) (int64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FetchMilestoneCount", arg0)
|
||||||
|
ret0, _ := ret[0].(int64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneCount indicates an expected call of FetchMilestoneCount.
|
||||||
|
func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneCount(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestoneCount), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneID mocks base method.
|
||||||
|
func (m *MockIHeimdallClient) FetchMilestoneID(arg0 context.Context, arg1 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FetchMilestoneID", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneID indicates an expected call of FetchMilestoneID.
|
||||||
|
func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneID(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneID", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestoneID), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchNoAckMilestone mocks base method.
|
||||||
|
func (m *MockIHeimdallClient) FetchNoAckMilestone(arg0 context.Context, arg1 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FetchNoAckMilestone", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchNoAckMilestone indicates an expected call of FetchNoAckMilestone.
|
||||||
|
func (mr *MockIHeimdallClientMockRecorder) FetchNoAckMilestone(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchNoAckMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchNoAckMilestone), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// Span mocks base method.
|
// Span mocks base method.
|
||||||
func (m *MockIHeimdallClient) Span(arg0 context.Context, arg1 uint64) (*span.HeimdallSpan, error) {
|
func (m *MockIHeimdallClient) Span(arg0 context.Context, arg1 uint64) (*span.HeimdallSpan, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
@ -1,8 +1,8 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: GenesisContract)
|
// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: GenesisContract)
|
||||||
|
|
||||||
// Package bor is a generated GoMock package.
|
// Package mock is a generated GoMock package.
|
||||||
package bor
|
package mock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
big "math/big"
|
big "math/big"
|
||||||
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
consensus "github.com/ledgerwatch/erigon/consensus"
|
consensus "github.com/ledgerwatch/erigon/consensus"
|
||||||
clerk "github.com/ledgerwatch/erigon/consensus/bor/clerk"
|
rlp "github.com/ledgerwatch/erigon/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockGenesisContract is a mock of GenesisContract interface.
|
// MockGenesisContract is a mock of GenesisContract interface.
|
||||||
@ -37,7 +37,7 @@ func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CommitState mocks base method.
|
// CommitState mocks base method.
|
||||||
func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 consensus.SystemCall) error {
|
func (m *MockGenesisContract) CommitState(arg0 rlp.RawValue, arg1 consensus.SystemCall) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CommitState", arg0, arg1)
|
ret := m.ctrl.Call(m, "CommitState", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
@ -1,8 +1,8 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: Spanner)
|
// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: Spanner)
|
||||||
|
|
||||||
// Package bor is a generated GoMock package.
|
// Package mock is a generated GoMock package.
|
||||||
package bor
|
package mock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@ -52,7 +52,7 @@ func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1 interface{}) *gomock.Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentProducers mocks base method.
|
// GetCurrentProducers mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentProducers(arg0 uint64, arg1 common.Address, arg2 func(uint64) (*span.HeimdallSpan, error)) ([]*valset.Validator, error) {
|
func (m *MockSpanner) GetCurrentProducers(arg0 uint64, arg1 common.Address, arg2 consensus.ChainHeaderReader) ([]*valset.Validator, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentProducers", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "GetCurrentProducers", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*valset.Validator)
|
ret0, _ := ret[0].([]*valset.Validator)
|
||||||
@ -82,7 +82,7 @@ func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0 interface{}) *gomock.Call
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidators mocks base method.
|
// GetCurrentValidators mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentValidators(arg0 uint64, arg1 common.Address, arg2 func(uint64) (*span.HeimdallSpan, error)) ([]*valset.Validator, error) {
|
func (m *MockSpanner) GetCurrentValidators(arg0 uint64, arg1 common.Address, arg2 consensus.ChainHeaderReader) ([]*valset.Validator, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*valset.Validator)
|
ret0, _ := ret[0].([]*valset.Validator)
|
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/ledgerwatch/erigon/consensus/bor/valset"
|
"github.com/ledgerwatch/erigon/consensus/bor/valset"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate mockgen -destination=./span_mock.go -package=bor . Spanner
|
//go:generate mockgen -destination=./mock/spanner_mock.go -package=mock . Spanner
|
||||||
type Spanner interface {
|
type Spanner interface {
|
||||||
GetCurrentSpan(syscall consensus.SystemCall) (*span.Span, error)
|
GetCurrentSpan(syscall consensus.SystemCall) (*span.Span, error)
|
||||||
GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error)
|
GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error)
|
@ -21,19 +21,20 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
"github.com/ledgerwatch/log/v3"
|
||||||
|
|
||||||
"github.com/ledgerwatch/erigon-lib/chain"
|
"github.com/ledgerwatch/erigon-lib/chain"
|
||||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||||
|
|
||||||
"github.com/ledgerwatch/erigon/core/state"
|
"github.com/ledgerwatch/erigon/core/state"
|
||||||
"github.com/ledgerwatch/erigon/core/types"
|
"github.com/ledgerwatch/erigon/core/types"
|
||||||
"github.com/ledgerwatch/erigon/rlp"
|
"github.com/ledgerwatch/erigon/rlp"
|
||||||
"github.com/ledgerwatch/erigon/rpc"
|
"github.com/ledgerwatch/erigon/rpc"
|
||||||
"github.com/ledgerwatch/log/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChainHeaderReader defines a small collection of methods needed to access the local
|
// ChainHeaderReader defines a small collection of methods needed to access the local
|
||||||
// blockchain during header verification.
|
// blockchain during header verification.
|
||||||
|
//
|
||||||
|
//go:generate mockgen -destination=./mock/chain_header_reader_mock.go -package=mock . ChainHeaderReader
|
||||||
type ChainHeaderReader interface {
|
type ChainHeaderReader interface {
|
||||||
// Config retrieves the blockchain's chain configuration.
|
// Config retrieves the blockchain's chain configuration.
|
||||||
Config() *chain.Config
|
Config() *chain.Config
|
||||||
|
150
consensus/mock/chain_header_reader_mock.go
Normal file
150
consensus/mock/chain_header_reader_mock.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/ledgerwatch/erigon/consensus (interfaces: ChainHeaderReader)
|
||||||
|
|
||||||
|
// Package mock is a generated GoMock package.
|
||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
big "math/big"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
chain "github.com/ledgerwatch/erigon-lib/chain"
|
||||||
|
common "github.com/ledgerwatch/erigon-lib/common"
|
||||||
|
types "github.com/ledgerwatch/erigon/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockChainHeaderReader is a mock of ChainHeaderReader interface.
|
||||||
|
type MockChainHeaderReader struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockChainHeaderReaderMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockChainHeaderReaderMockRecorder is the mock recorder for MockChainHeaderReader.
|
||||||
|
type MockChainHeaderReaderMockRecorder struct {
|
||||||
|
mock *MockChainHeaderReader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockChainHeaderReader creates a new mock instance.
|
||||||
|
func NewMockChainHeaderReader(ctrl *gomock.Controller) *MockChainHeaderReader {
|
||||||
|
mock := &MockChainHeaderReader{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockChainHeaderReaderMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockChainHeaderReader) EXPECT() *MockChainHeaderReaderMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// BorSpan mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) BorSpan(arg0 uint64) []byte {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "BorSpan", arg0)
|
||||||
|
ret0, _ := ret[0].([]byte)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BorSpan indicates an expected call of BorSpan.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) BorSpan(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BorSpan", reflect.TypeOf((*MockChainHeaderReader)(nil).BorSpan), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) Config() *chain.Config {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Config")
|
||||||
|
ret0, _ := ret[0].(*chain.Config)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config indicates an expected call of Config.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) Config() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Config", reflect.TypeOf((*MockChainHeaderReader)(nil).Config))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentHeader mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) CurrentHeader() *types.Header {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CurrentHeader")
|
||||||
|
ret0, _ := ret[0].(*types.Header)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentHeader indicates an expected call of CurrentHeader.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) CurrentHeader() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentHeader", reflect.TypeOf((*MockChainHeaderReader)(nil).CurrentHeader))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrozenBlocks mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) FrozenBlocks() uint64 {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FrozenBlocks")
|
||||||
|
ret0, _ := ret[0].(uint64)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrozenBlocks indicates an expected call of FrozenBlocks.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) FrozenBlocks() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FrozenBlocks", reflect.TypeOf((*MockChainHeaderReader)(nil).FrozenBlocks))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeader mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) GetHeader(arg0 common.Hash, arg1 uint64) *types.Header {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetHeader", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(*types.Header)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeader indicates an expected call of GetHeader.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) GetHeader(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHeader", reflect.TypeOf((*MockChainHeaderReader)(nil).GetHeader), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeaderByHash mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) GetHeaderByHash(arg0 common.Hash) *types.Header {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetHeaderByHash", arg0)
|
||||||
|
ret0, _ := ret[0].(*types.Header)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeaderByHash indicates an expected call of GetHeaderByHash.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) GetHeaderByHash(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHeaderByHash", reflect.TypeOf((*MockChainHeaderReader)(nil).GetHeaderByHash), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeaderByNumber mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) GetHeaderByNumber(arg0 uint64) *types.Header {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetHeaderByNumber", arg0)
|
||||||
|
ret0, _ := ret[0].(*types.Header)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeaderByNumber indicates an expected call of GetHeaderByNumber.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) GetHeaderByNumber(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHeaderByNumber", reflect.TypeOf((*MockChainHeaderReader)(nil).GetHeaderByNumber), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTd mocks base method.
|
||||||
|
func (m *MockChainHeaderReader) GetTd(arg0 common.Hash, arg1 uint64) *big.Int {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetTd", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(*big.Int)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTd indicates an expected call of GetTd.
|
||||||
|
func (mr *MockChainHeaderReaderMockRecorder) GetTd(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTd", reflect.TypeOf((*MockChainHeaderReader)(nil).GetTd), arg0, arg1)
|
||||||
|
}
|
@ -12,6 +12,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru/arc/v2"
|
lru "github.com/hashicorp/golang-lru/arc/v2"
|
||||||
|
"github.com/ledgerwatch/log/v3"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/ledgerwatch/erigon-lib/chain"
|
"github.com/ledgerwatch/erigon-lib/chain"
|
||||||
"github.com/ledgerwatch/erigon-lib/common"
|
"github.com/ledgerwatch/erigon-lib/common"
|
||||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||||
@ -32,8 +35,6 @@ import (
|
|||||||
"github.com/ledgerwatch/erigon/rlp"
|
"github.com/ledgerwatch/erigon/rlp"
|
||||||
"github.com/ledgerwatch/erigon/turbo/services"
|
"github.com/ledgerwatch/erigon/turbo/services"
|
||||||
"github.com/ledgerwatch/erigon/turbo/stages/headerdownload"
|
"github.com/ledgerwatch/erigon/turbo/stages/headerdownload"
|
||||||
"github.com/ledgerwatch/log/v3"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -201,13 +202,17 @@ func BorHeimdallForward(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var nextSpanId uint64
|
var lastSpanId uint64
|
||||||
if k != nil {
|
if k != nil {
|
||||||
nextSpanId = binary.BigEndian.Uint64(k) + 1
|
lastSpanId = binary.BigEndian.Uint64(k)
|
||||||
}
|
}
|
||||||
snapshotLastSpanId := cfg.blockReader.(LastFrozen).LastFrozenSpanID()
|
snapshotLastSpanId := cfg.blockReader.(LastFrozen).LastFrozenSpanID()
|
||||||
if snapshotLastSpanId+1 > nextSpanId {
|
if snapshotLastSpanId > lastSpanId {
|
||||||
nextSpanId = snapshotLastSpanId + 1
|
lastSpanId = snapshotLastSpanId
|
||||||
|
}
|
||||||
|
var nextSpanId uint64
|
||||||
|
if lastSpanId > 0 {
|
||||||
|
nextSpanId = lastSpanId + 1
|
||||||
}
|
}
|
||||||
var endSpanID uint64
|
var endSpanID uint64
|
||||||
if headNumber > zerothSpanEnd {
|
if headNumber > zerothSpanEnd {
|
||||||
@ -231,7 +236,6 @@ func BorHeimdallForward(
|
|||||||
var blockNum uint64
|
var blockNum uint64
|
||||||
var fetchTime time.Duration
|
var fetchTime time.Duration
|
||||||
var eventRecords int
|
var eventRecords int
|
||||||
var lastSpanId uint64
|
|
||||||
|
|
||||||
logTimer := time.NewTicker(logInterval)
|
logTimer := time.NewTicker(logInterval)
|
||||||
defer logTimer.Stop()
|
defer logTimer.Stop()
|
||||||
|
44
eth/stagedsync/stage_bor_heimdall_test.go
Normal file
44
eth/stagedsync/stage_bor_heimdall_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package stagedsync_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ledgerwatch/log/v3"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
||||||
|
"github.com/ledgerwatch/erigon/eth/stagedsync/test"
|
||||||
|
"github.com/ledgerwatch/erigon/turbo/testlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBorHeimdallForwardPersistsSpans(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
logger := testlog.Logger(t, log.LvlInfo)
|
||||||
|
numBlocks := 6640
|
||||||
|
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
|
||||||
|
spans, err := testHarness.ReadSpansFromDb(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, spans, 3)
|
||||||
|
require.Equal(t, uint64(0), spans[0].ID)
|
||||||
|
require.Equal(t, uint64(0), spans[0].StartBlock)
|
||||||
|
require.Equal(t, uint64(255), spans[0].EndBlock)
|
||||||
|
require.Equal(t, uint64(1), spans[1].ID)
|
||||||
|
require.Equal(t, uint64(256), spans[1].StartBlock)
|
||||||
|
require.Equal(t, uint64(6655), spans[1].EndBlock)
|
||||||
|
require.Equal(t, uint64(2), spans[2].ID)
|
||||||
|
require.Equal(t, uint64(6656), spans[2].StartBlock)
|
||||||
|
require.Equal(t, uint64(13055), spans[2].EndBlock)
|
||||||
|
}
|
20
eth/stagedsync/test/chain_configs.go
Normal file
20
eth/stagedsync/test/chain_configs.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ledgerwatch/erigon-lib/chain"
|
||||||
|
"github.com/ledgerwatch/erigon/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BorDevnetChainConfigWithNoBlockSealDelays() *chain.Config {
|
||||||
|
// take care not to mutate global var (shallow copy)
|
||||||
|
chainConfigCopy := *params.BorDevnetChainConfig
|
||||||
|
borConfigCopy := *chainConfigCopy.Bor
|
||||||
|
borConfigCopy.Period = map[string]uint64{
|
||||||
|
"0": 0,
|
||||||
|
}
|
||||||
|
borConfigCopy.ProducerDelay = map[string]uint64{
|
||||||
|
"0": 0,
|
||||||
|
}
|
||||||
|
chainConfigCopy.Bor = &borConfigCopy
|
||||||
|
return &chainConfigCopy
|
||||||
|
}
|
459
eth/stagedsync/test/harness.go
Normal file
459
eth/stagedsync/test/harness.go
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
|
"github.com/ledgerwatch/log/v3"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/ledgerwatch/erigon-lib/chain"
|
||||||
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||||
|
"github.com/ledgerwatch/erigon-lib/kv"
|
||||||
|
"github.com/ledgerwatch/erigon-lib/kv/memdb"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus/bor"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus/bor/clerk"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus/bor/contract"
|
||||||
|
heimdallmock "github.com/ledgerwatch/erigon/consensus/bor/heimdall/mock"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus/bor/heimdall/span"
|
||||||
|
bormock "github.com/ledgerwatch/erigon/consensus/bor/mock"
|
||||||
|
"github.com/ledgerwatch/erigon/consensus/bor/valset"
|
||||||
|
consensusmock "github.com/ledgerwatch/erigon/consensus/mock"
|
||||||
|
"github.com/ledgerwatch/erigon/core"
|
||||||
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
||||||
|
"github.com/ledgerwatch/erigon/core/types"
|
||||||
|
"github.com/ledgerwatch/erigon/crypto"
|
||||||
|
"github.com/ledgerwatch/erigon/eth/ethconfig"
|
||||||
|
"github.com/ledgerwatch/erigon/eth/stagedsync"
|
||||||
|
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
||||||
|
"github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitHarness(ctx context.Context, t *testing.T, logger log.Logger, cfg HarnessCfg) Harness {
|
||||||
|
chainDataDb := memdb.NewTestDB(t)
|
||||||
|
borConsensusDb := memdb.NewTestDB(t)
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
heimdallClient := heimdallmock.NewMockIHeimdallClient(ctrl)
|
||||||
|
snapshotsDir := t.TempDir()
|
||||||
|
blocksFreezingCfg := ethconfig.NewSnapCfg(true, true, true)
|
||||||
|
allRoSnapshots := freezeblocks.NewRoSnapshots(blocksFreezingCfg, snapshotsDir, logger)
|
||||||
|
allRoSnapshots.OptimisticalyReopenWithDB(chainDataDb)
|
||||||
|
allBorRoSnapshots := freezeblocks.NewBorRoSnapshots(blocksFreezingCfg, snapshotsDir, logger)
|
||||||
|
allBorRoSnapshots.OptimisticalyReopenWithDB(chainDataDb)
|
||||||
|
blockReader := freezeblocks.NewBlockReader(allRoSnapshots, allBorRoSnapshots)
|
||||||
|
bhCfg := stagedsync.StageBorHeimdallCfg(
|
||||||
|
chainDataDb,
|
||||||
|
borConsensusDb,
|
||||||
|
stagedsync.NewProposingState(ðconfig.Defaults.Miner),
|
||||||
|
*cfg.ChainConfig,
|
||||||
|
heimdallClient,
|
||||||
|
blockReader,
|
||||||
|
nil, // headerDownloader
|
||||||
|
nil, // penalize
|
||||||
|
nil, // not used
|
||||||
|
nil, // not used
|
||||||
|
)
|
||||||
|
stateSyncStages := stagedsync.DefaultStages(
|
||||||
|
ctx,
|
||||||
|
stagedsync.SnapshotsCfg{},
|
||||||
|
stagedsync.HeadersCfg{},
|
||||||
|
bhCfg,
|
||||||
|
stagedsync.BlockHashesCfg{},
|
||||||
|
stagedsync.BodiesCfg{},
|
||||||
|
stagedsync.SendersCfg{},
|
||||||
|
stagedsync.ExecuteBlockCfg{},
|
||||||
|
stagedsync.HashStateCfg{},
|
||||||
|
stagedsync.TrieCfg{},
|
||||||
|
stagedsync.HistoryCfg{},
|
||||||
|
stagedsync.LogIndexCfg{},
|
||||||
|
stagedsync.CallTracesCfg{},
|
||||||
|
stagedsync.TxLookupCfg{},
|
||||||
|
stagedsync.FinishCfg{},
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
stateSync := stagedsync.New(stateSyncStages, stagedsync.DefaultUnwindOrder, stagedsync.DefaultPruneOrder, logger)
|
||||||
|
validatorKey, err := crypto.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
validatorAddress := crypto.PubkeyToAddress(validatorKey.PublicKey)
|
||||||
|
h := Harness{
|
||||||
|
logger: logger,
|
||||||
|
chainDataDb: chainDataDb,
|
||||||
|
borConsensusDb: borConsensusDb,
|
||||||
|
chainConfig: cfg.ChainConfig,
|
||||||
|
blockReader: blockReader,
|
||||||
|
stateSyncStages: stateSyncStages,
|
||||||
|
stateSync: stateSync,
|
||||||
|
bhCfg: bhCfg,
|
||||||
|
heimdallClient: heimdallClient,
|
||||||
|
sealedHeaders: make(map[uint64]*types.Header),
|
||||||
|
borSpanner: bormock.NewMockSpanner(ctrl),
|
||||||
|
validatorAddress: validatorAddress,
|
||||||
|
validatorKey: validatorKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.ChainConfig.Bor != nil {
|
||||||
|
h.setHeimdallNextMockSpan(logger)
|
||||||
|
h.mockBorSpanner()
|
||||||
|
h.mockHeimdallClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
h.generateChain(ctx, t, ctrl, cfg)
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
type genesisInitData struct {
|
||||||
|
genesis *types.Genesis
|
||||||
|
genesisAllocPrivateKeys map[libcommon.Address]*ecdsa.PrivateKey
|
||||||
|
fundedAddresses []libcommon.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
type HarnessCfg struct {
|
||||||
|
ChainConfig *chain.Config
|
||||||
|
GenerateChainNumBlocks int
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) SaveStageProgress(ctx context.Context, t *testing.T, stageId stages.SyncStage, progress uint64) {
|
||||||
|
rwTx, err := h.chainDataDb.BeginRw(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer rwTx.Rollback()
|
||||||
|
|
||||||
|
err = stages.SaveStageProgress(rwTx, stageId, progress)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = rwTx.Commit()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) RunStageForward(t *testing.T, id stages.SyncStage) {
|
||||||
|
err := h.stateSync.SetCurrentStage(id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
stage, found := h.findStateSyncStageById(id)
|
||||||
|
require.True(t, found)
|
||||||
|
|
||||||
|
stageState, err := h.stateSync.StageState(id, nil, h.chainDataDb)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = stage.Forward(true, false, stageState, h.stateSync, nil, h.logger)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) ReadSpansFromDb(ctx context.Context) (spans []*span.HeimdallSpan, err error) {
|
||||||
|
err = h.chainDataDb.View(ctx, func(tx kv.Tx) error {
|
||||||
|
spanIter, err := tx.Range(kv.BorSpans, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for spanIter.HasNext() {
|
||||||
|
keyBytes, spanBytes, err := spanIter.Next()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
spanKey := binary.BigEndian.Uint64(keyBytes)
|
||||||
|
var heimdallSpan span.HeimdallSpan
|
||||||
|
if err = json.Unmarshal(spanBytes, &heimdallSpan); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if spanKey != heimdallSpan.ID {
|
||||||
|
return fmt.Errorf("span key and id mismatch %d!=%d", spanKey, heimdallSpan.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
spans = append(spans, &heimdallSpan)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return spans, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) createGenesisInitData(t *testing.T) *genesisInitData {
|
||||||
|
accountPrivateKey, err := crypto.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
accountAddress := crypto.PubkeyToAddress(accountPrivateKey.PublicKey)
|
||||||
|
|
||||||
|
h.genesisInitData = &genesisInitData{
|
||||||
|
genesis: &types.Genesis{
|
||||||
|
Config: h.chainConfig,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
accountAddress: {
|
||||||
|
Balance: new(big.Int).Exp(big.NewInt(1_000), big.NewInt(18), nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
genesisAllocPrivateKeys: map[libcommon.Address]*ecdsa.PrivateKey{
|
||||||
|
accountAddress: accountPrivateKey,
|
||||||
|
},
|
||||||
|
fundedAddresses: []libcommon.Address{
|
||||||
|
accountAddress,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.genesisInitData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) generateChain(ctx context.Context, t *testing.T, ctrl *gomock.Controller, cfg HarnessCfg) {
|
||||||
|
genInitData := h.createGenesisInitData(t)
|
||||||
|
consensusEngine := h.consensusEngine(t, cfg)
|
||||||
|
genesisTmpDbDir := t.TempDir()
|
||||||
|
_, parentBlock, err := core.CommitGenesisBlock(h.chainDataDb, genInitData.genesis, genesisTmpDbDir, h.logger)
|
||||||
|
require.NoError(t, err)
|
||||||
|
h.sealedHeaders[parentBlock.Number().Uint64()] = parentBlock.Header()
|
||||||
|
mockChainHR := h.mockChainHeaderReader(ctrl)
|
||||||
|
|
||||||
|
chainPack, err := core.GenerateChain(
|
||||||
|
h.chainConfig,
|
||||||
|
parentBlock,
|
||||||
|
consensusEngine,
|
||||||
|
h.chainDataDb,
|
||||||
|
cfg.GenerateChainNumBlocks,
|
||||||
|
func(i int, gen *core.BlockGen) {
|
||||||
|
// seal parent block first so that we can Prepare the current header
|
||||||
|
if gen.GetParent().Number().Uint64() > 0 {
|
||||||
|
h.seal(t, mockChainHR, consensusEngine, gen.GetParent())
|
||||||
|
}
|
||||||
|
|
||||||
|
h.logger.Info("Preparing mock header", "headerNum", gen.GetHeader().Number)
|
||||||
|
gen.GetHeader().ParentHash = h.sealedHeaders[gen.GetParent().Number().Uint64()].Hash()
|
||||||
|
if err := consensusEngine.Prepare(mockChainHR, gen.GetHeader(), nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.logger.Info("Adding 1 mock tx to block", "blockNum", gen.GetHeader().Number)
|
||||||
|
chainId := uint256.Int{}
|
||||||
|
overflow := chainId.SetFromBig(h.chainConfig.ChainID)
|
||||||
|
require.False(t, overflow)
|
||||||
|
from := h.genesisInitData.fundedAddresses[0]
|
||||||
|
tx, err := types.SignTx(
|
||||||
|
types.NewEIP1559Transaction(
|
||||||
|
chainId,
|
||||||
|
gen.TxNonce(from),
|
||||||
|
from, // send to itself
|
||||||
|
new(uint256.Int),
|
||||||
|
21000,
|
||||||
|
new(uint256.Int),
|
||||||
|
new(uint256.Int),
|
||||||
|
uint256.NewInt(937500001),
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
*types.LatestSignerForChainID(h.chainConfig.ChainID),
|
||||||
|
h.genesisInitData.genesisAllocPrivateKeys[from],
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
h.seal(t, mockChainHR, consensusEngine, chainPack.TopBlock)
|
||||||
|
sealedHeadersList := make([]*types.Header, len(h.sealedHeaders))
|
||||||
|
for num, header := range h.sealedHeaders {
|
||||||
|
sealedHeadersList[num] = header
|
||||||
|
}
|
||||||
|
|
||||||
|
h.saveHeaders(ctx, t, sealedHeadersList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) seal(t *testing.T, chr consensus.ChainHeaderReader, eng consensus.Engine, block *types.Block) {
|
||||||
|
h.logger.Info("Sealing mock block", "blockNum", block.Number())
|
||||||
|
sealRes, sealStop := make(chan *types.Block, 1), make(chan struct{}, 1)
|
||||||
|
if err := eng.Seal(chr, block, sealRes, sealStop); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sealedParentBlock := <-sealRes
|
||||||
|
h.sealedHeaders[sealedParentBlock.Number().Uint64()] = sealedParentBlock.Header()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) consensusEngine(t *testing.T, cfg HarnessCfg) consensus.Engine {
|
||||||
|
if h.chainConfig.Bor != nil {
|
||||||
|
genesisContracts := contract.NewGenesisContractsClient(
|
||||||
|
h.chainConfig,
|
||||||
|
h.chainConfig.Bor.ValidatorContract,
|
||||||
|
h.chainConfig.Bor.StateReceiverContract,
|
||||||
|
h.logger,
|
||||||
|
)
|
||||||
|
|
||||||
|
borConsensusEng := bor.New(
|
||||||
|
h.chainConfig,
|
||||||
|
h.borConsensusDb,
|
||||||
|
nil,
|
||||||
|
h.borSpanner,
|
||||||
|
h.heimdallClient,
|
||||||
|
genesisContracts,
|
||||||
|
h.logger,
|
||||||
|
)
|
||||||
|
|
||||||
|
borConsensusEng.Authorize(h.validatorAddress, func(_ libcommon.Address, _ string, msg []byte) ([]byte, error) {
|
||||||
|
return crypto.Sign(crypto.Keccak256(msg), h.validatorKey)
|
||||||
|
})
|
||||||
|
|
||||||
|
return borConsensusEng
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatal(fmt.Sprintf("unimplmented consensus engine init for cfg %v", cfg.ChainConfig))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) saveHeaders(ctx context.Context, t *testing.T, headers []*types.Header) {
|
||||||
|
rwTx, err := h.chainDataDb.BeginRw(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer rwTx.Rollback()
|
||||||
|
|
||||||
|
for _, header := range headers {
|
||||||
|
err = rawdb.WriteHeader(rwTx, header)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = rawdb.WriteCanonicalHash(rwTx, header.Hash(), header.Number.Uint64())
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rwTx.Commit()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) mockChainHeaderReader(ctrl *gomock.Controller) consensus.ChainHeaderReader {
|
||||||
|
mockChainHR := consensusmock.NewMockChainHeaderReader(ctrl)
|
||||||
|
mockChainHR.
|
||||||
|
EXPECT().
|
||||||
|
GetHeader(gomock.Any(), gomock.Any()).
|
||||||
|
DoAndReturn(func(_ libcommon.Hash, number uint64) *types.Header {
|
||||||
|
return h.sealedHeaders[number]
|
||||||
|
}).
|
||||||
|
AnyTimes()
|
||||||
|
|
||||||
|
mockChainHR.
|
||||||
|
EXPECT().
|
||||||
|
GetHeaderByNumber(gomock.Any()).
|
||||||
|
DoAndReturn(func(number uint64) *types.Header {
|
||||||
|
return h.sealedHeaders[number]
|
||||||
|
}).
|
||||||
|
AnyTimes()
|
||||||
|
|
||||||
|
mockChainHR.
|
||||||
|
EXPECT().
|
||||||
|
FrozenBlocks().
|
||||||
|
Return(uint64(0)).
|
||||||
|
AnyTimes()
|
||||||
|
|
||||||
|
return mockChainHR
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) setHeimdallNextMockSpan(logger log.Logger) {
|
||||||
|
validators := []*valset.Validator{
|
||||||
|
{
|
||||||
|
ID: 1,
|
||||||
|
Address: h.validatorAddress,
|
||||||
|
VotingPower: 1000,
|
||||||
|
ProposerPriority: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
validatorSet := valset.NewValidatorSet(validators, logger)
|
||||||
|
selectedProducers := make([]valset.Validator, len(validators))
|
||||||
|
for i := range validators {
|
||||||
|
selectedProducers[i] = *validators[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
h.heimdallNextMockSpan = &span.HeimdallSpan{
|
||||||
|
Span: span.Span{
|
||||||
|
ID: 0,
|
||||||
|
StartBlock: 0,
|
||||||
|
EndBlock: 255,
|
||||||
|
},
|
||||||
|
ValidatorSet: *validatorSet,
|
||||||
|
SelectedProducers: selectedProducers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) mockBorSpanner() {
|
||||||
|
h.borSpanner.
|
||||||
|
EXPECT().
|
||||||
|
GetCurrentValidators(gomock.Any(), gomock.Any(), gomock.Any()).
|
||||||
|
Return(h.heimdallNextMockSpan.ValidatorSet.Validators, nil).
|
||||||
|
AnyTimes()
|
||||||
|
|
||||||
|
h.borSpanner.
|
||||||
|
EXPECT().
|
||||||
|
GetCurrentProducers(gomock.Any(), gomock.Any(), gomock.Any()).
|
||||||
|
DoAndReturn(func(_ uint64, _ libcommon.Address, _ consensus.ChainHeaderReader) ([]*valset.Validator, error) {
|
||||||
|
res := make([]*valset.Validator, len(h.heimdallNextMockSpan.SelectedProducers))
|
||||||
|
for i := range h.heimdallNextMockSpan.SelectedProducers {
|
||||||
|
res[i] = &h.heimdallNextMockSpan.SelectedProducers[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}).
|
||||||
|
AnyTimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) mockHeimdallClient() {
|
||||||
|
h.heimdallClient.
|
||||||
|
EXPECT().
|
||||||
|
Span(gomock.Any(), gomock.Any()).
|
||||||
|
DoAndReturn(func(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) {
|
||||||
|
res := h.heimdallNextMockSpan
|
||||||
|
h.heimdallNextMockSpan = &span.HeimdallSpan{
|
||||||
|
Span: span.Span{
|
||||||
|
ID: res.ID + 1,
|
||||||
|
StartBlock: res.EndBlock + 1,
|
||||||
|
EndBlock: res.EndBlock + 6400,
|
||||||
|
},
|
||||||
|
ValidatorSet: res.ValidatorSet,
|
||||||
|
SelectedProducers: res.SelectedProducers,
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}).
|
||||||
|
AnyTimes()
|
||||||
|
|
||||||
|
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
|
||||||
|
}).
|
||||||
|
AnyTimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Harness) findStateSyncStageById(id stages.SyncStage) (*stagedsync.Stage, bool) {
|
||||||
|
for _, s := range h.stateSyncStages {
|
||||||
|
if s.ID == id {
|
||||||
|
return s, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user