Skip to content

Commit

Permalink
p2p/sentry: sentry doesn't start with ErrNoHead (#10454) (#10523)
Browse files Browse the repository at this point in the history
cherry-pick #10494 to
release/2.60
  • Loading branch information
battlmonstr authored May 28, 2024
1 parent e9840ad commit 9501f93
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 15 deletions.
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

0 comments on commit 9501f93

Please sign in to comment.