mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
21 Commits
fix-proces
...
race-condi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9de96e8716 | ||
|
|
cc643ac4cc | ||
|
|
abefe1e9d5 | ||
|
|
b4e89fb28b | ||
|
|
4ad1c4df01 | ||
|
|
6a197b47d9 | ||
|
|
d102421a25 | ||
|
|
7b1490429c | ||
|
|
bbdf19cfd0 | ||
|
|
5d94030b4f | ||
|
|
16273a2040 | ||
|
|
97663548a1 | ||
|
|
7d9d8454b1 | ||
|
|
21bdbd548a | ||
|
|
e2caaf972f | ||
|
|
c5ddc266ae | ||
|
|
74518f0e1b | ||
|
|
122c3f44cc | ||
|
|
b1b13cfca7 | ||
|
|
495013e832 | ||
|
|
ae82c17dc3 |
12
.github/workflows/go.yml
vendored
12
.github/workflows/go.yml
vendored
@@ -38,10 +38,10 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Go 1.17
|
||||
- name: Set up Go 1.18
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
- name: Run Gosec Security Scanner
|
||||
run: | # https://github.com/securego/gosec/issues/469
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
@@ -55,16 +55,16 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go 1.17
|
||||
- name: Set up Go 1.18
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
id: go
|
||||
|
||||
- name: Golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
args: --print-issued-lines --sort-results --no-config --timeout=10m --disable-all -E deadcode -E errcheck -E gosimple --skip-files=validator/web/site_data.go --skip-dirs=proto --go=1.17
|
||||
args: --print-issued-lines --sort-results --no-config --timeout=10m --disable-all -E deadcode -E errcheck -E gosimple --skip-files=validator/web/site_data.go --skip-dirs=proto --go=1.18
|
||||
version: v1.45.2
|
||||
skip-go-installation: true
|
||||
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
|
||||
@@ -31,6 +31,12 @@ type ChainInfoFetcher interface {
|
||||
HeadDomainFetcher
|
||||
}
|
||||
|
||||
// HeadUpdater defines a common interface for methods in blockchain service
|
||||
// which allow to update the head info
|
||||
type HeadUpdater interface {
|
||||
UpdateHead(context.Context) error
|
||||
}
|
||||
|
||||
// TimeFetcher retrieves the Ethereum consensus data that's related to time.
|
||||
type TimeFetcher interface {
|
||||
GenesisTime() time.Time
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
|
||||
|
||||
cp := ðpb.Checkpoint{Epoch: 5, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||
c := setupBeaconChain(t, beaconDB)
|
||||
c.store.SetFinalizedCheckpt(cp)
|
||||
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
||||
|
||||
assert.Equal(t, cp.Epoch, c.FinalizedCheckpt().Epoch, "Unexpected finalized epoch")
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
genesisRoot := [32]byte{'A'}
|
||||
cp := ðpb.Checkpoint{Root: genesisRoot[:]}
|
||||
c := setupBeaconChain(t, beaconDB)
|
||||
c.store.SetFinalizedCheckpt(cp)
|
||||
c.store.SetFinalizedCheckptAndPayloadHash(cp, [32]byte{'a'})
|
||||
c.originBlockRoot = genesisRoot
|
||||
assert.DeepEqual(t, c.originBlockRoot[:], c.FinalizedCheckpt().Root)
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
||||
c := setupBeaconChain(t, beaconDB)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch")
|
||||
cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||
c.store.SetJustifiedCheckpt(cp)
|
||||
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
||||
assert.Equal(t, cp.Epoch, c.CurrentJustifiedCheckpt().Epoch, "Unexpected justified epoch")
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
c := setupBeaconChain(t, beaconDB)
|
||||
genesisRoot := [32]byte{'B'}
|
||||
cp := ðpb.Checkpoint{Root: genesisRoot[:]}
|
||||
c.store.SetJustifiedCheckpt(cp)
|
||||
c.store.SetJustifiedCheckptAndPayloadHash(cp, [32]byte{})
|
||||
c.originBlockRoot = genesisRoot
|
||||
assert.DeepEqual(t, c.originBlockRoot[:], c.CurrentJustifiedCheckpt().Root)
|
||||
}
|
||||
|
||||
@@ -31,11 +31,9 @@ var (
|
||||
|
||||
// notifyForkchoiceUpdateArg is the argument for the forkchoice update notification `notifyForkchoiceUpdate`.
|
||||
type notifyForkchoiceUpdateArg struct {
|
||||
headState state.BeaconState
|
||||
headRoot [32]byte
|
||||
headBlock interfaces.BeaconBlock
|
||||
finalizedRoot [32]byte
|
||||
justifiedRoot [32]byte
|
||||
headState state.BeaconState
|
||||
headRoot [32]byte
|
||||
headBlock interfaces.BeaconBlock
|
||||
}
|
||||
|
||||
// notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should:
|
||||
@@ -61,18 +59,12 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
finalizedHash, err := s.getPayloadHash(ctx, arg.finalizedRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized block hash")
|
||||
}
|
||||
justifiedHash, err := s.getPayloadHash(ctx, arg.justifiedRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get justified block hash")
|
||||
}
|
||||
finalizedHash := s.store.FinalizedPayloadBlockHash()
|
||||
justifiedHash := s.store.JustifiedPayloadBlockHash()
|
||||
fcs := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: headPayload.BlockHash,
|
||||
SafeBlockHash: justifiedHash,
|
||||
FinalizedBlockHash: finalizedHash,
|
||||
SafeBlockHash: justifiedHash[:],
|
||||
FinalizedBlockHash: finalizedHash[:],
|
||||
}
|
||||
|
||||
nextSlot := s.CurrentSlot() + 1 // Cache payload ID for next slot proposer.
|
||||
@@ -89,10 +81,11 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
log.WithFields(logrus.Fields{
|
||||
"headSlot": headBlk.Slot(),
|
||||
"headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash)),
|
||||
"finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash)),
|
||||
"finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash[:])),
|
||||
}).Info("Called fork choice updated with optimistic block")
|
||||
return payloadID, s.optimisticCandidateBlock(ctx, headBlk)
|
||||
case powchain.ErrInvalidPayloadStatus:
|
||||
newPayloadInvalidNodeCount.Inc()
|
||||
headRoot := arg.headRoot
|
||||
invalidRoots, err := s.ForkChoicer().SetOptimisticToInvalid(ctx, headRoot, bytesutil.ToBytes32(headBlk.ParentRoot()), bytesutil.ToBytes32(lastValidHash))
|
||||
if err != nil {
|
||||
@@ -101,12 +94,35 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
if err := s.removeInvalidBlockAndState(ctx, invalidRoots); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := s.updateHead(ctx, s.justifiedBalances.balances)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := s.getBlock(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err := s.cfg.StateGen.StateByRoot(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pid, err := s.notifyForkchoiceUpdate(ctx, ¬ifyForkchoiceUpdateArg{
|
||||
headState: st,
|
||||
headRoot: r,
|
||||
headBlock: b.Block(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": headBlk.Slot(),
|
||||
"blockRoot": fmt.Sprintf("%#x", headRoot),
|
||||
"invalidCount": len(invalidRoots),
|
||||
}).Warn("Pruned invalid blocks")
|
||||
return nil, ErrInvalidPayload
|
||||
return pid, ErrInvalidPayload
|
||||
|
||||
default:
|
||||
return nil, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error())
|
||||
}
|
||||
@@ -125,19 +141,19 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
|
||||
// getPayloadHash returns the payload hash given the block root.
|
||||
// if the block is before bellatrix fork epoch, it returns the zero hash.
|
||||
func (s *Service) getPayloadHash(ctx context.Context, root [32]byte) ([]byte, error) {
|
||||
finalizedBlock, err := s.getBlock(ctx, s.ensureRootNotZeros(root))
|
||||
func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, error) {
|
||||
blk, err := s.getBlock(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(root)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return [32]byte{}, err
|
||||
}
|
||||
if blocks.IsPreBellatrixVersion(finalizedBlock.Block().Version()) {
|
||||
return params.BeaconConfig().ZeroHash[:], nil
|
||||
if blocks.IsPreBellatrixVersion(blk.Block().Version()) {
|
||||
return params.BeaconConfig().ZeroHash, nil
|
||||
}
|
||||
payload, err := finalizedBlock.Block().Body().ExecutionPayload()
|
||||
payload, err := blk.Block().Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
return [32]byte{}, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
return payload.BlockHash, nil
|
||||
return bytesutil.ToBytes32(payload.BlockHash), nil
|
||||
}
|
||||
|
||||
// notifyForkchoiceUpdate signals execution engine on a new payload.
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
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/powchain"
|
||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||
@@ -174,12 +175,15 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
service.cfg.ExecutionEngineCaller = &mockPOW.EngineClient{ErrForkchoiceUpdated: tt.newForkchoiceErr}
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
||||
fc := ðpb.Checkpoint{Epoch: 1, Root: tt.finalizedRoot[:]}
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'})
|
||||
arg := ¬ifyForkchoiceUpdateArg{
|
||||
headState: st,
|
||||
headRoot: tt.headRoot,
|
||||
headBlock: tt.blk,
|
||||
finalizedRoot: tt.finalizedRoot,
|
||||
justifiedRoot: tt.justifiedRoot,
|
||||
headState: st,
|
||||
headRoot: tt.headRoot,
|
||||
headBlock: tt.blk,
|
||||
}
|
||||
_, err := service.notifyForkchoiceUpdate(ctx, arg)
|
||||
if tt.errString != "" {
|
||||
@@ -191,6 +195,147 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// A <- B <- C <- D
|
||||
// \
|
||||
// ---------- E <- F
|
||||
// \
|
||||
// ------ G
|
||||
// D is the current head, attestations for F and G come late, both are invalid.
|
||||
// We switch recursively to F then G and finally to D.
|
||||
//
|
||||
// We test:
|
||||
// 1. forkchoice removes blocks F and G from the forkchoice implementation
|
||||
// 2. forkchoice removes the weights of these blocks
|
||||
// 3. the blockchain package calls fcu to obtain heads G -> F -> D.
|
||||
|
||||
func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
// Prepare blocks
|
||||
ba := util.NewBeaconBlockBellatrix()
|
||||
ba.Block.Body.ExecutionPayload.BlockNumber = 1
|
||||
wba, err := wrapper.WrappedSignedBeaconBlock(ba)
|
||||
require.NoError(t, err)
|
||||
bra, err := wba.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wba))
|
||||
|
||||
bb := util.NewBeaconBlockBellatrix()
|
||||
bb.Block.Body.ExecutionPayload.BlockNumber = 2
|
||||
wbb, err := wrapper.WrappedSignedBeaconBlock(bb)
|
||||
require.NoError(t, err)
|
||||
brb, err := wbb.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbb))
|
||||
|
||||
bc := util.NewBeaconBlockBellatrix()
|
||||
bc.Block.Body.ExecutionPayload.BlockNumber = 3
|
||||
wbc, err := wrapper.WrappedSignedBeaconBlock(bc)
|
||||
require.NoError(t, err)
|
||||
brc, err := wbc.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbc))
|
||||
|
||||
bd := util.NewBeaconBlockBellatrix()
|
||||
pd := [32]byte{'D'}
|
||||
bd.Block.Body.ExecutionPayload.BlockHash = pd[:]
|
||||
bd.Block.Body.ExecutionPayload.BlockNumber = 4
|
||||
wbd, err := wrapper.WrappedSignedBeaconBlock(bd)
|
||||
require.NoError(t, err)
|
||||
brd, err := wbd.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbd))
|
||||
|
||||
be := util.NewBeaconBlockBellatrix()
|
||||
pe := [32]byte{'E'}
|
||||
be.Block.Body.ExecutionPayload.BlockHash = pe[:]
|
||||
be.Block.Body.ExecutionPayload.BlockNumber = 5
|
||||
wbe, err := wrapper.WrappedSignedBeaconBlock(be)
|
||||
require.NoError(t, err)
|
||||
bre, err := wbe.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbe))
|
||||
|
||||
bf := util.NewBeaconBlockBellatrix()
|
||||
pf := [32]byte{'F'}
|
||||
bf.Block.Body.ExecutionPayload.BlockHash = pf[:]
|
||||
bf.Block.Body.ExecutionPayload.BlockNumber = 6
|
||||
bf.Block.ParentRoot = bre[:]
|
||||
wbf, err := wrapper.WrappedSignedBeaconBlock(bf)
|
||||
require.NoError(t, err)
|
||||
brf, err := wbf.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbf))
|
||||
|
||||
bg := util.NewBeaconBlockBellatrix()
|
||||
bg.Block.Body.ExecutionPayload.BlockNumber = 7
|
||||
pg := [32]byte{'G'}
|
||||
bg.Block.Body.ExecutionPayload.BlockHash = pg[:]
|
||||
bg.Block.ParentRoot = bre[:]
|
||||
wbg, err := wrapper.WrappedSignedBeaconBlock(bg)
|
||||
require.NoError(t, err)
|
||||
brg, err := wbg.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbg))
|
||||
|
||||
// Insert blocks into forkchoice
|
||||
fcs := doublylinkedtree.New(0, 0)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithForkChoiceStore(fcs),
|
||||
WithProposerIdsCache(cache.NewProposerPayloadIDsCache()),
|
||||
}
|
||||
service, err := NewService(ctx, opts...)
|
||||
service.justifiedBalances.balances = []uint64{50, 100, 200}
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 1, bra, [32]byte{}, [32]byte{'A'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 2, brb, bra, [32]byte{'B'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 3, brc, brb, [32]byte{'C'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 4, brd, brc, [32]byte{'D'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 5, bre, brb, [32]byte{'E'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 6, brf, bre, [32]byte{'F'}, 0, 0))
|
||||
require.NoError(t, fcs.InsertOptimisticBlock(ctx, 7, brg, bre, [32]byte{'G'}, 0, 0))
|
||||
|
||||
// Insert Attestations to D, F and G so that they have higher weight than D
|
||||
// Ensure G is head
|
||||
fcs.ProcessAttestation(ctx, []uint64{0}, brd, 1)
|
||||
fcs.ProcessAttestation(ctx, []uint64{1}, brf, 1)
|
||||
fcs.ProcessAttestation(ctx, []uint64{2}, brg, 1)
|
||||
headRoot, err := fcs.Head(ctx, 0, bra, []uint64{50, 100, 200}, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brg, headRoot)
|
||||
|
||||
// Prepare Engine Mock to return invalid unless head is D, LVH = E
|
||||
service.cfg.ExecutionEngineCaller = &mockPOW.EngineClient{ErrForkchoiceUpdated: powchain.ErrInvalidPayloadStatus, ForkChoiceUpdatedResp: pe[:], OverrideValidHash: [32]byte{'D'}}
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
||||
fc := ðpb.Checkpoint{Epoch: 0, Root: bra[:]}
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'})
|
||||
a := ¬ifyForkchoiceUpdateArg{
|
||||
headState: st,
|
||||
headBlock: wbg.Block(),
|
||||
headRoot: brg,
|
||||
}
|
||||
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
||||
require.ErrorIs(t, ErrInvalidPayload, err)
|
||||
// Ensure Head is D
|
||||
headRoot, err = fcs.Head(ctx, 0, bra, service.justifiedBalances.balances, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, brd, headRoot)
|
||||
|
||||
// Ensure F and G where removed but their parent E wasn't
|
||||
require.Equal(t, false, fcs.HasNode(brf))
|
||||
require.Equal(t, false, fcs.HasNode(brg))
|
||||
require.Equal(t, true, fcs.HasNode(bre))
|
||||
}
|
||||
|
||||
func Test_NotifyNewPayload(t *testing.T) {
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.TerminalTotalDifficulty = "2"
|
||||
@@ -537,11 +682,11 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) {
|
||||
jRoot, err := tt.justified.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, tt.justified))
|
||||
service.store.SetJustifiedCheckpt(
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(
|
||||
ðpb.Checkpoint{
|
||||
Root: jRoot[:],
|
||||
Epoch: slots.ToEpoch(tt.justified.Block().Slot()),
|
||||
})
|
||||
}, [32]byte{'a'})
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrappedParentBlock))
|
||||
|
||||
err = service.optimisticCandidateBlock(ctx, tt.blk)
|
||||
@@ -803,7 +948,7 @@ func TestService_getPayloadHash(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = service.getPayloadHash(ctx, [32]byte{})
|
||||
_, err = service.getPayloadHash(ctx, []byte{})
|
||||
require.ErrorIs(t, errBlockNotFoundInCacheOrDB, err)
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
@@ -813,20 +958,20 @@ func TestService_getPayloadHash(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(r, wsb)
|
||||
|
||||
h, err := service.getPayloadHash(ctx, r)
|
||||
h, err := service.getPayloadHash(ctx, r[:])
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], h)
|
||||
require.DeepEqual(t, params.BeaconConfig().ZeroHash, h)
|
||||
|
||||
bb := util.NewBeaconBlockBellatrix()
|
||||
h = []byte{'a'}
|
||||
bb.Block.Body.ExecutionPayload.BlockHash = h
|
||||
h = [32]byte{'a'}
|
||||
bb.Block.Body.ExecutionPayload.BlockHash = h[:]
|
||||
r, err = b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(bb)
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock(r, wsb)
|
||||
|
||||
h, err = service.getPayloadHash(ctx, r)
|
||||
h, err = service.getPayloadHash(ctx, r[:])
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, []byte{'a'}, h)
|
||||
require.DeepEqual(t, [32]byte{'a'}, h)
|
||||
}
|
||||
|
||||
@@ -154,8 +154,8 @@ func TestUpdateHead_MissingJustifiedRoot(t *testing.T) {
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{'b'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{})
|
||||
headRoot, err := service.updateHead(context.Background(), []uint64{})
|
||||
require.NoError(t, err)
|
||||
@@ -298,8 +298,8 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
|
||||
Root: bellatrixBlkRoot[:],
|
||||
Epoch: 1,
|
||||
}
|
||||
service.store.SetFinalizedCheckpt(fcp)
|
||||
service.store.SetJustifiedCheckpt(fcp)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(fcp, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(fcp, [32]byte{'b'})
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bellatrixBlkRoot))
|
||||
|
||||
bellatrixState, _ := util.DeterministicGenesisStateBellatrix(t, 2)
|
||||
|
||||
@@ -64,7 +64,11 @@ func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
||||
return err
|
||||
}
|
||||
if bytes.Equal(r, f.Root) {
|
||||
s.store.SetJustifiedCheckpt(bj)
|
||||
h, err := s.getPayloadHash(ctx, bj.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(bj, h)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -324,9 +324,9 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
r := [32]byte{'g'}
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, r))
|
||||
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'b'})
|
||||
service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
|
||||
r = bytesutil.ToBytes32([]byte{'A'})
|
||||
@@ -358,9 +358,9 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
assert.Equal(t, 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot(), "Unexpected state slot")
|
||||
|
||||
require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'b'})
|
||||
service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: r[:]})
|
||||
cp3 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, fieldparams.RootLength)}
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})))
|
||||
@@ -500,7 +500,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_ProtoArray(t *testing.T) {
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{})
|
||||
b33 := util.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
@@ -535,7 +535,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_DoublyLinkedTree(t *testing
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{})
|
||||
b33 := util.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
@@ -564,7 +564,7 @@ func TestVerifyFinalizedConsistency_OK(t *testing.T) {
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r32[:], Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r32[:], Epoch: 1}, [32]byte{})
|
||||
|
||||
b33 := util.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
@@ -591,7 +591,7 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: r32[:], Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r32[:], Epoch: 1}, [32]byte{})
|
||||
|
||||
b33 := util.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
|
||||
@@ -127,7 +127,7 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, signed.Block(), blockRoot, postState); err != nil {
|
||||
return errors.Wrapf(err, "could not insert block %d to fork choice store", signed.Block().Slot())
|
||||
}
|
||||
s.insertSlashingsToForkChoiceStore(ctx, signed.Block())
|
||||
s.insertSlashingsToForkChoiceStore(ctx, signed.Block().Body().AttesterSlashings())
|
||||
if isValidPayload {
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, blockRoot); err != nil {
|
||||
return errors.Wrap(err, "could not set optimistic block to valid")
|
||||
@@ -195,9 +195,19 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
||||
newFinalized := postState.FinalizedCheckpointEpoch() > finalized.Epoch
|
||||
if newFinalized {
|
||||
s.store.SetPrevFinalizedCheckpt(finalized)
|
||||
s.store.SetFinalizedCheckpt(postState.FinalizedCheckpoint())
|
||||
cp := postState.FinalizedCheckpoint()
|
||||
h, err := s.getPayloadHash(ctx, cp.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(cp, h)
|
||||
s.store.SetPrevJustifiedCheckpt(justified)
|
||||
s.store.SetJustifiedCheckpt(postState.CurrentJustifiedCheckpoint())
|
||||
cp = postState.CurrentJustifiedCheckpoint()
|
||||
h, err = s.getPayloadHash(ctx, cp.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h)
|
||||
}
|
||||
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
||||
@@ -413,6 +423,10 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
}
|
||||
}
|
||||
s.saveInitSyncBlock(blockRoots[i], b)
|
||||
if err = s.handleBlockAfterBatchVerify(ctx, b, blockRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for r, st := range boundaries {
|
||||
@@ -426,14 +440,10 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
||||
if err := s.cfg.StateGen.SaveState(ctx, lastBR, preState); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
f := fCheckpoints[len(fCheckpoints)-1]
|
||||
j := jCheckpoints[len(jCheckpoints)-1]
|
||||
arg := ¬ifyForkchoiceUpdateArg{
|
||||
headState: preState,
|
||||
headRoot: lastBR,
|
||||
headBlock: lastB.Block(),
|
||||
finalizedRoot: bytesutil.ToBytes32(f.Root),
|
||||
justifiedRoot: bytesutil.ToBytes32(j.Root),
|
||||
headState: preState,
|
||||
headRoot: lastBR,
|
||||
headBlock: lastB.Block(),
|
||||
}
|
||||
if _, err := s.notifyForkchoiceUpdate(ctx, arg); err != nil {
|
||||
return nil, nil, err
|
||||
@@ -484,7 +494,11 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
|
||||
return err
|
||||
}
|
||||
s.store.SetPrevFinalizedCheckpt(finalized)
|
||||
s.store.SetFinalizedCheckpt(fCheckpoint)
|
||||
h, err := s.getPayloadHash(ctx, fCheckpoint.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(fCheckpoint, h)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -495,15 +509,15 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState state.Beaco
|
||||
defer span.End()
|
||||
|
||||
if postState.Slot()+1 == s.nextEpochBoundarySlot {
|
||||
// Update caches for the next epoch at epoch boundary slot - 1.
|
||||
if err := helpers.UpdateCommitteeCache(postState, coreTime.NextEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
copied := postState.Copy()
|
||||
copied, err := transition.ProcessSlots(ctx, copied, copied.Slot()+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Update caches for the next epoch at epoch boundary slot - 1.
|
||||
if err := helpers.UpdateCommitteeCache(copied, coreTime.CurrentEpoch(copied)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(ctx, copied); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -576,8 +590,7 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk interfac
|
||||
|
||||
// Inserts attester slashing indices to fork choice store.
|
||||
// To call this function, it's caller's responsibility to ensure the slashing object is valid.
|
||||
func (s *Service) insertSlashingsToForkChoiceStore(ctx context.Context, blk interfaces.BeaconBlock) {
|
||||
slashings := blk.Body().AttesterSlashings()
|
||||
func (s *Service) insertSlashingsToForkChoiceStore(ctx context.Context, slashings []*ethpb.AttesterSlashing) {
|
||||
for _, slashing := range slashings {
|
||||
indices := blocks.SlashableAttesterIndices(slashing)
|
||||
for _, index := range indices {
|
||||
|
||||
@@ -208,7 +208,11 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
||||
return errNilJustifiedInStore
|
||||
}
|
||||
s.store.SetPrevJustifiedCheckpt(justified)
|
||||
s.store.SetJustifiedCheckpt(cpt)
|
||||
h, err := s.getPayloadHash(ctx, cpt.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(cpt, h)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -227,7 +231,11 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo
|
||||
if err := s.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, cp); err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckpt(cp)
|
||||
h, err := s.getPayloadHash(ctx, cp.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.store.SetJustifiedCheckptAndPayloadHash(cp, h)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ func TestStore_OnBlock_ProtoArray(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: validGenesisRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: roots[0]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: roots[0]}, [32]byte{'b'})
|
||||
service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
|
||||
root, err := tt.blk.Block.HashTreeRoot()
|
||||
@@ -232,9 +232,9 @@ func TestStore_OnBlock_DoublyLinkedTree(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: validGenesisRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: roots[0]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: roots[0]}, [32]byte{'b'})
|
||||
service.store.SetPrevFinalizedCheckpt(ðpb.Checkpoint{Root: validGenesisRoot[:]})
|
||||
|
||||
root, err := tt.blk.Block.HashTreeRoot()
|
||||
@@ -289,7 +289,8 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
@@ -353,7 +354,8 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
@@ -415,7 +417,9 @@ func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.saveInitSyncBlock(gRoot, wsb)
|
||||
st, keys := util.DeterministicGenesisState(t, 64)
|
||||
@@ -484,7 +488,7 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'})
|
||||
update, err = service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, update, "Should be able to update justified")
|
||||
@@ -516,7 +520,7 @@ func TestShouldUpdateJustified_ReturnFalse_ProtoArray(t *testing.T) {
|
||||
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'})
|
||||
|
||||
update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]})
|
||||
require.NoError(t, err)
|
||||
@@ -549,7 +553,7 @@ func TestShouldUpdateJustified_ReturnFalse_DoublyLinkedTree(t *testing.T) {
|
||||
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: lastJustifiedRoot[:]})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: lastJustifiedRoot[:]}, [32]byte{'a'})
|
||||
|
||||
update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]})
|
||||
require.NoError(t, err)
|
||||
@@ -577,7 +581,7 @@ func TestCachedPreState_CanGetFromStateSummary_ProtoArray(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
@@ -614,7 +618,7 @@ func TestCachedPreState_CanGetFromStateSummary_DoublyLinkedTree(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
@@ -648,7 +652,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
gRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||
require.NoError(t, err)
|
||||
@@ -656,7 +660,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 1
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
wb, err := wrapper.WrappedBeaconBlock(b.Block)
|
||||
require.NoError(t, err)
|
||||
err = service.verifyBlkPreState(ctx, wb)
|
||||
@@ -691,7 +695,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wsb))
|
||||
r, err := signedBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}})
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: []byte{'A'}}, [32]byte{'a'})
|
||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{Root: []byte{'A'}})
|
||||
st, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
@@ -723,7 +727,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -768,7 +772,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_DoublyLinkedTree(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -814,7 +818,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_ProtoArray(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -863,7 +867,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_DoublyLinkedTree(t *testing.T) {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: make([]byte, 32)}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -913,7 +917,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_ProtoArray(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
// Set finalized epoch to 1.
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -974,7 +978,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_DoublyLinkedTree(t *testing
|
||||
require.NoError(t, err)
|
||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
||||
// Set finalized epoch to 1.
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 1})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 1}, [32]byte{})
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -1350,7 +1354,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: tt.args.finalizedRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: tt.args.finalizedRoot[:]}, [32]byte{})
|
||||
err = service.VerifyFinalizedBlkDescendant(ctx, tt.args.parentRoot)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
@@ -1378,7 +1382,7 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot))
|
||||
service.originBlockRoot = gRoot
|
||||
currentCp := ðpb.Checkpoint{Epoch: 1}
|
||||
service.store.SetJustifiedCheckpt(currentCp)
|
||||
service.store.SetJustifiedCheckptAndPayloadHash(currentCp, [32]byte{'a'})
|
||||
newCp := ðpb.Checkpoint{Epoch: 2, Root: gRoot[:]}
|
||||
|
||||
require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
|
||||
@@ -1439,7 +1443,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
|
||||
testState := gs.Copy()
|
||||
for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
@@ -1493,7 +1497,7 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
|
||||
testState := gs.Copy()
|
||||
for i := types.Slot(1); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
@@ -1524,7 +1528,7 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(8))
|
||||
@@ -1563,7 +1567,7 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 7}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(6))
|
||||
@@ -1885,5 +1889,5 @@ func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
||||
b.Block.Body.AttesterSlashings = slashings
|
||||
wb, err := wrapper.WrappedSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
service.insertSlashingsToForkChoiceStore(ctx, wb.Block())
|
||||
service.insertSlashingsToForkChoiceStore(ctx, wb.Block().Body().AttesterSlashings())
|
||||
}
|
||||
|
||||
@@ -128,39 +128,52 @@ func (s *Service) spawnProcessAttestationsRoutine(stateFeed *event.Feed) {
|
||||
return
|
||||
}
|
||||
|
||||
// Continue when there's no fork choice attestation, there's nothing to process and update head.
|
||||
// This covers the condition when the node is still initial syncing to the head of the chain.
|
||||
if s.cfg.AttPool.ForkchoiceAttestationCount() == 0 {
|
||||
continue
|
||||
if err := s.UpdateHead(s.ctx); err != nil {
|
||||
log.WithError(err).Error("Could not process attestations and update head")
|
||||
return
|
||||
}
|
||||
s.processAttestations(s.ctx)
|
||||
|
||||
justified := s.store.JustifiedCheckpt()
|
||||
if justified == nil {
|
||||
log.WithError(errNilJustifiedInStore).Error("Could not get justified checkpoint")
|
||||
continue
|
||||
}
|
||||
balances, err := s.justifiedBalances.get(s.ctx, bytesutil.ToBytes32(justified.Root))
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Unable to get justified balances for root %v", justified.Root)
|
||||
continue
|
||||
}
|
||||
newHeadRoot, err := s.updateHead(s.ctx, balances)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Resolving fork due to new attestation")
|
||||
}
|
||||
if s.headRoot() != newHeadRoot {
|
||||
log.WithFields(logrus.Fields{
|
||||
"oldHeadRoot": fmt.Sprintf("%#x", s.headRoot()),
|
||||
"newHeadRoot": fmt.Sprintf("%#x", newHeadRoot),
|
||||
}).Debug("Head changed due to attestations")
|
||||
}
|
||||
s.notifyEngineIfChangedHead(s.ctx, newHeadRoot)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// UpdateHead updates the canonical head of the chain based on information from fork-choice attestations and votes.
|
||||
// It requires no external inputs.
|
||||
func (s *Service) UpdateHead(ctx context.Context) error {
|
||||
// Continue when there's no fork choice attestation, there's nothing to process and update head.
|
||||
// This covers the condition when the node is still initial syncing to the head of the chain.
|
||||
if s.cfg.AttPool.ForkchoiceAttestationCount() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Only one process can process attestations and update head at a time.
|
||||
s.processAttestationsLock.Lock()
|
||||
defer s.processAttestationsLock.Unlock()
|
||||
|
||||
s.processAttestations(ctx)
|
||||
|
||||
justified := s.store.JustifiedCheckpt()
|
||||
if justified == nil {
|
||||
return errNilJustifiedInStore
|
||||
}
|
||||
balances, err := s.justifiedBalances.get(ctx, bytesutil.ToBytes32(justified.Root))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newHeadRoot, err := s.updateHead(ctx, balances)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Resolving fork due to new attestation")
|
||||
}
|
||||
if s.headRoot() != newHeadRoot {
|
||||
log.WithFields(logrus.Fields{
|
||||
"oldHeadRoot": fmt.Sprintf("%#x", s.headRoot()),
|
||||
"newHeadRoot": fmt.Sprintf("%#x", newHeadRoot),
|
||||
}).Debug("Head changed due to attestations")
|
||||
}
|
||||
s.notifyEngineIfChangedHead(ctx, newHeadRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
// This calls notify Forkchoice Update in the event that the head has changed
|
||||
func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32]byte) {
|
||||
if s.headRoot() == newHeadRoot {
|
||||
@@ -172,12 +185,6 @@ func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32
|
||||
return // We don't have the block, don't notify the engine and update head.
|
||||
}
|
||||
|
||||
finalized := s.store.FinalizedCheckpt()
|
||||
if finalized == nil {
|
||||
log.WithError(errNilFinalizedInStore).Error("could not get finalized checkpoint")
|
||||
return
|
||||
}
|
||||
|
||||
newHeadBlock, err := s.getBlock(ctx, newHeadRoot)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get new head block")
|
||||
@@ -189,11 +196,9 @@ func (s *Service) notifyEngineIfChangedHead(ctx context.Context, newHeadRoot [32
|
||||
return
|
||||
}
|
||||
arg := ¬ifyForkchoiceUpdateArg{
|
||||
headState: headState,
|
||||
headRoot: newHeadRoot,
|
||||
headBlock: newHeadBlock.Block(),
|
||||
finalizedRoot: bytesutil.ToBytes32(finalized.Root),
|
||||
justifiedRoot: bytesutil.ToBytes32(s.store.JustifiedCheckpt().Root),
|
||||
headState: headState,
|
||||
headRoot: newHeadRoot,
|
||||
headBlock: newHeadBlock.Block(),
|
||||
}
|
||||
_, err = s.notifyForkchoiceUpdate(s.ctx, arg)
|
||||
if err != nil {
|
||||
|
||||
@@ -137,14 +137,14 @@ func TestNotifyEngineIfChangedHead(t *testing.T) {
|
||||
service.cfg.ProposerSlotIndexCache = cache.NewProposerPayloadIDsCache()
|
||||
service.notifyEngineIfChangedHead(ctx, service.headRoot())
|
||||
hookErr := "could not notify forkchoice update"
|
||||
finalizedErr := "could not get finalized checkpoint"
|
||||
require.LogsDoNotContain(t, hook, finalizedErr)
|
||||
invalidStateErr := "Could not get state from db"
|
||||
require.LogsDoNotContain(t, hook, invalidStateErr)
|
||||
require.LogsDoNotContain(t, hook, hookErr)
|
||||
gb, err := wrapper.WrappedSignedBeaconBlock(util.NewBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
service.saveInitSyncBlock([32]byte{'a'}, gb)
|
||||
service.notifyEngineIfChangedHead(ctx, [32]byte{'a'})
|
||||
require.LogsContain(t, hook, finalizedErr)
|
||||
require.LogsContain(t, hook, invalidStateErr)
|
||||
|
||||
hook.Reset()
|
||||
service.head = &head{
|
||||
@@ -169,9 +169,9 @@ func TestNotifyEngineIfChangedHead(t *testing.T) {
|
||||
state: st,
|
||||
}
|
||||
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(2, 1, [8]byte{1})
|
||||
service.store.SetFinalizedCheckpt(finalized)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(finalized, [32]byte{})
|
||||
service.notifyEngineIfChangedHead(ctx, r1)
|
||||
require.LogsDoNotContain(t, hook, finalizedErr)
|
||||
require.LogsDoNotContain(t, hook, invalidStateErr)
|
||||
require.LogsDoNotContain(t, hook, hookErr)
|
||||
|
||||
// Block in DB
|
||||
@@ -191,12 +191,46 @@ func TestNotifyEngineIfChangedHead(t *testing.T) {
|
||||
state: st,
|
||||
}
|
||||
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(2, 1, [8]byte{1})
|
||||
service.store.SetFinalizedCheckpt(finalized)
|
||||
service.store.SetFinalizedCheckptAndPayloadHash(finalized, [32]byte{})
|
||||
service.notifyEngineIfChangedHead(ctx, r1)
|
||||
require.LogsDoNotContain(t, hook, finalizedErr)
|
||||
require.LogsDoNotContain(t, hook, invalidStateErr)
|
||||
require.LogsDoNotContain(t, hook, hookErr)
|
||||
vId, payloadID, has := service.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(2)
|
||||
require.Equal(t, true, has)
|
||||
require.Equal(t, types.ValidatorIndex(1), vId)
|
||||
require.Equal(t, [8]byte{1}, payloadID)
|
||||
}
|
||||
|
||||
func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
opts := testServiceOptsWithDB(t)
|
||||
opts = append(opts, WithAttestationPool(attestations.NewPool()), WithStateNotifier(&mockBeaconNode{}))
|
||||
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
service.genesisTime = 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))
|
||||
atts, err := util.GenerateAttestations(genesisState, pks, 1, 0, false)
|
||||
require.NoError(t, err)
|
||||
tRoot := bytesutil.ToBytes32(atts[0].Data.Target.Root)
|
||||
copied := genesisState.Copy()
|
||||
copied, err = transition.ProcessSlots(ctx, copied, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: tRoot[:]}))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertOptimisticBlock(ctx, 0, tRoot, tRoot, params.BeaconConfig().ZeroHash, 1, 1))
|
||||
require.NoError(t, service.cfg.AttPool.SaveForkchoiceAttestations(atts))
|
||||
b := util.NewBeaconBlock()
|
||||
wb, err := wrapper.WrappedSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wb))
|
||||
service.head.root = r // Old head
|
||||
require.Equal(t, 1, len(service.cfg.AttPool.ForkchoiceAttestations()))
|
||||
require.NoError(t, err, service.UpdateHead(ctx))
|
||||
require.Equal(t, tRoot, service.head.root) // Validate head is the new one
|
||||
require.Equal(t, 0, len(service.cfg.AttPool.ForkchoiceAttestations())) // Validate att pool is empty
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"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"
|
||||
@@ -24,9 +25,14 @@ type BlockReceiver interface {
|
||||
HasBlock(ctx context.Context, root [32]byte) bool
|
||||
}
|
||||
|
||||
// ReceiveBlock is a function that defines the the operations (minus pubsub)
|
||||
// that are performed on blocks that is received from regular sync service. The operations consists of:
|
||||
// 1. Validate block, apply state transition and update check points
|
||||
// SlashingReceiver interface defines the methods of chain service for receiving validated slashing over the wire.
|
||||
type SlashingReceiver interface {
|
||||
ReceiveAttesterSlashing(ctx context.Context, slashings *ethpb.AttesterSlashing)
|
||||
}
|
||||
|
||||
// ReceiveBlock is a function that defines the operations (minus pubsub)
|
||||
// that are performed on a received block. The operations consist of:
|
||||
// 1. Validate block, apply state transition and update checkpoints
|
||||
// 2. Apply fork choice to the processed block
|
||||
// 3. Save latest head info
|
||||
func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
@@ -79,7 +85,7 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig
|
||||
defer span.End()
|
||||
|
||||
// Apply state transition on the incoming newly received block batches, one by one.
|
||||
fCheckpoints, jCheckpoints, err := s.onBlockBatch(ctx, blocks, blkRoots)
|
||||
_, _, err := s.onBlockBatch(ctx, blocks, blkRoots)
|
||||
if err != nil {
|
||||
err := errors.Wrap(err, "could not process block in batch")
|
||||
tracing.AnnotateError(span, err)
|
||||
@@ -88,10 +94,6 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.Sig
|
||||
|
||||
for i, b := range blocks {
|
||||
blockCopy := b.Copy()
|
||||
if err = s.handleBlockAfterBatchVerify(ctx, blockCopy, blkRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
@@ -133,6 +135,11 @@ func (s *Service) HasBlock(ctx context.Context, root [32]byte) bool {
|
||||
return s.hasBlockInInitSyncOrDB(ctx, root)
|
||||
}
|
||||
|
||||
// ReceiveAttesterSlashing receives an attester slashing and inserts it to forkchoice
|
||||
func (s *Service) ReceiveAttesterSlashing(ctx context.Context, slashing *ethpb.AttesterSlashing) {
|
||||
s.insertSlashingsToForkChoiceStore(ctx, []*ethpb.AttesterSlashing{slashing})
|
||||
}
|
||||
|
||||
func (s *Service) handlePostBlockOperations(b interfaces.BeaconBlock) error {
|
||||
// Delete the processed block attestations from attestation pool.
|
||||
if err := s.deletePoolAtts(b.Body().Attestations()); err != nil {
|
||||
|
||||
@@ -141,7 +141,8 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
h := [32]byte{'a'}
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, h)
|
||||
root, err := tt.args.block.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(tt.args.block)
|
||||
@@ -181,7 +182,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
root, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
wg := sync.WaitGroup{}
|
||||
@@ -262,7 +263,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
|
||||
gRoot, err := gBlk.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||
root, err := tt.args.block.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
wsb, err := wrapper.WrappedSignedBeaconBlock(tt.args.block)
|
||||
@@ -312,7 +313,7 @@ func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
|
||||
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)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{})
|
||||
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
assert.LogsContain(t, hook, "Entering mode to save hot states in DB")
|
||||
@@ -323,7 +324,7 @@ func TestCheckSaveHotStateDB_Disabling(t *testing.T) {
|
||||
opts := testServiceOptsWithDB(t)
|
||||
s, err := NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{})
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
s.genesisTime = time.Now()
|
||||
|
||||
@@ -336,7 +337,7 @@ func TestCheckSaveHotStateDB_Overflow(t *testing.T) {
|
||||
opts := testServiceOptsWithDB(t)
|
||||
s, err := NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 10000000})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{})
|
||||
s.genesisTime = time.Now()
|
||||
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
|
||||
@@ -50,21 +50,22 @@ const headSyncMinEpochsAfterCheckpoint = 128
|
||||
// Service represents a service that handles the internal
|
||||
// logic of managing the full PoS beacon chain.
|
||||
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
|
||||
nextEpochBoundarySlot types.Slot
|
||||
boundaryRoots [][32]byte
|
||||
checkpointStateCache *cache.CheckpointStateCache
|
||||
initSyncBlocks map[[32]byte]interfaces.SignedBeaconBlock
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
justifiedBalances *stateBalanceCache
|
||||
wsVerifier *WeakSubjectivityVerifier
|
||||
store *store.Store
|
||||
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
|
||||
nextEpochBoundarySlot types.Slot
|
||||
boundaryRoots [][32]byte
|
||||
checkpointStateCache *cache.CheckpointStateCache
|
||||
initSyncBlocks map[[32]byte]interfaces.SignedBeaconBlock
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
justifiedBalances *stateBalanceCache
|
||||
wsVerifier *WeakSubjectivityVerifier
|
||||
store *store.Store
|
||||
processAttestationsLock sync.Mutex
|
||||
}
|
||||
|
||||
// config options for the service.
|
||||
@@ -143,6 +144,7 @@ func (s *Service) Stop() error {
|
||||
defer s.cancel()
|
||||
|
||||
if s.cfg.StateGen != nil && s.head != nil && s.head.state != nil {
|
||||
// Save the last finalized state so that starting up in the following run will be much faster.
|
||||
if err := s.cfg.StateGen.ForceCheckpoint(s.ctx, s.head.state.FinalizedCheckpoint().Root); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -221,7 +221,8 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
trie, _, err := util.DepositTrieFromDeposits(deposits)
|
||||
require.NoError(t, err)
|
||||
hashTreeRoot := trie.HashTreeRoot()
|
||||
hashTreeRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
genState, err := transition.EmptyGenesisState()
|
||||
require.NoError(t, err)
|
||||
err = genState.SetEth1Data(ðpb.Eth1Data{
|
||||
@@ -500,7 +501,7 @@ func TestHasBlock_ForkChoiceAndDB_ProtoArray(t *testing.T) {
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
b := util.NewBeaconBlock()
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -521,7 +522,7 @@ func TestHasBlock_ForkChoiceAndDB_DoublyLinkedTree(t *testing.T) {
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
b := util.NewBeaconBlock()
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -594,7 +595,7 @@ func BenchmarkHasBlockForkChoiceStore_ProtoArray(b *testing.B) {
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
r, err := blk.Block.HashTreeRoot()
|
||||
require.NoError(b, err)
|
||||
@@ -617,7 +618,7 @@ func BenchmarkHasBlockForkChoiceStore_DoublyLinkedTree(b *testing.B) {
|
||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
||||
store: &store.Store{},
|
||||
}
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||
blk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
r, err := blk.Block.HashTreeRoot()
|
||||
require.NoError(b, err)
|
||||
|
||||
@@ -23,6 +23,13 @@ func (s *Store) JustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return s.justifiedCheckpt
|
||||
}
|
||||
|
||||
// JustifiedPayloadBlockHash returns the justified payload block hash reflecting justified check point.
|
||||
func (s *Store) JustifiedPayloadBlockHash() [32]byte {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return s.justifiedPayloadBlockHash
|
||||
}
|
||||
|
||||
// PrevFinalizedCheckpt returns the previous finalized checkpoint in the Store.
|
||||
func (s *Store) PrevFinalizedCheckpt() *ethpb.Checkpoint {
|
||||
s.RLock()
|
||||
@@ -37,6 +44,13 @@ func (s *Store) FinalizedCheckpt() *ethpb.Checkpoint {
|
||||
return s.finalizedCheckpt
|
||||
}
|
||||
|
||||
// FinalizedPayloadBlockHash returns the finalized payload block hash reflecting finalized check point.
|
||||
func (s *Store) FinalizedPayloadBlockHash() [32]byte {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return s.finalizedPayloadBlockHash
|
||||
}
|
||||
|
||||
// SetPrevJustifiedCheckpt sets the previous justified checkpoint in the Store.
|
||||
func (s *Store) SetPrevJustifiedCheckpt(cp *ethpb.Checkpoint) {
|
||||
s.Lock()
|
||||
@@ -51,18 +65,20 @@ func (s *Store) SetBestJustifiedCheckpt(cp *ethpb.Checkpoint) {
|
||||
s.bestJustifiedCheckpt = cp
|
||||
}
|
||||
|
||||
// SetJustifiedCheckpt sets the justified checkpoint in the Store.
|
||||
func (s *Store) SetJustifiedCheckpt(cp *ethpb.Checkpoint) {
|
||||
// SetJustifiedCheckptAndPayloadHash sets the justified checkpoint and blockhash in the Store.
|
||||
func (s *Store) SetJustifiedCheckptAndPayloadHash(cp *ethpb.Checkpoint, h [32]byte) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.justifiedCheckpt = cp
|
||||
s.justifiedPayloadBlockHash = h
|
||||
}
|
||||
|
||||
// SetFinalizedCheckpt sets the finalized checkpoint in the Store.
|
||||
func (s *Store) SetFinalizedCheckpt(cp *ethpb.Checkpoint) {
|
||||
// SetFinalizedCheckptAndPayloadHash sets the finalized checkpoint and blockhash in the Store.
|
||||
func (s *Store) SetFinalizedCheckptAndPayloadHash(cp *ethpb.Checkpoint, h [32]byte) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.finalizedCheckpt = cp
|
||||
s.finalizedPayloadBlockHash = h
|
||||
}
|
||||
|
||||
// SetPrevFinalizedCheckpt sets the previous finalized checkpoint in the Store.
|
||||
|
||||
@@ -30,8 +30,10 @@ func Test_store_JustifiedCheckpt(t *testing.T) {
|
||||
var cp *ethpb.Checkpoint
|
||||
require.Equal(t, cp, s.JustifiedCheckpt())
|
||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||
s.SetJustifiedCheckpt(cp)
|
||||
h := [32]byte{'b'}
|
||||
s.SetJustifiedCheckptAndPayloadHash(cp, h)
|
||||
require.Equal(t, cp, s.JustifiedCheckpt())
|
||||
require.Equal(t, h, s.JustifiedPayloadBlockHash())
|
||||
}
|
||||
|
||||
func Test_store_FinalizedCheckpt(t *testing.T) {
|
||||
@@ -39,8 +41,10 @@ func Test_store_FinalizedCheckpt(t *testing.T) {
|
||||
var cp *ethpb.Checkpoint
|
||||
require.Equal(t, cp, s.FinalizedCheckpt())
|
||||
cp = ðpb.Checkpoint{Epoch: 1, Root: []byte{'a'}}
|
||||
s.SetFinalizedCheckpt(cp)
|
||||
h := [32]byte{'b'}
|
||||
s.SetFinalizedCheckptAndPayloadHash(cp, h)
|
||||
require.Equal(t, cp, s.FinalizedCheckpt())
|
||||
require.Equal(t, h, s.FinalizedPayloadBlockHash())
|
||||
}
|
||||
|
||||
func Test_store_PrevFinalizedCheckpt(t *testing.T) {
|
||||
|
||||
@@ -17,9 +17,11 @@ import (
|
||||
// best_justified_checkpoint: Checkpoint
|
||||
// proposerBoostRoot: Root
|
||||
type Store struct {
|
||||
justifiedCheckpt *ethpb.Checkpoint
|
||||
finalizedCheckpt *ethpb.Checkpoint
|
||||
bestJustifiedCheckpt *ethpb.Checkpoint
|
||||
justifiedCheckpt *ethpb.Checkpoint
|
||||
justifiedPayloadBlockHash [32]byte
|
||||
finalizedCheckpt *ethpb.Checkpoint
|
||||
finalizedPayloadBlockHash [32]byte
|
||||
bestJustifiedCheckpt *ethpb.Checkpoint
|
||||
sync.RWMutex
|
||||
// These are not part of the consensus spec, but we do use them to return gRPC API requests.
|
||||
// TODO(10094): Consider removing in v3.
|
||||
|
||||
@@ -450,3 +450,9 @@ func (s *ChainService) IsOptimistic(_ context.Context) (bool, error) {
|
||||
func (s *ChainService) IsOptimisticForRoot(_ context.Context, _ [32]byte) (bool, error) {
|
||||
return s.Optimistic, nil
|
||||
}
|
||||
|
||||
// ProcessAttestationsAndUpdateHead mocks the same method in the chain service.
|
||||
func (s *ChainService) UpdateHead(_ context.Context) error { return nil }
|
||||
|
||||
// ReceiveAttesterSlashing mocks the same method in the chain service.
|
||||
func (s *ChainService) ReceiveAttesterSlashing(context.Context, *ethpb.AttesterSlashing) {}
|
||||
|
||||
@@ -79,7 +79,7 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
store: &store.Store{},
|
||||
wsVerifier: wv,
|
||||
}
|
||||
s.store.SetFinalizedCheckpt(ðpb.Checkpoint{Epoch: tt.finalizedEpoch})
|
||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: tt.finalizedEpoch}, [32]byte{})
|
||||
err = s.wsVerifier.VerifyWeakSubjectivity(context.Background(), s.store.FinalizedCheckpt().Epoch)
|
||||
if tt.wantErr == nil {
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -430,7 +430,11 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
|
||||
}
|
||||
trie, err := trie.GenerateTrieFromItems(deps, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err, "Could not generate deposit trie")
|
||||
assert.Equal(t, trie.HashTreeRoot(), cachedDeposits.Deposits.HashTreeRoot())
|
||||
rootA, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
rootB, err := cachedDeposits.Deposits.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, rootA, rootB)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
@@ -488,7 +492,11 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
}
|
||||
trie, err := trie.GenerateTrieFromItems(deps, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err, "Could not generate deposit trie")
|
||||
assert.Equal(t, trie.HashTreeRoot(), cachedDeposits.Deposits.HashTreeRoot())
|
||||
rootA, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
rootB, err := cachedDeposits.Deposits.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, rootA, rootB)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_HandleZeroDeposits(t *testing.T) {
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/altair",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//testing/endtoend/evaluators:__subpackages__",
|
||||
"//testing/spectest:__subpackages__",
|
||||
"//testing/util:__pkg__",
|
||||
"//validator/client:__pkg__",
|
||||
|
||||
@@ -143,7 +143,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
@@ -202,7 +203,8 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
dep[0].Data.Signature = make([]byte, 96)
|
||||
trie, _, err := util.DepositTrieFromDeposits(dep)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
|
||||
@@ -173,7 +173,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
@@ -233,7 +234,8 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
dep[0].Data.Signature = make([]byte, 96)
|
||||
trie, _, err := util.DepositTrieFromDeposits(dep)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
@@ -289,7 +291,9 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
dep[i].Proof = proof
|
||||
}
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
@@ -376,7 +380,9 @@ func TestProcessDeposit_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
|
||||
@@ -106,7 +106,7 @@ func weighJustificationAndFinalization(state state.BeaconState,
|
||||
if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newBits := state.JustificationBits()
|
||||
newBits = state.JustificationBits()
|
||||
newBits.SetBitAt(1, true)
|
||||
if err := state.SetJustificationBits(newBits); err != nil {
|
||||
return nil, err
|
||||
@@ -122,7 +122,7 @@ func weighJustificationAndFinalization(state state.BeaconState,
|
||||
if err := state.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newBits := state.JustificationBits()
|
||||
newBits = state.JustificationBits()
|
||||
newBits.SetBitAt(0, true)
|
||||
if err := state.SetJustificationBits(newBits); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -41,7 +41,10 @@ func UpdateGenesisEth1Data(state state.BeaconState, deposits []*ethpb.Deposit, e
|
||||
}
|
||||
}
|
||||
|
||||
depositRoot := t.HashTreeRoot()
|
||||
depositRoot, err := t.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eth1Data.DepositRoot = depositRoot[:]
|
||||
err = state.SetEth1Data(eth1Data)
|
||||
if err != nil {
|
||||
|
||||
@@ -40,6 +40,7 @@ go_library(
|
||||
"//beacon-chain/db/iface:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/genesis:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/v1:go_default_library",
|
||||
"//beacon-chain/state/v2:go_default_library",
|
||||
"//beacon-chain/state/v3:go_default_library",
|
||||
|
||||
@@ -83,7 +83,7 @@ func TestEnsureEmbeddedGenesis(t *testing.T) {
|
||||
// Embedded Genesis works with Mainnet config
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ConfigName = params.ConfigNames[params.Mainnet]
|
||||
cfg.ConfigName = params.MainnetName
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/genesis"
|
||||
state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||
@@ -204,7 +205,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly
|
||||
// look at issue https://github.com/prysmaticlabs/prysm/issues/9262.
|
||||
switch rawType := states[i].InnerStateUnsafe().(type) {
|
||||
case *ethpb.BeaconState:
|
||||
pbState, err := v1.ProtobufBeaconState(rawType)
|
||||
var pbState *ethpb.BeaconState
|
||||
var err error
|
||||
if features.Get().EnableNativeState {
|
||||
pbState, err = state_native.ProtobufBeaconStatePhase0(rawType)
|
||||
} else {
|
||||
pbState, err = v1.ProtobufBeaconState(rawType)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -225,7 +232,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly
|
||||
return err
|
||||
}
|
||||
case *ethpb.BeaconStateAltair:
|
||||
pbState, err := v2.ProtobufBeaconState(rawType)
|
||||
var pbState *ethpb.BeaconStateAltair
|
||||
var err error
|
||||
if features.Get().EnableNativeState {
|
||||
pbState, err = state_native.ProtobufBeaconStateAltair(rawType)
|
||||
} else {
|
||||
pbState, err = v2.ProtobufBeaconState(rawType)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -247,7 +260,13 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly
|
||||
return err
|
||||
}
|
||||
case *ethpb.BeaconStateBellatrix:
|
||||
pbState, err := v3.ProtobufBeaconState(rawType)
|
||||
var pbState *ethpb.BeaconStateBellatrix
|
||||
var err error
|
||||
if features.Get().EnableNativeState {
|
||||
pbState, err = state_native.ProtobufBeaconStateBellatrix(rawType)
|
||||
} else {
|
||||
pbState, err = v3.ProtobufBeaconState(rawType)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -274,28 +293,7 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly
|
||||
}
|
||||
|
||||
// store the validator entries separately to save space.
|
||||
valBkt := tx.Bucket(stateValidatorsBucket)
|
||||
for hashStr, validatorEntry := range validatorsEntries {
|
||||
key := []byte(hashStr)
|
||||
// if the entry is not in the cache and not in the DB,
|
||||
// then insert it in the DB and add to the cache.
|
||||
if _, ok := s.validatorEntryCache.Get(key); !ok {
|
||||
validatorEntryCacheMiss.Inc()
|
||||
if valEntry := valBkt.Get(key); valEntry == nil {
|
||||
valBytes, encodeErr := encode(ctx, validatorEntry)
|
||||
if encodeErr != nil {
|
||||
return encodeErr
|
||||
}
|
||||
if putErr := valBkt.Put(key, valBytes); putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
s.validatorEntryCache.Set(key, validatorEntry, int64(len(valBytes)))
|
||||
}
|
||||
} else {
|
||||
validatorEntryCacheHit.Inc()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return s.storeValidatorEntriesSeparately(ctx, tx, validatorsEntries)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -303,6 +301,31 @@ func (s *Store) SaveStatesEfficient(ctx context.Context, states []state.ReadOnly
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) storeValidatorEntriesSeparately(ctx context.Context, tx *bolt.Tx, validatorsEntries map[string]*ethpb.Validator) error {
|
||||
valBkt := tx.Bucket(stateValidatorsBucket)
|
||||
for hashStr, validatorEntry := range validatorsEntries {
|
||||
key := []byte(hashStr)
|
||||
// if the entry is not in the cache and not in the DB,
|
||||
// then insert it in the DB and add to the cache.
|
||||
if _, ok := s.validatorEntryCache.Get(key); !ok {
|
||||
validatorEntryCacheMiss.Inc()
|
||||
if valEntry := valBkt.Get(key); valEntry == nil {
|
||||
valBytes, encodeErr := encode(ctx, validatorEntry)
|
||||
if encodeErr != nil {
|
||||
return encodeErr
|
||||
}
|
||||
if putErr := valBkt.Put(key, valBytes); putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
s.validatorEntryCache.Set(key, validatorEntry, int64(len(valBytes)))
|
||||
}
|
||||
} else {
|
||||
validatorEntryCacheHit.Inc()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasState checks if a state by root exists in the db.
|
||||
func (s *Store) HasState(ctx context.Context, blockRoot [32]byte) bool {
|
||||
_, span := trace.StartSpan(ctx, "BeaconDB.HasState")
|
||||
|
||||
@@ -15,13 +15,13 @@ func TestSaveOrigin(t *testing.T) {
|
||||
// Embedded Genesis works with Mainnet config
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ConfigName = params.ConfigNames[params.Mainnet]
|
||||
cfg.ConfigName = params.MainnetName
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
ctx := context.Background()
|
||||
db := setupDB(t)
|
||||
|
||||
st, err := genesis.State(params.Mainnet.String())
|
||||
st, err := genesis.State(params.MainnetName)
|
||||
require.NoError(t, err)
|
||||
|
||||
sb, err := st.MarshalSSZ()
|
||||
|
||||
@@ -81,7 +81,7 @@ func (s *Store) removeNode(ctx context.Context, node *Node) ([][32]byte, error)
|
||||
if i != len(children)-1 {
|
||||
children[i] = children[len(children)-1]
|
||||
}
|
||||
node.parent.children = children[:len(children)-2]
|
||||
node.parent.children = children[:len(children)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,6 +779,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
PeerManager: p2pService,
|
||||
MetadataProvider: p2pService,
|
||||
ChainInfoFetcher: chainService,
|
||||
HeadUpdater: chainService,
|
||||
HeadFetcher: chainService,
|
||||
CanonicalFetcher: chainService,
|
||||
ForkFetcher: chainService,
|
||||
|
||||
@@ -34,7 +34,7 @@ go_library(
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/powchain/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native/v1:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/state/v1:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
|
||||
@@ -22,7 +22,7 @@ const repeatedSearches = 2 * searchThreshold
|
||||
|
||||
// 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, "beacon-chain.web3service.BlockExists")
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.BlockExists")
|
||||
defer span.End()
|
||||
|
||||
if exists, hdrInfo, err := s.headerCache.HeaderInfoByHash(hash); exists || err != nil {
|
||||
@@ -45,24 +45,9 @@ func (s *Service) BlockExists(ctx context.Context, hash common.Hash) (bool, *big
|
||||
return true, new(big.Int).Set(header.Number), nil
|
||||
}
|
||||
|
||||
// BlockExistsWithCache returns true if the block exists in cache, its height and any possible error encountered.
|
||||
func (s *Service) BlockExistsWithCache(ctx context.Context, hash common.Hash) (bool, *big.Int, error) {
|
||||
_, span := trace.StartSpan(ctx, "beacon-chain.web3service.BlockExistsWithCache")
|
||||
defer span.End()
|
||||
if exists, hdrInfo, err := s.headerCache.HeaderInfoByHash(hash); exists || err != nil {
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
span.AddAttributes(trace.BoolAttribute("blockCacheHit", true))
|
||||
return true, hdrInfo.Number, nil
|
||||
}
|
||||
span.AddAttributes(trace.BoolAttribute("blockCacheHit", false))
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
// BlockHashByHeight returns the block hash of the block at the given height.
|
||||
func (s *Service) BlockHashByHeight(ctx context.Context, height *big.Int) (common.Hash, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.web3service.BlockHashByHeight")
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.BlockHashByHeight")
|
||||
defer span.End()
|
||||
|
||||
if exists, hInfo, err := s.headerCache.HeaderInfoByHeight(height); exists || err != nil {
|
||||
@@ -90,9 +75,9 @@ func (s *Service) BlockHashByHeight(ctx context.Context, height *big.Int) (commo
|
||||
return header.Hash(), nil
|
||||
}
|
||||
|
||||
// BlockTimeByHeight fetches an eth1.0 block timestamp by its height.
|
||||
// BlockTimeByHeight fetches an eth1 block timestamp by its height.
|
||||
func (s *Service) BlockTimeByHeight(ctx context.Context, height *big.Int) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.web3service.BlockTimeByHeight")
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.BlockTimeByHeight")
|
||||
defer span.End()
|
||||
if s.eth1DataFetcher == nil {
|
||||
err := errors.New("nil eth1DataFetcher")
|
||||
@@ -111,7 +96,7 @@ func (s *Service) BlockTimeByHeight(ctx context.Context, height *big.Int) (uint6
|
||||
// This is an optimized version with the worst case being O(2*repeatedSearches) number of calls
|
||||
// while in best case search for the block is performed in O(1).
|
||||
func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.HeaderInfo, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.web3service.BlockByTimestamp")
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.BlockByTimestamp")
|
||||
defer span.End()
|
||||
|
||||
s.latestEth1DataLock.RLock()
|
||||
@@ -122,15 +107,14 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea
|
||||
if time > latestBlkTime {
|
||||
return nil, errors.Errorf("provided time is later than the current eth1 head. %d > %d", time, latestBlkTime)
|
||||
}
|
||||
// Initialize a pointer to eth1 chain's history to start our search
|
||||
// from.
|
||||
// Initialize a pointer to eth1 chain's history to start our search from.
|
||||
cursorNum := big.NewInt(0).SetUint64(latestBlkHeight)
|
||||
cursorTime := latestBlkTime
|
||||
|
||||
numOfBlocks := uint64(0)
|
||||
estimatedBlk := cursorNum.Uint64()
|
||||
maxTimeBuffer := searchThreshold * params.BeaconConfig().SecondsPerETH1Block
|
||||
// Terminate if we cant find an acceptable block after
|
||||
// Terminate if we can't find an acceptable block after
|
||||
// repeated searches.
|
||||
for i := 0; i < repeatedSearches; i++ {
|
||||
if ctx.Err() != nil {
|
||||
@@ -157,12 +141,12 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea
|
||||
// time - buffer <= head.time <= time + buffer
|
||||
break
|
||||
}
|
||||
hinfo, err := s.retrieveHeaderInfo(ctx, estimatedBlk)
|
||||
hInfo, err := s.retrieveHeaderInfo(ctx, estimatedBlk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cursorNum = hinfo.Number
|
||||
cursorTime = hinfo.Time
|
||||
cursorNum = hInfo.Number
|
||||
cursorTime = hInfo.Time
|
||||
}
|
||||
|
||||
// Exit early if we get the desired block.
|
||||
@@ -170,15 +154,15 @@ func (s *Service) BlockByTimestamp(ctx context.Context, time uint64) (*types.Hea
|
||||
return s.retrieveHeaderInfo(ctx, cursorNum.Uint64())
|
||||
}
|
||||
if cursorTime > time {
|
||||
return s.findLessTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time)
|
||||
return s.findMaxTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time)
|
||||
}
|
||||
return s.findMoreTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time)
|
||||
return s.findMinTargetEth1Block(ctx, big.NewInt(0).SetUint64(estimatedBlk), time)
|
||||
}
|
||||
|
||||
// Performs a search to find a target eth1 block which is earlier than or equal to the
|
||||
// target time. This method is used when head.time > targetTime
|
||||
func (s *Service) findLessTargetEth1Block(ctx context.Context, startBlk *big.Int, targetTime uint64) (*types.HeaderInfo, error) {
|
||||
for bn := startBlk; ; bn = big.NewInt(0).Sub(bn, big.NewInt(1)) {
|
||||
func (s *Service) findMaxTargetEth1Block(ctx context.Context, upperBoundBlk *big.Int, targetTime uint64) (*types.HeaderInfo, error) {
|
||||
for bn := upperBoundBlk; ; bn = big.NewInt(0).Sub(bn, big.NewInt(1)) {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
@@ -194,8 +178,8 @@ func (s *Service) findLessTargetEth1Block(ctx context.Context, startBlk *big.Int
|
||||
|
||||
// Performs a search to find a target eth1 block which is just earlier than or equal to the
|
||||
// target time. This method is used when head.time < targetTime
|
||||
func (s *Service) findMoreTargetEth1Block(ctx context.Context, startBlk *big.Int, targetTime uint64) (*types.HeaderInfo, error) {
|
||||
for bn := startBlk; ; bn = big.NewInt(0).Add(bn, big.NewInt(1)) {
|
||||
func (s *Service) findMinTargetEth1Block(ctx context.Context, lowerBoundBlk *big.Int, targetTime uint64) (*types.HeaderInfo, error) {
|
||||
for bn := lowerBoundBlk; ; bn = big.NewInt(0).Add(bn, big.NewInt(1)) {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
@@ -203,8 +187,7 @@ func (s *Service) findMoreTargetEth1Block(ctx context.Context, startBlk *big.Int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Return the last block before we hit the threshold
|
||||
// time.
|
||||
// Return the last block before we hit the threshold time.
|
||||
if info.Time > targetTime {
|
||||
return s.retrieveHeaderInfo(ctx, info.Number.Uint64()-1)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func TestLatestMainchainInfo_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
tickerChan := make(chan time.Time)
|
||||
web3Service.headTicker = &time.Ticker{C: tickerChan}
|
||||
web3Service.eth1HeadTicker = &time.Ticker{C: tickerChan}
|
||||
tickerChan <- time.Now()
|
||||
web3Service.cancel()
|
||||
exitRoutine <- true
|
||||
@@ -207,51 +207,6 @@ func TestBlockExists_UsesCachedBlockInfo(t *testing.T) {
|
||||
require.Equal(t, 0, height.Cmp(header.Number))
|
||||
}
|
||||
|
||||
func TestBlockExistsWithCache_UsesCachedHeaderInfo(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
server, endpoint, err := mockPOW.SetupRPCServer()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
server.Stop()
|
||||
})
|
||||
web3Service, err := NewService(context.Background(),
|
||||
WithHttpEndpoints([]string{endpoint}),
|
||||
WithDatabase(beaconDB),
|
||||
)
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
|
||||
header := &gethTypes.Header{
|
||||
Number: big.NewInt(0),
|
||||
}
|
||||
|
||||
err = web3Service.headerCache.AddHeader(header)
|
||||
require.NoError(t, err)
|
||||
|
||||
exists, height, err := web3Service.BlockExistsWithCache(context.Background(), header.Hash())
|
||||
require.NoError(t, err, "Could not get block hash with given height")
|
||||
require.Equal(t, true, exists)
|
||||
require.Equal(t, 0, height.Cmp(header.Number))
|
||||
}
|
||||
|
||||
func TestBlockExistsWithCache_HeaderNotCached(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
server, endpoint, err := mockPOW.SetupRPCServer()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
server.Stop()
|
||||
})
|
||||
web3Service, err := NewService(context.Background(),
|
||||
WithHttpEndpoints([]string{endpoint}),
|
||||
WithDatabase(beaconDB),
|
||||
)
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
|
||||
exists, height, err := web3Service.BlockExistsWithCache(context.Background(), common.BytesToHash([]byte("hash")))
|
||||
require.NoError(t, err, "Could not get block hash with given height")
|
||||
require.Equal(t, false, exists)
|
||||
require.Equal(t, (*big.Int)(nil), height)
|
||||
}
|
||||
|
||||
func TestService_BlockNumberByTimestamp(t *testing.T) {
|
||||
beaconDB := dbutil.SetupDB(t)
|
||||
testAcc, err := mock.Setup()
|
||||
@@ -313,11 +268,11 @@ func TestService_BlockNumberByTimestampLessTargetTime(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
// Provide an unattainable target time
|
||||
_, err = web3Service.findLessTargetEth1Block(ctx, hd.Number, hd.Time/2)
|
||||
_, err = web3Service.findMaxTargetEth1Block(ctx, hd.Number, hd.Time/2)
|
||||
require.ErrorContains(t, context.DeadlineExceeded.Error(), err)
|
||||
|
||||
// Provide an attainable target time
|
||||
blk, err := web3Service.findLessTargetEth1Block(context.Background(), hd.Number, hd.Time-5)
|
||||
blk, err := web3Service.findMaxTargetEth1Block(context.Background(), hd.Number, hd.Time-5)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, hd.Number.Uint64(), blk.Number.Uint64(), "retrieved block is not less than the head")
|
||||
}
|
||||
@@ -351,11 +306,11 @@ func TestService_BlockNumberByTimestampMoreTargetTime(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
// Provide an unattainable target time with respect to head
|
||||
_, err = web3Service.findMoreTargetEth1Block(ctx, big.NewInt(0).Div(hd.Number, big.NewInt(2)), hd.Time)
|
||||
_, err = web3Service.findMinTargetEth1Block(ctx, big.NewInt(0).Div(hd.Number, big.NewInt(2)), hd.Time)
|
||||
require.ErrorContains(t, context.DeadlineExceeded.Error(), err)
|
||||
|
||||
// Provide an attainable target time with respect to head
|
||||
blk, err := web3Service.findMoreTargetEth1Block(context.Background(), big.NewInt(0).Sub(hd.Number, big.NewInt(5)), hd.Time)
|
||||
blk, err := web3Service.findMinTargetEth1Block(context.Background(), big.NewInt(0).Sub(hd.Number, big.NewInt(5)), hd.Time)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, hd.Number.Uint64(), blk.Number.Uint64(), "retrieved block is not equal to the head")
|
||||
}
|
||||
|
||||
@@ -138,7 +138,8 @@ func TestProcessDeposit_InvalidPublicKey(t *testing.T) {
|
||||
deposits[0].Proof, err = trie.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
@@ -178,7 +179,8 @@ func TestProcessDeposit_InvalidSignature(t *testing.T) {
|
||||
trie, err := trie.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
@@ -213,7 +215,8 @@ func TestProcessDeposit_UnableToVerify(t *testing.T) {
|
||||
|
||||
trie, _, err := util.DepositTrieFromDeposits(deposits)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: root[:],
|
||||
@@ -265,7 +268,8 @@ func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
|
||||
trie, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: root[:],
|
||||
@@ -281,7 +285,8 @@ func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
for i := 0; i < int(factor-1); i++ {
|
||||
assert.NoError(t, trie.Insert(dataRoot[:], i))
|
||||
|
||||
trieRoot := trie.HashTreeRoot()
|
||||
trieRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data.DepositRoot = trieRoot[:]
|
||||
eth1Data.DepositCount = uint64(i + 1)
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ const (
|
||||
ExecutionBlockByHashMethod = "eth_getBlockByHash"
|
||||
// ExecutionBlockByNumberMethod request string for JSON-RPC.
|
||||
ExecutionBlockByNumberMethod = "eth_getBlockByNumber"
|
||||
// Defines the seconds to wait before timing out engine endpoints with block execution semantics (newPayload, forkchoiceUpdated).
|
||||
payloadAndForkchoiceUpdatedTimeout = 8 * time.Second
|
||||
// Defines the seconds before timing out engine endpoints with non-block execution semantics.
|
||||
defaultEngineTimeout = time.Second
|
||||
)
|
||||
|
||||
// ForkchoiceUpdatedResponse is the response kind received by the
|
||||
@@ -65,7 +69,9 @@ func (s *Service) NewPayload(ctx context.Context, payload *pb.ExecutionPayload)
|
||||
defer func() {
|
||||
newPayloadLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
d := time.Now().Add(payloadAndForkchoiceUpdatedTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.PayloadStatus{}
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payload)
|
||||
if err != nil {
|
||||
@@ -99,6 +105,9 @@ func (s *Service) ForkchoiceUpdated(
|
||||
forkchoiceUpdatedLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
d := time.Now().Add(payloadAndForkchoiceUpdatedTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &ForkchoiceUpdatedResponse{}
|
||||
err := s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, attrs)
|
||||
if err != nil {
|
||||
@@ -132,6 +141,9 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.Execut
|
||||
getPayloadLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
d := time.Now().Add(defaultEngineTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.ExecutionPayload{}
|
||||
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
|
||||
return result, handleRPCError(err)
|
||||
@@ -147,10 +159,14 @@ func (s *Service) ExchangeTransitionConfiguration(
|
||||
// We set terminal block number to 0 as the parameter is not set on the consensus layer.
|
||||
zeroBigNum := big.NewInt(0)
|
||||
cfg.TerminalBlockNumber = zeroBigNum.Bytes()
|
||||
d := time.Now().Add(defaultEngineTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.TransitionConfiguration{}
|
||||
if err := s.rpcClient.CallContext(ctx, result, ExchangeTransitionConfigurationMethod, cfg); err != nil {
|
||||
return handleRPCError(err)
|
||||
}
|
||||
|
||||
// We surface an error to the user if local configuration settings mismatch
|
||||
// according to the response from the execution node.
|
||||
cfgTerminalHash := params.BeaconConfig().TerminalBlockHash[:]
|
||||
|
||||
@@ -19,8 +19,6 @@ var (
|
||||
ErrUnknownPayload = errors.New("payload does not exist or is not available")
|
||||
// ErrUnknownPayloadStatus when the payload status is unknown.
|
||||
ErrUnknownPayloadStatus = errors.New("unknown payload status")
|
||||
// ErrUnsupportedScheme for unsupported URL schemes.
|
||||
ErrUnsupportedScheme = errors.New("unsupported url scheme, only http(s) and ipc are supported")
|
||||
// ErrConfigMismatch when the execution node's terminal total difficulty or
|
||||
// terminal block hash received via the API mismatches Prysm's configuration value.
|
||||
ErrConfigMismatch = errors.New("execution client configuration mismatch")
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
@@ -16,7 +17,9 @@ import (
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
coreState "github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
@@ -33,22 +36,28 @@ var (
|
||||
const eth1DataSavingInterval = 1000
|
||||
const maxTolerableDifference = 50
|
||||
const defaultEth1HeaderReqLimit = uint64(1000)
|
||||
const depositlogRequestLimit = 10000
|
||||
const depositLogRequestLimit = 10000
|
||||
const additiveFactorMultiplier = 0.10
|
||||
const multiplicativeDecreaseDivisor = 2
|
||||
|
||||
var errTimedOut = errors.New("net/http: request canceled")
|
||||
|
||||
func tooMuchDataRequestedError(err error) bool {
|
||||
// this error is only infura specific (other providers might have different error messages)
|
||||
return err.Error() == "query returned more than 10000 results"
|
||||
}
|
||||
|
||||
func clientTimedOutError(err error) bool {
|
||||
return strings.Contains(err.Error(), errTimedOut.Error())
|
||||
}
|
||||
|
||||
// Eth2GenesisPowchainInfo retrieves the genesis time and eth1 block number of the beacon chain
|
||||
// from the deposit contract.
|
||||
func (s *Service) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
|
||||
return s.chainStartData.GenesisTime, big.NewInt(int64(s.chainStartData.GenesisBlock))
|
||||
}
|
||||
|
||||
// ProcessETH1Block processes the logs from the provided eth1Block.
|
||||
// ProcessETH1Block processes logs from the provided eth1 block.
|
||||
func (s *Service) ProcessETH1Block(ctx context.Context, blkNum *big.Int) error {
|
||||
query := ethereum.FilterQuery{
|
||||
Addresses: []common.Address{
|
||||
@@ -71,7 +80,7 @@ func (s *Service) ProcessETH1Block(ctx context.Context, blkNum *big.Int) error {
|
||||
}
|
||||
}
|
||||
if !s.chainStartData.Chainstarted {
|
||||
if err := s.checkBlockNumberForChainStart(ctx, blkNum); err != nil {
|
||||
if err := s.processChainStartFromBlockNum(ctx, blkNum); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -79,7 +88,7 @@ func (s *Service) ProcessETH1Block(ctx context.Context, blkNum *big.Int) error {
|
||||
}
|
||||
|
||||
// ProcessLog is the main method which handles the processing of all
|
||||
// logs from the deposit contract on the ETH1.0 chain.
|
||||
// logs from the deposit contract on the eth1 chain.
|
||||
func (s *Service) ProcessLog(ctx context.Context, depositLog gethTypes.Log) error {
|
||||
s.processingLock.RLock()
|
||||
defer s.processingLock.RUnlock()
|
||||
@@ -98,7 +107,7 @@ func (s *Service) ProcessLog(ctx context.Context, depositLog gethTypes.Log) erro
|
||||
}
|
||||
|
||||
// ProcessDepositLog processes the log which had been received from
|
||||
// the ETH1.0 chain by trying to ascertain which participant deposited
|
||||
// the eth1 chain by trying to ascertain which participant deposited
|
||||
// in the contract.
|
||||
func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Log) error {
|
||||
pubkey, withdrawalCredentials, amount, signature, merkleTreeIndex, err := contracts.UnpackDepositLogData(depositLog.Data)
|
||||
@@ -131,7 +140,7 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
|
||||
depositHash, err := depositData.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to determine hashed value of deposit")
|
||||
return errors.Wrap(err, "unable to determine hashed value of deposit")
|
||||
}
|
||||
|
||||
// Defensive check to validate incoming index.
|
||||
@@ -149,20 +158,27 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
if !s.chainStartData.Chainstarted {
|
||||
proof, err := s.depositTrie.MerkleProof(int(index))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to generate merkle proof for deposit")
|
||||
return errors.Wrap(err, "unable to generate merkle proof for deposit")
|
||||
}
|
||||
deposit.Proof = proof
|
||||
}
|
||||
|
||||
// We always store all historical deposits in the DB.
|
||||
err = s.cfg.depositCache.InsertDeposit(ctx, deposit, depositLog.BlockNumber, index, s.depositTrie.HashTreeRoot())
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
err = s.cfg.depositCache.InsertDeposit(ctx, deposit, depositLog.BlockNumber, index, root)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to insert deposit into cache")
|
||||
}
|
||||
validData := true
|
||||
if !s.chainStartData.Chainstarted {
|
||||
s.chainStartData.ChainstartDeposits = append(s.chainStartData.ChainstartDeposits, deposit)
|
||||
root := s.depositTrie.HashTreeRoot()
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: uint64(len(s.chainStartData.ChainstartDeposits)),
|
||||
@@ -172,7 +188,11 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
validData = false
|
||||
}
|
||||
} else {
|
||||
s.cfg.depositCache.InsertPendingDeposit(ctx, deposit, depositLog.BlockNumber, index, s.depositTrie.HashTreeRoot())
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
s.cfg.depositCache.InsertPendingDeposit(ctx, deposit, depositLog.BlockNumber, index, root)
|
||||
}
|
||||
if validData {
|
||||
log.WithFields(logrus.Fields{
|
||||
@@ -206,7 +226,7 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
}
|
||||
|
||||
// ProcessChainStart processes the log which had been received from
|
||||
// the ETH1.0 chain by trying to determine when to start the beacon chain.
|
||||
// the eth1 chain by trying to determine when to start the beacon chain.
|
||||
func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte, blockNumber *big.Int) {
|
||||
s.chainStartData.Chainstarted = true
|
||||
s.chainStartData.GenesisBlock = blockNumber.Uint64()
|
||||
@@ -216,12 +236,16 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
||||
for i := range s.chainStartData.ChainstartDeposits {
|
||||
proof, err := s.depositTrie.MerkleProof(i)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to generate deposit proof %v", err)
|
||||
log.Errorf("unable to generate deposit proof %v", err)
|
||||
}
|
||||
s.chainStartData.ChainstartDeposits[i].Proof = proof
|
||||
}
|
||||
|
||||
root := s.depositTrie.HashTreeRoot()
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil { // This should never happen.
|
||||
log.WithError(err).Error("unable to determine root of deposit trie, aborting chain start")
|
||||
return
|
||||
}
|
||||
s.chainStartData.Eth1Data = ðpb.Eth1Data{
|
||||
DepositCount: uint64(len(s.chainStartData.ChainstartDeposits)),
|
||||
DepositRoot: root[:],
|
||||
@@ -238,15 +262,15 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
||||
},
|
||||
})
|
||||
if err := s.savePowchainData(s.ctx); err != nil {
|
||||
// continue on, if the save fails as this will get re-saved
|
||||
// continue on if the save fails as this will get re-saved
|
||||
// in the next interval.
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// createGenesisTime adds in the genesis delay to the eth1 block time
|
||||
// on which it was triggered.
|
||||
func createGenesisTime(timeStamp uint64) uint64 {
|
||||
// adds in the genesis delay to the eth1 block time
|
||||
// on which it was triggered.
|
||||
return timeStamp + params.BeaconConfig().GenesisDelay
|
||||
}
|
||||
|
||||
@@ -283,7 +307,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
latestFollowHeight, err := s.followBlockHeight(ctx)
|
||||
latestFollowHeight, err := s.followedBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -309,7 +333,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
remainingLogs := logCount - uint64(s.lastReceivedMerkleIndex+1)
|
||||
// only change the end block if the remaining logs are below the required log limit.
|
||||
// reset our query and end block in this case.
|
||||
withinLimit := remainingLogs < depositlogRequestLimit
|
||||
withinLimit := remainingLogs < depositLogRequestLimit
|
||||
aboveFollowHeight := end >= latestFollowHeight
|
||||
if withinLimit && aboveFollowHeight {
|
||||
query.ToBlock = big.NewInt(0).SetUint64(latestFollowHeight)
|
||||
@@ -404,9 +428,9 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
// logs from the period last polled to now.
|
||||
func (s *Service) requestBatchedHeadersAndLogs(ctx context.Context) error {
|
||||
// We request for the nth block behind the current head, in order to have
|
||||
// stabilized logs when we retrieve it from the 1.0 chain.
|
||||
// stabilized logs when we retrieve it from the eth1 chain.
|
||||
|
||||
requestedBlock, err := s.followBlockHeight(ctx)
|
||||
requestedBlock, err := s.followedBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -448,18 +472,17 @@ func (s *Service) retrieveBlockHashAndTime(ctx context.Context, blkNum *big.Int)
|
||||
return bHash, timeStamp, nil
|
||||
}
|
||||
|
||||
// checkBlockNumberForChainStart checks the given block number for if chainstart has occurred.
|
||||
func (s *Service) checkBlockNumberForChainStart(ctx context.Context, blkNum *big.Int) error {
|
||||
func (s *Service) processChainStartFromBlockNum(ctx context.Context, blkNum *big.Int) error {
|
||||
bHash, timeStamp, err := s.retrieveBlockHashAndTime(ctx, blkNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.checkForChainstart(ctx, bHash, blkNum, timeStamp)
|
||||
s.processChainStartIfReady(ctx, bHash, blkNum, timeStamp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) checkHeaderForChainstart(ctx context.Context, header *gethTypes.Header) {
|
||||
s.checkForChainstart(ctx, header.Hash(), header.Number, header.Time)
|
||||
func (s *Service) processChainStartFromHeader(ctx context.Context, header *gethTypes.Header) {
|
||||
s.processChainStartIfReady(ctx, header.Hash(), header.Number, header.Time)
|
||||
}
|
||||
|
||||
func (s *Service) checkHeaderRange(ctx context.Context, start, end uint64, headersMap map[uint64]*gethTypes.Header,
|
||||
@@ -475,7 +498,7 @@ func (s *Service) checkHeaderRange(ctx context.Context, start, end uint64, heade
|
||||
i--
|
||||
continue
|
||||
}
|
||||
s.checkHeaderForChainstart(ctx, h)
|
||||
s.processChainStartFromHeader(ctx, h)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -495,7 +518,7 @@ func (s *Service) currentCountAndTime(ctx context.Context, blockTime uint64) (ui
|
||||
return valCount, createGenesisTime(blockTime)
|
||||
}
|
||||
|
||||
func (s *Service) checkForChainstart(ctx context.Context, blockHash [32]byte, blockNumber *big.Int, blockTime uint64) {
|
||||
func (s *Service) processChainStartIfReady(ctx context.Context, blockHash [32]byte, blockNumber *big.Int, blockTime uint64) {
|
||||
valCount, genesisTime := s.currentCountAndTime(ctx, blockTime)
|
||||
if valCount == 0 {
|
||||
return
|
||||
@@ -507,9 +530,15 @@ func (s *Service) checkForChainstart(ctx context.Context, blockHash [32]byte, bl
|
||||
}
|
||||
}
|
||||
|
||||
// save all powchain related metadata to disk.
|
||||
// savePowchainData saves all powchain related metadata to disk.
|
||||
func (s *Service) savePowchainData(ctx context.Context) error {
|
||||
pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe())
|
||||
var pbState *ethpb.BeaconState
|
||||
var err error
|
||||
if features.Get().EnableNativeState {
|
||||
pbState, err = state_native.ProtobufBeaconStatePhase0(s.preGenesisState.InnerStateUnsafe())
|
||||
} else {
|
||||
pbState, err = v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -589,7 +589,7 @@ func TestCheckForChainstart_NoValidator(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := newPowchainService(t, testAcc, beaconDB)
|
||||
s.checkForChainstart(context.Background(), [32]byte{}, nil, 0)
|
||||
s.processChainStartIfReady(context.Background(), [32]byte{}, nil, 0)
|
||||
require.LogsDoNotContain(t, hook, "Could not determine active validator count from pre genesis state")
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@@ -30,7 +29,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
nativev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
|
||||
native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
@@ -98,7 +97,6 @@ type POWBlockFetcher interface {
|
||||
BlockByTimestamp(ctx context.Context, time uint64) (*types.HeaderInfo, error)
|
||||
BlockHashByHeight(ctx context.Context, height *big.Int) (common.Hash, error)
|
||||
BlockExists(ctx context.Context, hash common.Hash) (bool, *big.Int, error)
|
||||
BlockExistsWithCache(ctx context.Context, hash common.Hash) (bool, *big.Int, error)
|
||||
}
|
||||
|
||||
// Chain defines a standard interface for the powchain service in Prysm.
|
||||
@@ -114,7 +112,6 @@ type RPCDataFetcher interface {
|
||||
Close()
|
||||
HeaderByNumber(ctx context.Context, number *big.Int) (*gethTypes.Header, error)
|
||||
HeaderByHash(ctx context.Context, hash common.Hash) (*gethTypes.Header, error)
|
||||
SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error)
|
||||
}
|
||||
|
||||
// RPCClient defines the rpc methods required to interact with the eth1 node.
|
||||
@@ -139,10 +136,10 @@ type config struct {
|
||||
}
|
||||
|
||||
// Service fetches important information about the canonical
|
||||
// Ethereum ETH1.0 chain via a web3 endpoint using an ethclient. The Random
|
||||
// Beacon Chain requires synchronization with the ETH1.0 chain's current
|
||||
// blockhash, block number, and access to logs within the
|
||||
// Validator Registration Contract on the ETH1.0 chain to kick off the beacon
|
||||
// eth1 chain via a web3 endpoint using an ethclient.
|
||||
// The beacon chain requires synchronization with the eth1 chain's current
|
||||
// block hash, block number, and access to logs within the
|
||||
// Validator Registration Contract on the eth1 chain to kick off the beacon
|
||||
// chain's validator registration process.
|
||||
type Service struct {
|
||||
connectedETH1 bool
|
||||
@@ -152,7 +149,7 @@ type Service struct {
|
||||
cfg *config
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
headTicker *time.Ticker
|
||||
eth1HeadTicker *time.Ticker
|
||||
httpLogger bind.ContractFilterer
|
||||
eth1DataFetcher RPCDataFetcher
|
||||
rpcClient RPCClient
|
||||
@@ -173,11 +170,11 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
depositTrie, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, errors.Wrap(err, "could not setup deposit trie")
|
||||
return nil, errors.Wrap(err, "could not set up deposit trie")
|
||||
}
|
||||
genState, err := transition.EmptyGenesisState()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not setup genesis state")
|
||||
return nil, errors.Wrap(err, "could not set up genesis state")
|
||||
}
|
||||
|
||||
s := &Service{
|
||||
@@ -201,7 +198,7 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
},
|
||||
lastReceivedMerkleIndex: -1,
|
||||
preGenesisState: genState,
|
||||
headTicker: time.NewTicker(time.Duration(params.BeaconConfig().SecondsPerETH1Block) * time.Second),
|
||||
eth1HeadTicker: time.NewTicker(time.Duration(params.BeaconConfig().SecondsPerETH1Block) * time.Second),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
@@ -225,7 +222,7 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Start a web3 service's main event loop.
|
||||
// Start the powchain service's main event loop.
|
||||
func (s *Service) Start() {
|
||||
if err := s.setupExecutionClientConnections(s.ctx, s.cfg.currHttpEndpoint); err != nil {
|
||||
log.WithError(err).Error("Could not connect to execution endpoint")
|
||||
@@ -273,7 +270,7 @@ func (s *Service) Stop() error {
|
||||
func (s *Service) ClearPreGenesisData() {
|
||||
s.chainStartData.ChainstartDeposits = []*ethpb.Deposit{}
|
||||
if features.Get().EnableNativeState {
|
||||
s.preGenesisState = &nativev1.BeaconState{}
|
||||
s.preGenesisState = &native.BeaconState{}
|
||||
} else {
|
||||
s.preGenesisState = &v1.BeaconState{}
|
||||
}
|
||||
@@ -372,7 +369,7 @@ func (s *Service) ETH1ConnectionErrors() []error {
|
||||
|
||||
// refers to the latest eth1 block which follows the condition: eth1_timestamp +
|
||||
// SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE <= current_unix_time
|
||||
func (s *Service) followBlockHeight(_ context.Context) (uint64, error) {
|
||||
func (s *Service) followedBlockHeight(_ context.Context) (uint64, error) {
|
||||
latestValidBlock := uint64(0)
|
||||
if s.latestEth1Data.BlockHeight > params.BeaconConfig().Eth1FollowDistance {
|
||||
latestValidBlock = s.latestEth1Data.BlockHeight - params.BeaconConfig().Eth1FollowDistance
|
||||
@@ -386,8 +383,7 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo
|
||||
}
|
||||
s.cfg.depositCache.InsertDepositContainers(ctx, ctrs)
|
||||
if !s.chainStartData.Chainstarted {
|
||||
// do not add to pending cache
|
||||
// if no genesis state exists.
|
||||
// Do not add to pending cache if no genesis state exists.
|
||||
validDepositsCount.Add(float64(s.preGenesisState.Eth1DepositIndex()))
|
||||
return nil
|
||||
}
|
||||
@@ -395,7 +391,7 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Default to all deposits post-genesis deposits in
|
||||
// Default to all post-genesis deposits in
|
||||
// the event we cannot find a finalized state.
|
||||
currIndex := genesisState.Eth1DepositIndex()
|
||||
chkPt, err := s.cfg.beaconDB.FinalizedCheckpoint(ctx)
|
||||
@@ -411,17 +407,17 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo
|
||||
// Set deposit index to the one in the current archived state.
|
||||
currIndex = fState.Eth1DepositIndex()
|
||||
|
||||
// when a node pauses for some time and starts again, the deposits to finalize
|
||||
// accumulates. we finalize them here before we are ready to receive a block.
|
||||
// When a node pauses for some time and starts again, the deposits to finalize
|
||||
// accumulates. We finalize them here before we are ready to receive a block.
|
||||
// Otherwise, the first few blocks will be slower to compute as we will
|
||||
// hold the lock and be busy finalizing the deposits.
|
||||
// The deposit index in the state is always the index of the next deposit
|
||||
// to be included(rather than the last one to be processed). This was most likely
|
||||
// to be included (rather than the last one to be processed). This was most likely
|
||||
// done as the state cannot represent signed integers.
|
||||
actualIndex := int64(currIndex) - 1 // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
s.cfg.depositCache.InsertFinalizedDeposits(ctx, actualIndex)
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.cfg.depositCache.PruneProofs(ctx, actualIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
@@ -498,8 +494,7 @@ func (s *Service) batchRequestHeaders(startBlock, endBlock uint64) ([]*gethTypes
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
// safelyHandleHeader will recover and log any panic that occurs from the
|
||||
// block
|
||||
// safelyHandleHeader will recover and log any panic that occurs from the block
|
||||
func safelyHandlePanic() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
@@ -522,7 +517,7 @@ func (s *Service) handleETH1FollowDistance() {
|
||||
log.Warn("Execution client is not syncing")
|
||||
}
|
||||
if !s.chainStartData.Chainstarted {
|
||||
if err := s.checkBlockNumberForChainStart(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil {
|
||||
if err := s.processChainStartFromBlockNum(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil {
|
||||
s.runError = err
|
||||
log.Error(err)
|
||||
return
|
||||
@@ -530,9 +525,8 @@ func (s *Service) handleETH1FollowDistance() {
|
||||
}
|
||||
// If the last requested block has not changed,
|
||||
// we do not request batched logs as this means there are no new
|
||||
// logs for the powchain service to process. Also is a potential
|
||||
// failure condition as would mean we have not respected the protocol
|
||||
// threshold.
|
||||
// logs for the powchain service to process. Also it is a potential
|
||||
// failure condition as would mean we have not respected the protocol threshold.
|
||||
if s.latestEth1Data.LastRequestedBlock == s.latestEth1Data.BlockHeight {
|
||||
log.Error("Beacon node is not respecting the follow distance")
|
||||
return
|
||||
@@ -595,7 +589,7 @@ func (s *Service) initPOWService() {
|
||||
if s.chainStartData.Chainstarted && s.chainStartData.GenesisBlock == 0 {
|
||||
genHash := common.BytesToHash(s.chainStartData.Eth1Data.BlockHash)
|
||||
genBlock := s.chainStartData.GenesisBlock
|
||||
// In the event our provided chainstart data references a non-existent blockhash
|
||||
// In the event our provided chainstart data references a non-existent block hash,
|
||||
// we assume the genesis block to be 0.
|
||||
if genHash != [32]byte{} {
|
||||
genHeader, err := s.eth1DataFetcher.HeaderByHash(ctx, genHash)
|
||||
@@ -618,7 +612,7 @@ func (s *Service) initPOWService() {
|
||||
}
|
||||
}
|
||||
|
||||
// run subscribes to all the services for the ETH1.0 chain.
|
||||
// run subscribes to all the services for the eth1 chain.
|
||||
func (s *Service) run(done <-chan struct{}) {
|
||||
s.runError = nil
|
||||
|
||||
@@ -636,7 +630,7 @@ func (s *Service) run(done <-chan struct{}) {
|
||||
s.updateConnectedETH1(false)
|
||||
log.Debug("Context closed, exiting goroutine")
|
||||
return
|
||||
case <-s.headTicker.C:
|
||||
case <-s.eth1HeadTicker.C:
|
||||
head, err := s.eth1DataFetcher.HeaderByNumber(s.ctx, nil)
|
||||
if err != nil {
|
||||
s.pollConnectionStatus(s.ctx)
|
||||
@@ -692,10 +686,10 @@ func (s *Service) logTillChainStart(ctx context.Context) {
|
||||
}
|
||||
|
||||
// cacheHeadersForEth1DataVote makes sure that voting for eth1data after startup utilizes cached headers
|
||||
// instead of making multiple RPC requests to the ETH1 endpoint.
|
||||
// instead of making multiple RPC requests to the eth1 endpoint.
|
||||
func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error {
|
||||
// Find the end block to request from.
|
||||
end, err := s.followBlockHeight(ctx)
|
||||
end, err := s.followedBlockHeight(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -703,20 +697,48 @@ func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// We call batchRequestHeaders for its header caching side-effect, so we don't need the return value.
|
||||
_, err = s.batchRequestHeaders(start, end)
|
||||
if err != nil {
|
||||
return err
|
||||
return s.cacheBlockHeaders(start, end)
|
||||
}
|
||||
|
||||
// Caches block headers from the desired range.
|
||||
func (s *Service) cacheBlockHeaders(start, end uint64) error {
|
||||
batchSize := s.cfg.eth1HeaderReqLimit
|
||||
for i := start; i < end; i += batchSize {
|
||||
startReq := i
|
||||
endReq := i + batchSize
|
||||
if endReq > end {
|
||||
endReq = end
|
||||
}
|
||||
// We call batchRequestHeaders for its header caching side-effect, so we don't need the return value.
|
||||
_, err := s.batchRequestHeaders(startReq, endReq)
|
||||
if err != nil {
|
||||
if clientTimedOutError(err) {
|
||||
// Reduce batch size as eth1 node is
|
||||
// unable to respond to the request in time.
|
||||
batchSize /= 2
|
||||
// Always have it greater than 0.
|
||||
if batchSize == 0 {
|
||||
batchSize += 1
|
||||
}
|
||||
|
||||
// Reset request value
|
||||
if i > batchSize {
|
||||
i -= batchSize
|
||||
}
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// determines the earliest voting block from which to start caching all our previous headers from.
|
||||
// Determines the earliest voting block from which to start caching all our previous headers from.
|
||||
func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock uint64) (uint64, error) {
|
||||
genesisTime := s.chainStartData.GenesisTime
|
||||
currSlot := slots.CurrentSlot(genesisTime)
|
||||
|
||||
// In the event genesis has not occurred yet, we just request go back follow_distance blocks.
|
||||
// In the event genesis has not occurred yet, we just request to go back follow_distance blocks.
|
||||
if genesisTime == 0 || currSlot == 0 {
|
||||
earliestBlk := uint64(0)
|
||||
if followBlock > params.BeaconConfig().Eth1FollowDistance {
|
||||
@@ -763,7 +785,7 @@ func (s *Service) initializeEth1Data(ctx context.Context, eth1DataInDB *ethpb.ET
|
||||
return nil
|
||||
}
|
||||
|
||||
// validates that all deposit containers are valid and have their relevant indices
|
||||
// Validates that all deposit containers are valid and have their relevant indices
|
||||
// in order.
|
||||
func validateDepositContainers(ctrs []*ethpb.DepositContainer) bool {
|
||||
ctrLen := len(ctrs)
|
||||
@@ -786,7 +808,7 @@ func validateDepositContainers(ctrs []*ethpb.DepositContainer) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// validates the current powchain data saved and makes sure that any
|
||||
// Validates the current powchain data is saved and makes sure that any
|
||||
// embedded genesis state is correctly accounted for.
|
||||
func (s *Service) ensureValidPowchainData(ctx context.Context) error {
|
||||
genState, err := s.cfg.beaconDB.GenesisState(ctx)
|
||||
@@ -802,7 +824,13 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error {
|
||||
return errors.Wrap(err, "unable to retrieve eth1 data")
|
||||
}
|
||||
if eth1Data == nil || !eth1Data.ChainstartData.Chainstarted || !validateDepositContainers(eth1Data.DepositContainers) {
|
||||
pbState, err := v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe())
|
||||
var pbState *ethpb.BeaconState
|
||||
var err error
|
||||
if features.Get().EnableNativeState {
|
||||
pbState, err = native.ProtobufBeaconStatePhase0(s.preGenesisState.InnerStateUnsafe())
|
||||
} else {
|
||||
pbState, err = v1.ProtobufBeaconState(s.preGenesisState.InnerStateUnsafe())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
@@ -265,7 +267,7 @@ func TestFollowBlock_OK(t *testing.T) {
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
|
||||
h, err := web3Service.followBlockHeight(context.Background())
|
||||
h, err := web3Service.followedBlockHeight(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, baseHeight, h, "Unexpected block height")
|
||||
numToForward := uint64(2)
|
||||
@@ -278,7 +280,7 @@ func TestFollowBlock_OK(t *testing.T) {
|
||||
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64()
|
||||
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time()
|
||||
|
||||
h, err = web3Service.followBlockHeight(context.Background())
|
||||
h, err = web3Service.followedBlockHeight(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedHeight, h, "Unexpected block height")
|
||||
}
|
||||
@@ -843,3 +845,50 @@ func TestETH1Endpoints(t *testing.T) {
|
||||
// Check endpoints are all present.
|
||||
assert.DeepSSZEqual(t, endpoints, s1.ETH1Endpoints(), "Unexpected http endpoint slice")
|
||||
}
|
||||
|
||||
func TestService_CacheBlockHeaders(t *testing.T) {
|
||||
rClient := &slowRPCClient{limit: 1000}
|
||||
s := &Service{
|
||||
cfg: &config{eth1HeaderReqLimit: 1000},
|
||||
rpcClient: rClient,
|
||||
headerCache: newHeaderCache(),
|
||||
}
|
||||
assert.NoError(t, s.cacheBlockHeaders(1, 1000))
|
||||
assert.Equal(t, 1, rClient.numOfCalls)
|
||||
// Reset Num of Calls
|
||||
rClient.numOfCalls = 0
|
||||
|
||||
assert.NoError(t, s.cacheBlockHeaders(1000, 3000))
|
||||
// 1000 - 2000 would be 1001 headers which is higher than our request limit, it
|
||||
// is then reduced to 500 and tried again.
|
||||
assert.Equal(t, 5, rClient.numOfCalls)
|
||||
}
|
||||
|
||||
type slowRPCClient struct {
|
||||
limit int
|
||||
numOfCalls int
|
||||
}
|
||||
|
||||
func (s *slowRPCClient) Close() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *slowRPCClient) BatchCall(b []rpc.BatchElem) error {
|
||||
s.numOfCalls++
|
||||
if len(b) > s.limit {
|
||||
return errTimedOut
|
||||
}
|
||||
for _, e := range b {
|
||||
num, err := hexutil.DecodeBig(e.Args[0].(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h := &gethTypes.Header{Number: num}
|
||||
*e.Result.(*gethTypes.Header) = *h
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *slowRPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ type EngineClient struct {
|
||||
BlockByHashMap map[[32]byte]*pb.ExecutionBlock
|
||||
TerminalBlockHash []byte
|
||||
TerminalBlockHashExists bool
|
||||
OverrideValidHash [32]byte
|
||||
}
|
||||
|
||||
// NewPayload --
|
||||
@@ -37,8 +38,11 @@ func (e *EngineClient) NewPayload(_ context.Context, _ *pb.ExecutionPayload) ([]
|
||||
|
||||
// ForkchoiceUpdated --
|
||||
func (e *EngineClient) ForkchoiceUpdated(
|
||||
_ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes,
|
||||
_ context.Context, fcs *pb.ForkchoiceState, _ *pb.PayloadAttributes,
|
||||
) (*pb.PayloadIDBytes, []byte, error) {
|
||||
if e.OverrideValidHash != [32]byte{} && bytesutil.ToBytes32(fcs.HeadBlockHash) == e.OverrideValidHash {
|
||||
return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, nil
|
||||
}
|
||||
return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, e.ErrForkchoiceUpdated
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,3 @@ func (_ *FaultyMockPOWChain) ClearPreGenesisData() {
|
||||
func (_ *FaultyMockPOWChain) IsConnectedToETH1() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// BlockExistsWithCache --
|
||||
func (f *FaultyMockPOWChain) BlockExistsWithCache(ctx context.Context, hash common.Hash) (bool, *big.Int, error) {
|
||||
return f.BlockExists(ctx, hash)
|
||||
}
|
||||
|
||||
@@ -179,11 +179,6 @@ func (m *POWChain) InsertBlock(height int, time uint64, hash []byte) *POWChain {
|
||||
return m
|
||||
}
|
||||
|
||||
// BlockExistsWithCache --
|
||||
func (m *POWChain) BlockExistsWithCache(ctx context.Context, hash common.Hash) (bool, *big.Int, error) {
|
||||
return m.BlockExists(ctx, hash)
|
||||
}
|
||||
|
||||
func SetupRPCServer() (*rpc.Server, string, error) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("eth", &testETHRPC{}); err != nil {
|
||||
|
||||
@@ -37,4 +37,5 @@ type Server struct {
|
||||
V1Alpha1ValidatorServer *v1alpha1validator.Server
|
||||
SyncChecker sync.Checker
|
||||
CanonicalHistory *stategen.CanonicalHistory
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
// providing RPC endpoints intended for validator clients.
|
||||
type Server struct {
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
TimeFetcher blockchain.TimeFetcher
|
||||
SyncChecker sync.Checker
|
||||
AttestationsPool attestations.Pool
|
||||
|
||||
@@ -670,6 +670,7 @@ func TestProduceBlock(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -774,6 +775,7 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -879,6 +881,7 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -1028,6 +1031,7 @@ func TestProduceBlockV2(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -1174,6 +1178,7 @@ func TestProduceBlindedBlock(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -1280,6 +1285,7 @@ func TestProduceBlindedBlock(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -1429,6 +1435,7 @@ func TestProduceBlindedBlock(t *testing.T) {
|
||||
HeadFetcher: &mockChain.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mockChain.ChainService{},
|
||||
HeadUpdater: &mockChain.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
|
||||
@@ -46,4 +46,5 @@ type Server struct {
|
||||
StateGen stategen.StateManager
|
||||
SyncChecker sync.Checker
|
||||
ReplayerBuilder stategen.ReplayerBuilder
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ func (bs *Server) GetValidatorParticipation(
|
||||
}
|
||||
// Use the last slot of requested epoch to obtain current and previous epoch attestations.
|
||||
// This ensures that we don't miss previous attestations when input requested epochs.
|
||||
startSlot, err := slots.EpochEnd(requestedEpoch)
|
||||
endSlot, err := slots.EpochEnd(requestedEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -507,14 +507,14 @@ func (bs *Server) GetValidatorParticipation(
|
||||
// The above check ensures a future *epoch* isn't requested, but the end slot of the requested epoch could still
|
||||
// be past the current slot. In that case, use the current slot as the best approximation of the requested epoch.
|
||||
// Replayer will make sure the slot ultimately used is canonical.
|
||||
if startSlot > currentSlot {
|
||||
startSlot = currentSlot
|
||||
if endSlot > currentSlot {
|
||||
endSlot = currentSlot
|
||||
}
|
||||
|
||||
// ReplayerBuilder ensures that a canonical chain is followed to the slot
|
||||
beaconState, err := bs.ReplayerBuilder.ReplayerForSlot(startSlot).ReplayBlocks(ctx)
|
||||
beaconState, err := bs.ReplayerBuilder.ReplayerForSlot(endSlot).ReplayBlocks(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", startSlot, err))
|
||||
return nil, status.Error(codes.Internal, fmt.Sprintf("error replaying blocks for state at slot %d: %v", endSlot, err))
|
||||
}
|
||||
var v []*precompute.Validator
|
||||
var b *precompute.Balance
|
||||
|
||||
@@ -197,10 +197,16 @@ func (vs *Server) rebuildDepositTrie(ctx context.Context, canonicalEth1Data *eth
|
||||
|
||||
// validate that the provided deposit trie matches up with the canonical eth1 data provided.
|
||||
func validateDepositTrie(trie *trie.SparseMerkleTrie, canonicalEth1Data *ethpb.Eth1Data) (bool, error) {
|
||||
if trie == nil || canonicalEth1Data == nil {
|
||||
return false, errors.New("nil trie or eth1data provided")
|
||||
}
|
||||
if trie.NumOfItems() != int(canonicalEth1Data.DepositCount) {
|
||||
return false, errors.Errorf("wanted the canonical count of %d but received %d", canonicalEth1Data.DepositCount, trie.NumOfItems())
|
||||
}
|
||||
rt := trie.HashTreeRoot()
|
||||
rt, err := trie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !bytes.Equal(rt[:], canonicalEth1Data.DepositRoot) {
|
||||
return false, errors.Errorf("wanted the canonical deposit root of %#x but received %#x", canonicalEth1Data.DepositRoot, rt)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,10 @@ func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequ
|
||||
return nil, fmt.Errorf("syncing to latest head, not ready to respond")
|
||||
}
|
||||
|
||||
if err := vs.HeadUpdater.UpdateHead(ctx); err != nil {
|
||||
log.WithError(err).Error("Could not process attestations and update head")
|
||||
}
|
||||
|
||||
// Retrieve the parent block as the current head of the canonical chain.
|
||||
parentRoot, err := vs.HeadFetcher.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -72,6 +72,7 @@ func TestProposer_GetBlock_OK(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mock.ChainService{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -158,6 +159,7 @@ func TestProposer_GetBlock_AddsUnaggregatedAtts(t *testing.T) {
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
MockEth1Votes: true,
|
||||
SlashingsPool: slashings.NewPool(),
|
||||
AttPool: attestations.NewPool(),
|
||||
@@ -503,10 +505,14 @@ func TestProposer_PendingDeposits_OutsideEth1FollowWindow(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
blk := util.NewBeaconBlock()
|
||||
@@ -638,10 +644,14 @@ func TestProposer_PendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -737,10 +747,14 @@ func TestProposer_PendingDeposits_CantReturnBelowStateEth1DepositIndex(t *testin
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -833,10 +847,14 @@ func TestProposer_PendingDeposits_CantReturnMoreThanMax(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -927,10 +945,14 @@ func TestProposer_PendingDeposits_CantReturnMoreThanDepositCount(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -1036,10 +1058,14 @@ func TestProposer_DepositTrie_UtilizesCachedFinalizedDeposits(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -1055,8 +1081,10 @@ func TestProposer_DepositTrie_UtilizesCachedFinalizedDeposits(t *testing.T) {
|
||||
trie, err := bs.depositTrie(ctx, ðpb.Eth1Data{}, big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)))
|
||||
require.NoError(t, err)
|
||||
|
||||
actualRoot := trie.HashTreeRoot()
|
||||
expectedRoot := depositTrie.HashTreeRoot()
|
||||
actualRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedRoot, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedRoot, actualRoot, "Incorrect deposit trie root")
|
||||
}
|
||||
|
||||
@@ -1146,10 +1174,14 @@ func TestProposer_DepositTrie_RebuildTrie(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
d := depositCache.AllDepositContainers(ctx)
|
||||
origDeposit, ok := proto.Clone(d[0].Deposit).(*ethpb.Deposit)
|
||||
@@ -1177,8 +1209,10 @@ func TestProposer_DepositTrie_RebuildTrie(t *testing.T) {
|
||||
trie, err := bs.depositTrie(ctx, ðpb.Eth1Data{}, big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)))
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedRoot := depositTrie.HashTreeRoot()
|
||||
actualRoot := trie.HashTreeRoot()
|
||||
expectedRoot, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
actualRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedRoot, actualRoot, "Incorrect deposit trie root")
|
||||
|
||||
}
|
||||
@@ -1230,7 +1264,8 @@ func TestProposer_ValidateDepositTrie(t *testing.T) {
|
||||
assert.NoError(t, trie.Insert([]byte{'a'}, 0))
|
||||
assert.NoError(t, trie.Insert([]byte{'b'}, 1))
|
||||
assert.NoError(t, trie.Insert([]byte{'c'}, 2))
|
||||
rt := trie.HashTreeRoot()
|
||||
rt, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
return ðpb.Eth1Data{DepositRoot: rt[:], DepositCount: 3, BlockHash: []byte{}}
|
||||
},
|
||||
trieCreator: func() *trie.SparseMerkleTrie {
|
||||
@@ -1274,7 +1309,9 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dc.Deposit, dc.Eth1BlockHeight, dc.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dc.Deposit, dc.Eth1BlockHeight, dc.Index, root))
|
||||
|
||||
t.Run("choose highest count", func(t *testing.T) {
|
||||
t.Skip()
|
||||
@@ -1976,10 +2013,14 @@ func TestProposer_Deposits_ReturnsEmptyList_IfLatestEth1DataEqGenesisEth1Block(t
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -2066,6 +2107,7 @@ func TestProposer_GetBeaconBlock_PreForkEpoch(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mock.ChainService{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -2178,6 +2220,7 @@ func TestProposer_GetBeaconBlock_PostForkEpoch(t *testing.T) {
|
||||
HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mock.ChainService{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: &mockPOW.POWChain{},
|
||||
@@ -2331,6 +2374,7 @@ func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) {
|
||||
TimeFetcher: &mock.ChainService{Genesis: time.Now()},
|
||||
SyncChecker: &mockSync.Sync{IsSyncing: false},
|
||||
BlockReceiver: &mock.ChainService{},
|
||||
HeadUpdater: &mock.ChainService{},
|
||||
ChainStartFetcher: &mockPOW.POWChain{},
|
||||
Eth1InfoFetcher: &mockPOW.POWChain{},
|
||||
Eth1BlockFetcher: c,
|
||||
|
||||
@@ -43,6 +43,7 @@ type Server struct {
|
||||
AttestationCache *cache.AttestationCache
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
TimeFetcher blockchain.TimeFetcher
|
||||
|
||||
@@ -137,7 +137,9 @@ func TestWaitForActivation_ValidatorOriginallyExists(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 10 /*blockNum*/, 0, root))
|
||||
trie, err := v1.InitializeFromProtoUnsafe(beaconState)
|
||||
require.NoError(t, err)
|
||||
vs := &Server{
|
||||
|
||||
@@ -41,7 +41,9 @@ func TestValidatorStatus_DepositedEth1(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -84,7 +86,9 @@ func TestValidatorStatus_Deposited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -134,7 +138,9 @@ func TestValidatorStatus_PartiallyDeposited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -202,7 +208,9 @@ func TestValidatorStatus_Pending(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
@@ -247,7 +255,9 @@ func TestValidatorStatus_Active(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
|
||||
// Active because activation epoch <= current epoch < exit epoch.
|
||||
activeEpoch := helpers.ActivationExitEpoch(0)
|
||||
@@ -334,7 +344,9 @@ func TestValidatorStatus_Exiting(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -391,7 +403,9 @@ func TestValidatorStatus_Slashing(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -449,7 +463,9 @@ func TestValidatorStatus_Exited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -532,11 +548,15 @@ func TestActivationStatus_OK(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, root))
|
||||
|
||||
dep = deposits[2]
|
||||
assert.NoError(t, depositTrie.Insert(dep.Data.Signature, 15))
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, depositTrie.HashTreeRoot()))
|
||||
root, err = depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, root))
|
||||
|
||||
vs := &Server{
|
||||
Ctx: context.Background(),
|
||||
@@ -677,7 +697,9 @@ func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
|
||||
deposit := ðpb.Deposit{
|
||||
Data: depData,
|
||||
}
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, int64(i), depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, int64(i), root))
|
||||
|
||||
}
|
||||
|
||||
@@ -758,10 +780,14 @@ func TestMultipleValidatorStatus_Pubkeys(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
dep := deposits[0]
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, root))
|
||||
dep = deposits[2]
|
||||
assert.NoError(t, depositTrie.Insert(dep.Data.Signature, 15))
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, depositTrie.HashTreeRoot()))
|
||||
root, err = depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, root))
|
||||
|
||||
vs := &Server{
|
||||
Ctx: context.Background(),
|
||||
@@ -918,7 +944,9 @@ func TestValidatorStatus_Invalid(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
|
||||
@@ -78,6 +78,7 @@ type Config struct {
|
||||
BeaconMonitoringPort int
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
HeadUpdater blockchain.HeadUpdater
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
CanonicalFetcher blockchain.CanonicalFetcher
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
@@ -189,6 +190,7 @@ func (s *Service) Start() {
|
||||
AttPool: s.cfg.AttestationsPool,
|
||||
ExitPool: s.cfg.ExitPool,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
HeadUpdater: s.cfg.HeadUpdater,
|
||||
ForkFetcher: s.cfg.ForkFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
TimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
@@ -215,6 +217,7 @@ func (s *Service) Start() {
|
||||
}
|
||||
validatorServerV1 := &validator.Server{
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
HeadUpdater: s.cfg.HeadUpdater,
|
||||
TimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
AttestationsPool: s.cfg.AttestationsPool,
|
||||
@@ -261,6 +264,7 @@ func (s *Service) Start() {
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
AttestationsPool: s.cfg.AttestationsPool,
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
HeadUpdater: s.cfg.HeadUpdater,
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
FinalizationFetcher: s.cfg.FinalizationFetcher,
|
||||
CanonicalFetcher: s.cfg.CanonicalFetcher,
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/state/state-native/custom-types:go_default_library",
|
||||
"//beacon-chain/state/state-native/types:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//beacon-chain/state/types:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
|
||||
@@ -16,7 +16,7 @@ type FieldTrie struct {
|
||||
*sync.RWMutex
|
||||
reference *stateutil.Reference
|
||||
fieldLayers [][]*[32]byte
|
||||
field types.FieldIndex
|
||||
field types.BeaconStateField
|
||||
dataType types.DataType
|
||||
length uint64
|
||||
numOfElems int
|
||||
@@ -25,7 +25,7 @@ type FieldTrie struct {
|
||||
// NewFieldTrie is the constructor for the field trie data structure. It creates the corresponding
|
||||
// trie according to the given parameters. Depending on whether the field is a basic/composite array
|
||||
// which is either fixed/variable length, it will appropriately determine the trie.
|
||||
func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) {
|
||||
func NewFieldTrie(field types.BeaconStateField, dataType types.DataType, elements interface{}, length uint64) (*FieldTrie, error) {
|
||||
if elements == nil {
|
||||
return &FieldTrie{
|
||||
field: field,
|
||||
@@ -36,10 +36,19 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
|
||||
numOfElems: 0,
|
||||
}, nil
|
||||
}
|
||||
fieldRoots, err := fieldConverters(field, []uint64{}, elements, true)
|
||||
|
||||
var fieldRoots [][32]byte
|
||||
var err error
|
||||
if field.Native() {
|
||||
fieldRoots, err = fieldConvertersNative(field, []uint64{}, elements, true)
|
||||
} else {
|
||||
fieldRoots, err = fieldConverters(field, []uint64{}, elements, true)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := validateElements(field, dataType, elements, length); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -84,10 +93,18 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if len(indices) == 0 {
|
||||
return f.TrieRoot()
|
||||
}
|
||||
fieldRoots, err := fieldConverters(f.field, indices, elements, false)
|
||||
|
||||
var fieldRoots [][32]byte
|
||||
var err error
|
||||
if f.field.Native() {
|
||||
fieldRoots, err = fieldConvertersNative(f.field, indices, elements, false)
|
||||
} else {
|
||||
fieldRoots, err = fieldConverters(f.field, indices, elements, false)
|
||||
}
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
if err := f.validateIndices(indices); err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
@@ -18,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
// ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers.
|
||||
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex types.FieldIndex) [][]byte {
|
||||
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte {
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
proof := make([][]byte, 0)
|
||||
@@ -49,7 +50,7 @@ func (f *FieldTrie) validateIndices(idxs []uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateElements(field types.FieldIndex, dataType types.DataType, elements interface{}, length uint64) error {
|
||||
func validateElements(field types.BeaconStateField, dataType types.DataType, elements interface{}, length uint64) error {
|
||||
if dataType == types.CompressedArray {
|
||||
comLength, err := field.ElemsInChunk()
|
||||
if err != nil {
|
||||
@@ -65,68 +66,118 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements
|
||||
}
|
||||
|
||||
// fieldConverters converts the corresponding field and the provided elements to the appropriate roots.
|
||||
func fieldConverters(field types.FieldIndex, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
func fieldConverters(field types.BeaconStateField, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch field {
|
||||
case types.BlockRoots:
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.BlockRoots:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for block roots")
|
||||
}
|
||||
return convertBlockRoots(indices, elements, convertAll)
|
||||
case types.StateRoots:
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.StateRoots:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for state roots")
|
||||
}
|
||||
return convertStateRoots(indices, elements, convertAll)
|
||||
case types.RandaoMixes:
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.RandaoMixes:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for randao mixes")
|
||||
}
|
||||
return convertRandaoMixes(indices, elements, convertAll)
|
||||
case types.Eth1DataVotes:
|
||||
val, ok := elements.([]*ethpb.Eth1Data)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleEth1DataSlice(val, indices, convertAll)
|
||||
return convertEth1DataVotes(indices, elements, convertAll)
|
||||
case types.Validators:
|
||||
val, ok := elements.([]*ethpb.Validator)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleValidatorSlice(val, indices, convertAll)
|
||||
return convertValidators(indices, elements, convertAll)
|
||||
case types.PreviousEpochAttestations, types.CurrentEpochAttestations:
|
||||
val, ok := elements.([]*ethpb.PendingAttestation)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handlePendingAttestationSlice(val, indices, convertAll)
|
||||
return convertAttestations(indices, elements, convertAll)
|
||||
case types.Balances:
|
||||
val, ok := elements.([]uint64)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleBalanceSlice(val, indices, convertAll)
|
||||
return convertBalances(indices, elements, convertAll)
|
||||
default:
|
||||
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name())
|
||||
}
|
||||
}
|
||||
|
||||
// fieldConvertersNative converts the corresponding field and the provided elements to the appropriate roots.
|
||||
func fieldConvertersNative(field types.BeaconStateField, indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch field {
|
||||
case nativetypes.BlockRoots:
|
||||
return convertBlockRoots(indices, elements, convertAll)
|
||||
case nativetypes.StateRoots:
|
||||
return convertStateRoots(indices, elements, convertAll)
|
||||
case nativetypes.RandaoMixes:
|
||||
return convertRandaoMixes(indices, elements, convertAll)
|
||||
case nativetypes.Eth1DataVotes:
|
||||
return convertEth1DataVotes(indices, elements, convertAll)
|
||||
case nativetypes.Validators:
|
||||
return convertValidators(indices, elements, convertAll)
|
||||
case nativetypes.PreviousEpochAttestations, nativetypes.CurrentEpochAttestations:
|
||||
return convertAttestations(indices, elements, convertAll)
|
||||
case nativetypes.Balances:
|
||||
return convertBalances(indices, elements, convertAll)
|
||||
default:
|
||||
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name())
|
||||
}
|
||||
}
|
||||
|
||||
func convertBlockRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.BlockRoots:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for block roots")
|
||||
}
|
||||
}
|
||||
|
||||
func convertStateRoots(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.StateRoots:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for state roots")
|
||||
}
|
||||
}
|
||||
|
||||
func convertRandaoMixes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
switch val := elements.(type) {
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.RandaoMixes:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for randao mixes")
|
||||
}
|
||||
}
|
||||
|
||||
func convertEth1DataVotes(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
val, ok := elements.([]*ethpb.Eth1Data)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Eth1Data{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleEth1DataSlice(val, indices, convertAll)
|
||||
}
|
||||
|
||||
func convertValidators(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
val, ok := elements.([]*ethpb.Validator)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.Validator{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleValidatorSlice(val, indices, convertAll)
|
||||
}
|
||||
|
||||
func convertAttestations(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
val, ok := elements.([]*ethpb.PendingAttestation)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handlePendingAttestationSlice(val, indices, convertAll)
|
||||
}
|
||||
|
||||
func convertBalances(indices []uint64, elements interface{}, convertAll bool) ([][32]byte, error) {
|
||||
val, ok := elements.([]uint64)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Wanted type of %v but got %v",
|
||||
reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name())
|
||||
}
|
||||
return handleBalanceSlice(val, indices, convertAll)
|
||||
}
|
||||
|
||||
// handleByteArrays computes and returns byte arrays in a slice of root format.
|
||||
func handleByteArrays(val [][]byte, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestFieldTrie_NewTrie(t *testing.T) {
|
||||
newState, _ := util.DeterministicGenesisState(t, 40)
|
||||
|
||||
// 5 represents the enum value of state roots
|
||||
trie, err := fieldtrie.NewFieldTrie(5, stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(5), stateTypes.BasicArray, newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
root, err := stateutil.RootsArrayHashTreeRoot(newState.StateRoots(), uint64(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
@@ -30,7 +30,7 @@ func TestFieldTrie_NewTrie(t *testing.T) {
|
||||
func TestFieldTrie_RecomputeTrie(t *testing.T) {
|
||||
newState, _ := util.DeterministicGenesisState(t, 32)
|
||||
// 10 represents the enum value of validators
|
||||
trie, err := fieldtrie.NewFieldTrie(11, stateTypes.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit)
|
||||
trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(11), stateTypes.CompositeArray, newState.Validators(), params.BeaconConfig().ValidatorRegistryLimit)
|
||||
require.NoError(t, err)
|
||||
|
||||
changedIdx := []uint64{2, 29}
|
||||
@@ -58,7 +58,7 @@ func TestFieldTrie_RecomputeTrie(t *testing.T) {
|
||||
func TestFieldTrie_CopyTrieImmutable(t *testing.T) {
|
||||
newState, _ := util.DeterministicGenesisState(t, 32)
|
||||
// 12 represents the enum value of randao mixes.
|
||||
trie, err := fieldtrie.NewFieldTrie(13, stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
trie, err := fieldtrie.NewFieldTrie(stateTypes.FieldIndex(13), stateTypes.BasicArray, newState.RandaoMixes(), uint64(params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
require.NoError(t, err)
|
||||
|
||||
newTrie := trie.CopyTrie()
|
||||
|
||||
@@ -18,7 +18,7 @@ var (
|
||||
// State returns a copy of the genesis state from a hardcoded value.
|
||||
func State(name string) (state.BeaconState, error) {
|
||||
switch name {
|
||||
case params.ConfigNames[params.Mainnet]:
|
||||
case params.MainnetName:
|
||||
return load(mainnetRawSSZCompressed)
|
||||
default:
|
||||
// No state found.
|
||||
|
||||
@@ -9,15 +9,15 @@ import (
|
||||
|
||||
func TestGenesisState(t *testing.T) {
|
||||
tests := []struct {
|
||||
name params.ConfigName
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: params.Mainnet,
|
||||
name: params.MainnetName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(params.ConfigNames[tt.name], func(t *testing.T) {
|
||||
st, err := genesis.State(params.ConfigNames[tt.name])
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st, err := genesis.State(tt.name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
load("//proto:ssz_proto_library.bzl", "ssz_proto_files")
|
||||
load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"field_roots.go",
|
||||
"getters_attestation.go",
|
||||
"getters_block.go",
|
||||
"getters_checkpoint.go",
|
||||
"getters_eth1.go",
|
||||
"getters_misc.go",
|
||||
"getters_participation.go",
|
||||
"getters_payload_header.go",
|
||||
"getters_randao.go",
|
||||
"getters_state.go",
|
||||
"getters_sync_committee.go",
|
||||
"getters_validator.go",
|
||||
"hasher.go",
|
||||
"proofs.go",
|
||||
"readonly_validator.go",
|
||||
"setters_attestation.go",
|
||||
@@ -22,19 +23,20 @@ go_library(
|
||||
"setters_checkpoint.go",
|
||||
"setters_eth1.go",
|
||||
"setters_misc.go",
|
||||
"setters_participation.go",
|
||||
"setters_payload_header.go",
|
||||
"setters_randao.go",
|
||||
"setters_state.go",
|
||||
"setters_sync_committee.go",
|
||||
"setters_validator.go",
|
||||
"ssz.go",
|
||||
"state_trie.go",
|
||||
"types.go",
|
||||
"unsupported_getters.go",
|
||||
"unsupported_setters.go",
|
||||
":ssz_generated_files", # keep
|
||||
] + select({
|
||||
"//config:mainnet": ["beacon_state_mainnet.go"],
|
||||
"//config:minimal": ["beacon_state_minimal.go"],
|
||||
}),
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1",
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//contracts/deposit:__subpackages__",
|
||||
@@ -54,6 +56,7 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/fieldtrie:go_default_library",
|
||||
"//beacon-chain/state/state-native/custom-types:go_default_library",
|
||||
"//beacon-chain/state/state-native/types:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//beacon-chain/state/types:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
@@ -73,14 +76,15 @@ go_library(
|
||||
],
|
||||
)
|
||||
|
||||
# gazelle:exclude types_bench_test.go
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"getters_attestation_test.go",
|
||||
"getters_block_test.go",
|
||||
"getters_checkpoint_test.go",
|
||||
"getters_test.go",
|
||||
"getters_validator_test.go",
|
||||
"hasher_test.go",
|
||||
"proofs_test.go",
|
||||
"readonly_validator_test.go",
|
||||
"references_test.go",
|
||||
@@ -95,9 +99,12 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/state-native/types:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//beacon-chain/state/testing:go_default_library",
|
||||
"//beacon-chain/state/types:go_default_library",
|
||||
"//beacon-chain/state/v1:go_default_library",
|
||||
"//beacon-chain/state/v2:go_default_library",
|
||||
"//beacon-chain/state/v3:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
@@ -113,20 +120,3 @@ go_test(
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
ssz_gen_marshal(
|
||||
name = "ssz_generated_files",
|
||||
srcs = select({
|
||||
"//config:mainnet": ["beacon_state_mainnet.go"],
|
||||
"//config:minimal": ["beacon_state_minimal.go"],
|
||||
}),
|
||||
includes = [
|
||||
"//beacon-chain/state/state-native/custom-types:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
],
|
||||
objs = [
|
||||
"BeaconState[no-htr]",
|
||||
],
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build !minimal
|
||||
// +build !minimal
|
||||
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -9,15 +9,16 @@ import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// BeaconState defines a struct containing utilities for the eth2 chain state, defining
|
||||
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
|
||||
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
|
||||
type BeaconState struct {
|
||||
version int
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
@@ -33,6 +34,8 @@ type BeaconState struct {
|
||||
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"`
|
||||
slashings []uint64 `ssz-gen:"true" ssz-size:"8192"`
|
||||
previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
|
||||
currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
|
||||
previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
|
||||
@@ -45,11 +48,11 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeader *ethpb.ExecutionPayloadHeader `ssz-gen:"true"`
|
||||
|
||||
lock sync.RWMutex
|
||||
dirtyFields map[types.FieldIndex]bool
|
||||
dirtyIndices map[types.FieldIndex][]uint64
|
||||
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
|
||||
rebuildTrie map[types.FieldIndex]bool
|
||||
dirtyFields map[nativetypes.FieldIndex]bool
|
||||
dirtyIndices map[nativetypes.FieldIndex][]uint64
|
||||
stateFieldLeaves map[nativetypes.FieldIndex]*fieldtrie.FieldTrie
|
||||
rebuildTrie map[nativetypes.FieldIndex]bool
|
||||
valMapHandler *stateutil.ValidatorMapHandler
|
||||
merkleLayers [][][]byte
|
||||
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
|
||||
sharedFieldReferences map[nativetypes.FieldIndex]*stateutil.Reference
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build !minimal
|
||||
// +build !minimal
|
||||
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
@@ -79,4 +80,9 @@ func TestMainnetSszValuesAgainstFieldParams(t *testing.T) {
|
||||
require.Equal(t, true, ok, "Required field not found")
|
||||
v = f.Tag.Get("ssz-size")
|
||||
assert.Equal(t, "1", v)
|
||||
|
||||
f, ok = bsType.FieldByName("inactivityScores")
|
||||
require.Equal(t, true, ok, "Required field not found")
|
||||
v = f.Tag.Get("ssz-max")
|
||||
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build minimal
|
||||
// +build minimal
|
||||
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -9,15 +9,16 @@ import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
|
||||
eth2types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// BeaconState defines a struct containing utilities for the eth2 chain state, defining
|
||||
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
|
||||
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
|
||||
type BeaconState struct {
|
||||
version int
|
||||
genesisTime uint64 `ssz-gen:"true"`
|
||||
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
|
||||
slot eth2types.Slot `ssz-gen:"true"`
|
||||
@@ -33,6 +34,8 @@ type BeaconState struct {
|
||||
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"`
|
||||
slashings []uint64 `ssz-gen:"true" ssz-size:"64"`
|
||||
previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"`
|
||||
currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"`
|
||||
previousEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
currentEpochParticipation []byte `ssz-gen:"true" ssz-max:"1099511627776"`
|
||||
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
|
||||
@@ -45,11 +48,11 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeader *ethpb.ExecutionPayloadHeader `ssz-gen:"true"`
|
||||
|
||||
lock sync.RWMutex
|
||||
dirtyFields map[types.FieldIndex]bool
|
||||
dirtyIndices map[types.FieldIndex][]uint64
|
||||
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
|
||||
rebuildTrie map[types.FieldIndex]bool
|
||||
dirtyFields map[nativetypes.FieldIndex]bool
|
||||
dirtyIndices map[nativetypes.FieldIndex][]uint64
|
||||
stateFieldLeaves map[nativetypes.FieldIndex]*fieldtrie.FieldTrie
|
||||
rebuildTrie map[nativetypes.FieldIndex]bool
|
||||
valMapHandler *stateutil.ValidatorMapHandler
|
||||
merkleLayers [][][]byte
|
||||
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
|
||||
sharedFieldReferences map[nativetypes.FieldIndex]*stateutil.Reference
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build minimal
|
||||
// +build minimal
|
||||
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@@ -79,4 +79,9 @@ func TestMinimalSszValuesAgainstFieldParams(t *testing.T) {
|
||||
require.Equal(t, true, ok, "Required field not found")
|
||||
v = f.Tag.Get("ssz-size")
|
||||
assert.Equal(t, "1", v)
|
||||
|
||||
f, ok = bsType.FieldByName("inactivityScores")
|
||||
require.Equal(t, true, ok, "Required field not found")
|
||||
v = f.Tag.Get("ssz-max")
|
||||
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
// Package v1 defines how the beacon chain state for Ethereum
|
||||
// Package state_native defines how the beacon chain state for Ethereum
|
||||
// functions in the running beacon node, using an advanced,
|
||||
// immutable implementation of the state data structure.
|
||||
//
|
||||
// BeaconState getters may be accessed from inside or outside the package. To
|
||||
// avoid duplicating locks, we have internal and external versions of the
|
||||
// getter The external function carries out the short-circuit conditions,
|
||||
// obtains a read lock, then calls the internal function. The internal function
|
||||
// carries out the short-circuit conditions and returns the required data
|
||||
// without further locking, allowing it to be used by other package-level
|
||||
// functions that already hold a lock. Hence the functions look something
|
||||
// like this:
|
||||
// getter. The external function obtains a read lock, then calls the internal function.
|
||||
// The internal function returns the required data without further locking,
|
||||
// allowing it to be used by other package-level functions that already hold a lock.
|
||||
// Hence the functions look something like this:
|
||||
//
|
||||
// func (b *BeaconState) Foo() uint64 {
|
||||
// // Short-circuit conditions.
|
||||
// if !b.hasInnerState() {
|
||||
// return 0
|
||||
// }
|
||||
//
|
||||
// // Read lock.
|
||||
// b.lock.RLock()
|
||||
// defer b.lock.RUnlock()
|
||||
@@ -26,15 +19,12 @@
|
||||
// }
|
||||
//
|
||||
// func (b *BeaconState) foo() uint64 {
|
||||
// // Short-circuit conditions.
|
||||
// if !b.hasInnerState() {
|
||||
// return 0
|
||||
// }
|
||||
// (...) // Some processing logic.
|
||||
//
|
||||
// return b.state.foo
|
||||
// return b.foo
|
||||
// }
|
||||
//
|
||||
// Although it is technically possible to remove the short-circuit conditions
|
||||
// from the external function, that would require every read to obtain a lock
|
||||
// even if the data was not present, leading to potential slowdowns.
|
||||
package v1
|
||||
package state_native
|
||||
@@ -1,11 +1,16 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// PreviousEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if b.version != version.Phase0 {
|
||||
return nil, errNotSupported("PreviousEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
if b.previousEpochAttestations == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -24,6 +29,10 @@ func (b *BeaconState) previousEpochAttestationsVal() []*ethpb.PendingAttestation
|
||||
|
||||
// CurrentEpochAttestations corresponding to blocks on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) {
|
||||
if b.version != version.Phase0 {
|
||||
return nil, errNotSupported("CurrentEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
if b.currentEpochAttestations == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
)
|
||||
|
||||
func TestBeaconState_PreviousEpochAttestations(t *testing.T) {
|
||||
s, err := InitializeFromProto(ðpb.BeaconState{})
|
||||
s, err := InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
atts, err := s.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts)
|
||||
|
||||
want := []*ethpb.PendingAttestation{{ProposerIndex: 100}}
|
||||
s, err = InitializeFromProto(ðpb.BeaconState{PreviousEpochAttestations: want})
|
||||
s, err = InitializeFromProtoPhase0(ðpb.BeaconState{PreviousEpochAttestations: want})
|
||||
require.NoError(t, err)
|
||||
got, err := s.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
@@ -27,14 +27,14 @@ func TestBeaconState_PreviousEpochAttestations(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentEpochAttestations(t *testing.T) {
|
||||
s, err := InitializeFromProto(ðpb.BeaconState{})
|
||||
s, err := InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
atts, err := s.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, []*ethpb.PendingAttestation(nil), atts)
|
||||
|
||||
want := []*ethpb.PendingAttestation{{ProposerIndex: 101}}
|
||||
s, err = InitializeFromProto(ðpb.BeaconState{CurrentEpochAttestations: want})
|
||||
s, err = InitializeFromProtoPhase0(ðpb.BeaconState{CurrentEpochAttestations: want})
|
||||
require.NoError(t, err)
|
||||
got, err := s.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
@@ -1,4 +1,4 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
117
beacon-chain/state/state-native/getters_block_test.go
Normal file
117
beacon-chain/state/state-native/getters_block_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func TestBeaconState_LatestBlockHeader_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateLatestBlockHeader(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
},
|
||||
func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{LatestBlockHeader: BH})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_LatestBlockHeader_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateLatestBlockHeader(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{})
|
||||
},
|
||||
func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{LatestBlockHeader: BH})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_LatestBlockHeader_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateLatestBlockHeader(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
},
|
||||
func(BH *ethpb.BeaconBlockHeader) (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{LatestBlockHeader: BH})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRoots_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootsNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRoots_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootsNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRoots_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootsNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRootAtIndex_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootAtIndexNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRootAtIndex_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootAtIndexNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_BlockRootAtIndex_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateBlockRootAtIndexNative(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
},
|
||||
func(BR [][]byte) (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{BlockRoots: BR})
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
202
beacon-chain/state/state-native/getters_checkpoint_test.go
Normal file
202
beacon-chain/state/state-native/getters_checkpoint_test.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpointNil_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpointNil_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpointNil_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpoint_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpoint_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_PreviousJustifiedCheckpoint_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStatePreviousJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpointNil_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpointNil_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpointNil_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpoint_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpoint_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_CurrentJustifiedCheckpoint_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateCurrentJustifiedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpointNil_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpointNil_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpointNil_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpointNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpoint_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{FinalizedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpoint_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{FinalizedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_FinalizedCheckpoint_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateFinalizedCheckpoint(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{FinalizedCheckpoint: cp})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBitsNil_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBitsNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBitsNil_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBitsNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBitsNil_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBitsNil(
|
||||
t,
|
||||
func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBits_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBits(
|
||||
t,
|
||||
func(bits bitfield.Bitvector4) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafePhase0(ðpb.BeaconState{JustificationBits: bits})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBits_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBits(
|
||||
t,
|
||||
func(bits bitfield.Bitvector4) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{JustificationBits: bits})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_JustificationBits_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateJustificationBits(
|
||||
t,
|
||||
func(bits bitfield.Bitvector4) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{JustificationBits: bits})
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -1,9 +1,8 @@
|
||||
package v2
|
||||
package state_native
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// GenesisTime of the beacon state as a uint64.
|
||||
@@ -25,8 +24,8 @@ func (b *BeaconState) GenesisValidatorsRoot() []byte {
|
||||
// Version of the beacon state. This method
|
||||
// is strictly meant to be used without a lock
|
||||
// internally.
|
||||
func (_ *BeaconState) Version() int {
|
||||
return version.Altair
|
||||
func (b *BeaconState) Version() int {
|
||||
return b.version
|
||||
}
|
||||
|
||||
// Slot of the current beacon chain state.
|
||||
@@ -1,7 +1,15 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// CurrentEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("CurrentEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
if b.currentEpochParticipation == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -14,6 +22,10 @@ func (b *BeaconState) CurrentEpochParticipation() ([]byte, error) {
|
||||
|
||||
// PreviousEpochParticipation corresponding to participation bits on the beacon chain.
|
||||
func (b *BeaconState) PreviousEpochParticipation() ([]byte, error) {
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("PreviousEpochParticipation", b.version)
|
||||
}
|
||||
|
||||
if b.previousEpochParticipation == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// LatestExecutionPayloadHeader of the beacon state.
|
||||
func (b *BeaconState) LatestExecutionPayloadHeader() (*ethpb.ExecutionPayloadHeader, error) {
|
||||
if b.version == version.Phase0 || b.version == version.Altair {
|
||||
return nil, errNotSupported("LatestExecutionPayloadHeader", b.version)
|
||||
}
|
||||
|
||||
if b.latestExecutionPayloadHeader == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
279
beacon-chain/state/state-native/getters_state.go
Normal file
279
beacon-chain/state/state-native/getters_state.go
Normal file
@@ -0,0 +1,279 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// ToProtoUnsafe returns the pointer value of the underlying
|
||||
// beacon state proto object, bypassing immutability. Use with care.
|
||||
func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
gvrCopy := b.genesisValidatorsRoot
|
||||
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
return ðpb.BeaconState{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.fork,
|
||||
LatestBlockHeader: b.latestBlockHeader,
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1Data,
|
||||
Eth1DataVotes: b.eth1DataVotes,
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validators,
|
||||
Balances: b.balances,
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashings,
|
||||
PreviousEpochAttestations: b.previousEpochAttestations,
|
||||
CurrentEpochAttestations: b.currentEpochAttestations,
|
||||
JustificationBits: b.justificationBits,
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
}
|
||||
case version.Altair:
|
||||
return ðpb.BeaconStateAltair{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.fork,
|
||||
LatestBlockHeader: b.latestBlockHeader,
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1Data,
|
||||
Eth1DataVotes: b.eth1DataVotes,
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validators,
|
||||
Balances: b.balances,
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashings,
|
||||
PreviousEpochParticipation: b.previousEpochParticipation,
|
||||
CurrentEpochParticipation: b.currentEpochParticipation,
|
||||
JustificationBits: b.justificationBits,
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
InactivityScores: b.inactivityScores,
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
}
|
||||
case version.Bellatrix:
|
||||
return ðpb.BeaconStateBellatrix{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.fork,
|
||||
LatestBlockHeader: b.latestBlockHeader,
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1Data,
|
||||
Eth1DataVotes: b.eth1DataVotes,
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validators,
|
||||
Balances: b.balances,
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashings,
|
||||
PreviousEpochParticipation: b.previousEpochParticipation,
|
||||
CurrentEpochParticipation: b.currentEpochParticipation,
|
||||
JustificationBits: b.justificationBits,
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
InactivityScores: b.inactivityScores,
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader,
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ToProto the beacon state into a protobuf for usage.
|
||||
func (b *BeaconState) ToProto() interface{} {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
gvrCopy := b.genesisValidatorsRoot
|
||||
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
return ðpb.BeaconState{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.forkVal(),
|
||||
LatestBlockHeader: b.latestBlockHeaderVal(),
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1DataVal(),
|
||||
Eth1DataVotes: b.eth1DataVotesVal(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validatorsVal(),
|
||||
Balances: b.balancesVal(),
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashingsVal(),
|
||||
PreviousEpochAttestations: b.previousEpochAttestationsVal(),
|
||||
CurrentEpochAttestations: b.currentEpochAttestationsVal(),
|
||||
JustificationBits: b.justificationBitsVal(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpointVal(),
|
||||
}
|
||||
case version.Altair:
|
||||
return ðpb.BeaconStateAltair{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.forkVal(),
|
||||
LatestBlockHeader: b.latestBlockHeaderVal(),
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1DataVal(),
|
||||
Eth1DataVotes: b.eth1DataVotesVal(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validatorsVal(),
|
||||
Balances: b.balancesVal(),
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashingsVal(),
|
||||
PreviousEpochParticipation: b.previousEpochParticipationVal(),
|
||||
CurrentEpochParticipation: b.currentEpochParticipationVal(),
|
||||
JustificationBits: b.justificationBitsVal(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpointVal(),
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
|
||||
NextSyncCommittee: b.nextSyncCommitteeVal(),
|
||||
}
|
||||
case version.Bellatrix:
|
||||
return ðpb.BeaconStateBellatrix{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.forkVal(),
|
||||
LatestBlockHeader: b.latestBlockHeaderVal(),
|
||||
BlockRoots: b.blockRoots.Slice(),
|
||||
StateRoots: b.stateRoots.Slice(),
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1DataVal(),
|
||||
Eth1DataVotes: b.eth1DataVotesVal(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validatorsVal(),
|
||||
Balances: b.balancesVal(),
|
||||
RandaoMixes: b.randaoMixes.Slice(),
|
||||
Slashings: b.slashingsVal(),
|
||||
PreviousEpochParticipation: b.previousEpochParticipationVal(),
|
||||
CurrentEpochParticipation: b.currentEpochParticipationVal(),
|
||||
JustificationBits: b.justificationBitsVal(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpointVal(),
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
|
||||
NextSyncCommittee: b.nextSyncCommitteeVal(),
|
||||
LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// StateRoots kept track of in the beacon state.
|
||||
func (b *BeaconState) StateRoots() [][]byte {
|
||||
if b.stateRoots == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.stateRoots.Slice()
|
||||
}
|
||||
|
||||
// StateRootAtIndex retrieves a specific state root based on an
|
||||
// input index value.
|
||||
func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
|
||||
if b.stateRoots == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
r, err := b.stateRootAtIndex(idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r[:], nil
|
||||
}
|
||||
|
||||
// stateRootAtIndex retrieves a specific state root based on an
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.stateRoots)) <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.stateRoots[idx], nil
|
||||
}
|
||||
|
||||
// ProtobufBeaconStatePhase0 transforms an input into beacon state in the form of protobuf.
|
||||
// Error is returned if the input is not type protobuf beacon state.
|
||||
func ProtobufBeaconStatePhase0(s interface{}) (*ethpb.BeaconState, error) {
|
||||
pbState, ok := s.(*ethpb.BeaconState)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type ethpb.BeaconState")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
// ProtobufBeaconStateAltair transforms an input into beacon state Altair in the form of protobuf.
|
||||
// Error is returned if the input is not type protobuf beacon state.
|
||||
func ProtobufBeaconStateAltair(s interface{}) (*ethpb.BeaconStateAltair, error) {
|
||||
pbState, ok := s.(*ethpb.BeaconStateAltair)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type pb.BeaconStateAltair")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
// ProtobufBeaconStateBellatrix transforms an input into beacon state Bellatrix in the form of protobuf.
|
||||
// Error is returned if the input is not type protobuf beacon state.
|
||||
func ProtobufBeaconStateBellatrix(s interface{}) (*ethpb.BeaconStateBellatrix, error) {
|
||||
pbState, ok := s.(*ethpb.BeaconStateBellatrix)
|
||||
if !ok {
|
||||
return nil, errors.New("input is not type pb.BeaconStateBellatrix")
|
||||
}
|
||||
return pbState, nil
|
||||
}
|
||||
|
||||
// InnerStateUnsafe returns the pointer value of the underlying
|
||||
// beacon state proto object, bypassing immutability. Use with care.
|
||||
func (b *BeaconState) InnerStateUnsafe() interface{} {
|
||||
return b.ToProtoUnsafe()
|
||||
}
|
||||
|
||||
// CloneInnerState the beacon state into a protobuf for usage.
|
||||
func (b *BeaconState) CloneInnerState() interface{} {
|
||||
return b.ToProto()
|
||||
}
|
||||
@@ -1,27 +1,20 @@
|
||||
package v2
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// currentSyncCommitteeVal of the current sync committee in beacon chain state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee {
|
||||
return CopySyncCommittee(b.currentSyncCommittee)
|
||||
}
|
||||
|
||||
// nextSyncCommitteeVal of the next sync committee in beacon chain state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) nextSyncCommitteeVal() *ethpb.SyncCommittee {
|
||||
return CopySyncCommittee(b.nextSyncCommittee)
|
||||
}
|
||||
|
||||
// CurrentSyncCommittee of the current sync committee in beacon chain state.
|
||||
func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("CurrentSyncCommittee", b.version)
|
||||
}
|
||||
|
||||
if b.currentSyncCommittee == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -29,11 +22,21 @@ func (b *BeaconState) CurrentSyncCommittee() (*ethpb.SyncCommittee, error) {
|
||||
return b.currentSyncCommitteeVal(), nil
|
||||
}
|
||||
|
||||
// currentSyncCommitteeVal of the current sync committee in beacon chain state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) currentSyncCommitteeVal() *ethpb.SyncCommittee {
|
||||
return copySyncCommittee(b.currentSyncCommittee)
|
||||
}
|
||||
|
||||
// NextSyncCommittee of the next sync committee in beacon chain state.
|
||||
func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("NextSyncCommittee", b.version)
|
||||
}
|
||||
|
||||
if b.nextSyncCommittee == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -41,8 +44,14 @@ func (b *BeaconState) NextSyncCommittee() (*ethpb.SyncCommittee, error) {
|
||||
return b.nextSyncCommitteeVal(), nil
|
||||
}
|
||||
|
||||
// CopySyncCommittee copies the provided sync committee object.
|
||||
func CopySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee {
|
||||
// nextSyncCommitteeVal of the next sync committee in beacon chain state.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) nextSyncCommitteeVal() *ethpb.SyncCommittee {
|
||||
return copySyncCommittee(b.nextSyncCommittee)
|
||||
}
|
||||
|
||||
// copySyncCommittee copies the provided sync committee object.
|
||||
func copySyncCommittee(data *ethpb.SyncCommittee) *ethpb.SyncCommittee {
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
99
beacon-chain/state/state-native/getters_test.go
Normal file
99
beacon-chain/state/state-native/getters_test.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func TestBeaconState_SlotDataRace_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{Slot: 1})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_SlotDataRace_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{Slot: 1})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_SlotDataRace_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateSlotDataRace(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{Slot: 1})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchCurrentJustifiedCheckpt_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{CurrentJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchCurrentJustifiedCheckpt_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{CurrentJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchCurrentJustifiedCheckpt_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchCurrentJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{CurrentJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchPreviousJustifiedCheckpt_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{PreviousJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchPreviousJustifiedCheckpt_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{PreviousJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_MatchPreviousJustifiedCheckpt_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateMatchPreviousJustifiedCheckptNative(
|
||||
t,
|
||||
func(cp *ethpb.Checkpoint) (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{PreviousJustifiedCheckpoint: cp})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestBeaconState_ValidatorByPubkey_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_ValidatorByPubkey_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoAltair(ðpb.BeaconStateAltair{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_ValidatorByPubkey_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorByPubkey(t, func() (state.BeaconState, error) {
|
||||
return InitializeFromProtoBellatrix(ðpb.BeaconStateBellatrix{})
|
||||
})
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// ValidatorIndexOutOfRangeError represents an error scenario where a validator does not exist
|
||||
@@ -111,7 +111,7 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return v1.NewValidator(b.validators[idx])
|
||||
return NewValidator(b.validators[idx])
|
||||
}
|
||||
|
||||
// ValidatorIndexByPubkey returns a given validator by its 48-byte public key.
|
||||
@@ -164,7 +164,7 @@ func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyV
|
||||
b.lock.RUnlock()
|
||||
|
||||
for i, v := range validators {
|
||||
v, err := v1.NewValidator(v)
|
||||
v, err := NewValidator(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -250,6 +250,22 @@ func (b *BeaconState) slashingsVal() []uint64 {
|
||||
return res
|
||||
}
|
||||
|
||||
// InactivityScores of validators participating in consensus on the beacon chain.
|
||||
func (b *BeaconState) InactivityScores() ([]uint64, error) {
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("InactivityScores", b.version)
|
||||
}
|
||||
|
||||
if b.inactivityScores == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.inactivityScoresVal(), nil
|
||||
}
|
||||
|
||||
// inactivityScoresVal of validators participating in consensus on the beacon chain.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) inactivityScoresVal() []uint64 {
|
||||
@@ -261,15 +277,3 @@ func (b *BeaconState) inactivityScoresVal() []uint64 {
|
||||
copy(res, b.inactivityScores)
|
||||
return res
|
||||
}
|
||||
|
||||
// InactivityScores of validators participating in consensus on the beacon chain.
|
||||
func (b *BeaconState) InactivityScores() ([]uint64, error) {
|
||||
if b.inactivityScores == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.inactivityScoresVal(), nil
|
||||
}
|
||||
34
beacon-chain/state/state-native/getters_validator_test.go
Normal file
34
beacon-chain/state/state-native/getters_validator_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
testtmpl "github.com/prysmaticlabs/prysm/beacon-chain/state/testing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Phase0(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) {
|
||||
return statenative.InitializeFromProtoUnsafePhase0(ðpb.BeaconState{
|
||||
Validators: nil,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Altair(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) {
|
||||
return statenative.InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{
|
||||
Validators: nil,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestBeaconState_ValidatorAtIndexReadOnly_HandlesNilSlice_Bellatrix(t *testing.T) {
|
||||
testtmpl.VerifyBeaconStateValidatorAtIndexReadOnlyHandlesNilSlice(t, func() (state.BeaconState, error) {
|
||||
return statenative.InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{
|
||||
Validators: nil,
|
||||
})
|
||||
})
|
||||
}
|
||||
240
beacon-chain/state/state-native/hasher.go
Normal file
240
beacon-chain/state/state-native/hasher.go
Normal file
@@ -0,0 +1,240 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/encoding/ssz"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ComputeFieldRootsWithHasher hashes the provided state and returns its respective field roots.
|
||||
func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasher")
|
||||
defer span.End()
|
||||
|
||||
if state == nil {
|
||||
return nil, errors.New("nil state")
|
||||
}
|
||||
hasher := hash.CustomSHA256Hasher()
|
||||
var fieldRoots [][]byte
|
||||
switch state.version {
|
||||
case version.Phase0:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateFieldCount)
|
||||
case version.Altair:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateAltairFieldCount)
|
||||
case version.Bellatrix:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateBellatrixFieldCount)
|
||||
}
|
||||
|
||||
// Genesis time root.
|
||||
genesisRoot := ssz.Uint64Root(state.genesisTime)
|
||||
fieldRoots[nativetypes.GenesisTime.RealPosition()] = genesisRoot[:]
|
||||
|
||||
// Genesis validators root.
|
||||
r := [32]byte{}
|
||||
copy(r[:], state.genesisValidatorsRoot[:])
|
||||
fieldRoots[nativetypes.GenesisValidatorsRoot.RealPosition()] = r[:]
|
||||
|
||||
// Slot root.
|
||||
slotRoot := ssz.Uint64Root(uint64(state.slot))
|
||||
fieldRoots[nativetypes.Slot.RealPosition()] = slotRoot[:]
|
||||
|
||||
// Fork data structure root.
|
||||
forkHashTreeRoot, err := ssz.ForkRoot(state.fork)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute fork merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Fork.RealPosition()] = forkHashTreeRoot[:]
|
||||
|
||||
// BeaconBlockHeader data structure root.
|
||||
headerHashTreeRoot, err := stateutil.BlockHeaderRoot(state.latestBlockHeader)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block header merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.LatestBlockHeader.RealPosition()] = headerHashTreeRoot[:]
|
||||
|
||||
// BlockRoots array root.
|
||||
bRoots := make([][]byte, len(state.blockRoots))
|
||||
for i := range bRoots {
|
||||
bRoots[i] = state.blockRoots[i][:]
|
||||
}
|
||||
blockRootsRoot, err := stateutil.ArraysRoot(bRoots, fieldparams.BlockRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute block roots merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.BlockRoots.RealPosition()] = blockRootsRoot[:]
|
||||
|
||||
// StateRoots array root.
|
||||
sRoots := make([][]byte, len(state.stateRoots))
|
||||
for i := range sRoots {
|
||||
sRoots[i] = state.stateRoots[i][:]
|
||||
}
|
||||
stateRootsRoot, err := stateutil.ArraysRoot(sRoots, fieldparams.StateRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute state roots merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.StateRoots.RealPosition()] = stateRootsRoot[:]
|
||||
|
||||
// HistoricalRoots slice root.
|
||||
hRoots := make([][]byte, len(state.historicalRoots))
|
||||
for i := range hRoots {
|
||||
hRoots[i] = state.historicalRoots[i][:]
|
||||
}
|
||||
historicalRootsRt, err := ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute historical roots merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.HistoricalRoots.RealPosition()] = historicalRootsRt[:]
|
||||
|
||||
// Eth1Data data structure root.
|
||||
eth1HashTreeRoot, err := stateutil.Eth1Root(hasher, state.eth1Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute eth1data merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Eth1Data.RealPosition()] = eth1HashTreeRoot[:]
|
||||
|
||||
// Eth1DataVotes slice root.
|
||||
eth1VotesRoot, err := stateutil.Eth1DataVotesRoot(state.eth1DataVotes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute eth1data votes merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Eth1DataVotes.RealPosition()] = eth1VotesRoot[:]
|
||||
|
||||
// Eth1DepositIndex root.
|
||||
eth1DepositIndexBuf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.eth1DepositIndex)
|
||||
eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf)
|
||||
fieldRoots[nativetypes.Eth1DepositIndex.RealPosition()] = eth1DepositBuf[:]
|
||||
|
||||
// Validators slice root.
|
||||
validatorsRoot, err := stateutil.ValidatorRegistryRoot(state.validators)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute validator registry merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Validators.RealPosition()] = validatorsRoot[:]
|
||||
|
||||
// Balances slice root.
|
||||
balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.balances)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute validator balances merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Balances.RealPosition()] = balancesRoot[:]
|
||||
|
||||
// RandaoMixes array root.
|
||||
mixes := make([][]byte, len(state.randaoMixes))
|
||||
for i := range mixes {
|
||||
mixes[i] = state.randaoMixes[i][:]
|
||||
}
|
||||
randaoRootsRoot, err := stateutil.ArraysRoot(mixes, fieldparams.RandaoMixesLength)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute randao roots merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.RandaoMixes.RealPosition()] = randaoRootsRoot[:]
|
||||
|
||||
// Slashings array root.
|
||||
slashingsRootsRoot, err := ssz.SlashingsRoot(state.slashings)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute slashings merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.Slashings.RealPosition()] = slashingsRootsRoot[:]
|
||||
|
||||
if state.version == version.Phase0 {
|
||||
// PreviousEpochAttestations slice root.
|
||||
prevAttsRoot, err := stateutil.EpochAttestationsRoot(state.previousEpochAttestations)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.PreviousEpochAttestations.RealPosition()] = prevAttsRoot[:]
|
||||
|
||||
// CurrentEpochAttestations slice root.
|
||||
currAttsRoot, err := stateutil.EpochAttestationsRoot(state.currentEpochAttestations)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.CurrentEpochAttestations.RealPosition()] = currAttsRoot[:]
|
||||
}
|
||||
|
||||
if state.version == version.Altair || state.version == version.Bellatrix {
|
||||
// PreviousEpochParticipation slice root.
|
||||
prevParticipationRoot, err := stateutil.ParticipationBitsRoot(state.previousEpochParticipation)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute previous epoch participation merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.PreviousEpochParticipationBits.RealPosition()] = prevParticipationRoot[:]
|
||||
|
||||
// CurrentEpochParticipation slice root.
|
||||
currParticipationRoot, err := stateutil.ParticipationBitsRoot(state.currentEpochParticipation)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute current epoch participation merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.CurrentEpochParticipationBits.RealPosition()] = currParticipationRoot[:]
|
||||
}
|
||||
|
||||
// JustificationBits root.
|
||||
justifiedBitsRoot := bytesutil.ToBytes32(state.justificationBits)
|
||||
fieldRoots[nativetypes.JustificationBits.RealPosition()] = justifiedBitsRoot[:]
|
||||
|
||||
// PreviousJustifiedCheckpoint data structure root.
|
||||
prevCheckRoot, err := ssz.CheckpointRoot(hasher, state.previousJustifiedCheckpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.PreviousJustifiedCheckpoint.RealPosition()] = prevCheckRoot[:]
|
||||
|
||||
// CurrentJustifiedCheckpoint data structure root.
|
||||
currJustRoot, err := ssz.CheckpointRoot(hasher, state.currentJustifiedCheckpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.CurrentJustifiedCheckpoint.RealPosition()] = currJustRoot[:]
|
||||
|
||||
// FinalizedCheckpoint data structure root.
|
||||
finalRoot, err := ssz.CheckpointRoot(hasher, state.finalizedCheckpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.FinalizedCheckpoint.RealPosition()] = finalRoot[:]
|
||||
|
||||
if state.version == version.Altair || state.version == version.Bellatrix {
|
||||
// Inactivity scores root.
|
||||
inactivityScoresRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.inactivityScores)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute inactivityScoreRoot")
|
||||
}
|
||||
fieldRoots[nativetypes.InactivityScores.RealPosition()] = inactivityScoresRoot[:]
|
||||
|
||||
// Current sync committee root.
|
||||
currentSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.currentSyncCommittee)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute sync committee merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.CurrentSyncCommittee.RealPosition()] = currentSyncCommitteeRoot[:]
|
||||
|
||||
// Next sync committee root.
|
||||
nextSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.nextSyncCommittee)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute sync committee merkleization")
|
||||
}
|
||||
fieldRoots[nativetypes.NextSyncCommittee.RealPosition()] = nextSyncCommitteeRoot[:]
|
||||
}
|
||||
|
||||
if state.version == version.Bellatrix {
|
||||
// Execution payload root.
|
||||
executionPayloadRoot, err := state.latestExecutionPayloadHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldRoots[nativetypes.LatestExecutionPayloadHeader.RealPosition()] = executionPayloadRoot[:]
|
||||
}
|
||||
|
||||
return fieldRoots, nil
|
||||
}
|
||||
355
beacon-chain/state/state-native/hasher_test.go
Normal file
355
beacon-chain/state/state-native/hasher_test.go
Normal file
@@ -0,0 +1,355 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
state_native "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
)
|
||||
|
||||
func TestComputeFieldRootsWithHasher_Phase0(t *testing.T) {
|
||||
beaconState, err := util.NewBeaconState(util.FillRootsNaturalOpt)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetGenesisTime(123))
|
||||
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
|
||||
require.NoError(t, beaconState.SetSlot(123))
|
||||
require.NoError(t, beaconState.SetFork(fork()))
|
||||
require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader()))
|
||||
historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots))
|
||||
require.NoError(t, beaconState.SetEth1Data(eth1Data()))
|
||||
require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()}))
|
||||
require.NoError(t, beaconState.SetEth1DepositIndex(123))
|
||||
require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()}))
|
||||
require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3}))
|
||||
randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetRandaoMixes(randaoMixes))
|
||||
require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3}))
|
||||
require.NoError(t, beaconState.AppendPreviousEpochAttestations(pendingAttestation("previous")))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(pendingAttestation("current")))
|
||||
require.NoError(t, beaconState.SetJustificationBits(justificationBits()))
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous")))
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current")))
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized")))
|
||||
|
||||
v1State, ok := beaconState.(*v1.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
initState, err := state_native.InitializeFromProtoPhase0(protoState)
|
||||
require.NoError(t, err)
|
||||
s, ok := initState.(*state_native.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
expected := [][]byte{
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38},
|
||||
{0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac},
|
||||
{0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e},
|
||||
{0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42},
|
||||
{0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f},
|
||||
{0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8},
|
||||
{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x54, 0xd3, 0xce, 0x8a, 0x3f, 0xfd, 0x21, 0x3a, 0xb4, 0xa6, 0xd, 0xb, 0x9f, 0xf2, 0x88, 0xf0, 0xb1, 0x44, 0x9d, 0xb1, 0x2, 0x95, 0x67, 0xdf, 0x6f, 0x28, 0xa9, 0x68, 0xcd, 0xaa, 0x8c, 0x54},
|
||||
{0xeb, 0x8, 0xb4, 0x1b, 0x76, 0xa2, 0x23, 0xbb, 0x4a, 0xd3, 0x78, 0xca, 0x2e, 0xe8, 0x2c, 0xa1, 0xbf, 0x45, 0xf2, 0x58, 0xdf, 0x39, 0xdf, 0x43, 0x40, 0xb, 0x96, 0xcf, 0xfd, 0x9a, 0x87, 0x85},
|
||||
{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c},
|
||||
{0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1},
|
||||
{0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff},
|
||||
}
|
||||
assert.DeepEqual(t, expected, root)
|
||||
}
|
||||
|
||||
func TestComputeFieldRootsWithHasher_Altair(t *testing.T) {
|
||||
beaconState, err := util.NewBeaconStateAltair(util.FillRootsNaturalOptAltair)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetGenesisTime(123))
|
||||
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
|
||||
require.NoError(t, beaconState.SetSlot(123))
|
||||
require.NoError(t, beaconState.SetFork(fork()))
|
||||
require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader()))
|
||||
historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots))
|
||||
require.NoError(t, beaconState.SetEth1Data(eth1Data()))
|
||||
require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()}))
|
||||
require.NoError(t, beaconState.SetEth1DepositIndex(123))
|
||||
require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()}))
|
||||
require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3}))
|
||||
randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetRandaoMixes(randaoMixes))
|
||||
require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetPreviousParticipationBits([]byte{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetCurrentParticipationBits([]byte{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetJustificationBits(justificationBits()))
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous")))
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current")))
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized")))
|
||||
require.NoError(t, beaconState.SetInactivityScores([]uint64{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee("current")))
|
||||
require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee("next")))
|
||||
|
||||
v1State, ok := beaconState.(*v2.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconStateAltair)
|
||||
require.Equal(t, true, ok)
|
||||
initState, err := state_native.InitializeFromProtoAltair(protoState)
|
||||
require.NoError(t, err)
|
||||
s, ok := initState.(*state_native.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
expected := [][]byte{
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38},
|
||||
{0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac},
|
||||
{0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e},
|
||||
{0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42},
|
||||
{0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f},
|
||||
{0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8},
|
||||
{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb},
|
||||
{0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb},
|
||||
{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c},
|
||||
{0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1},
|
||||
{0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff},
|
||||
{0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f},
|
||||
{0x3d, 0xf3, 0x66, 0xd4, 0x12, 0x40, 0x3f, 0x28, 0xeb, 0xe4, 0x19, 0x59, 0xae, 0xab, 0x4d, 0xf3, 0x98, 0x88, 0x7f, 0x1e, 0x58, 0xa, 0x5d, 0xd4, 0xeb, 0xe5, 0x5d, 0x3d, 0x11, 0x70, 0x24, 0x76},
|
||||
{0xd6, 0x4c, 0xb1, 0xac, 0x61, 0x7, 0x26, 0xbb, 0xd3, 0x27, 0x2a, 0xcd, 0xdd, 0x55, 0xf, 0x2b, 0x6a, 0xe8, 0x1, 0x31, 0x48, 0x66, 0x2f, 0x98, 0x7b, 0x6d, 0x27, 0x69, 0xd9, 0x40, 0xcc, 0x37},
|
||||
}
|
||||
assert.DeepEqual(t, expected, root)
|
||||
}
|
||||
|
||||
func TestComputeFieldRootsWithHasher_Bellatrix(t *testing.T) {
|
||||
beaconState, err := util.NewBeaconStateBellatrix(util.FillRootsNaturalOptBellatrix)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetGenesisTime(123))
|
||||
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
|
||||
require.NoError(t, beaconState.SetSlot(123))
|
||||
require.NoError(t, beaconState.SetFork(fork()))
|
||||
require.NoError(t, beaconState.SetLatestBlockHeader(latestBlockHeader()))
|
||||
historicalRoots, err := util.PrepareRoots(int(params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetHistoricalRoots(historicalRoots))
|
||||
require.NoError(t, beaconState.SetEth1Data(eth1Data()))
|
||||
require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data()}))
|
||||
require.NoError(t, beaconState.SetEth1DepositIndex(123))
|
||||
require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{validator()}))
|
||||
require.NoError(t, beaconState.SetBalances([]uint64{1, 2, 3}))
|
||||
randaoMixes, err := util.PrepareRoots(int(params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetRandaoMixes(randaoMixes))
|
||||
require.NoError(t, beaconState.SetSlashings([]uint64{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetPreviousParticipationBits([]byte{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetCurrentParticipationBits([]byte{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetJustificationBits(justificationBits()))
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(checkpoint("previous")))
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(checkpoint("current")))
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(checkpoint("finalized")))
|
||||
require.NoError(t, beaconState.SetInactivityScores([]uint64{1, 2, 3}))
|
||||
require.NoError(t, beaconState.SetCurrentSyncCommittee(syncCommittee("current")))
|
||||
require.NoError(t, beaconState.SetNextSyncCommittee(syncCommittee("next")))
|
||||
require.NoError(t, beaconState.SetLatestExecutionPayloadHeader(executionPayloadHeader()))
|
||||
|
||||
v1State, ok := beaconState.(*v3.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
protoState, ok := v1State.InnerStateUnsafe().(*ethpb.BeaconStateBellatrix)
|
||||
require.Equal(t, true, ok)
|
||||
initState, err := state_native.InitializeFromProtoBellatrix(protoState)
|
||||
require.NoError(t, err)
|
||||
s, ok := initState.(*state_native.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
root, err := state_native.ComputeFieldRootsWithHasher(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
expected := [][]byte{
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x67, 0x76, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x58, 0xba, 0xf, 0x9b, 0x4f, 0x63, 0x1c, 0xa6, 0x19, 0xb1, 0xa2, 0x1f, 0xd1, 0x29, 0xc7, 0x67, 0x9c, 0x32, 0x4, 0x1f, 0xcf, 0x4e, 0x64, 0x9b, 0x8f, 0x21, 0xb4, 0xe6, 0xa5, 0xc9, 0xc, 0x38},
|
||||
{0x8b, 0x5, 0x59, 0x78, 0xed, 0xbe, 0x2c, 0xde, 0xa6, 0xf, 0x52, 0xdc, 0x16, 0x83, 0xa0, 0x5d, 0x8, 0xc3, 0x37, 0x91, 0x3a, 0xf6, 0xfa, 0x6, 0x62, 0xc9, 0x6, 0xb1, 0x41, 0x48, 0xaf, 0xec},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xcc, 0xa1, 0x69, 0xa8, 0x8b, 0x1e, 0x49, 0x5, 0x1f, 0xe4, 0xd8, 0xff, 0x82, 0xa2, 0x2e, 0xf0, 0x54, 0xd1, 0x13, 0xc9, 0x8e, 0xb9, 0x82, 0xa6, 0x9e, 0x42, 0x2, 0xec, 0x97, 0x6f, 0x33, 0x88},
|
||||
{0xf, 0xad, 0xd3, 0x92, 0x4b, 0xda, 0xfa, 0xc6, 0x61, 0x50, 0xb7, 0xdf, 0x5f, 0x2c, 0xd0, 0x94, 0xc3, 0xaf, 0x41, 0x9d, 0xa, 0xea, 0x50, 0x96, 0x82, 0x62, 0x1c, 0x72, 0x26, 0x20, 0x6b, 0xac},
|
||||
{0xc9, 0x4e, 0x2c, 0xb0, 0x20, 0xe3, 0xe7, 0x8c, 0x5c, 0xbd, 0xeb, 0x9b, 0xa5, 0x7b, 0x53, 0x50, 0xca, 0xfe, 0xe9, 0x48, 0x9e, 0x8d, 0xf8, 0x4a, 0xe6, 0x8d, 0x9c, 0x97, 0x81, 0x74, 0xb, 0x5e},
|
||||
{0x71, 0x52, 0xd2, 0x9b, 0x87, 0x3c, 0x8a, 0xd9, 0x51, 0x55, 0xc0, 0x42, 0xb, 0xc4, 0x12, 0xa4, 0x79, 0xf5, 0x7d, 0x37, 0x16, 0xf4, 0x90, 0x72, 0x5d, 0xe0, 0x34, 0xb4, 0x2, 0x8c, 0x39, 0xe4},
|
||||
{0x7b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0xf, 0xf7, 0x4f, 0xe1, 0xa9, 0x72, 0x9c, 0x95, 0xf0, 0xe1, 0xde, 0xa4, 0x32, 0xc, 0x67, 0x52, 0x23, 0x13, 0x9e, 0xe2, 0x40, 0x8d, 0xf6, 0x18, 0x57, 0xf0, 0x1a, 0x4a, 0xad, 0x46, 0xce, 0x42},
|
||||
{0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f},
|
||||
{0x64, 0xbd, 0x40, 0xa7, 0x10, 0x44, 0x84, 0xed, 0xf3, 0x5f, 0xc3, 0x5d, 0x7b, 0xbe, 0xe8, 0x75, 0xbf, 0x66, 0xcb, 0xce, 0x77, 0xfa, 0x0, 0x3, 0xdd, 0xfb, 0x80, 0xd2, 0x77, 0x1b, 0xc2, 0x8},
|
||||
{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb},
|
||||
{0x75, 0xb2, 0xae, 0x1d, 0xd8, 0xca, 0xe6, 0x4d, 0xa8, 0xc5, 0xc9, 0x19, 0x8, 0x96, 0xaf, 0x9b, 0xe6, 0xf6, 0x99, 0xb9, 0x58, 0x56, 0x5b, 0x25, 0xea, 0x9c, 0x86, 0x5e, 0x96, 0x6a, 0x48, 0xb},
|
||||
{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
{0x76, 0x88, 0xa0, 0x68, 0x45, 0x25, 0x8f, 0xd5, 0xf9, 0xb2, 0xb0, 0x42, 0x68, 0x6b, 0x51, 0xcc, 0x29, 0x94, 0x63, 0x85, 0xec, 0xf5, 0x47, 0xf0, 0x9c, 0x46, 0x86, 0xa9, 0x99, 0x7d, 0x29, 0x6c},
|
||||
{0x41, 0x44, 0x52, 0xff, 0x8c, 0xa6, 0xb3, 0x2e, 0xcc, 0x5e, 0x63, 0x8f, 0x8e, 0x7d, 0xe7, 0x52, 0x42, 0x94, 0x55, 0x2f, 0x89, 0xdd, 0x1e, 0x3c, 0xb0, 0xf4, 0x51, 0x51, 0x36, 0x81, 0x72, 0x1},
|
||||
{0xa9, 0xbb, 0x6a, 0x1f, 0x5d, 0x86, 0x7d, 0xa7, 0x5a, 0x7d, 0x9d, 0x8d, 0xc0, 0x15, 0xb7, 0x0, 0xee, 0xa9, 0x68, 0x51, 0x88, 0x57, 0x5a, 0xd9, 0x4e, 0x1d, 0x8e, 0x44, 0xbf, 0xdc, 0x73, 0xff},
|
||||
{0xf9, 0x11, 0x2c, 0xc2, 0x71, 0x70, 0xde, 0x47, 0x26, 0xeb, 0x26, 0xd4, 0xa4, 0xe8, 0x68, 0xb, 0x16, 0xa2, 0x6e, 0x52, 0x54, 0xe, 0x5c, 0x83, 0x17, 0x3, 0xea, 0xdd, 0xd5, 0xa7, 0xb2, 0x3f},
|
||||
{0x3d, 0xf3, 0x66, 0xd4, 0x12, 0x40, 0x3f, 0x28, 0xeb, 0xe4, 0x19, 0x59, 0xae, 0xab, 0x4d, 0xf3, 0x98, 0x88, 0x7f, 0x1e, 0x58, 0xa, 0x5d, 0xd4, 0xeb, 0xe5, 0x5d, 0x3d, 0x11, 0x70, 0x24, 0x76},
|
||||
{0xd6, 0x4c, 0xb1, 0xac, 0x61, 0x7, 0x26, 0xbb, 0xd3, 0x27, 0x2a, 0xcd, 0xdd, 0x55, 0xf, 0x2b, 0x6a, 0xe8, 0x1, 0x31, 0x48, 0x66, 0x2f, 0x98, 0x7b, 0x6d, 0x27, 0x69, 0xd9, 0x40, 0xcc, 0x37},
|
||||
{0xbc, 0xbb, 0x39, 0x57, 0x61, 0x1d, 0x54, 0xd6, 0x1b, 0xfe, 0x7a, 0xbd, 0x29, 0x52, 0x57, 0xdd, 0x19, 0x1, 0x89, 0x22, 0x7d, 0xdf, 0x7b, 0x53, 0x9f, 0xb, 0x46, 0x5, 0x9f, 0x80, 0xcc, 0x8e},
|
||||
}
|
||||
assert.DeepEqual(t, expected, root)
|
||||
}
|
||||
|
||||
func genesisValidatorsRoot() []byte {
|
||||
gvr := bytesutil.ToBytes32([]byte("gvr"))
|
||||
return gvr[:]
|
||||
}
|
||||
|
||||
func fork() *ethpb.Fork {
|
||||
prev := bytesutil.ToBytes4([]byte("prev"))
|
||||
curr := bytesutil.ToBytes4([]byte("curr"))
|
||||
return ðpb.Fork{
|
||||
PreviousVersion: prev[:],
|
||||
CurrentVersion: curr[:],
|
||||
Epoch: 123,
|
||||
}
|
||||
}
|
||||
|
||||
func latestBlockHeader() *ethpb.BeaconBlockHeader {
|
||||
pr := bytesutil.ToBytes32([]byte("parent"))
|
||||
sr := bytesutil.ToBytes32([]byte("state"))
|
||||
br := bytesutil.ToBytes32([]byte("body"))
|
||||
return ðpb.BeaconBlockHeader{
|
||||
Slot: 123,
|
||||
ProposerIndex: 123,
|
||||
ParentRoot: pr[:],
|
||||
StateRoot: sr[:],
|
||||
BodyRoot: br[:],
|
||||
}
|
||||
}
|
||||
|
||||
func eth1Data() *ethpb.Eth1Data {
|
||||
dr := bytesutil.ToBytes32([]byte("deposit"))
|
||||
bh := bytesutil.ToBytes32([]byte("block"))
|
||||
return ðpb.Eth1Data{
|
||||
DepositRoot: dr[:],
|
||||
DepositCount: 123,
|
||||
BlockHash: bh[:],
|
||||
}
|
||||
}
|
||||
|
||||
func validator() *ethpb.Validator {
|
||||
pk := bytesutil.ToBytes48([]byte("public"))
|
||||
wc := bytesutil.ToBytes32([]byte("withdrawal"))
|
||||
return ðpb.Validator{
|
||||
PublicKey: pk[:],
|
||||
WithdrawalCredentials: wc[:],
|
||||
EffectiveBalance: 123,
|
||||
Slashed: true,
|
||||
ActivationEligibilityEpoch: 123,
|
||||
ActivationEpoch: 123,
|
||||
ExitEpoch: 123,
|
||||
WithdrawableEpoch: 123,
|
||||
}
|
||||
}
|
||||
|
||||
func pendingAttestation(prefix string) *ethpb.PendingAttestation {
|
||||
bbr := bytesutil.ToBytes32([]byte(prefix + "beacon"))
|
||||
r := bytesutil.ToBytes32([]byte(prefix + "root"))
|
||||
return ðpb.PendingAttestation{
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 123,
|
||||
CommitteeIndex: 123,
|
||||
BeaconBlockRoot: bbr[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 123,
|
||||
Root: r[:],
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 123,
|
||||
Root: r[:],
|
||||
},
|
||||
},
|
||||
InclusionDelay: 123,
|
||||
ProposerIndex: 123,
|
||||
}
|
||||
}
|
||||
|
||||
func justificationBits() bitfield.Bitvector4 {
|
||||
v := bitfield.NewBitvector4()
|
||||
v.SetBitAt(1, true)
|
||||
return v
|
||||
}
|
||||
|
||||
func checkpoint(prefix string) *ethpb.Checkpoint {
|
||||
r := bytesutil.ToBytes32([]byte(prefix + "root"))
|
||||
return ðpb.Checkpoint{
|
||||
Epoch: 123,
|
||||
Root: r[:],
|
||||
}
|
||||
}
|
||||
|
||||
func syncCommittee(prefix string) *ethpb.SyncCommittee {
|
||||
pubkeys := make([][]byte, params.BeaconConfig().SyncCommitteeSize)
|
||||
for i := range pubkeys {
|
||||
key := bytesutil.ToBytes48([]byte(prefix + "pubkey"))
|
||||
pubkeys[i] = key[:]
|
||||
}
|
||||
agg := bytesutil.ToBytes48([]byte(prefix + "aggregate"))
|
||||
return ðpb.SyncCommittee{
|
||||
Pubkeys: pubkeys,
|
||||
AggregatePubkey: agg[:],
|
||||
}
|
||||
}
|
||||
|
||||
func executionPayloadHeader() *ethpb.ExecutionPayloadHeader {
|
||||
ph := bytesutil.ToBytes32([]byte("parent"))
|
||||
fr := bytesutil.PadTo([]byte("fee"), 20)
|
||||
sr := bytesutil.ToBytes32([]byte("state"))
|
||||
rr := bytesutil.ToBytes32([]byte("receipts"))
|
||||
lb := bytesutil.PadTo([]byte("logs"), 256)
|
||||
pr := bytesutil.ToBytes32([]byte("prev"))
|
||||
ed := bytesutil.ToBytes32([]byte("extra"))
|
||||
bf := bytesutil.ToBytes32([]byte("base"))
|
||||
bh := bytesutil.ToBytes32([]byte("block"))
|
||||
tr := bytesutil.ToBytes32([]byte("transactions"))
|
||||
return ðpb.ExecutionPayloadHeader{
|
||||
ParentHash: ph[:],
|
||||
FeeRecipient: fr,
|
||||
StateRoot: sr[:],
|
||||
ReceiptsRoot: rr[:],
|
||||
LogsBloom: lb,
|
||||
PrevRandao: pr[:],
|
||||
BlockNumber: 0,
|
||||
GasLimit: 0,
|
||||
GasUsed: 0,
|
||||
Timestamp: 0,
|
||||
ExtraData: ed[:],
|
||||
BaseFeePerGas: bf[:],
|
||||
BlockHash: bh[:],
|
||||
TransactionsRoot: tr[:],
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/fieldtrie"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -18,19 +20,32 @@ func FinalizedRootGeneralizedIndex() uint64 {
|
||||
}
|
||||
|
||||
// CurrentSyncCommitteeGeneralizedIndex for the beacon state.
|
||||
func CurrentSyncCommitteeGeneralizedIndex() uint64 {
|
||||
return uint64(currentSyncCommittee)
|
||||
func (b *BeaconState) CurrentSyncCommitteeGeneralizedIndex() (uint64, error) {
|
||||
if b.version == version.Phase0 {
|
||||
return 0, errNotSupported("CurrentSyncCommitteeGeneralizedIndex", b.version)
|
||||
}
|
||||
|
||||
return uint64(nativetypes.CurrentSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// NextSyncCommitteeGeneralizedIndex for the beacon state.
|
||||
func NextSyncCommitteeGeneralizedIndex() uint64 {
|
||||
return uint64(nextSyncCommittee)
|
||||
func (b *BeaconState) NextSyncCommitteeGeneralizedIndex() (uint64, error) {
|
||||
if b.version == version.Phase0 {
|
||||
return 0, errNotSupported("NextSyncCommitteeGeneralizedIndex", b.version)
|
||||
}
|
||||
|
||||
return uint64(nativetypes.NextSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// CurrentSyncCommitteeProof from the state's Merkle trie representation.
|
||||
func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("CurrentSyncCommitteeProof", b.version)
|
||||
}
|
||||
|
||||
// In case the Merkle layers of the trie are not populated, we need
|
||||
// to perform some initialization.
|
||||
if err := b.initializeMerkleLayers(ctx); err != nil {
|
||||
@@ -41,20 +56,25 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte,
|
||||
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, currentSyncCommittee), nil
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.CurrentSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// NextSyncCommitteeProof from the state's Merkle trie representation.
|
||||
func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("NextSyncCommitteeProof", b.version)
|
||||
}
|
||||
|
||||
if err := b.initializeMerkleLayers(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nextSyncCommittee), nil
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.NextSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// FinalizedRootProof crafts a Merkle proof for the finalized root
|
||||
@@ -62,13 +82,18 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err
|
||||
func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version == version.Phase0 {
|
||||
return nil, errNotSupported("FinalizedRootProof", b.version)
|
||||
}
|
||||
|
||||
if err := b.initializeMerkleLayers(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cpt := b.finalizedCheckpoint
|
||||
cpt := b.finalizedCheckpointVal()
|
||||
// The epoch field of a finalized checkpoint is the neighbor
|
||||
// index of the finalized root field in its Merkle tree representation
|
||||
// of the checkpoint. This neighbor is the first element added to the proof.
|
||||
@@ -77,7 +102,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error)
|
||||
epochRoot := bytesutil.ToBytes32(epochBuf)
|
||||
proof := make([][]byte, 0)
|
||||
proof = append(proof, epochRoot[:])
|
||||
branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, finalizedCheckpoint)
|
||||
branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, nativetypes.FinalizedCheckpoint.RealPosition())
|
||||
proof = append(proof, branch...)
|
||||
return proof, nil
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package v1_test
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
|
||||
statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
@@ -27,7 +27,7 @@ func TestBeaconStateMerkleProofs(t *testing.T) {
|
||||
finalizedRoot := st.FinalizedCheckpoint().Root
|
||||
proof, err := st.FinalizedRootProof(ctx)
|
||||
require.NoError(t, err)
|
||||
gIndex := v1.FinalizedRootGeneralizedIndex()
|
||||
gIndex := statenative.FinalizedRootGeneralizedIndex()
|
||||
valid := trie.VerifyMerkleProof(htr[:], finalizedRoot, gIndex, proof)
|
||||
require.Equal(t, true, valid)
|
||||
})
|
||||
@@ -51,7 +51,7 @@ func TestBeaconStateMerkleProofs(t *testing.T) {
|
||||
// changed and should have been marked as a dirty state field.
|
||||
// The proof validity should be false for the old root, but true for the new.
|
||||
finalizedRoot := st.FinalizedCheckpoint().Root
|
||||
gIndex := v1.FinalizedRootGeneralizedIndex()
|
||||
gIndex := statenative.FinalizedRootGeneralizedIndex()
|
||||
valid := trie.VerifyMerkleProof(currentRoot[:], finalizedRoot, gIndex, proof)
|
||||
require.Equal(t, false, valid)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
@@ -1,9 +1,9 @@
|
||||
package v1_test
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
|
||||
statenative "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -12,63 +12,63 @@ import (
|
||||
)
|
||||
|
||||
func TestReadOnlyValidator_ReturnsErrorOnNil(t *testing.T) {
|
||||
if _, err := v1.NewValidator(nil); err != v1.ErrNilWrappedValidator {
|
||||
t.Errorf("Wrong error returned. Got %v, wanted %v", err, v1.ErrNilWrappedValidator)
|
||||
if _, err := statenative.NewValidator(nil); err != statenative.ErrNilWrappedValidator {
|
||||
t.Errorf("Wrong error returned. Got %v, wanted %v", err, statenative.ErrNilWrappedValidator)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_EffectiveBalance(t *testing.T) {
|
||||
bal := uint64(234)
|
||||
v, err := v1.NewValidator(ðpb.Validator{EffectiveBalance: bal})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{EffectiveBalance: bal})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, bal, v.EffectiveBalance())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_ActivationEligibilityEpoch(t *testing.T) {
|
||||
epoch := types.Epoch(234)
|
||||
v, err := v1.NewValidator(ðpb.Validator{ActivationEligibilityEpoch: epoch})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{ActivationEligibilityEpoch: epoch})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, epoch, v.ActivationEligibilityEpoch())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_ActivationEpoch(t *testing.T) {
|
||||
epoch := types.Epoch(234)
|
||||
v, err := v1.NewValidator(ðpb.Validator{ActivationEpoch: epoch})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{ActivationEpoch: epoch})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, epoch, v.ActivationEpoch())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_WithdrawableEpoch(t *testing.T) {
|
||||
epoch := types.Epoch(234)
|
||||
v, err := v1.NewValidator(ðpb.Validator{WithdrawableEpoch: epoch})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{WithdrawableEpoch: epoch})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, epoch, v.WithdrawableEpoch())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_ExitEpoch(t *testing.T) {
|
||||
epoch := types.Epoch(234)
|
||||
v, err := v1.NewValidator(ðpb.Validator{ExitEpoch: epoch})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{ExitEpoch: epoch})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, epoch, v.ExitEpoch())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_PublicKey(t *testing.T) {
|
||||
key := [fieldparams.BLSPubkeyLength]byte{0xFA, 0xCC}
|
||||
v, err := v1.NewValidator(ðpb.Validator{PublicKey: key[:]})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{PublicKey: key[:]})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, key, v.PublicKey())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_WithdrawalCredentials(t *testing.T) {
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v, err := v1.NewValidator(ðpb.Validator{WithdrawalCredentials: creds})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{WithdrawalCredentials: creds})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, creds, v.WithdrawalCredentials())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_Slashed(t *testing.T) {
|
||||
slashed := true
|
||||
v, err := v1.NewValidator(ðpb.Validator{Slashed: slashed})
|
||||
v, err := statenative.NewValidator(ðpb.Validator{Slashed: slashed})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, slashed, v.Slashed())
|
||||
}
|
||||
715
beacon-chain/state/state-native/references_test.go
Normal file
715
beacon-chain/state/state-native/references_test.go
Normal file
@@ -0,0 +1,715 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestStateReferenceSharing_Finalizer_Phase0(t *testing.T) {
|
||||
// This test showcases the logic on the RandaoMixes field with the GC finalizer.
|
||||
|
||||
s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{RandaoMixes: [][]byte{[]byte("foo")}})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes")
|
||||
|
||||
func() {
|
||||
// Create object in a different scope for GC
|
||||
b := a.Copy()
|
||||
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
|
||||
_ = b
|
||||
}()
|
||||
|
||||
runtime.GC() // Should run finalizer on object b
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
|
||||
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
|
||||
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
|
||||
if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 {
|
||||
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateReferenceSharing_Finalizer_Altair(t *testing.T) {
|
||||
// This test showcases the logic on the RandaoMixes field with the GC finalizer.
|
||||
|
||||
s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{RandaoMixes: [][]byte{[]byte("foo")}})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes")
|
||||
|
||||
func() {
|
||||
// Create object in a different scope for GC
|
||||
b := a.Copy()
|
||||
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
|
||||
_ = b
|
||||
}()
|
||||
|
||||
runtime.GC() // Should run finalizer on object b
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
|
||||
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
|
||||
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
|
||||
if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 {
|
||||
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateReferenceSharing_Finalizer_Bellatrix(t *testing.T) {
|
||||
// This test showcases the logic on the RandaoMixes field with the GC finalizer.
|
||||
|
||||
s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{RandaoMixes: [][]byte{[]byte("foo")}})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected a single reference for RANDAO mixes")
|
||||
|
||||
func() {
|
||||
// Create object in a different scope for GC
|
||||
b := a.Copy()
|
||||
assert.Equal(t, uint(2), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 references to RANDAO mixes")
|
||||
_ = b
|
||||
}()
|
||||
|
||||
runtime.GC() // Should run finalizer on object b
|
||||
assert.Equal(t, uint(1), a.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 1 shared reference to RANDAO mixes!")
|
||||
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, uint(2), b.sharedFieldReferences[nativetypes.RandaoMixes].Refs(), "Expected 2 shared references to RANDAO mixes")
|
||||
require.NoError(t, b.UpdateRandaoMixesAtIndex(0, []byte("bar")))
|
||||
if b.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 || a.sharedFieldReferences[nativetypes.RandaoMixes].Refs() != 1 {
|
||||
t.Error("Expected 1 shared reference to RANDAO mix for both a and b")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRootsMutation_Phase0(t *testing.T) {
|
||||
root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{
|
||||
BlockRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
StateRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 2)
|
||||
|
||||
// Assert shared state.
|
||||
blockRootsA := a.BlockRoots()
|
||||
stateRootsA := a.StateRoots()
|
||||
blockRootsB := b.BlockRoots()
|
||||
stateRootsB := b.StateRoots()
|
||||
assertValFound(t, blockRootsA, root1[:])
|
||||
assertValFound(t, blockRootsB, root1[:])
|
||||
assertValFound(t, stateRootsA, root1[:])
|
||||
assertValFound(t, stateRootsB, root1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateBlockRootAtIndex(0, root2))
|
||||
require.NoError(t, a.UpdateStateRootAtIndex(0, root2))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValNotFound(t, a.BlockRoots(), root1[:])
|
||||
assertValNotFound(t, a.StateRoots(), root1[:])
|
||||
assertValFound(t, a.BlockRoots(), root2[:])
|
||||
assertValFound(t, a.StateRoots(), root2[:])
|
||||
assertValFound(t, b.BlockRoots(), root1[:])
|
||||
assertValFound(t, b.StateRoots(), root1[:])
|
||||
assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found")
|
||||
assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRootsMutation_Altair(t *testing.T) {
|
||||
root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{
|
||||
BlockRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
StateRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 2)
|
||||
|
||||
// Assert shared state.
|
||||
blockRootsA := a.BlockRoots()
|
||||
stateRootsA := a.StateRoots()
|
||||
blockRootsB := b.BlockRoots()
|
||||
stateRootsB := b.StateRoots()
|
||||
assertValFound(t, blockRootsA, root1[:])
|
||||
assertValFound(t, blockRootsB, root1[:])
|
||||
assertValFound(t, stateRootsA, root1[:])
|
||||
assertValFound(t, stateRootsB, root1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateBlockRootAtIndex(0, root2))
|
||||
require.NoError(t, a.UpdateStateRootAtIndex(0, root2))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValNotFound(t, a.BlockRoots(), root1[:])
|
||||
assertValNotFound(t, a.StateRoots(), root1[:])
|
||||
assertValFound(t, a.BlockRoots(), root2[:])
|
||||
assertValFound(t, a.StateRoots(), root2[:])
|
||||
assertValFound(t, b.BlockRoots(), root1[:])
|
||||
assertValFound(t, b.StateRoots(), root1[:])
|
||||
assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found")
|
||||
assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRootsMutation_Bellatrix(t *testing.T) {
|
||||
root1, root2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{
|
||||
BlockRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
StateRoots: [][]byte{
|
||||
root1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 2)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 2)
|
||||
|
||||
// Assert shared state.
|
||||
blockRootsA := a.BlockRoots()
|
||||
stateRootsA := a.StateRoots()
|
||||
blockRootsB := b.BlockRoots()
|
||||
stateRootsB := b.StateRoots()
|
||||
assertValFound(t, blockRootsA, root1[:])
|
||||
assertValFound(t, blockRootsB, root1[:])
|
||||
assertValFound(t, stateRootsA, root1[:])
|
||||
assertValFound(t, stateRootsB, root1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateBlockRootAtIndex(0, root2))
|
||||
require.NoError(t, a.UpdateStateRootAtIndex(0, root2))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValNotFound(t, a.BlockRoots(), root1[:])
|
||||
assertValNotFound(t, a.StateRoots(), root1[:])
|
||||
assertValFound(t, a.BlockRoots(), root2[:])
|
||||
assertValFound(t, a.StateRoots(), root2[:])
|
||||
assertValFound(t, b.BlockRoots(), root1[:])
|
||||
assertValFound(t, b.StateRoots(), root1[:])
|
||||
assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found")
|
||||
assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, a, nativetypes.StateRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.BlockRoots, 1)
|
||||
assertRefCount(t, b, nativetypes.StateRoots, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Phase0(t *testing.T) {
|
||||
|
||||
val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{
|
||||
RandaoMixes: [][]byte{
|
||||
val1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 2)
|
||||
|
||||
// Assert shared state.
|
||||
mixesA := a.RandaoMixes()
|
||||
mixesB := b.RandaoMixes()
|
||||
assertValFound(t, mixesA, val1[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValFound(t, a.RandaoMixes(), val2[:])
|
||||
assertValNotFound(t, a.RandaoMixes(), val1[:])
|
||||
assertValFound(t, b.RandaoMixes(), val1[:])
|
||||
assertValNotFound(t, b.RandaoMixes(), val2[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
assertValNotFound(t, mixesB, val2[:])
|
||||
assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Altair(t *testing.T) {
|
||||
|
||||
val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{
|
||||
RandaoMixes: [][]byte{
|
||||
val1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 2)
|
||||
|
||||
// Assert shared state.
|
||||
mixesA := a.RandaoMixes()
|
||||
mixesB := b.RandaoMixes()
|
||||
assertValFound(t, mixesA, val1[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValFound(t, a.RandaoMixes(), val2[:])
|
||||
assertValNotFound(t, a.RandaoMixes(), val1[:])
|
||||
assertValFound(t, b.RandaoMixes(), val1[:])
|
||||
assertValNotFound(t, b.RandaoMixes(), val2[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
assertValNotFound(t, mixesB, val2[:])
|
||||
assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedRandaoMutation_Bellatrix(t *testing.T) {
|
||||
|
||||
val1, val2 := bytesutil.ToBytes32([]byte("foo")), bytesutil.ToBytes32([]byte("bar"))
|
||||
s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{
|
||||
RandaoMixes: [][]byte{
|
||||
val1[:],
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.NoError(t, err)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 2)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 2)
|
||||
|
||||
// Assert shared state.
|
||||
mixesA := a.RandaoMixes()
|
||||
mixesB := b.RandaoMixes()
|
||||
assertValFound(t, mixesA, val1[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
require.NoError(t, a.UpdateRandaoMixesAtIndex(0, val2[:]))
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
assertValFound(t, a.RandaoMixes(), val2[:])
|
||||
assertValNotFound(t, a.RandaoMixes(), val1[:])
|
||||
assertValFound(t, b.RandaoMixes(), val1[:])
|
||||
assertValNotFound(t, b.RandaoMixes(), val2[:])
|
||||
assertValFound(t, mixesB, val1[:])
|
||||
assertValNotFound(t, mixesB, val2[:])
|
||||
assert.DeepEqual(t, val2[:], a.RandaoMixes()[0], "Expected mutation not found")
|
||||
assert.DeepEqual(t, val1[:], mixesB[0], "Unexpected mutation found")
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.RandaoMixes, 1)
|
||||
assertRefCount(t, b, nativetypes.RandaoMixes, 1)
|
||||
}
|
||||
|
||||
func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) {
|
||||
assertAttFound := func(vals []*ethpb.PendingAttestation, val uint64) {
|
||||
for i := range vals {
|
||||
if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Log(string(debug.Stack()))
|
||||
t.Fatalf("Expected attestation not found (%v), want: %v", vals, val)
|
||||
}
|
||||
assertAttNotFound := func(vals []*ethpb.PendingAttestation, val uint64) {
|
||||
for i := range vals {
|
||||
if reflect.DeepEqual(vals[i].AggregationBits, bitfield.NewBitlist(val)) {
|
||||
t.Log(string(debug.Stack()))
|
||||
t.Fatalf("Unexpected attestation found (%v): %v", vals, val)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 1)
|
||||
assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 1)
|
||||
|
||||
// Update initial state.
|
||||
atts := []*ethpb.PendingAttestation{
|
||||
{AggregationBits: bitfield.NewBitlist(1)},
|
||||
{AggregationBits: bitfield.NewBitlist(2)},
|
||||
}
|
||||
a.setPreviousEpochAttestations(atts[:1])
|
||||
a.setCurrentEpochAttestations(atts[:1])
|
||||
curAtt, err := a.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(curAtt), "Unexpected number of attestations")
|
||||
preAtt, err := a.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(preAtt), "Unexpected number of attestations")
|
||||
|
||||
// Copy, increases reference count.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 2)
|
||||
assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 2)
|
||||
assertRefCount(t, b, nativetypes.PreviousEpochAttestations, 2)
|
||||
assertRefCount(t, b, nativetypes.CurrentEpochAttestations, 2)
|
||||
prevAtts, err := b.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(prevAtts), "Unexpected number of attestations")
|
||||
currAtts, err := b.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(currAtts), "Unexpected number of attestations")
|
||||
|
||||
// Assert shared state.
|
||||
currAttsA, err := a.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsA, err := a.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
currAttsB, err := b.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsB, err := b.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
if len(currAttsA) != len(currAttsB) || len(currAttsA) < 1 {
|
||||
t.Errorf("Unexpected number of attestations, want: %v", 1)
|
||||
}
|
||||
if len(prevAttsA) != len(prevAttsB) || len(prevAttsA) < 1 {
|
||||
t.Errorf("Unexpected number of attestations, want: %v", 1)
|
||||
}
|
||||
assertAttFound(currAttsA, 1)
|
||||
assertAttFound(prevAttsA, 1)
|
||||
assertAttFound(currAttsB, 1)
|
||||
assertAttFound(prevAttsB, 1)
|
||||
|
||||
// Extend state attestations.
|
||||
require.NoError(t, a.AppendCurrentEpochAttestations(atts[1]))
|
||||
require.NoError(t, a.AppendPreviousEpochAttestations(atts[1]))
|
||||
curAtt, err = a.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, len(curAtt), "Unexpected number of attestations")
|
||||
preAtt, err = a.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations")
|
||||
currAttsA, err = a.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsA, err = a.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
currAttsB, err = b.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsB, err = b.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assertAttFound(currAttsA, 1)
|
||||
assertAttFound(prevAttsA, 1)
|
||||
assertAttFound(currAttsA, 2)
|
||||
assertAttFound(prevAttsA, 2)
|
||||
assertAttFound(currAttsB, 1)
|
||||
assertAttFound(prevAttsB, 1)
|
||||
assertAttNotFound(currAttsB, 2)
|
||||
assertAttNotFound(prevAttsB, 2)
|
||||
|
||||
// Mutator should only affect calling state: a.
|
||||
applyToEveryAttestation := func(state *BeaconState) {
|
||||
// One MUST copy on write.
|
||||
currEpochAtts, err := state.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
atts = make([]*ethpb.PendingAttestation, len(currEpochAtts))
|
||||
copy(atts, currEpochAtts)
|
||||
state.setCurrentEpochAttestations(atts)
|
||||
currEpochAtts, err = state.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
for i := range currEpochAtts {
|
||||
att := ethpb.CopyPendingAttestation(currEpochAtts[i])
|
||||
att.AggregationBits = bitfield.NewBitlist(3)
|
||||
currEpochAtts[i] = att
|
||||
}
|
||||
state.setCurrentEpochAttestations(currEpochAtts)
|
||||
|
||||
prevEpochAtts, err := state.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
atts = make([]*ethpb.PendingAttestation, len(prevEpochAtts))
|
||||
copy(atts, prevEpochAtts)
|
||||
state.setPreviousEpochAttestations(atts)
|
||||
prevEpochAtts, err = state.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
for i := range prevEpochAtts {
|
||||
att := ethpb.CopyPendingAttestation(prevEpochAtts[i])
|
||||
att.AggregationBits = bitfield.NewBitlist(3)
|
||||
prevEpochAtts[i] = att
|
||||
}
|
||||
state.setPreviousEpochAttestations(prevEpochAtts)
|
||||
}
|
||||
applyToEveryAttestation(a)
|
||||
|
||||
// Assert no shared state mutation occurred only on state a (copy on write).
|
||||
currAttsA, err = a.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsA, err = a.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assertAttFound(currAttsA, 3)
|
||||
assertAttFound(prevAttsA, 3)
|
||||
assertAttNotFound(currAttsA, 1)
|
||||
assertAttNotFound(prevAttsA, 1)
|
||||
assertAttNotFound(currAttsA, 2)
|
||||
assertAttNotFound(prevAttsA, 2)
|
||||
// State b must be unaffected.
|
||||
currAttsB, err = b.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
prevAttsB, err = b.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assertAttNotFound(currAttsB, 3)
|
||||
assertAttNotFound(prevAttsB, 3)
|
||||
assertAttFound(currAttsB, 1)
|
||||
assertAttFound(prevAttsB, 1)
|
||||
assertAttNotFound(currAttsB, 2)
|
||||
assertAttNotFound(prevAttsB, 2)
|
||||
|
||||
// Copy on write happened, reference counters are reset.
|
||||
assertRefCount(t, a, nativetypes.CurrentEpochAttestations, 1)
|
||||
assertRefCount(t, b, nativetypes.CurrentEpochAttestations, 1)
|
||||
assertRefCount(t, a, nativetypes.PreviousEpochAttestations, 1)
|
||||
assertRefCount(t, b, nativetypes.PreviousEpochAttestations, 1)
|
||||
}
|
||||
|
||||
func TestValidatorReferences_RemainsConsistent_Phase0(t *testing.T) {
|
||||
s, err := InitializeFromProtoUnsafePhase0(ðpb.BeaconState{
|
||||
Validators: []*ethpb.Validator{
|
||||
{PublicKey: []byte{'A'}},
|
||||
{PublicKey: []byte{'B'}},
|
||||
{PublicKey: []byte{'C'}},
|
||||
{PublicKey: []byte{'D'}},
|
||||
{PublicKey: []byte{'E'}},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Create a second state.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Update First Validator.
|
||||
assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}}))
|
||||
|
||||
assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different")
|
||||
// Modify all validators from copied state.
|
||||
assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil
|
||||
}))
|
||||
|
||||
// Ensure reference is properly accounted for.
|
||||
assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey())
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func TestValidatorReferences_RemainsConsistent_Altair(t *testing.T) {
|
||||
s, err := InitializeFromProtoUnsafeAltair(ðpb.BeaconStateAltair{
|
||||
Validators: []*ethpb.Validator{
|
||||
{PublicKey: []byte{'A'}},
|
||||
{PublicKey: []byte{'B'}},
|
||||
{PublicKey: []byte{'C'}},
|
||||
{PublicKey: []byte{'D'}},
|
||||
{PublicKey: []byte{'E'}},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Create a second state.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Update First Validator.
|
||||
assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}}))
|
||||
|
||||
assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different")
|
||||
// Modify all validators from copied state.
|
||||
assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil
|
||||
}))
|
||||
|
||||
// Ensure reference is properly accounted for.
|
||||
assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey())
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func TestValidatorReferences_RemainsConsistent_Bellatrix(t *testing.T) {
|
||||
s, err := InitializeFromProtoUnsafeBellatrix(ðpb.BeaconStateBellatrix{
|
||||
Validators: []*ethpb.Validator{
|
||||
{PublicKey: []byte{'A'}},
|
||||
{PublicKey: []byte{'B'}},
|
||||
{PublicKey: []byte{'C'}},
|
||||
{PublicKey: []byte{'D'}},
|
||||
{PublicKey: []byte{'E'}},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
a, ok := s.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Create a second state.
|
||||
copied := a.Copy()
|
||||
b, ok := copied.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Update First Validator.
|
||||
assert.NoError(t, a.UpdateValidatorAtIndex(0, ðpb.Validator{PublicKey: []byte{'Z'}}))
|
||||
|
||||
assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different")
|
||||
// Modify all validators from copied state.
|
||||
assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil
|
||||
}))
|
||||
|
||||
// Ensure reference is properly accounted for.
|
||||
assert.NoError(t, a.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
|
||||
assert.NotEqual(t, bytesutil.ToBytes48([]byte{'V'}), val.PublicKey())
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
// assertRefCount checks whether reference count for a given state
|
||||
// at a given index is equal to expected amount.
|
||||
func assertRefCount(t *testing.T, b *BeaconState, idx nativetypes.FieldIndex, want uint) {
|
||||
if cnt := b.sharedFieldReferences[idx].Refs(); cnt != want {
|
||||
t.Errorf("Unexpected count of references for index %d, want: %v, got: %v", idx, want, cnt)
|
||||
}
|
||||
}
|
||||
|
||||
// assertValFound checks whether item with a given value exists in list.
|
||||
func assertValFound(t *testing.T, vals [][]byte, val []byte) {
|
||||
for i := range vals {
|
||||
if reflect.DeepEqual(vals[i], val) {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Log(string(debug.Stack()))
|
||||
t.Fatalf("Expected value not found (%v), want: %v", vals, val)
|
||||
}
|
||||
|
||||
// assertValNotFound checks whether item with a given value doesn't exist in list.
|
||||
func assertValNotFound(t *testing.T, vals [][]byte, val []byte) {
|
||||
for i := range vals {
|
||||
if reflect.DeepEqual(vals[i], val) {
|
||||
t.Log(string(debug.Stack()))
|
||||
t.Errorf("Unexpected value found (%v),: %v", vals, val)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
)
|
||||
|
||||
// RotateAttestations sets the previous epoch attestations to the current epoch attestations and
|
||||
@@ -14,27 +16,31 @@ func (b *BeaconState) RotateAttestations() error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version != version.Phase0 {
|
||||
return errNotSupported("RotateAttestations", b.version)
|
||||
}
|
||||
|
||||
b.setPreviousEpochAttestations(b.currentEpochAttestationsVal())
|
||||
b.setCurrentEpochAttestations([]*ethpb.PendingAttestation{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) setPreviousEpochAttestations(val []*ethpb.PendingAttestation) {
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.PreviousEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.previousEpochAttestations = val
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.rebuildTrie[previousEpochAttestations] = true
|
||||
b.markFieldAsDirty(nativetypes.PreviousEpochAttestations)
|
||||
b.rebuildTrie[nativetypes.PreviousEpochAttestations] = true
|
||||
}
|
||||
|
||||
func (b *BeaconState) setCurrentEpochAttestations(val []*ethpb.PendingAttestation) {
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1)
|
||||
|
||||
b.currentEpochAttestations = val
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.rebuildTrie[currentEpochAttestations] = true
|
||||
b.markFieldAsDirty(nativetypes.CurrentEpochAttestations)
|
||||
b.rebuildTrie[nativetypes.CurrentEpochAttestations] = true
|
||||
}
|
||||
|
||||
// AppendCurrentEpochAttestations for the beacon state. Appends the new value
|
||||
@@ -43,23 +49,27 @@ func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestati
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version != version.Phase0 {
|
||||
return errNotSupported("AppendCurrentEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
atts := b.currentEpochAttestations
|
||||
max := uint64(fieldparams.CurrentEpochAttestationsLength)
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("current pending attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 {
|
||||
if b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
atts = make([]*ethpb.PendingAttestation, len(b.currentEpochAttestations))
|
||||
copy(atts, b.currentEpochAttestations)
|
||||
b.sharedFieldReferences[currentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.CurrentEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.CurrentEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.currentEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(currentEpochAttestations)
|
||||
b.addDirtyIndices(currentEpochAttestations, []uint64{uint64(len(b.currentEpochAttestations) - 1)})
|
||||
b.markFieldAsDirty(nativetypes.CurrentEpochAttestations)
|
||||
b.addDirtyIndices(nativetypes.CurrentEpochAttestations, []uint64{uint64(len(b.currentEpochAttestations) - 1)})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -69,21 +79,25 @@ func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestat
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version != version.Phase0 {
|
||||
return errNotSupported("AppendPreviousEpochAttestations", b.version)
|
||||
}
|
||||
|
||||
atts := b.previousEpochAttestations
|
||||
max := uint64(fieldparams.PreviousEpochAttestationsLength)
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("previous pending attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 {
|
||||
if b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].Refs() > 1 {
|
||||
atts = make([]*ethpb.PendingAttestation, len(b.previousEpochAttestations))
|
||||
copy(atts, b.previousEpochAttestations)
|
||||
b.sharedFieldReferences[previousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.PreviousEpochAttestations].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.PreviousEpochAttestations] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.previousEpochAttestations = append(atts, val)
|
||||
b.markFieldAsDirty(previousEpochAttestations)
|
||||
b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.previousEpochAttestations) - 1)})
|
||||
b.markFieldAsDirty(nativetypes.PreviousEpochAttestations)
|
||||
b.addDirtyIndices(nativetypes.PreviousEpochAttestations, []uint64{uint64(len(b.previousEpochAttestations) - 1)})
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestBeaconState_RotateAttestations(t *testing.T) {
|
||||
st, err := InitializeFromProto(ðpb.BeaconState{
|
||||
st, err := InitializeFromProtoPhase0(ðpb.BeaconState{
|
||||
Slot: 1,
|
||||
CurrentEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 456}}},
|
||||
PreviousEpochAttestations: []*ethpb.PendingAttestation{{Data: ðpb.AttestationData{Slot: 123}}},
|
||||
@@ -17,10 +17,8 @@ func TestBeaconState_RotateAttestations(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, st.RotateAttestations())
|
||||
currEpochAtts, err := st.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(currEpochAtts))
|
||||
prevEpochAtts, err := st.PreviousEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Slot(456), prevEpochAtts[0].Data.Slot)
|
||||
s, ok := st.(*BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, 0, len(s.currentEpochAttestationsVal()))
|
||||
require.Equal(t, types.Slot(456), s.previousEpochAttestationsVal()[0].Data.Slot)
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -15,7 +16,7 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val)
|
||||
b.markFieldAsDirty(latestBlockHeader)
|
||||
b.markFieldAsDirty(nativetypes.LatestBlockHeader)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -25,8 +26,8 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.BlockRoots].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][32]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
@@ -34,8 +35,8 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
}
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
b.markFieldAsDirty(nativetypes.BlockRoots)
|
||||
b.rebuildTrie[nativetypes.BlockRoots] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -49,19 +50,19 @@ func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) err
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
if ref := b.sharedFieldReferences[nativetypes.BlockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.BlockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
b.markFieldAsDirty(nativetypes.BlockRoots)
|
||||
b.addDirtyIndices(nativetypes.BlockRoots, []uint64{idx})
|
||||
return nil
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package v2
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -11,7 +12,7 @@ func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.justificationBits = val
|
||||
b.markFieldAsDirty(justificationBits)
|
||||
b.markFieldAsDirty(nativetypes.JustificationBits)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,7 +22,7 @@ func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) erro
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.previousJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(previousJustifiedCheckpoint)
|
||||
b.markFieldAsDirty(nativetypes.PreviousJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.currentJustifiedCheckpoint = val
|
||||
b.markFieldAsDirty(currentJustifiedCheckpoint)
|
||||
b.markFieldAsDirty(nativetypes.CurrentJustifiedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -41,6 +42,6 @@ func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.finalizedCheckpoint = val
|
||||
b.markFieldAsDirty(finalizedCheckpoint)
|
||||
b.markFieldAsDirty(nativetypes.FinalizedCheckpoint)
|
||||
return nil
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package v3
|
||||
package state_native
|
||||
|
||||
import (
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -11,7 +12,7 @@ func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.eth1Data = val
|
||||
b.markFieldAsDirty(eth1Data)
|
||||
b.markFieldAsDirty(nativetypes.Eth1Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,12 +22,12 @@ func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.Eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1)
|
||||
|
||||
b.eth1DataVotes = val
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.rebuildTrie[eth1DataVotes] = true
|
||||
b.markFieldAsDirty(nativetypes.Eth1DataVotes)
|
||||
b.rebuildTrie[nativetypes.Eth1DataVotes] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.eth1DepositIndex = val
|
||||
b.markFieldAsDirty(eth1DepositIndex)
|
||||
b.markFieldAsDirty(nativetypes.Eth1DepositIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -47,16 +48,16 @@ func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
votes := b.eth1DataVotes
|
||||
if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 {
|
||||
if b.sharedFieldReferences[nativetypes.Eth1DataVotes].Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes))
|
||||
copy(votes, b.eth1DataVotes)
|
||||
b.sharedFieldReferences[eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.Eth1DataVotes].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.Eth1DataVotes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.eth1DataVotes = append(votes, val)
|
||||
b.markFieldAsDirty(eth1DataVotes)
|
||||
b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)})
|
||||
b.markFieldAsDirty(nativetypes.Eth1DataVotes)
|
||||
b.addDirtyIndices(nativetypes.Eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)})
|
||||
return nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package v1
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
nativetypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
@@ -46,7 +46,7 @@ func (b *BeaconState) SetGenesisTime(val uint64) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.genesisTime = val
|
||||
b.markFieldAsDirty(genesisTime)
|
||||
b.markFieldAsDirty(nativetypes.GenesisTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func (b *BeaconState) SetGenesisValidatorsRoot(val []byte) error {
|
||||
return errors.New("incorrect validators root length")
|
||||
}
|
||||
b.genesisValidatorsRoot = bytesutil.ToBytes32(val)
|
||||
b.markFieldAsDirty(genesisValidatorsRoot)
|
||||
b.markFieldAsDirty(nativetypes.GenesisValidatorsRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func (b *BeaconState) SetSlot(val types.Slot) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.slot = val
|
||||
b.markFieldAsDirty(slot)
|
||||
b.markFieldAsDirty(nativetypes.Slot)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error {
|
||||
return errors.New("proto.Clone did not return a fork proto")
|
||||
}
|
||||
b.fork = fk
|
||||
b.markFieldAsDirty(fork)
|
||||
b.markFieldAsDirty(nativetypes.Fork)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -93,15 +93,15 @@ func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.HistoricalRoots].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1)
|
||||
|
||||
roots := make([][32]byte, len(val))
|
||||
for i, r := range val {
|
||||
copy(roots[i][:], r)
|
||||
}
|
||||
b.historicalRoots = roots
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
b.markFieldAsDirty(nativetypes.HistoricalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -112,15 +112,15 @@ func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
|
||||
defer b.lock.Unlock()
|
||||
|
||||
roots := b.historicalRoots
|
||||
if b.sharedFieldReferences[historicalRoots].Refs() > 1 {
|
||||
if b.sharedFieldReferences[nativetypes.HistoricalRoots].Refs() > 1 {
|
||||
roots = make([][32]byte, len(b.historicalRoots))
|
||||
copy(roots, b.historicalRoots)
|
||||
b.sharedFieldReferences[historicalRoots].MinusRef()
|
||||
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[nativetypes.HistoricalRoots].MinusRef()
|
||||
b.sharedFieldReferences[nativetypes.HistoricalRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
b.historicalRoots = append(roots, root)
|
||||
b.markFieldAsDirty(historicalRoots)
|
||||
b.markFieldAsDirty(nativetypes.HistoricalRoots)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -159,13 +159,13 @@ func (b *BeaconState) recomputeRoot(idx int) {
|
||||
b.merkleLayers = layers
|
||||
}
|
||||
|
||||
func (b *BeaconState) markFieldAsDirty(field stateTypes.FieldIndex) {
|
||||
func (b *BeaconState) markFieldAsDirty(field nativetypes.FieldIndex) {
|
||||
b.dirtyFields[field] = true
|
||||
}
|
||||
|
||||
// addDirtyIndices adds the relevant dirty field indices, so that they
|
||||
// can be recomputed.
|
||||
func (b *BeaconState) addDirtyIndices(index stateTypes.FieldIndex, indices []uint64) {
|
||||
func (b *BeaconState) addDirtyIndices(index nativetypes.FieldIndex, indices []uint64) {
|
||||
if b.rebuildTrie[index] {
|
||||
return
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user