Skip to content

Commit

Permalink
use validator new RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
rauljordan committed Dec 11, 2019
1 parent 6e549c9 commit 8a32b59
Show file tree
Hide file tree
Showing 130 changed files with 3,687 additions and 3,212 deletions.
14 changes: 7 additions & 7 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "5c5b65a961b5e7251435efc9548648b45142a07993ad3e100850c240cb76e9af",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/general.tar.gz",
sha256 = "069880d4864e303ad8fca0ecbe61a1e0f2174a7935bbd22bfdfdd7cad34ae9cd",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.2/general.tar.gz",
)

http_archive(
Expand All @@ -162,8 +162,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "3b5f0168af4331d09da52bebc26609def9d11be3e6c784ce7c3df3596617808d",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/minimal.tar.gz",
sha256 = "e71a8b5bef94bba04b8897101a3eb76f2c6de14295eb8b23261b570b3ba1e485",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.2/minimal.tar.gz",
)

http_archive(
Expand All @@ -178,8 +178,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "f3ff68508dfe9696f23506daf0ca895cda955e30398741e00cffa33a01b0565c",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/mainnet.tar.gz",
sha256 = "32c8921bdd469b7de99b8f4d3128e8fbb7da7212fd4aaecec69be42f7ed5493a",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.2/mainnet.tar.gz",
)

