Compare commits

...

2 Commits

Author SHA1 Message Date
Nishant Das
6c09424feb Initialize Data Correctly For Powchain Service (#8812)
* initialize index correctly

* comments

* review comments

* Update beacon-chain/powchain/service.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-04-25 00:11:54 -05:00
Preston Van Loon
a45b04543a Independent eth1 voting (#8811) 2021-04-24 20:33:29 -05:00
6 changed files with 163 additions and 35 deletions

View File

@@ -76,6 +76,8 @@ http_archive(
http_archive(
name = "io_bazel_rules_docker",
patch_args = ["-p1"],
patches = ["//third_party:rules_docker_bad_checksum.patch"],
sha256 = "1286175a94c0b1335efe1d75d22ea06e89742557d3fac2a0366f242a6eac6f5a",
strip_prefix = "rules_docker-ba4310833230294fa69b7d6ea1787ac684631a7d",
urls = ["https://github.com/bazelbuild/rules_docker/archive/ba4310833230294fa69b7d6ea1787ac684631a7d.tar.gz"],

View File

@@ -4,6 +4,7 @@
package powchain
import (
"bytes"
"context"
"fmt"
"math/big"
@@ -220,20 +221,8 @@ func NewService(ctx context.Context, config *Web3ServiceConfig) (*Service, error
if err != nil {
return nil, errors.Wrap(err, "unable to retrieve eth1 data")
}
if eth1Data != nil {
s.depositTrie = trieutil.CreateTrieFromProto(eth1Data.Trie)
s.chainStartData = eth1Data.ChainstartData
if !reflect.ValueOf(eth1Data.BeaconState).IsZero() {
s.preGenesisState, err = stateV0.InitializeFromProto(eth1Data.BeaconState)
if err != nil {
return nil, errors.Wrap(err, "Could not initialize state trie")
}
}
s.latestEth1Data = eth1Data.CurrentEth1Data
s.lastReceivedMerkleIndex = int64(len(s.depositTrie.Items()) - 1)
if err := s.initDepositCaches(ctx, eth1Data.DepositContainers); err != nil {
return nil, errors.Wrap(err, "could not initialize caches")
}
if err := s.initializeEth1Data(ctx, eth1Data); err != nil {
return nil, err
}
return s, nil
}
@@ -936,6 +925,53 @@ func (s *Service) fallbackToNextEndpoint() {
log.Infof("Falling back to alternative endpoint: %s", logutil.MaskCredentialsLogging(s.currHttpEndpoint.Url))
}
// initializes our service from the provided eth1data object by initializing all the relevant
// fields and data.
func (s *Service) initializeEth1Data(ctx context.Context, eth1DataInDB *protodb.ETH1ChainData) error {
// The node has no eth1data persisted on disk, so we exit and instead
// request from contract logs.
if eth1DataInDB == nil {
return nil
}
s.depositTrie = trieutil.CreateTrieFromProto(eth1DataInDB.Trie)
s.chainStartData = eth1DataInDB.ChainstartData
var err error
if !reflect.ValueOf(eth1DataInDB.BeaconState).IsZero() {
s.preGenesisState, err = stateV0.InitializeFromProto(eth1DataInDB.BeaconState)
if err != nil {
return errors.Wrap(err, "Could not initialize state trie")
}
}
s.latestEth1Data = eth1DataInDB.CurrentEth1Data
items := s.depositTrie.Items()
s.lastReceivedMerkleIndex = int64(len(items) - 1)
// Account for 0 elements existing in the deposit trie.
if len(items) == 1 && bytes.Equal(items[0], params.BeaconConfig().ZeroHash[:]) {
s.lastReceivedMerkleIndex = -1
}
if err := s.initDepositCaches(ctx, eth1DataInDB.DepositContainers); err != nil {
return errors.Wrap(err, "could not initialize caches")
}
return nil
}
// validates that all deposit containers are valid and have their relevant indices
// in order.
func (s *Service) validateDepositContainers(ctrs []*protodb.DepositContainer) bool {
ctrLen := len(ctrs)
// Exit for empty containers.
if ctrLen == 0 {
return true
}
for _, c := range ctrs {
if c.Index == 0 {
return true
}
}
log.Info("Recovering missing deposit containers, node is re-requesting missing deposit data")
return false
}
// validates the current powchain data saved and makes sure that any
// embedded genesis state is correctly accounted for.
func (s *Service) ensureValidPowchainData(ctx context.Context) error {
@@ -951,7 +987,7 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error {
if err != nil {
return errors.Wrap(err, "unable to retrieve eth1 data")
}
if eth1Data == nil || !eth1Data.ChainstartData.Chainstarted {
if eth1Data == nil || !eth1Data.ChainstartData.Chainstarted || !s.validateDepositContainers(eth1Data.DepositContainers) {
pbState, err := stateV0.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe())
if err != nil {
return err

View File

@@ -620,6 +620,83 @@ func TestService_EnsureConsistentPowchainData(t *testing.T) {
assert.Equal(t, true, eth1Data.ChainstartData.Chainstarted)
}
func TestService_InitializeCorrectly(t *testing.T) {
beaconDB := dbutil.SetupDB(t)
cache, err := depositcache.New()
require.NoError(t, err)
s1, err := NewService(context.Background(), &Web3ServiceConfig{
BeaconDB: beaconDB,
DepositCache: cache,
})
require.NoError(t, err)
genState, err := testutil.NewBeaconState()
require.NoError(t, err)
assert.NoError(t, genState.SetSlot(1000))
require.NoError(t, s1.cfg.BeaconDB.SaveGenesisData(context.Background(), genState))
require.NoError(t, s1.ensureValidPowchainData(context.Background()))
eth1Data, err := s1.cfg.BeaconDB.PowchainData(context.Background())
assert.NoError(t, err)
assert.NoError(t, s1.initializeEth1Data(context.Background(), eth1Data))
assert.Equal(t, int64(-1), s1.lastReceivedMerkleIndex, "received incorrect last received merkle index")
}
func TestService_EnsureValidPowchainData(t *testing.T) {
beaconDB := dbutil.SetupDB(t)
cache, err := depositcache.New()
require.NoError(t, err)
s1, err := NewService(context.Background(), &Web3ServiceConfig{
BeaconDB: beaconDB,
DepositCache: cache,
})
require.NoError(t, err)
genState, err := testutil.NewBeaconState()
require.NoError(t, err)
assert.NoError(t, genState.SetSlot(1000))
require.NoError(t, s1.cfg.BeaconDB.SaveGenesisData(context.Background(), genState))
err = s1.cfg.BeaconDB.SavePowchainData(context.Background(), &protodb.ETH1ChainData{
ChainstartData: &protodb.ChainStartData{Chainstarted: true},
DepositContainers: []*protodb.DepositContainer{{Index: 1}},
})
require.NoError(t, err)
require.NoError(t, s1.ensureValidPowchainData(context.Background()))
eth1Data, err := s1.cfg.BeaconDB.PowchainData(context.Background())
assert.NoError(t, err)
assert.NotNil(t, eth1Data)
assert.Equal(t, 0, len(eth1Data.DepositContainers))
}
func TestService_ValidateDepositContainers(t *testing.T) {
beaconDB := dbutil.SetupDB(t)
cache, err := depositcache.New()
require.NoError(t, err)
s1, err := NewService(context.Background(), &Web3ServiceConfig{
BeaconDB: beaconDB,
DepositCache: cache,
})
require.NoError(t, err)
ctrs := make([]*protodb.DepositContainer, 0)
assert.Equal(t, true, s1.validateDepositContainers(ctrs))
for i := 0; i < 10; i++ {
ctrs = append(ctrs, &protodb.DepositContainer{Index: int64(i), Eth1BlockHeight: uint64(i + 10)})
}
assert.Equal(t, true, s1.validateDepositContainers(ctrs))
ctrs = make([]*protodb.DepositContainer, 0)
for i := 1; i < 10; i++ {
ctrs = append(ctrs, &protodb.DepositContainer{Index: int64(i), Eth1BlockHeight: uint64(i + 10)})
}
assert.Equal(t, false, s1.validateDepositContainers(ctrs))
}
func TestTimestampIsChecked(t *testing.T) {
timestamp := uint64(time.Now().Unix())
assert.Equal(t, false, eth1HeadIsBehind(timestamp))

View File

@@ -229,28 +229,19 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState iface.Be
return vs.ChainStartFetcher.ChainStartEth1Data(), nil
}
inRangeVotes, err := vs.inRangeVotes(ctx, beaconState, lastBlockByEarliestValidTime.Number, lastBlockByLatestValidTime.Number)
if err != nil {
return nil, err
}
if len(inRangeVotes) == 0 {
if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
if err != nil {
log.WithError(err).Error("Could not get hash of last block by latest valid time")
return vs.randomETH1DataVote(ctx)
}
return &ethpb.Eth1Data{
BlockHash: hash.Bytes(),
DepositCount: lastBlockDepositCount,
DepositRoot: lastBlockDepositRoot[:],
}, nil
if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime.Number)
if err != nil {
log.WithError(err).Error("Could not get hash of last block by latest valid time")
return vs.randomETH1DataVote(ctx)
}
return vs.HeadFetcher.HeadETH1Data(), nil
return &ethpb.Eth1Data{
BlockHash: hash.Bytes(),
DepositCount: lastBlockDepositCount,
DepositRoot: lastBlockDepositRoot[:],
}, nil
}
chosenVote := chosenEth1DataMajorityVote(inRangeVotes)
return &chosenVote.data.eth1Data, nil
return vs.HeadFetcher.HeadETH1Data(), nil
}
func (vs *Server) slotStartTime(slot types.Slot) uint64 {

View File

@@ -1092,6 +1092,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
depositCache.InsertDeposit(context.Background(), dc.Deposit, dc.Eth1BlockHeight, dc.Index, depositTrie.Root())
t.Run("choose highest count", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1128,6 +1129,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count at earliest valid time - choose highest count", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(52, earliestValidTime+2, []byte("second")).
@@ -1163,6 +1165,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count at latest valid time - choose highest count", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1198,6 +1201,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count before range - choose highest count within range", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(49, earliestValidTime-1, []byte("before_range")).
InsertBlock(50, earliestValidTime, []byte("earliest")).
@@ -1234,6 +1238,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count after range - choose highest count within range", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1270,6 +1275,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count on unknown block - choose known block with highest count", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1433,6 +1439,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("same count - choose more recent block", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1468,6 +1475,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("highest count on block with less deposits - choose another block", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().
InsertBlock(50, earliestValidTime, []byte("earliest")).
InsertBlock(51, earliestValidTime+1, []byte("first")).
@@ -1504,6 +1512,7 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
})
t.Run("only one block at earliest valid time - choose this block", func(t *testing.T) {
t.Skip()
p := mockPOW.NewPOWChain().InsertBlock(50, earliestValidTime, []byte("earliest"))
beaconState, err := stateV0.InitializeFromProto(&pbp2p.BeaconState{

View File

@@ -0,0 +1,13 @@
diff --git a/repositories/go_repositories.bzl b/repositories/go_repositories.bzl
index 58054f7..12e93eb 100644
--- a/repositories/go_repositories.bzl
+++ b/repositories/go_repositories.bzl
@@ -39,7 +39,7 @@ def go_deps():
name = "com_github_google_go_containerregistry",
urls = ["https://api.github.com/repos/google/go-containerregistry/tarball/8a2841911ffee4f6892ca0083e89752fb46c48dd"], # v0.1.4
strip_prefix = "google-go-containerregistry-8a28419",
- sha256 = "60b9a600affa5667bd444019a4e218b7752d8500cfa923c1ac54ce2f88f773e2",
+ sha256 = "cadb09cb5bcbe00688c73d716d1c9e774d6e4959abec4c425a1b995faf33e964",
importpath = "github.com/google/go-containerregistry",
type = "tar.gz",
)