mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 08:23:46 +00:00
add context to Fetch* methods (#445)
* add context * fix mocks * fixes after CR * fixes * fix * Linters
This commit is contained in:
parent
c3d62b8ea1
commit
3c42bfc633
15 changed files with 188 additions and 133 deletions
|
|
@ -2,6 +2,7 @@ package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -273,14 +274,14 @@ func (c *Bor) Author(header *types.Header) (common.Address, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyHeader checks whether a header conforms to the consensus rules.
|
// VerifyHeader checks whether a header conforms to the consensus rules.
|
||||||
func (c *Bor) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
|
func (c *Bor) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, _ bool) error {
|
||||||
return c.verifyHeader(chain, header, nil)
|
return c.verifyHeader(chain, header, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
||||||
// method returns a quit channel to abort the operations and a results channel to
|
// method returns a quit channel to abort the operations and a results channel to
|
||||||
// retrieve the async verifications (the order is that of the input slice).
|
// retrieve the async verifications (the order is that of the input slice).
|
||||||
func (c *Bor) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
|
func (c *Bor) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, _ []bool) (chan<- struct{}, <-chan error) {
|
||||||
abort := make(chan struct{})
|
abort := make(chan struct{})
|
||||||
results := make(chan error, len(headers))
|
results := make(chan error, len(headers))
|
||||||
|
|
||||||
|
|
@ -487,6 +488,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
// at a checkpoint block without a parent (light client CHT), or we have piled
|
// at a checkpoint block without a parent (light client CHT), or we have piled
|
||||||
// up more headers than allowed to be reorged (chain reinit from a freezer),
|
// up more headers than allowed to be reorged (chain reinit from a freezer),
|
||||||
// consider the checkpoint trusted and snapshot it.
|
// consider the checkpoint trusted and snapshot it.
|
||||||
|
|
||||||
// TODO fix this
|
// TODO fix this
|
||||||
// nolint:nestif
|
// nolint:nestif
|
||||||
if number == 0 {
|
if number == 0 {
|
||||||
|
|
@ -496,7 +498,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
hash := checkpoint.Hash()
|
hash := checkpoint.Hash()
|
||||||
|
|
||||||
// get validators and current span
|
// get validators and current span
|
||||||
validators, err := c.spanner.GetCurrentValidators(hash, number+1)
|
validators, err := c.spanner.GetCurrentValidators(context.Background(), hash, number+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -539,7 +541,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
|
|
||||||
// check if snapshot is nil
|
// check if snapshot is nil
|
||||||
if snap == nil {
|
if snap == nil {
|
||||||
return nil, fmt.Errorf("Unknown error while retrieving snapshot at block number %v", number)
|
return nil, fmt.Errorf("unknown error while retrieving snapshot at block number %v", number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previous snapshot found, apply any pending headers on top of it
|
// Previous snapshot found, apply any pending headers on top of it
|
||||||
|
|
@ -568,7 +570,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
|
|
||||||
// VerifyUncles implements consensus.Engine, always returning an error for any
|
// VerifyUncles implements consensus.Engine, always returning an error for any
|
||||||
// uncles as this consensus mechanism doesn't permit uncles.
|
// uncles as this consensus mechanism doesn't permit uncles.
|
||||||
func (c *Bor) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
func (c *Bor) VerifyUncles(_ consensus.ChainReader, block *types.Block) error {
|
||||||
if len(block.Uncles()) > 0 {
|
if len(block.Uncles()) > 0 {
|
||||||
return errors.New("uncles not allowed")
|
return errors.New("uncles not allowed")
|
||||||
}
|
}
|
||||||
|
|
@ -662,7 +664,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
|
|
||||||
// get validator set if number
|
// get validator set if number
|
||||||
if IsSprintStart(number+1, c.config.Sprint) {
|
if IsSprintStart(number+1, c.config.Sprint) {
|
||||||
newValidators, err := c.spanner.GetCurrentValidators(header.ParentHash, number+1)
|
newValidators, err := c.spanner.GetCurrentValidators(context.Background(), header.ParentHash, number+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unknown validators")
|
return errors.New("unknown validators")
|
||||||
}
|
}
|
||||||
|
|
@ -706,24 +708,27 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||||
// rewards given.
|
// rewards given.
|
||||||
func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
|
func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, _ []*types.Transaction, _ []*types.Header) {
|
||||||
stateSyncData := []*types.StateSyncData{}
|
var (
|
||||||
|
stateSyncData []*types.StateSyncData
|
||||||
var err error
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
|
|
||||||
if headerNumber%c.config.Sprint == 0 {
|
if headerNumber%c.config.Sprint == 0 {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
||||||
// check and commit span
|
// check and commit span
|
||||||
if err := c.checkAndCommitSpan(state, header, cx); err != nil {
|
if err := c.checkAndCommitSpan(ctx, state, header, cx); err != nil {
|
||||||
log.Error("Error while committing span", "error", err)
|
log.Error("Error while committing span", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.HeimdallClient != nil {
|
if c.HeimdallClient != nil {
|
||||||
// commit statees
|
// commit statees
|
||||||
stateSyncData, err = c.CommitStates(state, header, cx)
|
stateSyncData, err = c.CommitStates(ctx, state, header, cx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error while committing states", "error", err)
|
log.Error("Error while committing states", "error", err)
|
||||||
return
|
return
|
||||||
|
|
@ -780,16 +785,18 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State
|
||||||
|
|
||||||
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
|
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
|
||||||
// nor block rewards given, and returns the final block.
|
// nor block rewards given, and returns the final block.
|
||||||
func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, _ []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
stateSyncData := []*types.StateSyncData{}
|
var stateSyncData []*types.StateSyncData
|
||||||
|
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
|
|
||||||
if headerNumber%c.config.Sprint == 0 {
|
if headerNumber%c.config.Sprint == 0 {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
||||||
|
|
||||||
// check and commit span
|
// check and commit span
|
||||||
err := c.checkAndCommitSpan(state, header, cx)
|
err := c.checkAndCommitSpan(ctx, state, header, cx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error while committing span", "error", err)
|
log.Error("Error while committing span", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -797,7 +804,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
|
||||||
|
|
||||||
if c.HeimdallClient != nil {
|
if c.HeimdallClient != nil {
|
||||||
// commit states
|
// commit states
|
||||||
stateSyncData, err = c.CommitStates(state, header, cx)
|
stateSyncData, err = c.CommitStates(ctx, state, header, cx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error while committing states", "error", err)
|
log.Error("Error while committing states", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -932,7 +939,7 @@ func Sign(signFn SignerFn, signer common.Address, header *types.Header, c *param
|
||||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||||
// that a new block should have based on the previous blocks in the chain and the
|
// that a new block should have based on the previous blocks in the chain and the
|
||||||
// current signer.
|
// current signer.
|
||||||
func (c *Bor) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
|
func (c *Bor) CalcDifficulty(chain consensus.ChainHeaderReader, _ uint64, parent *types.Header) *big.Int {
|
||||||
snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil)
|
snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -969,37 +976,38 @@ func (c *Bor) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Bor) checkAndCommitSpan(
|
func (c *Bor) checkAndCommitSpan(
|
||||||
|
ctx context.Context,
|
||||||
state *state.StateDB,
|
state *state.StateDB,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
chain core.ChainContext,
|
chain core.ChainContext,
|
||||||
) error {
|
) error {
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
|
|
||||||
span, err := c.spanner.GetCurrentSpan(header.ParentHash)
|
currentSpan, err := c.spanner.GetCurrentSpan(ctx, header.ParentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.needToCommitSpan(span, headerNumber) {
|
if c.needToCommitSpan(currentSpan, headerNumber) {
|
||||||
return c.FetchAndCommitSpan(span.ID+1, state, header, chain)
|
return c.FetchAndCommitSpan(ctx, currentSpan.ID+1, state, header, chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Bor) needToCommitSpan(span *span.Span, headerNumber uint64) bool {
|
func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool {
|
||||||
// if span is nil
|
// if span is nil
|
||||||
if span == nil {
|
if currentSpan == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// check span is not set initially
|
// check span is not set initially
|
||||||
if span.EndBlock == 0 {
|
if currentSpan.EndBlock == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// if current block is first block of last sprint in current span
|
// if current block is first block of last sprint in current span
|
||||||
if span.EndBlock > c.config.Sprint && span.EndBlock-c.config.Sprint+1 == headerNumber {
|
if currentSpan.EndBlock > c.config.Sprint && currentSpan.EndBlock-c.config.Sprint+1 == headerNumber {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1007,6 +1015,7 @@ func (c *Bor) needToCommitSpan(span *span.Span, headerNumber uint64) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Bor) FetchAndCommitSpan(
|
func (c *Bor) FetchAndCommitSpan(
|
||||||
|
ctx context.Context,
|
||||||
newSpanID uint64,
|
newSpanID uint64,
|
||||||
state *state.StateDB,
|
state *state.StateDB,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
|
|
@ -1016,14 +1025,14 @@ func (c *Bor) FetchAndCommitSpan(
|
||||||
|
|
||||||
if c.HeimdallClient == nil {
|
if c.HeimdallClient == nil {
|
||||||
// fixme: move to a new mock or fake and remove c.HeimdallClient completely
|
// fixme: move to a new mock or fake and remove c.HeimdallClient completely
|
||||||
s, err := c.getNextHeimdallSpanForTest(newSpanID, header, chain)
|
s, err := c.getNextHeimdallSpanForTest(ctx, newSpanID, header, chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
heimdallSpan = *s
|
heimdallSpan = *s
|
||||||
} else {
|
} else {
|
||||||
response, err := c.HeimdallClient.Span(newSpanID)
|
response, err := c.HeimdallClient.Span(ctx, newSpanID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -1040,11 +1049,12 @@ func (c *Bor) FetchAndCommitSpan(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.spanner.CommitSpan(heimdallSpan, state, header, chain)
|
return c.spanner.CommitSpan(ctx, heimdallSpan, state, header, chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitStates commit states
|
// CommitStates commit states
|
||||||
func (c *Bor) CommitStates(
|
func (c *Bor) CommitStates(
|
||||||
|
ctx context.Context,
|
||||||
state *state.StateDB,
|
state *state.StateDB,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
chain statefull.ChainContext,
|
chain statefull.ChainContext,
|
||||||
|
|
@ -1065,7 +1075,7 @@ func (c *Bor) CommitStates(
|
||||||
"fromID", lastStateID+1,
|
"fromID", lastStateID+1,
|
||||||
"to", to.Format(time.RFC3339))
|
"to", to.Format(time.RFC3339))
|
||||||
|
|
||||||
eventRecords, err := c.HeimdallClient.StateSyncEvents(lastStateID+1, to.Unix())
|
eventRecords, err := c.HeimdallClient.StateSyncEvents(ctx, lastStateID+1, to.Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error occurred when fetching state sync events", "stateID", lastStateID+1, "error", err)
|
log.Error("Error occurred when fetching state sync events", "stateID", lastStateID+1, "error", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1127,8 +1137,8 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) {
|
||||||
c.HeimdallClient = h
|
c.HeimdallClient = h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
|
func (c *Bor) GetCurrentValidators(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
|
||||||
return c.spanner.GetCurrentValidators(headerHash, blockNumber)
|
return c.spanner.GetCurrentValidators(ctx, headerHash, blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -1136,13 +1146,14 @@ func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) (
|
||||||
//
|
//
|
||||||
|
|
||||||
func (c *Bor) getNextHeimdallSpanForTest(
|
func (c *Bor) getNextHeimdallSpanForTest(
|
||||||
|
ctx context.Context,
|
||||||
newSpanID uint64,
|
newSpanID uint64,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
chain core.ChainContext,
|
chain core.ChainContext,
|
||||||
) (*span.HeimdallSpan, error) {
|
) (*span.HeimdallSpan, error) {
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
|
|
||||||
spanBor, err := c.spanner.GetCurrentSpan(header.ParentHash)
|
spanBor, err := c.spanner.GetCurrentSpan(ctx, header.ParentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ func (gc *GenesisContractsClient) CommitState(
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
||||||
gasUsed, err := statefull.ApplyMessage(msg, state, header, gc.chainConfig, chCtx)
|
gasUsed, err := statefull.ApplyMessage(context.Background(), msg, state, header, gc.chainConfig, chCtx)
|
||||||
|
|
||||||
// Logging event log with time and individual gasUsed
|
// Logging event log with time and individual gasUsed
|
||||||
log.Info("→ committing new state", "eventRecord", event.String(gasUsed))
|
log.Info("→ committing new state", "eventRecord", event.String(gasUsed))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package bor
|
package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
||||||
|
|
@ -8,8 +10,8 @@ import (
|
||||||
|
|
||||||
//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
|
//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient
|
||||||
type IHeimdallClient interface {
|
type IHeimdallClient interface {
|
||||||
StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error)
|
StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error)
|
||||||
Span(spanID uint64) (*span.HeimdallSpan, error)
|
Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error)
|
||||||
FetchLatestCheckpoint() (*checkpoint.Checkpoint, error)
|
FetchLatestCheckpoint(ctx context.Context) (*checkpoint.Checkpoint, error)
|
||||||
Close()
|
Close()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,17 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// errShutdownDetected is returned if a shutdown was detected
|
var (
|
||||||
var errShutdownDetected = errors.New("shutdown detected")
|
// ErrShutdownDetected is returned if a shutdown was detected
|
||||||
|
ErrShutdownDetected = errors.New("shutdown detected")
|
||||||
|
ErrNoResponse = errors.New("got a nil response")
|
||||||
|
ErrNotSuccessfulResponse = errors.New("error while fetching data from Heimdall")
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
stateFetchLimit = 50
|
stateFetchLimit = 50
|
||||||
apiHeimdallTimeout = 5 * time.Second
|
apiHeimdallTimeout = 5 * time.Second
|
||||||
|
retryCall = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type StateSyncEventsResponse struct {
|
type StateSyncEventsResponse struct {
|
||||||
|
|
@ -59,7 +64,7 @@ const (
|
||||||
fetchSpanFormat = "bor/span/%d"
|
fetchSpanFormat = "bor/span/%d"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *HeimdallClient) StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
func (h *HeimdallClient) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
||||||
eventRecords := make([]*clerk.EventRecordWithTime, 0)
|
eventRecords := make([]*clerk.EventRecordWithTime, 0)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
@ -70,7 +75,7 @@ func (h *HeimdallClient) StateSyncEvents(fromID uint64, to int64) ([]*clerk.Even
|
||||||
|
|
||||||
log.Info("Fetching state sync events", "queryParams", url.RawQuery)
|
log.Info("Fetching state sync events", "queryParams", url.RawQuery)
|
||||||
|
|
||||||
response, err := FetchWithRetry[StateSyncEventsResponse](h.client, url, h.closeCh)
|
response, err := FetchWithRetry[StateSyncEventsResponse](ctx, h.client, url, h.closeCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -96,13 +101,13 @@ func (h *HeimdallClient) StateSyncEvents(fromID uint64, to int64) ([]*clerk.Even
|
||||||
return eventRecords, nil
|
return eventRecords, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeimdallClient) Span(spanID uint64) (*span.HeimdallSpan, error) {
|
func (h *HeimdallClient) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) {
|
||||||
url, err := spanURL(h.urlString, spanID)
|
url, err := spanURL(h.urlString, spanID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := FetchWithRetry[SpanResponse](h.client, url, h.closeCh)
|
response, err := FetchWithRetry[SpanResponse](ctx, h.client, url, h.closeCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -111,13 +116,13 @@ func (h *HeimdallClient) Span(spanID uint64) (*span.HeimdallSpan, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchLatestCheckpoint fetches the latest bor submitted checkpoint from heimdall
|
// FetchLatestCheckpoint fetches the latest bor submitted checkpoint from heimdall
|
||||||
func (h *HeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) {
|
func (h *HeimdallClient) FetchLatestCheckpoint(ctx context.Context) (*checkpoint.Checkpoint, error) {
|
||||||
url, err := latestCheckpointURL(h.urlString)
|
url, err := latestCheckpointURL(h.urlString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := FetchWithRetry[checkpoint.CheckpointResponse](h.client, url, h.closeCh)
|
response, err := FetchWithRetry[checkpoint.CheckpointResponse](ctx, h.client, url, h.closeCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -126,58 +131,75 @@ func (h *HeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchWithRetry returns data from heimdall with retry
|
// FetchWithRetry returns data from heimdall with retry
|
||||||
func FetchWithRetry[T any](client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) {
|
func FetchWithRetry[T any](ctx context.Context, client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) {
|
||||||
// attempt counter
|
|
||||||
attempt := 1
|
|
||||||
result := new(T)
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), apiHeimdallTimeout)
|
|
||||||
|
|
||||||
// request data once
|
// request data once
|
||||||
body, err := internalFetch(ctx, client, url)
|
result, err := Fetch[T](ctx, client, url)
|
||||||
|
if err == nil {
|
||||||
cancel()
|
|
||||||
|
|
||||||
if err == nil && body != nil {
|
|
||||||
err = json.Unmarshal(body, result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attempt counter
|
||||||
|
attempt := 1
|
||||||
|
|
||||||
|
log.Warn("an error while trying fetching from Heimdall", "attempt", attempt, "error", err)
|
||||||
|
|
||||||
// create a new ticker for retrying the request
|
// create a new ticker for retrying the request
|
||||||
ticker := time.NewTicker(5 * time.Second)
|
ticker := time.NewTicker(retryCall)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
const logEach = 5
|
||||||
|
|
||||||
|
retryLoop:
|
||||||
for {
|
for {
|
||||||
log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", url.Path, "attempt", attempt)
|
log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", url.Path, "attempt", attempt)
|
||||||
|
|
||||||
attempt++
|
attempt++
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Debug("Shutdown detected, terminating request by context.Done")
|
||||||
|
|
||||||
|
return nil, ctx.Err()
|
||||||
case <-closeCh:
|
case <-closeCh:
|
||||||
log.Debug("Shutdown detected, terminating request")
|
log.Debug("Shutdown detected, terminating request by closing")
|
||||||
|
|
||||||
return nil, errShutdownDetected
|
return nil, ErrShutdownDetected
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
ctx, cancel = context.WithTimeout(context.Background(), apiHeimdallTimeout)
|
result, err = Fetch[T](ctx, client, url)
|
||||||
|
if err != nil {
|
||||||
body, err = internalFetch(ctx, client, url)
|
if attempt%logEach == 0 {
|
||||||
|
log.Warn("an error while trying fetching from Heimdall", "attempt", attempt, "error", err)
|
||||||
cancel()
|
|
||||||
|
|
||||||
if err == nil && body != nil {
|
|
||||||
err = json.Unmarshal(body, result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
continue retryLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch returns data from heimdall
|
||||||
|
func Fetch[T any](ctx context.Context, client http.Client, url *url.URL) (*T, error) {
|
||||||
|
result := new(T)
|
||||||
|
|
||||||
|
body, err := internalFetchWithTimeout(ctx, client, url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if body == nil {
|
||||||
|
return nil, ErrNoResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func spanURL(urlString string, spanID uint64) (*url.URL, error) {
|
func spanURL(urlString string, spanID uint64) (*url.URL, error) {
|
||||||
return makeURL(urlString, fmt.Sprintf(fetchSpanFormat, spanID), "")
|
return makeURL(urlString, fmt.Sprintf(fetchSpanFormat, spanID), "")
|
||||||
}
|
}
|
||||||
|
|
@ -215,11 +237,12 @@ func internalFetch(ctx context.Context, client http.Client, u *url.URL) ([]byte,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
// check status code
|
// check status code
|
||||||
if res.StatusCode != 200 && res.StatusCode != 204 {
|
if res.StatusCode != 200 && res.StatusCode != 204 {
|
||||||
return nil, fmt.Errorf("Error while fetching data from Heimdall")
|
return nil, fmt.Errorf("%w: response code %d", ErrNotSuccessfulResponse, res.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmarshall data from buffer
|
// unmarshall data from buffer
|
||||||
|
|
@ -236,6 +259,14 @@ func internalFetch(ctx context.Context, client http.Client, u *url.URL) ([]byte,
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func internalFetchWithTimeout(ctx context.Context, client http.Client, url *url.URL) ([]byte, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, apiHeimdallTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// request data once
|
||||||
|
return internalFetch(ctx, client, url)
|
||||||
|
}
|
||||||
|
|
||||||
// Close sends a signal to stop the running process
|
// Close sends a signal to stop the running process
|
||||||
func (h *HeimdallClient) Close() {
|
func (h *HeimdallClient) Close() {
|
||||||
close(h.closeCh)
|
close(h.closeCh)
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func NewChainSpanner(ethAPI api.Caller, validatorSet abi.ABI, chainConfig *param
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentSpan get current span from contract
|
// GetCurrentSpan get current span from contract
|
||||||
func (c *ChainSpanner) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
|
func (c *ChainSpanner) GetCurrentSpan(ctx context.Context, headerHash common.Hash) (*Span, error) {
|
||||||
// block
|
// block
|
||||||
blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
|
blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false)
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ func (c *ChainSpanner) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
|
||||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||||
|
|
||||||
// todo: would we like to have a timeout here?
|
// todo: would we like to have a timeout here?
|
||||||
result, err := c.ethAPI.Call(context.Background(), ethapi.TransactionArgs{
|
result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
Gas: &gas,
|
Gas: &gas,
|
||||||
To: &toAddress,
|
To: &toAddress,
|
||||||
Data: &msgData,
|
Data: &msgData,
|
||||||
|
|
@ -89,8 +89,8 @@ func (c *ChainSpanner) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidators get current validators
|
// GetCurrentValidators get current validators
|
||||||
func (c *ChainSpanner) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
|
func (c *ChainSpanner) GetCurrentValidators(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// method
|
// method
|
||||||
|
|
@ -146,7 +146,7 @@ func (c *ChainSpanner) GetCurrentValidators(headerHash common.Hash, blockNumber
|
||||||
|
|
||||||
const method = "commitSpan"
|
const method = "commitSpan"
|
||||||
|
|
||||||
func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error {
|
func (c *ChainSpanner) CommitSpan(ctx context.Context, heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error {
|
||||||
// get validators bytes
|
// get validators bytes
|
||||||
validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators))
|
validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators))
|
||||||
for _, val := range heimdallSpan.ValidatorSet.Validators {
|
for _, val := range heimdallSpan.ValidatorSet.Validators {
|
||||||
|
|
@ -194,7 +194,7 @@ func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, state *state.StateD
|
||||||
msg := statefull.GetSystemMessage(c.validatorContractAddress, data)
|
msg := statefull.GetSystemMessage(c.validatorContractAddress, data)
|
||||||
|
|
||||||
// apply message
|
// apply message
|
||||||
_, err = statefull.ApplyMessage(msg, state, header, c.chainConfig, chainContext)
|
_, err = statefull.ApplyMessage(ctx, msg, state, header, c.chainConfig, chainContext)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package bor
|
package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/valset"
|
"github.com/ethereum/go-ethereum/consensus/bor/valset"
|
||||||
|
|
@ -11,7 +13,7 @@ import (
|
||||||
|
|
||||||
//go:generate mockgen -destination=./span_mock.go -package=bor . Spanner
|
//go:generate mockgen -destination=./span_mock.go -package=bor . Spanner
|
||||||
type Spanner interface {
|
type Spanner interface {
|
||||||
GetCurrentSpan(headerHash common.Hash) (*span.Span, error)
|
GetCurrentSpan(ctx context.Context, headerHash common.Hash) (*span.Span, error)
|
||||||
GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error)
|
GetCurrentValidators(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error)
|
||||||
CommitSpan(heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error
|
CommitSpan(ctx context.Context, heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package bor
|
package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
common "github.com/ethereum/go-ethereum/common"
|
common "github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -40,45 +41,45 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitSpan mocks base method.
|
// CommitSpan mocks base method.
|
||||||
func (m *MockSpanner) CommitSpan(arg0 span.HeimdallSpan, arg1 *state.StateDB, arg2 *types.Header, arg3 core.ChainContext) error {
|
func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 span.HeimdallSpan, arg2 *state.StateDB, arg3 *types.Header, arg4 core.ChainContext) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3)
|
ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitSpan indicates an expected call of CommitSpan.
|
// CommitSpan indicates an expected call of CommitSpan.
|
||||||
func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentSpan mocks base method.
|
// GetCurrentSpan mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentSpan(arg0 common.Hash) (*span.Span, error) {
|
func (m *MockSpanner) GetCurrentSpan(arg0 context.Context, arg1 common.Hash) (*span.Span, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentSpan", arg0)
|
ret := m.ctrl.Call(m, "GetCurrentSpan", arg0, arg1)
|
||||||
ret0, _ := ret[0].(*span.Span)
|
ret0, _ := ret[0].(*span.Span)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentSpan indicates an expected call of GetCurrentSpan.
|
// GetCurrentSpan indicates an expected call of GetCurrentSpan.
|
||||||
func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0 interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidators mocks base method.
|
// GetCurrentValidators mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentValidators(arg0 common.Hash, arg1 uint64) ([]*valset.Validator, error) {
|
func (m *MockSpanner) GetCurrentValidators(arg0 context.Context, arg1 common.Hash, arg2 uint64) ([]*valset.Validator, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1)
|
ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*valset.Validator)
|
ret0, _ := ret[0].([]*valset.Validator)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidators indicates an expected call of GetCurrentValidators.
|
// GetCurrentValidators indicates an expected call of GetCurrentValidators.
|
||||||
func (mr *MockSpannerMockRecorder) GetCurrentValidators(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) GetCurrentValidators(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidators), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidators), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package statefull
|
package statefull
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
|
@ -59,6 +60,7 @@ func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
|
||||||
|
|
||||||
// apply message
|
// apply message
|
||||||
func ApplyMessage(
|
func ApplyMessage(
|
||||||
|
_ context.Context,
|
||||||
msg callmsg,
|
msg callmsg,
|
||||||
state *state.StateDB,
|
state *state.StateDB,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
|
|
|
||||||
|
|
@ -1796,7 +1796,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
|
||||||
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
spanner := bor.NewMockSpanner(ctrl)
|
spanner := bor.NewMockSpanner(ctrl)
|
||||||
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
||||||
{
|
{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Address: miner.TestBankAddress,
|
Address: miner.TestBankAddress,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -632,7 +633,8 @@ func (s *Ethereum) startCheckpointWhitelistService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// first run the checkpoint whitelist
|
// first run the checkpoint whitelist
|
||||||
err := s.handleWhitelistCheckpoint()
|
// TODO: add context timeout if needed
|
||||||
|
err := s.handleWhitelistCheckpoint(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrBorConsensusWithoutHeimdall) || errors.Is(err, ErrNotBorConsensus) {
|
if errors.Is(err, ErrBorConsensusWithoutHeimdall) || errors.Is(err, ErrNotBorConsensus) {
|
||||||
return
|
return
|
||||||
|
|
@ -647,7 +649,8 @@ func (s *Ethereum) startCheckpointWhitelistService() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
err := s.handleWhitelistCheckpoint()
|
// TODO: add context timeout if needed
|
||||||
|
err = s.handleWhitelistCheckpoint(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("unable to whitelist checkpoint", "err", err)
|
log.Warn("unable to whitelist checkpoint", "err", err)
|
||||||
}
|
}
|
||||||
|
|
@ -663,7 +666,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleWhitelistCheckpoint handles the checkpoint whitelist mechanism.
|
// handleWhitelistCheckpoint handles the checkpoint whitelist mechanism.
|
||||||
func (s *Ethereum) handleWhitelistCheckpoint() error {
|
func (s *Ethereum) handleWhitelistCheckpoint(ctx context.Context) error {
|
||||||
ethHandler := (*ethHandler)(s.handler)
|
ethHandler := (*ethHandler)(s.handler)
|
||||||
|
|
||||||
bor, ok := ethHandler.chain.Engine().(*bor.Bor)
|
bor, ok := ethHandler.chain.Engine().(*bor.Bor)
|
||||||
|
|
@ -675,7 +678,7 @@ func (s *Ethereum) handleWhitelistCheckpoint() error {
|
||||||
return ErrBorConsensusWithoutHeimdall
|
return ErrBorConsensusWithoutHeimdall
|
||||||
}
|
}
|
||||||
|
|
||||||
endBlockNum, endBlockHash, err := ethHandler.fetchWhitelistCheckpoint(bor)
|
endBlockNum, endBlockHash, err := ethHandler.fetchWhitelistCheckpoint(ctx, bor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ var (
|
||||||
|
|
||||||
// fetchWhitelistCheckpoint fetched the latest checkpoint from it's local heimdall
|
// fetchWhitelistCheckpoint fetched the latest checkpoint from it's local heimdall
|
||||||
// and verifies the data against bor data.
|
// and verifies the data against bor data.
|
||||||
func (h *ethHandler) fetchWhitelistCheckpoint(bor *bor.Bor) (uint64, common.Hash, error) {
|
func (h *ethHandler) fetchWhitelistCheckpoint(ctx context.Context, bor *bor.Bor) (uint64, common.Hash, error) {
|
||||||
// check for checkpoint whitelisting: bor
|
// check for checkpoint whitelisting: bor
|
||||||
checkpoint, err := bor.HeimdallClient.FetchLatestCheckpoint()
|
checkpoint, err := bor.HeimdallClient.FetchLatestCheckpoint(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to fetch latest checkpoint for whitelisting")
|
log.Debug("Failed to fetch latest checkpoint for whitelisting")
|
||||||
return 0, common.Hash{}, errCheckpoint
|
return 0, common.Hash{}, errCheckpoint
|
||||||
|
|
@ -51,7 +51,7 @@ func (h *ethHandler) fetchWhitelistCheckpoint(bor *bor.Bor) (uint64, common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify the root hash of checkpoint
|
// verify the root hash of checkpoint
|
||||||
roothash, err := h.ethAPI.GetRootHash(context.Background(), checkpoint.StartBlock.Uint64(), checkpoint.EndBlock.Uint64())
|
roothash, err := h.ethAPI.GetRootHash(ctx, checkpoint.StartBlock.Uint64(), checkpoint.EndBlock.Uint64())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to get root hash of checkpoint while whitelisting")
|
log.Debug("Failed to get root hash of checkpoint while whitelisting")
|
||||||
return 0, common.Hash{}, errRootHash
|
return 0, common.Hash{}, errRootHash
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ func NewBorDefaultMiner(t *testing.T) *DefaultBorMiner {
|
||||||
ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
spanner := bor.NewMockSpanner(ctrl)
|
spanner := bor.NewMockSpanner(ctrl)
|
||||||
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
||||||
{
|
{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Address: common.Address{0x1},
|
Address: common.Address{0x1},
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ func testGenerateBlockAndImport(t *testing.T, isClique bool, isBor bool) {
|
||||||
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
spanner := bor.NewMockSpanner(ctrl)
|
spanner := bor.NewMockSpanner(ctrl)
|
||||||
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
||||||
{
|
{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Address: TestBankAddress,
|
Address: TestBankAddress,
|
||||||
|
|
@ -622,7 +622,7 @@ func BenchmarkBorMining(b *testing.B) {
|
||||||
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
spanner := bor.NewMockSpanner(ctrl)
|
spanner := bor.NewMockSpanner(ctrl)
|
||||||
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{
|
||||||
{
|
{
|
||||||
ID: 0,
|
ID: 0,
|
||||||
Address: TestBankAddress,
|
Address: TestBankAddress,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
//go:build integration
|
//go:build integration
|
||||||
// +build integration
|
|
||||||
|
|
||||||
package bor
|
package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -41,11 +41,11 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
|
||||||
h, heimdallSpan, ctrl := getMockedHeimdallClient(t)
|
h, heimdallSpan, ctrl := getMockedHeimdallClient(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
_, span := loadSpanFromFile(t)
|
_, currentSpan := loadSpanFromFile(t)
|
||||||
|
|
||||||
h.EXPECT().Close().AnyTimes()
|
h.EXPECT().Close().AnyTimes()
|
||||||
h.EXPECT().FetchLatestCheckpoint().Return(&checkpoint.Checkpoint{
|
h.EXPECT().FetchLatestCheckpoint(gomock.Any()).Return(&checkpoint.Checkpoint{
|
||||||
Proposer: span.SelectedProducers[0].Address,
|
Proposer: currentSpan.SelectedProducers[0].Address,
|
||||||
StartBlock: big.NewInt(0),
|
StartBlock: big.NewInt(0),
|
||||||
EndBlock: big.NewInt(int64(spanSize)),
|
EndBlock: big.NewInt(int64(spanSize)),
|
||||||
}, nil).AnyTimes()
|
}, nil).AnyTimes()
|
||||||
|
|
@ -62,7 +62,7 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
|
||||||
insertNewBlock(t, chain, block)
|
insertNewBlock(t, chain, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
validators, err := _bor.GetCurrentValidators(block.Hash(), spanSize) // check validator set at the first block of new span
|
validators, err := _bor.GetCurrentValidators(context.Background(), block.Hash(), spanSize) // check validator set at the first block of new span
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ func TestFetchStateSyncEvents(t *testing.T) {
|
||||||
|
|
||||||
h := mocks.NewMockIHeimdallClient(ctrl)
|
h := mocks.NewMockIHeimdallClient(ctrl)
|
||||||
h.EXPECT().Close().AnyTimes()
|
h.EXPECT().Close().AnyTimes()
|
||||||
h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes()
|
h.EXPECT().Span(gomock.Any(), uint64(1)).Return(&res.Result, nil).AnyTimes()
|
||||||
|
|
||||||
// B.2 Mock State Sync events
|
// B.2 Mock State Sync events
|
||||||
fromID := uint64(1)
|
fromID := uint64(1)
|
||||||
|
|
@ -112,7 +112,7 @@ func TestFetchStateSyncEvents(t *testing.T) {
|
||||||
sample.Time = time.Unix(to-int64(eventCount+1), 0) // last event.Time will be just < to
|
sample.Time = time.Unix(to-int64(eventCount+1), 0) // last event.Time will be just < to
|
||||||
eventRecords := generateFakeStateSyncEvents(sample, eventCount)
|
eventRecords := generateFakeStateSyncEvents(sample, eventCount)
|
||||||
|
|
||||||
h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
|
h.EXPECT().StateSyncEvents(gomock.Any(), fromID, to).Return(eventRecords, nil).AnyTimes()
|
||||||
_bor.SetHeimdallClient(h)
|
_bor.SetHeimdallClient(h)
|
||||||
|
|
||||||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
||||||
|
|
@ -135,7 +135,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
|
||||||
|
|
||||||
h := mocks.NewMockIHeimdallClient(ctrl)
|
h := mocks.NewMockIHeimdallClient(ctrl)
|
||||||
h.EXPECT().Close().AnyTimes()
|
h.EXPECT().Close().AnyTimes()
|
||||||
h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes()
|
h.EXPECT().Span(gomock.Any(), uint64(1)).Return(&res.Result, nil).AnyTimes()
|
||||||
|
|
||||||
// Mock State Sync events
|
// Mock State Sync events
|
||||||
// at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
|
// at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
|
||||||
|
|
@ -154,7 +154,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
|
||||||
buildStateEvent(sample, 6, 4), // id = 6, time = 4
|
buildStateEvent(sample, 6, 4), // id = 6, time = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
|
h.EXPECT().StateSyncEvents(gomock.Any(), fromID, to).Return(eventRecords, nil).AnyTimes()
|
||||||
_bor.SetHeimdallClient(h)
|
_bor.SetHeimdallClient(h)
|
||||||
|
|
||||||
// Insert blocks for 0th sprint
|
// Insert blocks for 0th sprint
|
||||||
|
|
@ -178,7 +178,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
|
||||||
buildStateEvent(sample, 5, 7),
|
buildStateEvent(sample, 5, 7),
|
||||||
buildStateEvent(sample, 6, 4),
|
buildStateEvent(sample, 6, 4),
|
||||||
}
|
}
|
||||||
h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes()
|
h.EXPECT().StateSyncEvents(gomock.Any(), fromID, to).Return(eventRecords, nil).AnyTimes()
|
||||||
|
|
||||||
for i := sprintSize + 1; i <= spanSize; i++ {
|
for i := sprintSize + 1; i <= spanSize; i++ {
|
||||||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
||||||
|
|
@ -227,8 +227,10 @@ func TestOutOfTurnSigning(t *testing.T) {
|
||||||
|
|
||||||
expectedDifficulty := uint64(3 - expectedSuccessionNumber) // len(validators) - succession
|
expectedDifficulty := uint64(3 - expectedSuccessionNumber) // len(validators) - succession
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
header.Time += (bor.CalcProducerDelay(header.Number.Uint64(), expectedSuccessionNumber, init.genesis.Config.Bor) -
|
|
||||||
bor.CalcProducerDelay(header.Number.Uint64(), 0, init.genesis.Config.Bor))
|
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), expectedSuccessionNumber, init.genesis.Config.Bor) -
|
||||||
|
bor.CalcProducerDelay(header.Number.Uint64(), 0, init.genesis.Config.Bor)
|
||||||
|
|
||||||
sign(t, header, signerKey, init.genesis.Config.Bor)
|
sign(t, header, signerKey, init.genesis.Config.Bor)
|
||||||
block = types.NewBlockWithHeader(header)
|
block = types.NewBlockWithHeader(header)
|
||||||
|
|
||||||
|
|
@ -282,9 +284,9 @@ func getMockedHeimdallClient(t *testing.T) (*mocks.MockIHeimdallClient, *span.He
|
||||||
|
|
||||||
_, heimdallSpan := loadSpanFromFile(t)
|
_, heimdallSpan := loadSpanFromFile(t)
|
||||||
|
|
||||||
h.EXPECT().Span(uint64(1)).Return(heimdallSpan, nil).AnyTimes()
|
h.EXPECT().Span(gomock.Any(), uint64(1)).Return(heimdallSpan, nil).AnyTimes()
|
||||||
|
|
||||||
h.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any()).
|
h.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()).
|
||||||
Return([]*clerk.EventRecordWithTime{getSampleEventRecord(t)}, nil).AnyTimes()
|
Return([]*clerk.EventRecordWithTime{getSampleEventRecord(t)}, nil).AnyTimes()
|
||||||
|
|
||||||
return h, heimdallSpan, ctrl
|
return h, heimdallSpan, ctrl
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
|
|
@ -49,46 +50,46 @@ func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchLatestCheckpoint mocks base method.
|
// FetchLatestCheckpoint mocks base method.
|
||||||
func (m *MockIHeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) {
|
func (m *MockIHeimdallClient) FetchLatestCheckpoint(arg0 context.Context) (*checkpoint.Checkpoint, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "FetchLatestCheckpoint")
|
ret := m.ctrl.Call(m, "FetchLatestCheckpoint", arg0)
|
||||||
ret0, _ := ret[0].(*checkpoint.Checkpoint)
|
ret0, _ := ret[0].(*checkpoint.Checkpoint)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchLatestCheckpoint indicates an expected call of FetchLatestCheckpoint.
|
// FetchLatestCheckpoint indicates an expected call of FetchLatestCheckpoint.
|
||||||
func (mr *MockIHeimdallClientMockRecorder) FetchLatestCheckpoint() *gomock.Call {
|
func (mr *MockIHeimdallClientMockRecorder) FetchLatestCheckpoint(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLatestCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLatestCheckpoint))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLatestCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLatestCheckpoint), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Span mocks base method.
|
// Span mocks base method.
|
||||||
func (m *MockIHeimdallClient) Span(arg0 uint64) (*span.HeimdallSpan, error) {
|
func (m *MockIHeimdallClient) Span(arg0 context.Context, arg1 uint64) (*span.HeimdallSpan, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Span", arg0)
|
ret := m.ctrl.Call(m, "Span", arg0, arg1)
|
||||||
ret0, _ := ret[0].(*span.HeimdallSpan)
|
ret0, _ := ret[0].(*span.HeimdallSpan)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Span indicates an expected call of Span.
|
// Span indicates an expected call of Span.
|
||||||
func (mr *MockIHeimdallClientMockRecorder) Span(arg0 interface{}) *gomock.Call {
|
func (mr *MockIHeimdallClientMockRecorder) Span(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockIHeimdallClient)(nil).Span), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockIHeimdallClient)(nil).Span), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateSyncEvents mocks base method.
|
// StateSyncEvents mocks base method.
|
||||||
func (m *MockIHeimdallClient) StateSyncEvents(arg0 uint64, arg1 int64) ([]*clerk.EventRecordWithTime, error) {
|
func (m *MockIHeimdallClient) StateSyncEvents(arg0 context.Context, arg1 uint64, arg2 int64) ([]*clerk.EventRecordWithTime, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1)
|
ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*clerk.EventRecordWithTime)
|
ret0, _ := ret[0].([]*clerk.EventRecordWithTime)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateSyncEvents indicates an expected call of StateSyncEvents.
|
// StateSyncEvents indicates an expected call of StateSyncEvents.
|
||||||
func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue