Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

p2p/sentry: sentry doesn't start with ErrNoHead (#10454) #10523

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/integration/commands/stages.go
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig,
chainConfig,
genesisBlock,
chainConfig.ChainID.Uint64(),
logger,
)

maxBlockBroadcastPeers := func(header *types.Header) uint { return 0 }
Expand Down
1 change: 1 addition & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger
chainConfig,
genesis,
backend.config.NetworkID,
logger,
)

// limit "new block" broadcasts to at most 10 random peers at time
Expand Down
4 changes: 1 addition & 3 deletions p2p/sentry/sentry_multi_client/sentry_multi_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ func SentryReconnectAndPumpStreamLoop[TMessage interface{}](
statusData, err := statusDataFactory(ctx)

if err != nil {
if !errors.Is(err, sentry.ErrNoHead) {
logger.Error("SentryReconnectAndPumpStreamLoop: statusDataFactory error", "stream", streamName, "err", err)
}
logger.Error("SentryReconnectAndPumpStreamLoop: statusDataFactory error", "stream", streamName, "err", err)
time.Sleep(time.Second)
continue
}
Expand Down
53 changes: 41 additions & 12 deletions p2p/sentry/status_data_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/big"

"github.com/holiman/uint256"
"github.com/ledgerwatch/log/v3"

"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
Expand All @@ -32,27 +33,59 @@ type StatusDataProvider struct {

networkId uint64
genesisHash libcommon.Hash
genesisHead ChainHead
heightForks []uint64
timeForks []uint64

logger log.Logger
}

func NewStatusDataProvider(
db kv.RoDB,
chainConfig *chain.Config,
genesis *types.Block,
networkId uint64,
logger log.Logger,
) *StatusDataProvider {
s := &StatusDataProvider{
db: db,
networkId: networkId,
genesisHash: genesis.Hash(),
genesisHead: makeGenesisChainHead(genesis),
logger: logger,
}

s.heightForks, s.timeForks = forkid.GatherForks(chainConfig, genesis.Time())

return s
}

func uint256FromBigInt(num *big.Int) (*uint256.Int, error) {
if num == nil {
num = new(big.Int)
}
num256 := new(uint256.Int)
overflow := num256.SetFromBig(num)
if overflow {
return nil, fmt.Errorf("uint256FromBigInt: big.Int greater than 2^256-1")
}
return num256, nil
}

func makeGenesisChainHead(genesis *types.Block) ChainHead {
genesisDifficulty, err := uint256FromBigInt(genesis.Difficulty())
if err != nil {
panic(fmt.Errorf("makeGenesisChainHead: difficulty conversion error: %w", err))
}

return ChainHead{
HeadHeight: genesis.NumberU64(),
HeadTime: genesis.Time(),
HeadHash: genesis.Hash(),
HeadTd: genesisDifficulty,
}
}

func (s *StatusDataProvider) makeStatusData(head ChainHead) *proto_sentry.StatusData {
return &proto_sentry.StatusData{
NetworkId: s.networkId,
Expand All @@ -71,6 +104,10 @@ func (s *StatusDataProvider) makeStatusData(head ChainHead) *proto_sentry.Status
func (s *StatusDataProvider) GetStatusData(ctx context.Context) (*proto_sentry.StatusData, error) {
chainHead, err := ReadChainHead(ctx, s.db)
if err != nil {
if errors.Is(err, ErrNoHead) {
s.logger.Warn("sentry.StatusDataProvider: The canonical chain current header not found in the database. Check the database consistency. Using genesis as a fallback.")
return s.makeStatusData(s.genesisHead), nil
}
return nil, err
}
return s.makeStatusData(chainHead), err
Expand All @@ -84,23 +121,15 @@ func ReadChainHeadWithTx(tx kv.Tx) (ChainHead, error) {

height := header.Number.Uint64()
hash := header.Hash()

var time uint64
if header != nil {
time = header.Time
}
time := header.Time

td, err := rawdb.ReadTd(tx, hash, height)
if err != nil {
return ChainHead{}, fmt.Errorf("ReadChainHead: ReadTd error at height %d and hash %s: %w", height, hash, err)
}
if td == nil {
td = new(big.Int)
}
td256 := new(uint256.Int)
overflow := td256.SetFromBig(td)
if overflow {
return ChainHead{}, fmt.Errorf("ReadChainHead: total difficulty higher than 2^256-1")
td256, err := uint256FromBigInt(td)
if err != nil {
return ChainHead{}, fmt.Errorf("ReadChainHead: total difficulty conversion error: %w", err)
}

return ChainHead{height, time, hash, td256}, nil
Expand Down
1 change: 1 addition & 0 deletions turbo/stages/mock/mock_sentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK
mock.ChainConfig,
mock.Genesis,
mock.ChainConfig.ChainID.Uint64(),
logger,
)

maxBlockBroadcastPeers := func(header *types.Header) uint { return 0 }
Expand Down
Loading