mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
27 Commits
prestonvan
...
old-clock-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a4adba3ae | ||
|
|
eb2303f02f | ||
|
|
cd7fd7ebb6 | ||
|
|
c10cbd9291 | ||
|
|
e5ab259ee1 | ||
|
|
9e74c3d641 | ||
|
|
59dcea81c2 | ||
|
|
9149dc2aae | ||
|
|
a7c9c76b18 | ||
|
|
5a4edf897f | ||
|
|
2d6b157eea | ||
|
|
32745b5484 | ||
|
|
bfdaf2ec5a | ||
|
|
39c343bcab | ||
|
|
de1ecf2d60 | ||
|
|
7aee67af90 | ||
|
|
9830ce43d6 | ||
|
|
63a8690140 | ||
|
|
7978a0269b | ||
|
|
021df67fdc | ||
|
|
f20e6351f5 | ||
|
|
a2e834a683 | ||
|
|
da25624b1d | ||
|
|
1a5dd879c5 | ||
|
|
65a9ede2d3 | ||
|
|
4b083c2ca9 | ||
|
|
82ae4caca8 |
@@ -5,6 +5,7 @@
|
||||
[](https://github.com/ethereum/consensus-specs/tree/v1.2.0-rc.1)
|
||||
[](https://github.com/ethereum/execution-apis/tree/v1.0.0-alpha.9/src/engine)
|
||||
[](https://discord.gg/CTYGPUJ)
|
||||
[](https://www.gitpoap.io/gh/prysmaticlabs/prysm)
|
||||
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/eth2/) specification, developed by [Prysmatic Labs](https://prysmaticlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
|
||||
|
||||
@@ -309,9 +309,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "4e8a18b21d056c4032605621b1a6632198eabab57cb90c61e273f344c287f1b2",
|
||||
strip_prefix = "eth2-networks-791a5369c5981e829698b17fbcdcdacbdaba97c8",
|
||||
url = "https://github.com/eth-clients/eth2-networks/archive/791a5369c5981e829698b17fbcdcdacbdaba97c8.tar.gz",
|
||||
sha256 = "126b615e3853e29b61f082f6c89c8bc1c38cd92fb84b0004396fc49e7acc8d9f",
|
||||
strip_prefix = "eth2-networks-f3ccbe0cf5798d5cd23e4e6e7119aefa043c0935",
|
||||
url = "https://github.com/eth-clients/eth2-networks/archive/f3ccbe0cf5798d5cd23e4e6e7119aefa043c0935.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
@@ -4,6 +4,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"chain_info.go",
|
||||
"clock.go",
|
||||
"error.go",
|
||||
"execution_engine.go",
|
||||
"head.go",
|
||||
@@ -52,6 +53,7 @@ go_library(
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/forkchoice/types:go_default_library",
|
||||
"//beacon-chain/geninit:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
@@ -59,7 +61,6 @@ go_library(
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
|
||||
@@ -27,8 +27,8 @@ type ChainInfoFetcher interface {
|
||||
GenesisFetcher
|
||||
CanonicalFetcher
|
||||
ForkFetcher
|
||||
TimeFetcher
|
||||
HeadDomainFetcher
|
||||
ClockProvider
|
||||
}
|
||||
|
||||
// HeadUpdater defines a common interface for methods in blockchain service
|
||||
@@ -37,9 +37,7 @@ type HeadUpdater interface {
|
||||
UpdateHead(context.Context) error
|
||||
}
|
||||
|
||||
// TimeFetcher retrieves the Ethereum consensus data that's related to time.
|
||||
type TimeFetcher interface {
|
||||
GenesisTime() time.Time
|
||||
type CurrentSlotter interface {
|
||||
CurrentSlot() types.Slot
|
||||
}
|
||||
|
||||
@@ -220,11 +218,6 @@ func (s *Service) HeadETH1Data() *ethpb.Eth1Data {
|
||||
return s.head.state.Eth1Data()
|
||||
}
|
||||
|
||||
// GenesisTime returns the genesis time of beacon chain.
|
||||
func (s *Service) GenesisTime() time.Time {
|
||||
return s.genesisTime
|
||||
}
|
||||
|
||||
// GenesisValidatorsRoot returns the genesis validators
|
||||
// root of the chain.
|
||||
func (s *Service) GenesisValidatorsRoot() [32]byte {
|
||||
@@ -343,8 +336,14 @@ func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool,
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Historical non-canonical blocks here are returned as optimistic for safety.
|
||||
isCanonical, err := s.IsCanonical(ctx, root)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if slots.ToEpoch(ss.Slot)+1 < validatedCheckpoint.Epoch {
|
||||
return false, nil
|
||||
return !isCanonical, nil
|
||||
}
|
||||
|
||||
// Checkpoint root could be zeros before the first finalized epoch. Use genesis root if the case.
|
||||
@@ -359,22 +358,49 @@ func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte) (bool,
|
||||
if ss.Slot > lastValidated.Slot {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
isCanonical, err := s.IsCanonical(ctx, root)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Historical non-canonical blocks here are returned as optimistic for safety.
|
||||
return !isCanonical, nil
|
||||
}
|
||||
|
||||
// SetGenesisTime sets the genesis time of beacon chain.
|
||||
func (s *Service) SetGenesisTime(t time.Time) {
|
||||
s.genesisTime = t
|
||||
s.clock = NewClock(t)
|
||||
close(s.clockReady)
|
||||
}
|
||||
|
||||
func (s *Service) setClock(c Clock) {
|
||||
s.clock = c
|
||||
close(s.clockReady)
|
||||
}
|
||||
|
||||
func (s *Service) genesisTime() time.Time {
|
||||
c, err := s.WaitForClock(context.TODO())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.GenesisTime()
|
||||
}
|
||||
|
||||
// ForkChoiceStore returns the fork choice store in the service.
|
||||
func (s *Service) ForkChoiceStore() forkchoice.ForkChoicer {
|
||||
return s.cfg.ForkChoiceStore
|
||||
}
|
||||
|
||||
// ClockProvider implements WaitForClock, yielding a clock type that can be used to get
|
||||
// the genesis time, slot values derived from genesis, or a possibly synthetic time.Now value
|
||||
type ClockProvider interface {
|
||||
WaitForClock(context.Context) (Clock, error)
|
||||
}
|
||||
|
||||
// WaitForClock will block until the Clock is ready. This provides a syncronization mechanism for services that
|
||||
// need the clock to be available before they can start running.
|
||||
func (s *Service) WaitForClock(ctx context.Context) (Clock, error) {
|
||||
if s.clockReady != nil {
|
||||
select {
|
||||
case <-s.clockReady:
|
||||
return s.clock, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
return s.clock, nil
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
|
||||
// Ensure Service implements chain info interface.
|
||||
var _ ChainInfoFetcher = (*Service)(nil)
|
||||
var _ TimeFetcher = (*Service)(nil)
|
||||
var _ ForkFetcher = (*Service)(nil)
|
||||
|
||||
// prepareForkchoiceState prepares a beacon state with the given data to mock
|
||||
@@ -202,9 +201,9 @@ func TestHeadState_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGenesisTime_CanRetrieve(t *testing.T) {
|
||||
c := &Service{genesisTime: time.Unix(999, 0)}
|
||||
c := &Service{clock: NewClock(time.Unix(999, 0))}
|
||||
wanted := time.Unix(999, 0)
|
||||
assert.Equal(t, wanted, c.GenesisTime(), "Did not get wanted genesis time")
|
||||
assert.Equal(t, wanted, c.genesisTime(), "Did not get wanted genesis time")
|
||||
}
|
||||
|
||||
func TestCurrentFork_CanRetrieve(t *testing.T) {
|
||||
@@ -304,6 +303,7 @@ func TestService_HeadGenesisValidatorsRoot(t *testing.T) {
|
||||
root = c.HeadGenesisValidatorsRoot()
|
||||
require.DeepEqual(t, root[:], s.GenesisValidatorsRoot())
|
||||
}
|
||||
|
||||
func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}}
|
||||
@@ -474,7 +474,7 @@ func TestService_IsOptimistic_DoublyLinkedTree(t *testing.T) {
|
||||
|
||||
func TestService_IsOptimisticBeforeBellatrix(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{genesisTime: time.Now()}
|
||||
c := &Service{clock: NewClock(time.Now())}
|
||||
opt, err := c.IsOptimistic(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, opt)
|
||||
|
||||
69
beacon-chain/blockchain/clock.go
Normal file
69
beacon-chain/blockchain/clock.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Clock abstracts important time-related concerns in the beacon chain:
|
||||
// - genesis time
|
||||
// - provides a time.Now() construct that can be overriden in tests
|
||||
// - syncronization point for code that needs to know the genesis time
|
||||
// - CurrentSlot: convenience conversion for current time -> slot
|
||||
// - support backwards compatibility with the TimeFetcher interface
|
||||
type Clock interface {
|
||||
GenesisTime() time.Time
|
||||
CurrentSlot() types.Slot
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// clock is a type that fulfills the TimeFetcher interface. This can be used in a number of places where
|
||||
// blockchain.ChainInfoFetcher has historically been used.
|
||||
type clock struct {
|
||||
time.Time
|
||||
now Now
|
||||
}
|
||||
var _ Clock = &clock{}
|
||||
|
||||
// clock provides an accessor to the embedded time, also fulfilling the blockchain.TimeFetcher interface.
|
||||
func (gt clock) GenesisTime() time.Time {
|
||||
return gt.Time
|
||||
}
|
||||
|
||||
// CurrentSlot returns the current slot relative to the time.Time value clock embeds.
|
||||
func (gt clock) CurrentSlot() types.Slot {
|
||||
return slots.Duration(gt.Time, gt.now())
|
||||
}
|
||||
|
||||
// Now provides a value for time.Now() that can be overriden in tests.
|
||||
func (gt clock) Now() time.Time {
|
||||
return gt.now()
|
||||
}
|
||||
|
||||
// ClockOpt is a functional option to change the behavior of a clock value made by NewClock.
|
||||
// It is primarily intended as a way to inject an alternate time.Now() callback (WithNow) for testing.
|
||||
type ClockOpt func(*clock)
|
||||
|
||||
// WithNow allows tests in particular to inject an alternate implementation of time.Now (vs using system time)
|
||||
func WithNow(n Now) ClockOpt {
|
||||
return func(gt *clock) {
|
||||
gt.now = n
|
||||
}
|
||||
}
|
||||
|
||||
// NewClock constructs a clock value using the given time value. Optional ClockOpt can be provided.
|
||||
// If an implementation of the Now function type is not provided (via WithNow), time.Now (system time) will be used by default.
|
||||
func NewClock(t time.Time, opts ...ClockOpt) clock {
|
||||
gt := clock{Time: t}
|
||||
for _, o := range opts {
|
||||
o(>)
|
||||
}
|
||||
if gt.now == nil {
|
||||
gt.now = time.Now
|
||||
}
|
||||
return gt
|
||||
}
|
||||
|
||||
// Now is a function that can return the current time. This will be time.Now by default, but can be overridden for tests.
|
||||
type Now func() time.Time
|
||||
31
beacon-chain/blockchain/clock_test.go
Normal file
31
beacon-chain/blockchain/clock_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestClock_GenesisTime(t *testing.T) {
|
||||
n := time.Now()
|
||||
gt := NewClock(n)
|
||||
gtt := gt.GenesisTime()
|
||||
require.Equal(t, gt.Time, gtt)
|
||||
require.Equal(t, n, gtt)
|
||||
}
|
||||
|
||||
func TestWithNow(t *testing.T) {
|
||||
genUnix := time.Unix(0, 0)
|
||||
var expectedSlots uint64 = 7200 // a day worth of slots
|
||||
now := genUnix.Add(time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot * expectedSlots))
|
||||
fn := func() time.Time {
|
||||
return now
|
||||
}
|
||||
|
||||
gt := NewClock(genUnix, WithNow(fn))
|
||||
// in this scenario, "genesis" is exactly 24 hours before "now"
|
||||
// so "now" should be 7200 slots after "genesis"
|
||||
require.Equal(t, types.Slot(expectedSlots), gt.CurrentSlot())
|
||||
}
|
||||
@@ -40,12 +40,14 @@ var (
|
||||
// The block is deemed invalid according to execution layer client.
|
||||
// The block violates certain fork choice rules (before finalized slot, not finalized ancestor)
|
||||
type invalidBlock struct {
|
||||
invalidAncestorRoots [][32]byte
|
||||
error
|
||||
root [32]byte
|
||||
}
|
||||
|
||||
type invalidBlockError interface {
|
||||
Error() string
|
||||
InvalidAncestorRoots() [][32]byte
|
||||
BlockRoot() [32]byte
|
||||
}
|
||||
|
||||
@@ -54,6 +56,11 @@ func (e invalidBlock) BlockRoot() [32]byte {
|
||||
return e.root
|
||||
}
|
||||
|
||||
// InvalidAncestorRoots returns an optional list of invalid roots of the invalid block which leads up last valid root.
|
||||
func (e invalidBlock) InvalidAncestorRoots() [][32]byte {
|
||||
return e.invalidAncestorRoots
|
||||
}
|
||||
|
||||
// IsInvalidBlock returns true if the error has `invalidBlock`.
|
||||
func IsInvalidBlock(e error) bool {
|
||||
if e == nil {
|
||||
@@ -78,3 +85,15 @@ func InvalidBlockRoot(e error) [32]byte {
|
||||
}
|
||||
return d.BlockRoot()
|
||||
}
|
||||
|
||||
// InvalidAncestorRoots returns a list of invalid roots up to last valid root.
|
||||
func InvalidAncestorRoots(e error) [][32]byte {
|
||||
if e == nil {
|
||||
return [][32]byte{}
|
||||
}
|
||||
d, ok := e.(invalidBlockError)
|
||||
if !ok {
|
||||
return [][32]byte{}
|
||||
}
|
||||
return d.InvalidAncestorRoots()
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ func TestIsInvalidBlock(t *testing.T) {
|
||||
|
||||
newErr := errors.Wrap(err, "wrap me")
|
||||
require.Equal(t, true, IsInvalidBlock(newErr))
|
||||
require.DeepEqual(t, [][32]byte(nil), InvalidAncestorRoots(err))
|
||||
}
|
||||
|
||||
func TestInvalidBlockRoot(t *testing.T) {
|
||||
@@ -22,4 +23,14 @@ func TestInvalidBlockRoot(t *testing.T) {
|
||||
|
||||
err := invalidBlock{error: ErrInvalidPayload, root: [32]byte{'a'}}
|
||||
require.Equal(t, [32]byte{'a'}, InvalidBlockRoot(err))
|
||||
require.DeepEqual(t, [][32]byte(nil), InvalidAncestorRoots(err))
|
||||
}
|
||||
|
||||
func TestInvalidRoots(t *testing.T) {
|
||||
roots := [][32]byte{{'d'}, {'b'}, {'c'}}
|
||||
err := invalidBlock{error: ErrInvalidPayload, root: [32]byte{'a'}, invalidAncestorRoots: roots}
|
||||
|
||||
require.Equal(t, true, IsInvalidBlock(err))
|
||||
require.Equal(t, [32]byte{'a'}, InvalidBlockRoot(err))
|
||||
require.DeepEqual(t, roots, InvalidAncestorRoots(err))
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
"invalidCount": len(invalidRoots),
|
||||
"newHeadRoot": fmt.Sprintf("%#x", bytesutil.Trunc(r[:])),
|
||||
}).Warn("Pruned invalid blocks")
|
||||
return pid, invalidBlock{error: ErrInvalidPayload, root: arg.headRoot}
|
||||
return pid, invalidBlock{error: ErrInvalidPayload, root: arg.headRoot, invalidAncestorRoots: invalidRoots}
|
||||
|
||||
default:
|
||||
log.WithError(err).Error(ErrUndefinedExecutionEngineError)
|
||||
@@ -232,7 +232,10 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
|
||||
"blockRoot": fmt.Sprintf("%#x", root),
|
||||
"invalidCount": len(invalidRoots),
|
||||
}).Warn("Pruned invalid blocks")
|
||||
return false, ErrInvalidPayload
|
||||
return false, invalidBlock{
|
||||
invalidAncestorRoots: invalidRoots,
|
||||
error: ErrInvalidPayload,
|
||||
}
|
||||
case powchain.ErrInvalidBlockHashPayloadStatus:
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
return false, ErrInvalidBlockHashPayloadStatus
|
||||
@@ -312,7 +315,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
}
|
||||
|
||||
// Get timestamp.
|
||||
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
||||
t, err := slots.ToTime(uint64(s.genesisTime().Unix()), slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ func Test_NotifyNewPayload(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
service.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
r, err := bellatrixBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
||||
@@ -800,7 +800,7 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
params.BeaconConfig().SafeSlotsToImportOptimistically = 128
|
||||
service.genesisTime = time.Now().Add(-time.Second * 12 * 2 * 128)
|
||||
service.SetGenesisTime(time.Now().Add(-time.Second * 12 * 2 * 128))
|
||||
|
||||
parentBlk := util.NewBeaconBlockBellatrix()
|
||||
wrappedParentBlock, err := wrapper.WrappedSignedBeaconBlock(parentBlk)
|
||||
@@ -903,7 +903,7 @@ func Test_IsOptimisticShallowExecutionParent(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
params.BeaconConfig().SafeSlotsToImportOptimistically = 128
|
||||
service.genesisTime = time.Now().Add(-time.Second * 12 * 2 * 128)
|
||||
service.SetGenesisTime(time.Now().Add(-time.Second * 12 * 2 * 128))
|
||||
payload := &v1.ExecutionPayload{
|
||||
ParentHash: make([]byte, 32),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
|
||||
@@ -219,7 +219,7 @@ func TestSaveOrphanedAtts_NoCommonAncestor(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2 -- 3
|
||||
@@ -273,7 +273,7 @@ func TestSaveOrphanedAtts(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2 -- 3
|
||||
@@ -339,7 +339,7 @@ func TestSaveOrphanedAtts_CanFilter(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+2)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+2)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2
|
||||
@@ -393,7 +393,7 @@ func TestSaveOrphanedAtts_NoCommonAncestor_DoublyLinkedTrie(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2 -- 3
|
||||
@@ -452,7 +452,7 @@ func TestSaveOrphanedAtts_DoublyLinkedTrie(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2 -- 3
|
||||
@@ -522,7 +522,7 @@ func TestSaveOrphanedAtts_CanFilter_DoublyLinkedTrie(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
service.genesisTime = time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+2)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
service.SetGenesisTime(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+2)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
|
||||
|
||||
// Chain setup
|
||||
// 0 -- 1 -- 2
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestService_getBlock(t *testing.T) {
|
||||
// block in cache
|
||||
b, err := wrapper.WrappedSignedBeaconBlock(b1)
|
||||
require.NoError(t, err)
|
||||
s.saveInitSyncBlock(ctx, r1, b)
|
||||
require.NoError(t, s.saveInitSyncBlock(ctx, r1, b))
|
||||
got, err := s.getBlock(ctx, r1)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, b, got)
|
||||
@@ -59,7 +59,7 @@ func TestService_hasBlockInInitSyncOrDB(t *testing.T) {
|
||||
// block in cache
|
||||
b, err := wrapper.WrappedSignedBeaconBlock(b1)
|
||||
require.NoError(t, err)
|
||||
s.saveInitSyncBlock(ctx, r1, b)
|
||||
require.NoError(t, s.saveInitSyncBlock(ctx, r1, b))
|
||||
require.Equal(t, true, s.hasBlockInInitSyncOrDB(ctx, r1))
|
||||
|
||||
// block in db
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *Service) OnAttestation(ctx context.Context, a *ethpb.Attestation) error
|
||||
return err
|
||||
}
|
||||
|
||||
genesisTime := uint64(s.genesisTime.Unix())
|
||||
genesisTime := uint64(s.genesisTime().Unix())
|
||||
|
||||
// Verify attestation target is from current epoch or previous epoch.
|
||||
if err := verifyAttTargetEpoch(ctx, genesisTime, uint64(time.Now().Unix()), tgt); err != nil {
|
||||
|
||||
@@ -132,8 +132,12 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.savePostStateInfo(ctx, blockRoot, signed, postState); err != nil {
|
||||
return err
|
||||
|
||||
if err := s.cfg.BeaconDB.SaveBlock(ctx, signed); err != nil {
|
||||
return errors.Wrapf(err, "could not save block from slot %d", signed.Block().Slot())
|
||||
}
|
||||
if err := s.cfg.StateGen.SaveState(ctx, blockRoot, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
|
||||
if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, signed.Block(), blockRoot, postState); err != nil {
|
||||
@@ -538,20 +542,6 @@ func (s *Service) InsertSlashingsToForkChoiceStore(ctx context.Context, slashing
|
||||
}
|
||||
}
|
||||
|
||||
// This saves post state info to DB or cache. This also saves post state info to fork choice store.
|
||||
// Post state info consists of processed block and state. Do not call this method unless the block and state are verified.
|
||||
func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b interfaces.SignedBeaconBlock, st state.BeaconState) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.savePostStateInfo")
|
||||
defer span.End()
|
||||
if err := s.cfg.BeaconDB.SaveBlock(ctx, b); err != nil {
|
||||
return errors.Wrapf(err, "could not save block from slot %d", b.Block().Slot())
|
||||
}
|
||||
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This removes the attestations from the mem pool. It will only remove the attestations if input root `r` is canonical,
|
||||
// meaning the block `b` is part of the canonical chain.
|
||||
func (s *Service) pruneCanonicalAttsFromPool(ctx context.Context, r [32]byte, b interfaces.SignedBeaconBlock) error {
|
||||
|
||||
@@ -24,7 +24,11 @@ import (
|
||||
|
||||
// CurrentSlot returns the current slot based on time.
|
||||
func (s *Service) CurrentSlot() types.Slot {
|
||||
return slots.CurrentSlot(uint64(s.genesisTime.Unix()))
|
||||
c, err := s.WaitForClock(context.TODO())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.CurrentSlot()
|
||||
}
|
||||
|
||||
// getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block
|
||||
@@ -48,7 +52,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b interfaces.BeaconBlock
|
||||
}
|
||||
|
||||
// Verify block slot time is not from the future.
|
||||
if err := slots.VerifyTime(uint64(s.genesisTime.Unix()), b.Slot(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
if err := slots.VerifyTime(uint64(s.genesisTime().Unix()), b.Slot(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -779,7 +779,7 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling_DoublyLinkedTree(t *testin
|
||||
|
||||
err = service.fillInForkChoiceMissingBlocks(
|
||||
context.Background(), wsb.Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
|
||||
require.ErrorIs(t, errNotDescendantOfFinalized, err)
|
||||
require.Equal(t, errNotDescendantOfFinalized.Error(), err.Error())
|
||||
}
|
||||
|
||||
// blockTree1 constructs the following tree:
|
||||
@@ -873,7 +873,7 @@ func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byt
|
||||
}
|
||||
|
||||
func TestCurrentSlot_HandlesOverflow(t *testing.T) {
|
||||
svc := Service{genesisTime: prysmTime.Now().Add(1 * time.Hour)}
|
||||
svc := Service{clock: NewClock(prysmTime.Now().Add(1 * time.Hour))}
|
||||
|
||||
slot := svc.CurrentSlot()
|
||||
require.Equal(t, types.Slot(0), slot, "Unexpected slot")
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
@@ -38,7 +36,7 @@ func (s *Service) AttestationTargetState(ctx context.Context, target *ethpb.Chec
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := slots.ValidateClock(ss, uint64(s.genesisTime.Unix())); err != nil {
|
||||
if err := slots.ValidateClock(ss, uint64(s.genesisTime().Unix())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.getAttPreState(ctx, target)
|
||||
@@ -102,19 +100,14 @@ func (s *Service) spawnProcessAttestationsRoutine(stateFeed *event.Feed) {
|
||||
break
|
||||
}
|
||||
|
||||
if s.genesisTime.IsZero() {
|
||||
log.Warn("ProcessAttestations routine waiting for genesis time")
|
||||
for s.genesisTime.IsZero() {
|
||||
if err := s.ctx.Err(); err != nil {
|
||||
log.WithError(err).Error("Giving up waiting for genesis time")
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
log.Warn("Genesis time received, now available to process attestations")
|
||||
log.Warn("ProcessAttestations routine waiting for genesis time")
|
||||
c, err := s.WaitForClock(s.ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("timeout waiting for genesis time in spawnProcessAttestationsRoutine")
|
||||
}
|
||||
log.Warn("Genesis time received, now available to process attestations")
|
||||
|
||||
st := slots.NewSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||||
st := slots.NewSlotTicker(c.GenesisTime(), params.BeaconConfig().SecondsPerSlot)
|
||||
for {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
@@ -219,7 +212,7 @@ func (s *Service) processAttestations(ctx context.Context) {
|
||||
// This delays consideration in the fork choice until their slot is in the past.
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
|
||||
nextSlot := a.Data.Slot + 1
|
||||
if err := slots.VerifyTime(uint64(s.genesisTime.Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
if err := slots.VerifyTime(uint64(s.genesisTime().Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -233,7 +226,7 @@ func (s *Service) processAttestations(ctx context.Context) {
|
||||
log.WithError(err).Error("Could not delete fork choice attestation in pool")
|
||||
}
|
||||
|
||||
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime) {
|
||||
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime()) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestAttestationCheckPtState_FarFutureSlot(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB)
|
||||
chainService.genesisTime = time.Now()
|
||||
chainService.SetGenesisTime(time.Now())
|
||||
|
||||
e := types.Epoch(slots.MaxSlotBuffer/uint64(params.BeaconConfig().SlotsPerEpoch) + 1)
|
||||
_, err := chainService.AttestationTargetState(context.Background(), ðpb.Checkpoint{Epoch: e})
|
||||
@@ -102,7 +102,7 @@ func TestProcessAttestations_Ok(t *testing.T) {
|
||||
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.genesisTime = prysmTime.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
service.SetGenesisTime(prysmTime.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second))
|
||||
genesisState, pks := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(prysmTime.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
@@ -209,7 +209,7 @@ func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) {
|
||||
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.genesisTime = prysmTime.Now().Add(-2 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
service.SetGenesisTime(prysmTime.Now().Add(-2 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second))
|
||||
genesisState, pks := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
copied := genesisState.Copy()
|
||||
|
||||
@@ -7,17 +7,12 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// This defines how many epochs since finality the run time will begin to save hot state on to the DB.
|
||||
var epochsSinceFinalitySaveHotStateDB = types.Epoch(100)
|
||||
|
||||
// BlockReceiver interface defines the methods of chain service for receiving and processing new blocks.
|
||||
type BlockReceiver interface {
|
||||
ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error
|
||||
@@ -53,18 +48,13 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaco
|
||||
return err
|
||||
}
|
||||
|
||||
// Have we been finalizing? Should we start saving hot states to db?
|
||||
if err := s.checkSaveHotStateDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reports on block and fork choice metrics.
|
||||
finalized := s.FinalizedCheckpt()
|
||||
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), finalized)
|
||||
|
||||
// Log block sync status.
|
||||
justified := s.CurrentJustifiedCheckpt()
|
||||
if err := logBlockSyncStatus(blockCopy.Block(), blockRoot, justified, finalized, receivedTime, uint64(s.genesisTime.Unix())); err != nil {
|
||||
if err := logBlockSyncStatus(blockCopy.Block(), blockRoot, justified, finalized, receivedTime, uint64(s.genesisTime().Unix())); err != nil {
|
||||
log.WithError(err).Error("Unable to log block sync status")
|
||||
}
|
||||
// Log payload data
|
||||
@@ -160,25 +150,3 @@ func (s *Service) handlePostBlockOperations(b interfaces.BeaconBlock) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This checks whether it's time to start saving hot state to DB.
|
||||
// It's time when there's `epochsSinceFinalitySaveHotStateDB` epochs of non-finality.
|
||||
func (s *Service) checkSaveHotStateDB(ctx context.Context) error {
|
||||
currentEpoch := slots.ToEpoch(s.CurrentSlot())
|
||||
// Prevent `sinceFinality` going underflow.
|
||||
var sinceFinality types.Epoch
|
||||
finalized := s.FinalizedCheckpt()
|
||||
if finalized == nil {
|
||||
return errNilFinalizedInStore
|
||||
}
|
||||
if currentEpoch > finalized.Epoch {
|
||||
sinceFinality = currentEpoch - finalized.Epoch
|
||||
}
|
||||
|
||||
if sinceFinality >= epochsSinceFinalitySaveHotStateDB {
|
||||
s.cfg.StateGen.EnableSaveHotStateToDB(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.cfg.StateGen.DisableSaveHotStateToDB(ctx)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,6 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
blockchainTesting "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
@@ -21,7 +17,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestService_ReceiveBlock(t *testing.T) {
|
||||
@@ -284,40 +281,3 @@ func TestService_HasBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, s.HasBlock(context.Background(), r))
|
||||
}
|
||||
|
||||
func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
|
||||
opts := testServiceOptsWithDB(t)
|
||||
hook := logTest.NewGlobal()
|
||||
s, err := NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
assert.LogsContain(t, hook, "Entering mode to save hot states in DB")
|
||||
}
|
||||
|
||||
func TestCheckSaveHotStateDB_Disabling(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
opts := testServiceOptsWithDB(t)
|
||||
s, err := NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
s.genesisTime = time.Now()
|
||||
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
assert.LogsContain(t, hook, "Exiting mode to save hot states in DB")
|
||||
}
|
||||
|
||||
func TestCheckSaveHotStateDB_Overflow(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
opts := testServiceOptsWithDB(t)
|
||||
s, err := NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
s.genesisTime = time.Now()
|
||||
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
assert.LogsDoNotContain(t, hook, "Entering mode to save hot states in DB")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/geninit"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||
@@ -53,7 +52,6 @@ type Service struct {
|
||||
cfg *config
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
genesisTime time.Time
|
||||
head *head
|
||||
headLock sync.RWMutex
|
||||
originBlockRoot [32]byte // genesis root, or weak subjectivity checkpoint root, depending on how the node is initialized
|
||||
@@ -65,6 +63,9 @@ type Service struct {
|
||||
justifiedBalances *stateBalanceCache
|
||||
wsVerifier *WeakSubjectivityVerifier
|
||||
processAttestationsLock sync.Mutex
|
||||
clock Clock
|
||||
clockReady chan struct{}
|
||||
clockWaiter geninit.ClockWaiter
|
||||
}
|
||||
|
||||
// config options for the service.
|
||||
@@ -138,6 +139,70 @@ func (s *Service) Start() {
|
||||
s.fillMissingPayloadIDRoutine(s.ctx, s.cfg.StateNotifier.StateFeed())
|
||||
}
|
||||
|
||||
func (s *Service) CombinedStart(genesis state.BeaconState) error {
|
||||
// TODO: we only do this on the genesis code path, not from disk - why?
|
||||
/*
|
||||
// Update committee shuffled indices for genesis epoch.
|
||||
if err := helpers.UpdateCommitteeCache(ctx, genesisState, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, genesisState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*/
|
||||
gt := time.Unix(int64(genesis.GenesisTime()), 0)
|
||||
s.SetGenesisTime(gt)
|
||||
s.cfg.AttService.SetGenesisTime(genesis.GenesisTime())
|
||||
|
||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||
s.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||
} else {
|
||||
s.cfg.ForkChoiceStore = protoarray.New()
|
||||
}
|
||||
// TODO: move head to use fork choice - we currently do not call initializeHeadFromDB!!
|
||||
|
||||
gb, err := s.cfg.BeaconDB.GenesisBlock(s.ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get genesis block from db")
|
||||
}
|
||||
if err := wrapper.BeaconBlockIsNil(gb); err != nil {
|
||||
return errors.Wrap(err, "nil value from database block query")
|
||||
}
|
||||
gbr, err := gb.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not compute hash_tree_root of genesis block")
|
||||
}
|
||||
if err := s.cfg.ForkChoiceStore.InsertNode(s.ctx, genesis, gbr); err != nil {
|
||||
log.Fatalf("Could not process genesis block for fork choice: %v", err)
|
||||
}
|
||||
s.cfg.ForkChoiceStore.SetGenesisTime(genesis.GenesisTime())
|
||||
|
||||
obr, err := s.cfg.BeaconDB.OriginCheckpointBlockRoot(s.ctx)
|
||||
if err == nil {
|
||||
// this means checkpoint sync was used, use the database origin root value
|
||||
s.originBlockRoot = obr
|
||||
} else {
|
||||
if !errors.Is(err, db.ErrNotFound) {
|
||||
return errors.Wrap(err, "could not retrieve checkpoint sync chain origin data from db")
|
||||
}
|
||||
// this means we got ErrNotFound, meaning checkpoint sync wasn't used, so the node should
|
||||
// be synced from genesis. In this case, use the genesis block root as origin.
|
||||
s.originBlockRoot = gbr
|
||||
}
|
||||
// TODO: should we set origin root when its the genesis block root, or is this method only for checkpoint sync?
|
||||
s.cfg.ForkChoiceStore.SetOriginRoot(s.originBlockRoot)
|
||||
|
||||
spawnCountdownIfPreGenesis(s.ctx, gt, genesis)
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: gt,
|
||||
GenesisValidatorsRoot: genesis.GenesisValidatorsRoot(),
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop the blockchain service's main event loop and associated goroutines.
|
||||
func (s *Service) Stop() error {
|
||||
defer s.cancel()
|
||||
@@ -173,7 +238,7 @@ func (s *Service) Status() error {
|
||||
// StartFromSavedState initializes the blockchain using a previously saved finalized checkpoint.
|
||||
func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
log.Info("Blockchain data already exists in DB, initializing...")
|
||||
s.genesisTime = time.Unix(int64(saved.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime.
|
||||
s.SetGenesisTime(time.Unix(int64(saved.GenesisTime()), 0)) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime.
|
||||
s.cfg.AttService.SetGenesisTime(saved.GenesisTime())
|
||||
|
||||
originRoot, err := s.originRootFromSavedState(s.ctx)
|
||||
@@ -185,7 +250,12 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
if err := s.initializeHeadFromDB(s.ctx); err != nil {
|
||||
return errors.Wrap(err, "could not set up chain info")
|
||||
}
|
||||
spawnCountdownIfPreGenesis(s.ctx, s.genesisTime, s.cfg.BeaconDB)
|
||||
gs, err := s.cfg.BeaconDB.GenesisState(s.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gt := time.Unix(int64(gs.GenesisTime()), 0)
|
||||
spawnCountdownIfPreGenesis(s.ctx, gt, gs)
|
||||
|
||||
justified, err := s.cfg.BeaconDB.JustifiedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
@@ -218,7 +288,7 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
Root: bytesutil.ToBytes32(finalized.Root)}); err != nil {
|
||||
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
|
||||
}
|
||||
forkChoicer.SetGenesisTime(uint64(s.genesisTime.Unix()))
|
||||
forkChoicer.SetGenesisTime(uint64(s.genesisTime().Unix()))
|
||||
|
||||
st, err := s.cfg.StateGen.StateByRoot(s.ctx, fRoot)
|
||||
if err != nil {
|
||||
@@ -247,7 +317,7 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: s.genesisTime,
|
||||
StartTime: s.genesisTime(),
|
||||
GenesisValidatorsRoot: saved.GenesisValidatorsRoot(),
|
||||
},
|
||||
})
|
||||
@@ -295,48 +365,11 @@ func (s *Service) initializeHeadFromDB(ctx context.Context) error {
|
||||
return errors.New("no finalized epoch in the database")
|
||||
}
|
||||
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||
var finalizedState state.BeaconState
|
||||
|
||||
finalizedState, err = s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
||||
finalizedState, err := s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
|
||||
if flags.Get().HeadSync {
|
||||
headBlock, err := s.cfg.BeaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head block")
|
||||
}
|
||||
headEpoch := slots.ToEpoch(headBlock.Block().Slot())
|
||||
var epochsSinceFinality types.Epoch
|
||||
if headEpoch > finalized.Epoch {
|
||||
epochsSinceFinality = headEpoch - finalized.Epoch
|
||||
}
|
||||
// Head sync when node is far enough beyond known finalized epoch,
|
||||
// this becomes really useful during long period of non-finality.
|
||||
if epochsSinceFinality >= headSyncMinEpochsAfterCheckpoint {
|
||||
headRoot, err := headBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash head block")
|
||||
}
|
||||
finalizedState, err := s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
log.Infof("Regenerating state from the last checkpoint at slot %d to current head slot of %d."+
|
||||
"This process may take a while, please wait.", finalizedState.Slot(), headBlock.Block().Slot())
|
||||
headState, err := s.cfg.StateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state")
|
||||
}
|
||||
s.setHead(headRoot, headBlock, headState)
|
||||
return nil
|
||||
} else {
|
||||
log.Warnf("Finalized checkpoint at slot %d is too close to the current head slot, "+
|
||||
"resetting head from the checkpoint ('--%s' flag is ignored).",
|
||||
finalizedState.Slot(), flags.HeadSync.Name)
|
||||
}
|
||||
}
|
||||
if finalizedState == nil || finalizedState.IsNil() {
|
||||
return errors.New("finalized state can't be nil")
|
||||
}
|
||||
@@ -352,34 +385,15 @@ func (s *Service) initializeHeadFromDB(ctx context.Context) error {
|
||||
|
||||
func (s *Service) startFromPOWChain() error {
|
||||
log.Info("Waiting to reach the validator deposit threshold to start the beacon chain...")
|
||||
if s.cfg.ChainStartFetcher == nil {
|
||||
return errors.New("not configured web3Service for POW chain")
|
||||
}
|
||||
go func() {
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
defer stateSub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case e := <-stateChannel:
|
||||
if e.Type == statefeed.ChainStarted {
|
||||
data, ok := e.Data.(*statefeed.ChainStartedData)
|
||||
if !ok {
|
||||
log.Error("event data is not type *statefeed.ChainStartedData")
|
||||
return
|
||||
}
|
||||
log.WithField("starttime", data.StartTime).Debug("Received chain start event")
|
||||
s.onPowchainStart(s.ctx, data.StartTime)
|
||||
return
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
log.Debug("Context closed, exiting goroutine")
|
||||
return
|
||||
case err := <-stateSub.Err():
|
||||
log.WithError(err).Error("Subscription to state notifier failed")
|
||||
return
|
||||
}
|
||||
c, err := s.clockWaiter.WaitForClock(s.ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("timeout while waiting for genesis during blockchain service startup")
|
||||
return
|
||||
}
|
||||
log.WithField("starttime", c.GenesisTime()).Debug("Received chain start event")
|
||||
s.onPowchainStart(s.ctx, c.GenesisTime())
|
||||
s.setClock(c)
|
||||
}()
|
||||
|
||||
return nil
|
||||
@@ -388,8 +402,7 @@ func (s *Service) startFromPOWChain() error {
|
||||
// onPowchainStart initializes a series of deposits from the ChainStart deposits in the eth1
|
||||
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
|
||||
func (s *Service) onPowchainStart(ctx context.Context, genesisTime time.Time) {
|
||||
preGenesisState := s.cfg.ChainStartFetcher.PreGenesisState()
|
||||
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.cfg.ChainStartFetcher.ChainStartEth1Data())
|
||||
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not initialize beacon chain: %v", err)
|
||||
}
|
||||
@@ -414,29 +427,10 @@ func (s *Service) onPowchainStart(ctx context.Context, genesisTime time.Time) {
|
||||
// initializes the state and genesis block of the beacon chain to persistent storage
|
||||
// based on a genesis timestamp value obtained from the ChainStart event emitted
|
||||
// by the ETH1.0 Deposit Contract and the POWChain service of the node.
|
||||
func (s *Service) initializeBeaconChain(
|
||||
ctx context.Context,
|
||||
genesisTime time.Time,
|
||||
preGenesisState state.BeaconState,
|
||||
eth1data *ethpb.Eth1Data) (state.BeaconState, error) {
|
||||
func (s *Service) initializeBeaconChain(ctx context.Context, genesisTime time.Time) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.Service.initializeBeaconChain")
|
||||
defer span.End()
|
||||
s.genesisTime = genesisTime
|
||||
unixTime := uint64(genesisTime.Unix())
|
||||
|
||||
genesisState, err := transition.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not initialize genesis state")
|
||||
}
|
||||
|
||||
if err := s.saveGenesisData(ctx, genesisState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save genesis data")
|
||||
}
|
||||
|
||||
log.Info("Initialized beacon chain genesis state")
|
||||
|
||||
// Clear out all pre-genesis data now that the state is initialized.
|
||||
s.cfg.ChainStartFetcher.ClearPreGenesisData()
|
||||
s.SetGenesisTime(genesisTime)
|
||||
|
||||
// Update committee shuffled indices for genesis epoch.
|
||||
if err := helpers.UpdateCommitteeCache(ctx, genesisState, 0); err != nil {
|
||||
@@ -447,15 +441,11 @@ func (s *Service) initializeBeaconChain(
|
||||
}
|
||||
|
||||
s.cfg.AttService.SetGenesisTime(genesisState.GenesisTime())
|
||||
|
||||
return genesisState, nil
|
||||
}
|
||||
|
||||
// This gets called when beacon chain is first initialized to save genesis data (state, block, and more) in db.
|
||||
func (s *Service) saveGenesisData(ctx context.Context, genesisState state.BeaconState) error {
|
||||
if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis data")
|
||||
}
|
||||
genesisBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
if err != nil || genesisBlk == nil || genesisBlk.IsNil() {
|
||||
return fmt.Errorf("could not load genesis block: %v", err)
|
||||
@@ -476,7 +466,7 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState state.Beacon
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "Could not set optimistic status of genesis block to false")
|
||||
}
|
||||
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime.Unix()))
|
||||
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime().Unix()))
|
||||
|
||||
s.setHead(genesisBlkRoot, genesisBlk, genesisState)
|
||||
return nil
|
||||
@@ -494,19 +484,14 @@ func (s *Service) hasBlock(ctx context.Context, root [32]byte) bool {
|
||||
return s.cfg.BeaconDB.HasBlock(ctx, root)
|
||||
}
|
||||
|
||||
func spawnCountdownIfPreGenesis(ctx context.Context, genesisTime time.Time, db db.HeadAccessDatabase) {
|
||||
currentTime := prysmTime.Now()
|
||||
if currentTime.After(genesisTime) {
|
||||
func spawnCountdownIfPreGenesis(ctx context.Context, gt time.Time, gs state.BeaconState) {
|
||||
// only proceed if this function runs before genesis time
|
||||
if prysmTime.Now().After(gt) {
|
||||
return
|
||||
}
|
||||
|
||||
gState, err := db.GenesisState(ctx)
|
||||
gr, err := gs.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not retrieve genesis state: %v", err)
|
||||
log.WithError(err).Fatal("Could not compute hash_tree_root of genesis state")
|
||||
}
|
||||
gRoot, err := gState.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slots.CountdownToGenesis(ctx, genesisTime, uint64(gState.NumValidators()), gRoot)
|
||||
go slots.CountdownToGenesis(ctx, gt, uint64(gs.NumValidators()), gr)
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
|
||||
chainService, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err, "Unable to setup chain service")
|
||||
chainService.genesisTime = time.Unix(1, 0) // non-zero time
|
||||
chainService.SetGenesisTime(time.Unix(1, 0)) // non-zero time
|
||||
|
||||
return chainService
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ go_library(
|
||||
],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/feed:go_default_library",
|
||||
"//beacon-chain/core/feed/block:go_default_library",
|
||||
|
||||
@@ -5,6 +5,7 @@ package testing
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -64,6 +65,7 @@ type ChainService struct {
|
||||
ReceiveBlockMockErr error
|
||||
OptimisticCheckRootReceived [32]byte
|
||||
FinalizedRoots map[[32]byte]bool
|
||||
Clock blockchain.Clock
|
||||
}
|
||||
|
||||
// ForkChoicer mocks the same method in the chain service
|
||||
@@ -326,6 +328,13 @@ func (s *ChainService) GenesisTime() time.Time {
|
||||
return s.Genesis
|
||||
}
|
||||
|
||||
func (s *ChainService) WaitForClock(ctx context.Context) (blockchain.Clock, error) {
|
||||
if s.Clock == nil {
|
||||
return blockchain.NewClock(time.Now()), nil
|
||||
}
|
||||
return s.Clock, nil
|
||||
}
|
||||
|
||||
// GenesisValidatorsRoot mocks the same method in the chain service.
|
||||
func (s *ChainService) GenesisValidatorsRoot() [32]byte {
|
||||
return s.ValidatorsRoot
|
||||
@@ -336,7 +345,7 @@ func (s *ChainService) CurrentSlot() types.Slot {
|
||||
if s.Slot != nil {
|
||||
return *s.Slot
|
||||
}
|
||||
return types.Slot(uint64(time.Now().Unix()-s.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot)
|
||||
return s.Clock.CurrentSlot()
|
||||
}
|
||||
|
||||
// Participation mocks the same method in the chain service.
|
||||
@@ -464,3 +473,11 @@ func (s *ChainService) ReceiveAttesterSlashing(context.Context, *ethpb.AttesterS
|
||||
func (s *ChainService) IsFinalized(_ context.Context, blockRoot [32]byte) bool {
|
||||
return s.FinalizedRoots[blockRoot]
|
||||
}
|
||||
|
||||
func NewMockClock(now time.Time, slotsAfterGenesis types.Slot) blockchain.Clock {
|
||||
offset := uint64(slotsAfterGenesis) * params.BeaconConfig().SecondsPerSlot
|
||||
genesis := now.Add(-1 * time.Second * time.Duration(offset))
|
||||
return blockchain.NewClock(genesis, blockchain.WithNow(func() time.Time {
|
||||
return genesis
|
||||
}))
|
||||
}
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"attestation.go",
|
||||
"attester_slashing.go",
|
||||
"deposit.go",
|
||||
"error.go",
|
||||
"eth1_data.go",
|
||||
"exit.go",
|
||||
"genesis.go",
|
||||
@@ -15,6 +16,7 @@ go_library(
|
||||
"proposer_slashing.go",
|
||||
"randao.go",
|
||||
"signature.go",
|
||||
"withdrawals.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks",
|
||||
visibility = [
|
||||
@@ -39,6 +41,7 @@ go_library(
|
||||
"//contracts/deposit:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//crypto/hash/htr:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
@@ -74,6 +77,7 @@ go_test(
|
||||
"proposer_slashing_test.go",
|
||||
"randao_test.go",
|
||||
"signature_test.go",
|
||||
"withdrawals_test.go",
|
||||
],
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
@@ -92,6 +96,7 @@ go_test(
|
||||
"//consensus-types/wrapper:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash/htr:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
|
||||
8
beacon-chain/core/blocks/error.go
Normal file
8
beacon-chain/core/blocks/error.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package blocks
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
var errNilSignedWithdrawalMessage = errors.New("nil SignedBLSToExecutionChange message")
|
||||
var errNilWithdrawalMessage = errors.New("nil BLSToExecutionChange message")
|
||||
var errInvalidBLSPrefix = errors.New("withdrawal credential prefix is not a BLS prefix")
|
||||
var errInvalidWithdrawalCredentials = errors.New("withdrawal credentials do not match")
|
||||
@@ -101,15 +101,6 @@ func Test_IsMergeComplete(t *testing.T) {
|
||||
}(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "has tx root",
|
||||
payload: func() *enginev1.ExecutionPayloadHeader {
|
||||
h := emptyPayloadHeader()
|
||||
h.TransactionsRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return h
|
||||
}(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "has extra data",
|
||||
payload: func() *enginev1.ExecutionPayloadHeader {
|
||||
|
||||
78
beacon-chain/core/blocks/withdrawals.go
Normal file
78
beacon-chain/core/blocks/withdrawals.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash/htr"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
const executionToBLSPadding = 12
|
||||
|
||||
// ProcessBLSToExecutionChange validates a SignedBLSToExecution message and
|
||||
// changes the validator's withdrawal address accordingly.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
//def process_bls_to_execution_change(state: BeaconState, signed_address_change: SignedBLSToExecutionChange) -> None:
|
||||
// validator = state.validators[address_change.validator_index]
|
||||
//
|
||||
// assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
|
||||
// assert validator.withdrawal_credentials[1:] == hash(address_change.from_bls_pubkey)[1:]
|
||||
//
|
||||
// domain = get_domain(state, DOMAIN_BLS_TO_EXECUTION_CHANGE)
|
||||
// signing_root = compute_signing_root(address_change, domain)
|
||||
// assert bls.Verify(address_change.from_bls_pubkey, signing_root, signed_address_change.signature)
|
||||
//
|
||||
// validator.withdrawal_credentials = (
|
||||
// ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||
// + b'\x00' * 11
|
||||
// + address_change.to_execution_address
|
||||
// )
|
||||
//
|
||||
func ProcessBLSToExecutionChange(st state.BeaconState, signed *ethpb.SignedBLSToExecutionChange) (state.BeaconState, error) {
|
||||
if signed == nil {
|
||||
return st, errNilSignedWithdrawalMessage
|
||||
}
|
||||
message := signed.Message
|
||||
if message == nil {
|
||||
return st, errNilWithdrawalMessage
|
||||
}
|
||||
|
||||
val, err := st.ValidatorAtIndex(message.ValidatorIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cred := val.WithdrawalCredentials
|
||||
if cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte {
|
||||
return nil, errInvalidBLSPrefix
|
||||
}
|
||||
|
||||
// hash the public key and verify it matches the withdrawal credentials
|
||||
fromPubkey := message.FromBlsPubkey
|
||||
pubkeyChunks := [][32]byte{bytesutil.ToBytes32(fromPubkey[:32]), bytesutil.ToBytes32(fromPubkey[32:])}
|
||||
digest := make([][32]byte, 1)
|
||||
htr.VectorizedSha256(pubkeyChunks, digest)
|
||||
if !bytes.Equal(digest[0][1:], cred[1:]) {
|
||||
return nil, errInvalidWithdrawalCredentials
|
||||
}
|
||||
|
||||
epoch := slots.ToEpoch(st.Slot())
|
||||
domain, err := signing.Domain(st.Fork(), epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := signing.VerifySigningRoot(message, fromPubkey, signed.Signature, domain); err != nil {
|
||||
return nil, signing.ErrSigFailedToVerify
|
||||
}
|
||||
newCredentials := make([]byte, executionToBLSPadding)
|
||||
newCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
val.WithdrawalCredentials = append(newCredentials, message.ToExecutionAddress...)
|
||||
err = st.UpdateValidatorAtIndex(message.ValidatorIndex, val)
|
||||
return st, err
|
||||
}
|
||||
193
beacon-chain/core/blocks/withdrawals_test.go
Normal file
193
beacon-chain/core/blocks/withdrawals_test.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package blocks_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash/htr"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestProcessBLSToExecutionChange(t *testing.T) {
|
||||
t.Run("happy case", func(t *testing.T) {
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubkey := priv.PublicKey().Marshal()
|
||||
|
||||
message := ðpb.BLSToExecutionChange{
|
||||
ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13},
|
||||
ValidatorIndex: 0,
|
||||
FromBlsPubkey: pubkey,
|
||||
}
|
||||
|
||||
pubkeyChunks := [][32]byte{bytesutil.ToBytes32(pubkey[:32]), bytesutil.ToBytes32(pubkey[32:])}
|
||||
digest := make([][32]byte, 1)
|
||||
htr.VectorizedSha256(pubkeyChunks, digest)
|
||||
digest[0][0] = params.BeaconConfig().BLSWithdrawalPrefixByte
|
||||
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
WithdrawalCredentials: digest[0][:],
|
||||
},
|
||||
}
|
||||
st, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: ðpb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv)
|
||||
require.NoError(t, err)
|
||||
|
||||
signed := ðpb.SignedBLSToExecutionChange{
|
||||
Message: message,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
st, err = blocks.ProcessBLSToExecutionChange(st, signed)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err := st.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.DeepEqual(t, message.ToExecutionAddress, val.WithdrawalCredentials[12:])
|
||||
})
|
||||
|
||||
t.Run("non-existent validator", func(t *testing.T) {
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubkey := priv.PublicKey().Marshal()
|
||||
|
||||
message := ðpb.BLSToExecutionChange{
|
||||
ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13},
|
||||
ValidatorIndex: 1,
|
||||
FromBlsPubkey: pubkey,
|
||||
}
|
||||
|
||||
pubkeyChunks := [][32]byte{bytesutil.ToBytes32(pubkey[:32]), bytesutil.ToBytes32(pubkey[32:])}
|
||||
digest := make([][32]byte, 1)
|
||||
htr.VectorizedSha256(pubkeyChunks, digest)
|
||||
digest[0][0] = params.BeaconConfig().BLSWithdrawalPrefixByte
|
||||
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
WithdrawalCredentials: digest[0][:],
|
||||
},
|
||||
}
|
||||
st, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: ðpb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv)
|
||||
require.NoError(t, err)
|
||||
|
||||
signed := ðpb.SignedBLSToExecutionChange{
|
||||
Message: message,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
_, err = blocks.ProcessBLSToExecutionChange(st, signed)
|
||||
require.ErrorContains(t, "out of range", err)
|
||||
})
|
||||
|
||||
t.Run("signature does not verify", func(t *testing.T) {
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubkey := priv.PublicKey().Marshal()
|
||||
|
||||
message := ðpb.BLSToExecutionChange{
|
||||
ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13},
|
||||
ValidatorIndex: 0,
|
||||
FromBlsPubkey: pubkey,
|
||||
}
|
||||
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
WithdrawalCredentials: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
}
|
||||
st, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: ðpb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv)
|
||||
require.NoError(t, err)
|
||||
|
||||
signed := ðpb.SignedBLSToExecutionChange{
|
||||
Message: message,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
_, err = blocks.ProcessBLSToExecutionChange(st, signed)
|
||||
require.ErrorContains(t, "withdrawal credentials do not match", err)
|
||||
})
|
||||
|
||||
t.Run("invalid BLS prefix", func(t *testing.T) {
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
pubkey := priv.PublicKey().Marshal()
|
||||
|
||||
message := ðpb.BLSToExecutionChange{
|
||||
ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13},
|
||||
ValidatorIndex: 0,
|
||||
FromBlsPubkey: pubkey,
|
||||
}
|
||||
|
||||
pubkeyChunks := [][32]byte{bytesutil.ToBytes32(pubkey[:32]), bytesutil.ToBytes32(pubkey[32:])}
|
||||
digest := make([][32]byte, 1)
|
||||
htr.VectorizedSha256(pubkeyChunks, digest)
|
||||
digest[0][0] = params.BeaconConfig().BLSWithdrawalPrefixByte
|
||||
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
WithdrawalCredentials: digest[0][:],
|
||||
},
|
||||
}
|
||||
registry[0].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
|
||||
st, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: ðpb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv)
|
||||
require.NoError(t, err)
|
||||
|
||||
signed := ðpb.SignedBLSToExecutionChange{
|
||||
Message: message,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
_, err = blocks.ProcessBLSToExecutionChange(st, signed)
|
||||
require.ErrorContains(t, "withdrawal credential prefix is not a BLS prefix", err)
|
||||
|
||||
})
|
||||
}
|
||||
69
beacon-chain/geninit/clock.go
Normal file
69
beacon-chain/geninit/clock.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package geninit
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Clock abstracts important time-related concerns in the beacon chain:
|
||||
// - genesis time
|
||||
// - provides a time.Now() construct that can be overriden in tests
|
||||
// - syncronization point for code that needs to know the genesis time
|
||||
// - CurrentSlot: convenience conversion for current time -> slot
|
||||
// - support backwards compatibility with the TimeFetcher interface
|
||||
type Clock interface {
|
||||
GenesisTime() time.Time
|
||||
CurrentSlot() types.Slot
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// clock is a type that fulfills the TimeFetcher interface. This can be used in a number of places where
|
||||
// blockchain.ChainInfoFetcher has historically been used.
|
||||
type clock struct {
|
||||
genesis time.Time
|
||||
now Now
|
||||
}
|
||||
var _ Clock = &clock{}
|
||||
|
||||
// clock provides an accessor to the embedded time, also fulfilling the blockchain.TimeFetcher interface.
|
||||
func (gt clock) GenesisTime() time.Time {
|
||||
return gt.genesis
|
||||
}
|
||||
|
||||
// CurrentSlot returns the current slot relative to the time.Time value clock embeds.
|
||||
func (gt clock) CurrentSlot() types.Slot {
|
||||
return slots.Duration(gt.genesis, gt.now())
|
||||
}
|
||||
|
||||
// Now provides a value for time.Now() that can be overriden in tests.
|
||||
func (gt clock) Now() time.Time {
|
||||
return gt.now()
|
||||
}
|
||||
|
||||
// ClockOpt is a functional option to change the behavior of a clock value made by NewClock.
|
||||
// It is primarily intended as a way to inject an alternate time.Now() callback (WithNow) for testing.
|
||||
type ClockOpt func(*clock)
|
||||
|
||||
// WithNow allows tests in particular to inject an alternate implementation of time.Now (vs using system time)
|
||||
func WithNow(n Now) ClockOpt {
|
||||
return func(gt *clock) {
|
||||
gt.now = n
|
||||
}
|
||||
}
|
||||
|
||||
// NewClock constructs a clock value using the given time value. Optional ClockOpt can be provided.
|
||||
// If an implementation of the Now function type is not provided (via WithNow), time.Now (system time) will be used by default.
|
||||
func NewClock(t time.Time, opts ...ClockOpt) clock {
|
||||
gt := clock{genesis: t}
|
||||
for _, o := range opts {
|
||||
o(>)
|
||||
}
|
||||
if gt.now == nil {
|
||||
gt.now = time.Now
|
||||
}
|
||||
return gt
|
||||
}
|
||||
|
||||
// Now is a function that can return the current time. This will be time.Now by default, but can be overridden for tests.
|
||||
type Now func() time.Time
|
||||
84
beacon-chain/geninit/service.go
Normal file
84
beacon-chain/geninit/service.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"go.opencensus.io/trace"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/runtime"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
ctx context.Context
|
||||
powWaiter ClockWaiter
|
||||
genesisSetter ClockSetter
|
||||
powFetcher powchain.ChainStartFetcher
|
||||
d db.HeadAccessDatabase
|
||||
}
|
||||
var _ runtime.Service = &Service{}
|
||||
|
||||
type ServiceOption func(*Service)
|
||||
|
||||
func New(ctx context.Context, pw ClockWaiter, gs ClockSetter, f powchain.ChainStartFetcher, d db.HeadAccessDatabase, opts ...ServiceOption) (*Service, error) {
|
||||
s := &Service{
|
||||
ctx: ctx,
|
||||
powWaiter: pw,
|
||||
genesisSetter: gs,
|
||||
powFetcher: f,
|
||||
d: d,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(s)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Service) Start() {
|
||||
go s.run()
|
||||
}
|
||||
|
||||
func (s *Service) run() {
|
||||
c, err := s.powWaiter.WaitForClock(s.ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("timeout waiting for genesis timestamp")
|
||||
}
|
||||
if err = s.saveGenesis(c); err != nil {
|
||||
log.Fatalf("Could not initialize beacon chain, %s", err.Error())
|
||||
}
|
||||
s.genesisSetter.SetGenesisClock(c)
|
||||
}
|
||||
|
||||
func (s *Service) saveGenesis(c Clock) error {
|
||||
ctx, span := trace.StartSpan(s.ctx, "beacon-chain.geninit.Service.saveGenesis")
|
||||
defer span.End()
|
||||
eth1 := s.powFetcher.ChainStartEth1Data()
|
||||
pst := s.powFetcher.PreGenesisState()
|
||||
st, err := transition.OptimizedGenesisBeaconState(uint64(c.GenesisTime().Unix()), pst, eth1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.d.SaveGenesisData(ctx, st); err != nil {
|
||||
return errors.Wrap(err, "db error, could not save genesis data")
|
||||
}
|
||||
log.Info("Initialized beacon chain genesis state")
|
||||
// Clear out all pre-genesis data now that the state is initialized.
|
||||
s.powFetcher.ClearPreGenesisData()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Status() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type GenesisReady struct {
|
||||
time time.Time
|
||||
}
|
||||
50
beacon-chain/geninit/waiter.go
Normal file
50
beacon-chain/geninit/waiter.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ClockWaiter interface {
|
||||
WaitForClock(context.Context) (Clock, error)
|
||||
}
|
||||
|
||||
type ClockSetter interface {
|
||||
SetGenesisTime(time.Time)
|
||||
SetGenesisClock(Clock)
|
||||
}
|
||||
|
||||
type ClockSync struct {
|
||||
ready chan struct{}
|
||||
c Clock
|
||||
}
|
||||
|
||||
func (w *ClockSync) SetGenesisTime(g time.Time) {
|
||||
w.c = NewClock(g)
|
||||
close(w.ready)
|
||||
w.ready = nil
|
||||
}
|
||||
|
||||
func (w *ClockSync) SetGenesisClock(c Clock) {
|
||||
w.c = c
|
||||
close(w.ready)
|
||||
w.ready = nil
|
||||
}
|
||||
|
||||
func (w *ClockSync) WaitForClock(ctx context.Context) (Clock, error) {
|
||||
if w.ready == nil {
|
||||
return w.c, nil
|
||||
}
|
||||
select {
|
||||
case <-w.ready:
|
||||
return w.c, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func NewClockSync() *ClockSync {
|
||||
return &ClockSync{
|
||||
ready: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ go_library(
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/gateway:go_default_library",
|
||||
"//beacon-chain/geninit:go_default_library",
|
||||
"//beacon-chain/monitor:go_default_library",
|
||||
"//beacon-chain/node/registration:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/gateway"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/geninit"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/monitor"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/node/registration"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
@@ -211,8 +212,17 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
powSync := geninit.NewClockSync()
|
||||
genSync := geninit.NewClockSync()
|
||||
|
||||
log.Debugln("Registering POW Chain Service")
|
||||
if err := beacon.registerPOWChainService(); err != nil {
|
||||
powService, err := beacon.registerPOWChainService(powSync)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugln("Registering Genesis Init Service")
|
||||
if err := beacon.registerGenesisInitService(powSync, genSync, powService, beacon.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -629,17 +639,17 @@ func (b *BeaconNode) registerBlockchainService() error {
|
||||
return b.services.RegisterService(blockchainService)
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerPOWChainService() error {
|
||||
func (b *BeaconNode) registerPOWChainService(gcs geninit.ClockSetter) (*powchain.Service, error) {
|
||||
if b.cliCtx.Bool(testSkipPowFlag) {
|
||||
return b.services.RegisterService(&powchain.Service{})
|
||||
return nil, b.services.RegisterService(&powchain.Service{})
|
||||
}
|
||||
bs, err := powchain.NewPowchainCollector(b.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
depositContractAddr, err := powchain.DepositContractAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skipcq: CRT-D0001
|
||||
@@ -652,13 +662,23 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
powchain.WithStateGen(b.stateGen),
|
||||
powchain.WithBeaconNodeStatsUpdater(bs),
|
||||
powchain.WithFinalizedStateAtStartup(b.finalizedStateAtStartUp),
|
||||
powchain.WithGenesisClockSetter(gcs),
|
||||
)
|
||||
web3Service, err := powchain.NewService(b.ctx, opts...)
|
||||
srv, err := powchain.NewService(b.ctx, opts...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not register proof-of-work chain web3Service")
|
||||
return nil, errors.Wrap(err, "could not register proof-of-work chain web3Service")
|
||||
}
|
||||
|
||||
return b.services.RegisterService(web3Service)
|
||||
err = b.services.RegisterService(srv)
|
||||
return srv, err
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerGenesisInitService(w geninit.ClockWaiter, s geninit.ClockSetter, f powchain.ChainStartFetcher, d db.HeadAccessDatabase) error {
|
||||
g, err := geninit.New(b.ctx, w, s, f, d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.services.RegisterService(g)
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerSyncService() error {
|
||||
@@ -821,7 +841,6 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
FinalizationFetcher: chainService,
|
||||
BlockReceiver: chainService,
|
||||
AttestationReceiver: chainService,
|
||||
GenesisTimeFetcher: chainService,
|
||||
GenesisFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
AttestationsPool: b.attestationPool,
|
||||
@@ -844,6 +863,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
MaxMsgSize: maxMsgSize,
|
||||
ProposerIdsCache: b.proposerIdsCache,
|
||||
BlockBuilder: b.fetchBuilderService(),
|
||||
ClockProvider: chainService,
|
||||
})
|
||||
|
||||
return b.services.RegisterService(rpcService)
|
||||
|
||||
@@ -32,6 +32,7 @@ go_library(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/geninit:go_default_library",
|
||||
"//beacon-chain/powchain/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
|
||||
@@ -20,6 +20,8 @@ const searchThreshold = 5
|
||||
// amount of times we repeat a failed search till is satisfies the conditional.
|
||||
const repeatedSearches = 2 * searchThreshold
|
||||
|
||||
var errBlockTimeTooLate = errors.New("provided time is later than the current eth1 head")
|
||||
|
||||
// BlockExists returns true if the block exists, its height and any possible error encountered.
|
||||
func (s *Service) BlockExists(ctx context.Context, hash common.Hash) (bool, *big.Int, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.BlockExists")
|
||||
@@ -105,7 +107,7 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea
|
||||
s.latestEth1DataLock.RUnlock()
|
||||
|
||||
if time > latestBlkTime {
|
||||
return nil, errors.Errorf("provided time is later than the current eth1 head. %d > %d", time, latestBlkTime)
|
||||
return nil, errors.Wrap(errBlockTimeTooLate, fmt.Sprintf("(%d > %d)", time, latestBlkTime))
|
||||
}
|
||||
// Initialize a pointer to eth1 chain's history to start our search from.
|
||||
cursorNum := big.NewInt(0).SetUint64(latestBlkHeight)
|
||||
|
||||
@@ -159,6 +159,7 @@ func FuzzExecutionPayload(f *testing.F) {
|
||||
}
|
||||
|
||||
func FuzzExecutionBlock(f *testing.F) {
|
||||
f.Skip("Is skipped until false positive rate can be resolved.")
|
||||
logsBloom := [256]byte{'j', 'u', 'n', 'k'}
|
||||
addr := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
|
||||
innerData := &types.DynamicFeeTx{
|
||||
@@ -209,7 +210,16 @@ func FuzzExecutionBlock(f *testing.F) {
|
||||
if gethErr != nil || prysmErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Exit early if fuzzer is inserting bogus hashes in.
|
||||
if isBogusTransactionHash(prysmResp, gethResp) {
|
||||
return
|
||||
}
|
||||
// Exit early if fuzzer provides bogus fields.
|
||||
valid, err := jsonFieldsAreValid(prysmResp, gethResp)
|
||||
assert.NoError(t, err)
|
||||
if !valid {
|
||||
return
|
||||
}
|
||||
assert.NoError(t, validateBlockConsistency(prysmResp, gethResp))
|
||||
|
||||
gethBlob, gethErr := json.Marshal(gethResp)
|
||||
@@ -227,6 +237,27 @@ func FuzzExecutionBlock(f *testing.F) {
|
||||
})
|
||||
}
|
||||
|
||||
func isBogusTransactionHash(blk *pb.ExecutionBlock, jsonMap map[string]interface{}) bool {
|
||||
if blk.Transactions == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, tx := range blk.Transactions {
|
||||
jsonTx, ok := jsonMap["transactions"].([]interface{})[i].(map[string]interface{})
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
// Fuzzer removed hash field.
|
||||
if _, ok := jsonTx["hash"]; !ok {
|
||||
return true
|
||||
}
|
||||
if tx.Hash().String() != jsonTx["hash"].(string) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func compareHeaders(t *testing.T, jsonBlob []byte) {
|
||||
gethResp := &types.Header{}
|
||||
prysmResp := &pb.ExecutionBlock{}
|
||||
@@ -284,3 +315,25 @@ func validateBlockConsistency(execBlock *pb.ExecutionBlock, jsonMap map[string]i
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func jsonFieldsAreValid(execBlock *pb.ExecutionBlock, jsonMap map[string]interface{}) (bool, error) {
|
||||
bType := reflect.TypeOf(execBlock).Elem()
|
||||
|
||||
fieldnum := bType.NumField()
|
||||
|
||||
for i := 0; i < fieldnum; i++ {
|
||||
field := bType.Field(i)
|
||||
fName := field.Tag.Get("json")
|
||||
if field.Name == "Header" {
|
||||
continue
|
||||
}
|
||||
if fName == "" {
|
||||
return false, errors.Errorf("Field %s had no json tag", field.Name)
|
||||
}
|
||||
_, ok := jsonMap[fName]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
||||
log.WithFields(logrus.Fields{
|
||||
"ChainStartTime": chainStartTime,
|
||||
}).Info("Minimum number of validators reached for beacon-chain to start")
|
||||
s.genSync.SetGenesisTime(chainStartTime)
|
||||
s.cfg.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.ChainStarted,
|
||||
Data: &statefeed.ChainStartedData{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/geninit"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/network"
|
||||
@@ -123,3 +124,10 @@ func WithFinalizedStateAtStartup(st state.BeaconState) Option {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithGenesisClockSetter(cs geninit.ClockSetter) Option {
|
||||
return func(s *Service) error {
|
||||
s.genSync = cs
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/geninit"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
@@ -161,6 +162,7 @@ type Service struct {
|
||||
lastReceivedMerkleIndex int64 // Keeps track of the last received index to prevent log spam.
|
||||
runError error
|
||||
preGenesisState state.BeaconState
|
||||
genSync geninit.ClockSetter
|
||||
}
|
||||
|
||||
// NewService sets up a new instance with an ethclient when given a web3 endpoint as a string in the config.
|
||||
@@ -580,13 +582,20 @@ func (s *Service) initPOWService() {
|
||||
|
||||
if err := s.processPastLogs(ctx); err != nil {
|
||||
s.retryExecutionClientConnection(ctx, err)
|
||||
errorLogger(err, "Unable to process past deposit contract logs")
|
||||
errorLogger(
|
||||
err,
|
||||
"Unable to process past deposit contract logs, perhaps your execution client is not fully synced",
|
||||
)
|
||||
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")
|
||||
if errors.Is(err, errBlockTimeTooLate) {
|
||||
log.WithError(err).Warn("Unable to cache headers for execution client votes")
|
||||
} else {
|
||||
errorLogger(err, "Unable to cache headers for execution client votes")
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Handle edge case with embedded genesis state by fetching genesis header to determine
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"baseFeePerGas\":\"0x7fffffffffffffff\",\"difficulty\":\"0x7fffffffffffffff\",\"extraData\":\"0x\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"hash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"logsBloom\":\"0x6a756e6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x7fffffffffffffff\",\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"sha3Uncles\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"timestamp\":\"0x64\",\"totalDifficulty\":\"999999999999999999999999999999999999999\",\"transactions\":[{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"},{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xfffffffffffaffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"}],\"transactionsRoot\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"baseFeePerGas\":\"0x7fffffffffffffff\",\"difficulty\":\"0x7fffffffffffffff\",\"extraData\":\"0x\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"hash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"logsBloom\":\"0x6a756e6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x7fffffffffffffff\",\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"sha3Uncles\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"timestamp\":\"0x64\",\"totalDifficulty\":\"999999999999999999999999999999999999999\",\"tran0sactions\":[{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb9<7efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"},{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"}],\"transactionsRoot\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"baseFeePerGas\":\"0x7fffffffffffffff\",\"difficulty\":\"0x7fffffffffffffff\",\"extraData\":\"0x\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"hash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"logsBloom\":\"0x6a756e6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x7fffffffffffffff\",\"parentHash\":\"0xff01ff01ff01ff01ffffff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"sha3Uncles\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"timestamp\":\"0x64\",\"totalDifficulty\":\"999999999999999999999999999999999999999\",\"transactions\":[{\"type\":\"0x2\",\"nonce\":\"0xffffffffff01ffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xffffffffffffffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hasM\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"},{\"type\":\"0x2\",\"nonce\":\"0xffffffffffffffff\",\"gasPrice\":null,\"maxPriorityFeePerGas\":\"0x7fffffffffffffff\",\"maxFeePerGas\":\"0x7fffffffffffffff\",\"gas\":\"0xfffffffffffaffff\",\"value\":\"0x7fffffffffffffff\",\"input\":\"0x72616e646f6d\",\"v\":\"0x0\",\"r\":\"0x7fffffffffffffff\",\"s\":\"0x7fffffffffffffff\",\"to\":\"0x095e7baea6a6c7c4c2dfeb977efac326af552d87\",\"chainId\":\"0x7fffffffffffffff\",\"accessList\":[],\"hash\":\"0x26db3ef2c0e5945b24088d6a4165d0bb2959abd848b57891aa041b72518548ab\"}],\"transactionsRoot\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}")
|
||||
@@ -46,6 +46,7 @@ go_library(
|
||||
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
|
||||
"@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library",
|
||||
"@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//plugin/ocgrpc:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
@@ -61,6 +62,7 @@ go_test(
|
||||
srcs = ["service_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/powchain/testing:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
||||
|
||||
@@ -80,6 +80,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
|
||||
@@ -53,7 +53,11 @@ func (e *blockIdParseError) Error() string {
|
||||
// GetWeakSubjectivity computes the starting epoch of the current weak subjectivity period, and then also
|
||||
// determines the best block root and state root to use for a Checkpoint Sync starting from that point.
|
||||
func (bs *Server) GetWeakSubjectivity(ctx context.Context, _ *empty.Empty) (*ethpbv1.WeakSubjectivityResponse, error) {
|
||||
if err := rpchelpers.ValidateSync(ctx, bs.SyncChecker, bs.HeadFetcher, bs.GenesisTimeFetcher, bs.OptimisticModeFetcher); err != nil {
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, bs.SyncChecker, bs.HeadFetcher, c, bs.OptimisticModeFetcher); err != nil {
|
||||
// This is already a grpc error, so we can't wrap it any further
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,7 +74,11 @@ func (bs *Server) GetWeakSubjectivity(ctx context.Context, _ *empty.Empty) (*eth
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not get weak subjectivity slot: %v", err)
|
||||
}
|
||||
cbr, err := bs.CanonicalHistory.BlockRootForSlot(ctx, wsSlot)
|
||||
h, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
cbr, err := h.BlockRootForSlot(ctx, wsSlot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, fmt.Sprintf("could not find highest block below slot %d", wsSlot))
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ func TestGetSpec(t *testing.T) {
|
||||
config.CapellaForkVersion = []byte("CapellaForkVersion")
|
||||
config.CapellaForkEpoch = 103
|
||||
config.BLSWithdrawalPrefixByte = byte('b')
|
||||
config.ETH1AddressWithdrawalPrefixByte = byte('c')
|
||||
config.GenesisDelay = 24
|
||||
config.SecondsPerSlot = 25
|
||||
config.MinAttestationInclusionDelay = 26
|
||||
@@ -135,7 +136,7 @@ func TestGetSpec(t *testing.T) {
|
||||
resp, err := server.GetSpec(context.Background(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 101, len(resp.Data))
|
||||
assert.Equal(t, 102, len(resp.Data))
|
||||
for k, v := range resp.Data {
|
||||
switch k {
|
||||
case "CONFIG_NAME":
|
||||
@@ -212,6 +213,8 @@ func TestGetSpec(t *testing.T) {
|
||||
assert.Equal(t, "1000", v)
|
||||
case "BLS_WITHDRAWAL_PREFIX":
|
||||
assert.Equal(t, "0x62", v)
|
||||
case "ETH1_ADDRESS_WITHDRAWAL_PREFIX":
|
||||
assert.Equal(t, "0x63", v)
|
||||
case "GENESIS_DELAY":
|
||||
assert.Equal(t, "24", v)
|
||||
case "SECONDS_PER_SLOT":
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
type Server struct {
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
BlockReceiver blockchain.BlockReceiver
|
||||
BlockNotifier blockfeed.Notifier
|
||||
OperationNotifier operation.Notifier
|
||||
@@ -37,8 +36,9 @@ type Server struct {
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
||||
SyncChecker sync.Checker
|
||||
CanonicalHistory *stategen.CanonicalHistory
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
SyncChecker sync.Checker
|
||||
CanonicalHistoryWaiter stategen.CanonicalHistoryWaiter
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
ExecutionPayloadReconstructor powchain.ExecutionPayloadReconstructor
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
@@ -30,10 +30,11 @@ func (bs *Server) GetGenesis(ctx context.Context, _ *emptypb.Empty) (*ethpb.Gene
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.GetGenesis")
|
||||
defer span.End()
|
||||
|
||||
genesisTime := bs.GenesisTimeFetcher.GenesisTime()
|
||||
if genesisTime.IsZero() {
|
||||
return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known")
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
genesisTime := c.GenesisTime()
|
||||
validatorRoot := bs.ChainInfoFetcher.GenesisValidatorsRoot()
|
||||
if bytes.Equal(validatorRoot[:], params.BeaconConfig().ZeroHash[:]) {
|
||||
return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known")
|
||||
|
||||
@@ -2,6 +2,7 @@ package beacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -29,11 +30,11 @@ func TestGetGenesis(t *testing.T) {
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{
|
||||
Genesis: genesis,
|
||||
Clock: blockchain.NewClock(genesis),
|
||||
ValidatorsRoot: validatorsRoot,
|
||||
}
|
||||
s := Server{
|
||||
GenesisTimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
resp, err := s.GetGenesis(ctx, &emptypb.Empty{})
|
||||
@@ -46,11 +47,11 @@ func TestGetGenesis(t *testing.T) {
|
||||
|
||||
t.Run("No genesis time", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{
|
||||
Genesis: time.Time{},
|
||||
Clock: blockchain.NewClock(time.Time{}),
|
||||
ValidatorsRoot: validatorsRoot,
|
||||
}
|
||||
s := Server{
|
||||
GenesisTimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
_, err := s.GetGenesis(ctx, &emptypb.Empty{})
|
||||
@@ -59,11 +60,11 @@ func TestGetGenesis(t *testing.T) {
|
||||
|
||||
t.Run("No genesis validators root", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{
|
||||
Genesis: genesis,
|
||||
Clock: blockchain.NewClock(genesis),
|
||||
ValidatorsRoot: [32]byte{},
|
||||
}
|
||||
s := Server{
|
||||
GenesisTimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
ChainInfoFetcher: chainService,
|
||||
}
|
||||
_, err := s.GetGenesis(ctx, &emptypb.Empty{})
|
||||
|
||||
@@ -27,7 +27,11 @@ func (bs *Server) ListSyncCommittees(ctx context.Context, req *ethpbv2.StateSync
|
||||
ctx, span := trace.StartSpan(ctx, "beacon.ListSyncCommittees")
|
||||
defer span.End()
|
||||
|
||||
currentSlot := bs.GenesisTimeFetcher.CurrentSlot()
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentSlot := c.CurrentSlot()
|
||||
currentEpoch := slots.ToEpoch(currentSlot)
|
||||
currentPeriodStartEpoch, err := slots.SyncCommitteePeriodStartEpoch(currentEpoch)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@ package beacon
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -161,11 +162,9 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
db := dbTest.SetupDB(t)
|
||||
|
||||
chainService := &mock.ChainService{}
|
||||
chainService := &mock.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: chainService,
|
||||
StateFetcher: &testutil.MockFetcher{
|
||||
BeaconState: st,
|
||||
},
|
||||
@@ -204,11 +203,9 @@ func TestListSyncCommittees(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
chainService := &mock.ChainService{Optimistic: true}
|
||||
chainService := &mock.ChainService{Optimistic: true, Clock: blockchain.NewClock(time.Now())}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: chainService,
|
||||
StateFetcher: &testutil.MockFetcher{
|
||||
BeaconState: st,
|
||||
},
|
||||
@@ -262,11 +259,9 @@ func TestListSyncCommitteesFuture(t *testing.T) {
|
||||
}))
|
||||
db := dbTest.SetupDB(t)
|
||||
|
||||
chainService := &mock.ChainService{}
|
||||
chainService := &mock.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
s := &Server{
|
||||
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: chainService,
|
||||
StateFetcher: &futureSyncMockFetcher{
|
||||
BeaconState: st,
|
||||
},
|
||||
|
||||
@@ -21,20 +21,14 @@ func ValidateSync(
|
||||
ctx context.Context,
|
||||
syncChecker sync.Checker,
|
||||
headFetcher blockchain.HeadFetcher,
|
||||
timeFetcher blockchain.TimeFetcher,
|
||||
clock blockchain.Clock,
|
||||
optimisticModeFetcher blockchain.OptimisticModeFetcher,
|
||||
) error {
|
||||
if !syncChecker.Syncing() {
|
||||
return nil
|
||||
}
|
||||
headSlot := headFetcher.HeadSlot()
|
||||
isOptimistic := false
|
||||
|
||||
headState, err := headFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
isOptimistic, err = IsOptimistic(ctx, headState, optimisticModeFetcher)
|
||||
isOptimistic, err := optimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not check optimistic status: %v", err)
|
||||
}
|
||||
@@ -42,7 +36,7 @@ func ValidateSync(
|
||||
syncDetailsContainer := &syncDetailsContainer{
|
||||
SyncDetails: &SyncDetailsJson{
|
||||
HeadSlot: strconv.FormatUint(uint64(headSlot), 10),
|
||||
SyncDistance: strconv.FormatUint(uint64(timeFetcher.CurrentSlot()-headSlot), 10),
|
||||
SyncDistance: strconv.FormatUint(uint64(clock.CurrentSlot()-headSlot), 10),
|
||||
IsSyncing: true,
|
||||
IsOptimistic: isOptimistic,
|
||||
},
|
||||
|
||||
@@ -15,7 +15,6 @@ go_library(
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/p2p/peers:go_default_library",
|
||||
"//beacon-chain/p2p/peers/peerdata:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/migration:go_default_library",
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers/peerdata"
|
||||
rpchelpers "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1"
|
||||
"github.com/prysmaticlabs/prysm/proto/migration"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -266,22 +265,24 @@ func (ns *Server) GetSyncStatus(ctx context.Context, _ *emptypb.Empty) (*ethpb.S
|
||||
ctx, span := trace.StartSpan(ctx, "node.GetSyncStatus")
|
||||
defer span.End()
|
||||
|
||||
headSlot := ns.HeadFetcher.HeadSlot()
|
||||
|
||||
headState, err := ns.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
|
||||
isOptimistic, err := rpchelpers.IsOptimistic(ctx, headState, ns.OptimisticModeFetcher)
|
||||
isOptimistic, err := ns.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check optimistic status: %v", err)
|
||||
}
|
||||
|
||||
c, err := ns.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
headSlot := ns.HeadFetcher.HeadSlot()
|
||||
sd, err := c.CurrentSlot().SafeSubSlot(headSlot)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "error computing sync_distance, head > current slot, %s", err)
|
||||
}
|
||||
return ðpb.SyncingResponse{
|
||||
Data: ðpb.SyncInfo{
|
||||
HeadSlot: headSlot,
|
||||
SyncDistance: ns.GenesisTimeFetcher.CurrentSlot() - headSlot,
|
||||
SyncDistance: sd,
|
||||
IsSyncing: ns.SyncChecker.Syncing(),
|
||||
IsOptimistic: isOptimistic,
|
||||
},
|
||||
|
||||
@@ -173,7 +173,7 @@ func TestSyncStatus(t *testing.T) {
|
||||
|
||||
s := &Server{
|
||||
HeadFetcher: chainService,
|
||||
GenesisTimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
SyncChecker: syncChecker,
|
||||
}
|
||||
|
||||
@@ -22,6 +22,6 @@ type Server struct {
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
MetadataProvider p2p.MetadataProvider
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ go_test(
|
||||
srcs = ["validator_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
type Server struct {
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
TimeFetcher blockchain.TimeFetcher
|
||||
SyncChecker sync.Checker
|
||||
AttestationsPool attestations.Pool
|
||||
PeerManager p2p.PeerManager
|
||||
@@ -24,4 +23,5 @@ type Server struct {
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
V1Alpha1Server *v1alpha1validator.Server
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
@@ -42,27 +42,30 @@ func (vs *Server) GetAttesterDuties(ctx context.Context, req *ethpbv1.AttesterDu
|
||||
ctx, span := trace.StartSpan(ctx, "validator.GetAttesterDuties")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs := vs.TimeFetcher.CurrentSlot()
|
||||
cs := c.CurrentSlot()
|
||||
currentEpoch := slots.ToEpoch(cs)
|
||||
if req.Epoch > currentEpoch+1 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Request epoch %d can not be greater than next epoch %d", req.Epoch, currentEpoch+1)
|
||||
}
|
||||
|
||||
isOptimistic, err := vs.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check optimistic status: %v", err)
|
||||
}
|
||||
|
||||
s, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
|
||||
isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.OptimisticModeFetcher)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
s, err = advanceState(ctx, s, req.Epoch, currentEpoch)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not advance state to requested epoch start slot: %v", err)
|
||||
@@ -126,27 +129,30 @@ func (vs *Server) GetProposerDuties(ctx context.Context, req *ethpbv1.ProposerDu
|
||||
ctx, span := trace.StartSpan(ctx, "validator.GetProposerDuties")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs := vs.TimeFetcher.CurrentSlot()
|
||||
cs := c.CurrentSlot()
|
||||
currentEpoch := slots.ToEpoch(cs)
|
||||
if req.Epoch > currentEpoch+1 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Request epoch %d can not be greater than next epoch %d", req.Epoch, currentEpoch+1)
|
||||
}
|
||||
|
||||
isOptimistic, err := vs.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check optimistic status: %v", err)
|
||||
}
|
||||
|
||||
s, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
|
||||
isOptimistic, err := rpchelpers.IsOptimistic(ctx, s, vs.OptimisticModeFetcher)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
|
||||
}
|
||||
|
||||
s, err = advanceState(ctx, s, req.Epoch, currentEpoch)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not advance state to requested epoch start slot: %v", err)
|
||||
@@ -204,12 +210,16 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
|
||||
ctx, span := trace.StartSpan(ctx, "validator.GetSyncCommitteeDuties")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currentEpoch := slots.ToEpoch(vs.TimeFetcher.CurrentSlot())
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
lastValidEpoch := syncCommitteeDutiesLastValidEpoch(currentEpoch)
|
||||
if req.Epoch > lastValidEpoch {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Epoch is too far in the future. Maximum valid epoch is %v.", lastValidEpoch)
|
||||
@@ -274,7 +284,11 @@ func (vs *Server) ProduceBlock(ctx context.Context, req *ethpbv1.ProduceBlockReq
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProduceBlock")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -291,7 +305,11 @@ func (vs *Server) ProduceBlockV2(ctx context.Context, req *ethpbv1.ProduceBlockR
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProduceBlockV2")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -355,7 +373,11 @@ func (vs *Server) ProduceBlockV2SSZ(ctx context.Context, req *ethpbv1.ProduceBlo
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProduceBlockV2SSZ")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -426,7 +448,11 @@ func (vs *Server) ProduceBlindedBlock(ctx context.Context, req *ethpbv1.ProduceB
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProduceBlindedBlock")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -493,7 +519,11 @@ func (vs *Server) ProduceBlindedBlockSSZ(ctx context.Context, req *ethpbv1.Produ
|
||||
ctx, span := trace.StartSpan(ctx, "validator.ProduceBlindedBlockSSZ")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -635,6 +665,10 @@ func (vs *Server) SubmitAggregateAndProofs(ctx context.Context, req *ethpbv1.Sub
|
||||
ctx, span := trace.StartSpan(ctx, "validator.SubmitAggregateAndProofs")
|
||||
defer span.End()
|
||||
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
for _, agg := range req.Data {
|
||||
if agg == nil || agg.Message == nil || agg.Message.Aggregate == nil || agg.Message.Aggregate.Data == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Signed aggregate request can't be nil")
|
||||
@@ -650,7 +684,7 @@ func (vs *Server) SubmitAggregateAndProofs(ctx context.Context, req *ethpbv1.Sub
|
||||
|
||||
// As a preventive measure, a beacon node shouldn't broadcast an attestation whose slot is out of range.
|
||||
if err := helpers.ValidateAttestationTime(agg.Message.Aggregate.Data.Slot,
|
||||
vs.TimeFetcher.GenesisTime(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
c.GenesisTime(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Attestation slot is no longer valid from current time")
|
||||
}
|
||||
}
|
||||
@@ -685,7 +719,11 @@ func (vs *Server) SubmitBeaconCommitteeSubscription(ctx context.Context, req *et
|
||||
ctx, span := trace.StartSpan(ctx, "validator.SubmitBeaconCommitteeSubscription")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
@@ -762,7 +800,11 @@ func (vs *Server) SubmitSyncCommitteeSubscription(ctx context.Context, req *ethp
|
||||
ctx, span := trace.StartSpan(ctx, "validator.SubmitSyncCommitteeSubscription")
|
||||
defer span.End()
|
||||
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, vs.TimeFetcher, vs.OptimisticModeFetcher); err != nil {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := rpchelpers.ValidateSync(ctx, vs.SyncChecker, vs.HeadFetcher, c, vs.OptimisticModeFetcher); err != nil {
|
||||
// We simply return the error because it's already a gRPC error.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package validator
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -75,13 +76,12 @@ func TestGetAttesterDuties(t *testing.T) {
|
||||
pubKeys[i] = deposits[i].Data.PublicKey
|
||||
}
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs, Root: genesisRoot[:],
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
OptimisticModeFetcher: chain,
|
||||
}
|
||||
@@ -155,12 +155,13 @@ func TestGetAttesterDuties(t *testing.T) {
|
||||
indices[i] = uint64(i)
|
||||
}
|
||||
chainSlot := params.BeaconConfig().SlotsPerEpoch.Mul(2)
|
||||
clock := mockChain.NewMockClock(time.Now(), chainSlot)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs, Root: genesisRoot[:], Clock: clock,
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
OptimisticModeFetcher: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
@@ -224,13 +225,12 @@ func TestGetAttesterDuties(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
|
||||
State: bs, Root: genesisRoot[:], Optimistic: true,
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
OptimisticModeFetcher: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
@@ -251,7 +251,7 @@ func TestGetAttesterDuties_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.GetAttesterDuties(context.Background(), ðpbv1.AttesterDutiesRequest{})
|
||||
@@ -282,13 +282,12 @@ func TestGetProposerDuties(t *testing.T) {
|
||||
pubKeys[i] = deposits[i].Data.PublicKey
|
||||
}
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs, Root: genesisRoot[:],
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
OptimisticModeFetcher: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
@@ -334,12 +333,15 @@ func TestGetProposerDuties(t *testing.T) {
|
||||
indices[i] = uint64(i)
|
||||
}
|
||||
chainSlot := params.BeaconConfig().SlotsPerEpoch.Mul(2)
|
||||
clock := mockChain.NewMockClock(time.Now(), chainSlot)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
Clock: clock,
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
OptimisticModeFetcher: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
@@ -383,13 +385,12 @@ func TestGetProposerDuties(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
|
||||
State: bs, Root: genesisRoot[:], Optimistic: true,
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
OptimisticModeFetcher: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
@@ -409,7 +410,7 @@ func TestGetProposerDuties_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.GetProposerDuties(context.Background(), ðpbv1.ProposerDutiesRequest{})
|
||||
@@ -437,11 +438,11 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
require.NoError(t, st.SetNextSyncCommittee(nextCommittee))
|
||||
db := dbutil.SetupDB(t)
|
||||
|
||||
mockChainService := &mockChain.ChainService{Genesis: genesisTime}
|
||||
mockChainService := &mockChain.ChainService{Clock: blockchain.NewClock(genesisTime)}
|
||||
vs := &Server{
|
||||
StateFetcher: &testutil.MockFetcher{BeaconState: st},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
ClockProvider: mockChainService,
|
||||
HeadFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
}
|
||||
@@ -576,11 +577,14 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
return newSyncPeriodSt
|
||||
}
|
||||
}
|
||||
mockChainService := &mockChain.ChainService{Genesis: genesisTime, Slot: &newSyncPeriodStartSlot}
|
||||
clock := mockChain.NewMockClock(time.Now(), newSyncPeriodStartSlot)
|
||||
mockChainService := &mockChain.ChainService{
|
||||
Clock: clock,
|
||||
}
|
||||
vs := &Server{
|
||||
StateFetcher: &testutil.MockFetcher{BeaconState: stateFetchFn(newSyncPeriodStartSlot)},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
ClockProvider: mockChainService,
|
||||
HeadFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
}
|
||||
@@ -610,11 +614,14 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
|
||||
util.SaveBlock(t, ctx, db, blk)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, root))
|
||||
|
||||
mockChainService := &mockChain.ChainService{Genesis: genesisTime, Optimistic: true}
|
||||
mockChainService := &mockChain.ChainService{
|
||||
Clock: blockchain.NewClock(genesisTime),
|
||||
Optimistic: true,
|
||||
}
|
||||
vs := &Server{
|
||||
StateFetcher: &testutil.MockFetcher{BeaconState: st},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
ClockProvider: mockChainService,
|
||||
HeadFetcher: mockChainService,
|
||||
OptimisticModeFetcher: mockChainService,
|
||||
}
|
||||
@@ -635,7 +642,7 @@ func TestGetSyncCommitteeDuties_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.GetSyncCommitteeDuties(context.Background(), ðpbv2.SyncCommitteeDutiesRequest{})
|
||||
@@ -745,7 +752,7 @@ func TestProduceBlock_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.ProduceBlock(context.Background(), ðpbv1.ProduceBlockRequest{})
|
||||
@@ -1011,7 +1018,7 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{},
|
||||
ClockProvider: &mockChain.ChainService{},
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
OptimisticModeFetcher: &mockChain.ChainService{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -1500,7 +1507,7 @@ func TestProduceBlockV2SSZ(t *testing.T) {
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{},
|
||||
ClockProvider: &mockChain.ChainService{},
|
||||
HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]},
|
||||
OptimisticModeFetcher: &mockChain.ChainService{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -1691,7 +1698,7 @@ func TestProduceBlockV2_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.ProduceBlockV2(context.Background(), ðpbv1.ProduceBlockRequest{})
|
||||
@@ -1705,7 +1712,7 @@ func TestProduceBlockV2SSZ_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.ProduceBlockV2SSZ(context.Background(), ðpbv1.ProduceBlockRequest{})
|
||||
@@ -1971,7 +1978,7 @@ func TestProduceBlindedBlock(t *testing.T) {
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{},
|
||||
ClockProvider: &mockChain.ChainService{},
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
OptimisticModeFetcher: &mockChain.ChainService{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -2460,7 +2467,7 @@ func TestProduceBlindedBlockSSZ(t *testing.T) {
|
||||
TotalDifficulty: "0x1",
|
||||
},
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{},
|
||||
ClockProvider: &mockChain.ChainService{},
|
||||
HeadFetcher: &mockChain.ChainService{State: bs, Root: parentRoot[:]},
|
||||
OptimisticModeFetcher: &mockChain.ChainService{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -2651,7 +2658,7 @@ func TestProduceBlindedBlock_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.ProduceBlindedBlock(context.Background(), ðpbv1.ProduceBlockRequest{})
|
||||
@@ -2665,7 +2672,7 @@ func TestProduceBlindedBlockSSZ_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.ProduceBlindedBlockSSZ(context.Background(), ðpbv1.ProduceBlockRequest{})
|
||||
@@ -2704,6 +2711,7 @@ func TestProduceAttestationData(t *testing.T) {
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
v1Alpha1Server := &v1alpha1validator.Server{
|
||||
P2P: &p2pmock.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -2714,8 +2722,8 @@ func TestProduceAttestationData(t *testing.T) {
|
||||
FinalizationFetcher: &mockChain.ChainService{
|
||||
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
|
||||
},
|
||||
TimeFetcher: &mockChain.ChainService{
|
||||
Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
ClockProvider: &mockChain.ChainService{
|
||||
Clock: blockchain.NewClock(gent),
|
||||
},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
@@ -2925,11 +2933,11 @@ func TestSubmitBeaconCommitteeSubscription(t *testing.T) {
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs, Root:genesisRoot[:], Slot: &chainSlot,
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
V1Alpha1Server: &v1alpha1validator.Server{},
|
||||
}
|
||||
@@ -3040,7 +3048,7 @@ func TestSubmitBeaconCommitteeSubscription_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.SubmitBeaconCommitteeSubscription(context.Background(), ðpbv1.SubmitBeaconCommitteeSubscriptionsRequest{})
|
||||
@@ -3069,11 +3077,12 @@ func TestSubmitSyncCommitteeSubscription(t *testing.T) {
|
||||
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Slot: &chainSlot,
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
V1Alpha1Server: &v1alpha1validator.Server{},
|
||||
}
|
||||
@@ -3199,7 +3208,7 @@ func TestSubmitSyncCommitteeSubscription_SyncNotReady(t *testing.T) {
|
||||
vs := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: true},
|
||||
HeadFetcher: chainService,
|
||||
TimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
}
|
||||
_, err = vs.SubmitSyncCommitteeSubscription(context.Background(), ðpbv2.SubmitSyncCommitteeSubscriptionsRequest{})
|
||||
@@ -3236,11 +3245,12 @@ func TestSubmitAggregateAndProofs(t *testing.T) {
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
Genesis: time.Now(), Slot: &chainSlot,
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
Slot: &chainSlot,
|
||||
}
|
||||
broadcaster := &p2pmock.MockBroadcaster{}
|
||||
vs := Server{
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
Broadcaster: broadcaster,
|
||||
}
|
||||
|
||||
@@ -3458,11 +3468,11 @@ func TestSubmitAggregateAndProofs(t *testing.T) {
|
||||
t.Run("invalid attestation time", func(t *testing.T) {
|
||||
chainSlot := types.Slot(0)
|
||||
chain := &mockChain.ChainService{
|
||||
Genesis: time.Now().Add(time.Hour * 2), Slot: &chainSlot,
|
||||
Clock: blockchain.NewClock(time.Now().Add(time.Hour * 2)), Slot: &chainSlot,
|
||||
}
|
||||
broadcaster := &p2pmock.MockBroadcaster{}
|
||||
vs := Server{
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
Broadcaster: broadcaster,
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
shard_count = 4,
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
|
||||
@@ -32,6 +32,10 @@ func (bs *Server) ListValidatorAssignments(
|
||||
)
|
||||
}
|
||||
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
var res []*ethpb.ValidatorAssignments_CommitteeAssignment
|
||||
filtered := map[types.ValidatorIndex]bool{} // track filtered validators to prevent duplication in the response.
|
||||
filteredIndices := make([]types.ValidatorIndex, 0)
|
||||
@@ -45,7 +49,7 @@ func (bs *Server) ListValidatorAssignments(
|
||||
requestedEpoch = q.Epoch
|
||||
}
|
||||
|
||||
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
if requestedEpoch > currentEpoch {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
@@ -59,7 +63,11 @@ func (bs *Server) ListValidatorAssignments(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
requestedState, err := bs.ReplayerBuilder.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
requestedState, err := b.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("could not replay all blocks from the closest stored state (at slot %d) "+
|
||||
"to the requested epoch (%d) - %v", startSlot, requestedEpoch, err)
|
||||
|
||||
@@ -28,16 +28,18 @@ func TestServer_ListAssignments_CannotRequestFutureEpoch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, db)
|
||||
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
require.NoError(t, err)
|
||||
wanted := errNoEpochInfoError
|
||||
_, err := bs.ListValidatorAssignments(
|
||||
_, err = bs.ListValidatorAssignments(
|
||||
ctx,
|
||||
ðpb.ListValidatorAssignmentsRequest{
|
||||
QueryFilter: ðpb.ListValidatorAssignmentsRequest_Epoch{
|
||||
Epoch: slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
|
||||
Epoch: slots.ToEpoch(c.CurrentSlot()) + 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -59,7 +61,7 @@ func TestServer_ListAssignments_NoResults(t *testing.T) {
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st)),
|
||||
}
|
||||
@@ -121,7 +123,7 @@ func TestServer_ListAssignments_Pagination_InputOutOfRange(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(s)),
|
||||
}
|
||||
@@ -197,7 +199,7 @@ func TestServer_ListAssignments_Pagination_DefaultPageSize_NoArchive(t *testing.
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(s)),
|
||||
}
|
||||
@@ -264,7 +266,7 @@ func TestServer_ListAssignments_FilterPubkeysIndices_NoPagination(t *testing.T)
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(s)),
|
||||
}
|
||||
@@ -335,7 +337,7 @@ func TestServer_ListAssignments_CanFilterPubkeysIndices_WithPagination(t *testin
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
|
||||
|
||||
@@ -340,7 +340,12 @@ func (bs *Server) StreamIndexedAttestations(
|
||||
func (bs *Server) collectReceivedAttestations(ctx context.Context) {
|
||||
attsByRoot := make(map[[32]byte][]*ethpb.Attestation)
|
||||
twoThirdsASlot := 2 * slots.DivideSlotBy(3) /* 2/3 slot duration */
|
||||
ticker := slots.NewSlotTickerWithOffset(bs.GenesisTimeFetcher.GenesisTime(), twoThirdsASlot, params.BeaconConfig().SecondsPerSlot)
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("timeout while waiting for genesis timestamp in collectReceivedAttestations")
|
||||
return
|
||||
}
|
||||
ticker := slots.NewSlotTickerWithOffset(c.GenesisTime(), twoThirdsASlot, params.BeaconConfig().SecondsPerSlot)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C():
|
||||
|
||||
@@ -3,11 +3,6 @@ package beacon
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
@@ -36,6 +31,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServer_ListAttestations_NoResults(t *testing.T) {
|
||||
@@ -567,7 +565,7 @@ func TestServer_ListIndexedAttestations_GenesisEpoch(t *testing.T) {
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &chainMock.ChainService{State: state},
|
||||
ClockProvider: &chainMock.ChainService{State: state},
|
||||
HeadFetcher: &chainMock.ChainService{State: state},
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
@@ -666,9 +664,7 @@ func TestServer_ListIndexedAttestations_OldEpoch(t *testing.T) {
|
||||
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &chainMock.ChainService{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &chainMock.ChainService{},
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
err = db.SaveStateSummary(ctx, ðpb.StateSummary{
|
||||
@@ -831,9 +827,7 @@ func TestServer_StreamIndexedAttestations_ContextCanceled(t *testing.T) {
|
||||
server := &Server{
|
||||
Ctx: ctx,
|
||||
AttestationNotifier: chainService.OperationNotifier(),
|
||||
GenesisTimeFetcher: &chainMock.ChainService{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &chainMock.ChainService{},
|
||||
}
|
||||
|
||||
exitRoutine := make(chan bool)
|
||||
@@ -935,9 +929,7 @@ func TestServer_StreamIndexedAttestations_OK(t *testing.T) {
|
||||
HeadFetcher: &chainMock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &chainMock.ChainService{
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &chainMock.ChainService{},
|
||||
AttestationNotifier: chainService.OperationNotifier(),
|
||||
CollectedAttestationsBuffer: make(chan []*ethpb.Attestation, 1),
|
||||
StateGen: stategen.New(db),
|
||||
|
||||
@@ -23,7 +23,11 @@ func (bs *Server) ListBeaconCommittees(
|
||||
ctx context.Context,
|
||||
req *ethpb.ListCommitteesRequest,
|
||||
) (*ethpb.BeaconCommittees, error) {
|
||||
currentSlot := bs.GenesisTimeFetcher.CurrentSlot()
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentSlot := c.CurrentSlot()
|
||||
var requestedSlot types.Slot
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *ethpb.ListCommitteesRequest_Epoch:
|
||||
@@ -74,7 +78,11 @@ func (bs *Server) retrieveCommitteesForEpoch(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
requestedState, err := bs.ReplayerBuilder.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
requestedState, err := b.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, status.Errorf(codes.Internal, "error replaying blocks for state at slot %d: %v", startSlot, err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package beacon
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -35,12 +36,13 @@ func TestServer_ListBeaconCommittees_CurrentEpoch(t *testing.T) {
|
||||
headState := setupActiveValidators(t, numValidators)
|
||||
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
m := &mock.ChainService{
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
bs := &Server{
|
||||
HeadFetcher: m,
|
||||
GenesisTimeFetcher: m,
|
||||
ClockProvider: m,
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
b := util.NewBeaconBlock()
|
||||
@@ -106,13 +108,14 @@ func TestServer_ListBeaconCommittees_PreviousEpoch(t *testing.T) {
|
||||
require.NoError(t, db.SaveState(ctx, headState, gRoot))
|
||||
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
m := &mock.ChainService{
|
||||
State: headState,
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
bs := &Server{
|
||||
HeadFetcher: m,
|
||||
GenesisTimeFetcher: m,
|
||||
ClockProvider: m,
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, db)
|
||||
@@ -162,12 +165,13 @@ func TestRetrieveCommitteesForRoot(t *testing.T) {
|
||||
headState := setupActiveValidators(t, numValidators)
|
||||
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
m := &mock.ChainService{
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
bs := &Server{
|
||||
HeadFetcher: m,
|
||||
GenesisTimeFetcher: m,
|
||||
ClockProvider: m,
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
b := util.NewBeaconBlock()
|
||||
|
||||
@@ -33,7 +33,6 @@ type Server struct {
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
DepositFetcher depositcache.DepositFetcher
|
||||
BlockFetcher powchain.POWBlockFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
StateNotifier statefeed.Notifier
|
||||
BlockNotifier blockfeed.Notifier
|
||||
AttestationNotifier operation.Notifier
|
||||
@@ -44,8 +43,9 @@ type Server struct {
|
||||
ReceivedAttestationsBuffer chan *ethpb.Attestation
|
||||
CollectedAttestationsBuffer chan []*ethpb.Attestation
|
||||
StateGen stategen.StateManager
|
||||
SyncChecker sync.Checker
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
SyncChecker sync.Checker
|
||||
CanonicalHistoryWaiter stategen.CanonicalHistoryWaiter
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ func (bs *Server) ListValidatorBalances(
|
||||
req.PageSize, cmd.Get().MaxRPCPageSize)
|
||||
}
|
||||
|
||||
if bs.GenesisTimeFetcher == nil {
|
||||
return nil, status.Errorf(codes.Internal, "Nil genesis time fetcher")
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
requestedEpoch := currentEpoch
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *ethpb.ListValidatorBalancesRequest_Epoch:
|
||||
@@ -65,7 +66,11 @@ func (bs *Server) ListValidatorBalances(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
requestedState, err := bs.ReplayerBuilder.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
requestedState, err := b.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", startSlot, err))
|
||||
}
|
||||
@@ -193,7 +198,11 @@ func (bs *Server) ListValidators(
|
||||
req.PageSize, cmd.Get().MaxRPCPageSize)
|
||||
}
|
||||
|
||||
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
requestedEpoch := currentEpoch
|
||||
|
||||
switch q := req.QueryFilter.(type) {
|
||||
@@ -213,14 +222,17 @@ func (bs *Server) ListValidators(
|
||||
requestedEpoch = q.Epoch
|
||||
}
|
||||
var reqState state.BeaconState
|
||||
var err error
|
||||
if requestedEpoch != currentEpoch {
|
||||
var s types.Slot
|
||||
s, err = slots.EpochStart(requestedEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqState, err = bs.ReplayerBuilder.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
reqState, err = b.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", s, err))
|
||||
}
|
||||
@@ -391,7 +403,11 @@ func (bs *Server) GetValidator(
|
||||
func (bs *Server) GetValidatorActiveSetChanges(
|
||||
ctx context.Context, req *ethpb.GetValidatorActiveSetChangesRequest,
|
||||
) (*ethpb.ActiveSetChanges, error) {
|
||||
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
|
||||
var requestedEpoch types.Epoch
|
||||
switch q := req.QueryFilter.(type) {
|
||||
@@ -415,7 +431,11 @@ func (bs *Server) GetValidatorActiveSetChanges(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
requestedState, err := bs.ReplayerBuilder.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
requestedState, err := b.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", s, err))
|
||||
}
|
||||
@@ -476,7 +496,11 @@ func (bs *Server) GetValidatorActiveSetChanges(
|
||||
func (bs *Server) GetValidatorParticipation(
|
||||
ctx context.Context, req *ethpb.GetValidatorParticipationRequest,
|
||||
) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
currentSlot := bs.GenesisTimeFetcher.CurrentSlot()
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentSlot := c.CurrentSlot()
|
||||
currentEpoch := slots.ToEpoch(currentSlot)
|
||||
|
||||
var requestedEpoch types.Epoch
|
||||
@@ -512,7 +536,11 @@ func (bs *Server) GetValidatorParticipation(
|
||||
}
|
||||
|
||||
// ReplayerBuilder ensures that a canonical chain is followed to the slot
|
||||
beaconState, err := bs.ReplayerBuilder.ReplayerForSlot(endSlot).ReplayBlocks(ctx)
|
||||
rb, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
beaconState, err := rb.ReplayerForSlot(endSlot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", endSlot, err))
|
||||
}
|
||||
@@ -660,12 +688,16 @@ func (bs *Server) GetValidatorPerformance(
|
||||
if bs.SyncChecker.Syncing() {
|
||||
return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
|
||||
headState, err := bs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
|
||||
}
|
||||
currSlot := bs.GenesisTimeFetcher.CurrentSlot()
|
||||
currSlot := c.CurrentSlot()
|
||||
|
||||
if currSlot > headState.Slot() {
|
||||
headRoot, err := bs.HeadFetcher.HeadRoot(ctx)
|
||||
@@ -817,7 +849,11 @@ func (bs *Server) GetIndividualVotes(
|
||||
ctx context.Context,
|
||||
req *ethpb.IndividualVotesRequest,
|
||||
) (*ethpb.IndividualVotesRespond, error) {
|
||||
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
if req.Epoch > currentEpoch {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
@@ -831,7 +867,11 @@ func (bs *Server) GetIndividualVotes(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err := bs.ReplayerBuilder.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
b, err := bs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
st, err := b.ReplayerForSlot(s).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to replay blocks for state at epoch %d: %v", req.Epoch, err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -51,19 +52,21 @@ func TestServer_GetValidatorActiveSetChanges_CannotRequestFutureEpoch(t *testing
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, st.SetSlot(0))
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
BeaconDB: beaconDB,
|
||||
}
|
||||
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
require.NoError(t, err)
|
||||
wanted := errNoEpochInfoError
|
||||
_, err = bs.GetValidatorActiveSetChanges(
|
||||
ctx,
|
||||
ðpb.GetValidatorActiveSetChangesRequest{
|
||||
QueryFilter: ðpb.GetValidatorActiveSetChangesRequest_Epoch{
|
||||
Epoch: slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
|
||||
Epoch: slots.ToEpoch(c.CurrentSlot()) + 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -82,15 +85,17 @@ func TestServer_ListValidatorBalances_CannotRequestFutureEpoch(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
|
||||
wanted := errNoEpochInfoError
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = bs.ListValidatorBalances(
|
||||
ctx,
|
||||
ðpb.ListValidatorBalancesRequest{
|
||||
QueryFilter: ðpb.ListValidatorBalancesRequest_Epoch{
|
||||
Epoch: slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
|
||||
Epoch: slots.ToEpoch(c.CurrentSlot()) + 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -105,7 +110,7 @@ func TestServer_ListValidatorBalances_NoResults(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, st.SetSlot(0))
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -172,7 +177,7 @@ func TestServer_ListValidatorBalances_DefaultResponse_NoArchive(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
@@ -201,7 +206,7 @@ func TestServer_ListValidatorBalances_PaginationOutOfRange(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
|
||||
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
@@ -250,7 +255,7 @@ func TestServer_ListValidatorBalances_Pagination_Default(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
|
||||
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
@@ -334,7 +339,7 @@ func TestServer_ListValidatorBalances_Pagination_CustomPageSizes(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
|
||||
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
@@ -402,7 +407,7 @@ func TestServer_ListValidatorBalances_OutOfRange(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
|
||||
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
@@ -425,10 +430,7 @@ func TestServer_ListValidators_CannotRequestFutureEpoch(t *testing.T) {
|
||||
require.NoError(t, st.SetSlot(0))
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
@@ -449,12 +451,10 @@ func TestServer_ListValidators_CannotRequestFutureEpoch(t *testing.T) {
|
||||
func TestServer_ListValidators_reqStateIsNil(t *testing.T) {
|
||||
beaconDB := dbTest.SetupDB(t)
|
||||
secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
gent := time.Now().Add(time.Duration(-1*int64(secondsPerEpoch)) * time.Second)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 1.
|
||||
Genesis: time.Now().Add(time.Duration(-1*int64(secondsPerEpoch)) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: nil,
|
||||
},
|
||||
@@ -492,10 +492,7 @@ func TestServer_ListValidators_NoResults(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
@@ -562,10 +559,7 @@ func TestServer_ListValidators_OnlyActiveValidators(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -630,10 +624,7 @@ func TestServer_ListValidators_InactiveInTheMiddle(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -665,7 +656,7 @@ func TestServer_ListValidatorBalances_UnknownValidatorInResponse(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
|
||||
|
||||
bs := &Server{
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
@@ -715,10 +706,7 @@ func TestServer_ListValidators_NoPagination(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
FinalizationFetcher: &mock.ChainService{
|
||||
FinalizedCheckPoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
@@ -748,10 +736,7 @@ func TestServer_ListValidators_StategenNotUsed(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
|
||||
received, err := bs.ListValidators(context.Background(), ðpb.ListValidatorsRequest{})
|
||||
@@ -786,10 +771,7 @@ func TestServer_ListValidators_IndicesPubKeys(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -822,10 +804,7 @@ func TestServer_ListValidators_Pagination(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -959,10 +938,7 @@ func TestServer_ListValidators_PaginationOutOfRange(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -1003,10 +979,7 @@ func TestServer_ListValidators_DefaultPageSize(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
// We are in epoch 0.
|
||||
Genesis: time.Now(),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -1045,13 +1018,12 @@ func TestServer_ListValidators_FromOldEpoch(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, r))
|
||||
|
||||
secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
gent := time.Now().Add(time.Duration(-1*int64(uint64(epochs)*secondsPerEpoch)) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
Genesis: time.Now().Add(time.Duration(-1*int64(uint64(epochs)*secondsPerEpoch)) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
@@ -1124,13 +1096,12 @@ func TestServer_ListValidators_ProcessHeadStateSlots(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
gent := time.Now().Add(time.Duration(-1*int64(secondsPerEpoch)) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
Genesis: time.Now().Add(time.Duration(-1*int64(secondsPerEpoch)) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
@@ -1283,7 +1254,7 @@ func TestServer_GetValidatorActiveSetChanges(t *testing.T) {
|
||||
FinalizationFetcher: &mock.ChainService{
|
||||
FinalizedCheckPoint: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, fieldparams.RootLength)},
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
res, err := bs.GetValidatorActiveSetChanges(ctx, ðpb.GetValidatorActiveSetChangesRequest{
|
||||
@@ -1487,16 +1458,18 @@ func TestServer_GetValidatorParticipation_CannotRequestFutureEpoch(t *testing.T)
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
|
||||
wanted := "Cannot retrieve information about an epoch"
|
||||
c, err := bs.ClockProvider.WaitForClock(ctx)
|
||||
require.NoError(t, err)
|
||||
_, err = bs.GetValidatorParticipation(
|
||||
ctx,
|
||||
ðpb.GetValidatorParticipationRequest{
|
||||
QueryFilter: ðpb.GetValidatorParticipationRequest_Epoch{
|
||||
Epoch: slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
|
||||
Epoch: slots.ToEpoch(c.CurrentSlot()) + 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -1550,13 +1523,12 @@ func TestServer_GetValidatorParticipation_CurrentAndPrevEpoch(t *testing.T) {
|
||||
|
||||
m := &mock.ChainService{State: headState}
|
||||
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
HeadFetcher: m,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
CanonicalFetcher: &mock.ChainService{
|
||||
CanonicalRoots: map[[32]byte]bool{
|
||||
bRoot: true,
|
||||
@@ -1629,13 +1601,12 @@ func TestServer_GetValidatorParticipation_OrphanedUntilGenesis(t *testing.T) {
|
||||
|
||||
m := &mock.ChainService{State: headState}
|
||||
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
HeadFetcher: m,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent),
|
||||
CanonicalFetcher: &mock.ChainService{
|
||||
CanonicalRoots: map[[32]byte]bool{
|
||||
bRoot: true,
|
||||
@@ -1726,13 +1697,12 @@ func runGetValidatorParticipationCurrentAndPrevEpoch(t *testing.T, genState stat
|
||||
|
||||
m := &mock.ChainService{State: genState}
|
||||
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
BeaconDB: beaconDB,
|
||||
HeadFetcher: m,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
GenesisTimeFetcher: &mock.ChainService{
|
||||
Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
FinalizationFetcher: &mock.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Epoch: 100}},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
@@ -1837,11 +1807,12 @@ func TestGetValidatorPerformance_OK(t *testing.T) {
|
||||
require.NoError(t, headState.SetValidators(validators))
|
||||
require.NoError(t, headState.SetBalances([]uint64{100, 101, 102}))
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
farFuture := params.BeaconConfig().FarFutureSlot
|
||||
@@ -1901,13 +1872,14 @@ func TestGetValidatorPerformance_Indices(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, headState.SetValidators(validators))
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
// 10 epochs into the future.
|
||||
State: headState,
|
||||
},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
}
|
||||
c := headState.Copy()
|
||||
vp, bp, err := precompute.New(ctx, c)
|
||||
@@ -1974,13 +1946,14 @@ func TestGetValidatorPerformance_IndicesPubkeys(t *testing.T) {
|
||||
require.NoError(t, headState.SetValidators(validators))
|
||||
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
// 10 epochs into the future.
|
||||
State: headState,
|
||||
},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
}
|
||||
c := headState.Copy()
|
||||
vp, bp, err := precompute.New(ctx, c)
|
||||
@@ -2053,11 +2026,12 @@ func TestGetValidatorPerformanceAltair_OK(t *testing.T) {
|
||||
require.NoError(t, headState.SetInactivityScores([]uint64{0, 0, 0}))
|
||||
require.NoError(t, headState.SetBalances([]uint64{100, 101, 102}))
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
want := ðpb.ValidatorPerformanceResponse{
|
||||
@@ -2123,11 +2097,13 @@ func TestGetValidatorPerformanceBellatrix_OK(t *testing.T) {
|
||||
require.NoError(t, headState.SetInactivityScores([]uint64{0, 0, 0}))
|
||||
require.NoError(t, headState.SetBalances([]uint64{100, 101, 102}))
|
||||
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: clock},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
}
|
||||
want := ðpb.ValidatorPerformanceResponse{
|
||||
@@ -2194,12 +2170,14 @@ func setupValidators(t testing.TB, _ db.Database, count int) ([]*ethpb.Validator
|
||||
}
|
||||
|
||||
func TestServer_GetIndividualVotes_RequestFutureSlot(t *testing.T) {
|
||||
ds := &Server{GenesisTimeFetcher: &mock.ChainService{}}
|
||||
ds := &Server{ClockProvider: &mock.ChainService{}}
|
||||
c, err := ds.ClockProvider.WaitForClock(context.Background())
|
||||
require.NoError(t, err)
|
||||
req := ðpb.IndividualVotesRequest{
|
||||
Epoch: slots.ToEpoch(ds.GenesisTimeFetcher.CurrentSlot()) + 1,
|
||||
Epoch: slots.ToEpoch(c.CurrentSlot()) + 1,
|
||||
}
|
||||
wanted := errNoEpochInfoError
|
||||
_, err := ds.GetIndividualVotes(context.Background(), req)
|
||||
_, err = ds.GetIndividualVotes(context.Background(), req)
|
||||
assert.ErrorContains(t, wanted, err)
|
||||
}
|
||||
|
||||
@@ -2229,7 +2207,7 @@ func TestServer_GetIndividualVotes_ValidatorsDontExist(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
@@ -2325,7 +2303,7 @@ func TestServer_GetIndividualVotes_Working(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
@@ -2390,7 +2368,7 @@ func TestServer_GetIndividualVotes_WorkingAltair(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
@@ -2476,7 +2454,7 @@ func TestServer_GetIndividualVotes_AltairEndOfEpoch(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
@@ -2564,7 +2542,7 @@ func TestServer_GetIndividualVotes_BellatrixEndOfEpoch(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, beaconDB)
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ go_test(
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
|
||||
@@ -41,12 +41,14 @@ func (ds *Server) GetBlock(
|
||||
|
||||
// GetInclusionSlot of an attestation in block.
|
||||
func (ds *Server) GetInclusionSlot(ctx context.Context, req *pbrpc.InclusionSlotRequest) (*pbrpc.InclusionSlotResponse, error) {
|
||||
ds.GenesisTimeFetcher.CurrentSlot()
|
||||
|
||||
c, err := ds.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
// Attestation has one epoch to get included in the chain. This blocks users from requesting too soon.
|
||||
epochBack := types.Slot(0)
|
||||
if ds.GenesisTimeFetcher.CurrentSlot() > params.BeaconConfig().SlotsPerEpoch {
|
||||
epochBack = ds.GenesisTimeFetcher.CurrentSlot() - params.BeaconConfig().SlotsPerEpoch
|
||||
if c.CurrentSlot() > params.BeaconConfig().SlotsPerEpoch {
|
||||
epochBack = c.CurrentSlot() - params.BeaconConfig().SlotsPerEpoch
|
||||
}
|
||||
if epochBack < req.Slot {
|
||||
return nil, fmt.Errorf("attestation has one epoch window, please request slot older than %d", epochBack)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
@@ -51,10 +52,11 @@ func TestServer_GetAttestationInclusionSlot(t *testing.T) {
|
||||
db := dbTest.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
offset := int64(2 * params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
bs := &Server{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db),
|
||||
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(gent)},
|
||||
}
|
||||
|
||||
s, _ := util.DeterministicGenesisState(t, 2048)
|
||||
|
||||
@@ -25,13 +25,13 @@ import (
|
||||
// gated behind the feature flag --enable-debug-rpc-endpoints.
|
||||
type Server struct {
|
||||
BeaconDB db.NoHeadAccessDatabase
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
StateGen *stategen.State
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
PeerManager p2p.PeerManager
|
||||
PeersFetcher p2p.PeersProvider
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
PeersFetcher p2p.PeersProvider
|
||||
CanonicalHistoryWaiter stategen.CanonicalHistoryWaiter
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
// SetLoggingLevel of a beacon node according to a request type,
|
||||
|
||||
@@ -18,7 +18,11 @@ func (ds *Server) GetBeaconState(
|
||||
) (*pbrpc.SSZResponse, error) {
|
||||
switch q := req.QueryFilter.(type) {
|
||||
case *pbrpc.BeaconStateRequest_Slot:
|
||||
currentSlot := ds.GenesisTimeFetcher.CurrentSlot()
|
||||
c, err := ds.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentSlot := c.CurrentSlot()
|
||||
requestedSlot := q.Slot
|
||||
if requestedSlot > currentSlot {
|
||||
return nil, status.Errorf(
|
||||
@@ -29,7 +33,11 @@ func (ds *Server) GetBeaconState(
|
||||
)
|
||||
}
|
||||
|
||||
st, err := ds.ReplayerBuilder.ReplayerForSlot(q.Slot).ReplayBlocks(ctx)
|
||||
b, err := ds.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
st, err := b.ReplayerForSlot(q.Slot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", q.Slot, err))
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestServer_GetBeaconState(t *testing.T) {
|
||||
require.NoError(t, db.SaveState(ctx, st, gRoot))
|
||||
bs := &Server{
|
||||
StateGen: gen,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
}
|
||||
addDefaultReplayerBuilder(bs, db)
|
||||
_, err = bs.GetBeaconState(ctx, &pbrpc.BeaconStateRequest{})
|
||||
@@ -95,13 +95,15 @@ func TestServer_GetBeaconState(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServer_GetBeaconState_RequestFutureSlot(t *testing.T) {
|
||||
ds := &Server{GenesisTimeFetcher: &mock.ChainService{}}
|
||||
ds := &Server{ClockProvider: &mock.ChainService{}}
|
||||
c, err := ds.ClockProvider.WaitForClock(context.Background())
|
||||
require.NoError(t, err)
|
||||
req := &pbrpc.BeaconStateRequest{
|
||||
QueryFilter: &pbrpc.BeaconStateRequest_Slot{
|
||||
Slot: ds.GenesisTimeFetcher.CurrentSlot() + 1,
|
||||
Slot: c.CurrentSlot() + 1,
|
||||
},
|
||||
}
|
||||
wanted := "Cannot retrieve information about a slot in the future"
|
||||
_, err := ds.GetBeaconState(context.Background(), req)
|
||||
_, err = ds.GetBeaconState(context.Background(), req)
|
||||
assert.ErrorContains(t, wanted, err)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ go_test(
|
||||
srcs = ["server_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
|
||||
@@ -38,11 +38,11 @@ type Server struct {
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
POWChainInfoFetcher powchain.ChainInfoFetcher
|
||||
BeaconMonitoringHost string
|
||||
BeaconMonitoringPort int
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
// GetSyncStatus checks the current network sync status of the node.
|
||||
@@ -59,7 +59,11 @@ func (ns *Server) GetGenesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesi
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve contract address from db: %v", err)
|
||||
}
|
||||
genesisTime := ns.GenesisTimeFetcher.GenesisTime()
|
||||
c, err := ns.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
genesisTime := c.GenesisTime()
|
||||
var defaultGenesisTime time.Time
|
||||
var gt *timestamp.Timestamp
|
||||
if genesisTime == defaultGenesisTime {
|
||||
|
||||
@@ -3,6 +3,7 @@ package node
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -51,7 +52,7 @@ func TestNodeServer_GetGenesis(t *testing.T) {
|
||||
genValRoot := bytesutil.ToBytes32([]byte("I am root"))
|
||||
ns := &Server{
|
||||
BeaconDB: db,
|
||||
GenesisTimeFetcher: &mock.ChainService{},
|
||||
ClockProvider: &mock.ChainService{},
|
||||
GenesisFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
ValidatorsRoot: genValRoot,
|
||||
@@ -64,7 +65,7 @@ func TestNodeServer_GetGenesis(t *testing.T) {
|
||||
assert.Equal(t, res.GenesisTime.Seconds, pUnix.Seconds)
|
||||
assert.DeepEqual(t, genValRoot[:], res.GenesisValidatorsRoot)
|
||||
|
||||
ns.GenesisTimeFetcher = &mock.ChainService{Genesis: time.Unix(10, 0)}
|
||||
ns.ClockProvider = &mock.ChainService{Clock: blockchain.NewClock(time.Unix(10, 0))}
|
||||
res, err = ns.GetGenesis(context.Background(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
pUnix = timestamppb.New(time.Unix(10, 0))
|
||||
|
||||
@@ -117,6 +117,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/builder/testing:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
|
||||
@@ -129,9 +129,13 @@ func (vs *Server) SubmitSignedAggregateSelectionProof(
|
||||
return nil, status.Error(codes.InvalidArgument, "Signed signatures can't be zero hashes")
|
||||
}
|
||||
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout waiting for genesis time initialization, %s", err)
|
||||
}
|
||||
// As a preventive measure, a beacon node shouldn't broadcast an attestation whose slot is out of range.
|
||||
if err := helpers.ValidateAttestationTime(req.SignedAggregateAndProof.Message.Aggregate.Data.Slot,
|
||||
vs.TimeFetcher.GenesisTime(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
c.GenesisTime(), params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Attestation slot is no longer valid from current time")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -55,7 +56,7 @@ func TestSubmitAggregateAndProof_CantFindValidatorIndex(t *testing.T) {
|
||||
server := &Server{
|
||||
HeadFetcher: &mock.ChainService{State: s},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -83,7 +84,7 @@ func TestSubmitAggregateAndProof_IsAggregatorAndNoAtts(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{State: s},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -117,7 +118,7 @@ func TestSubmitAggregateAndProof_UnaggregateOk(t *testing.T) {
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -155,7 +156,7 @@ func TestSubmitAggregateAndProof_AggregateOk(t *testing.T) {
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -195,7 +196,7 @@ func TestSubmitAggregateAndProof_AggregateNotOk(t *testing.T) {
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -324,7 +325,7 @@ func TestSubmitAggregateAndProof_PreferOwnAttestation(t *testing.T) {
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -375,7 +376,7 @@ func TestSubmitAggregateAndProof_SelectsMostBitsWhenOwnAttestationNotPresent(t *
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttPool: attestations.NewPool(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -428,8 +429,8 @@ func TestSubmitSignedAggregateSelectionProof_ZeroHashesSignatures(t *testing.T)
|
||||
}
|
||||
|
||||
func TestSubmitSignedAggregateSelectionProof_InvalidSlot(t *testing.T) {
|
||||
c := &mock.ChainService{Genesis: time.Now()}
|
||||
aggregatorServer := &Server{TimeFetcher: c}
|
||||
c := &mock.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
aggregatorServer := &Server{ClockProvider: c}
|
||||
req := ðpb.SignedAggregateSubmitRequest{
|
||||
SignedAggregateAndProof: ðpb.SignedAggregateAttestationAndProof{
|
||||
Signature: []byte{'a'},
|
||||
|
||||
@@ -41,15 +41,16 @@ func (vs *Server) StreamDuties(req *ethpb.DutiesRequest, stream ethpb.BeaconNode
|
||||
return status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
c, err := vs.ClockProvider.WaitForClock(stream.Context())
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "timeout waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
// If we are post-genesis time, then set the current epoch to
|
||||
// the number epochs since the genesis time, otherwise 0 by default.
|
||||
genesisTime := vs.TimeFetcher.GenesisTime()
|
||||
if genesisTime.IsZero() {
|
||||
return status.Error(codes.Unavailable, "genesis time is not set")
|
||||
}
|
||||
genesisTime := c.GenesisTime()
|
||||
var currentEpoch types.Epoch
|
||||
if genesisTime.Before(prysmTime.Now()) {
|
||||
currentEpoch = slots.EpochsSinceGenesis(vs.TimeFetcher.GenesisTime())
|
||||
if genesisTime.Before(c.Now()) {
|
||||
currentEpoch = slots.EpochsSinceGenesis(genesisTime)
|
||||
}
|
||||
req.Epoch = currentEpoch
|
||||
res, err := vs.duties(stream.Context(), req)
|
||||
@@ -66,7 +67,7 @@ func (vs *Server) StreamDuties(req *ethpb.DutiesRequest, stream ethpb.BeaconNode
|
||||
defer stateSub.Unsubscribe()
|
||||
|
||||
secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
epochTicker := slots.NewSlotTicker(vs.TimeFetcher.GenesisTime(), secondsPerEpoch)
|
||||
epochTicker := slots.NewSlotTicker(genesisTime, secondsPerEpoch)
|
||||
for {
|
||||
select {
|
||||
// Ticks every epoch to submit assignments to connected validator clients.
|
||||
@@ -82,7 +83,7 @@ func (vs *Server) StreamDuties(req *ethpb.DutiesRequest, stream ethpb.BeaconNode
|
||||
case ev := <-stateChannel:
|
||||
// If a reorg occurred, we recompute duties for the connected validator clients
|
||||
// and send another response over the server stream right away.
|
||||
currentEpoch = slots.EpochsSinceGenesis(vs.TimeFetcher.GenesisTime())
|
||||
currentEpoch = slots.EpochsSinceGenesis(genesisTime)
|
||||
if ev.Type == statefeed.Reorg {
|
||||
data, ok := ev.Data.(*ethpbv1.EventChainReorg)
|
||||
if !ok {
|
||||
@@ -108,7 +109,11 @@ func (vs *Server) StreamDuties(req *ethpb.DutiesRequest, stream ethpb.BeaconNode
|
||||
// Compute the validator duties from the head state's corresponding epoch
|
||||
// for validators public key / indices requested.
|
||||
func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
|
||||
currentEpoch := slots.ToEpoch(vs.TimeFetcher.CurrentSlot())
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
currentEpoch := slots.ToEpoch(c.CurrentSlot())
|
||||
if req.Epoch > currentEpoch+1 {
|
||||
return nil, status.Errorf(codes.Unavailable, "Request epoch %d can not be greater than next epoch %d", req.Epoch, currentEpoch+1)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package validator
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -57,11 +58,13 @@ func TestGetDuties_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Genesis: time.Now(),
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
@@ -141,12 +144,15 @@ func TestGetAltairDuties_SyncCommitteeOK(t *testing.T) {
|
||||
}
|
||||
|
||||
slot := uint64(params.BeaconConfig().SlotsPerEpoch) * uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod) * params.BeaconConfig().SecondsPerSlot
|
||||
gent := time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Genesis: time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second),
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
@@ -247,12 +253,15 @@ func TestGetBellatrixDuties_SyncCommitteeOK(t *testing.T) {
|
||||
}
|
||||
|
||||
slot := uint64(params.BeaconConfig().SlotsPerEpoch) * uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod) * params.BeaconConfig().SecondsPerSlot
|
||||
gent := time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Genesis: time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second),
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
@@ -336,15 +345,18 @@ func TestGetAltairDuties_UnknownPubkey(t *testing.T) {
|
||||
require.NoError(t, helpers.UpdateSyncCommitteeCache(bs))
|
||||
|
||||
slot := uint64(params.BeaconConfig().SlotsPerEpoch) * uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod) * params.BeaconConfig().SecondsPerSlot
|
||||
gent := time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second)
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Genesis: time.Now().Add(time.Duration(-1*int64(slot-1)) * time.Second),
|
||||
State: bs,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(gent),
|
||||
}
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
DepositFetcher: depositCache,
|
||||
@@ -365,10 +377,10 @@ func TestGetAltairDuties_UnknownPubkey(t *testing.T) {
|
||||
|
||||
func TestGetDuties_SlotOutOfUpperBound(t *testing.T) {
|
||||
chain := &mockChain.ChainService{
|
||||
Genesis: time.Now(),
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
}
|
||||
req := ðpb.DutiesRequest{
|
||||
Epoch: types.Epoch(chain.CurrentSlot()/params.BeaconConfig().SlotsPerEpoch + 2),
|
||||
@@ -400,11 +412,13 @@ func TestGetDuties_CurrentEpoch_ShouldNotFail(t *testing.T) {
|
||||
}
|
||||
|
||||
chain := &mockChain.ChainService{
|
||||
State: bState, Root: genesisRoot[:], Genesis: time.Now(),
|
||||
State: bState,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
@@ -439,11 +453,12 @@ func TestGetDuties_MultipleKeys_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
chain := &mockChain.ChainService{
|
||||
State: bs, Root: genesisRoot[:], Genesis: time.Now(),
|
||||
State: bs, Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
HeadFetcher: chain,
|
||||
TimeFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
@@ -506,13 +521,13 @@ func TestStreamDuties_OK(t *testing.T) {
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
c := &mockChain.ChainService{
|
||||
Genesis: time.Now(),
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
Ctx: ctx,
|
||||
HeadFetcher: &mockChain.ChainService{State: bs, Root: genesisRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: c,
|
||||
ClockProvider: c,
|
||||
StateNotifier: &mockChain.MockStateNotifier{},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
@@ -564,13 +579,13 @@ func TestStreamDuties_OK_ChainReorg(t *testing.T) {
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
c := &mockChain.ChainService{
|
||||
Genesis: time.Now(),
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
vs := &Server{
|
||||
Ctx: ctx,
|
||||
HeadFetcher: &mockChain.ChainService{State: bs, Root: genesisRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: c,
|
||||
ClockProvider: c,
|
||||
StateNotifier: &mockChain.MockStateNotifier{},
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
|
||||
@@ -42,7 +42,11 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := helpers.ValidateAttestationTime(req.Slot, vs.TimeFetcher.GenesisTime(),
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if err := helpers.ValidateAttestationTime(req.Slot, c.GenesisTime(),
|
||||
params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid request: %v", err))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -121,6 +122,7 @@ func TestGetAttestationData_OK(t *testing.T) {
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
attesterServer := &Server{
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -131,8 +133,8 @@ func TestGetAttestationData_OK(t *testing.T) {
|
||||
FinalizationFetcher: &mock.ChainService{
|
||||
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
|
||||
},
|
||||
TimeFetcher: &mock.ChainService{
|
||||
Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second),
|
||||
ClockProvider: &mock.ChainService{
|
||||
Clock: blockchain.NewClock(gent),
|
||||
},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
@@ -178,7 +180,7 @@ func TestGetAttestationData_Optimistic(t *testing.T) {
|
||||
|
||||
as := &Server{
|
||||
SyncChecker: &mockSync.Sync{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
OptimisticModeFetcher: &mock.ChainService{Optimistic: true},
|
||||
}
|
||||
@@ -192,7 +194,7 @@ func TestGetAttestationData_Optimistic(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
as = &Server{
|
||||
SyncChecker: &mockSync.Sync{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
HeadFetcher: &mock.ChainService{Optimistic: false, State: beaconState},
|
||||
OptimisticModeFetcher: &mock.ChainService{Optimistic: false},
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
@@ -252,6 +254,8 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) {
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
attesterServer := &Server{
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
@@ -260,7 +264,7 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) {
|
||||
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
|
||||
},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: clock},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
|
||||
@@ -299,11 +303,13 @@ func TestAttestationDataSlot_handlesInProgressRequest(t *testing.T) {
|
||||
}
|
||||
slot := types.Slot(2)
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
server := &Server{
|
||||
HeadFetcher: &mock.ChainService{State: state},
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: clock},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
|
||||
@@ -347,10 +353,12 @@ func TestServer_GetAttestationData_InvalidRequestSlot(t *testing.T) {
|
||||
|
||||
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
attesterServer := &Server{
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: clock},
|
||||
}
|
||||
|
||||
req := ðpb.AttestationDataRequest{
|
||||
@@ -411,17 +419,19 @@ func TestServer_GetAttestationData_HeadStateSlotGreaterThanRequestSlot(t *testin
|
||||
beaconstate := beaconState.Copy()
|
||||
require.NoError(t, beaconstate.SetSlot(beaconstate.Slot()-1))
|
||||
require.NoError(t, db.SaveState(ctx, beaconstate, blockRoot2))
|
||||
chainService := &mock.ChainService{
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset = int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := time.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
chainService := &mock.ChainService{
|
||||
Clock: clock,
|
||||
}
|
||||
attesterServer := &Server{
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
AttestationCache: cache.NewAttestationCache(),
|
||||
HeadFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]},
|
||||
FinalizationFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint()},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: chainService,
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
StateGen: stategen.New(db),
|
||||
}
|
||||
@@ -486,6 +496,8 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) {
|
||||
Genesis: time.Now(),
|
||||
}
|
||||
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
gent := prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)
|
||||
clock := blockchain.NewClock(gent)
|
||||
attesterServer := &Server{
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
@@ -496,7 +508,7 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) {
|
||||
FinalizationFetcher: &mock.ChainService{
|
||||
CurrentJustifiedCheckPoint: beaconState.CurrentJustifiedCheckpoint(),
|
||||
},
|
||||
TimeFetcher: &mock.ChainService{Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)},
|
||||
ClockProvider: &mock.ChainService{Clock: clock},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -39,11 +40,15 @@ func TestProposeExit_Notification(t *testing.T) {
|
||||
// Set genesis time to be 100 epochs ago.
|
||||
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
genesisTime := time.Now().Add(time.Duration(-100*offset) * time.Second)
|
||||
mockChainService := &mockChain.ChainService{State: beaconState, Root: genesisRoot[:], Genesis: genesisTime}
|
||||
mockChainService := &mockChain.ChainService{
|
||||
State: beaconState,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(genesisTime),
|
||||
}
|
||||
server := &Server{
|
||||
HeadFetcher: mockChainService,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
ClockProvider: mockChainService,
|
||||
StateNotifier: mockChainService.StateNotifier(),
|
||||
OperationNotifier: mockChainService.OperationNotifier(),
|
||||
ExitPool: voluntaryexits.NewPool(),
|
||||
@@ -106,11 +111,15 @@ func TestProposeExit_NoPanic(t *testing.T) {
|
||||
// Set genesis time to be 100 epochs ago.
|
||||
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
genesisTime := time.Now().Add(time.Duration(-100*offset) * time.Second)
|
||||
mockChainService := &mockChain.ChainService{State: beaconState, Root: genesisRoot[:], Genesis: genesisTime}
|
||||
mockChainService := &mockChain.ChainService{
|
||||
State: beaconState,
|
||||
Root: genesisRoot[:],
|
||||
Clock: blockchain.NewClock(genesisTime),
|
||||
}
|
||||
server := &Server{
|
||||
HeadFetcher: mockChainService,
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
TimeFetcher: mockChainService,
|
||||
ClockProvider: mockChainService,
|
||||
StateNotifier: mockChainService.StateNotifier(),
|
||||
OperationNotifier: mockChainService.OperationNotifier(),
|
||||
ExitPool: voluntaryexits.NewPool(),
|
||||
|
||||
@@ -188,8 +188,14 @@ func (vs *Server) computeStateRoot(ctx context.Context, block interfaces.SignedB
|
||||
return root[:], nil
|
||||
}
|
||||
|
||||
// SubmitValidatorRegistration submits validator registrations.
|
||||
func (vs *Server) SubmitValidatorRegistration(ctx context.Context, reg *ethpb.SignedValidatorRegistrationsV1) (*emptypb.Empty, error) {
|
||||
// SubmitValidatorRegistration submits validator registration.
|
||||
// Deprecated: Use SubmitValidatorRegistrations instead.
|
||||
func (vs *Server) SubmitValidatorRegistration(ctx context.Context, reg *ethpb.SignedValidatorRegistrationV1) (*emptypb.Empty, error) {
|
||||
return vs.SubmitValidatorRegistrations(ctx, ðpb.SignedValidatorRegistrationsV1{Messages: []*ethpb.SignedValidatorRegistrationV1{reg}})
|
||||
}
|
||||
|
||||
// SubmitValidatorRegistrations submits validator registrations.
|
||||
func (vs *Server) SubmitValidatorRegistrations(ctx context.Context, reg *ethpb.SignedValidatorRegistrationsV1) (*emptypb.Empty, error) {
|
||||
// No-op is the builder is nil / not configured. The node should still function without a builder.
|
||||
if vs.BlockBuilder == nil || !vs.BlockBuilder.Configured() {
|
||||
return &emptypb.Empty{}, nil
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -441,7 +442,7 @@ func TestServer_GetBellatrixBeaconBlock_HappyCase(t *testing.T) {
|
||||
|
||||
proposerServer := &Server{
|
||||
HeadFetcher: &blockchainTest.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false},
|
||||
TimeFetcher: &blockchainTest.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &blockchainTest.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &blockchainTest.ChainService{},
|
||||
HeadUpdater: &blockchainTest.ChainService{},
|
||||
@@ -570,7 +571,7 @@ func TestServer_GetBellatrixBeaconBlock_BuilderCase(t *testing.T) {
|
||||
proposerServer := &Server{
|
||||
FinalizationFetcher: &blockchainTest.ChainService{FinalizedCheckPoint: ðpb.Checkpoint{Root: wbr1[:]}},
|
||||
HeadFetcher: &blockchainTest.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false, Block: wb1},
|
||||
TimeFetcher: &blockchainTest.ChainService{Genesis: time.Unix(int64(beaconState.GenesisTime()), 0)},
|
||||
ClockProvider: &blockchainTest.ChainService{Clock: blockchain.NewClock(time.Unix(int64(beaconState.GenesisTime()), 0))},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &blockchainTest.ChainService{},
|
||||
HeadUpdater: &blockchainTest.ChainService{},
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -2329,7 +2330,7 @@ func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) {
|
||||
}
|
||||
proposerServer := &Server{
|
||||
HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:], Optimistic: false},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mock.ChainService{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
@@ -2394,8 +2395,8 @@ func TestProposer_GetBeaconBlock_Optimistic(t *testing.T) {
|
||||
|
||||
bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerServer := &Server{OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, TimeFetcher: &mock.ChainService{}}
|
||||
clockp := &mock.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
proposerServer := &Server{OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, ClockProvider: clockp}
|
||||
req := ðpb.BlockRequest{
|
||||
Slot: bellatrixSlot + 1,
|
||||
}
|
||||
@@ -2506,20 +2507,20 @@ func TestProposer_PrepareBeaconProposer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposer_SubmitValidatorRegistration(t *testing.T) {
|
||||
func TestProposer_SubmitValidatorRegistrations(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
proposerServer := &Server{}
|
||||
reg := ðpb.SignedValidatorRegistrationsV1{}
|
||||
_, err := proposerServer.SubmitValidatorRegistration(ctx, reg)
|
||||
_, err := proposerServer.SubmitValidatorRegistrations(ctx, reg)
|
||||
require.NoError(t, err)
|
||||
proposerServer = &Server{BlockBuilder: &builderTest.MockBuilderService{}}
|
||||
_, err = proposerServer.SubmitValidatorRegistration(ctx, reg)
|
||||
_, err = proposerServer.SubmitValidatorRegistrations(ctx, reg)
|
||||
require.NoError(t, err)
|
||||
proposerServer = &Server{BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true}}
|
||||
_, err = proposerServer.SubmitValidatorRegistration(ctx, reg)
|
||||
_, err = proposerServer.SubmitValidatorRegistrations(ctx, reg)
|
||||
require.NoError(t, err)
|
||||
proposerServer = &Server{BlockBuilder: &builderTest.MockBuilderService{HasConfigured: true, ErrRegisterValidator: errors.New("bad")}}
|
||||
_, err = proposerServer.SubmitValidatorRegistration(ctx, reg)
|
||||
_, err = proposerServer.SubmitValidatorRegistrations(ctx, reg)
|
||||
require.ErrorContains(t, "bad", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ type Server struct {
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
TimeFetcher blockchain.TimeFetcher
|
||||
BlockFetcher powchain.POWBlockFetcher
|
||||
DepositFetcher depositcache.DepositFetcher
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
@@ -67,10 +66,11 @@ type Server struct {
|
||||
PendingDepositsFetcher depositcache.PendingDepositsFetcher
|
||||
OperationNotifier opfeed.Notifier
|
||||
StateGen stategen.StateManager
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
CanonicalHistoryWaiter stategen.CanonicalHistoryWaiter
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
ExecutionEngineCaller powchain.EngineCaller
|
||||
BlockBuilder builder.BlockBuilder
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
// WaitForActivation checks if a validator public key exists in the active validator registry of the current
|
||||
@@ -124,7 +124,7 @@ func (vs *Server) ValidatorIndex(ctx context.Context, req *ethpb.ValidatorIndexR
|
||||
}
|
||||
index, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(req.PublicKey))
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Internal, "Could not find validator index for public key %#x not found", req.PublicKey)
|
||||
return nil, status.Errorf(codes.NotFound, "Could not find validator index for public key %#x not found", req.PublicKey)
|
||||
}
|
||||
|
||||
return ðpb.ValidatorIndexResponse{Index: index}, nil
|
||||
|
||||
@@ -146,7 +146,11 @@ func (vs *Server) CheckDoppelGanger(ctx context.Context, req *ethpb.DoppelGanger
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not get previous epoch's end")
|
||||
}
|
||||
prevState, err := vs.ReplayerBuilder.ReplayerForSlot(prevEpochEnd).ReplayBlocks(ctx)
|
||||
b, err := vs.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
prevState, err := b.ReplayerForSlot(prevEpochEnd).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not get previous state")
|
||||
}
|
||||
@@ -252,7 +256,11 @@ func (vs *Server) activationStatus(
|
||||
// Spec:
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md
|
||||
func (vs *Server) optimisticStatus(ctx context.Context) error {
|
||||
if slots.ToEpoch(vs.TimeFetcher.CurrentSlot()) < params.BeaconConfig().BellatrixForkEpoch {
|
||||
c, err := vs.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "timeout while waiting for genesis timestamp, %s", err)
|
||||
}
|
||||
if slots.ToEpoch(c.CurrentSlot()) < params.BeaconConfig().BellatrixForkEpoch {
|
||||
return nil
|
||||
}
|
||||
optimistic, err := vs.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
@@ -363,15 +371,6 @@ func (vs *Server) validatorStatus(
|
||||
}
|
||||
}
|
||||
|
||||
func (vs *Server) retrieveAfterEpochTransition(ctx context.Context, epoch types.Epoch) (state.BeaconState, error) {
|
||||
endSlot, err := slots.EpochEnd(epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// replay to first slot of following epoch
|
||||
return vs.ReplayerBuilder.ReplayerForSlot(endSlot).ReplayToSlot(ctx, endSlot+1)
|
||||
}
|
||||
|
||||
func checkValidatorsAreRecent(headEpoch types.Epoch, req *ethpb.DoppelGangerRequest) (bool, *ethpb.DoppelGangerResponse) {
|
||||
validatorsAreRecent := true
|
||||
resp := ðpb.DoppelGangerResponse{
|
||||
|
||||
@@ -2,6 +2,7 @@ package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -604,7 +605,8 @@ func TestActivationStatus_OK(t *testing.T) {
|
||||
|
||||
func TestOptimisticStatus(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
server := &Server{OptimisticModeFetcher: &mockChain.ChainService{}, TimeFetcher: &mockChain.ChainService{}}
|
||||
clockp := &mockChain.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
server := &Server{OptimisticModeFetcher: &mockChain.ChainService{}, ClockProvider: clockp}
|
||||
err := server.optimisticStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -612,14 +614,14 @@ func TestOptimisticStatus(t *testing.T) {
|
||||
cfg.BellatrixForkEpoch = 2
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: true}, TimeFetcher: &mockChain.ChainService{}}
|
||||
server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: true}, ClockProvider: clockp}
|
||||
err = server.optimisticStatus(context.Background())
|
||||
s, ok := status.FromError(err)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, codes.Unavailable, s.Code())
|
||||
require.ErrorContains(t, errOptimisticMode.Error(), err)
|
||||
|
||||
server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: false}, TimeFetcher: &mockChain.ChainService{}}
|
||||
server = &Server{OptimisticModeFetcher: &mockChain.ChainService{Optimistic: false}, ClockProvider: clockp}
|
||||
err = server.optimisticStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||
@@ -27,8 +28,8 @@ import (
|
||||
func TestGetSyncMessageBlockRoot_OK(t *testing.T) {
|
||||
r := []byte{'a'}
|
||||
server := &Server{
|
||||
HeadFetcher: &mock.ChainService{Root: r},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
HeadFetcher: &mock.ChainService{Root: r},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
}
|
||||
res, err := server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
@@ -43,7 +44,7 @@ func TestGetSyncMessageBlockRoot_Optimistic(t *testing.T) {
|
||||
|
||||
server := &Server{
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
OptimisticModeFetcher: &mock.ChainService{Optimistic: true},
|
||||
}
|
||||
_, err := server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{})
|
||||
@@ -54,7 +55,7 @@ func TestGetSyncMessageBlockRoot_Optimistic(t *testing.T) {
|
||||
|
||||
server = &Server{
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
ClockProvider: &mock.ChainService{Clock: blockchain.NewClock(time.Now())},
|
||||
OptimisticModeFetcher: &mock.ChainService{Optimistic: false},
|
||||
}
|
||||
_, err = server.GetSyncMessageBlockRoot(context.Background(), &emptypb.Empty{})
|
||||
@@ -103,14 +104,16 @@ func TestGetSyncSubcommitteeIndex_Ok(t *testing.T) {
|
||||
|
||||
func TestGetSyncCommitteeContribution_FiltersDuplicates(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateAltair(t, 10)
|
||||
chain := &mock.ChainService{
|
||||
State: st,
|
||||
SyncCommitteeIndices: []types.CommitteeIndex{10},
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
server := &Server{
|
||||
SyncCommitteePool: synccommittee.NewStore(),
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: st,
|
||||
SyncCommitteeIndices: []types.CommitteeIndex{10},
|
||||
},
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
HeadFetcher: chain,
|
||||
ClockProvider: chain,
|
||||
}
|
||||
secKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,7 +4,6 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
|
||||
grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
|
||||
grpcprometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/builder"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
@@ -90,7 +90,6 @@ type Config struct {
|
||||
POWChainService powchain.Chain
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
POWChainInfoFetcher powchain.ChainInfoFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
EnableDebugRPCEndpoints bool
|
||||
MockEth1Votes bool
|
||||
@@ -115,6 +114,7 @@ type Config struct {
|
||||
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
BlockBuilder builder.BlockBuilder
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
// NewService instantiates a new RPC service instance that will
|
||||
@@ -175,7 +175,6 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
|
||||
// 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() {
|
||||
@@ -186,7 +185,8 @@ func (s *Service) Start() {
|
||||
stateCache = s.cfg.StateGen.CombinedCache()
|
||||
}
|
||||
withCache := stategen.WithCache(stateCache)
|
||||
ch := stategen.NewCanonicalHistory(s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, s.cfg.ChainInfoFetcher, withCache)
|
||||
//ch := stategen.NewCanonicalHistory(s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, s.cfg.ChainInfoFetcher, withCache)
|
||||
rbw := NewCanonicalHistoryWaiter(s.cfg.ChainInfoFetcher, s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, withCache)
|
||||
|
||||
validatorServer := &validatorv1alpha1.Server{
|
||||
Ctx: s.ctx,
|
||||
@@ -197,7 +197,6 @@ func (s *Service) Start() {
|
||||
HeadUpdater: s.cfg.HeadUpdater,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
TimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
BlockFetcher: s.cfg.POWChainService,
|
||||
DepositFetcher: s.cfg.DepositFetcher,
|
||||
ChainStartFetcher: s.cfg.ChainStartFetcher,
|
||||
@@ -215,16 +214,16 @@ func (s *Service) Start() {
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
StateGen: s.cfg.StateGen,
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
ReplayerBuilder: ch,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
BlockBuilder: s.cfg.BlockBuilder,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
validatorServerV1 := &validator.Server{
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
HeadUpdater: s.cfg.HeadUpdater,
|
||||
TimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
AttestationsPool: s.cfg.AttestationsPool,
|
||||
@@ -232,13 +231,14 @@ func (s *Service) Start() {
|
||||
Broadcaster: s.cfg.Broadcaster,
|
||||
V1Alpha1Server: validatorServer,
|
||||
StateFetcher: &statefetcher.StateProvider{
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
ReplayerBuilder: ch,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
},
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
|
||||
nodeServer := &nodev1alpha1.Server{
|
||||
@@ -247,24 +247,24 @@ func (s *Service) Start() {
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
GenesisFetcher: s.cfg.GenesisFetcher,
|
||||
POWChainInfoFetcher: s.cfg.POWChainInfoFetcher,
|
||||
BeaconMonitoringHost: s.cfg.BeaconMonitoringHost,
|
||||
BeaconMonitoringPort: s.cfg.BeaconMonitoringPort,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
nodeServerV1 := &node.Server{
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
MetadataProvider: s.cfg.MetadataProvider,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
|
||||
beaconChainServer := &beaconv1alpha1.Server{
|
||||
@@ -280,7 +280,6 @@ func (s *Service) Start() {
|
||||
ChainStartFetcher: s.cfg.ChainStartFetcher,
|
||||
DepositFetcher: s.cfg.DepositFetcher,
|
||||
BlockFetcher: s.cfg.POWChainService,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
StateNotifier: s.cfg.StateNotifier,
|
||||
BlockNotifier: s.cfg.BlockNotifier,
|
||||
AttestationNotifier: s.cfg.OperationNotifier,
|
||||
@@ -289,26 +288,26 @@ func (s *Service) Start() {
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
ReceivedAttestationsBuffer: make(chan *ethpbv1alpha1.Attestation, attestationBufferSize),
|
||||
CollectedAttestationsBuffer: make(chan []*ethpbv1alpha1.Attestation, attestationBufferSize),
|
||||
ReplayerBuilder: ch,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
beaconChainServerV1 := &beacon.Server{
|
||||
CanonicalHistory: ch,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
AttestationsPool: s.cfg.AttestationsPool,
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
BlockNotifier: s.cfg.BlockNotifier,
|
||||
OperationNotifier: s.cfg.OperationNotifier,
|
||||
Broadcaster: s.cfg.Broadcaster,
|
||||
BlockReceiver: s.cfg.BlockReceiver,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
AttestationsPool: s.cfg.AttestationsPool,
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
BlockNotifier: s.cfg.BlockNotifier,
|
||||
OperationNotifier: s.cfg.OperationNotifier,
|
||||
Broadcaster: s.cfg.Broadcaster,
|
||||
BlockReceiver: s.cfg.BlockReceiver,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
StateFetcher: &statefetcher.StateProvider{
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
ReplayerBuilder: ch,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
},
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
@@ -316,6 +315,7 @@ func (s *Service) Start() {
|
||||
V1Alpha1ValidatorServer: validatorServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
ExecutionPayloadReconstructor: s.cfg.ExecutionPayloadReconstructor,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
|
||||
@@ -331,24 +331,24 @@ func (s *Service) Start() {
|
||||
if s.cfg.EnableDebugRPCEndpoints {
|
||||
log.Info("Enabled debug gRPC endpoints")
|
||||
debugServer := &debugv1alpha1.Server{
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
StateGen: s.cfg.StateGen,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
ReplayerBuilder: ch,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
StateGen: s.cfg.StateGen,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
}
|
||||
debugServerV1 := &debug.Server{
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
StateFetcher: &statefetcher.StateProvider{
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
ReplayerBuilder: ch,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
|
||||
StateGenService: s.cfg.StateGen,
|
||||
CanonicalHistoryWaiter: rbw,
|
||||
ClockProvider: s.cfg.ClockProvider,
|
||||
},
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
}
|
||||
@@ -429,3 +429,27 @@ func (s *Service) logNewClientConnection(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewCanonicalHistoryWaiter(c blockchain.ClockProvider, h stategen.HistoryAccessor, cc stategen.CanonicalChecker, opts ...stategen.CanonicalHistoryOption) stategen.CanonicalHistoryWaiter {
|
||||
return &canonicalHistoryWaiter{
|
||||
c: c,
|
||||
h: h,
|
||||
cc: cc,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
type canonicalHistoryWaiter struct {
|
||||
c blockchain.ClockProvider
|
||||
h stategen.HistoryAccessor
|
||||
cc stategen.CanonicalChecker
|
||||
opts []stategen.CanonicalHistoryOption
|
||||
}
|
||||
|
||||
func (w *canonicalHistoryWaiter) WaitForCanonicalHistory(ctx context.Context) (*stategen.CanonicalHistory, error) {
|
||||
c, err := w.c.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "timeout waiting for genesis timestamp")
|
||||
}
|
||||
return stategen.NewCanonicalHistory(w.h, w.cc, c, w.opts...), nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package rpc
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -24,7 +25,7 @@ func init() {
|
||||
func TestLifecycle_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
chainService := &mock.ChainService{
|
||||
Genesis: time.Now(),
|
||||
Clock: blockchain.NewClock(time.Now()),
|
||||
}
|
||||
rpcService := NewService(context.Background(), &Config{
|
||||
Port: "7348",
|
||||
@@ -32,9 +33,9 @@ func TestLifecycle_OK(t *testing.T) {
|
||||
BlockReceiver: chainService,
|
||||
AttestationReceiver: chainService,
|
||||
HeadFetcher: chainService,
|
||||
GenesisTimeFetcher: chainService,
|
||||
POWChainService: &mockPOW.POWChain{},
|
||||
StateNotifier: chainService.StateNotifier(),
|
||||
ClockProvider: chainService,
|
||||
})
|
||||
|
||||
rpcService.Start()
|
||||
@@ -55,12 +56,12 @@ func TestStatus_CredentialError(t *testing.T) {
|
||||
|
||||
func TestRPC_InsecureEndpoint(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
chainService := &mock.ChainService{Genesis: time.Now()}
|
||||
chainService := &mock.ChainService{Clock: blockchain.NewClock(time.Now())}
|
||||
rpcService := NewService(context.Background(), &Config{
|
||||
Port: "7777",
|
||||
SyncService: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: chainService,
|
||||
GenesisTimeFetcher: chainService,
|
||||
ClockProvider: chainService,
|
||||
AttestationReceiver: chainService,
|
||||
HeadFetcher: chainService,
|
||||
POWChainService: &mockPOW.POWChain{},
|
||||
|
||||
@@ -24,6 +24,7 @@ go_test(
|
||||
srcs = ["fetcher_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
|
||||
@@ -81,9 +81,9 @@ type Fetcher interface {
|
||||
type StateProvider struct {
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
StateGenService stategen.StateManager
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
StateGenService stategen.StateManager
|
||||
CanonicalHistoryWaiter stategen.CanonicalHistoryWaiter
|
||||
ClockProvider blockchain.ClockProvider
|
||||
}
|
||||
|
||||
// State returns the BeaconState for a given identifier. The identifier can be one of:
|
||||
@@ -200,14 +200,22 @@ func (p *StateProvider) StateBySlot(ctx context.Context, target types.Slot) (sta
|
||||
ctx, span := trace.StartSpan(ctx, "statefetcher.StateBySlot")
|
||||
defer span.End()
|
||||
|
||||
if target > p.GenesisTimeFetcher.CurrentSlot() {
|
||||
c, err := p.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "timeout while waiting for genesis timestamp")
|
||||
}
|
||||
if target > c.CurrentSlot() {
|
||||
return nil, errors.New("requested slot is in the future")
|
||||
}
|
||||
if target > p.ChainInfoFetcher.HeadSlot() {
|
||||
return nil, errors.New("requested slot number is higher than head slot number")
|
||||
}
|
||||
|
||||
st, err := p.ReplayerBuilder.ReplayerForSlot(target).ReplayBlocks(ctx)
|
||||
b, err := p.ReplayerBuilder(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err := b.ReplayerForSlot(target).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("error while replaying history to slot=%d", target)
|
||||
return nil, errors.Wrap(err, msg)
|
||||
@@ -285,7 +293,11 @@ func (p *StateProvider) stateRootByHex(ctx context.Context, stateId []byte) ([]b
|
||||
}
|
||||
|
||||
func (p *StateProvider) stateRootBySlot(ctx context.Context, slot types.Slot) ([]byte, error) {
|
||||
currentSlot := p.GenesisTimeFetcher.CurrentSlot()
|
||||
c, err := p.ClockProvider.WaitForClock(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "timeout waiting for genesis time")
|
||||
}
|
||||
currentSlot := c.CurrentSlot()
|
||||
if slot > currentSlot {
|
||||
return nil, errors.New("slot cannot be in the future")
|
||||
}
|
||||
@@ -304,3 +316,7 @@ func (p *StateProvider) stateRootBySlot(ctx context.Context, slot types.Slot) ([
|
||||
}
|
||||
return blks[0].Block().StateRoot(), nil
|
||||
}
|
||||
|
||||
func (p *StateProvider) ReplayerBuilder(ctx context.Context) (stategen.ReplayerBuilder, error) {
|
||||
return p.CanonicalHistoryWaiter.WaitForCanonicalHistory(ctx)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user