Add Eth1 Header Timestamp Check (#8771)

* add time check

* unit test

* fix

* Update beacon-chain/powchain/service.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
This commit is contained in:
Nishant Das
2021-04-17 21:55:41 +08:00
committed by GitHub
parent afc0ace624
commit cff7dbd015
2 changed files with 48 additions and 12 deletions

View File

@@ -59,17 +59,20 @@ var (
})
)
// time to wait before trying to reconnect with the eth1 node.
var backOffPeriod = 15 * time.Second
// Amount of times before we log the status of the eth1 dial attempt.
var logThreshold = 8
// period to log chainstart related information
var logPeriod = 1 * time.Minute
// error when eth1 node is not synced.
var errNotSynced = errors.New("eth1 node is still syncing")
var (
// time to wait before trying to reconnect with the eth1 node.
backOffPeriod = 15 * time.Second
// amount of times before we log the status of the eth1 dial attempt.
logThreshold = 8
// period to log chainstart related information
logPeriod = 1 * time.Minute
// threshold of how old we will accept an eth1 node's head to be.
eth1Threshold = 20 * time.Minute
// error when eth1 node is not synced.
errNotSynced = errors.New("eth1 node is still syncing")
// error when eth1 node is too far behind.
errFarBehind = errors.Errorf("eth1 head is more than %s behind from current wall clock time", eth1Threshold.String())
)
// ChainStartFetcher retrieves information pertaining to the chain start event
// of the beacon chain for usage across various services.
@@ -535,7 +538,14 @@ func (s *Service) isEth1NodeSynced() (bool, error) {
if err != nil {
return false, err
}
return syncProg == nil, nil
if syncProg != nil {
return false, nil
}
head, err := s.eth1DataFetcher.HeaderByNumber(s.ctx, nil)
if err != nil {
return false, err
}
return !eth1HeadIsBehind(head.Time), nil
}
// Reconnect to eth1 node in case of any failure.
@@ -777,6 +787,11 @@ func (s *Service) run(done <-chan struct{}) {
s.retryETH1Node(err)
continue
}
if eth1HeadIsBehind(head.Time) {
log.WithError(errFarBehind).Debug("Could not get an up to date eth1 header")
s.retryETH1Node(errFarBehind)
continue
}
s.processBlockHeader(head)
s.handleETH1FollowDistance()
s.checkDefaultEndpoint()
@@ -972,3 +987,11 @@ func dedupEndpoints(endpoints []string) []string {
}
return newEndpoints
}
// Checks if the provided timestamp is beyond the prescribed bound from
// the current wall clock time.
func eth1HeadIsBehind(timestamp uint64) bool {
timeout := timeutils.Now().Add(-eth1Threshold)
// check that web3 client is syncing
return time.Unix(int64(timestamp), 0).Before(timeout)
}

View File

@@ -278,7 +278,11 @@ func TestService_Eth1Synced(t *testing.T) {
web3Service = setDefaultMocks(web3Service)
web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend)
require.NoError(t, err)
web3Service.eth1DataFetcher = &goodFetcher{backend: testAcc.Backend}
currTime := testAcc.Backend.Blockchain().CurrentHeader().Time
now := time.Now()
assert.NoError(t, testAcc.Backend.AdjustTime(now.Sub(time.Unix(int64(currTime), 0))))
testAcc.Backend.Commit()
synced, err := web3Service.isEth1NodeSynced()
@@ -615,3 +619,12 @@ func TestService_EnsureConsistentPowchainData(t *testing.T) {
assert.NotNil(t, eth1Data)
assert.Equal(t, true, eth1Data.ChainstartData.Chainstarted)
}
func TestTimestampIsChecked(t *testing.T) {
timestamp := uint64(time.Now().Unix())
assert.Equal(t, false, eth1HeadIsBehind(timestamp))
// Give an older timestmap beyond threshold.
timestamp = uint64(time.Now().Add(-eth1Threshold).Add(-1 * time.Minute).Unix())
assert.Equal(t, true, eth1HeadIsBehind(timestamp))
}