http_archive(
Expand Down Expand Up @@ -1249,7 +1249,7 @@ go_repository(

go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "5f21afe48ab14bd0d5311cf5d33853a3e23d2fda",
commit = "17c665094e46b62fc8387e6bb163d99549c639d9",
importpath = "github.com/prysmaticlabs/ethereumapis",
patch_args = ["-p1"],
patches = [
Expand Down
7 changes: 5 additions & 2 deletions beacon-chain/blockchain/chain_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
ctx := context.Background()

c := setupBeaconChain(t, db)

if err := c.forkChoiceStore.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
r := [32]byte{'g'}
if err := db.SaveState(ctx, &pb.BeaconState{}, r); err != nil {
t.Fatal(err)
}
if err := c.forkChoiceStore.GenesisStore(ctx, &ethpb.Checkpoint{Root: r[:]}, &ethpb.Checkpoint{Root: r[:]}); err != nil {
t.Fatal(err)
}

Expand Down
6 changes: 2 additions & 4 deletions beacon-chain/blockchain/forkchoice/lmd_ghost_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,10 @@ func TestGetHeadFromYaml(t *testing.T) {

s := &pb.BeaconState{Validators: validators}

if err := store.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
if err := store.db.SaveState(ctx, s, bytesutil.ToBytes32(blksRoot[0])); err != nil {
t.Fatal(err)
}

store.justifiedCheckpt.Root = blksRoot[0]
if err := store.db.SaveState(ctx, s, bytesutil.ToBytes32(blksRoot[0])); err != nil {
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{Root: blksRoot[0]}, &ethpb.Checkpoint{Root: blksRoot[0]}); err != nil {
t.Fatal(err)
}

Expand Down
71 changes: 65 additions & 6 deletions beacon-chain/blockchain/forkchoice/process_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package forkchoice
import (
"context"
"fmt"
"time"

"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
Expand All @@ -15,6 +16,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
Expand All @@ -28,32 +30,49 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
//
// Spec pseudocode definition:
// def on_attestation(store: Store, attestation: Attestation) -> None:
// """
// Run ``on_attestation`` upon receiving a new ``attestation`` from either within a block or directly on the wire.
//
// An ``attestation`` that is asserted as invalid may be valid at a later time,
// consider scheduling it for later processing in such case.
// """
// target = attestation.data.target
//
// # Attestations must be from the current or previous epoch
// current_epoch = compute_epoch_at_slot(get_current_slot(store))
// # Use GENESIS_EPOCH for previous when genesis to avoid underflow
// previous_epoch = current_epoch - 1 if current_epoch > GENESIS_EPOCH else GENESIS_EPOCH
// assert target.epoch in [current_epoch, previous_epoch]
// # Cannot calculate the current shuffling if have not seen the target
// assert target.root in store.blocks
//
// # Attestations target be for a known block. If target block is unknown, delay consideration until the block is found
// assert target.root in store.blocks
// # Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrives
// base_state = store.block_states[target.root].copy()
// assert store.time >= base_state.genesis_time + compute_start_slot_of_epoch(target.epoch) * SECONDS_PER_SLOT
// assert store.time >= base_state.genesis_time + compute_start_slot_at_epoch(target.epoch) * SECONDS_PER_SLOT
//
// # Attestations must be for a known block. If block is unknown, delay consideration until the block is found
// assert attestation.data.beacon_block_root in store.blocks
// # Attestations must not be for blocks in the future. If not, the attestation should not be considered
// assert store.blocks[attestation.data.beacon_block_root].slot <= attestation.data.slot
//
// # Store target checkpoint state if not yet seen
// if target not in store.checkpoint_states:
// process_slots(base_state, compute_start_slot_of_epoch(target.epoch))
// process_slots(base_state, compute_start_slot_at_epoch(target.epoch))
// store.checkpoint_states[target] = base_state
// target_state = store.checkpoint_states[target]
//
// # Attestations can only affect the fork choice of subsequent slots.
// # Delay consideration in the fork choice until their slot is in the past.
// attestation_slot = get_attestation_data_slot(target_state, attestation.data)
// assert store.time >= (attestation_slot + 1) * SECONDS_PER_SLOT
// assert store.time >= (attestation.data.slot + 1) * SECONDS_PER_SLOT
//
// # Get state at the `target` to validate attestation and calculate the committees
// indexed_attestation = get_indexed_attestation(target_state, attestation)
// assert is_valid_indexed_attestation(target_state, indexed_attestation)
//
// # Update latest messages
// for i in indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices:
// for i in indexed_attestation.attesting_indices:
// if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch:
// store.latest_messages[i] = LatestMessage(epoch=target.epoch, root=attestation.data.beacon_block_root)
func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) error {
Expand All @@ -74,11 +93,21 @@ func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) error {
return err
}

// Verify attestation target is from current epoch or previous epoch.
if err := s.verifyAttTargetEpoch(ctx, baseState.GenesisTime, uint64(time.Now().Unix()), tgt); err != nil {
return err
}

// Verify Attestations cannot be from future epochs.
if err := helpers.VerifySlotTime(baseState.GenesisTime, tgtSlot); err != nil {
return errors.Wrap(err, "could not verify attestation target slot")
}

// Verify attestation beacon block is known and not from the future.
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
return errors.Wrap(err, "could not verify attestation beacon block")
}

// Store target checkpoint state if not yet seen.
baseState, err = s.saveCheckpointState(ctx, baseState, tgt)
if err != nil {
Expand Down Expand Up @@ -133,6 +162,36 @@ func (s *Store) verifyAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*pb
return baseState, nil
}

// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
func (s *Store) verifyAttTargetEpoch(ctx context.Context, genesisTime uint64, nowTime uint64, c *ethpb.Checkpoint) error {
currentSlot := (nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot
currentEpoch := helpers.SlotToEpoch(currentSlot)
var prevEpoch uint64
// Prevents previous epoch under flow
if currentEpoch > 1 {
prevEpoch = currentEpoch - 1
}
if c.Epoch != prevEpoch && c.Epoch != currentEpoch {
return fmt.Errorf("target epoch %d does not match current epoch %d or prev epoch %d", c.Epoch, currentEpoch, prevEpoch)
}
return nil
}

// verifyBeaconBlock verifies beacon head block is known and not from the future.
func (s *Store) verifyBeaconBlock(ctx context.Context, data *ethpb.AttestationData) error {
b, err := s.db.Block(ctx, bytesutil.ToBytes32(data.BeaconBlockRoot))
if err != nil {
return err
}
if b == nil {
return fmt.Errorf("beacon block %#x does not exist", bytesutil.Trunc(data.BeaconBlockRoot))
}
if b.Slot > data.Slot {
return fmt.Errorf("could not process attestation for future block, %d > %d", b.Slot, data.Slot)
}
return nil
}

// saveCheckpointState saves and returns the processed state with the associated check point.
func (s *Store) saveCheckpointState(ctx context.Context, baseState *pb.BeaconState, c *ethpb.Checkpoint) (*pb.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "forkchoice.saveCheckpointState")
Expand Down Expand Up @@ -186,7 +245,7 @@ func (s *Store) updateAttVotes(
tgtRoot []byte,
tgtEpoch uint64) error {

indices := append(indexedAtt.CustodyBit_0Indices, indexedAtt.CustodyBit_1Indices...)
indices := indexedAtt.AttestingIndices
s.voteLock.Lock()
defer s.voteLock.Unlock()
for _, i := range indices {
Expand Down
107 changes: 102 additions & 5 deletions beacon-chain/blockchain/forkchoice/process_attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,21 @@ func TestStore_OnAttestation(t *testing.T) {
wantErrString: "pre state of target block 0 does not exist",
},
{
name: "process attestation from future epoch",
name: "process attestation doesn't match current epoch",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Epoch: params.BeaconConfig().FarFutureEpoch,
Root: BlkWithStateBadAttRoot[:]}}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "could not process slot from the future",
wantErrString: "does not match current epoch",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
if err := store.GenesisStore(
ctx,
&ethpb.Checkpoint{Root: BlkWithValidStateRoot[:]},
&ethpb.Checkpoint{Root: BlkWithValidStateRoot[:]}); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -128,7 +131,11 @@ func TestStore_SaveCheckpointState(t *testing.T) {
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
FinalizedCheckpoint: &ethpb.Checkpoint{},
}
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
r := [32]byte{'g'}
if err := store.db.SaveState(ctx, s, r); err != nil {
t.Fatal(err)
}
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{Root: r[:]}, &ethpb.Checkpoint{Root: r[:]}); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -175,7 +182,7 @@ func TestStore_SaveCheckpointState(t *testing.T) {
}

s.Slot = params.BeaconConfig().SlotsPerEpoch + 1
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{Root: r[:]}, &ethpb.Checkpoint{Root: r[:]}); err != nil {
t.Fatal(err)
}
cp3 := &ethpb.Checkpoint{Epoch: 1, Root: []byte{'C'}}
Expand Down Expand Up @@ -210,3 +217,93 @@ func TestStore_ReturnAggregatedAttestation(t *testing.T) {
t.Error("did not retrieve saved attestation")
}
}

func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

store := NewForkChoiceService(ctx, db)
if err := store.verifyAttTargetEpoch(
ctx,
0,
params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{}); err != nil {
t.Error(err)
}
}

func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

store := NewForkChoiceService(ctx, db)
if err := store.verifyAttTargetEpoch(
ctx,
0,
params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{Epoch: 1}); err != nil {
t.Error(err)
}
}

