mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-20 08:31:11 +00:00
78a25f99c3
* Update fastssz * Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz * fmt * gaz * Merge refs/heads/master into update-fssz * goimports * Merge refs/heads/master into update-fssz * Merge refs/heads/master into update-fssz * Merge refs/heads/master into update-fssz * Merge refs/heads/master into update-fssz * Merge refs/heads/master into update-fssz * Fix * fix ethereumapis * fix again * kafka * fix gen file * fix compute signing root * gofmt * checkpoint progress * progress * checkpoint * progress * Fix build * checkpoint * helpers * Another test fixed * gaz * another test fix * gofmt * some fixes * Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz * fix one test * Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz * fill empty checkpoint roots * more padding * more padding * Fix //beacon-chain/rpc/debug:go_default_test * fix //beacon-chain/core/state:go_default_test * fix //beacon-chain/core/state:go_default_test * fix some htr errors * fix //slasher/rpc:go_default_test * Progress on //beacon-chain/core/blocks:go_default_test * Progress on //beacon-chain/core/blocks:go_default_test * Progress on //beacon-chain/core/blocks:go_default_test * fix //slasher/db/kv:go_default_test * progress * fix //beacon-chain/sync/initial-sync:go_raceon_test * gofmt and gaz * fix one more test, taking a break * Fix //beacon-chain/core/blocks:go_default_test * Complete beacon-chain/powchain * Do most of beacon-chain/rpc/beacon/ * Do most of beacon-chain/blockchain * fix //beacon-chain/operations/attestations/kv:go_default_test * Fix //beacon-chain/cache/depositcache:go_default_test * Fix //slasher/detection:go_default_test * Progress * fix //beacon-chain/rpc/validator:go_default_test * gofmt * fix //validator/client:go_default_test * fix * fix //beacon-chain/blockchain:go_raceoff_test * fix //beacon-chain/rpc/beacon:go_default_test * fix 1 of 4 shards in //beacon-chain/sync:go_default_test * Fix //beacon-chain/sync:go_default_test and gofmt * prevent panic * fix //beacon-chain/state/stategen:go_default_test * fix * Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz * fix most tests * Self review, go mod tidy, run regen scripts * fix slasher * Update ethereumapis * disable spawn strategy override * Merge refs/heads/master into update-fssz * Merge refs/heads/master into update-fssz * Remove extra line in imports * Remove extra line in imports * Gofmt * PR feedback from @nisdas
319 lines
12 KiB
Go
319 lines
12 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/mock"
|
|
"github.com/prysmaticlabs/prysm/shared/p2putils"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
|
"github.com/prysmaticlabs/prysm/slasher/beaconclient"
|
|
testDB "github.com/prysmaticlabs/prysm/slasher/db/testing"
|
|
"github.com/prysmaticlabs/prysm/slasher/detection"
|
|
)
|
|
|
|
func TestServer_IsSlashableAttestation(t *testing.T) {
|
|
db := testDB.SetupSlasherDB(t, false)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
bClient := mock.NewMockBeaconChainClient(ctrl)
|
|
nClient := mock.NewMockNodeClient(ctrl)
|
|
ctx := context.Background()
|
|
|
|
_, keys, err := testutil.DeterministicDepositsAndKeys(4)
|
|
require.NoError(t, err)
|
|
wantedValidators1 := ðpb.Validators{
|
|
ValidatorList: []*ethpb.Validators_ValidatorContainer{
|
|
{
|
|
Index: 3, Validator: ðpb.Validator{PublicKey: keys[3].PublicKey().Marshal()},
|
|
},
|
|
},
|
|
}
|
|
|
|
wantedGenesis := ðpb.Genesis{
|
|
GenesisValidatorsRoot: bytesutil.PadTo([]byte("I am genesis"), 32),
|
|
}
|
|
|
|
savedAttestation := ðpb.IndexedAttestation{
|
|
AttestingIndices: []uint64{3},
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 3, Root: make([]byte, 32)},
|
|
Target: ðpb.Checkpoint{Epoch: 4, Root: make([]byte, 32)},
|
|
BeaconBlockRoot: make([]byte, 32),
|
|
},
|
|
Signature: make([]byte, 96),
|
|
}
|
|
|
|
cfg := &detection.Config{
|
|
SlasherDB: db,
|
|
}
|
|
fork, err := p2putils.Fork(savedAttestation.Data.Target.Epoch)
|
|
require.NoError(t, err)
|
|
|
|
bcCfg := &beaconclient.Config{BeaconClient: bClient, NodeClient: nClient, SlasherDB: db}
|
|
bs, err := beaconclient.NewBeaconClientService(ctx, bcCfg)
|
|
ds := detection.NewDetectionService(ctx, cfg)
|
|
server := Server{ctx: ctx, detector: ds, slasherDB: db, beaconClient: bs}
|
|
nClient.EXPECT().GetGenesis(gomock.Any(), gomock.Any()).Return(wantedGenesis, nil).AnyTimes()
|
|
bClient.EXPECT().ListValidators(
|
|
gomock.Any(),
|
|
gomock.Any(),
|
|
).Return(wantedValidators1, nil).AnyTimes()
|
|
domain, err := helpers.Domain(fork, savedAttestation.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, wantedGenesis.GenesisValidatorsRoot)
|
|
require.NoError(t, err)
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(100)
|
|
var wentThrough bool
|
|
for i := uint64(0); i < 100; i++ {
|
|
go func(j uint64) {
|
|
defer wg.Done()
|
|
iatt := state.CopyIndexedAttestation(savedAttestation)
|
|
iatt.Data.Slot += j
|
|
root, err := helpers.ComputeSigningRoot(iatt.Data, domain)
|
|
require.NoError(t, err)
|
|
var validatorSig bls.Signature
|
|
validatorSig = keys[iatt.AttestingIndices[0]].Sign(root[:])
|
|
marshalledSig := validatorSig.Marshal()
|
|
iatt.Signature = marshalledSig
|
|
slashings, err := server.IsSlashableAttestation(ctx, iatt)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
|
|
if len(slashings.AttesterSlashing) == 0 && !wentThrough {
|
|
wentThrough = true
|
|
} else if len(slashings.AttesterSlashing) == 0 && wentThrough {
|
|
t.Fatalf("Only one attestation should go through without slashing: %v", iatt)
|
|
}
|
|
}(i)
|
|
}
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
func TestServer_IsSlashableAttestationNoUpdate(t *testing.T) {
|
|
db := testDB.SetupSlasherDB(t, false)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
bClient := mock.NewMockBeaconChainClient(ctrl)
|
|
nClient := mock.NewMockNodeClient(ctrl)
|
|
ctx := context.Background()
|
|
|
|
_, keys, err := testutil.DeterministicDepositsAndKeys(4)
|
|
require.NoError(t, err)
|
|
wantedValidators1 := ðpb.Validators{
|
|
ValidatorList: []*ethpb.Validators_ValidatorContainer{
|
|
{
|
|
Index: 3, Validator: ðpb.Validator{PublicKey: keys[3].PublicKey().Marshal()},
|
|
},
|
|
},
|
|
}
|
|
bClient.EXPECT().ListValidators(
|
|
gomock.Any(),
|
|
gomock.Any(),
|
|
).Return(wantedValidators1, nil)
|
|
|
|
wantedGenesis := ðpb.Genesis{
|
|
GenesisValidatorsRoot: bytesutil.PadTo([]byte("I am genesis"), 32),
|
|
}
|
|
nClient.EXPECT().GetGenesis(gomock.Any(), gomock.Any()).Return(wantedGenesis, nil)
|
|
savedAttestation := ðpb.IndexedAttestation{
|
|
AttestingIndices: []uint64{3},
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 3, Root: make([]byte, 32)},
|
|
Target: ðpb.Checkpoint{Epoch: 4, Root: make([]byte, 32)},
|
|
BeaconBlockRoot: make([]byte, 32),
|
|
},
|
|
Signature: make([]byte, 96),
|
|
}
|
|
incomingAtt := ðpb.IndexedAttestation{
|
|
AttestingIndices: []uint64{1, 3},
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 2, Root: make([]byte, 32)},
|
|
Target: ðpb.Checkpoint{Epoch: 4, Root: make([]byte, 32)},
|
|
BeaconBlockRoot: make([]byte, 32),
|
|
},
|
|
Signature: make([]byte, 96),
|
|
}
|
|
cfg := &detection.Config{
|
|
SlasherDB: db,
|
|
}
|
|
fork, err := p2putils.Fork(savedAttestation.Data.Target.Epoch)
|
|
require.NoError(t, err)
|
|
domain, err := helpers.Domain(fork, savedAttestation.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, wantedGenesis.GenesisValidatorsRoot)
|
|
require.NoError(t, err)
|
|
root, err := helpers.ComputeSigningRoot(savedAttestation.Data, domain)
|
|
require.NoError(t, err)
|
|
sig := []bls.Signature{}
|
|
for _, idx := range savedAttestation.AttestingIndices {
|
|
validatorSig := keys[idx].Sign(root[:])
|
|
sig = append(sig, validatorSig)
|
|
}
|
|
aggSig := bls.AggregateSignatures(sig)
|
|
marshalledSig := aggSig.Marshal()
|
|
|
|
savedAttestation.Signature = marshalledSig
|
|
|
|
bcCfg := &beaconclient.Config{BeaconClient: bClient, NodeClient: nClient, SlasherDB: db}
|
|
bs, err := beaconclient.NewBeaconClientService(ctx, bcCfg)
|
|
ds := detection.NewDetectionService(ctx, cfg)
|
|
server := Server{ctx: ctx, detector: ds, slasherDB: db, beaconClient: bs}
|
|
slashings, err := server.IsSlashableAttestation(ctx, savedAttestation)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
require.Equal(t, 0, len(slashings.AttesterSlashing), "Found slashings while no slashing should have been found on first attestation")
|
|
sl, err := server.IsSlashableAttestationNoUpdate(ctx, incomingAtt)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
require.Equal(t, true, sl.Slashable, "Attestation should be found to be slashable")
|
|
}
|
|
|
|
func TestServer_IsSlashableBlock(t *testing.T) {
|
|
db := testDB.SetupSlasherDB(t, false)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
bClient := mock.NewMockBeaconChainClient(ctrl)
|
|
nClient := mock.NewMockNodeClient(ctrl)
|
|
ctx := context.Background()
|
|
|
|
_, keys, err := testutil.DeterministicDepositsAndKeys(4)
|
|
require.NoError(t, err)
|
|
wantedValidators := ðpb.Validators{
|
|
ValidatorList: []*ethpb.Validators_ValidatorContainer{
|
|
{
|
|
Index: 1, Validator: ðpb.Validator{PublicKey: keys[1].PublicKey().Marshal()},
|
|
},
|
|
},
|
|
}
|
|
bClient.EXPECT().ListValidators(
|
|
gomock.Any(),
|
|
gomock.Any(),
|
|
).Return(wantedValidators, nil).AnyTimes()
|
|
|
|
wantedGenesis := ðpb.Genesis{
|
|
GenesisValidatorsRoot: bytesutil.PadTo([]byte("I am genesis"), 32),
|
|
}
|
|
nClient.EXPECT().GetGenesis(gomock.Any(), gomock.Any()).Return(wantedGenesis, nil).AnyTimes()
|
|
savedBlock := ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
Slot: 1,
|
|
ProposerIndex: 1,
|
|
BodyRoot: bytesutil.PadTo([]byte("body root"), 32),
|
|
StateRoot: make([]byte, 32),
|
|
ParentRoot: make([]byte, 32),
|
|
},
|
|
Signature: make([]byte, 96),
|
|
}
|
|
|
|
cfg := &detection.Config{
|
|
SlasherDB: db,
|
|
}
|
|
savedBlockEpoch := helpers.SlotToEpoch(savedBlock.Header.Slot)
|
|
fork, err := p2putils.Fork(savedBlockEpoch)
|
|
require.NoError(t, err)
|
|
domain, err := helpers.Domain(fork, savedBlockEpoch, params.BeaconConfig().DomainBeaconProposer, wantedGenesis.GenesisValidatorsRoot)
|
|
require.NoError(t, err)
|
|
|
|
bcCfg := &beaconclient.Config{BeaconClient: bClient, NodeClient: nClient, SlasherDB: db}
|
|
bs, err := beaconclient.NewBeaconClientService(ctx, bcCfg)
|
|
ds := detection.NewDetectionService(ctx, cfg)
|
|
server := Server{ctx: ctx, detector: ds, slasherDB: db, beaconClient: bs}
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(100)
|
|
var wentThrough bool
|
|
for i := uint64(0); i < 100; i++ {
|
|
go func(j uint64) {
|
|
defer wg.Done()
|
|
sbbh := state.CopySignedBeaconBlockHeader(savedBlock)
|
|
sbbh.Header.BodyRoot = bytesutil.PadTo([]byte(fmt.Sprintf("%d", j)), 32)
|
|
bhr, err := stateutil.BlockHeaderRoot(sbbh.Header)
|
|
assert.NoError(t, err)
|
|
root, err := helpers.ComputeSigningRoot(bhr, domain)
|
|
assert.NoError(t, err)
|
|
sbbh.Signature = keys[sbbh.Header.ProposerIndex].Sign(root[:]).Marshal()
|
|
slashings, err := server.IsSlashableBlock(ctx, sbbh)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
if len(slashings.ProposerSlashing) == 0 && !wentThrough {
|
|
wentThrough = true
|
|
} else if len(slashings.ProposerSlashing) == 0 && wentThrough {
|
|
t.Fatalf("Only one block should go through without slashing: %v", sbbh)
|
|
}
|
|
}(i)
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestServer_IsSlashableBlockNoUpdate(t *testing.T) {
|
|
db := testDB.SetupSlasherDB(t, false)
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
bClient := mock.NewMockBeaconChainClient(ctrl)
|
|
nClient := mock.NewMockNodeClient(ctrl)
|
|
ctx := context.Background()
|
|
|
|
_, keys, err := testutil.DeterministicDepositsAndKeys(4)
|
|
require.NoError(t, err)
|
|
wantedValidators := ðpb.Validators{
|
|
ValidatorList: []*ethpb.Validators_ValidatorContainer{
|
|
{
|
|
Index: 1, Validator: ðpb.Validator{PublicKey: keys[1].PublicKey().Marshal()},
|
|
},
|
|
},
|
|
}
|
|
bClient.EXPECT().ListValidators(
|
|
gomock.Any(),
|
|
gomock.Any(),
|
|
).Return(wantedValidators, nil)
|
|
|
|
wantedGenesis := ðpb.Genesis{
|
|
GenesisValidatorsRoot: bytesutil.PadTo([]byte("I am genesis"), 32),
|
|
}
|
|
nClient.EXPECT().GetGenesis(gomock.Any(), gomock.Any()).Return(wantedGenesis, nil)
|
|
savedBlock := ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
Slot: 1,
|
|
ProposerIndex: 1,
|
|
BodyRoot: bytesutil.PadTo([]byte("body root"), 32),
|
|
},
|
|
}
|
|
incomingBlock := ðpb.BeaconBlockHeader{
|
|
Slot: 1,
|
|
ProposerIndex: 1,
|
|
BodyRoot: bytesutil.PadTo([]byte("body root2"), 32),
|
|
}
|
|
cfg := &detection.Config{
|
|
SlasherDB: db,
|
|
}
|
|
savedBlockEpoch := helpers.SlotToEpoch(savedBlock.Header.Slot)
|
|
fork, err := p2putils.Fork(savedBlockEpoch)
|
|
require.NoError(t, err)
|
|
domain, err := helpers.Domain(fork, savedBlockEpoch, params.BeaconConfig().DomainBeaconProposer, wantedGenesis.GenesisValidatorsRoot)
|
|
require.NoError(t, err)
|
|
bhr, err := stateutil.BlockHeaderRoot(savedBlock.Header)
|
|
require.NoError(t, err)
|
|
root, err := helpers.ComputeSigningRoot(bhr, domain)
|
|
require.NoError(t, err)
|
|
blockSig := keys[savedBlock.Header.ProposerIndex].Sign(root[:])
|
|
marshalledSig := blockSig.Marshal()
|
|
savedBlock.Signature = marshalledSig
|
|
bcCfg := &beaconclient.Config{BeaconClient: bClient, NodeClient: nClient, SlasherDB: db}
|
|
bs, err := beaconclient.NewBeaconClientService(ctx, bcCfg)
|
|
ds := detection.NewDetectionService(ctx, cfg)
|
|
server := Server{ctx: ctx, detector: ds, slasherDB: db, beaconClient: bs}
|
|
slashings, err := server.IsSlashableBlock(ctx, savedBlock)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
require.Equal(t, 0, len(slashings.ProposerSlashing), "Found slashings while no slashing should have been found on first block")
|
|
sl, err := server.IsSlashableBlockNoUpdate(ctx, incomingBlock)
|
|
require.NoError(t, err, "Got error while trying to detect slashing")
|
|
require.Equal(t, true, sl.Slashable, "Block should be found to be slashable")
|
|
}
|