mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-11 06:18:05 -05:00
Compare commits
1 Commits
copyOnWrit
...
e2ez
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08aff8f60f |
13
BUILD.bazel
13
BUILD.bazel
@@ -115,19 +115,18 @@ nogo(
|
||||
"@org_golang_x_tools//go/analysis/passes/assign:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/inspect:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_default_library",
|
||||
"//tools/analyzers/comparesame:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/cryptorand:go_default_library",
|
||||
"//tools/analyzers/errcheck:go_default_library",
|
||||
"//tools/analyzers/featureconfig:go_default_library",
|
||||
"//tools/analyzers/gocognit:go_default_library",
|
||||
"//tools/analyzers/ineffassign:go_default_library",
|
||||
"//tools/analyzers/interfacechecker:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/comparesame:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
"//tools/analyzers/nop:go_default_library",
|
||||
"//tools/analyzers/slicedirect:go_default_library",
|
||||
"//tools/analyzers/interfacechecker:go_default_library",
|
||||
"//tools/analyzers/ineffassign:go_default_library",
|
||||
"//tools/analyzers/properpermissions:go_default_library",
|
||||
"//tools/analyzers/recursivelock:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
"//tools/analyzers/slicedirect:go_default_library",
|
||||
"//tools/analyzers/uintcast:go_default_library",
|
||||
] + select({
|
||||
# nogo checks that fail with coverage enabled.
|
||||
|
||||
@@ -176,7 +176,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.17.9",
|
||||
go_version = "1.17.6",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ go_library(
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
|
||||
@@ -273,13 +273,13 @@ func (s *Service) CurrentFork() *ethpb.Fork {
|
||||
|
||||
// IsCanonical returns true if the input block root is part of the canonical chain.
|
||||
func (s *Service) IsCanonical(ctx context.Context, blockRoot [32]byte) (bool, error) {
|
||||
// If the block has not been finalized, check fork choice store to see if the block is canonical
|
||||
if s.cfg.ForkChoiceStore.HasNode(blockRoot) {
|
||||
return s.cfg.ForkChoiceStore.IsCanonical(blockRoot), nil
|
||||
// If the block has been finalized, the block will always be part of the canonical chain.
|
||||
if s.cfg.BeaconDB.IsFinalizedBlock(ctx, blockRoot) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If the block has been finalized, the block will always be part of the canonical chain.
|
||||
return s.cfg.BeaconDB.IsFinalizedBlock(ctx, blockRoot), nil
|
||||
// If the block has not been finalized, check fork choice store to see if the block is canonical
|
||||
return s.cfg.ForkChoiceStore.IsCanonical(blockRoot), nil
|
||||
}
|
||||
|
||||
// ChainHeads returns all possible chain heads (leaves of fork choice tree).
|
||||
|
||||
@@ -138,26 +138,6 @@ var (
|
||||
Name: "state_balance_cache_miss",
|
||||
Help: "Count the number of state balance cache hits.",
|
||||
})
|
||||
newPayloadValidNodeCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "new_payload_valid_node_count",
|
||||
Help: "Count the number of valid nodes after newPayload EE call",
|
||||
})
|
||||
newPayloadOptimisticNodeCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "new_payload_optimistic_node_count",
|
||||
Help: "Count the number of optimistic nodes after newPayload EE call",
|
||||
})
|
||||
newPayloadInvalidNodeCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "new_payload_invalid_node_count",
|
||||
Help: "Count the number of invalid nodes after newPayload EE call",
|
||||
})
|
||||
forkchoiceUpdatedValidNodeCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "forkchoice_updated_valid_node_count",
|
||||
Help: "Count the number of valid nodes after forkchoiceUpdated EE call",
|
||||
})
|
||||
forkchoiceUpdatedOptimisticNodeCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "forkchoice_updated_optimistic_node_count",
|
||||
Help: "Count the number of optimistic nodes after forkchoiceUpdated EE call",
|
||||
})
|
||||
)
|
||||
|
||||
// reportSlotMetrics reports slot related metrics.
|
||||
|
||||
@@ -83,18 +83,16 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, headState state.Be
|
||||
if err != nil {
|
||||
switch err {
|
||||
case powchain.ErrAcceptedSyncingPayloadStatus:
|
||||
forkchoiceUpdatedOptimisticNodeCount.Inc()
|
||||
log.WithFields(logrus.Fields{
|
||||
"headSlot": headBlk.Slot(),
|
||||
"headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash)),
|
||||
"finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash)),
|
||||
"headSlot": headBlk.Slot(),
|
||||
"headHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash)),
|
||||
"finalizedHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash)),
|
||||
}).Info("Called fork choice updated with optimistic block")
|
||||
return payloadID, nil
|
||||
default:
|
||||
return nil, errors.Wrap(err, "could not notify forkchoice update from execution engine")
|
||||
}
|
||||
}
|
||||
forkchoiceUpdatedValidNodeCount.Inc()
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, headRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set block to valid")
|
||||
}
|
||||
@@ -137,14 +135,12 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion, postSta
|
||||
if err != nil {
|
||||
switch err {
|
||||
case powchain.ErrAcceptedSyncingPayloadStatus:
|
||||
newPayloadOptimisticNodeCount.Inc()
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": blk.Block().Slot(),
|
||||
"payloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
|
||||
"slot": blk.Block().Slot(),
|
||||
"blockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
|
||||
}).Info("Called new payload with optimistic block")
|
||||
return false, nil
|
||||
case powchain.ErrInvalidPayloadStatus:
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
root, err := blk.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -161,7 +157,7 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion, postSta
|
||||
return false, errors.Wrap(err, "could not validate execution payload from execution engine")
|
||||
}
|
||||
}
|
||||
newPayloadValidNodeCount.Inc()
|
||||
|
||||
// During the transition event, the transition block should be verified for sanity.
|
||||
if blocks.IsPreBellatrixVersion(preStateVersion) {
|
||||
// Handle case where pre-state is Altair but block contains payload.
|
||||
|
||||
@@ -127,8 +127,8 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, signed.Block(), blockRoot, postState); err != nil {
|
||||
return errors.Wrapf(err, "could not insert block %d to fork choice store", signed.Block().Slot())
|
||||
if err := s.savePostStateInfo(ctx, blockRoot, signed, postState, false /* reg sync */); err != nil {
|
||||
return err
|
||||
}
|
||||
if isValidPayload {
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, blockRoot); err != nil {
|
||||
@@ -148,9 +148,6 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.savePostStateInfo(ctx, blockRoot, signed, postState, false /* reg sync */); err != nil {
|
||||
return err
|
||||
}
|
||||
// If slasher is configured, forward the attestations in the block via
|
||||
// an event feed for processing.
|
||||
if features.Get().EnableSlasher {
|
||||
@@ -612,6 +609,9 @@ func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b block.Sig
|
||||
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, b.Block(), r, st); err != nil {
|
||||
return errors.Wrapf(err, "could not insert block %d to fork choice store", b.Block().Slot())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
mathutil "github.com/prysmaticlabs/prysm/math"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
@@ -403,17 +402,10 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
// We update the cache up to the last deposit index in the finalized block's state.
|
||||
// We can be confident that these deposits will be included in some block
|
||||
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
|
||||
eth1DepositIndex, err := mathutil.Int(finalizedState.Eth1DepositIndex())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not cast eth1 deposit index")
|
||||
}
|
||||
// The deposit index in the state is always the index of the next deposit
|
||||
// to be included(rather than the last one to be processed). This was most likely
|
||||
// done as the state cannot represent signed integers.
|
||||
eth1DepositIndex -= 1
|
||||
s.cfg.DepositCache.InsertFinalizedDeposits(ctx, int64(eth1DepositIndex))
|
||||
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
|
||||
s.cfg.DepositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.cfg.DepositCache.PruneProofs(ctx, int64(eth1DepositIndex)); err != nil {
|
||||
if err = s.cfg.DepositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1516,7 +1516,6 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(8))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
@@ -1530,64 +1529,8 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
}
|
||||
assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}))
|
||||
fDeposits := depositCache.FinalizedDeposits(ctx)
|
||||
assert.Equal(t, 7, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
|
||||
deps := depositCache.AllDeposits(ctx, big.NewInt(107))
|
||||
for _, d := range deps {
|
||||
assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
opts := testServiceOptsWithDB(t)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
opts = append(opts, WithDepositCache(depositCache))
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
gs, _ := util.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 7}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(6))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
gs2 := gs.Copy()
|
||||
assert.NoError(t, gs2.SetEth1Data(ðpb.Eth1Data{DepositCount: 15}))
|
||||
assert.NoError(t, gs2.SetEth1DepositIndex(13))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}, gs2))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
root := []byte(strconv.Itoa(int(i)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, ðpb.Deposit{Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.FromBytes48([fieldparams.BLSPubkeyLength]byte{}),
|
||||
WithdrawalCredentials: params.BeaconConfig().ZeroHash[:],
|
||||
Amount: 0,
|
||||
Signature: zeroSig[:],
|
||||
}, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root)))
|
||||
}
|
||||
// Insert 3 deposits before hand.
|
||||
depositCache.InsertFinalizedDeposits(ctx, 2)
|
||||
|
||||
assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}))
|
||||
fDeposits := depositCache.FinalizedDeposits(ctx)
|
||||
assert.Equal(t, 5, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
|
||||
|
||||
deps := depositCache.AllDeposits(ctx, big.NewInt(105))
|
||||
for _, d := range deps {
|
||||
assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
|
||||
}
|
||||
|
||||
// Insert New Finalized State with higher deposit count.
|
||||
assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}))
|
||||
fDeposits = depositCache.FinalizedDeposits(ctx)
|
||||
assert.Equal(t, 12, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
|
||||
deps = depositCache.AllDeposits(ctx, big.NewInt(112))
|
||||
assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
|
||||
deps := depositCache.AllDeposits(ctx, big.NewInt(109))
|
||||
for _, d := range deps {
|
||||
assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestat
|
||||
func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) error {
|
||||
// A canonical root implies the root to has an ancestor that aligns with finalized check point.
|
||||
// In this case, we could exit early to save on additional computation.
|
||||
blockRoot := bytesutil.ToBytes32(root)
|
||||
if s.cfg.ForkChoiceStore.HasNode(blockRoot) && s.cfg.ForkChoiceStore.IsCanonical(blockRoot) {
|
||||
if s.cfg.ForkChoiceStore.IsCanonical(bytesutil.ToBytes32(root)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ type DepositFetcher interface {
|
||||
DepositByPubkey(ctx context.Context, pubKey []byte) (*ethpb.Deposit, *big.Int)
|
||||
DepositsNumberAndRootAtHeight(ctx context.Context, blockHeight *big.Int) (uint64, [32]byte)
|
||||
FinalizedDeposits(ctx context.Context) *FinalizedDeposits
|
||||
NonFinalizedDeposits(ctx context.Context, lastFinalizedIndex int64, untilBlk *big.Int) []*ethpb.Deposit
|
||||
NonFinalizedDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit
|
||||
}
|
||||
|
||||
// FinalizedDeposits stores the trie of deposits that have been included
|
||||
@@ -137,22 +137,6 @@ func (dc *DepositCache) InsertFinalizedDeposits(ctx context.Context, eth1Deposit
|
||||
|
||||
depositTrie := dc.finalizedDeposits.Deposits
|
||||
insertIndex := int(dc.finalizedDeposits.MerkleTrieIndex + 1)
|
||||
|
||||
// Don't insert into finalized trie if there is no deposit to
|
||||
// insert.
|
||||
if len(dc.deposits) == 0 {
|
||||
return
|
||||
}
|
||||
// In the event we have less deposits than we need to
|
||||
// finalize we finalize till the index on which we do have it.
|
||||
if len(dc.deposits) <= int(eth1DepositIndex) {
|
||||
eth1DepositIndex = int64(len(dc.deposits)) - 1
|
||||
}
|
||||
// If we finalize to some lower deposit index, we
|
||||
// ignore it.
|
||||
if int(eth1DepositIndex) < insertIndex {
|
||||
return
|
||||
}
|
||||
for _, d := range dc.deposits {
|
||||
if d.Index <= dc.finalizedDeposits.MerkleTrieIndex {
|
||||
continue
|
||||
@@ -262,7 +246,7 @@ func (dc *DepositCache) FinalizedDeposits(ctx context.Context) *FinalizedDeposit
|
||||
|
||||
// NonFinalizedDeposits returns the list of non-finalized deposits until the given block number (inclusive).
|
||||
// If no block is specified then this method returns all non-finalized deposits.
|
||||
func (dc *DepositCache) NonFinalizedDeposits(ctx context.Context, lastFinalizedIndex int64, untilBlk *big.Int) []*ethpb.Deposit {
|
||||
func (dc *DepositCache) NonFinalizedDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit {
|
||||
ctx, span := trace.StartSpan(ctx, "DepositsCache.NonFinalizedDeposits")
|
||||
defer span.End()
|
||||
dc.depositsLock.RLock()
|
||||
@@ -272,9 +256,10 @@ func (dc *DepositCache) NonFinalizedDeposits(ctx context.Context, lastFinalizedI
|
||||
return dc.allDeposits(untilBlk)
|
||||
}
|
||||
|
||||
lastFinalizedDepositIndex := dc.finalizedDeposits.MerkleTrieIndex
|
||||
var deposits []*ethpb.Deposit
|
||||
for _, d := range dc.deposits {
|
||||
if (d.Index > lastFinalizedIndex) && (untilBlk == nil || untilBlk.Uint64() >= d.Eth1BlockHeight) {
|
||||
if (d.Index > lastFinalizedDepositIndex) && (untilBlk == nil || untilBlk.Uint64() >= d.Eth1BlockHeight) {
|
||||
deposits = append(deposits, d.Deposit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
Index: 1,
|
||||
},
|
||||
}
|
||||
newFinalizedDeposit := ðpb.DepositContainer{
|
||||
newFinalizedDeposit := ethpb.DepositContainer{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{2}, 48),
|
||||
@@ -471,17 +471,17 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
}
|
||||
dc.deposits = oldFinalizedDeposits
|
||||
dc.InsertFinalizedDeposits(context.Background(), 1)
|
||||
// Artificially exclude old deposits so that they can only be retrieved from previously finalized deposits.
|
||||
dc.deposits = []*ethpb.DepositContainer{&newFinalizedDeposit}
|
||||
|
||||
dc.InsertFinalizedDeposits(context.Background(), 2)
|
||||
|
||||
dc.deposits = append(dc.deposits, []*ethpb.DepositContainer{newFinalizedDeposit}...)
|
||||
|
||||
cachedDeposits := dc.FinalizedDeposits(context.Background())
|
||||
require.NotNil(t, cachedDeposits, "Deposits not cached")
|
||||
assert.Equal(t, int64(1), cachedDeposits.MerkleTrieIndex)
|
||||
assert.Equal(t, int64(2), cachedDeposits.MerkleTrieIndex)
|
||||
|
||||
var deps [][]byte
|
||||
for _, d := range oldFinalizedDeposits {
|
||||
for _, d := range append(oldFinalizedDeposits, &newFinalizedDeposit) {
|
||||
hash, err := d.Deposit.Data.HashTreeRoot()
|
||||
require.NoError(t, err, "Could not hash deposit data")
|
||||
deps = append(deps, hash[:])
|
||||
@@ -491,140 +491,6 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
assert.Equal(t, trie.HashTreeRoot(), cachedDeposits.Deposits.HashTreeRoot())
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_HandleZeroDeposits(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
dc.InsertFinalizedDeposits(context.Background(), 2)
|
||||
|
||||
cachedDeposits := dc.FinalizedDeposits(context.Background())
|
||||
require.NotNil(t, cachedDeposits, "Deposits not cached")
|
||||
assert.Equal(t, int64(-1), cachedDeposits.MerkleTrieIndex)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_HandleSmallerThanExpectedDeposits(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
finalizedDeposits := []*ethpb.DepositContainer{
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{0}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 0,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{1}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 1,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{2}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 2,
|
||||
},
|
||||
}
|
||||
dc.deposits = finalizedDeposits
|
||||
|
||||
dc.InsertFinalizedDeposits(context.Background(), 5)
|
||||
|
||||
cachedDeposits := dc.FinalizedDeposits(context.Background())
|
||||
require.NotNil(t, cachedDeposits, "Deposits not cached")
|
||||
assert.Equal(t, int64(2), cachedDeposits.MerkleTrieIndex)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_HandleLowerEth1DepositIndex(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
finalizedDeposits := []*ethpb.DepositContainer{
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{0}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 0,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{1}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 1,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{2}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 2,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{3}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 3,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{4}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 4,
|
||||
},
|
||||
{
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{5}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: 5,
|
||||
},
|
||||
}
|
||||
dc.deposits = finalizedDeposits
|
||||
|
||||
dc.InsertFinalizedDeposits(context.Background(), 5)
|
||||
|
||||
// Reinsert finalized deposits with a lower index.
|
||||
dc.InsertFinalizedDeposits(context.Background(), 2)
|
||||
|
||||
cachedDeposits := dc.FinalizedDeposits(context.Background())
|
||||
require.NotNil(t, cachedDeposits, "Deposits not cached")
|
||||
assert.Equal(t, int64(5), cachedDeposits.MerkleTrieIndex)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_InitializedCorrectly(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
@@ -688,7 +554,7 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
|
||||
})
|
||||
dc.InsertFinalizedDeposits(context.Background(), 1)
|
||||
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), 1, nil)
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), nil)
|
||||
assert.Equal(t, 2, len(deps))
|
||||
}
|
||||
|
||||
@@ -745,89 +611,10 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
|
||||
})
|
||||
dc.InsertFinalizedDeposits(context.Background(), 1)
|
||||
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), 1, big.NewInt(10))
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), big.NewInt(10))
|
||||
assert.Equal(t, 1, len(deps))
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_ReturnsTrieCorrectly(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
generateCtr := func(height uint64, index int64) *ethpb.DepositContainer {
|
||||
return ðpb.DepositContainer{
|
||||
Eth1BlockHeight: height,
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{uint8(index)}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
finalizedDeposits := []*ethpb.DepositContainer{
|
||||
generateCtr(10, 0),
|
||||
generateCtr(11, 1),
|
||||
generateCtr(12, 2),
|
||||
generateCtr(12, 3),
|
||||
generateCtr(13, 4),
|
||||
generateCtr(13, 5),
|
||||
generateCtr(13, 6),
|
||||
generateCtr(14, 7),
|
||||
}
|
||||
dc.deposits = append(finalizedDeposits,
|
||||
generateCtr(15, 8),
|
||||
generateCtr(15, 9),
|
||||
generateCtr(30, 10))
|
||||
trieItems := make([][]byte, 0, len(dc.deposits))
|
||||
for _, dep := range dc.allDeposits(big.NewInt(30)) {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
trieItems = append(trieItems, depHash[:])
|
||||
}
|
||||
depositTrie, err := trie.GenerateTrieFromItems(trieItems, params.BeaconConfig().DepositContractTreeDepth)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Perform this in a non-sensical ordering
|
||||
dc.InsertFinalizedDeposits(context.Background(), 10)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 2)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 3)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 4)
|
||||
|
||||
// Mimick finalized deposit trie fetch.
|
||||
fd := dc.FinalizedDeposits(context.Background())
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), fd.MerkleTrieIndex, big.NewInt(14))
|
||||
insertIndex := fd.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range deps {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
if err = fd.Deposits.Insert(depHash[:], int(insertIndex)); err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
insertIndex++
|
||||
}
|
||||
dc.InsertFinalizedDeposits(context.Background(), 15)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 15)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 14)
|
||||
|
||||
fd = dc.FinalizedDeposits(context.Background())
|
||||
deps = dc.NonFinalizedDeposits(context.Background(), fd.MerkleTrieIndex, big.NewInt(30))
|
||||
insertIndex = fd.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range deps {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
if err = fd.Deposits.Insert(depHash[:], int(insertIndex)); err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
insertIndex++
|
||||
}
|
||||
assert.Equal(t, fd.Deposits.NumOfItems(), depositTrie.NumOfItems())
|
||||
}
|
||||
|
||||
func TestPruneProofs_Ok(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -47,18 +47,14 @@ type Config struct {
|
||||
// into the beacon chain database and running services at start up. This service should not be used in production
|
||||
// as it does not have any value other than ease of use for testing purposes.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
log.Warn("Saving generated genesis state in database for interop testing")
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
return &Service{
|
||||
s := &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// Start initializes the genesis state from configured flags.
|
||||
func (s *Service) Start() {
|
||||
log.Warn("Saving generated genesis state in database for interop testing")
|
||||
|
||||
if s.cfg.GenesisPath != "" {
|
||||
data, err := ioutil.ReadFile(s.cfg.GenesisPath)
|
||||
@@ -73,14 +69,14 @@ func (s *Service) Start() {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get state trie: %v", err)
|
||||
}
|
||||
if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil {
|
||||
if err := s.saveGenesisState(ctx, genesisTrie); err != nil {
|
||||
log.Fatalf("Could not save interop genesis state %v", err)
|
||||
}
|
||||
return
|
||||
return s
|
||||
}
|
||||
|
||||
// Save genesis state in db
|
||||
genesisState, _, err := interop.GenerateGenesisState(s.ctx, s.cfg.GenesisTime, s.cfg.NumValidators)
|
||||
genesisState, _, err := interop.GenerateGenesisState(ctx, s.cfg.GenesisTime, s.cfg.NumValidators)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not generate interop genesis state: %v", err)
|
||||
}
|
||||
@@ -96,11 +92,17 @@ func (s *Service) Start() {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slots.CountdownToGenesis(s.ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot)
|
||||
go slots.CountdownToGenesis(ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot)
|
||||
|
||||
if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil {
|
||||
if err := s.saveGenesisState(ctx, genesisTrie); err != nil {
|
||||
log.Fatalf("Could not save interop genesis state %v", err)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Start initializes the genesis state from configured flags.
|
||||
func (_ *Service) Start() {
|
||||
}
|
||||
|
||||
// Stop does nothing.
|
||||
@@ -153,7 +155,7 @@ func (_ *Service) FinalizedDeposits(_ context.Context) *depositcache.FinalizedDe
|
||||
}
|
||||
|
||||
// NonFinalizedDeposits mocks out the deposit cache functionality for interop.
|
||||
func (_ *Service) NonFinalizedDeposits(_ context.Context, _ int64, _ *big.Int) []*ethpb.Deposit {
|
||||
func (_ *Service) NonFinalizedDeposits(_ context.Context, _ *big.Int) []*ethpb.Deposit {
|
||||
return []*ethpb.Deposit{}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,4 +51,10 @@ var (
|
||||
Help: "The number of times pruning happened.",
|
||||
},
|
||||
)
|
||||
validatedCount = promauto.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "doublylinkedtree_validated_count",
|
||||
Help: "The number of blocks that have been fully validated.",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -120,6 +120,7 @@ func (n *Node) setNodeAndParentValidated(ctx context.Context) error {
|
||||
}
|
||||
|
||||
n.optimistic = false
|
||||
validatedCount.Inc()
|
||||
return n.parent.setNodeAndParentValidated(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,4 +51,10 @@ var (
|
||||
Help: "The number of times pruning happened.",
|
||||
},
|
||||
)
|
||||
validatedNodesCount = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "proto_array_validated_nodes_count",
|
||||
Help: "The number of nodes that have been fully validated.",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -43,6 +43,7 @@ func (f *ForkChoice) SetOptimisticToValid(ctx context.Context, root [32]byte) er
|
||||
if index == NonExistentNode {
|
||||
break
|
||||
}
|
||||
validatedNodesCount.Inc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -614,22 +614,16 @@ func (s *Store) prune(ctx context.Context, finalizedRoot [32]byte) error {
|
||||
node := copyNode(s.nodes[idx])
|
||||
parentIdx, ok := canonicalNodesMap[node.parent]
|
||||
if ok {
|
||||
currentIndex := uint64(len(canonicalNodes))
|
||||
s.nodesIndices[node.root] = currentIndex
|
||||
s.payloadIndices[node.payloadHash] = currentIndex
|
||||
canonicalNodesMap[idx] = currentIndex
|
||||
s.nodesIndices[node.root] = uint64(len(canonicalNodes))
|
||||
canonicalNodesMap[idx] = uint64(len(canonicalNodes))
|
||||
node.parent = parentIdx
|
||||
canonicalNodes = append(canonicalNodes, node)
|
||||
} else {
|
||||
// Remove node that is not part of finalized branch.
|
||||
// Remove node and synced tip that is not part of finalized branch.
|
||||
delete(s.nodesIndices, node.root)
|
||||
delete(s.canonicalNodes, node.root)
|
||||
delete(s.payloadIndices, node.payloadHash)
|
||||
}
|
||||
}
|
||||
s.nodesIndices[finalizedRoot] = uint64(0)
|
||||
s.canonicalNodes[finalizedRoot] = true
|
||||
s.payloadIndices[finalizedNode.payloadHash] = uint64(0)
|
||||
|
||||
// Recompute the best child and descendant for each canonical nodes.
|
||||
for _, node := range canonicalNodes {
|
||||
|
||||
@@ -375,7 +375,7 @@ func TestStore_Prune_MoreThanThreshold(t *testing.T) {
|
||||
parent: uint64(numOfNodes - 2),
|
||||
})
|
||||
indices[indexToHash(uint64(numOfNodes-1))] = uint64(numOfNodes - 1)
|
||||
s := &Store{nodes: nodes, nodesIndices: indices, canonicalNodes: map[[32]byte]bool{}, payloadIndices: map[[32]byte]uint64{}}
|
||||
s := &Store{nodes: nodes, nodesIndices: indices}
|
||||
|
||||
// Finalized root is at index 99 so everything before 99 should be pruned.
|
||||
require.NoError(t, s.prune(context.Background(), indexToHash(99)))
|
||||
@@ -413,7 +413,7 @@ func TestStore_Prune_MoreThanOnce(t *testing.T) {
|
||||
parent: uint64(numOfNodes - 2),
|
||||
})
|
||||
|
||||
s := &Store{nodes: nodes, nodesIndices: indices, canonicalNodes: map[[32]byte]bool{}, payloadIndices: map[[32]byte]uint64{}}
|
||||
s := &Store{nodes: nodes, nodesIndices: indices}
|
||||
|
||||
// Finalized root is at index 11 so everything before 11 should be pruned.
|
||||
require.NoError(t, s.prune(context.Background(), indexToHash(10)))
|
||||
@@ -441,7 +441,6 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
|
||||
bestDescendant: 1,
|
||||
root: indexToHash(uint64(0)),
|
||||
parent: NonExistentNode,
|
||||
payloadHash: [32]byte{'A'},
|
||||
},
|
||||
{
|
||||
slot: 101,
|
||||
@@ -449,7 +448,6 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
|
||||
bestChild: NonExistentNode,
|
||||
bestDescendant: NonExistentNode,
|
||||
parent: 0,
|
||||
payloadHash: [32]byte{'B'},
|
||||
},
|
||||
{
|
||||
slot: 101,
|
||||
@@ -457,7 +455,6 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
|
||||
parent: 0,
|
||||
bestChild: NonExistentNode,
|
||||
bestDescendant: NonExistentNode,
|
||||
payloadHash: [32]byte{'C'},
|
||||
},
|
||||
}
|
||||
s := &Store{
|
||||
@@ -468,22 +465,9 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
|
||||
indexToHash(uint64(1)): 1,
|
||||
indexToHash(uint64(2)): 2,
|
||||
},
|
||||
canonicalNodes: map[[32]byte]bool{
|
||||
indexToHash(uint64(0)): true,
|
||||
indexToHash(uint64(1)): true,
|
||||
indexToHash(uint64(2)): true,
|
||||
},
|
||||
payloadIndices: map[[32]byte]uint64{
|
||||
[32]byte{'A'}: 0,
|
||||
[32]byte{'B'}: 1,
|
||||
[32]byte{'C'}: 2,
|
||||
},
|
||||
}
|
||||
require.NoError(t, s.prune(context.Background(), indexToHash(uint64(1))))
|
||||
require.Equal(t, 1, len(s.nodes))
|
||||
require.Equal(t, 1, len(s.nodesIndices))
|
||||
require.Equal(t, 1, len(s.canonicalNodes))
|
||||
require.Equal(t, 1, len(s.payloadIndices))
|
||||
require.Equal(t, len(s.nodes), 1)
|
||||
}
|
||||
|
||||
// This test starts with the following branching diagram
|
||||
@@ -498,74 +482,25 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
|
||||
// J -- K -- L
|
||||
//
|
||||
//
|
||||
func TestStore_PruneBranched(t *testing.T) {
|
||||
func TestStore_PruneSyncedTips(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
f := setup(1, 1)
|
||||
|
||||
tests := []struct {
|
||||
finalizedRoot [32]byte
|
||||
wantedCanonical [32]byte
|
||||
wantedNonCanonical [32]byte
|
||||
canonicalCount int
|
||||
payloadHash [32]byte
|
||||
payloadIndex uint64
|
||||
nonExistentPayload [32]byte
|
||||
}{
|
||||
{
|
||||
[32]byte{'f'},
|
||||
[32]byte{'f'},
|
||||
[32]byte{'a'},
|
||||
1,
|
||||
[32]byte{'F'},
|
||||
0,
|
||||
[32]byte{'H'},
|
||||
},
|
||||
{
|
||||
[32]byte{'d'},
|
||||
[32]byte{'e'},
|
||||
[32]byte{'i'},
|
||||
3,
|
||||
[32]byte{'E'},
|
||||
1,
|
||||
[32]byte{'C'},
|
||||
},
|
||||
{
|
||||
[32]byte{'b'},
|
||||
[32]byte{'f'},
|
||||
[32]byte{'h'},
|
||||
5,
|
||||
[32]byte{'D'},
|
||||
3,
|
||||
[32]byte{'A'},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
f := setup(1, 1)
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'j'}, [32]byte{'b'}, [32]byte{'J'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'d'}, [32]byte{'E'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'g'}, [32]byte{'d'}, [32]byte{'G'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, [32]byte{'F'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'h'}, [32]byte{'g'}, [32]byte{'H'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'k'}, [32]byte{'g'}, [32]byte{'K'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'i'}, [32]byte{'h'}, [32]byte{'I'}, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'l'}, [32]byte{'k'}, [32]byte{'L'}, 1, 1))
|
||||
f.store.pruneThreshold = 0
|
||||
require.NoError(t, f.store.updateCanonicalNodes(ctx, [32]byte{'f'}))
|
||||
require.Equal(t, true, f.IsCanonical([32]byte{'a'}))
|
||||
require.Equal(t, true, f.IsCanonical([32]byte{'f'}))
|
||||
|
||||
require.NoError(t, f.Prune(ctx, tc.finalizedRoot))
|
||||
require.Equal(t, tc.canonicalCount, len(f.store.canonicalNodes))
|
||||
require.Equal(t, true, f.IsCanonical(tc.wantedCanonical))
|
||||
require.Equal(t, false, f.IsCanonical(tc.wantedNonCanonical))
|
||||
require.Equal(t, tc.payloadIndex, f.store.payloadIndices[tc.payloadHash])
|
||||
_, ok := f.store.payloadIndices[tc.nonExistentPayload]
|
||||
require.Equal(t, false, ok)
|
||||
}
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 100, [32]byte{'a'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 102, [32]byte{'j'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'e'}, [32]byte{'d'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 104, [32]byte{'g'}, [32]byte{'d'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'f'}, [32]byte{'e'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'h'}, [32]byte{'g'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 105, [32]byte{'k'}, [32]byte{'g'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'i'}, [32]byte{'h'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, f.InsertOptimisticBlock(ctx, 106, [32]byte{'l'}, [32]byte{'k'}, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
f.store.pruneThreshold = 0
|
||||
require.NoError(t, f.Prune(ctx, [32]byte{'f'}))
|
||||
require.Equal(t, 1, f.NodeCount())
|
||||
}
|
||||
|
||||
func TestStore_LeadsToViableHead(t *testing.T) {
|
||||
|
||||
@@ -95,7 +95,6 @@ func NewService(ctx context.Context, config *ValidatorMonitorConfig, tracked []t
|
||||
latestPerformance: make(map[types.ValidatorIndex]ValidatorLatestPerformance),
|
||||
aggregatedPerformance: make(map[types.ValidatorIndex]ValidatorAggregatedPerformance),
|
||||
trackedSyncCommitteeIndices: make(map[types.ValidatorIndex][]types.CommitteeIndex),
|
||||
isLogging: false,
|
||||
}
|
||||
for _, idx := range tracked {
|
||||
r.TrackedValidators[idx] = true
|
||||
@@ -118,6 +117,7 @@ func (s *Service) Start() {
|
||||
"ValidatorIndices": tracked,
|
||||
}).Info("Starting service")
|
||||
|
||||
s.isLogging = false
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.config.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
|
||||
|
||||
@@ -906,7 +906,6 @@ func (b *BeaconNode) registerDeterminsticGenesisService() error {
|
||||
DepositCache: b.depositCache,
|
||||
GenesisPath: genesisStatePath,
|
||||
})
|
||||
svc.Start()
|
||||
|
||||
// Register genesis state as start-up state when interop mode.
|
||||
// The start-up state gets reused across services.
|
||||
|
||||
@@ -3,6 +3,7 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"auth.go",
|
||||
"block_cache.go",
|
||||
"block_reader.go",
|
||||
"check_transition_config.go",
|
||||
@@ -15,7 +16,6 @@ go_library(
|
||||
"options.go",
|
||||
"prometheus.go",
|
||||
"provider.go",
|
||||
"rpc_connection.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/powchain",
|
||||
@@ -59,6 +59,7 @@ go_library(
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//ethclient:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_golang_jwt_jwt_v4//:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
@@ -73,6 +74,7 @@ go_test(
|
||||
name = "go_default_test",
|
||||
size = "medium",
|
||||
srcs = [
|
||||
"auth_test.go",
|
||||
"block_cache_test.go",
|
||||
"block_reader_test.go",
|
||||
"check_transition_config_test.go",
|
||||
@@ -123,6 +125,7 @@ go_test(
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//trie:go_default_library",
|
||||
"@com_github_golang_jwt_jwt_v4//:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package network
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -8,9 +8,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DefaultRPCHTTPTimeout for HTTP requests via an RPC connection to an execution node.
|
||||
const DefaultRPCHTTPTimeout = time.Second * 6
|
||||
|
||||
// This creates a custom HTTP transport which we can attach to our HTTP client
|
||||
// in order to inject JWT auth strings into our HTTP request headers. Authentication
|
||||
// is required when interacting with an Ethereum engine API server via HTTP, and JWT
|
||||
@@ -1,4 +1,4 @@
|
||||
package network
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -82,7 +81,7 @@ func (s *Service) checkTransitionConfiguration(
|
||||
return
|
||||
}
|
||||
case tm := <-ticker.C:
|
||||
ctx, cancel := context.WithDeadline(ctx, tm.Add(network.DefaultRPCHTTPTimeout))
|
||||
ctx, cancel := context.WithDeadline(ctx, tm.Add(DefaultRPCHTTPTimeout))
|
||||
err = s.ExchangeTransitionConfiguration(ctx, cfg)
|
||||
s.handleExchangeConfigurationError(err)
|
||||
if !hasTtdReached {
|
||||
@@ -120,16 +119,11 @@ func (s *Service) handleExchangeConfigurationError(err error) {
|
||||
// Logs the terminal total difficulty status.
|
||||
func (s *Service) logTtdStatus(ctx context.Context, ttd *uint256.Int) (bool, error) {
|
||||
latest, err := s.LatestExecutionBlock(ctx)
|
||||
switch {
|
||||
case errors.Is(err, hexutil.ErrEmptyString):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
if err != nil {
|
||||
return false, err
|
||||
case latest == nil:
|
||||
}
|
||||
if latest == nil {
|
||||
return false, errors.New("latest block is nil")
|
||||
case latest.TotalDifficulty == "":
|
||||
return false, nil
|
||||
default:
|
||||
}
|
||||
latestTtd, err := hexutil.DecodeBig(latest.TotalDifficulty)
|
||||
if err != nil {
|
||||
|
||||
@@ -190,38 +190,6 @@ func TestService_logTtdStatus(t *testing.T) {
|
||||
require.Equal(t, false, reached)
|
||||
}
|
||||
|
||||
func TestService_logTtdStatus_NotSyncedClient(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
defer func() {
|
||||
require.NoError(t, r.Body.Close())
|
||||
}()
|
||||
|
||||
resp := (*pb.ExecutionBlock)(nil) // Nil response when a client is not synced
|
||||
respJSON := map[string]interface{}{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": resp,
|
||||
}
|
||||
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
rpcClient, err := rpc.DialHTTP(srv.URL)
|
||||
require.NoError(t, err)
|
||||
defer rpcClient.Close()
|
||||
|
||||
service := &Service{
|
||||
cfg: &config{},
|
||||
}
|
||||
service.rpcClient = rpcClient
|
||||
|
||||
ttd := new(uint256.Int)
|
||||
reached, err := service.logTtdStatus(context.Background(), ttd.SetUint64(24343))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, reached)
|
||||
}
|
||||
|
||||
func emptyPayload() *pb.ExecutionPayload {
|
||||
return &pb.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
|
||||
@@ -10,12 +10,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -52,8 +49,8 @@ type EngineCaller interface {
|
||||
ExchangeTransitionConfiguration(
|
||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||
) error
|
||||
LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock, error)
|
||||
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
|
||||
GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error)
|
||||
}
|
||||
|
||||
// NewPayload calls the engine_newPayloadV1 method via JSON-RPC.
|
||||
@@ -177,78 +174,6 @@ func (s *Service) ExchangeTransitionConfiguration(
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTerminalBlockHash returns the valid terminal block hash based on total difficulty.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
||||
// # `pow_chain` abstractly represents all blocks in the PoW chain
|
||||
// for block in pow_chain:
|
||||
// parent = pow_chain[block.parent_hash]
|
||||
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// if block_reached_ttd and not parent_reached_ttd:
|
||||
// return block
|
||||
//
|
||||
// return None
|
||||
func (s *Service) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
||||
ttd := new(big.Int)
|
||||
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
|
||||
terminalTotalDifficulty, overflows := uint256.FromBig(ttd)
|
||||
if overflows {
|
||||
return nil, false, errors.New("could not convert terminal total difficulty to uint256")
|
||||
}
|
||||
blk, err := s.LatestExecutionBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get latest execution block")
|
||||
}
|
||||
if blk == nil {
|
||||
return nil, false, errors.New("latest execution block is nil")
|
||||
}
|
||||
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return nil, false, ctx.Err()
|
||||
}
|
||||
currentTotalDifficulty, err := tDStringToUint256(blk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
|
||||
parentHash := bytesutil.ToBytes32(blk.ParentHash)
|
||||
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := s.ExecutionBlockByHash(ctx, parentHash)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
if parentBlk == nil {
|
||||
return nil, false, errors.New("parent execution block is nil")
|
||||
}
|
||||
if blockReachedTTD {
|
||||
parentTotalDifficulty, err := tDStringToUint256(parentBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
if !parentReachedTTD {
|
||||
log.WithFields(logrus.Fields{
|
||||
"number": blk.Number,
|
||||
"hash": fmt.Sprintf("%#x", bytesutil.Trunc(blk.Hash)),
|
||||
"td": blk.TotalDifficulty,
|
||||
"parentTd": parentBlk.TotalDifficulty,
|
||||
"ttd": terminalTotalDifficulty,
|
||||
}).Info("Retrieved terminal block hash")
|
||||
return blk.Hash, true, nil
|
||||
}
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
blk = parentBlk
|
||||
}
|
||||
}
|
||||
|
||||
// LatestExecutionBlock fetches the latest execution engine block by calling
|
||||
// eth_blockByNumber via JSON-RPC.
|
||||
func (s *Service) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock, error) {
|
||||
@@ -326,15 +251,3 @@ func isTimeout(e error) bool {
|
||||
t, ok := e.(httpTimeoutError)
|
||||
return ok && t.Timeout()
|
||||
}
|
||||
|
||||
func tDStringToUint256(td string) (*uint256.Int, error) {
|
||||
b, err := hexutil.DecodeBig(td)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i, overflows := uint256.FromBig(b)
|
||||
if overflows {
|
||||
return nil, errors.New("total difficulty overflowed")
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@@ -418,155 +418,6 @@ func TestClient_HTTP(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
paramsTd string
|
||||
currentPowBlock *pb.ExecutionBlock
|
||||
parentPowBlock *pb.ExecutionBlock
|
||||
errLatestExecutionBlk error
|
||||
wantTerminalBlockHash []byte
|
||||
wantExists bool
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "config td overflows",
|
||||
paramsTd: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
errString: "could not convert terminal total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "could not get latest execution block",
|
||||
paramsTd: "1",
|
||||
errLatestExecutionBlk: errors.New("blah"),
|
||||
errString: "could not get latest execution block",
|
||||
},
|
||||
{
|
||||
name: "nil latest execution block",
|
||||
paramsTd: "1",
|
||||
errString: "latest execution block is nil",
|
||||
},
|
||||
{
|
||||
name: "current execution block invalid TD",
|
||||
paramsTd: "1",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
TotalDifficulty: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
},
|
||||
errString: "could not convert total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "current execution block has zero hash parent",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: params.BeaconConfig().ZeroHash[:],
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "could not get parent block",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
errString: "could not get parent execution block",
|
||||
},
|
||||
{
|
||||
name: "parent execution block invalid TD",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "1",
|
||||
},
|
||||
errString: "could not convert total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "happy case",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
wantExists: true,
|
||||
wantTerminalBlockHash: []byte{'a'},
|
||||
},
|
||||
{
|
||||
name: "ttd not reached",
|
||||
paramsTd: "3",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x2",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalTotalDifficulty = tt.paramsTd
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
var m map[[32]byte]*pb.ExecutionBlock
|
||||
if tt.parentPowBlock != nil {
|
||||
m = map[[32]byte]*pb.ExecutionBlock{
|
||||
bytesutil.ToBytes32(tt.parentPowBlock.Hash): tt.parentPowBlock,
|
||||
}
|
||||
}
|
||||
client := mocks.EngineClient{
|
||||
ErrLatestExecBlock: tt.errLatestExecutionBlk,
|
||||
ExecutionBlock: tt.currentPowBlock,
|
||||
BlockByHashMap: m,
|
||||
}
|
||||
b, e, err := client.GetTerminalBlockHash(context.Background())
|
||||
if tt.errString != "" {
|
||||
require.ErrorContains(t, tt.errString, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, tt.wantExists, e)
|
||||
require.DeepEqual(t, tt.wantTerminalBlockHash, b)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_tDStringToUint256(t *testing.T) {
|
||||
i, err := tDStringToUint256("0x0")
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, uint256.NewInt(0), i)
|
||||
|
||||
i, err = tDStringToUint256("0x10000")
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, uint256.NewInt(65536), i)
|
||||
|
||||
_, err = tDStringToUint256("100")
|
||||
require.ErrorContains(t, "hex string without 0x prefix", err)
|
||||
|
||||
_, err = tDStringToUint256("0xzzzzzz")
|
||||
require.ErrorContains(t, "invalid hex string", err)
|
||||
|
||||
_, err = tDStringToUint256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
require.ErrorContains(t, "hex number > 256 bits", err)
|
||||
}
|
||||
|
||||
func TestExchangeTransitionConfiguration(t *testing.T) {
|
||||
fix := fixtures()
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
@@ -8,9 +11,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
)
|
||||
|
||||
// DefaultRPCHTTPTimeout for HTTP requests via an RPC connection to an execution node.
|
||||
const DefaultRPCHTTPTimeout = time.Second * 6
|
||||
|
||||
type Option func(s *Service) error
|
||||
|
||||
// WithHttpEndpoints deduplicates and parses http endpoints for the powchain service to use,
|
||||
@@ -33,29 +38,20 @@ func WithHttpEndpoints(endpointStrings []string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithHttpEndpointsAndJWTSecret for authenticating the execution node JSON-RPC endpoint.
|
||||
func WithHttpEndpointsAndJWTSecret(endpointStrings []string, secret []byte) Option {
|
||||
return func(s *Service) error {
|
||||
// WithJWTSecret for authenticating the execution node JSON-RPC endpoint.
|
||||
func WithJWTSecret(secret []byte) Option {
|
||||
return func(c *Service) error {
|
||||
if len(secret) == 0 {
|
||||
return nil
|
||||
}
|
||||
stringEndpoints := dedupEndpoints(endpointStrings)
|
||||
endpoints := make([]network.Endpoint, len(stringEndpoints))
|
||||
// Overwrite authorization type for all endpoints to be of a bearer
|
||||
// type.
|
||||
for i, e := range stringEndpoints {
|
||||
hEndpoint := HttpEndpoint(e)
|
||||
hEndpoint.Auth.Method = authorization.Bearer
|
||||
hEndpoint.Auth.Value = string(secret)
|
||||
endpoints[i] = hEndpoint
|
||||
authTransport := &jwtTransport{
|
||||
underlyingTransport: http.DefaultTransport,
|
||||
jwtSecret: secret,
|
||||
}
|
||||
// Select first http endpoint in the provided list.
|
||||
var currEndpoint network.Endpoint
|
||||
if len(endpointStrings) > 0 {
|
||||
currEndpoint = endpoints[0]
|
||||
c.cfg.httpRPCClient = &http.Client{
|
||||
Timeout: DefaultRPCHTTPTimeout,
|
||||
Transport: authTransport,
|
||||
}
|
||||
s.cfg.httpEndpoints = endpoints
|
||||
s.cfg.currHttpEndpoint = currEndpoint
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
package powchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
gethRPC "github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit"
|
||||
"github.com/prysmaticlabs/prysm/io/logs"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
)
|
||||
|
||||
func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpoint network.Endpoint) error {
|
||||
client, err := s.newRPCClientWithAuth(ctx, currEndpoint)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not dial execution node")
|
||||
}
|
||||
// Attach the clients to the service struct.
|
||||
fetcher := ethclient.NewClient(client)
|
||||
s.rpcClient = client
|
||||
s.httpLogger = fetcher
|
||||
s.eth1DataFetcher = fetcher
|
||||
|
||||
depositContractCaller, err := contracts.NewDepositContractCaller(s.cfg.depositContractAddr, fetcher)
|
||||
if err != nil {
|
||||
client.Close()
|
||||
return errors.Wrap(err, "could not initialize deposit contract caller")
|
||||
}
|
||||
s.depositContractCaller = depositContractCaller
|
||||
|
||||
// Ensure we have the correct chain and deposit IDs.
|
||||
if err := ensureCorrectExecutionChain(ctx, fetcher); err != nil {
|
||||
client.Close()
|
||||
return errors.Wrap(err, "could not make initial request to verify execution chain ID")
|
||||
}
|
||||
s.updateConnectedETH1(true)
|
||||
s.runError = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Every N seconds, defined as a backoffPeriod, attempts to re-establish an execution client
|
||||
// connection and if this does not work, we fallback to the next endpoint if defined.
|
||||
func (s *Service) pollConnectionStatus(ctx context.Context) {
|
||||
// Use a custom logger to only log errors
|
||||
logCounter := 0
|
||||
errorLogger := func(err error, msg string) {
|
||||
if logCounter > logThreshold {
|
||||
log.Errorf("%s: %v", msg, err)
|
||||
logCounter = 0
|
||||
}
|
||||
logCounter++
|
||||
}
|
||||
ticker := time.NewTicker(backOffPeriod)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
log.Debugf("Trying to dial endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url))
|
||||
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
|
||||
errorLogger(err, "Could not connect to execution client endpoint")
|
||||
s.runError = err
|
||||
s.fallbackToNextEndpoint()
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
log.Debug("Received cancelled context,closing existing powchain service")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forces to retry an execution client connection.
|
||||
func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) {
|
||||
s.runError = err
|
||||
s.updateConnectedETH1(false)
|
||||
// Back off for a while before redialing.
|
||||
time.Sleep(backOffPeriod)
|
||||
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
|
||||
s.runError = err
|
||||
return
|
||||
}
|
||||
// Reset run error in the event of a successful connection.
|
||||
s.runError = nil
|
||||
}
|
||||
|
||||
// This performs a health check on our primary endpoint, and if it
|
||||
// is ready to serve we connect to it again. This method is only
|
||||
// relevant if we are on our backup endpoint.
|
||||
func (s *Service) checkDefaultEndpoint(ctx context.Context) {
|
||||
primaryEndpoint := s.cfg.httpEndpoints[0]
|
||||
// Return early if we are running on our primary
|
||||
// endpoint.
|
||||
if s.cfg.currHttpEndpoint.Equals(primaryEndpoint) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.setupExecutionClientConnections(ctx, primaryEndpoint); err != nil {
|
||||
log.Debugf("Primary endpoint not ready: %v", err)
|
||||
return
|
||||
}
|
||||
s.updateCurrHttpEndpoint(primaryEndpoint)
|
||||
}
|
||||
|
||||
// This is an inefficient way to search for the next endpoint, but given N is
|
||||
// expected to be small, it is fine to search this way.
|
||||
func (s *Service) fallbackToNextEndpoint() {
|
||||
currEndpoint := s.cfg.currHttpEndpoint
|
||||
currIndex := 0
|
||||
totalEndpoints := len(s.cfg.httpEndpoints)
|
||||
|
||||
for i, endpoint := range s.cfg.httpEndpoints {
|
||||
if endpoint.Equals(currEndpoint) {
|
||||
currIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
nextIndex := currIndex + 1
|
||||
if nextIndex >= totalEndpoints {
|
||||
nextIndex = 0
|
||||
}
|
||||
s.updateCurrHttpEndpoint(s.cfg.httpEndpoints[nextIndex])
|
||||
if nextIndex != currIndex {
|
||||
log.Infof("Falling back to alternative endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url))
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes an RPC connection with authentication headers.
|
||||
func (s *Service) newRPCClientWithAuth(ctx context.Context, endpoint network.Endpoint) (*gethRPC.Client, error) {
|
||||
// Need to handle ipc and http
|
||||
var client *gethRPC.Client
|
||||
u, err := url.Parse(endpoint.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "http", "https":
|
||||
client, err = gethRPC.DialHTTPWithClient(endpoint.Url, endpoint.HttpClient())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "":
|
||||
client, err = gethRPC.DialIPC(ctx, endpoint.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
|
||||
}
|
||||
if endpoint.Auth.Method != authorization.None {
|
||||
header, err := endpoint.Auth.ToHeaderValue()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.SetHeader("Authorization", header)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Checks the chain ID of the execution client to ensure
|
||||
// it matches local parameters of what Prysm expects.
|
||||
func ensureCorrectExecutionChain(ctx context.Context, client *ethclient.Client) error {
|
||||
cID, err := client.ChainID(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wantChainID := params.BeaconConfig().DepositChainID
|
||||
if cID.Uint64() != wantChainID {
|
||||
return fmt.Errorf("wanted chain ID %d, got %d", wantChainID, cID.Uint64())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
@@ -38,8 +39,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/container/trie"
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/io/logs"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/clientstats"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
@@ -111,7 +114,6 @@ type Chain interface {
|
||||
// RPCDataFetcher defines a subset of methods conformed to by ETH1.0 RPC clients for
|
||||
// fetching eth1 data from the clients.
|
||||
type RPCDataFetcher interface {
|
||||
Close()
|
||||
HeaderByNumber(ctx context.Context, number *big.Int) (*gethTypes.Header, error)
|
||||
HeaderByHash(ctx context.Context, hash common.Hash) (*gethTypes.Header, error)
|
||||
SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error)
|
||||
@@ -119,7 +121,6 @@ type RPCDataFetcher interface {
|
||||
|
||||
// RPCClient defines the rpc methods required to interact with the eth1 node.
|
||||
type RPCClient interface {
|
||||
Close()
|
||||
BatchCall(b []gethRPC.BatchElem) error
|
||||
CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error
|
||||
}
|
||||
@@ -134,6 +135,7 @@ type config struct {
|
||||
eth1HeaderReqLimit uint64
|
||||
beaconNodeStatsUpdater BeaconNodeStatsUpdater
|
||||
httpEndpoints []network.Endpoint
|
||||
httpRPCClient *http.Client
|
||||
currHttpEndpoint network.Endpoint
|
||||
finalizedStateAtStartup state.BeaconState
|
||||
}
|
||||
@@ -226,9 +228,14 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
|
||||
// Start a web3 service's main event loop.
|
||||
func (s *Service) Start() {
|
||||
if err := s.setupExecutionClientConnections(s.ctx, s.cfg.currHttpEndpoint); err != nil {
|
||||
log.WithError(err).Error("Could not connect to execution endpoint")
|
||||
|
||||
if err := s.connectToPowChain(); err != nil {
|
||||
log.WithError(err).Fatal("Could not connect to execution endpoint")
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"endpoint": logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url),
|
||||
}).Info("Connected to Ethereum execution client RPC")
|
||||
// If the chain has not started already and we don't have access to eth1 nodes, we will not be
|
||||
// able to generate the genesis state.
|
||||
if !s.chainStartData.Chainstarted && s.cfg.currHttpEndpoint.Url == "" {
|
||||
@@ -246,7 +253,7 @@ func (s *Service) Start() {
|
||||
s.isRunning = true
|
||||
|
||||
// Poll the execution client connection and fallback if errors occur.
|
||||
go s.pollConnectionStatus(s.ctx)
|
||||
go s.pollConnectionStatus()
|
||||
|
||||
// Check transition configuration for the engine API client in the background.
|
||||
go s.checkTransitionConfiguration(s.ctx, make(chan *feed.Event, 1))
|
||||
@@ -259,12 +266,7 @@ func (s *Service) Stop() error {
|
||||
if s.cancel != nil {
|
||||
defer s.cancel()
|
||||
}
|
||||
if s.rpcClient != nil {
|
||||
s.rpcClient.Close()
|
||||
}
|
||||
if s.eth1DataFetcher != nil {
|
||||
s.eth1DataFetcher.Close()
|
||||
}
|
||||
s.closeClients()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -336,7 +338,10 @@ func (s *Service) CurrentETH1Endpoint() string {
|
||||
|
||||
// CurrentETH1ConnectionError returns the error (if any) of the current connection.
|
||||
func (s *Service) CurrentETH1ConnectionError() error {
|
||||
return s.runError
|
||||
httpClient, rpcClient, err := s.dialETH1Nodes(s.cfg.currHttpEndpoint)
|
||||
httpClient.Close()
|
||||
rpcClient.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// ETH1Endpoints returns the slice of HTTP endpoint URLs (default is 0th element).
|
||||
@@ -353,17 +358,10 @@ func (s *Service) ETH1Endpoints() []string {
|
||||
func (s *Service) ETH1ConnectionErrors() []error {
|
||||
var errs []error
|
||||
for _, ep := range s.cfg.httpEndpoints {
|
||||
client, err := s.newRPCClientWithAuth(s.ctx, ep)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
if err := ensureCorrectExecutionChain(s.ctx, ethclient.NewClient(client)); err != nil {
|
||||
client.Close()
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
client.Close()
|
||||
httpClient, rpcClient, err := s.dialETH1Nodes(ep)
|
||||
httpClient.Close()
|
||||
rpcClient.Close()
|
||||
errs = append(errs, err)
|
||||
}
|
||||
return errs
|
||||
}
|
||||
@@ -378,6 +376,146 @@ func (s *Service) followBlockHeight(_ context.Context) (uint64, error) {
|
||||
return latestValidBlock, nil
|
||||
}
|
||||
|
||||
func (s *Service) connectToPowChain() error {
|
||||
httpClient, rpcClient, err := s.dialETH1Nodes(s.cfg.currHttpEndpoint)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not dial execution node")
|
||||
}
|
||||
|
||||
depositContractCaller, err := contracts.NewDepositContractCaller(s.cfg.depositContractAddr, httpClient)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize deposit contract caller")
|
||||
}
|
||||
|
||||
if httpClient == nil || rpcClient == nil || depositContractCaller == nil {
|
||||
return errors.New("execution client RPC is nil")
|
||||
}
|
||||
s.httpLogger = httpClient
|
||||
s.eth1DataFetcher = httpClient
|
||||
s.depositContractCaller = depositContractCaller
|
||||
s.rpcClient = rpcClient
|
||||
|
||||
s.updateConnectedETH1(true)
|
||||
s.runError = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) dialETH1Nodes(endpoint network.Endpoint) (*ethclient.Client, *gethRPC.Client, error) {
|
||||
httpRPCClient, err := gethRPC.Dial(endpoint.Url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if endpoint.Auth.Method != authorization.None {
|
||||
header, err := endpoint.Auth.ToHeaderValue()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
httpRPCClient.SetHeader("Authorization", header)
|
||||
}
|
||||
httpClient := ethclient.NewClient(httpRPCClient)
|
||||
// Add a method to clean-up and close clients in the event
|
||||
// of any connection failure.
|
||||
closeClients := func() {
|
||||
httpRPCClient.Close()
|
||||
httpClient.Close()
|
||||
}
|
||||
// Make a simple call to ensure we are actually connected to a working node.
|
||||
cID, err := httpClient.ChainID(s.ctx)
|
||||
if err != nil {
|
||||
closeClients()
|
||||
return nil, nil, err
|
||||
}
|
||||
nID, err := httpClient.NetworkID(s.ctx)
|
||||
if err != nil {
|
||||
closeClients()
|
||||
return nil, nil, err
|
||||
}
|
||||
if cID.Uint64() != params.BeaconConfig().DepositChainID {
|
||||
closeClients()
|
||||
return nil, nil, fmt.Errorf("eth1 node using incorrect chain id, %d != %d", cID.Uint64(), params.BeaconConfig().DepositChainID)
|
||||
}
|
||||
if nID.Uint64() != params.BeaconConfig().DepositNetworkID {
|
||||
closeClients()
|
||||
return nil, nil, fmt.Errorf("eth1 node using incorrect network id, %d != %d", nID.Uint64(), params.BeaconConfig().DepositNetworkID)
|
||||
}
|
||||
|
||||
return httpClient, httpRPCClient, nil
|
||||
}
|
||||
|
||||
// closes down our active eth1 clients.
|
||||
func (s *Service) closeClients() {
|
||||
gethClient, ok := s.rpcClient.(*gethRPC.Client)
|
||||
if ok {
|
||||
gethClient.Close()
|
||||
}
|
||||
httpClient, ok := s.eth1DataFetcher.(*ethclient.Client)
|
||||
if ok {
|
||||
httpClient.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) pollConnectionStatus() {
|
||||
// Use a custom logger to only log errors
|
||||
logCounter := 0
|
||||
errorLogger := func(err error, msg string) {
|
||||
if logCounter > logThreshold {
|
||||
log.Errorf("%s: %v", msg, err)
|
||||
logCounter = 0
|
||||
}
|
||||
logCounter++
|
||||
}
|
||||
ticker := time.NewTicker(backOffPeriod)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
log.Debugf("Trying to dial endpoint: %s", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url))
|
||||
errConnect := s.connectToPowChain()
|
||||
if errConnect != nil {
|
||||
errorLogger(errConnect, "Could not connect to powchain endpoint")
|
||||
s.runError = errConnect
|
||||
s.fallbackToNextEndpoint()
|
||||
continue
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
log.Debug("Received cancelled context,closing existing powchain service")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks if the eth1 node is healthy and ready to serve before
|
||||
// fetching data from it.
|
||||
func (s *Service) isEth1NodeSynced() (bool, error) {
|
||||
syncProg, err := s.eth1DataFetcher.SyncProgress(s.ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
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.
|
||||
func (s *Service) retryETH1Node(err error) {
|
||||
s.runError = err
|
||||
s.updateConnectedETH1(false)
|
||||
// Back off for a while before
|
||||
// resuming dialing the eth1 node.
|
||||
time.Sleep(backOffPeriod)
|
||||
if err := s.connectToPowChain(); err != nil {
|
||||
s.runError = err
|
||||
return
|
||||
}
|
||||
// Reset run error in the event of a successful connection.
|
||||
s.runError = nil
|
||||
}
|
||||
|
||||
func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositContainer) error {
|
||||
if len(ctrs) == 0 {
|
||||
return nil
|
||||
@@ -413,14 +551,11 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo
|
||||
// accumulates. we finalize them here before we are ready to receive a block.
|
||||
// Otherwise, the first few blocks will be slower to compute as we will
|
||||
// hold the lock and be busy finalizing the deposits.
|
||||
// The deposit index in the state is always the index of the next deposit
|
||||
// to be included(rather than the last one to be processed). This was most likely
|
||||
// done as the state cannot represent signed integers.
|
||||
actualIndex := int64(currIndex) - 1 // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
s.cfg.depositCache.InsertFinalizedDeposits(ctx, actualIndex)
|
||||
s.cfg.depositCache.InsertFinalizedDeposits(ctx, int64(currIndex)) // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
|
||||
if err = s.cfg.depositCache.PruneProofs(ctx, actualIndex); err != nil {
|
||||
// lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
if err = s.cfg.depositCache.PruneProofs(ctx, int64(currIndex)); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
}
|
||||
@@ -515,7 +650,7 @@ func (s *Service) handleETH1FollowDistance() {
|
||||
fiveMinutesTimeout := prysmTime.Now().Add(-5 * time.Minute)
|
||||
// check that web3 client is syncing
|
||||
if time.Unix(int64(s.latestEth1Data.BlockTime), 0).Before(fiveMinutesTimeout) {
|
||||
log.Warn("Execution client is not syncing")
|
||||
log.Warn("eth1 client is not syncing")
|
||||
}
|
||||
if !s.chainStartData.Chainstarted {
|
||||
if err := s.checkBlockNumberForChainStart(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil {
|
||||
@@ -545,15 +680,6 @@ func (s *Service) handleETH1FollowDistance() {
|
||||
}
|
||||
|
||||
func (s *Service) initPOWService() {
|
||||
// Use a custom logger to only log errors
|
||||
logCounter := 0
|
||||
errorLogger := func(err error, msg string) {
|
||||
if logCounter > logThreshold {
|
||||
log.Errorf("%s: %v", msg, err)
|
||||
logCounter = 0
|
||||
}
|
||||
logCounter++
|
||||
}
|
||||
|
||||
// Run in a select loop to retry in the event of any failures.
|
||||
for {
|
||||
@@ -564,8 +690,8 @@ func (s *Service) initPOWService() {
|
||||
ctx := s.ctx
|
||||
header, err := s.eth1DataFetcher.HeaderByNumber(ctx, nil)
|
||||
if err != nil {
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to retrieve latest execution client header")
|
||||
log.Errorf("Unable to retrieve latest ETH1.0 chain header: %v", err)
|
||||
s.retryETH1Node(err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -574,14 +700,14 @@ func (s *Service) initPOWService() {
|
||||
s.latestEth1Data.BlockTime = header.Time
|
||||
|
||||
if err := s.processPastLogs(ctx); err != nil {
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to process past deposit contract logs")
|
||||
log.Errorf("Unable to process past logs %v", err)
|
||||
s.retryETH1Node(err)
|
||||
continue
|
||||
}
|
||||
// Cache eth1 headers from our voting period.
|
||||
if err := s.cacheHeadersForEth1DataVote(ctx); err != nil {
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to cache headers for execution client votes")
|
||||
log.Errorf("Unable to process past headers %v", err)
|
||||
s.retryETH1Node(err)
|
||||
continue
|
||||
}
|
||||
// Handle edge case with embedded genesis state by fetching genesis header to determine
|
||||
@@ -594,15 +720,15 @@ func (s *Service) initPOWService() {
|
||||
if genHash != [32]byte{} {
|
||||
genHeader, err := s.eth1DataFetcher.HeaderByHash(ctx, genHash)
|
||||
if err != nil {
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to retrieve proof-of-stake genesis block data")
|
||||
log.Errorf("Unable to retrieve genesis ETH1.0 chain header: %v", err)
|
||||
s.retryETH1Node(err)
|
||||
continue
|
||||
}
|
||||
genBlock = genHeader.Number.Uint64()
|
||||
}
|
||||
s.chainStartData.GenesisBlock = genBlock
|
||||
if err := s.savePowchainData(ctx); err != nil {
|
||||
errorLogger(err, "Unable to save execution client data")
|
||||
log.Errorf("Unable to save powchain data: %v", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -631,16 +757,17 @@ func (s *Service) run(done <-chan struct{}) {
|
||||
head, err := s.eth1DataFetcher.HeaderByNumber(s.ctx, nil)
|
||||
if err != nil {
|
||||
log.WithError(err).Debug("Could not fetch latest eth1 header")
|
||||
s.retryETH1Node(err)
|
||||
continue
|
||||
}
|
||||
if eth1HeadIsBehind(head.Time) {
|
||||
s.retryExecutionClientConnection(s.ctx, err)
|
||||
log.WithError(errFarBehind).Debug("Could not get an up to date eth1 header")
|
||||
s.retryETH1Node(errFarBehind)
|
||||
continue
|
||||
}
|
||||
s.processBlockHeader(head)
|
||||
s.handleETH1FollowDistance()
|
||||
s.checkDefaultEndpoint(s.ctx)
|
||||
s.checkDefaultEndpoint()
|
||||
case <-chainstartTicker.C:
|
||||
if s.chainStartData.Chainstarted {
|
||||
chainstartTicker.Stop()
|
||||
@@ -727,6 +854,59 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock
|
||||
return hdr.Number.Uint64(), nil
|
||||
}
|
||||
|
||||
// This performs a health check on our primary endpoint, and if it
|
||||
// is ready to serve we connect to it again. This method is only
|
||||
// relevant if we are on our backup endpoint.
|
||||
func (s *Service) checkDefaultEndpoint() {
|
||||
primaryEndpoint := s.cfg.httpEndpoints[0]
|
||||
// Return early if we are running on our primary
|
||||
// endpoint.
|
||||
if s.cfg.currHttpEndpoint.Equals(primaryEndpoint) {
|
||||
return
|
||||
}
|
||||
|
||||
httpClient, rpcClient, err := s.dialETH1Nodes(primaryEndpoint)
|
||||
if err != nil {
|
||||
log.Debugf("Primary endpoint not ready: %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("Primary endpoint ready again, switching back to it")
|
||||
// Close the clients and let our main connection routine
|
||||
// properly connect with it.
|
||||
httpClient.Close()
|
||||
rpcClient.Close()
|
||||
// Close current active clients.
|
||||
s.closeClients()
|
||||
|
||||
// Switch back to primary endpoint and try connecting
|
||||
// to it again.
|
||||
s.updateCurrHttpEndpoint(primaryEndpoint)
|
||||
s.retryETH1Node(nil)
|
||||
}
|
||||
|
||||
// This is an inefficient way to search for the next endpoint, but given N is expected to be
|
||||
// small ( < 25), it is fine to search this way.
|
||||
func (s *Service) fallbackToNextEndpoint() {
|
||||
currEndpoint := s.cfg.currHttpEndpoint
|
||||
currIndex := 0
|
||||
totalEndpoints := len(s.cfg.httpEndpoints)
|
||||
|
||||
for i, endpoint := range s.cfg.httpEndpoints {
|
||||
if endpoint.Equals(currEndpoint) {
|
||||
currIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
nextIndex := currIndex + 1
|
||||
if nextIndex >= totalEndpoints {
|
||||
nextIndex = 0
|
||||
}
|
||||
s.updateCurrHttpEndpoint(s.cfg.httpEndpoints[nextIndex])
|
||||
if nextIndex != currIndex {
|
||||
log.Infof("Falling back to alternative endpoint: %s", logs.MaskCredentialsLogging(s.cfg.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 *ethpb.ETH1ChainData) error {
|
||||
|
||||
@@ -42,8 +42,6 @@ type goodLogger struct {
|
||||
backend *backends.SimulatedBackend
|
||||
}
|
||||
|
||||
func (_ *goodLogger) Close() {}
|
||||
|
||||
func (g *goodLogger) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- gethTypes.Log) (ethereum.Subscription, error) {
|
||||
if g.backend == nil {
|
||||
return new(event.Feed).Subscribe(ch), nil
|
||||
@@ -82,8 +80,6 @@ type goodFetcher struct {
|
||||
backend *backends.SimulatedBackend
|
||||
}
|
||||
|
||||
func (_ *goodFetcher) Close() {}
|
||||
|
||||
func (g *goodFetcher) HeaderByHash(_ context.Context, hash common.Hash) (*gethTypes.Header, error) {
|
||||
if bytes.Equal(hash.Bytes(), common.BytesToHash([]byte{0}).Bytes()) {
|
||||
return nil, fmt.Errorf("expected block hash to be nonzero %v", hash)
|
||||
@@ -229,6 +225,10 @@ func TestService_Eth1Synced(t *testing.T) {
|
||||
now := time.Now()
|
||||
assert.NoError(t, testAcc.Backend.AdjustTime(now.Sub(time.Unix(int64(currTime), 0))))
|
||||
testAcc.Backend.Commit()
|
||||
|
||||
synced, err := web3Service.isEth1NodeSynced()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, synced, "Expected eth1 nodes to be synced")
|
||||
}
|
||||
|
||||
func TestFollowBlock_OK(t *testing.T) {
|
||||
@@ -472,7 +472,7 @@ func TestInitDepositCacheWithFinalization_OK(t *testing.T) {
|
||||
require.NoError(t, s.cfg.beaconDB.SaveState(context.Background(), emptyState, headRoot))
|
||||
require.NoError(t, stateGen.SaveState(context.Background(), headRoot, emptyState))
|
||||
s.cfg.stateGen = stateGen
|
||||
require.NoError(t, emptyState.SetEth1DepositIndex(3))
|
||||
require.NoError(t, emptyState.SetEth1DepositIndex(2))
|
||||
|
||||
ctx := context.Background()
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(0), Root: headRoot[:]}))
|
||||
@@ -480,8 +480,8 @@ func TestInitDepositCacheWithFinalization_OK(t *testing.T) {
|
||||
|
||||
s.chainStartData.Chainstarted = true
|
||||
require.NoError(t, s.initDepositCaches(context.Background(), ctrs))
|
||||
fDeposits := s.cfg.depositCache.FinalizedDeposits(ctx)
|
||||
deps := s.cfg.depositCache.NonFinalizedDeposits(context.Background(), fDeposits.MerkleTrieIndex, nil)
|
||||
|
||||
deps := s.cfg.depositCache.NonFinalizedDeposits(context.Background(), nil)
|
||||
assert.Equal(t, 0, len(deps))
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ go_library(
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -2,32 +2,25 @@ package testing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
)
|
||||
|
||||
// EngineClient --
|
||||
type EngineClient struct {
|
||||
NewPayloadResp []byte
|
||||
PayloadIDBytes *pb.PayloadIDBytes
|
||||
ForkChoiceUpdatedResp []byte
|
||||
ExecutionPayload *pb.ExecutionPayload
|
||||
ExecutionBlock *pb.ExecutionBlock
|
||||
Err error
|
||||
ErrLatestExecBlock error
|
||||
ErrExecBlockByHash error
|
||||
ErrForkchoiceUpdated error
|
||||
ErrNewPayload error
|
||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||
TerminalBlockHash []byte
|
||||
TerminalBlockHashExists bool
|
||||
NewPayloadResp []byte
|
||||
PayloadIDBytes *pb.PayloadIDBytes
|
||||
ForkChoiceUpdatedResp []byte
|
||||
ExecutionPayload *pb.ExecutionPayload
|
||||
ExecutionBlock *pb.ExecutionBlock
|
||||
Err error
|
||||
ErrLatestExecBlock error
|
||||
ErrExecBlockByHash error
|
||||
ErrForkchoiceUpdated error
|
||||
ErrNewPayload error
|
||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||
}
|
||||
|
||||
// NewPayload --
|
||||
@@ -65,52 +58,3 @@ func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash) (*
|
||||
}
|
||||
return b, e.ErrExecBlockByHash
|
||||
}
|
||||
|
||||
// GetTerminalBlockHash --
|
||||
func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
|
||||
ttd := new(big.Int)
|
||||
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
|
||||
terminalTotalDifficulty, overflows := uint256.FromBig(ttd)
|
||||
if overflows {
|
||||
return nil, false, errors.New("could not convert terminal total difficulty to uint256")
|
||||
}
|
||||
blk, err := e.LatestExecutionBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get latest execution block")
|
||||
}
|
||||
if blk == nil {
|
||||
return nil, false, errors.New("latest execution block is nil")
|
||||
}
|
||||
|
||||
for {
|
||||
b, err := hexutil.DecodeBig(blk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
currentTotalDifficulty, _ := uint256.FromBig(b)
|
||||
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
|
||||
parentHash := bytesutil.ToBytes32(blk.ParentHash)
|
||||
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := e.ExecutionBlockByHash(ctx, parentHash)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
if blockReachedTTD {
|
||||
b, err := hexutil.DecodeBig(parentBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
parentTotalDifficulty, _ := uint256.FromBig(b)
|
||||
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
if !parentReachedTTD {
|
||||
return blk.Hash, true, nil
|
||||
}
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
blk = parentBlk
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +144,6 @@ type RPCClient struct {
|
||||
Backend *backends.SimulatedBackend
|
||||
}
|
||||
|
||||
func (_ *RPCClient) Close() {}
|
||||
|
||||
func (*RPCClient) CallContext(_ context.Context, _ interface{}, _ string, _ ...interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ go_library(
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
@@ -161,6 +162,7 @@ go_test(
|
||||
"@com_github_d4l3k_messagediff//:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_golang_mock//gomock:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
|
||||
@@ -37,24 +37,17 @@ func (vs *Server) StreamBlocksAltair(req *ethpb.StreamBlocksRequest, stream ethp
|
||||
case version.Phase0:
|
||||
phBlk, ok := data.SignedBlock.Proto().(*ethpb.SignedBeaconBlock)
|
||||
if !ok {
|
||||
log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlock")
|
||||
log.Warn("Mismatch between version and block type, was expecting *ethpb.SignedBeaconBlock")
|
||||
continue
|
||||
}
|
||||
b.Block = ðpb.StreamBlocksResponse_Phase0Block{Phase0Block: phBlk}
|
||||
case version.Altair:
|
||||
phBlk, ok := data.SignedBlock.Proto().(*ethpb.SignedBeaconBlockAltair)
|
||||
if !ok {
|
||||
log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlockAltair")
|
||||
log.Warn("Mismatch between version and block type, was expecting *v2.SignedBeaconBlockAltair")
|
||||
continue
|
||||
}
|
||||
b.Block = ðpb.StreamBlocksResponse_AltairBlock{AltairBlock: phBlk}
|
||||
case version.Bellatrix:
|
||||
phBlk, ok := data.SignedBlock.Proto().(*ethpb.SignedBeaconBlockBellatrix)
|
||||
if !ok {
|
||||
log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlockBellatrix")
|
||||
continue
|
||||
}
|
||||
b.Block = ðpb.StreamBlocksResponse_BellatrixBlock{BellatrixBlock: phBlk}
|
||||
}
|
||||
|
||||
if err := stream.Send(b); err != nil {
|
||||
|
||||
@@ -161,7 +161,7 @@ func (vs *Server) depositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1
|
||||
|
||||
finalizedDeposits := vs.DepositFetcher.FinalizedDeposits(ctx)
|
||||
depositTrie = finalizedDeposits.Deposits
|
||||
upToEth1DataDeposits := vs.DepositFetcher.NonFinalizedDeposits(ctx, finalizedDeposits.MerkleTrieIndex, canonicalEth1DataHeight)
|
||||
upToEth1DataDeposits := vs.DepositFetcher.NonFinalizedDeposits(ctx, canonicalEth1DataHeight)
|
||||
insertIndex := finalizedDeposits.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range upToEth1DataDeposits {
|
||||
|
||||
@@ -3,7 +3,11 @@ package validator
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
@@ -177,7 +181,79 @@ func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context) ([]byte, boo
|
||||
return terminalBlockHash.Bytes(), true, nil
|
||||
}
|
||||
|
||||
return vs.ExecutionEngineCaller.GetTerminalBlockHash(ctx)
|
||||
return vs.getPowBlockHashAtTerminalTotalDifficulty(ctx)
|
||||
}
|
||||
|
||||
// This returns the valid terminal block hash based on total difficulty.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
|
||||
// # `pow_chain` abstractly represents all blocks in the PoW chain
|
||||
// for block in pow_chain:
|
||||
// parent = pow_chain[block.parent_hash]
|
||||
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
|
||||
// if block_reached_ttd and not parent_reached_ttd:
|
||||
// return block
|
||||
//
|
||||
// return None
|
||||
func (vs *Server) getPowBlockHashAtTerminalTotalDifficulty(ctx context.Context) ([]byte, bool, error) {
|
||||
ttd := new(big.Int)
|
||||
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
|
||||
terminalTotalDifficulty, overflows := uint256.FromBig(ttd)
|
||||
if overflows {
|
||||
return nil, false, errors.New("could not convert terminal total difficulty to uint256")
|
||||
}
|
||||
blk, err := vs.ExecutionEngineCaller.LatestExecutionBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get latest execution block")
|
||||
}
|
||||
if blk == nil {
|
||||
return nil, false, errors.New("latest execution block is nil")
|
||||
}
|
||||
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return nil, false, ctx.Err()
|
||||
}
|
||||
currentTotalDifficulty, err := tDStringToUint256(blk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
|
||||
parentHash := bytesutil.ToBytes32(blk.ParentHash)
|
||||
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
|
||||
return nil, false, nil
|
||||
}
|
||||
parentBlk, err := vs.ExecutionEngineCaller.ExecutionBlockByHash(ctx, parentHash)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not get parent execution block")
|
||||
}
|
||||
if parentBlk == nil {
|
||||
return nil, false, errors.New("parent execution block is nil")
|
||||
}
|
||||
if blockReachedTTD {
|
||||
parentTotalDifficulty, err := tDStringToUint256(parentBlk.TotalDifficulty)
|
||||
if err != nil {
|
||||
return nil, false, errors.Wrap(err, "could not convert total difficulty to uint256")
|
||||
}
|
||||
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
|
||||
if !parentReachedTTD {
|
||||
log.WithFields(logrus.Fields{
|
||||
"number": blk.Number,
|
||||
"hash": fmt.Sprintf("%#x", bytesutil.Trunc(blk.Hash)),
|
||||
"td": blk.TotalDifficulty,
|
||||
"parentTd": parentBlk.TotalDifficulty,
|
||||
"ttd": terminalTotalDifficulty,
|
||||
}).Info("Retrieved terminal block hash")
|
||||
return blk.Hash, true, nil
|
||||
}
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
blk = parentBlk
|
||||
}
|
||||
}
|
||||
|
||||
// activationEpochNotReached returns true if activation epoch has not been reach.
|
||||
@@ -194,6 +270,18 @@ func activationEpochNotReached(slot types.Slot) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func tDStringToUint256(td string) (*uint256.Int, error) {
|
||||
b, err := hexutil.DecodeBig(td)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i, overflows := uint256.FromBig(b)
|
||||
if overflows {
|
||||
return nil, errors.New("total difficulty overflowed")
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func emptyPayload() *enginev1.ExecutionPayload {
|
||||
return &enginev1.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/holiman/uint256"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
@@ -21,6 +22,26 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
)
|
||||
|
||||
func Test_tDStringToUint256(t *testing.T) {
|
||||
i, err := tDStringToUint256("0x0")
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, uint256.NewInt(0), i)
|
||||
|
||||
i, err = tDStringToUint256("0x10000")
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, uint256.NewInt(65536), i)
|
||||
|
||||
_, err = tDStringToUint256("100")
|
||||
require.ErrorContains(t, "hex string without 0x prefix", err)
|
||||
|
||||
_, err = tDStringToUint256("0xzzzzzz")
|
||||
require.ErrorContains(t, "invalid hex string", err)
|
||||
|
||||
_, err = tDStringToUint256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
require.ErrorContains(t, "hex number > 256 bits", err)
|
||||
}
|
||||
|
||||
func TestServer_activationEpochNotReached(t *testing.T) {
|
||||
require.Equal(t, false, activationEpochNotReached(0))
|
||||
|
||||
@@ -133,6 +154,137 @@ func TestServer_getExecutionPayload(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
paramsTd string
|
||||
currentPowBlock *pb.ExecutionBlock
|
||||
parentPowBlock *pb.ExecutionBlock
|
||||
errLatestExecutionBlk error
|
||||
wantTerminalBlockHash []byte
|
||||
wantExists bool
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "config td overflows",
|
||||
paramsTd: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
errString: "could not convert terminal total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "could not get latest execution block",
|
||||
paramsTd: "1",
|
||||
errLatestExecutionBlk: errors.New("blah"),
|
||||
errString: "could not get latest execution block",
|
||||
},
|
||||
{
|
||||
name: "nil latest execution block",
|
||||
paramsTd: "1",
|
||||
errString: "latest execution block is nil",
|
||||
},
|
||||
{
|
||||
name: "current execution block invalid TD",
|
||||
paramsTd: "1",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
TotalDifficulty: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
|
||||
},
|
||||
errString: "could not convert total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "current execution block has zero hash parent",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: params.BeaconConfig().ZeroHash[:],
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "could not get parent block",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
errString: "could not get parent execution block",
|
||||
},
|
||||
{
|
||||
name: "parent execution block invalid TD",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "1",
|
||||
},
|
||||
errString: "could not convert total difficulty to uint256",
|
||||
},
|
||||
{
|
||||
name: "happy case",
|
||||
paramsTd: "2",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x3",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
wantExists: true,
|
||||
wantTerminalBlockHash: []byte{'a'},
|
||||
},
|
||||
{
|
||||
name: "ttd not reached",
|
||||
paramsTd: "3",
|
||||
currentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'a'},
|
||||
ParentHash: []byte{'b'},
|
||||
TotalDifficulty: "0x2",
|
||||
},
|
||||
parentPowBlock: &pb.ExecutionBlock{
|
||||
Hash: []byte{'b'},
|
||||
ParentHash: []byte{'c'},
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalTotalDifficulty = tt.paramsTd
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
var m map[[32]byte]*pb.ExecutionBlock
|
||||
if tt.parentPowBlock != nil {
|
||||
m = map[[32]byte]*pb.ExecutionBlock{
|
||||
bytesutil.ToBytes32(tt.parentPowBlock.Hash): tt.parentPowBlock,
|
||||
}
|
||||
}
|
||||
vs := &Server{
|
||||
ExecutionEngineCaller: &powtesting.EngineClient{
|
||||
ErrLatestExecBlock: tt.errLatestExecutionBlk,
|
||||
ExecutionBlock: tt.currentPowBlock,
|
||||
BlockByHashMap: m,
|
||||
},
|
||||
}
|
||||
b, e, err := vs.getPowBlockHashAtTerminalTotalDifficulty(context.Background())
|
||||
if tt.errString != "" {
|
||||
require.ErrorContains(t, tt.errString, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, tt.wantExists, e)
|
||||
require.DeepEqual(t, tt.wantTerminalBlockHash, b)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -116,14 +116,21 @@ type Config struct {
|
||||
// be registered into a running beacon node.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
s := &Service{
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
incomingAttestation: make(chan *ethpbv1alpha1.Attestation, params.BeaconConfig().DefaultBufferSize),
|
||||
connectedRPCClients: make(map[net.Addr]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// paranoid build time check to ensure ChainInfoFetcher implements required interfaces
|
||||
var _ stategen.CanonicalChecker = blockchain.ChainInfoFetcher(nil)
|
||||
var _ stategen.CurrentSlotter = blockchain.ChainInfoFetcher(nil)
|
||||
|
||||
// Start the gRPC server.
|
||||
func (s *Service) Start() {
|
||||
address := fmt.Sprintf("%s:%s", s.cfg.Host, s.cfg.Port)
|
||||
lis, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
@@ -152,6 +159,7 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
)),
|
||||
grpc.MaxRecvMsgSize(s.cfg.MaxMsgSize),
|
||||
}
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
if s.cfg.CertFlag != "" && s.cfg.KeyFlag != "" {
|
||||
creds, err := credentials.NewServerTLSFromFile(s.cfg.CertFlag, s.cfg.KeyFlag)
|
||||
if err != nil {
|
||||
@@ -165,17 +173,6 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
}
|
||||
s.grpcServer = grpc.NewServer(opts...)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// paranoid build time check to ensure ChainInfoFetcher implements required interfaces
|
||||
var _ stategen.CanonicalChecker = blockchain.ChainInfoFetcher(nil)
|
||||
var _ stategen.CurrentSlotter = blockchain.ChainInfoFetcher(nil)
|
||||
|
||||
// Start the gRPC server.
|
||||
func (s *Service) Start() {
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
|
||||
var stateCache stategen.CachedGetter
|
||||
if s.cfg.StateGen != nil {
|
||||
stateCache = s.cfg.StateGen.CombinedCache()
|
||||
|
||||
@@ -56,7 +56,7 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
numOfElems: retrieveLength(elements),
|
||||
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
|
||||
}, nil
|
||||
case types.CompositeArray, types.CompressedArray:
|
||||
return &FieldTrie{
|
||||
@@ -66,7 +66,7 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
numOfElems: retrieveLength(elements),
|
||||
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(dataType).Name())
|
||||
@@ -97,14 +97,14 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
return fieldRoot, nil
|
||||
case types.CompositeArray:
|
||||
fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayerVariable(fieldRoots, indices, f.fieldLayers)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
return stateutil.AddInMixin(fieldRoot, uint64(len(f.fieldLayers[0])))
|
||||
case types.CompressedArray:
|
||||
numOfElems, err := f.field.ElemsInChunk()
|
||||
@@ -133,7 +133,7 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
return stateutil.AddInMixin(fieldRoot, uint64(f.numOfElems))
|
||||
default:
|
||||
return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(f.dataType).Name())
|
||||
|
||||
@@ -57,11 +57,9 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements
|
||||
}
|
||||
length *= comLength
|
||||
}
|
||||
elemLen := retrieveLength(elements)
|
||||
|
||||
castedLen := int(length) // lint:ignore uintcast- ajhdjhd
|
||||
if elemLen > castedLen {
|
||||
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), elemLen, length)
|
||||
val := reflect.Indirect(reflect.ValueOf(elements))
|
||||
if uint64(val.Len()) > length {
|
||||
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), val.Len(), length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -74,7 +72,7 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.BlockRoots:
|
||||
return handleIndexer(val, indices, convertAll)
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for block roots")
|
||||
}
|
||||
@@ -92,7 +90,7 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.RandaoMixes:
|
||||
return handleIndexer(val, indices, convertAll)
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for randao mixes")
|
||||
}
|
||||
@@ -184,34 +182,6 @@ func handle32ByteArrays(val [][32]byte, indices []uint64, convertAll bool) ([][3
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
// handle32ByteArrays computes and returns 32 byte arrays in a slice of root format.
|
||||
func handleIndexer(indexer customtypes.Indexer, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
totalLength := indexer.TotalLength()
|
||||
if convertAll {
|
||||
length = int(totalLength) // lint:ignore uintcast- ajhdjhd
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
rootCreator := func(input [32]byte) {
|
||||
roots = append(roots, input)
|
||||
}
|
||||
if convertAll {
|
||||
for i := uint64(0); i < uint64(length); i++ {
|
||||
rootCreator(indexer.RootAtIndex(i))
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
if totalLength > 0 {
|
||||
for _, idx := range indices {
|
||||
if idx > totalLength-1 {
|
||||
return nil, fmt.Errorf("index %d greater than number of byte arrays %d", idx, totalLength)
|
||||
}
|
||||
rootCreator(indexer.RootAtIndex(idx))
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
// handleValidatorSlice returns the validator indices in a slice of root format.
|
||||
func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
@@ -378,17 +348,3 @@ func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, err
|
||||
}
|
||||
return [][32]byte{}, nil
|
||||
}
|
||||
|
||||
func retrieveLength(elements interface{}) int {
|
||||
elemLen := int(0)
|
||||
elemVal := reflect.ValueOf(elements)
|
||||
if reflect.Indirect(elemVal).Kind() == reflect.Struct {
|
||||
meth := elemVal.MethodByName("TotalLength")
|
||||
ret := meth.Call([]reflect.Value{})
|
||||
elemLen = int(ret[0].Uint()) // lint:ignore uintcast- ajhdjhd
|
||||
} else {
|
||||
val := reflect.Indirect(elemVal)
|
||||
elemLen = val.Len()
|
||||
}
|
||||
return elemLen
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -2,162 +2,28 @@ package customtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
fssz "github.com/ferranbt/fastssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (*BlockRoots)(nil)
|
||||
var _ fssz.HashRoot = (BlockRoots)([fieldparams.BlockRootsLength][32]byte{})
|
||||
var _ fssz.Marshaler = (*BlockRoots)(nil)
|
||||
var _ fssz.Unmarshaler = (*BlockRoots)(nil)
|
||||
|
||||
type Indexer interface {
|
||||
RootAtIndex(idx uint64) [32]byte
|
||||
TotalLength() uint64
|
||||
}
|
||||
|
||||
// BlockRoots represents block roots of the beacon state.
|
||||
type BlockRoots struct {
|
||||
baseArray *baseArrayBlockRoots
|
||||
fieldJournal map[uint64][32]byte
|
||||
generation uint64
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type baseArrayBlockRoots struct {
|
||||
baseArray *[fieldparams.BlockRootsLength][32]byte
|
||||
descendantMap map[uint64][]uintptr
|
||||
*sync.RWMutex
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type sorter struct {
|
||||
objs [][]uintptr
|
||||
generations []uint64
|
||||
}
|
||||
|
||||
func (s sorter) Len() int {
|
||||
return len(s.generations)
|
||||
}
|
||||
|
||||
func (s sorter) Swap(i, j int) {
|
||||
s.objs[i], s.objs[j] = s.objs[j], s.objs[i]
|
||||
s.generations[i], s.generations[j] = s.generations[j], s.generations[i]
|
||||
}
|
||||
|
||||
func (s sorter) Less(i, j int) bool {
|
||||
return s.generations[i] < s.generations[j]
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) RootAtIndex(idx uint64) [32]byte {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return b.baseArray[idx]
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) TotalLength() uint64 {
|
||||
return fieldparams.BlockRootsLength
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) addGeneration(generation uint64, descendant uintptr) {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
b.descendantMap[generation] = append(b.descendantMap[generation], descendant)
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) removeGeneration(generation uint64, descendant uintptr) {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
ptrVals := b.descendantMap[generation]
|
||||
newVals := []uintptr{}
|
||||
for _, v := range ptrVals {
|
||||
if v == descendant {
|
||||
continue
|
||||
}
|
||||
newVals = append(newVals, v)
|
||||
}
|
||||
b.descendantMap[generation] = newVals
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) numOfDescendants() uint64 {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return uint64(len(b.descendantMap))
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) cleanUp() {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
fmt.Printf("\n cleaning up block roots %d \n ", len(b.descendantMap))
|
||||
listOfObjs := [][]uintptr{}
|
||||
generations := []uint64{}
|
||||
for g, objs := range b.descendantMap {
|
||||
generations = append(generations, g)
|
||||
listOfObjs = append(listOfObjs, objs)
|
||||
}
|
||||
sortedObj := sorter{
|
||||
objs: listOfObjs,
|
||||
generations: generations,
|
||||
}
|
||||
sort.Sort(sortedObj)
|
||||
lastReferencedGen := 0
|
||||
lastRefrencedIdx := 0
|
||||
lastRefPointer := 0
|
||||
for i, g := range sortedObj.generations {
|
||||
for j, o := range sortedObj.objs[i] {
|
||||
|
||||
x := (*BlockRoots)(unsafe.Pointer(o))
|
||||
if x == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
lastReferencedGen = int(g) // lint:ignore uintcast- ajhdjhd
|
||||
lastRefrencedIdx = i
|
||||
lastRefPointer = j
|
||||
break
|
||||
}
|
||||
if lastReferencedGen != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n block root map %d, %d, %d \n ", lastReferencedGen, lastRefrencedIdx, lastRefPointer)
|
||||
|
||||
br := (*BlockRoots)(unsafe.Pointer(sortedObj.objs[lastRefrencedIdx][lastRefPointer]))
|
||||
for k, v := range br.fieldJournal {
|
||||
b.baseArray[k] = v
|
||||
}
|
||||
sortedObj.generations = sortedObj.generations[lastRefrencedIdx:]
|
||||
sortedObj.objs = sortedObj.objs[lastRefrencedIdx:]
|
||||
|
||||
newMap := make(map[uint64][]uintptr)
|
||||
for i, g := range sortedObj.generations {
|
||||
newMap[g] = sortedObj.objs[i]
|
||||
}
|
||||
b.descendantMap = newMap
|
||||
}
|
||||
type BlockRoots [fieldparams.BlockRootsLength][32]byte
|
||||
|
||||
// HashTreeRoot returns calculated hash root.
|
||||
func (r *BlockRoots) HashTreeRoot() ([32]byte, error) {
|
||||
func (r BlockRoots) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(r)
|
||||
}
|
||||
|
||||
// HashTreeRootWith hashes a BlockRoots object with a Hasher from the default HasherPool.
|
||||
func (r *BlockRoots) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
func (r BlockRoots) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
index := hh.Index()
|
||||
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
hh.Append(val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
hh.Append(rt[:])
|
||||
for _, sRoot := range r {
|
||||
hh.Append(sRoot[:])
|
||||
}
|
||||
hh.Merkleize(index)
|
||||
return nil
|
||||
@@ -168,13 +34,12 @@ func (r *BlockRoots) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != r.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
|
||||
}
|
||||
r.baseArray.Lock()
|
||||
defer r.baseArray.Unlock()
|
||||
|
||||
for i := range r.baseArray.baseArray {
|
||||
copy(r.baseArray.baseArray[i][:], buf[i*32:(i+1)*32])
|
||||
var roots BlockRoots
|
||||
for i := range roots {
|
||||
copy(roots[i][:], buf[i*32:(i+1)*32])
|
||||
}
|
||||
|
||||
*r = roots
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -190,13 +55,10 @@ func (r *BlockRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
// MarshalSSZ marshals BlockRoots into a serialized object.
|
||||
func (r *BlockRoots) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := make([]byte, fieldparams.BlockRootsLength*32)
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
copy(marshalled[i*32:], val[:])
|
||||
continue
|
||||
for i, r32 := range r {
|
||||
for j, rr := range r32 {
|
||||
marshalled[i*32+j] = rr
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
copy(marshalled[i*32:], rt[:])
|
||||
}
|
||||
return marshalled, nil
|
||||
}
|
||||
@@ -211,152 +73,10 @@ func (r *BlockRoots) Slice() [][]byte {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
bRoots := make([][]byte, r.baseArray.TotalLength())
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val[:]
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt[:]
|
||||
bRoots := make([][]byte, len(r))
|
||||
for i, root := range r {
|
||||
tmp := root
|
||||
bRoots[i] = tmp[:]
|
||||
}
|
||||
return bRoots
|
||||
}
|
||||
|
||||
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
|
||||
func (r *BlockRoots) Array() [fieldparams.BlockRootsLength][32]byte {
|
||||
if r == nil {
|
||||
return [fieldparams.BlockRootsLength][32]byte{}
|
||||
}
|
||||
bRoots := [fieldparams.BlockRootsLength][32]byte{}
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt
|
||||
}
|
||||
return bRoots
|
||||
}
|
||||
|
||||
func SetFromSlice(slice [][]byte) *BlockRoots {
|
||||
br := &BlockRoots{
|
||||
baseArray: &baseArrayBlockRoots{
|
||||
baseArray: new([fieldparams.BlockRootsLength][32]byte),
|
||||
descendantMap: map[uint64][]uintptr{},
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
},
|
||||
fieldJournal: map[uint64][32]byte{},
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
for i, rt := range slice {
|
||||
copy(br.baseArray.baseArray[i][:], rt)
|
||||
}
|
||||
runtime.SetFinalizer(br, blockRootsFinalizer)
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *BlockRoots) SetFromBaseField(field [fieldparams.BlockRootsLength][32]byte) {
|
||||
r.baseArray = &baseArrayBlockRoots{
|
||||
baseArray: &field,
|
||||
descendantMap: map[uint64][]uintptr{},
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
r.fieldJournal = map[uint64][32]byte{}
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.baseArray.addGeneration(0, reflect.ValueOf(r).Pointer())
|
||||
runtime.SetFinalizer(r, blockRootsFinalizer)
|
||||
}
|
||||
|
||||
func (r *BlockRoots) RootAtIndex(idx uint64) [32]byte {
|
||||
if val, ok := r.fieldJournal[idx]; ok {
|
||||
return val
|
||||
}
|
||||
return r.baseArray.RootAtIndex(idx)
|
||||
}
|
||||
|
||||
func (r *BlockRoots) SetRootAtIndex(idx uint64, val [32]byte) {
|
||||
if r.Refs() <= 1 && r.baseArray.Refs() <= 1 {
|
||||
r.baseArray.Lock()
|
||||
r.baseArray.baseArray[idx] = val
|
||||
r.baseArray.Unlock()
|
||||
return
|
||||
}
|
||||
if r.Refs() <= 1 {
|
||||
r.fieldJournal[idx] = val
|
||||
r.baseArray.removeGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
r.generation++
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
return
|
||||
}
|
||||
newJournal := make(map[uint64][32]byte)
|
||||
for k, val := range r.fieldJournal {
|
||||
newJournal[k] = val
|
||||
}
|
||||
|
||||
r.fieldJournal = newJournal
|
||||
r.MinusRef()
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.fieldJournal[idx] = val
|
||||
r.baseArray.removeGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
r.generation++
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
}
|
||||
|
||||
func (r *BlockRoots) Copy() *BlockRoots {
|
||||
r.baseArray.AddRef()
|
||||
r.Reference.AddRef()
|
||||
br := &BlockRoots{
|
||||
baseArray: r.baseArray,
|
||||
fieldJournal: r.fieldJournal,
|
||||
Reference: r.Reference,
|
||||
generation: r.generation,
|
||||
}
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(br).Pointer())
|
||||
if r.baseArray.numOfDescendants() > 20 {
|
||||
r.baseArray.cleanUp()
|
||||
}
|
||||
runtime.SetFinalizer(br, blockRootsFinalizer)
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *BlockRoots) TotalLength() uint64 {
|
||||
return fieldparams.BlockRootsLength
|
||||
}
|
||||
|
||||
func (r *BlockRoots) IncreaseRef() {
|
||||
r.Reference.AddRef()
|
||||
r.baseArray.Reference.AddRef()
|
||||
}
|
||||
|
||||
func (r *BlockRoots) DecreaseRef() {
|
||||
r.Reference.MinusRef()
|
||||
r.baseArray.Reference.MinusRef()
|
||||
}
|
||||
|
||||
func blockRootsFinalizer(br *BlockRoots) {
|
||||
br.baseArray.Lock()
|
||||
defer br.baseArray.Unlock()
|
||||
ptrVal := reflect.ValueOf(br).Pointer()
|
||||
vals, ok := br.baseArray.descendantMap[br.generation]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
exists := false
|
||||
wantedVals := []uintptr{}
|
||||
for _, v := range vals {
|
||||
if v == ptrVal {
|
||||
exists = true
|
||||
continue
|
||||
}
|
||||
newV := v
|
||||
wantedVals = append(wantedVals, newV)
|
||||
}
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
br.baseArray.descendantMap[br.generation] = wantedVals
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
package customtypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
)
|
||||
|
||||
func TestBlockRoots_Casting(t *testing.T) {
|
||||
var b [fieldparams.BlockRootsLength][32]byte
|
||||
f := SetFromSlice([][]byte{})
|
||||
f.SetFromBaseField(b)
|
||||
if !reflect.DeepEqual(f.Array(), b) {
|
||||
t.Errorf("Unequal: %v = %v", f.Array(), b)
|
||||
d := BlockRoots(b)
|
||||
if !reflect.DeepEqual([fieldparams.BlockRootsLength][32]byte(d), b) {
|
||||
t.Errorf("Unequal: %v = %v", d, b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockRoots_UnmarshalSSZ(t *testing.T) {
|
||||
t.Run("Ok", func(t *testing.T) {
|
||||
d := SetFromSlice([][]byte{})
|
||||
d := BlockRoots{}
|
||||
var b [fieldparams.BlockRootsLength][32]byte
|
||||
b[0] = [32]byte{'f', 'o', 'o'}
|
||||
b[1] = [32]byte{'b', 'a', 'r'}
|
||||
@@ -33,8 +32,8 @@ func TestBlockRoots_UnmarshalSSZ(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(b, d.Array()) {
|
||||
t.Errorf("Unequal: %v = %v", b, d.Array())
|
||||
if !reflect.DeepEqual(b, [fieldparams.BlockRootsLength][32]byte(d)) {
|
||||
t.Errorf("Unequal: %v = %v", b, [fieldparams.BlockRootsLength][32]byte(d))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -71,47 +70,28 @@ func TestBlockRoots_MarshalSSZTo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockRoots_MarshalSSZ(t *testing.T) {
|
||||
d := SetFromSlice([][]byte{})
|
||||
d.IncreaseRef()
|
||||
d.SetRootAtIndex(0, [32]byte{'f', 'o', 'o'})
|
||||
d.IncreaseRef()
|
||||
d.IncreaseRef()
|
||||
d.SetRootAtIndex(1, [32]byte{'b', 'a', 'r'})
|
||||
d := BlockRoots{}
|
||||
d[0] = [32]byte{'f', 'o', 'o'}
|
||||
d[1] = [32]byte{'b', 'a', 'r'}
|
||||
b, err := d.MarshalSSZ()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
rt := d.RootAtIndex(0)
|
||||
if !reflect.DeepEqual(rt[:], b[0:32]) {
|
||||
t.Errorf("Unequal: %v = %v", rt, b[0:32])
|
||||
if !reflect.DeepEqual(d[0][:], b[0:32]) {
|
||||
t.Errorf("Unequal: %v = %v", d[0], b[0:32])
|
||||
}
|
||||
rt = d.RootAtIndex(1)
|
||||
if !reflect.DeepEqual(rt[:], b[32:64]) {
|
||||
t.Errorf("Unequal: %v = %v", rt, b[32:64])
|
||||
}
|
||||
d2 := SetFromSlice([][]byte{})
|
||||
err = d2.UnmarshalSSZ(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
res, err := d2.MarshalSSZ()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !bytes.Equal(res, b) {
|
||||
t.Error("unequal")
|
||||
if !reflect.DeepEqual(d[1][:], b[32:64]) {
|
||||
t.Errorf("Unequal: %v = %v", d[0], b[32:64])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockRoots_SizeSSZ(t *testing.T) {
|
||||
d := SetFromSlice([][]byte{})
|
||||
d := BlockRoots{}
|
||||
if d.SizeSSZ() != fieldparams.BlockRootsLength*32 {
|
||||
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.BlockRootsLength*32, d.SizeSSZ())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
func TestBlockRoots_Slice(t *testing.T) {
|
||||
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
|
||||
roots := BlockRoots{}
|
||||
@@ -123,4 +103,3 @@ func TestBlockRoots_Slice(t *testing.T) {
|
||||
assert.DeepEqual(t, b[:], slice[10])
|
||||
assert.DeepEqual(t, c[:], slice[100])
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -2,77 +2,48 @@ package customtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
fssz "github.com/ferranbt/fastssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (*RandaoMixes)(nil)
|
||||
var _ fssz.HashRoot = (RandaoMixes)([fieldparams.RandaoMixesLength][32]byte{})
|
||||
var _ fssz.Marshaler = (*RandaoMixes)(nil)
|
||||
var _ fssz.Unmarshaler = (*RandaoMixes)(nil)
|
||||
|
||||
// BlockRoots represents block roots of the beacon state.
|
||||
type RandaoMixes struct {
|
||||
baseArray *baseArrayRandaoMixes
|
||||
fieldJournal map[uint64][32]byte
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type baseArrayRandaoMixes struct {
|
||||
baseArray *[fieldparams.RandaoMixesLength][32]byte
|
||||
*sync.RWMutex
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
func (b *baseArrayRandaoMixes) RootAtIndex(idx uint64) [32]byte {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return b.baseArray[idx]
|
||||
}
|
||||
|
||||
func (b *baseArrayRandaoMixes) TotalLength() uint64 {
|
||||
return fieldparams.RandaoMixesLength
|
||||
}
|
||||
// RandaoMixes represents RANDAO mixes of the beacon state.
|
||||
type RandaoMixes [fieldparams.RandaoMixesLength][32]byte
|
||||
|
||||
// HashTreeRoot returns calculated hash root.
|
||||
func (r *RandaoMixes) HashTreeRoot() ([32]byte, error) {
|
||||
func (r RandaoMixes) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(r)
|
||||
}
|
||||
|
||||
// HashTreeRootWith hashes a BlockRoots object with a Hasher from the default HasherPool.
|
||||
func (r *RandaoMixes) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
// HashTreeRootWith hashes a RandaoMixes object with a Hasher from the default HasherPool.
|
||||
func (r RandaoMixes) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
index := hh.Index()
|
||||
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
hh.Append(val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
hh.Append(rt[:])
|
||||
for _, sRoot := range r {
|
||||
hh.Append(sRoot[:])
|
||||
}
|
||||
hh.Merkleize(index)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSSZ deserializes the provided bytes buffer into the BlockRoots object.
|
||||
// UnmarshalSSZ deserializes the provided bytes buffer into the RandaoMixes object.
|
||||
func (r *RandaoMixes) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != r.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
|
||||
}
|
||||
r.baseArray.Lock()
|
||||
defer r.baseArray.Unlock()
|
||||
|
||||
for i := range r.baseArray.baseArray {
|
||||
copy(r.baseArray.baseArray[i][:], buf[i*32:(i+1)*32])
|
||||
var roots RandaoMixes
|
||||
for i := range roots {
|
||||
copy(roots[i][:], buf[i*32:(i+1)*32])
|
||||
}
|
||||
|
||||
*r = roots
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalSSZTo marshals BlockRoots with the provided byte slice.
|
||||
// MarshalSSZTo marshals RandaoMixes with the provided byte slice.
|
||||
func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
marshalled, err := r.MarshalSSZ()
|
||||
if err != nil {
|
||||
@@ -81,16 +52,13 @@ func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return append(dst, marshalled...), nil
|
||||
}
|
||||
|
||||
// MarshalSSZ marshals BlockRoots into a serialized object.
|
||||
// MarshalSSZ marshals RandaoMixes into a serialized object.
|
||||
func (r *RandaoMixes) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := make([]byte, fieldparams.RandaoMixesLength*32)
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
copy(marshalled[i*32:], val[:])
|
||||
continue
|
||||
for i, r32 := range r {
|
||||
for j, rr := range r32 {
|
||||
marshalled[i*32+j] = rr
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
copy(marshalled[i*32:], rt[:])
|
||||
}
|
||||
return marshalled, nil
|
||||
}
|
||||
@@ -100,90 +68,15 @@ func (_ *RandaoMixes) SizeSSZ() int {
|
||||
return fieldparams.RandaoMixesLength * 32
|
||||
}
|
||||
|
||||
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
|
||||
// Slice converts a customtypes.RandaoMixes object into a 2D byte slice.
|
||||
func (r *RandaoMixes) Slice() [][]byte {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
bRoots := make([][]byte, r.baseArray.TotalLength())
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val[:]
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt[:]
|
||||
mixes := make([][]byte, len(r))
|
||||
for i, root := range r {
|
||||
tmp := root
|
||||
mixes[i] = tmp[:]
|
||||
}
|
||||
return bRoots
|
||||
}
|
||||
|
||||
func SetFromSliceRandao(slice [][]byte) *RandaoMixes {
|
||||
br := &RandaoMixes{
|
||||
baseArray: &baseArrayRandaoMixes{
|
||||
baseArray: new([fieldparams.RandaoMixesLength][32]byte),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
},
|
||||
fieldJournal: map[uint64][32]byte{},
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
for i, rt := range slice {
|
||||
copy(br.baseArray.baseArray[i][:], rt)
|
||||
}
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) SetFromBaseField(field [fieldparams.RandaoMixesLength][32]byte) {
|
||||
r.baseArray.baseArray = &field
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) RootAtIndex(idx uint64) [32]byte {
|
||||
if val, ok := r.fieldJournal[idx]; ok {
|
||||
return val
|
||||
}
|
||||
return r.baseArray.RootAtIndex(idx)
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) SetRootAtIndex(idx uint64, val [32]byte) {
|
||||
if r.Refs() <= 1 && r.baseArray.Refs() <= 1 {
|
||||
r.baseArray.baseArray[idx] = val
|
||||
return
|
||||
}
|
||||
if r.Refs() <= 1 {
|
||||
r.fieldJournal[idx] = val
|
||||
return
|
||||
}
|
||||
newJournal := make(map[uint64][32]byte)
|
||||
for k, val := range r.fieldJournal {
|
||||
newJournal[k] = val
|
||||
}
|
||||
r.fieldJournal = newJournal
|
||||
r.MinusRef()
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.fieldJournal[idx] = val
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) Copy() *RandaoMixes {
|
||||
r.baseArray.AddRef()
|
||||
r.Reference.AddRef()
|
||||
rm := &RandaoMixes{
|
||||
baseArray: r.baseArray,
|
||||
fieldJournal: r.fieldJournal,
|
||||
Reference: r.Reference,
|
||||
}
|
||||
return rm
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) TotalLength() uint64 {
|
||||
return fieldparams.RandaoMixesLength
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) IncreaseRef() {
|
||||
r.Reference.AddRef()
|
||||
r.baseArray.Reference.AddRef()
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) DecreaseRef() {
|
||||
r.Reference.MinusRef()
|
||||
r.baseArray.Reference.MinusRef()
|
||||
return mixes
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
return b.blockRoots[idx], nil
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
return b.randaoMixes[idx], nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -62,5 +62,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
return len(b.randaoMixes)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -24,12 +25,14 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][32]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -39,13 +42,24 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,6 +3,7 @@ package v1
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -13,12 +14,14 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -28,13 +31,24 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -36,8 +36,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
copy(bRoots[i][:], r)
|
||||
}
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
copy(sRoots[i][:], r)
|
||||
@@ -46,7 +48,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
for i, r := range st.HistoricalRoots {
|
||||
copy(hRoots[i][:], r)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
copy(mixes[i][:], m)
|
||||
}
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -55,7 +60,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: bRoots,
|
||||
blockRoots: &bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -63,7 +68,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: mixes,
|
||||
randaoMixes: &mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochAttestations: st.PreviousEpochAttestations,
|
||||
currentEpochAttestations: st.CurrentEpochAttestations,
|
||||
@@ -94,6 +99,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -121,9 +127,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
slashings: b.slashings,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
blockRoots: b.blockRoots,
|
||||
stateRoots: b.stateRoots,
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
randaoMixes: b.randaoMixes,
|
||||
previousEpochAttestations: b.previousEpochAttestations,
|
||||
currentEpochAttestations: b.currentEpochAttestations,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
@@ -205,9 +211,6 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
}
|
||||
|
||||
}
|
||||
b.blockRoots.MinusRef()
|
||||
b.randaoMixes.MinusRef()
|
||||
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -76,8 +76,9 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
|
||||
return b.blockRoots[idx], nil
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
|
||||
return b.randaoMixes[idx], nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -62,5 +63,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
return len(b.randaoMixes)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -24,12 +25,14 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][32]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -39,13 +42,24 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,6 +3,7 @@ package v2
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -13,12 +14,14 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -28,13 +31,24 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
@@ -45,7 +47,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
for i, r := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -54,7 +59,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: bRoots,
|
||||
blockRoots: &bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -62,7 +67,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: mixes,
|
||||
randaoMixes: &mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
@@ -96,6 +101,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -122,9 +128,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
blockRoots: b.blockRoots,
|
||||
stateRoots: b.stateRoots,
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
randaoMixes: b.randaoMixes,
|
||||
slashings: b.slashings,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
|
||||
@@ -209,8 +215,6 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
b.blockRoots.DecreaseRef()
|
||||
b.randaoMixes.DecreaseRef()
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -76,8 +76,9 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
|
||||
return b.blockRoots[idx], nil
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
|
||||
return b.randaoMixes[idx], nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -62,5 +63,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
return len(b.randaoMixes)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -24,12 +25,14 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][fieldparams.RootLength]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -39,13 +42,24 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,6 +3,7 @@ package v3
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -13,12 +14,14 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][fieldparams.RootLength]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -28,13 +31,24 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -36,8 +36,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
@@ -46,7 +48,10 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
for i, r := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -55,7 +60,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: bRoots,
|
||||
blockRoots: &bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -63,7 +68,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: mixes,
|
||||
randaoMixes: &mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
@@ -96,7 +101,9 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
}
|
||||
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -123,9 +130,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
randaoMixes: b.randaoMixes,
|
||||
stateRoots: b.stateRoots,
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
blockRoots: b.blockRoots,
|
||||
slashings: b.slashings,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
|
||||
@@ -201,7 +208,6 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
@@ -211,9 +217,6 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
b.blockRoots.DecreaseRef()
|
||||
b.randaoMixes.DecreaseRef()
|
||||
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -49,29 +49,30 @@ type Service struct {
|
||||
synced *abool.AtomicBool
|
||||
chainStarted *abool.AtomicBool
|
||||
counter *ratecounter.RateCounter
|
||||
genesisChan chan time.Time
|
||||
}
|
||||
|
||||
// NewService configures the initial sync service responsible for bringing the node up to the
|
||||
// latest head of the blockchain.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Service{
|
||||
s := &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
synced: abool.New(),
|
||||
chainStarted: abool.New(),
|
||||
counter: ratecounter.NewRateCounter(counterSeconds * time.Second),
|
||||
genesisChan: make(chan time.Time),
|
||||
}
|
||||
go s.waitForStateInitialization()
|
||||
return s
|
||||
}
|
||||
|
||||
// Start the initial sync service.
|
||||
func (s *Service) Start() {
|
||||
genesis, err := s.waitForStateInitialization()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Failed to wait for state initialization.")
|
||||
return
|
||||
}
|
||||
// Wait for state initialized event.
|
||||
genesis := <-s.genesisChan
|
||||
if genesis.IsZero() {
|
||||
log.Debug("Exiting Initial Sync Service")
|
||||
return
|
||||
@@ -179,10 +180,9 @@ func (s *Service) waitForMinimumPeers() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return error
|
||||
// waitForStateInitialization makes sure that beacon node is ready to be accessed: it is either
|
||||
// already properly configured or system waits up until state initialized event is triggered.
|
||||
func (s *Service) waitForStateInitialization() (time.Time, error) {
|
||||
func (s *Service) waitForStateInitialization() {
|
||||
// Wait for state to be initialized.
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
@@ -198,14 +198,19 @@ func (s *Service) waitForStateInitialization() (time.Time, error) {
|
||||
continue
|
||||
}
|
||||
log.WithField("starttime", data.StartTime).Debug("Received state initialized event")
|
||||
return data.StartTime, nil
|
||||
s.genesisChan <- data.StartTime
|
||||
return
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
log.Debug("Context closed, exiting goroutine")
|
||||
// Send a zero time in the event we are exiting.
|
||||
return time.Time{}, errors.New("context closed, exiting goroutine")
|
||||
s.genesisChan <- time.Time{}
|
||||
return
|
||||
case err := <-stateSub.Err():
|
||||
log.WithError(err).Error("Subscription to state notifier failed")
|
||||
// Send a zero time in the event we are exiting.
|
||||
return time.Time{}, errors.Wrap(err, "subscription to state notifier failed")
|
||||
s.genesisChan <- time.Time{}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,11 @@ func TestService_InitStartStop(t *testing.T) {
|
||||
Chain: mc,
|
||||
StateNotifier: notifier,
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.NotNil(t, s)
|
||||
if tt.methodRuns != nil {
|
||||
tt.methodRuns(notifier.StateFeed())
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
@@ -177,11 +181,6 @@ func TestService_InitStartStop(t *testing.T) {
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if tt.methodRuns != nil {
|
||||
tt.methodRuns(notifier.StateFeed())
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Allow to exit from test (on no head loop waiting for head is started).
|
||||
// In most tests, this is redundant, as Start() already exited.
|
||||
@@ -208,6 +207,7 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
synced: abool.New(),
|
||||
chainStarted: abool.New(),
|
||||
counter: ratecounter.NewRateCounter(counterSeconds * time.Second),
|
||||
genesisChan: make(chan time.Time),
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -221,8 +221,9 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
_, err := s.waitForStateInitialization()
|
||||
assert.ErrorContains(t, "context closed", err)
|
||||
go s.waitForStateInitialization()
|
||||
currTime := <-s.genesisChan
|
||||
assert.Equal(t, true, currTime.IsZero())
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
@@ -235,6 +236,8 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
t.Fatalf("Test should have exited by now, timed out")
|
||||
}
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Context closed, exiting goroutine")
|
||||
assert.LogsDoNotContain(t, hook, "Subscription to state notifier failed")
|
||||
})
|
||||
|
||||
t.Run("no state and state init event received", func(t *testing.T) {
|
||||
@@ -248,9 +251,8 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
var err error
|
||||
receivedGenesisTime, err = s.waitForStateInitialization()
|
||||
require.NoError(t, err)
|
||||
go s.waitForStateInitialization()
|
||||
receivedGenesisTime = <-s.genesisChan
|
||||
assert.Equal(t, false, receivedGenesisTime.IsZero())
|
||||
wg.Done()
|
||||
}()
|
||||
@@ -279,6 +281,7 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
assert.LogsContain(t, hook, "Event feed data is not type *statefeed.InitializedData")
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Received state initialized event")
|
||||
assert.LogsDoNotContain(t, hook, "Context closed, exiting goroutine")
|
||||
})
|
||||
|
||||
t.Run("no state and state init event received and service start", func(t *testing.T) {
|
||||
@@ -293,8 +296,7 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
_, err := s.waitForStateInitialization()
|
||||
require.NoError(t, err)
|
||||
s.waitForStateInitialization()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
@@ -319,6 +321,7 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
}
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Received state initialized event")
|
||||
assert.LogsDoNotContain(t, hook, "Context closed, exiting goroutine")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ func NewService(ctx context.Context, opts ...Option) *Service {
|
||||
}
|
||||
r.subHandler = newSubTopicHandler()
|
||||
r.rateLimiter = newRateLimiter(r.cfg.p2p)
|
||||
r.initCaches()
|
||||
|
||||
go r.registerHandlers()
|
||||
go r.verifierRoutine()
|
||||
@@ -164,6 +163,8 @@ func NewService(ctx context.Context, opts ...Option) *Service {
|
||||
|
||||
// Start the regular sync service.
|
||||
func (s *Service) Start() {
|
||||
s.initCaches()
|
||||
|
||||
s.cfg.p2p.AddConnectionHandler(s.reValidatePeer, s.sendGoodbye)
|
||||
s.cfg.p2p.AddDisconnectionHandler(func(_ context.Context, _ peer.ID) error {
|
||||
// no-op
|
||||
|
||||
@@ -15,7 +15,7 @@ var (
|
||||
HTTPWeb3ProviderFlag = &cli.StringFlag{
|
||||
Name: "http-web3provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint. Can contain auth header as well in the format --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Basic xxx\" for project secret (base64 encoded) and --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Bearer xxx\" for jwt use",
|
||||
Value: "http://localhost:8545",
|
||||
Value: "",
|
||||
}
|
||||
// ExecutionJWTSecretFlag provides a path to a file containing a hex-encoded string representing a 32 byte secret
|
||||
// used to authenticate with an execution node via HTTP. This is required if using an HTTP connection, otherwise all requests
|
||||
|
||||
@@ -27,7 +27,7 @@ func FlagOptions(c *cli.Context) ([]powchain.Option, error) {
|
||||
powchain.WithEth1HeaderRequestLimit(c.Uint64(flags.Eth1HeaderReqLimit.Name)),
|
||||
}
|
||||
if len(jwtSecret) > 0 {
|
||||
opts = append(opts, powchain.WithHttpEndpointsAndJWTSecret(endpoints, jwtSecret))
|
||||
opts = append(opts, powchain.WithJWTSecret(jwtSecret))
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ var Commands = &cli.Command{
|
||||
flags.WalletPasswordFileFlag,
|
||||
flags.DeletePublicKeysFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -61,6 +62,7 @@ var Commands = &cli.Command{
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -91,6 +93,7 @@ var Commands = &cli.Command{
|
||||
flags.BackupPublicKeysFlag,
|
||||
flags.BackupPasswordFile,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -118,6 +121,7 @@ var Commands = &cli.Command{
|
||||
flags.AccountPasswordFileFlag,
|
||||
flags.ImportPrivateKeyFileFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -151,6 +155,7 @@ var Commands = &cli.Command{
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.ExitAllFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -22,6 +22,7 @@ var Commands = &cli.Command{
|
||||
cmd.DataDirFlag,
|
||||
flags.SlashingProtectionExportDirFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -46,6 +47,7 @@ var Commands = &cli.Command{
|
||||
cmd.DataDirFlag,
|
||||
flags.SlashingProtectionJSONFileFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -34,6 +34,7 @@ var Commands = &cli.Command{
|
||||
flags.Mnemonic25thWordFileFlag,
|
||||
flags.SkipMnemonic25thWordCheckFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -63,6 +64,7 @@ var Commands = &cli.Command{
|
||||
flags.RemoteSignerKeyPathFlag,
|
||||
flags.RemoteSignerCACertPathFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -91,6 +93,7 @@ var Commands = &cli.Command{
|
||||
flags.Mnemonic25thWordFileFlag,
|
||||
flags.SkipMnemonic25thWordCheckFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -35,6 +35,9 @@ const disabledFeatureFlag = "Disabled feature flag"
|
||||
|
||||
// Flags is a struct to represent which features the client will perform on runtime.
|
||||
type Flags struct {
|
||||
// Testnet Flags.
|
||||
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
|
||||
|
||||
// Feature related flags.
|
||||
RemoteSlasherProtection bool // RemoteSlasherProtection utilizes a beacon node with --slasher mode for validator slashing protection.
|
||||
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
|
||||
@@ -118,8 +121,13 @@ func InitWithReset(c *Flags) func() {
|
||||
}
|
||||
|
||||
// configureTestnet sets the config according to specified testnet flag
|
||||
func configureTestnet(ctx *cli.Context) {
|
||||
if ctx.Bool(PraterTestnet.Name) {
|
||||
func configureTestnet(ctx *cli.Context, cfg *Flags) {
|
||||
if ctx.Bool(PyrmontTestnet.Name) {
|
||||
log.Warn("Running on Pyrmont Testnet")
|
||||
params.UsePyrmontConfig()
|
||||
params.UsePyrmontNetworkConfig()
|
||||
cfg.PyrmontTestnet = true
|
||||
} else if ctx.Bool(PraterTestnet.Name) {
|
||||
log.Warn("Running on the Prater Testnet")
|
||||
params.UsePraterConfig()
|
||||
params.UsePraterNetworkConfig()
|
||||
@@ -137,7 +145,7 @@ func ConfigureBeaconChain(ctx *cli.Context) {
|
||||
if ctx.Bool(devModeFlag.Name) {
|
||||
enableDevModeFlags(ctx)
|
||||
}
|
||||
configureTestnet(ctx)
|
||||
configureTestnet(ctx, cfg)
|
||||
|
||||
if ctx.Bool(writeSSZStateTransitionsFlag.Name) {
|
||||
logEnabled(writeSSZStateTransitionsFlag)
|
||||
@@ -232,7 +240,7 @@ func ConfigureBeaconChain(ctx *cli.Context) {
|
||||
func ConfigureValidator(ctx *cli.Context) {
|
||||
complainOnDeprecatedFlags(ctx)
|
||||
cfg := &Flags{}
|
||||
configureTestnet(ctx)
|
||||
configureTestnet(ctx, cfg)
|
||||
if ctx.Bool(enableExternalSlasherProtectionFlag.Name) {
|
||||
log.Fatal(
|
||||
"Remote slashing protection has currently been disabled in Prysm due to safety concerns. " +
|
||||
|
||||
@@ -11,41 +11,41 @@ import (
|
||||
func TestInitFeatureConfig(t *testing.T) {
|
||||
defer Init(&Flags{})
|
||||
cfg := &Flags{
|
||||
EnablePeerScorer: true,
|
||||
PyrmontTestnet: true,
|
||||
}
|
||||
Init(cfg)
|
||||
c := Get()
|
||||
assert.Equal(t, true, c.EnablePeerScorer)
|
||||
assert.Equal(t, true, c.PyrmontTestnet)
|
||||
|
||||
// Reset back to false for the follow up tests.
|
||||
cfg = &Flags{RemoteSlasherProtection: false}
|
||||
cfg = &Flags{PyrmontTestnet: false}
|
||||
Init(cfg)
|
||||
}
|
||||
|
||||
func TestInitWithReset(t *testing.T) {
|
||||
defer Init(&Flags{})
|
||||
Init(&Flags{
|
||||
EnablePeerScorer: true,
|
||||
PyrmontTestnet: true,
|
||||
})
|
||||
assert.Equal(t, true, Get().EnablePeerScorer)
|
||||
assert.Equal(t, true, Get().PyrmontTestnet)
|
||||
|
||||
// Overwrite previously set value (value that didn't come by default).
|
||||
resetCfg := InitWithReset(&Flags{
|
||||
EnablePeerScorer: false,
|
||||
PyrmontTestnet: false,
|
||||
})
|
||||
assert.Equal(t, false, Get().EnablePeerScorer)
|
||||
assert.Equal(t, false, Get().PyrmontTestnet)
|
||||
|
||||
// Reset must get to previously set configuration (not to default config values).
|
||||
resetCfg()
|
||||
assert.Equal(t, true, Get().EnablePeerScorer)
|
||||
assert.Equal(t, true, Get().PyrmontTestnet)
|
||||
}
|
||||
|
||||
func TestConfigureBeaconConfig(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(enablePeerScorer.Name, true, "test")
|
||||
set.Bool(PyrmontTestnet.Name, true, "test")
|
||||
context := cli.NewContext(&app, set, nil)
|
||||
ConfigureBeaconChain(context)
|
||||
c := Get()
|
||||
assert.Equal(t, true, c.EnablePeerScorer)
|
||||
assert.Equal(t, true, c.PyrmontTestnet)
|
||||
}
|
||||
|
||||
@@ -70,11 +70,6 @@ var (
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
deprecatedPyrmontTestnet = &cli.BoolFlag{
|
||||
Name: "pyrmont",
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
var deprecatedFlags = []cli.Flag{
|
||||
@@ -89,5 +84,4 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedDisableNextSlotStateCache,
|
||||
deprecatedAttestationAggregationStrategy,
|
||||
deprecatedForceOptMaxCoverAggregationStategy,
|
||||
deprecatedPyrmontTestnet,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// PyrmontTestnet flag for the multiclient Ethereum consensus testnet.
|
||||
PyrmontTestnet = &cli.BoolFlag{
|
||||
Name: "pyrmont",
|
||||
Usage: "This defines the flag through which we can run on the Pyrmont Multiclient Testnet",
|
||||
}
|
||||
// PraterTestnet flag for the multiclient Ethereum consensus testnet.
|
||||
PraterTestnet = &cli.BoolFlag{
|
||||
Name: "prater",
|
||||
@@ -144,7 +149,6 @@ var devModeFlags = []cli.Flag{
|
||||
enablePeerScorer,
|
||||
enableVecHTR,
|
||||
enableForkChoiceDoublyLinkedTree,
|
||||
enableNativeState,
|
||||
}
|
||||
|
||||
// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
|
||||
@@ -152,6 +156,7 @@ var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
|
||||
writeWalletPasswordOnWebOnboarding,
|
||||
enableExternalSlasherProtectionFlag,
|
||||
disableAttestingHistoryDBCache,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
Mainnet,
|
||||
dynamicKeyReloadDebounceInterval,
|
||||
@@ -170,6 +175,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
|
||||
devModeFlag,
|
||||
writeSSZStateTransitionsFlag,
|
||||
disableGRPCConnectionLogging,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
Mainnet,
|
||||
enablePeerScorer,
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
"network_config.go",
|
||||
"testnet_e2e_config.go",
|
||||
"testnet_prater_config.go",
|
||||
"testnet_pyrmont_config.go",
|
||||
"testutils.go",
|
||||
"values.go",
|
||||
],
|
||||
@@ -47,7 +48,6 @@ go_test(
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
"@eth2_networks//:configs",
|
||||
"testdata/e2e_config.yaml",
|
||||
],
|
||||
gotags = ["develop"],
|
||||
race = "on",
|
||||
@@ -61,9 +61,3 @@ go_test(
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "custom_configs",
|
||||
srcs = glob(["testdata/*.yaml"]),
|
||||
visibility = ["//testing:__subpackages__"],
|
||||
)
|
||||
|
||||
@@ -18,94 +18,94 @@ import (
|
||||
|
||||
var placeholderFields = []string{"UPDATE_TIMEOUT", "INTERVALS_PER_SLOT"}
|
||||
|
||||
func TestLoadConfigFile(t *testing.T) {
|
||||
func TestLoadConfigFileMainnet(t *testing.T) {
|
||||
// See https://media.githubusercontent.com/media/ethereum/consensus-spec-tests/master/tests/minimal/config/phase0.yaml
|
||||
assertVals := func(name string, fields []string, expected, actual *params.BeaconChainConfig) {
|
||||
assertVals := func(name string, fields []string, c1, c2 *params.BeaconChainConfig) {
|
||||
// Misc params.
|
||||
assert.Equal(t, expected.MaxCommitteesPerSlot, actual.MaxCommitteesPerSlot, "%s: MaxCommitteesPerSlot", name)
|
||||
assert.Equal(t, expected.TargetCommitteeSize, actual.TargetCommitteeSize, "%s: TargetCommitteeSize", name)
|
||||
assert.Equal(t, expected.MaxValidatorsPerCommittee, actual.MaxValidatorsPerCommittee, "%s: MaxValidatorsPerCommittee", name)
|
||||
assert.Equal(t, expected.MinPerEpochChurnLimit, actual.MinPerEpochChurnLimit, "%s: MinPerEpochChurnLimit", name)
|
||||
assert.Equal(t, expected.ChurnLimitQuotient, actual.ChurnLimitQuotient, "%s: ChurnLimitQuotient", name)
|
||||
assert.Equal(t, expected.ShuffleRoundCount, actual.ShuffleRoundCount, "%s: ShuffleRoundCount", name)
|
||||
assert.Equal(t, expected.MinGenesisActiveValidatorCount, actual.MinGenesisActiveValidatorCount, "%s: MinGenesisActiveValidatorCount", name)
|
||||
assert.Equal(t, expected.MinGenesisTime, actual.MinGenesisTime, "%s: MinGenesisTime", name)
|
||||
assert.Equal(t, expected.HysteresisQuotient, actual.HysteresisQuotient, "%s: HysteresisQuotient", name)
|
||||
assert.Equal(t, expected.HysteresisDownwardMultiplier, actual.HysteresisDownwardMultiplier, "%s: HysteresisDownwardMultiplier", name)
|
||||
assert.Equal(t, expected.HysteresisUpwardMultiplier, actual.HysteresisUpwardMultiplier, "%s: HysteresisUpwardMultiplier", name)
|
||||
assert.Equal(t, c1.MaxCommitteesPerSlot, c2.MaxCommitteesPerSlot, "%s: MaxCommitteesPerSlot", name)
|
||||
assert.Equal(t, c1.TargetCommitteeSize, c2.TargetCommitteeSize, "%s: TargetCommitteeSize", name)
|
||||
assert.Equal(t, c1.MaxValidatorsPerCommittee, c2.MaxValidatorsPerCommittee, "%s: MaxValidatorsPerCommittee", name)
|
||||
assert.Equal(t, c1.MinPerEpochChurnLimit, c2.MinPerEpochChurnLimit, "%s: MinPerEpochChurnLimit", name)
|
||||
assert.Equal(t, c1.ChurnLimitQuotient, c2.ChurnLimitQuotient, "%s: ChurnLimitQuotient", name)
|
||||
assert.Equal(t, c1.ShuffleRoundCount, c2.ShuffleRoundCount, "%s: ShuffleRoundCount", name)
|
||||
assert.Equal(t, c1.MinGenesisActiveValidatorCount, c2.MinGenesisActiveValidatorCount, "%s: MinGenesisActiveValidatorCount", name)
|
||||
assert.Equal(t, c1.MinGenesisTime, c2.MinGenesisTime, "%s: MinGenesisTime", name)
|
||||
assert.Equal(t, c1.HysteresisQuotient, c2.HysteresisQuotient, "%s: HysteresisQuotient", name)
|
||||
assert.Equal(t, c1.HysteresisDownwardMultiplier, c2.HysteresisDownwardMultiplier, "%s: HysteresisDownwardMultiplier", name)
|
||||
assert.Equal(t, c1.HysteresisUpwardMultiplier, c2.HysteresisUpwardMultiplier, "%s: HysteresisUpwardMultiplier", name)
|
||||
|
||||
// Fork Choice params.
|
||||
assert.Equal(t, expected.SafeSlotsToUpdateJustified, actual.SafeSlotsToUpdateJustified, "%s: SafeSlotsToUpdateJustified", name)
|
||||
assert.Equal(t, c1.SafeSlotsToUpdateJustified, c2.SafeSlotsToUpdateJustified, "%s: SafeSlotsToUpdateJustified", name)
|
||||
|
||||
// Validator params.
|
||||
assert.Equal(t, expected.Eth1FollowDistance, actual.Eth1FollowDistance, "%s: Eth1FollowDistance", name)
|
||||
assert.Equal(t, expected.TargetAggregatorsPerCommittee, actual.TargetAggregatorsPerCommittee, "%s: TargetAggregatorsPerCommittee", name)
|
||||
assert.Equal(t, expected.RandomSubnetsPerValidator, actual.RandomSubnetsPerValidator, "%s: RandomSubnetsPerValidator", name)
|
||||
assert.Equal(t, expected.EpochsPerRandomSubnetSubscription, actual.EpochsPerRandomSubnetSubscription, "%s: EpochsPerRandomSubnetSubscription", name)
|
||||
assert.Equal(t, expected.SecondsPerETH1Block, actual.SecondsPerETH1Block, "%s: SecondsPerETH1Block", name)
|
||||
assert.Equal(t, c1.Eth1FollowDistance, c2.Eth1FollowDistance, "%s: Eth1FollowDistance", name)
|
||||
assert.Equal(t, c1.TargetAggregatorsPerCommittee, c2.TargetAggregatorsPerCommittee, "%s: TargetAggregatorsPerCommittee", name)
|
||||
assert.Equal(t, c1.RandomSubnetsPerValidator, c2.RandomSubnetsPerValidator, "%s: RandomSubnetsPerValidator", name)
|
||||
assert.Equal(t, c1.EpochsPerRandomSubnetSubscription, c2.EpochsPerRandomSubnetSubscription, "%s: EpochsPerRandomSubnetSubscription", name)
|
||||
assert.Equal(t, c1.SecondsPerETH1Block, c2.SecondsPerETH1Block, "%s: SecondsPerETH1Block", name)
|
||||
|
||||
// Deposit contract.
|
||||
assert.Equal(t, expected.DepositChainID, actual.DepositChainID, "%s: DepositChainID", name)
|
||||
assert.Equal(t, expected.DepositNetworkID, actual.DepositNetworkID, "%s: DepositNetworkID", name)
|
||||
assert.Equal(t, expected.DepositContractAddress, actual.DepositContractAddress, "%s: DepositContractAddress", name)
|
||||
assert.Equal(t, c1.DepositChainID, c2.DepositChainID, "%s: DepositChainID", name)
|
||||
assert.Equal(t, c1.DepositNetworkID, c2.DepositNetworkID, "%s: DepositNetworkID", name)
|
||||
assert.Equal(t, c1.DepositContractAddress, c2.DepositContractAddress, "%s: DepositContractAddress", name)
|
||||
|
||||
// Gwei values.
|
||||
assert.Equal(t, expected.MinDepositAmount, actual.MinDepositAmount, "%s: MinDepositAmount", name)
|
||||
assert.Equal(t, expected.MaxEffectiveBalance, actual.MaxEffectiveBalance, "%s: MaxEffectiveBalance", name)
|
||||
assert.Equal(t, expected.EjectionBalance, actual.EjectionBalance, "%s: EjectionBalance", name)
|
||||
assert.Equal(t, expected.EffectiveBalanceIncrement, actual.EffectiveBalanceIncrement, "%s: EffectiveBalanceIncrement", name)
|
||||
assert.Equal(t, c1.MinDepositAmount, c2.MinDepositAmount, "%s: MinDepositAmount", name)
|
||||
assert.Equal(t, c1.MaxEffectiveBalance, c2.MaxEffectiveBalance, "%s: MaxEffectiveBalance", name)
|
||||
assert.Equal(t, c1.EjectionBalance, c2.EjectionBalance, "%s: EjectionBalance", name)
|
||||
assert.Equal(t, c1.EffectiveBalanceIncrement, c2.EffectiveBalanceIncrement, "%s: EffectiveBalanceIncrement", name)
|
||||
|
||||
// Initial values.
|
||||
assert.DeepEqual(t, expected.GenesisForkVersion, actual.GenesisForkVersion, "%s: GenesisForkVersion", name)
|
||||
assert.DeepEqual(t, expected.BLSWithdrawalPrefixByte, actual.BLSWithdrawalPrefixByte, "%s: BLSWithdrawalPrefixByte", name)
|
||||
assert.DeepEqual(t, c1.GenesisForkVersion, c2.GenesisForkVersion, "%s: GenesisForkVersion", name)
|
||||
assert.DeepEqual(t, c1.BLSWithdrawalPrefixByte, c2.BLSWithdrawalPrefixByte, "%s: BLSWithdrawalPrefixByte", name)
|
||||
|
||||
// Time parameters.
|
||||
assert.Equal(t, expected.GenesisDelay, actual.GenesisDelay, "%s: GenesisDelay", name)
|
||||
assert.Equal(t, expected.SecondsPerSlot, actual.SecondsPerSlot, "%s: SecondsPerSlot", name)
|
||||
assert.Equal(t, expected.MinAttestationInclusionDelay, actual.MinAttestationInclusionDelay, "%s: MinAttestationInclusionDelay", name)
|
||||
assert.Equal(t, expected.SlotsPerEpoch, actual.SlotsPerEpoch, "%s: SlotsPerEpoch", name)
|
||||
assert.Equal(t, expected.MinSeedLookahead, actual.MinSeedLookahead, "%s: MinSeedLookahead", name)
|
||||
assert.Equal(t, expected.MaxSeedLookahead, actual.MaxSeedLookahead, "%s: MaxSeedLookahead", name)
|
||||
assert.Equal(t, expected.EpochsPerEth1VotingPeriod, actual.EpochsPerEth1VotingPeriod, "%s: EpochsPerEth1VotingPeriod", name)
|
||||
assert.Equal(t, expected.SlotsPerHistoricalRoot, actual.SlotsPerHistoricalRoot, "%s: SlotsPerHistoricalRoot", name)
|
||||
assert.Equal(t, expected.MinValidatorWithdrawabilityDelay, actual.MinValidatorWithdrawabilityDelay, "%s: MinValidatorWithdrawabilityDelay", name)
|
||||
assert.Equal(t, expected.ShardCommitteePeriod, actual.ShardCommitteePeriod, "%s: ShardCommitteePeriod", name)
|
||||
assert.Equal(t, expected.MinEpochsToInactivityPenalty, actual.MinEpochsToInactivityPenalty, "%s: MinEpochsToInactivityPenalty", name)
|
||||
assert.Equal(t, c1.GenesisDelay, c2.GenesisDelay, "%s: GenesisDelay", name)
|
||||
assert.Equal(t, c1.SecondsPerSlot, c2.SecondsPerSlot, "%s: SecondsPerSlot", name)
|
||||
assert.Equal(t, c1.MinAttestationInclusionDelay, c2.MinAttestationInclusionDelay, "%s: MinAttestationInclusionDelay", name)
|
||||
assert.Equal(t, c1.SlotsPerEpoch, c2.SlotsPerEpoch, "%s: SlotsPerEpoch", name)
|
||||
assert.Equal(t, c1.MinSeedLookahead, c2.MinSeedLookahead, "%s: MinSeedLookahead", name)
|
||||
assert.Equal(t, c1.MaxSeedLookahead, c2.MaxSeedLookahead, "%s: MaxSeedLookahead", name)
|
||||
assert.Equal(t, c1.EpochsPerEth1VotingPeriod, c2.EpochsPerEth1VotingPeriod, "%s: EpochsPerEth1VotingPeriod", name)
|
||||
assert.Equal(t, c1.SlotsPerHistoricalRoot, c2.SlotsPerHistoricalRoot, "%s: SlotsPerHistoricalRoot", name)
|
||||
assert.Equal(t, c1.MinValidatorWithdrawabilityDelay, c2.MinValidatorWithdrawabilityDelay, "%s: MinValidatorWithdrawabilityDelay", name)
|
||||
assert.Equal(t, c1.ShardCommitteePeriod, c2.ShardCommitteePeriod, "%s: ShardCommitteePeriod", name)
|
||||
assert.Equal(t, c1.MinEpochsToInactivityPenalty, c2.MinEpochsToInactivityPenalty, "%s: MinEpochsToInactivityPenalty", name)
|
||||
|
||||
// State vector lengths.
|
||||
assert.Equal(t, expected.EpochsPerHistoricalVector, actual.EpochsPerHistoricalVector, "%s: EpochsPerHistoricalVector", name)
|
||||
assert.Equal(t, expected.EpochsPerSlashingsVector, actual.EpochsPerSlashingsVector, "%s: EpochsPerSlashingsVector", name)
|
||||
assert.Equal(t, expected.HistoricalRootsLimit, actual.HistoricalRootsLimit, "%s: HistoricalRootsLimit", name)
|
||||
assert.Equal(t, expected.ValidatorRegistryLimit, actual.ValidatorRegistryLimit, "%s: ValidatorRegistryLimit", name)
|
||||
assert.Equal(t, c1.EpochsPerHistoricalVector, c2.EpochsPerHistoricalVector, "%s: EpochsPerHistoricalVector", name)
|
||||
assert.Equal(t, c1.EpochsPerSlashingsVector, c2.EpochsPerSlashingsVector, "%s: EpochsPerSlashingsVector", name)
|
||||
assert.Equal(t, c1.HistoricalRootsLimit, c2.HistoricalRootsLimit, "%s: HistoricalRootsLimit", name)
|
||||
assert.Equal(t, c1.ValidatorRegistryLimit, c2.ValidatorRegistryLimit, "%s: ValidatorRegistryLimit", name)
|
||||
|
||||
// Reward and penalty quotients.
|
||||
assert.Equal(t, expected.BaseRewardFactor, actual.BaseRewardFactor, "%s: BaseRewardFactor", name)
|
||||
assert.Equal(t, expected.WhistleBlowerRewardQuotient, actual.WhistleBlowerRewardQuotient, "%s: WhistleBlowerRewardQuotient", name)
|
||||
assert.Equal(t, expected.ProposerRewardQuotient, actual.ProposerRewardQuotient, "%s: ProposerRewardQuotient", name)
|
||||
assert.Equal(t, expected.InactivityPenaltyQuotient, actual.InactivityPenaltyQuotient, "%s: InactivityPenaltyQuotient", name)
|
||||
assert.Equal(t, expected.InactivityPenaltyQuotientAltair, actual.InactivityPenaltyQuotientAltair, "%s: InactivityPenaltyQuotientAltair", name)
|
||||
assert.Equal(t, expected.MinSlashingPenaltyQuotient, actual.MinSlashingPenaltyQuotient, "%s: MinSlashingPenaltyQuotient", name)
|
||||
assert.Equal(t, expected.MinSlashingPenaltyQuotientAltair, actual.MinSlashingPenaltyQuotientAltair, "%s: MinSlashingPenaltyQuotientAltair", name)
|
||||
assert.Equal(t, expected.ProportionalSlashingMultiplier, actual.ProportionalSlashingMultiplier, "%s: ProportionalSlashingMultiplier", name)
|
||||
assert.Equal(t, expected.ProportionalSlashingMultiplierAltair, actual.ProportionalSlashingMultiplierAltair, "%s: ProportionalSlashingMultiplierAltair", name)
|
||||
assert.Equal(t, c1.BaseRewardFactor, c2.BaseRewardFactor, "%s: BaseRewardFactor", name)
|
||||
assert.Equal(t, c1.WhistleBlowerRewardQuotient, c2.WhistleBlowerRewardQuotient, "%s: WhistleBlowerRewardQuotient", name)
|
||||
assert.Equal(t, c1.ProposerRewardQuotient, c2.ProposerRewardQuotient, "%s: ProposerRewardQuotient", name)
|
||||
assert.Equal(t, c1.InactivityPenaltyQuotient, c2.InactivityPenaltyQuotient, "%s: InactivityPenaltyQuotient", name)
|
||||
assert.Equal(t, c1.InactivityPenaltyQuotientAltair, c2.InactivityPenaltyQuotientAltair, "%s: InactivityPenaltyQuotientAltair", name)
|
||||
assert.Equal(t, c1.MinSlashingPenaltyQuotient, c2.MinSlashingPenaltyQuotient, "%s: MinSlashingPenaltyQuotient", name)
|
||||
assert.Equal(t, c1.MinSlashingPenaltyQuotientAltair, c2.MinSlashingPenaltyQuotientAltair, "%s: MinSlashingPenaltyQuotientAltair", name)
|
||||
assert.Equal(t, c1.ProportionalSlashingMultiplier, c2.ProportionalSlashingMultiplier, "%s: ProportionalSlashingMultiplier", name)
|
||||
assert.Equal(t, c1.ProportionalSlashingMultiplierAltair, c2.ProportionalSlashingMultiplierAltair, "%s: ProportionalSlashingMultiplierAltair", name)
|
||||
|
||||
// Max operations per block.
|
||||
assert.Equal(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings, "%s: MaxProposerSlashings", name)
|
||||
assert.Equal(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings, "%s: MaxAttesterSlashings", name)
|
||||
assert.Equal(t, expected.MaxAttestations, actual.MaxAttestations, "%s: MaxAttestations", name)
|
||||
assert.Equal(t, expected.MaxDeposits, actual.MaxDeposits, "%s: MaxDeposits", name)
|
||||
assert.Equal(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits, "%s: MaxVoluntaryExits", name)
|
||||
assert.Equal(t, c1.MaxProposerSlashings, c2.MaxProposerSlashings, "%s: MaxProposerSlashings", name)
|
||||
assert.Equal(t, c1.MaxAttesterSlashings, c2.MaxAttesterSlashings, "%s: MaxAttesterSlashings", name)
|
||||
assert.Equal(t, c1.MaxAttestations, c2.MaxAttestations, "%s: MaxAttestations", name)
|
||||
assert.Equal(t, c1.MaxDeposits, c2.MaxDeposits, "%s: MaxDeposits", name)
|
||||
assert.Equal(t, c1.MaxVoluntaryExits, c2.MaxVoluntaryExits, "%s: MaxVoluntaryExits", name)
|
||||
|
||||
// Signature domains.
|
||||
assert.Equal(t, expected.DomainBeaconProposer, actual.DomainBeaconProposer, "%s: DomainBeaconProposer", name)
|
||||
assert.Equal(t, expected.DomainBeaconAttester, actual.DomainBeaconAttester, "%s: DomainBeaconAttester", name)
|
||||
assert.Equal(t, expected.DomainRandao, actual.DomainRandao, "%s: DomainRandao", name)
|
||||
assert.Equal(t, expected.DomainDeposit, actual.DomainDeposit, "%s: DomainDeposit", name)
|
||||
assert.Equal(t, expected.DomainVoluntaryExit, actual.DomainVoluntaryExit, "%s: DomainVoluntaryExit", name)
|
||||
assert.Equal(t, expected.DomainSelectionProof, actual.DomainSelectionProof, "%s: DomainSelectionProof", name)
|
||||
assert.Equal(t, expected.DomainAggregateAndProof, actual.DomainAggregateAndProof, "%s: DomainAggregateAndProof", name)
|
||||
assert.Equal(t, c1.DomainBeaconProposer, c2.DomainBeaconProposer, "%s: DomainBeaconProposer", name)
|
||||
assert.Equal(t, c1.DomainBeaconAttester, c2.DomainBeaconAttester, "%s: DomainBeaconAttester", name)
|
||||
assert.Equal(t, c1.DomainRandao, c2.DomainRandao, "%s: DomainRandao", name)
|
||||
assert.Equal(t, c1.DomainDeposit, c2.DomainDeposit, "%s: DomainDeposit", name)
|
||||
assert.Equal(t, c1.DomainVoluntaryExit, c2.DomainVoluntaryExit, "%s: DomainVoluntaryExit", name)
|
||||
assert.Equal(t, c1.DomainSelectionProof, c2.DomainSelectionProof, "%s: DomainSelectionProof", name)
|
||||
assert.Equal(t, c1.DomainAggregateAndProof, c2.DomainAggregateAndProof, "%s: DomainAggregateAndProof", name)
|
||||
|
||||
assertYamlFieldsMatch(t, name, fields, expected, actual)
|
||||
assertYamlFieldsMatch(t, name, fields, c1, c2)
|
||||
}
|
||||
|
||||
t.Run("mainnet", func(t *testing.T) {
|
||||
@@ -129,17 +129,6 @@ func TestLoadConfigFile(t *testing.T) {
|
||||
fields := fieldsFromYamls(t, append(minimalPresetsFiles, minimalConfigFile))
|
||||
assertVals("minimal", fields, params.MinimalSpecConfig(), params.BeaconConfig())
|
||||
})
|
||||
|
||||
t.Run("e2e", func(t *testing.T) {
|
||||
minimalPresetsFiles := presetsFilePath(t, "minimal")
|
||||
for _, fp := range minimalPresetsFiles {
|
||||
params.LoadChainConfigFile(fp, nil)
|
||||
}
|
||||
configFile := "testdata/e2e_config.yaml"
|
||||
params.LoadChainConfigFile(configFile, nil)
|
||||
fields := fieldsFromYamls(t, append(minimalPresetsFiles, configFile))
|
||||
assertVals("e2e", fields, params.E2ETestConfig(), params.BeaconConfig())
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoadConfigFile_OverwriteCorrectly(t *testing.T) {
|
||||
|
||||
118
config/params/testdata/e2e_config.yaml
vendored
118
config/params/testdata/e2e_config.yaml
vendored
@@ -1,118 +0,0 @@
|
||||
# e2e config
|
||||
|
||||
# Extends the minimal preset
|
||||
PRESET_BASE: 'minimal'
|
||||
|
||||
|
||||
|
||||
# Transition
|
||||
# ---------------------------------------------------------------
|
||||
# TBD, 2**256-2**10 is a placeholder, e2e is 600
|
||||
TERMINAL_TOTAL_DIFFICULTY: 600
|
||||
# By default, don't use these params
|
||||
#TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
#TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 256 # Override for e2e tests
|
||||
# Jan 3, 2020
|
||||
MIN_GENESIS_TIME: 1578009600
|
||||
# Highest byte set to 0x01 to avoid collisions with mainnet versioning
|
||||
GENESIS_FORK_VERSION: 0x000000fd
|
||||
# [customized] Faster to spin up testnets, but does not give validator reasonable warning time for genesis
|
||||
GENESIS_DELAY: 10 # Override for e2e tests
|
||||
|
||||
|
||||
# Forking
|
||||
# ---------------------------------------------------------------
|
||||
# Values provided for illustrative purposes.
|
||||
# Individual tests/testnets may set different values.
|
||||
|
||||
# Altair
|
||||
ALTAIR_FORK_VERSION: 0x010000fd
|
||||
ALTAIR_FORK_EPOCH: 6 # Override for e2e
|
||||
# Bellatrix
|
||||
BELLATRIX_FORK_VERSION: 0x020000fd
|
||||
BELLATRIX_FORK_EPOCH: 8
|
||||
# Sharding
|
||||
SHARDING_FORK_VERSION: 0x030000fd
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] Faster for testing purposes
|
||||
SECONDS_PER_SLOT: 10 # Override for e2e tests
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 2 # Override for e2e tests
|
||||
# 2**8 (= 256) epochs
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# [customized] higher frequency of committee turnover and faster time to acceptable voluntary exit
|
||||
SHARD_COMMITTEE_PERIOD: 4 # Override for e2e tests
|
||||
# [customized] process deposits more quickly, but insecure
|
||||
ETH1_FOLLOW_DISTANCE: 4 # Override for e2e tests
|
||||
|
||||
|
||||
# Validator cycle
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# [customized] scale queue churn at much lower validator counts for testing
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
|
||||
|
||||
# Fork choice
|
||||
# ---------------------------------------------------------------
|
||||
# 70%
|
||||
PROPOSER_SCORE_BOOST: 70
|
||||
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# Ethereum Goerli testnet
|
||||
DEPOSIT_CHAIN_ID: 1337 # Override for e2e tests
|
||||
DEPOSIT_NETWORK_ID: 1337 # Override for e2e tests
|
||||
# Configured on a per testnet basis
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
|
||||
|
||||
# Updated penalty values
|
||||
# ---------------------------------------------------------------
|
||||
# 3 * 2**24 (= 50,331,648)
|
||||
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648
|
||||
# 2**6 (= 64)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64
|
||||
# 2
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2
|
||||
|
||||
|
||||
# Sync committee
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
SYNC_COMMITTEE_SIZE: 32
|
||||
# [customized]
|
||||
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 8
|
||||
|
||||
|
||||
# Sync protocol
|
||||
# ---------------------------------------------------------------
|
||||
# 1
|
||||
MIN_SYNC_COMMITTEE_PARTICIPANTS: 1
|
||||
|
||||
# Other e2e overrides
|
||||
# ---------------------------------------------------------------
|
||||
CONFIG_NAME: "end-to-end"
|
||||
SLOTS_PER_EPOCH: 6
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD: 2
|
||||
MAX_SEED_LOOKAHEAD: 1
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.DepositChainID = 1337 // Chain ID of eth1 dev net.
|
||||
e2eConfig.DepositNetworkID = 1337 // Network ID of eth1 dev net.
|
||||
|
||||
// Fork Parameters.
|
||||
// Altair Fork Parameters.
|
||||
e2eConfig.AltairForkEpoch = altairE2EForkEpoch
|
||||
e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch
|
||||
|
||||
|
||||
43
config/params/testnet_pyrmont_config.go
Normal file
43
config/params/testnet_pyrmont_config.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package params
|
||||
|
||||
import "math"
|
||||
|
||||
// UsePyrmontNetworkConfig uses the Pyrmont specific
|
||||
// network config.
|
||||
func UsePyrmontNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
cfg.ContractDeploymentBlock = 3743587
|
||||
cfg.BootstrapNodes = []string{
|
||||
"enr:-Ku4QOA5OGWObY8ep_x35NlGBEj7IuQULTjkgxC_0G1AszqGEA0Wn2RNlyLFx9zGTNB1gdFBA6ZDYxCgIza1uJUUOj4Dh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDVTPWXAAAgCf__________gmlkgnY0gmlwhDQPSjiJc2VjcDI1NmsxoQM6yTQB6XGWYJbI7NZFBjp4Yb9AYKQPBhVrfUclQUobb4N1ZHCCIyg",
|
||||
"enr:-Ku4QOksdA2tabOGrfOOr6NynThMoio6Ggka2oDPqUuFeWCqcRM2alNb8778O_5bK95p3EFt0cngTUXm2H7o1jkSJ_8Dh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDVTPWXAAAgCf__________gmlkgnY0gmlwhDaa13aJc2VjcDI1NmsxoQKdNQJvnohpf0VO0ZYCAJxGjT0uwJoAHbAiBMujGjK0SoN1ZHCCIyg",
|
||||
}
|
||||
OverrideBeaconNetworkConfig(cfg)
|
||||
}
|
||||
|
||||
// UsePyrmontConfig sets the main beacon chain
|
||||
// config for Pyrmont.
|
||||
func UsePyrmontConfig() {
|
||||
beaconConfig = PyrmontConfig()
|
||||
}
|
||||
|
||||
// PyrmontConfig defines the config for the
|
||||
// Pyrmont testnet.
|
||||
func PyrmontConfig() *BeaconChainConfig {
|
||||
cfg := MainnetConfig().Copy()
|
||||
cfg.MinGenesisTime = 1605700800
|
||||
cfg.GenesisDelay = 432000
|
||||
cfg.ConfigName = ConfigNames[Pyrmont]
|
||||
cfg.GenesisForkVersion = []byte{0x00, 0x00, 0x20, 0x09}
|
||||
cfg.AltairForkVersion = []byte{0x01, 0x00, 0x20, 0x09}
|
||||
cfg.AltairForkEpoch = 61650
|
||||
cfg.BellatrixForkVersion = []byte{0x02, 0x00, 0x20, 0x09}
|
||||
cfg.BellatrixForkEpoch = math.MaxUint64
|
||||
cfg.ShardingForkVersion = []byte{0x03, 0x00, 0x20, 0x09}
|
||||
cfg.ShardingForkEpoch = math.MaxUint64
|
||||
cfg.SecondsPerETH1Block = 14
|
||||
cfg.DepositChainID = 5
|
||||
cfg.DepositNetworkID = 5
|
||||
cfg.DepositContractAddress = "0x8c5fecdC472E27Bc447696F431E425D02dd46a8c"
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
}
|
||||
@@ -12,6 +12,7 @@ const (
|
||||
Mainnet ConfigName = iota
|
||||
Minimal
|
||||
EndToEnd
|
||||
Pyrmont
|
||||
Prater
|
||||
EndToEndMainnet
|
||||
)
|
||||
@@ -32,6 +33,7 @@ var ConfigNames = map[ConfigName]string{
|
||||
Mainnet: "mainnet",
|
||||
Minimal: "minimal",
|
||||
EndToEnd: "end-to-end",
|
||||
Pyrmont: "pyrmont",
|
||||
Prater: "prater",
|
||||
EndToEndMainnet: "end-to-end-mainnet",
|
||||
}
|
||||
@@ -40,6 +42,7 @@ var ConfigNames = map[ConfigName]string{
|
||||
var KnownConfigs = map[ConfigName]func() *BeaconChainConfig{
|
||||
Mainnet: MainnetConfig,
|
||||
Prater: PraterConfig,
|
||||
Pyrmont: PyrmontConfig,
|
||||
Minimal: MinimalSpecConfig,
|
||||
EndToEnd: E2ETestConfig,
|
||||
EndToEndMainnet: E2EMainnetTestConfig,
|
||||
|
||||
13
deps.bzl
13
deps.bzl
@@ -1274,6 +1274,12 @@ def prysm_deps():
|
||||
sum = "h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4=",
|
||||
version = "v0.0.0-20181222135242-d2cdd8c08219",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_gomarkdown_markdown",
|
||||
importpath = "github.com/gomarkdown/markdown",
|
||||
sum = "h1:YVvt637ygnOO9qjLBVmPOvrUmCz/i8YECSu/8UlOQW0=",
|
||||
version = "v0.0.0-20220310201231-552c6011c0b8",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_google_btree",
|
||||
@@ -3756,13 +3762,6 @@ def prysm_deps():
|
||||
sum = "h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=",
|
||||
version = "v2.3.0",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_uudashr_gocognit",
|
||||
importpath = "github.com/uudashr/gocognit",
|
||||
sum = "h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4=",
|
||||
version = "v1.0.5",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_valyala_bytebufferpool",
|
||||
importpath = "github.com/valyala/bytebufferpool",
|
||||
|
||||
2
go.mod
2
go.mod
@@ -77,7 +77,6 @@ require (
|
||||
github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/uudashr/gocognit v1.0.5
|
||||
github.com/wealdtech/go-bytesutil v1.1.1
|
||||
github.com/wealdtech/go-eth2-util v1.6.3
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3
|
||||
@@ -256,6 +255,7 @@ require (
|
||||
github.com/go-logr/logr v0.2.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-playground/validator/v10 v10.10.0
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8
|
||||
github.com/peterh/liner v1.2.0 // indirect
|
||||
github.com/prometheus/tsdb v0.10.0 // indirect
|
||||
github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220303211031-f753e083138c
|
||||
|
||||
5
go.sum
5
go.sum
@@ -447,6 +447,8 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8 h1:YVvt637ygnOO9qjLBVmPOvrUmCz/i8YECSu/8UlOQW0=
|
||||
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
@@ -1358,8 +1360,6 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4=
|
||||
github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
@@ -1806,7 +1806,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -3,32 +3,24 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"auth.go",
|
||||
"endpoint.go",
|
||||
"external_ip.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/network",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//network/authorization:go_default_library",
|
||||
"@com_github_golang_jwt_jwt_v4//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
deps = ["//network/authorization:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"auth_test.go",
|
||||
"endpoint_test.go",
|
||||
"external_ip_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//network/authorization:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_golang_jwt_jwt_v4//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -2,7 +2,6 @@ package network
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/network/authorization"
|
||||
@@ -25,22 +24,6 @@ func (e Endpoint) Equals(other Endpoint) bool {
|
||||
return e.Url == other.Url && e.Auth.Equals(other.Auth)
|
||||
}
|
||||
|
||||
// HttpClient creates a http client object dependant
|
||||
// on the properties of the network endpoint.
|
||||
func (e Endpoint) HttpClient() *http.Client {
|
||||
if e.Auth.Method != authorization.Bearer {
|
||||
return http.DefaultClient
|
||||
}
|
||||
authTransport := &jwtTransport{
|
||||
underlyingTransport: http.DefaultTransport,
|
||||
jwtSecret: []byte(e.Auth.Value),
|
||||
}
|
||||
return &http.Client{
|
||||
Timeout: DefaultRPCHTTPTimeout,
|
||||
Transport: authTransport,
|
||||
}
|
||||
}
|
||||
|
||||
// Equals compares two authorization data objects for equality.
|
||||
func (d AuthorizationData) Equals(other AuthorizationData) bool {
|
||||
return d.Method == other.Method && d.Value == other.Value
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"unsafeptr": {
|
||||
"exclude_files": {
|
||||
"beacon-chain/state/state-native/custom-types/block_roots.go": "Needed for field management operations",
|
||||
"external/.*": "Unsafe third party code",
|
||||
"rules_go_work-.*": "Third party code"
|
||||
}
|
||||
@@ -171,13 +170,5 @@
|
||||
"rules_go_work-.*": "Third party code",
|
||||
".*_test\\.go": "Tests are ok"
|
||||
}
|
||||
},
|
||||
"gocognit": {
|
||||
"exclude_files": {
|
||||
"external/.*": "Third party code",
|
||||
"rules_go_work-.*": "Third party code",
|
||||
".*\\.pb.*.go": "Generated code is ok",
|
||||
".*generated\\.ssz\\.go": "Generated code is ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -174,13 +173,6 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
|
||||
require.DeepEqual(t, [][]byte{[]byte("hi")}, payloadPb.Transactions)
|
||||
require.DeepEqual(t, [][]byte{[]byte("bye")}, payloadPb.Uncles)
|
||||
})
|
||||
t.Run("nil execution block", func(t *testing.T) {
|
||||
jsonPayload := (*enginev1.ExecutionBlock)(nil)
|
||||
enc, err := json.Marshal(jsonPayload)
|
||||
require.NoError(t, err)
|
||||
payloadPb := &enginev1.ExecutionBlock{}
|
||||
require.ErrorIs(t, hexutil.ErrEmptyString, json.Unmarshal(enc, payloadPb))
|
||||
})
|
||||
}
|
||||
|
||||
func TestPayloadIDBytes_MarshalUnmarshalJSON(t *testing.T) {
|
||||
|
||||
1042
proto/eth/service/key_management.pb.go
generated
1042
proto/eth/service/key_management.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -123,92 +123,6 @@ func local_request_KeyManagement_DeleteKeystores_0(ctx context.Context, marshale
|
||||
|
||||
}
|
||||
|
||||
func request_KeyManagement_ListRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, client KeyManagementClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq emptypb.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.ListRemoteKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_KeyManagement_ListRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, server KeyManagementServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq emptypb.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.ListRemoteKeys(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_KeyManagement_ImportRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, client KeyManagementClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ImportRemoteKeysRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ImportRemoteKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_KeyManagement_ImportRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, server KeyManagementServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ImportRemoteKeysRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ImportRemoteKeys(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_KeyManagement_DeleteRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, client KeyManagementClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteRemoteKeysRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.DeleteRemoteKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_KeyManagement_DeleteRemoteKeys_0(ctx context.Context, marshaler runtime.Marshaler, server KeyManagementServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteRemoteKeysRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.DeleteRemoteKeys(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterKeyManagementHandlerServer registers the http handlers for service KeyManagement to "mux".
|
||||
// UnaryRPC :call KeyManagementServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -284,75 +198,6 @@ func RegisterKeyManagementHandlerServer(ctx context.Context, mux *runtime.ServeM
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_KeyManagement_ListRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/ListRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_KeyManagement_ListRemoteKeys_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_ListRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_KeyManagement_ImportRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/ImportRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_KeyManagement_ImportRemoteKeys_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_ImportRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_KeyManagement_DeleteRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/DeleteRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_KeyManagement_DeleteRemoteKeys_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_DeleteRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -454,66 +299,6 @@ func RegisterKeyManagementHandlerClient(ctx context.Context, mux *runtime.ServeM
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_KeyManagement_ListRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/ListRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_KeyManagement_ListRemoteKeys_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_ListRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_KeyManagement_ImportRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/ImportRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_KeyManagement_ImportRemoteKeys_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_ImportRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_KeyManagement_DeleteRemoteKeys_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/DeleteRemoteKeys")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_KeyManagement_DeleteRemoteKeys_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_KeyManagement_DeleteRemoteKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -523,12 +308,6 @@ var (
|
||||
pattern_KeyManagement_ImportKeystores_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"internal", "eth", "v1", "keystores"}, ""))
|
||||
|
||||
pattern_KeyManagement_DeleteKeystores_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"internal", "eth", "v1", "keystores"}, ""))
|
||||
|
||||
pattern_KeyManagement_ListRemoteKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"internal", "eth", "v1", "remotekeys"}, ""))
|
||||
|
||||
pattern_KeyManagement_ImportRemoteKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"internal", "eth", "v1", "remotekeys"}, ""))
|
||||
|
||||
pattern_KeyManagement_DeleteRemoteKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"internal", "eth", "v1", "remotekeys"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -537,10 +316,4 @@ var (
|
||||
forward_KeyManagement_ImportKeystores_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_KeyManagement_DeleteKeystores_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_KeyManagement_ListRemoteKeys_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_KeyManagement_ImportRemoteKeys_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_KeyManagement_DeleteRemoteKeys_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
@@ -84,27 +84,6 @@ service KeyManagement {
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
rpc ListRemoteKeys(google.protobuf.Empty) returns (ListRemoteKeysResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/internal/eth/v1/remotekeys"
|
||||
};
|
||||
}
|
||||
|
||||
rpc ImportRemoteKeys(ImportRemoteKeysRequest) returns (ImportRemoteKeysResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/internal/eth/v1/remotekeys",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc DeleteRemoteKeys(DeleteRemoteKeysRequest) returns (DeleteRemoteKeysResponse) {
|
||||
option (google.api.http) = {
|
||||
delete: "/internal/eth/v1/remotekeys",
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message ListKeystoresResponse {
|
||||
@@ -154,55 +133,3 @@ message DeletedKeystoreStatus {
|
||||
Status status = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
|
||||
message ListRemoteKeysResponse {
|
||||
message Keystore {
|
||||
bytes pubkey = 1;
|
||||
string url = 2;
|
||||
bool readonly = 3;
|
||||
}
|
||||
repeated Keystore data = 1;
|
||||
}
|
||||
|
||||
message ImportRemoteKeysRequest {
|
||||
message Keystore {
|
||||
bytes pubkey = 1;
|
||||
string url = 2;
|
||||
}
|
||||
repeated Keystore remote_keys = 1;
|
||||
}
|
||||
|
||||
message ImportRemoteKeysResponse {
|
||||
repeated ImportedRemoteKeysStatus data = 1;
|
||||
}
|
||||
|
||||
message DeleteRemoteKeysRequest {
|
||||
repeated bytes pubkeys = 1;
|
||||
}
|
||||
|
||||
message DeleteRemoteKeysResponse {
|
||||
repeated DeletedRemoteKeysStatus data = 1;
|
||||
}
|
||||
|
||||
message ImportedRemoteKeysStatus {
|
||||
enum Status {
|
||||
UNKNOWN = 0;
|
||||
IMPORTED = 1;
|
||||
DUPLICATE = 2;
|
||||
ERROR = 3;
|
||||
}
|
||||
Status status = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message DeletedRemoteKeysStatus {
|
||||
enum Status {
|
||||
NOT_FOUND = 0;
|
||||
DELETED = 1;
|
||||
ERROR = 3; // skips 2 to match Delete KeyStore status which has error = 3.
|
||||
}
|
||||
Status status = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
|
||||
1550
proto/prysm/v1alpha1/validator.pb.go
generated
1550
proto/prysm/v1alpha1/validator.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -360,9 +360,6 @@ message StreamBlocksResponse {
|
||||
|
||||
// Representing an altair block.
|
||||
SignedBeaconBlockAltair altair_block = 2;
|
||||
|
||||
// Representing a bellatrix block.
|
||||
SignedBeaconBlockBellatrix bellatrix_block = 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ go_test(
|
||||
"//:prysm_sh",
|
||||
"//cmd/beacon-chain",
|
||||
"//cmd/validator",
|
||||
"//config/params:custom_configs",
|
||||
"//tools/bootnode",
|
||||
"@com_github_ethereum_go_ethereum//cmd/geth",
|
||||
"@web3signer",
|
||||
@@ -36,13 +35,13 @@ go_test(
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/operations/slashings/mock:go_default_library",
|
||||
"//beacon-chain/state/stategen/mock:go_default_library",
|
||||
"//build/bazel:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/endtoend/components:go_default_library",
|
||||
"//testing/endtoend/components/eth1:go_default_library",
|
||||
"//testing/endtoend/e2ez:go_default_library",
|
||||
"//testing/endtoend/evaluators:go_default_library",
|
||||
"//testing/endtoend/helpers:go_default_library",
|
||||
"//testing/endtoend/params:go_default_library",
|
||||
@@ -73,7 +72,6 @@ go_test(
|
||||
"//:prysm_sh",
|
||||
"//cmd/beacon-chain",
|
||||
"//cmd/validator",
|
||||
"//config/params:custom_configs",
|
||||
"//tools/bootnode",
|
||||
"@com_github_ethereum_go_ethereum//cmd/geth",
|
||||
"@web3signer",
|
||||
@@ -92,7 +90,6 @@ go_test(
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//build/bazel:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
|
||||
@@ -31,6 +31,7 @@ go_library(
|
||||
"//io/file:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"//testing/endtoend/components/eth1:go_default_library",
|
||||
"//testing/endtoend/e2ez:go_default_library",
|
||||
"//testing/endtoend/helpers:go_default_library",
|
||||
"//testing/endtoend/params:go_default_library",
|
||||
"//testing/endtoend/types:go_default_library",
|
||||
@@ -54,15 +55,11 @@ go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["web3remotesigner_test.go"],
|
||||
data = [
|
||||
"//config/params:custom_configs",
|
||||
"@web3signer",
|
||||
],
|
||||
data = ["@web3signer"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//testing/endtoend/params:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,14 +3,18 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/e2ez"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/bazelbuild/rules_go/go/tools/bazel"
|
||||
cmdshared "github.com/prysmaticlabs/prysm/cmd"
|
||||
@@ -24,7 +28,6 @@ import (
|
||||
|
||||
var _ e2etypes.ComponentRunner = (*BeaconNode)(nil)
|
||||
var _ e2etypes.ComponentRunner = (*BeaconNodeSet)(nil)
|
||||
var _ e2etypes.BeaconNodeSet = (*BeaconNodeSet)(nil)
|
||||
|
||||
// BeaconNodeSet represents set of beacon nodes.
|
||||
type BeaconNodeSet struct {
|
||||
@@ -33,18 +36,24 @@ type BeaconNodeSet struct {
|
||||
enr string
|
||||
ids []string
|
||||
started chan struct{}
|
||||
}
|
||||
|
||||
// SetENR assigns ENR to the set of beacon nodes.
|
||||
func (s *BeaconNodeSet) SetENR(enr string) {
|
||||
s.enr = enr
|
||||
nodes []*BeaconNode
|
||||
}
|
||||
|
||||
// NewBeaconNodes creates and returns a set of beacon nodes.
|
||||
func NewBeaconNodes(config *e2etypes.E2EConfig) *BeaconNodeSet {
|
||||
func NewBeaconNodes(config *e2etypes.E2EConfig, enr string) *BeaconNodeSet {
|
||||
// Create beacon nodes.
|
||||
//nodes := make([]e2etypes.ComponentRunner, e2e.TestParams.BeaconNodeCount)
|
||||
nodes := make([]*BeaconNode, e2e.TestParams.BeaconNodeCount)
|
||||
for i := 0; i < e2e.TestParams.BeaconNodeCount; i++ {
|
||||
nodes[i] = NewBeaconNode(config, i, enr)
|
||||
//nodes[i] = s.nodes[i]
|
||||
}
|
||||
|
||||
return &BeaconNodeSet{
|
||||
config: config,
|
||||
nodes: nodes,
|
||||
started: make(chan struct{}, 1),
|
||||
enr: enr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +63,9 @@ func (s *BeaconNodeSet) Start(ctx context.Context) error {
|
||||
return errors.New("empty ENR")
|
||||
}
|
||||
|
||||
// Create beacon nodes.
|
||||
nodes := make([]e2etypes.ComponentRunner, e2e.TestParams.BeaconNodeCount)
|
||||
for i := 0; i < e2e.TestParams.BeaconNodeCount; i++ {
|
||||
nodes[i] = NewBeaconNode(s.config, i, s.enr)
|
||||
nodes := make([]e2etypes.ComponentRunner, len(s.nodes))
|
||||
for i, n := range s.nodes {
|
||||
nodes[i] = n
|
||||
}
|
||||
|
||||
// Wait for all nodes to finish their job (blocking).
|
||||
@@ -74,6 +82,31 @@ func (s *BeaconNodeSet) Start(ctx context.Context) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BeaconNodeSet) ZPath() string {
|
||||
return "/beacon-nodes"
|
||||
}
|
||||
|
||||
func (s *BeaconNodeSet) ZMarkdown() (string, error) {
|
||||
tmpl := `
|
||||
%d beacon nodes
|
||||
---------------
|
||||
|
||||
%s`
|
||||
nodeList := ""
|
||||
for _, node := range s.nodes {
|
||||
nodeList = nodeList + fmt.Sprintf("\n - [beacon node #%d](%s)", node.index, node.ZPath())
|
||||
}
|
||||
return fmt.Sprintf(tmpl, len(s.nodes), nodeList), nil
|
||||
}
|
||||
|
||||
func (s *BeaconNodeSet) ZChildren() []e2ez.ZPage {
|
||||
zps := make([]e2ez.ZPage, len(s.nodes))
|
||||
for i := 0; i < len(s.nodes); i++ {
|
||||
zps[i] = s.nodes[i]
|
||||
}
|
||||
return zps
|
||||
}
|
||||
|
||||
// Started checks whether beacon node set is started and all nodes are ready to be queried.
|
||||
func (s *BeaconNodeSet) Started() <-chan struct{} {
|
||||
return s.started
|
||||
@@ -89,6 +122,62 @@ type BeaconNode struct {
|
||||
peerID string
|
||||
}
|
||||
|
||||
func (node *BeaconNode) ZPath() string {
|
||||
return fmt.Sprintf("/beacon-node/%d", node.index)
|
||||
}
|
||||
|
||||
var bnzm = template.Must(template.New("BeaconNode.ZMarkdown").Parse("" +
|
||||
"beacon node {{.Index}}\n" +
|
||||
"--------------\n\n" +
|
||||
"```\n" +
|
||||
"{{.StartCmd}}" +
|
||||
"```\n\n" +
|
||||
"http addr={{.HTTPAddr}}\n\n" +
|
||||
"grpc addr={{.GRPCAddr}}\n\n" +
|
||||
"db path={{.DBPath}}\n\n" +
|
||||
"log path={{.LogPath}}\n\n" +
|
||||
"stdout path={{.StdoutPath}}\n\n" +
|
||||
"stderr path={{.StderrPath}}\n\n"))
|
||||
|
||||
func (node *BeaconNode) ZMarkdown() (string, error) {
|
||||
bin, args, err := node.startCommand()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cmd := path.Join(bin, args[0])
|
||||
for _, a := range args {
|
||||
cmd += fmt.Sprintf("\n%s \\", a)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err = bnzm.Execute(buf, struct{
|
||||
Index int
|
||||
StartCmd string
|
||||
DBPath string
|
||||
LogPath string
|
||||
StdoutPath string
|
||||
StderrPath string
|
||||
HTTPAddr string
|
||||
GRPCAddr string
|
||||
}{
|
||||
Index: node.index,
|
||||
StartCmd: cmd,
|
||||
DBPath: node.dbPath(),
|
||||
LogPath: node.logPath(),
|
||||
StdoutPath: node.stdoutPath(),
|
||||
StderrPath: node.stderrPath(),
|
||||
HTTPAddr: node.httpAddr(),
|
||||
GRPCAddr: node.grpcAddr(),
|
||||
})
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func (node *BeaconNode) ZChildren() []e2ez.ZPage {
|
||||
return []e2ez.ZPage{}
|
||||
}
|
||||
|
||||
var _ e2ez.ZPage = &BeaconNode{}
|
||||
|
||||
// NewBeaconNode creates and returns a beacon node.
|
||||
func NewBeaconNode(config *e2etypes.E2EConfig, index int, enr string) *BeaconNode {
|
||||
return &BeaconNode{
|
||||
@@ -99,19 +188,13 @@ func NewBeaconNode(config *e2etypes.E2EConfig, index int, enr string) *BeaconNod
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts a fresh beacon node, connecting to all passed in beacon nodes.
|
||||
func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
func (node *BeaconNode) startCommand() (string, []string, error) {
|
||||
binaryPath, found := bazel.FindBinary("cmd/beacon-chain", "beacon-chain")
|
||||
if !found {
|
||||
log.Info(binaryPath)
|
||||
return errors.New("beacon chain binary not found")
|
||||
return "", []string{}, errors.New("beacon chain binary not found")
|
||||
}
|
||||
|
||||
config, index, enr := node.config, node.index, node.enr
|
||||
stdOutFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, index))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expectedNumOfPeers := e2e.TestParams.BeaconNodeCount + e2e.TestParams.LighthouseBeaconNodeCount - 1
|
||||
if node.config.TestSync {
|
||||
expectedNumOfPeers += 1
|
||||
@@ -122,11 +205,11 @@ func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
}
|
||||
jwtPath = path.Join(jwtPath, "geth/jwtsecret")
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s/eth2-beacon-node-%d", cmdshared.DataDirFlag.Name, e2e.TestParams.TestPath, index),
|
||||
fmt.Sprintf("--%s=%s", cmdshared.LogFileName.Name, stdOutFile.Name()),
|
||||
fmt.Sprintf("--%s=%s", cmdshared.DataDirFlag.Name, node.dbPath()),
|
||||
fmt.Sprintf("--%s=%s", cmdshared.LogFileName.Name, node.logPath()),
|
||||
fmt.Sprintf("--%s=%s", flags.DepositContractFlag.Name, e2e.TestParams.ContractAddress.Hex()),
|
||||
fmt.Sprintf("--%s=%d", flags.RPCPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeRPCPort+index),
|
||||
fmt.Sprintf("--%s=http://127.0.0.1:%d", flags.HTTPWeb3ProviderFlag.Name, e2e.TestParams.Ports.Eth1AuthRPCPort+index),
|
||||
fmt.Sprintf("--%s=http://127.0.0.1:%d", flags.HTTPWeb3ProviderFlag.Name, e2e.TestParams.Ports.Eth1RPCPort+index),
|
||||
fmt.Sprintf("--%s=%s", flags.ExecutionJWTSecretFlag.Name, jwtPath),
|
||||
fmt.Sprintf("--%s=%d", flags.MinSyncPeers.Name, 1),
|
||||
fmt.Sprintf("--%s=%d", cmdshared.P2PUDPPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeUDPPort+index),
|
||||
@@ -154,13 +237,53 @@ func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
}
|
||||
args = append(args, config.BeaconFlags...)
|
||||
|
||||
cmd := exec.CommandContext(ctx, binaryPath, args...) // #nosec G204 -- Safe
|
||||
// Write stdout and stderr to log files.
|
||||
stdout, err := os.Create(path.Join(e2e.TestParams.LogPath, fmt.Sprintf("beacon_node_%d_stdout.log", index)))
|
||||
return binaryPath, args, nil
|
||||
}
|
||||
|
||||
func (node *BeaconNode) dbPath() string {
|
||||
return fmt.Sprintf("%s/eth2-beacon-node-%d", e2e.TestParams.TestPath, node.index)
|
||||
}
|
||||
|
||||
func (node *BeaconNode) logPath() string {
|
||||
return filepath.Clean(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, node.index)))
|
||||
}
|
||||
|
||||
func (node *BeaconNode) stdoutPath() string {
|
||||
return path.Join(e2e.TestParams.LogPath, fmt.Sprintf("beacon_node_%d_stdout.log", node.index))
|
||||
}
|
||||
|
||||
func (node *BeaconNode) stderrPath() string {
|
||||
return path.Join(e2e.TestParams.LogPath, fmt.Sprintf("beacon_node_%d_stderr.log", node.index))
|
||||
}
|
||||
|
||||
func (node *BeaconNode) httpAddr() string {
|
||||
port := e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort+node.index
|
||||
return fmt.Sprintf("http://localhost:%d", port)
|
||||
}
|
||||
|
||||
func (node *BeaconNode) grpcAddr() string {
|
||||
port := e2e.TestParams.Ports.PrysmBeaconNodeRPCPort+node.index
|
||||
return fmt.Sprintf("localhost:%d", port)
|
||||
}
|
||||
|
||||
// Start starts a fresh beacon node, connecting to all passed in beacon nodes.
|
||||
func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
stdOutFile, err := helpers.DeleteAndCreateFile(node.logPath(), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderr, err := os.Create(path.Join(e2e.TestParams.LogPath, fmt.Sprintf("beacon_node_%d_stderr.log", index)))
|
||||
|
||||
bin, args, err := node.startCommand()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "filed to generate start command")
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, bin, args...) // #nosec G204 -- Safe
|
||||
// Write stdout and stderr to log files.
|
||||
stdout, err := os.Create(node.stdoutPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderr, err := os.Create(node.stderrPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,16 +297,16 @@ func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
}()
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
log.Infof("Starting beacon chain %d with flags: %s", index, strings.Join(args[2:], " "))
|
||||
log.Infof("Starting beacon chain %d with flags: %s", node.index, strings.Join(args[2:], " "))
|
||||
if err = cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start beacon node: %w", err)
|
||||
}
|
||||
|
||||
if err = helpers.WaitForTextInFile(stdOutFile, "gRPC server listening on port"); err != nil {
|
||||
return fmt.Errorf("could not find multiaddr for node %d, this means the node had issues starting: %w", index, err)
|
||||
return fmt.Errorf("could not find multiaddr for node %d, this means the node had issues starting: %w", node.index, err)
|
||||
}
|
||||
|
||||
if config.UseFixedPeerIDs {
|
||||
if node.config.UseFixedPeerIDs {
|
||||
peerId, err := helpers.FindFollowingTextInFile(stdOutFile, "Running node with peer id of ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find peer id: %w", err)
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/e2ez"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/bazelbuild/rules_go/go/tools/bazel"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
@@ -21,7 +24,6 @@ import (
|
||||
|
||||
var _ e2etypes.ComponentRunner = (*LighthouseBeaconNode)(nil)
|
||||
var _ e2etypes.ComponentRunner = (*LighthouseBeaconNodeSet)(nil)
|
||||
var _ e2etypes.BeaconNodeSet = (*LighthouseBeaconNodeSet)(nil)
|
||||
|
||||
// LighthouseBeaconNodeSet represents set of lighthouse beacon nodes.
|
||||
type LighthouseBeaconNodeSet struct {
|
||||
@@ -29,18 +31,20 @@ type LighthouseBeaconNodeSet struct {
|
||||
config *e2etypes.E2EConfig
|
||||
enr string
|
||||
started chan struct{}
|
||||
}
|
||||
|
||||
// SetENR assigns ENR to the set of beacon nodes.
|
||||
func (s *LighthouseBeaconNodeSet) SetENR(enr string) {
|
||||
s.enr = enr
|
||||
nodes []*LighthouseBeaconNode
|
||||
}
|
||||
|
||||
// NewLighthouseBeaconNodes creates and returns a set of lighthouse beacon nodes.
|
||||
func NewLighthouseBeaconNodes(config *e2etypes.E2EConfig) *LighthouseBeaconNodeSet {
|
||||
func NewLighthouseBeaconNodes(config *e2etypes.E2EConfig, enr string) *LighthouseBeaconNodeSet {
|
||||
nodes := make([]*LighthouseBeaconNode, e2e.TestParams.LighthouseBeaconNodeCount)
|
||||
for i := 0; i < e2e.TestParams.LighthouseBeaconNodeCount; i++ {
|
||||
nodes[i] = NewLighthouseBeaconNode(config, i, enr)
|
||||
}
|
||||
return &LighthouseBeaconNodeSet{
|
||||
config: config,
|
||||
started: make(chan struct{}, 1),
|
||||
enr: enr,
|
||||
nodes: nodes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +55,9 @@ func (s *LighthouseBeaconNodeSet) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Create beacon nodes.
|
||||
nodes := make([]e2etypes.ComponentRunner, e2e.TestParams.LighthouseBeaconNodeCount)
|
||||
nodes := make([]e2etypes.ComponentRunner, len(s.nodes))
|
||||
for i := 0; i < e2e.TestParams.LighthouseBeaconNodeCount; i++ {
|
||||
nodes[i] = NewLighthouseBeaconNode(s.config, i, s.enr)
|
||||
nodes[i] = s.nodes[i]
|
||||
}
|
||||
|
||||
// Wait for all nodes to finish their job (blocking).
|
||||
@@ -69,6 +73,32 @@ func (s *LighthouseBeaconNodeSet) Started() <-chan struct{} {
|
||||
return s.started
|
||||
}
|
||||
|
||||
func (s *LighthouseBeaconNodeSet) ZPath() string {
|
||||
return "/lh-beacon-nodes"
|
||||
}
|
||||
|
||||
func (s *LighthouseBeaconNodeSet) ZMarkdown() (string, error) {
|
||||
tmpl := `
|
||||
%d beacon nodes
|
||||
---------------
|
||||
|
||||
%s`
|
||||
nodeList := ""
|
||||
for _, node := range s.nodes {
|
||||
nodeList = nodeList + fmt.Sprintf("\n - [beacon node #%d](%s)", node.index, node.ZPath())
|
||||
}
|
||||
return fmt.Sprintf(tmpl, len(s.nodes), nodeList), nil
|
||||
}
|
||||
|
||||
func (s *LighthouseBeaconNodeSet) ZChildren() []e2ez.ZPage {
|
||||
zps := make([]e2ez.ZPage, len(s.nodes))
|
||||
for i := 0; i < len(s.nodes); i++ {
|
||||
zps[i] = s.nodes[i]
|
||||
}
|
||||
return zps
|
||||
}
|
||||
|
||||
|
||||
// LighthouseBeaconNode represents a lighthouse beacon node.
|
||||
type LighthouseBeaconNode struct {
|
||||
e2etypes.ComponentRunner
|
||||
@@ -88,39 +118,51 @@ func NewLighthouseBeaconNode(config *e2etypes.E2EConfig, index int, enr string)
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts a fresh beacon node, connecting to all passed in beacon nodes.
|
||||
func (node *LighthouseBeaconNode) Start(ctx context.Context) error {
|
||||
func (node *LighthouseBeaconNode) dbPath() string {
|
||||
return fmt.Sprintf("%s/lighthouse-beacon-node-%d", e2e.TestParams.TestPath, node.index)
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) stdoutPath() string {
|
||||
return path.Join(e2e.TestParams.LogPath, fmt.Sprintf("lighthouse_beacon_node_%d_stdout.log", node.index))
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) stderrPath() string {
|
||||
return path.Join(e2e.TestParams.LogPath, fmt.Sprintf("lighthouse_beacon_node_%d_stderr.log", node.index))
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) httpPort() int {
|
||||
return e2e.TestParams.Ports.LighthouseBeaconNodeHTTPPort+node.index
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) startCommand() (string, []string, error) {
|
||||
binaryPath, found := bazel.FindBinary("external/lighthouse", "lighthouse")
|
||||
if !found {
|
||||
log.Info(binaryPath)
|
||||
log.Error("beacon chain binary not found")
|
||||
}
|
||||
|
||||
_, index, _ := node.config, node.index, node.enr
|
||||
testDir, err := node.createTestnetDir(index)
|
||||
testDir, err := node.createTestnetDir(node.index)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", []string{}, err
|
||||
}
|
||||
|
||||
prysmNodeCount := e2e.TestParams.BeaconNodeCount
|
||||
jwtPath := path.Join(e2e.TestParams.TestPath, "eth1data/"+strconv.Itoa(node.index+prysmNodeCount)+"/")
|
||||
jwtPath = path.Join(jwtPath, "geth/jwtsecret")
|
||||
args := []string{
|
||||
"beacon_node",
|
||||
fmt.Sprintf("--datadir=%s/lighthouse-beacon-node-%d", e2e.TestParams.TestPath, index),
|
||||
fmt.Sprintf("--datadir=%s", node.dbPath()),
|
||||
fmt.Sprintf("--testnet-dir=%s", testDir),
|
||||
"--staking",
|
||||
"--enr-address=127.0.0.1",
|
||||
fmt.Sprintf("--enr-udp-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+index),
|
||||
fmt.Sprintf("--enr-tcp-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+index),
|
||||
fmt.Sprintf("--port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+index),
|
||||
fmt.Sprintf("--http-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeHTTPPort+index),
|
||||
fmt.Sprintf("--enr-udp-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+node.index),
|
||||
fmt.Sprintf("--enr-tcp-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+node.index),
|
||||
fmt.Sprintf("--port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeP2PPort+node.index),
|
||||
fmt.Sprintf("--http-port=%d", node.httpPort()),
|
||||
fmt.Sprintf("--target-peers=%d", 10),
|
||||
fmt.Sprintf("--eth1-endpoints=http://127.0.0.1:%d", e2e.TestParams.Ports.Eth1RPCPort+prysmNodeCount+index),
|
||||
fmt.Sprintf("--execution-endpoints=http://127.0.0.1:%d", e2e.TestParams.Ports.Eth1AuthRPCPort+prysmNodeCount+index),
|
||||
fmt.Sprintf("--eth1-endpoints=http://127.0.0.1:%d", e2e.TestParams.Ports.Eth1RPCPort+prysmNodeCount+node.index),
|
||||
fmt.Sprintf("--execution-endpoints=http://127.0.0.1:%d", e2e.TestParams.Ports.Eth1AuthRPCPort+prysmNodeCount+node.index),
|
||||
fmt.Sprintf("--jwt-secrets=%s", jwtPath),
|
||||
fmt.Sprintf("--boot-nodes=%s", node.enr),
|
||||
fmt.Sprintf("--metrics-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeMetricsPort+index),
|
||||
fmt.Sprintf("--metrics-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeMetricsPort+node.index),
|
||||
"--metrics",
|
||||
"--http",
|
||||
"--http-allow-sync-stalled",
|
||||
@@ -133,13 +175,22 @@ func (node *LighthouseBeaconNode) Start(ctx context.Context) error {
|
||||
args = append(args,
|
||||
fmt.Sprintf("--trusted-peers=%s", flagVal))
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, binaryPath, args...) /* #nosec G204 */
|
||||
// Write stdout and stderr to log files.
|
||||
stdout, err := os.Create(path.Join(e2e.TestParams.LogPath, fmt.Sprintf("lighthouse_beacon_node_%d_stdout.log", index)))
|
||||
return binaryPath, args, nil
|
||||
}
|
||||
|
||||
// Start starts a fresh beacon node, connecting to all passed in beacon nodes.
|
||||
func (node *LighthouseBeaconNode) Start(ctx context.Context) error {
|
||||
binaryPath, args, err := node.startCommand()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderr, err := os.Create(path.Join(e2e.TestParams.LogPath, fmt.Sprintf("lighthouse_beacon_node_%d_stderr.log", index)))
|
||||
cmd := exec.CommandContext(ctx, binaryPath, args...) /* #nosec G204 */
|
||||
// Write stdout and stderr to log files.
|
||||
stdout, err := os.Create(node.stdoutPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderr, err := os.Create(node.stderrPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -153,13 +204,13 @@ func (node *LighthouseBeaconNode) Start(ctx context.Context) error {
|
||||
}()
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
log.Infof("Starting lighthouse beacon chain %d with flags: %s", index, strings.Join(args[2:], " "))
|
||||
log.Infof("Starting lighthouse beacon chain %d with flags: %s", node.index, strings.Join(args[2:], " "))
|
||||
if err = cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start beacon node: %w", err)
|
||||
}
|
||||
|
||||
if err = helpers.WaitForTextInFile(stderr, "Configured for network"); err != nil {
|
||||
return fmt.Errorf("could not find initialization for node %d, this means the node had issues starting: %w", index, err)
|
||||
return fmt.Errorf("could not find initialization for node %d, this means the node had issues starting: %w", node.index, err)
|
||||
}
|
||||
|
||||
// Mark node as ready.
|
||||
@@ -196,3 +247,53 @@ func (node *LighthouseBeaconNode) createTestnetDir(index int) (string, error) {
|
||||
deployYaml := []byte("0")
|
||||
return testNetDir, file.WriteFile(deployPath, deployYaml)
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) ZPath() string {
|
||||
return fmt.Sprintf("/lh-beacon-node/%d", node.index)
|
||||
}
|
||||
|
||||
var lbnzm = template.Must(template.New("BeaconNode.ZMarkdown").Parse("" +
|
||||
"beacon node {{.Index}}\n" +
|
||||
"--------------\n\n" +
|
||||
"http addr={{.HTTPAddr}}\n\n" +
|
||||
"db path={{.DBPath}}\n\n" +
|
||||
"stdout path={{.StdoutPath}}\n\n" +
|
||||
"stderr path={{.StderrPath}}\n\n" +
|
||||
"```\n" +
|
||||
"{{.StartCmd}}" +
|
||||
"```\n\n"))
|
||||
|
||||
func (node *LighthouseBeaconNode) ZMarkdown() (string, error) {
|
||||
bin, args, err := node.startCommand()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cmd := path.Join(bin, args[0])
|
||||
for _, a := range args {
|
||||
cmd += fmt.Sprintf("\n%s \\", a)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err = lbnzm.Execute(buf, struct{
|
||||
Index int
|
||||
StartCmd string
|
||||
DBPath string
|
||||
StdoutPath string
|
||||
StderrPath string
|
||||
HTTPAddr string
|
||||
}{
|
||||
Index: node.index,
|
||||
StartCmd: cmd,
|
||||
DBPath: node.dbPath(),
|
||||
StdoutPath: node.stdoutPath(),
|
||||
StderrPath: node.stderrPath(),
|
||||
HTTPAddr: fmt.Sprintf("http://localhost:%d", node.httpPort()),
|
||||
})
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func (node *LighthouseBeaconNode) ZChildren() []e2ez.ZPage {
|
||||
return []e2ez.ZPage{}
|
||||
}
|
||||
|
||||
var _ e2ez.ZPage = &LighthouseBeaconNode{}
|
||||
|
||||
@@ -151,7 +151,7 @@ func (v *ValidatorNode) Start(ctx context.Context) error {
|
||||
args = append(args, features.E2EValidatorFlags...)
|
||||
}
|
||||
if v.config.UseWeb3RemoteSigner {
|
||||
args = append(args, fmt.Sprintf("--%s=http://localhost:%d", flags.Web3SignerURLFlag.Name, Web3RemoteSignerPort))
|
||||
args = append(args, fmt.Sprintf("--%s=localhost:%d", flags.Web3SignerURLFlag.Name, Web3RemoteSignerPort))
|
||||
// Write the pubkeys as comma seperated hex strings with 0x prefix.
|
||||
// See: https://docs.teku.consensys.net/en/latest/HowTo/External-Signer/Use-External-Signer/
|
||||
_, pubs, err := interop.DeterministicallyGenerateKeys(uint64(offset), uint64(validatorNum))
|
||||
|
||||
@@ -37,16 +37,13 @@ type rawKeyFile struct {
|
||||
}
|
||||
|
||||
type Web3RemoteSigner struct {
|
||||
ctx context.Context
|
||||
started chan struct{}
|
||||
configFilePath string
|
||||
cmd *exec.Cmd
|
||||
ctx context.Context
|
||||
started chan struct{}
|
||||
}
|
||||
|
||||
func NewWeb3RemoteSigner(configFilePath string) *Web3RemoteSigner {
|
||||
func NewWeb3RemoteSigner() *Web3RemoteSigner {
|
||||
return &Web3RemoteSigner{
|
||||
started: make(chan struct{}, 1),
|
||||
configFilePath: configFilePath,
|
||||
started: make(chan struct{}, 1),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,12 +66,6 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
network := "minimal"
|
||||
if len(w.configFilePath) > 0 {
|
||||
// A file path to yaml config file is acceptable network argument.
|
||||
network = w.configFilePath
|
||||
}
|
||||
|
||||
args := []string{
|
||||
// Global flags
|
||||
fmt.Sprintf("--key-store-path=%s", keystorePath),
|
||||
@@ -84,13 +75,13 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
|
||||
// Command
|
||||
"eth2",
|
||||
// Command flags
|
||||
"--network=" + network,
|
||||
"--network=minimal",
|
||||
"--slashing-protection-enabled=false", // Otherwise, a postgres DB is required.
|
||||
"--key-manager-api-enabled=true",
|
||||
"--enable-key-manager-api=true",
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, binaryPath, args...) // #nosec G204 -- Test code is safe to do this.
|
||||
w.cmd = cmd
|
||||
|
||||
// Write stdout and stderr to log files.
|
||||
stdout, err := os.Create(path.Join(e2e.TestParams.LogPath, "web3signer.stdout.log"))
|
||||
if err != nil {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bazelbuild/rules_go/go/tools/bazel"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/components"
|
||||
e2eparams "github.com/prysmaticlabs/prysm/testing/endtoend/params"
|
||||
@@ -14,11 +13,7 @@ import (
|
||||
|
||||
func TestWeb3RemoteSigner_StartsAndReturnsPublicKeys(t *testing.T) {
|
||||
require.NoError(t, e2eparams.Init(0))
|
||||
fp, err := bazel.Runfile("config/params/testdata/e2e_config.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wsc := components.NewWeb3RemoteSigner(fp)
|
||||
wsc := components.NewWeb3RemoteSigner()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -6,11 +6,10 @@ lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu-portable.tar.g
|
||||
def e2e_deps():
|
||||
http_archive(
|
||||
name = "web3signer",
|
||||
# Built from commit 17d253b which has important unreleased changes.
|
||||
urls = ["https://prysmaticlabs.com/uploads/web3signer-17d253b.tar.gz"],
|
||||
sha256 = "bf450a59a0845c1ce8100b3192c7fec021b565efe8b1ab46bed9f71cb994a6d7",
|
||||
urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/21.10.5/web3signer-21.10.5.tar.gz"],
|
||||
sha256 = "d122429f6a310bc555d1281e0b3f4e3ac43a7beec5e5dcf0a0d2416a5984f461",
|
||||
build_file = "@prysm//testing/endtoend:web3signer.BUILD",
|
||||
strip_prefix = "web3signer-develop",
|
||||
strip_prefix = "web3signer-21.10.5",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user