func TestAttEpoch_NotMatch(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

store := NewForkChoiceService(ctx, db)
if err := store.verifyAttTargetEpoch(
ctx,
0,
2*params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{}); !strings.Contains(err.Error(),
"target epoch 0 does not match current epoch 2 or prev epoch 1") {
t.Error("Did not receive wanted error")
}
}

func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

s := NewForkChoiceService(ctx, db)
d := &ethpb.AttestationData{}
if err := s.verifyBeaconBlock(ctx, d); !strings.Contains(err.Error(), "beacon block does not exist") {
t.Error("Did not receive the wanted error")
}
}

func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

s := NewForkChoiceService(ctx, db)
b := &ethpb.BeaconBlock{Slot: 2}
s.db.SaveBlock(ctx, b)
r, _ := ssz.SigningRoot(b)
d := &ethpb.AttestationData{Slot: 1, BeaconBlockRoot: r[:]}

if err := s.verifyBeaconBlock(ctx, d); !strings.Contains(err.Error(), "could not process attestation for future block") {
t.Error("Did not receive the wanted error")
}
}

func TestVerifyBeaconBlock_OK(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

s := NewForkChoiceService(ctx, db)
b := &ethpb.BeaconBlock{Slot: 2}
s.db.SaveBlock(ctx, b)
r, _ := ssz.SigningRoot(b)
d := &ethpb.AttestationData{Slot: 2, BeaconBlockRoot: r[:]}

if err := s.verifyBeaconBlock(ctx, d); err != nil {
t.Error("Did not receive the wanted error")
}
}
Loading

0 comments on commit 8a32b59

Please sign in to comment.