mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
2f10b1c7b1
* Remove gogoproto compiler * Remove more gogoproto * Improvements * Fix gengo * More scripts * Gazelle, fix deps * Fix version and errors * Fix gocast for arrays * Fix ethapis * Fixes * Fix compile errors * fix go.mod * //proto/... builds * Update for protov2 * temp fix compilation to move on * Change everything to emptypb.empty * Add grpc to proto/slashings * Fix almost all build failures * Oher build problems * FIX THIS FUCKING THING * gaz literally every .bazel * Final touches * Final final touches * Fix proto * Begin moving proto.Marshal to native * Fix site_data * Fixes * Fix duplicate gateway * Fix gateway target * Fix ethapis * Fixes from review * Update * Fix * Fix status test * Fix fuzz * Add isprotoslice to fun * Change DeepEqual to DeepSSZEqual for proto arrays * Fix build * Fix gaz * Update go * Fixes * Fixes * Add case for nil validators after copy * Fix cast * Fix test * Fix imports * Go mod * Only use extension where needed * Fixes * Split gateway from gengo * gaz * go mod * Add back hydrated state * fix hydrate * Fix proto.clone * Fies * Revert "Split gateway from gengo" This reverts commit 7298bb2054d446e427d9af97e13b8fabe8695085. * Revert "gaz" This reverts commit ca952565701a88727e22302d6c8d60ac48d97255. * Merge all gateway into one target * go mod * Gaz * Add generate v1_gateway files * run pb again * goimports * gaz * Fix comments * Fix protos * Fix PR * Fix protos * Update grpc-gateway and ethapis * Update ethapis and gen-go-cast * Go tidy * Reorder * Fix ethapis * fix spec tests * Fix script * Remove unused import * Fix fuzz * Fix gomod * Update version * Error if the cloned result is nil * Handle optional slots * ADd more empty checks to clone * Undo fuzz changes * Fix build.bazel * Gaz * Redo fuzz changes * Undo some eth1data changes * Update go.mod Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> * Undo clone beacon state * Remove gogo proto more and unused v1_gateway * Add manual fix for nil vals * Fix gaz * tidy * Tidy again * Add detailed error * Revert "Add detailed error" This reverts commit 59bc053dcd59569a54c95b07739d5a379665ec5d. * Undo varint changes * Fix nil validators in deposit test * Commit * Undo Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: Nishant Das <nishdas93@gmail.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
337 lines
10 KiB
Go
337 lines
10 KiB
Go
package helpers_test
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
types "github.com/prysmaticlabs/eth2-types"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"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/shared/timeutils"
|
|
)
|
|
|
|
func TestAttestation_IsAggregator(t *testing.T) {
|
|
t.Run("aggregator", func(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
committee, err := helpers.BeaconCommitteeFromState(beaconState, 0, 0)
|
|
require.NoError(t, err)
|
|
sig := privKeys[0].Sign([]byte{'A'})
|
|
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, true, agg, "Wanted aggregator true")
|
|
})
|
|
|
|
t.Run("not aggregator", func(t *testing.T) {
|
|
params.UseMinimalConfig()
|
|
defer params.UseMainnetConfig()
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 2048)
|
|
|
|
committee, err := helpers.BeaconCommitteeFromState(beaconState, 0, 0)
|
|
require.NoError(t, err)
|
|
sig := privKeys[0].Sign([]byte{'A'})
|
|
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, false, agg, "Wanted aggregator false")
|
|
})
|
|
}
|
|
|
|
func TestAttestation_AggregateSignature(t *testing.T) {
|
|
t.Run("verified", func(t *testing.T) {
|
|
pubkeys := make([]bls.PublicKey, 0, 100)
|
|
atts := make([]*ethpb.Attestation, 0, 100)
|
|
msg := bytesutil.ToBytes32([]byte("hello"))
|
|
for i := 0; i < 100; i++ {
|
|
priv, err := bls.RandKey()
|
|
require.NoError(t, err)
|
|
pub := priv.PublicKey()
|
|
sig := priv.Sign(msg[:])
|
|
pubkeys = append(pubkeys, pub)
|
|
att := ðpb.Attestation{Signature: sig.Marshal()}
|
|
atts = append(atts, att)
|
|
}
|
|
aggSig, err := helpers.AggregateSignature(atts)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, true, aggSig.FastAggregateVerify(pubkeys, msg), "Signature did not verify")
|
|
})
|
|
|
|
t.Run("not verified", func(t *testing.T) {
|
|
pubkeys := make([]bls.PublicKey, 0, 100)
|
|
atts := make([]*ethpb.Attestation, 0, 100)
|
|
msg := []byte("hello")
|
|
for i := 0; i < 100; i++ {
|
|
priv, err := bls.RandKey()
|
|
require.NoError(t, err)
|
|
pub := priv.PublicKey()
|
|
sig := priv.Sign(msg)
|
|
pubkeys = append(pubkeys, pub)
|
|
att := ðpb.Attestation{Signature: sig.Marshal()}
|
|
atts = append(atts, att)
|
|
}
|
|
aggSig, err := helpers.AggregateSignature(atts[0 : len(atts)-2])
|
|
require.NoError(t, err)
|
|
assert.Equal(t, false, aggSig.FastAggregateVerify(pubkeys, bytesutil.ToBytes32(msg)), "Signature not suppose to verify")
|
|
})
|
|
}
|
|
|
|
func TestAttestation_ComputeSubnetForAttestation(t *testing.T) {
|
|
// Create 10 committees
|
|
committeeCount := uint64(10)
|
|
validatorCount := committeeCount * params.BeaconConfig().TargetCommitteeSize
|
|
validators := make([]*ethpb.Validator, validatorCount)
|
|
|
|
for i := 0; i < len(validators); i++ {
|
|
k := make([]byte, 48)
|
|
copy(k, strconv.Itoa(i))
|
|
validators[i] = ðpb.Validator{
|
|
PublicKey: k,
|
|
WithdrawalCredentials: make([]byte, 32),
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
}
|
|
}
|
|
|
|
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
|
Validators: validators,
|
|
Slot: 200,
|
|
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
|
StateRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
require.NoError(t, err)
|
|
att := ðpb.Attestation{
|
|
AggregationBits: []byte{'A'},
|
|
Data: ðpb.AttestationData{
|
|
Slot: 34,
|
|
CommitteeIndex: 4,
|
|
BeaconBlockRoot: []byte{'C'},
|
|
Source: nil,
|
|
Target: nil,
|
|
},
|
|
Signature: []byte{'B'},
|
|
}
|
|
valCount, err := helpers.ActiveValidatorCount(state, helpers.SlotToEpoch(att.Data.Slot))
|
|
require.NoError(t, err)
|
|
sub := helpers.ComputeSubnetForAttestation(valCount, att)
|
|
assert.Equal(t, uint64(6), sub, "Did not get correct subnet for attestation")
|
|
}
|
|
|
|
func Test_ValidateAttestationTime(t *testing.T) {
|
|
if params.BeaconNetworkConfig().MaximumGossipClockDisparity < 200*time.Millisecond {
|
|
t.Fatal("This test expects the maximum clock disparity to be at least 200ms")
|
|
}
|
|
|
|
type args struct {
|
|
attSlot types.Slot
|
|
genesisTime time.Time
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
wantedErr string
|
|
}{
|
|
{
|
|
name: "attestation.slot == current_slot",
|
|
args: args{
|
|
attSlot: 15,
|
|
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
|
|
},
|
|
},
|
|
{
|
|
name: "attestation.slot == current_slot, received in middle of slot",
|
|
args: args{
|
|
attSlot: 15,
|
|
genesisTime: timeutils.Now().Add(
|
|
-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
|
|
).Add(-(time.Duration(params.BeaconConfig().SecondsPerSlot/2) * time.Second)),
|
|
},
|
|
},
|
|
{
|
|
name: "attestation.slot == current_slot, received 200ms early",
|
|
args: args{
|
|
attSlot: 16,
|
|
genesisTime: timeutils.Now().Add(
|
|
-16 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
|
|
).Add(-200 * time.Millisecond),
|
|
},
|
|
},
|
|
{
|
|
name: "attestation.slot > current_slot",
|
|
args: args{
|
|
attSlot: 16,
|
|
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
|
|
},
|
|
wantedErr: "not within attestation propagation range",
|
|
},
|
|
{
|
|
name: "attestation.slot < current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE",
|
|
args: args{
|
|
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange - 1,
|
|
genesisTime: timeutils.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
|
|
},
|
|
wantedErr: "not within attestation propagation range",
|
|
},
|
|
{
|
|
name: "attestation.slot = current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE",
|
|
args: args{
|
|
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange,
|
|
genesisTime: timeutils.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
|
|
},
|
|
},
|
|
{
|
|
name: "attestation.slot = current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE, received 200ms late",
|
|
args: args{
|
|
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange,
|
|
genesisTime: timeutils.Now().Add(
|
|
-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
|
|
).Add(200 * time.Millisecond),
|
|
},
|
|
},
|
|
{
|
|
name: "attestation.slot is well beyond current slot",
|
|
args: args{
|
|
attSlot: 1 << 32,
|
|
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
|
|
},
|
|
wantedErr: "which exceeds max allowed value relative to the local clock",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := helpers.ValidateAttestationTime(tt.args.attSlot, tt.args.genesisTime)
|
|
if tt.wantedErr != "" {
|
|
assert.ErrorContains(t, tt.wantedErr, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVerifyCheckpointEpoch_Ok(t *testing.T) {
|
|
// Genesis was 6 epochs ago exactly.
|
|
offset := params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot * 6)
|
|
genesis := time.Now().Add(-1 * time.Second * time.Duration(offset))
|
|
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 6}, genesis))
|
|
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 5}, genesis))
|
|
assert.Equal(t, false, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 4}, genesis))
|
|
assert.Equal(t, false, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 2}, genesis))
|
|
}
|
|
|
|
func TestValidateNilAttestation(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
attestation *ethpb.Attestation
|
|
errString string
|
|
}{
|
|
{
|
|
name: "nil attestation",
|
|
attestation: nil,
|
|
errString: "attestation can't be nil",
|
|
},
|
|
{
|
|
name: "nil attestation data",
|
|
attestation: ðpb.Attestation{},
|
|
errString: "attestation's data can't be nil",
|
|
},
|
|
{
|
|
name: "nil attestation source",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: nil,
|
|
Target: ðpb.Checkpoint{},
|
|
},
|
|
},
|
|
errString: "attestation's source can't be nil",
|
|
},
|
|
{
|
|
name: "nil attestation target",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: nil,
|
|
Source: ðpb.Checkpoint{},
|
|
},
|
|
},
|
|
errString: "attestation's target can't be nil",
|
|
},
|
|
{
|
|
name: "nil attestation bitfield",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{},
|
|
Source: ðpb.Checkpoint{},
|
|
},
|
|
},
|
|
errString: "attestation's bitfield can't be nil",
|
|
},
|
|
{
|
|
name: "good attestation",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{},
|
|
Source: ðpb.Checkpoint{},
|
|
},
|
|
AggregationBits: []byte{},
|
|
},
|
|
errString: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.errString != "" {
|
|
require.ErrorContains(t, tt.errString, helpers.ValidateNilAttestation(tt.attestation))
|
|
} else {
|
|
require.NoError(t, helpers.ValidateNilAttestation(tt.attestation))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateSlotTargetEpoch(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
attestation *ethpb.Attestation
|
|
errString string
|
|
}{
|
|
{
|
|
name: "incorrect slot",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{Epoch: 1},
|
|
Source: ðpb.Checkpoint{},
|
|
},
|
|
AggregationBits: []byte{},
|
|
},
|
|
errString: "slot 0 does not match target epoch 1",
|
|
},
|
|
{
|
|
name: "good attestation",
|
|
attestation: ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Slot: 2 * params.BeaconConfig().SlotsPerEpoch,
|
|
Target: ðpb.Checkpoint{Epoch: 2},
|
|
Source: ðpb.Checkpoint{},
|
|
},
|
|
AggregationBits: []byte{},
|
|
},
|
|
errString: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.errString != "" {
|
|
require.ErrorContains(t, tt.errString, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
|
|
} else {
|
|
require.NoError(t, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
|
|
}
|
|
})
|
|
}
|
|
}
|