Skip to content

Commit

Permalink
Adhere to ETH1 Follow Distance (#5941)
Browse files Browse the repository at this point in the history
* finally get it working
* Update beacon-chain/powchain/service_test.go
* Merge refs/heads/v0.12 into eth1Fixes
* fix test
* Merge branch 'eth1Fixes' of https://github.com/prysmaticlabs/geth-sharding into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
* Merge refs/heads/v0.12 into eth1Fixes
  • Loading branch information
nisdas committed May 22, 2020
1 parent 5de09b0 commit 1f20629
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 21 deletions.
22 changes: 14 additions & 8 deletions beacon-chain/powchain/log_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -284,15 +283,19 @@ func (s *Service) processPastLogs(ctx context.Context) error {
}
return nil
}
for currentBlockNum < s.LatestBlockHeight().Uint64() {
latestFollowHeight, err := s.followBlockHeight(ctx)
if err != nil {
return err
}
for currentBlockNum < latestFollowHeight {
// stop requesting, if we have all the logs
if logCount == uint64(s.lastReceivedMerkleIndex+1) {
break
}
start := currentBlockNum
end := currentBlockNum + eth1HeaderReqLimit
if end > s.LatestBlockHeight().Uint64() {
end = s.LatestBlockHeight().Uint64()
if end > latestFollowHeight {
end = latestFollowHeight
}
query := ethereum.FilterQuery{
Addresses: []common.Address{
Expand All @@ -303,9 +306,9 @@ func (s *Service) processPastLogs(ctx context.Context) error {
}
remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1)
// only change the end block if the remaining logs are below the required log limit.
if remainingLogs < depositlogRequestLimit && end >= s.LatestBlockHeight().Uint64() {
query.ToBlock = s.LatestBlockHeight()
end = s.LatestBlockHeight().Uint64()
if remainingLogs < depositlogRequestLimit && end >= latestFollowHeight {
query.ToBlock = big.NewInt(int64(latestFollowHeight))
end = latestFollowHeight
}
logs, err := s.httpLogger.FilterLogs(ctx, query)
if err != nil {
Expand Down Expand Up @@ -355,7 +358,10 @@ func (s *Service) requestBatchedLogs(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.

requestedBlock := s.latestEth1Data.BlockHeight - uint64(params.BeaconConfig().LogBlockDelay)
requestedBlock, err := s.followBlockHeight(ctx)
if err != nil {
return err
}
for i := s.latestEth1Data.LastRequestedBlock + 1; i <= requestedBlock; i++ {
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
if err != nil {
Expand Down
15 changes: 10 additions & 5 deletions beacon-chain/powchain/log_processing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,18 +488,18 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
}
web3Service.rpcClient = &mockPOW.RPCClient{Backend: testAcc.Backend}
web3Service.httpLogger = testAcc.Backend
web3Service.blockFetcher = &goodFetcher{backend: testAcc.Backend}
web3Service.latestEth1Data.LastRequestedBlock = 0
web3Service.latestEth1Data.BlockHeight = 0
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
params.SetupTestConfigCleanup(t)
bConfig := params.MinimalSpecConfig()
bConfig.MinGenesisTime = 0
bConfig.SecondsPerETH1Block = 10
params.OverrideBeaconConfig(bConfig)
flags.Get().DeploymentBlock = 0

testAcc.Backend.Commit()
if err := testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond()))); err != nil {
t.Fatal(err)
}

totalNumOfDeposits := depositsReqForChainStart + 30

Expand Down Expand Up @@ -529,7 +529,12 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
testAcc.Backend.Commit()
}
}
// Forward the chain to account for the follow distance
for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ {
testAcc.Backend.Commit()
}
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()

// Set up our subscriber now to listen for the chain started event.
stateChannel := make(chan *feed.Event, 1)
Expand Down Expand Up @@ -726,7 +731,7 @@ func TestConsistentGenesisState(t *testing.T) {
testAcc.Backend.Commit()
}

for i := 0; i < int(params.BeaconConfig().LogBlockDelay); i++ {
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
testAcc.Backend.Commit()
}

Expand Down
30 changes: 28 additions & 2 deletions beacon-chain/powchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,32 @@ func (s *Service) AreAllDepositsProcessed() (bool, error) {
return true, nil
}

// refers to the latest eth1 block which follows the condition: eth1_timestamp +
// SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= current_unix_time
func (s *Service) followBlockHeight(ctx context.Context) (uint64, error) {
latestValidBlock := uint64(0)
if s.latestEth1Data.BlockHeight > params.BeaconConfig().Eth1FollowDistance {
latestValidBlock = s.latestEth1Data.BlockHeight - params.BeaconConfig().Eth1FollowDistance
}
blockTime, err := s.BlockTimeByHeight(ctx, big.NewInt(int64(latestValidBlock)))
if err != nil {
return 0, err
}
followTime := func(t uint64) uint64 {
return t + params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().SecondsPerETH1Block
}
for followTime(blockTime) > s.latestEth1Data.BlockTime && latestValidBlock > 0 {
// reduce block height to get eth1 block which
// fulfills stated condition
latestValidBlock--
blockTime, err = s.BlockTimeByHeight(ctx, big.NewInt(int64(latestValidBlock)))
if err != nil {
return 0, err
}
}
return latestValidBlock, nil
}

func (s *Service) connectToPowChain() error {
powClient, httpClient, rpcClient, err := s.dialETH1Nodes()
if err != nil {
Expand Down Expand Up @@ -521,7 +547,7 @@ func safelyHandlePanic() {
}
}

func (s *Service) handleDelayTicker() {
func (s *Service) handleETH1FollowDistance() {
defer safelyHandlePanic()

// use a 5 minutes timeout for block time, because the max mining time is 278 sec (block 7208027)
Expand Down Expand Up @@ -653,7 +679,7 @@ func (s *Service) run(done <-chan struct{}) {
s.processSubscribedHeaders(header)
}
case <-ticker.C:
s.handleDelayTicker()
s.handleETH1FollowDistance()
}
}
}
63 changes: 63 additions & 0 deletions beacon-chain/powchain/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"
"time"

"github.com/prysmaticlabs/prysm/shared/params"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -259,6 +260,68 @@ func TestStop_OK(t *testing.T) {
hook.Reset()
}

func TestFollowBlock_OK(t *testing.T) {
depositcontract.Amount32Eth()
testAcc, err := contracts.Setup()
if err != nil {
t.Fatalf("Unable to set up simulated backend %v", err)
}
beaconDB := dbutil.SetupDB(t)
web3Service, err := NewService(context.Background(), &Web3ServiceConfig{
ETH1Endpoint: endpoint,
DepositContract: testAcc.ContractAddr,
BeaconDB: beaconDB,
})
if err != nil {
t.Fatalf("unable to setup web3 ETH1.0 chain service: %v", err)
}

// simulated backend sets eth1 block
// time as 10 seconds
conf := params.BeaconConfig()
conf.SecondsPerETH1Block = 10
params.OverrideBeaconConfig(conf)
defer func() {
params.UseMainnetConfig()
}()

web3Service = setDefaultMocks(web3Service)
web3Service.blockFetcher = &goodFetcher{backend: testAcc.Backend}
baseHeight := testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
// process follow_distance blocks
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
testAcc.Backend.Commit()
}
// set current height
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()

h, err := web3Service.followBlockHeight(context.Background())
if err != nil {
t.Fatal(err)
}
if h != baseHeight {
t.Errorf("Unexpected block height of %d received instead of %d", h, baseHeight)
}
numToForward := uint64(2)
expectedHeight := numToForward + baseHeight
// forward 2 blocks
for i := uint64(0); i < numToForward; i++ {
testAcc.Backend.Commit()
}
// set current height
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()

h, err = web3Service.followBlockHeight(context.Background())
if err != nil {
t.Fatal(err)
}
if h != expectedHeight {
t.Errorf("Unexpected block height of %d received instead of %d", h, expectedHeight)
}
}

func TestInitDataFromContract_OK(t *testing.T) {
testAcc, err := contracts.Setup()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/beacon/validators_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ func (is *infostream) depositQueueTimestamp(eth1BlockNumber *big.Int) (uint64, e
}
is.eth1BlocktimesMutex.Unlock()

followTime := time.Duration(params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().GoerliBlockTime) * time.Second
followTime := time.Duration(params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().SecondsPerETH1Block) * time.Second
eth1UnixTime := time.Unix(int64(blockTimestamp), 0).Add(followTime)

period := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().EpochsPerEth1VotingPeriod
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/rpc/validator/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (vs *Server) depositBlockSlot(ctx context.Context, eth1BlockNumBigInt *big.
if err != nil {
return 0, err
}
followTime := time.Duration(params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().GoerliBlockTime) * time.Second
followTime := time.Duration(params.BeaconConfig().Eth1FollowDistance*params.BeaconConfig().SecondsPerETH1Block) * time.Second
eth1UnixTime := time.Unix(int64(blockTimeStamp), 0).Add(followTime)
period := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().EpochsPerEth1VotingPeriod
votingPeriod := time.Duration(period*params.BeaconConfig().SecondsPerSlot) * time.Second
Expand Down
4 changes: 0 additions & 4 deletions shared/params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,13 @@ type BeaconChainConfig struct {

// Prysm constants.
GweiPerEth uint64 // GweiPerEth is the amount of gwei corresponding to 1 eth.
LogBlockDelay int64 // Number of blocks to wait from the current head before processing logs from the deposit contract.
BLSSecretKeyLength int // BLSSecretKeyLength defines the expected length of BLS secret keys in bytes.
BLSPubkeyLength int // BLSPubkeyLength defines the expected length of BLS public keys in bytes.
BLSSignatureLength int // BLSSignatureLength defines the expected length of BLS signatures in bytes.
DefaultBufferSize int // DefaultBufferSize for channels across the Prysm repository.
ValidatorPrivkeyFileName string // ValidatorPrivKeyFileName specifies the string name of a validator private key file.
WithdrawalPrivkeyFileName string // WithdrawalPrivKeyFileName specifies the string name of a withdrawal private key file.
RPCSyncCheck time.Duration // Number of seconds to query the sync service, to find out if the node is synced or not.
GoerliBlockTime uint64 // GoerliBlockTime is the number of seconds on avg a Goerli block is created.
EmptySignature [96]byte // EmptySignature is used to represent a zeroed out BLS Signature.
DefaultPageSize int // DefaultPageSize defines the default page size for RPC server request.
MaxPeersToSync int // MaxPeersToSync describes the limit for number of peers in round robin sync.
Expand Down Expand Up @@ -191,15 +189,13 @@ var defaultBeaconConfig = &BeaconChainConfig{

// Prysm constants.
GweiPerEth: 1000000000,
LogBlockDelay: 4,
BLSSecretKeyLength: 32,
BLSPubkeyLength: 48,
BLSSignatureLength: 96,
DefaultBufferSize: 10000,
WithdrawalPrivkeyFileName: "/shardwithdrawalkey",
ValidatorPrivkeyFileName: "/validatorprivatekey",
RPCSyncCheck: 1,
GoerliBlockTime: 14, // 14 seconds on average for a goerli block to be created.
EmptySignature: [96]byte{},
DefaultPageSize: 250,
MaxPeersToSync: 15,
Expand Down

0 comments on commit 1f20629

Please sign in to comment.