Skip to content

Commit

Permalink
Cache ETH1 Headers When Requesting Logs (#7861)
Browse files Browse the repository at this point in the history
* perform a quick patch

* perform a quick patch

* fix

* fix up

* Update beacon-chain/powchain/service.go

* start caching from here

* remove

* fix
  • Loading branch information
nisdas committed Nov 19, 2020
1 parent 4b6441f commit c3451a6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 17 deletions.
13 changes: 9 additions & 4 deletions beacon-chain/powchain/log_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,9 @@ func (s *Service) processPastLogs(ctx context.Context) error {
return nil
}

// requestBatchedLogs requests and processes all the logs from the period
// last polled to now.
func (s *Service) requestBatchedLogs(ctx context.Context) error {
// requestBatchedHeadersAndLogs requests and processes all the headers and
// logs from the period last polled to now.
func (s *Service) requestBatchedHeadersAndLogs(ctx context.Context) error {
// We request for the nth block behind the current head, in order to have
// stabilized logs when we retrieve it from the 1.0 chain.

Expand All @@ -361,7 +361,12 @@ func (s *Service) requestBatchedLogs(ctx context.Context) error {
return err
}
for i := s.latestEth1Data.LastRequestedBlock + 1; i <= requestedBlock; i++ {
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
// Cache eth1 block header here.
_, err := s.BlockHashByHeight(ctx, big.NewInt(int64(i)))
if err != nil {
return err
}
err = s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
if err != nil {
return err
}
Expand Down
53 changes: 40 additions & 13 deletions beacon-chain/powchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
Expand Down Expand Up @@ -643,7 +644,7 @@ func (s *Service) handleETH1FollowDistance() {
log.Error("Beacon node is not respecting the follow distance")
return
}
if err := s.requestBatchedLogs(ctx); err != nil {
if err := s.requestBatchedHeadersAndLogs(ctx); err != nil {
s.runError = err
log.Error(err)
return
Expand Down Expand Up @@ -681,7 +682,11 @@ func (s *Service) initPOWService() {
continue
}
// Cache eth1 headers from our voting period.
s.cacheHeadersForEth1DataVote(ctx)
if err := s.cacheHeadersForEth1DataVote(ctx); err != nil {
log.Errorf("Unable to process past headers %v", err)
s.retryETH1Node(err)
continue
}
return
}
}
Expand Down Expand Up @@ -756,23 +761,45 @@ func (s *Service) logTillChainStart() {

// cacheHeadersForEth1DataVote makes sure that voting for eth1data after startup utilizes cached headers
// instead of making multiple RPC requests to the ETH1 endpoint.
func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) {
blocksPerVotingPeriod := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch *
params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().SecondsPerETH1Block

func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error {
// Find the end block to request from.
end, err := s.followBlockHeight(ctx)
if err != nil {
log.Errorf("Unable to fetch height of follow block: %v", err)
return err
}

// We fetch twice the number of headers just to be safe.
start := uint64(0)
if end >= 2*blocksPerVotingPeriod {
start = end - 2*blocksPerVotingPeriod
start, err := s.determineEarliestVotingBlock(ctx, end)
if err != nil {
return err
}
// We call batchRequestHeaders for its header caching side-effect, so we don't need the return value.
_, err = s.batchRequestHeaders(start, end)
if err != nil {
log.Errorf("Unable to cache headers: %v", err)
return err
}
return nil
}

// determines the earliest voting block from which to start caching all our previous headers from.
func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock uint64) (uint64, error) {
genesisTime := s.chainStartData.GenesisTime
// In the event genesis has not occurred yet, we just request go back follow_distance blocks.
if genesisTime == 0 {
earliestBlk := uint64(0)
if followBlock > params.BeaconConfig().Eth1FollowDistance {
earliestBlk = followBlock - params.BeaconConfig().Eth1FollowDistance
}
return earliestBlk, nil
}
currSlot := helpers.CurrentSlot(genesisTime)
votingTime := helpers.VotingPeriodStartTime(genesisTime, currSlot)
followBackDist := 2 * params.BeaconConfig().SecondsPerETH1Block * params.BeaconConfig().Eth1FollowDistance
if followBackDist > votingTime {
return 0, errors.Errorf("invalid genesis time provided. %d > %d", followBackDist, votingTime)
}
earliestValidTime := votingTime - followBackDist
blkNum, err := s.BlockNumberByTimestamp(ctx, earliestValidTime)
if err != nil {
return 0, err
}
return blkNum.Uint64(), nil
}

0 comments on commit c3451a6

Please sign in to comment.