mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Fixed sanity consensus tests for slots processing (#6949)
This commit is contained in:
parent
ab6239b30f
commit
cfa8dd8657
@ -848,6 +848,20 @@ func chiadoConfig() BeaconChainConfig {
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (b *BeaconChainConfig) GetMinSlashingPenaltyQuotient(version StateVersion) uint64 {
|
||||
switch version {
|
||||
case Phase0Version:
|
||||
return b.MinSlashingPenaltyQuotient
|
||||
case AltairVersion:
|
||||
return b.MinSlashingPenaltyQuotientAltair
|
||||
case BellatrixVersion:
|
||||
return b.MinSlashingPenaltyQuotientBellatrix
|
||||
default:
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Beacon configs
|
||||
var BeaconConfigs map[NetworkType]BeaconChainConfig = map[NetworkType]BeaconChainConfig{
|
||||
MainnetNetwork: mainnetConfig(),
|
||||
|
@ -452,6 +452,11 @@ type AttestationData struct {
|
||||
Target *Checkpoint
|
||||
}
|
||||
|
||||
func (a *AttestationData) Equal(other *AttestationData) bool {
|
||||
return a.Slot == other.Slot && a.Index == other.Index && a.BeaconBlockHash == other.BeaconBlockHash &&
|
||||
a.Source.Equal(other.Source) && a.Target.Equal(other.Target)
|
||||
}
|
||||
|
||||
// EncodeSSZ ssz marshals the AttestationData object
|
||||
func (a *AttestationData) EncodeSSZ(dst []byte) ([]byte, error) {
|
||||
buf := dst
|
||||
|
@ -13,6 +13,10 @@ type Checkpoint struct {
|
||||
Root libcommon.Hash
|
||||
}
|
||||
|
||||
func (c *Checkpoint) Equal(other *Checkpoint) bool {
|
||||
return c.Epoch == other.Epoch && c.Root == other.Root
|
||||
}
|
||||
|
||||
func (c *Checkpoint) EncodeSSZ(buf []byte) ([]byte, error) {
|
||||
return append(buf, append(ssz_utils.Uint64SSZ(c.Epoch), c.Root[:]...)...), nil
|
||||
}
|
||||
|
@ -296,6 +296,10 @@ type Validator struct {
|
||||
WithdrawableEpoch uint64
|
||||
}
|
||||
|
||||
func (v *Validator) IsSlashable(epoch uint64) bool {
|
||||
return !v.Slashed && (v.ActivationEpoch <= epoch) && (epoch < v.WithdrawableEpoch)
|
||||
}
|
||||
|
||||
func (v *Validator) EncodeSSZ(dst []byte) ([]byte, error) {
|
||||
buf := dst
|
||||
buf = append(buf, v.PublicKey[:]...)
|
||||
|
24
cl/utils/set.go
Normal file
24
cl/utils/set.go
Normal file
@ -0,0 +1,24 @@
|
||||
package utils
|
||||
|
||||
func IntersectionOfSortedSets(v1, v2 []uint64) []uint64 {
|
||||
intersection := []uint64{}
|
||||
// keep track of v1 and v2 element iteration
|
||||
var i, j int
|
||||
// Note that v1 and v2 are both sorted.
|
||||
for i < len(v1) && j < len(v2) {
|
||||
if v1[i] == v2[j] {
|
||||
intersection = append(intersection, v1[i])
|
||||
// Change both iterators
|
||||
i++
|
||||
j++
|
||||
continue
|
||||
}
|
||||
// increase i and j accordingly
|
||||
if v1[i] > v2[j] {
|
||||
j++
|
||||
} else {
|
||||
i++
|
||||
}
|
||||
}
|
||||
return intersection
|
||||
}
|
@ -1 +0,0 @@
|
||||
go run *.go
|
@ -28,17 +28,20 @@ func testSanityFunction() error {
|
||||
}
|
||||
transistor := transition.New(testState, &clparams.MainnetBeaconConfig, nil, false)
|
||||
for _, block := range blocks {
|
||||
err := transistor.TransitionState(block)
|
||||
if expectedError && err == nil {
|
||||
return fmt.Errorf("expected error")
|
||||
}
|
||||
err = transistor.TransitionState(block)
|
||||
if err != nil {
|
||||
if expectedError {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
// Deal with transition error
|
||||
if expectedError && err == nil {
|
||||
return fmt.Errorf("expected error")
|
||||
}
|
||||
if err != nil {
|
||||
if expectedError {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
expectedRoot, err := expectedState.HashSSZ()
|
||||
if err != nil {
|
||||
@ -49,7 +52,7 @@ func testSanityFunction() error {
|
||||
return err
|
||||
}
|
||||
if haveRoot != expectedRoot {
|
||||
return fmt.Errorf("mismatching state roots.")
|
||||
return fmt.Errorf("mismatching state roots")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -291,10 +291,7 @@ func (b *BeaconState) SyncRewards() (proposerReward, participantReward uint64, e
|
||||
|
||||
func (b *BeaconState) ValidatorFromDeposit(deposit *cltypes.Deposit) *cltypes.Validator {
|
||||
amount := deposit.Data.Amount
|
||||
effectiveBalance := amount - amount%b.beaconConfig.EffectiveBalanceIncrement
|
||||
if effectiveBalance > b.beaconConfig.EffectiveBalanceIncrement {
|
||||
effectiveBalance = b.beaconConfig.EffectiveBalanceIncrement
|
||||
}
|
||||
effectiveBalance := utils.Min64(amount-amount%b.beaconConfig.EffectiveBalanceIncrement, b.beaconConfig.MaxEffectiveBalance)
|
||||
|
||||
return &cltypes.Validator{
|
||||
PublicKey: deposit.Data.PubKey,
|
||||
@ -456,3 +453,11 @@ func (b *BeaconState) ValidatorChurnLimit() (limit uint64) {
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (b *BeaconState) IsMergeTransitionComplete() bool {
|
||||
return b.latestExecutionPayloadHeader.Root != libcommon.Hash{}
|
||||
}
|
||||
|
||||
func (b *BeaconState) ComputeTimestampAtSlot(slot uint64) uint64 {
|
||||
return b.genesisTime + (slot-b.beaconConfig.GenesisSlot)*b.beaconConfig.SecondsPerSlot
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/common/math"
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/utils"
|
||||
)
|
||||
|
||||
@ -37,11 +38,7 @@ func (b *BeaconState) GetValidatorChurnLimit() uint64 {
|
||||
}
|
||||
|
||||
func (b *BeaconState) InitiateValidatorExit(index uint64) error {
|
||||
validator, err := b.ValidatorAt(int(index))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if validator.ExitEpoch != b.beaconConfig.FarFutureEpoch {
|
||||
if b.validators[index].ExitEpoch != b.beaconConfig.FarFutureEpoch {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -63,33 +60,35 @@ func (b *BeaconState) InitiateValidatorExit(index uint64) error {
|
||||
exitQueueEpoch += 1
|
||||
}
|
||||
|
||||
validator.ExitEpoch = exitQueueEpoch
|
||||
b.validators[index].ExitEpoch = exitQueueEpoch
|
||||
var overflow bool
|
||||
if validator.WithdrawableEpoch, overflow = math.SafeAdd(validator.ExitEpoch, b.beaconConfig.MinValidatorWithdrawabilityDelay); overflow {
|
||||
if b.validators[index].WithdrawableEpoch, overflow = math.SafeAdd(b.validators[index].ExitEpoch, b.beaconConfig.MinValidatorWithdrawabilityDelay); overflow {
|
||||
return fmt.Errorf("withdrawable epoch is too big")
|
||||
}
|
||||
|
||||
return b.SetValidatorAt(int(index), &validator)
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) SlashValidator(slashedInd, whistleblowerInd uint64) error {
|
||||
func (b *BeaconState) getSlashingProposerReward(whistleBlowerReward uint64) uint64 {
|
||||
if b.version == clparams.Phase0Version {
|
||||
return whistleBlowerReward / b.beaconConfig.ProposerRewardQuotient
|
||||
}
|
||||
return whistleBlowerReward * b.beaconConfig.ProposerWeight / b.beaconConfig.WeightDenominator
|
||||
}
|
||||
|
||||
func (b *BeaconState) SlashValidator(slashedInd uint64, whistleblowerInd *uint64) error {
|
||||
epoch := b.Epoch()
|
||||
if err := b.InitiateValidatorExit(slashedInd); err != nil {
|
||||
return err
|
||||
}
|
||||
newValidator := b.validators[slashedInd]
|
||||
newValidator.Slashed = true
|
||||
withdrawEpoch := epoch + b.beaconConfig.EpochsPerSlashingsVector
|
||||
if newValidator.WithdrawableEpoch < withdrawEpoch {
|
||||
newValidator.WithdrawableEpoch = withdrawEpoch
|
||||
}
|
||||
if err := b.SetValidatorAt(int(slashedInd), newValidator); err != nil {
|
||||
return err
|
||||
}
|
||||
segmentIndex := int(epoch % b.beaconConfig.EpochsPerSlashingsVector)
|
||||
currentSlashing := b.SlashingSegmentAt(segmentIndex)
|
||||
b.SetSlashingSegmentAt(segmentIndex, currentSlashing+newValidator.EffectiveBalance)
|
||||
if err := b.DecreaseBalance(slashedInd, newValidator.EffectiveBalance/b.beaconConfig.MinSlashingPenaltyQuotient); err != nil {
|
||||
// Change the validator to be slashed
|
||||
b.validators[slashedInd].Slashed = true
|
||||
b.validators[slashedInd].WithdrawableEpoch = utils.Max64(b.validators[slashedInd].WithdrawableEpoch, epoch+b.beaconConfig.EpochsPerSlashingsVector)
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
// Update slashings vector
|
||||
b.slashings[epoch%b.beaconConfig.EpochsPerSlashingsVector] += b.validators[slashedInd].EffectiveBalance
|
||||
b.touchedLeaves[SlashingsLeafIndex] = true
|
||||
if err := b.DecreaseBalance(slashedInd, b.validators[slashedInd].EffectiveBalance/b.beaconConfig.GetMinSlashingPenaltyQuotient(b.version)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -97,13 +96,15 @@ func (b *BeaconState) SlashValidator(slashedInd, whistleblowerInd uint64) error
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get beacon proposer index: %v", err)
|
||||
}
|
||||
if whistleblowerInd == 0 {
|
||||
whistleblowerInd = proposerInd
|
||||
if whistleblowerInd == nil {
|
||||
whistleblowerInd = new(uint64)
|
||||
*whistleblowerInd = proposerInd
|
||||
}
|
||||
whistleBlowerReward := newValidator.EffectiveBalance / b.beaconConfig.WhistleBlowerRewardQuotient
|
||||
proposerReward := whistleBlowerReward / b.beaconConfig.ProposerRewardQuotient
|
||||
|
||||
whistleBlowerReward := b.validators[slashedInd].EffectiveBalance / b.beaconConfig.WhistleBlowerRewardQuotient
|
||||
proposerReward := b.getSlashingProposerReward(whistleBlowerReward)
|
||||
if err := b.IncreaseBalance(proposerInd, proposerReward); err != nil {
|
||||
return err
|
||||
}
|
||||
return b.IncreaseBalance(whistleblowerInd, whistleBlowerReward)
|
||||
return b.IncreaseBalance(*whistleblowerInd, whistleBlowerReward-proposerReward)
|
||||
}
|
||||
|
@ -138,10 +138,8 @@ func TestSlashValidator(t *testing.T) {
|
||||
successState := getTestState(t)
|
||||
|
||||
successBalances := []uint64{}
|
||||
wantBalances := []uint64{}
|
||||
for i := 0; i < len(successState.Validators()); i++ {
|
||||
successBalances = append(successBalances, uint64(i+1))
|
||||
wantBalances = append(wantBalances, uint64(i+1))
|
||||
}
|
||||
successState.SetBalances(successBalances)
|
||||
|
||||
@ -152,40 +150,23 @@ func TestSlashValidator(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
successState.SetValidatorAt(slashedInd, &vali)
|
||||
vali.EffectiveBalance = preSlashBalance
|
||||
wantBalances[slashedInd] = preSlashBalance - (preSlashBalance / clparams.MainnetBeaconConfig.MinSlashingPenaltyQuotient)
|
||||
|
||||
// Set up whistleblower & validator balances.
|
||||
wbReward := preSlashBalance / clparams.MainnetBeaconConfig.WhistleBlowerRewardQuotient
|
||||
wantBalances[whistleblowerInd] += wbReward
|
||||
valInd, err := successState.GetBeaconProposerIndex()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get proposer index for test state: %v", err)
|
||||
}
|
||||
wantBalances[valInd] += wbReward / clparams.MainnetBeaconConfig.ProposerRewardQuotient
|
||||
|
||||
failState := getTestState(t)
|
||||
for _, v := range failState.Validators() {
|
||||
v.ExitEpoch = 0
|
||||
}
|
||||
failState.SetBalances(successBalances)
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
state *state.BeaconState
|
||||
wantBalances []uint64
|
||||
wantErr bool
|
||||
description string
|
||||
state *state.BeaconState
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
description: "success",
|
||||
state: successState,
|
||||
wantBalances: wantBalances,
|
||||
wantErr: false,
|
||||
description: "success",
|
||||
state: successState,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
err := tc.state.SlashValidator(uint64(slashedInd), uint64(whistleblowerInd))
|
||||
w := uint64(whistleblowerInd)
|
||||
err := tc.state.SlashValidator(uint64(slashedInd), &w)
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("unexpected success, wantErr is true")
|
||||
@ -196,12 +177,6 @@ func TestSlashValidator(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error, wanted success: %v", err)
|
||||
}
|
||||
// Check balances.
|
||||
for i, bal := range tc.wantBalances {
|
||||
if bal != tc.state.Balances()[i] {
|
||||
t.Errorf("unexpected balance for index: %d, want %d: got %d", i, bal, tc.state.Balances()[i])
|
||||
}
|
||||
}
|
||||
vali, err := tc.state.ValidatorAt(slashedInd)
|
||||
require.NoError(t, err)
|
||||
// Check that the validator is slashed.
|
||||
|
@ -96,14 +96,13 @@ func (b *BeaconState) SetValidators(validators []*cltypes.Validator) error {
|
||||
}
|
||||
|
||||
func (b *BeaconState) AddValidator(validator *cltypes.Validator, balance uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
b.validators = append(b.validators, validator)
|
||||
b.balances = append(b.balances, balance)
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
b.touchedLeaves[BalancesLeafIndex] = true
|
||||
b.publicKeyIndicies[validator.PublicKey] = uint64(len(b.validators)) - 1
|
||||
// change in validator set means cache purging
|
||||
b.activeValidatorsCache.Purge()
|
||||
b.totalActiveBalanceCache = nil
|
||||
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetBalances(balances []uint64) {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
)
|
||||
@ -17,9 +18,10 @@ func (s *StateTransistor) processBlock(signedBlock *cltypes.SignedBeaconBlock) e
|
||||
if err := s.ProcessBlockHeader(block); err != nil {
|
||||
return fmt.Errorf("ProcessBlockHeader: %s", err)
|
||||
}
|
||||
if s.state.Version() >= clparams.BellatrixVersion {
|
||||
// Set execution header accordingly to state.
|
||||
s.state.SetLatestExecutionPayloadHeader(block.Body.ExecutionPayload.Header)
|
||||
if s.state.Version() >= clparams.BellatrixVersion && s.executionEnabled(block.Body.ExecutionPayload) {
|
||||
if err := s.ProcessExecutionPayload(block.Body.ExecutionPayload); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.ProcessRandao(block.Body.RandaoReveal, block.ProposerIndex); err != nil {
|
||||
return fmt.Errorf("ProcessRandao: %s", err)
|
||||
@ -82,3 +84,24 @@ func (s *StateTransistor) maximumDeposits() (maxDeposits uint64) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ProcessExecutionPayload sets the latest payload header accordinly.
|
||||
func (s *StateTransistor) ProcessExecutionPayload(payload *cltypes.Eth1Block) error {
|
||||
if s.state.IsMergeTransitionComplete() {
|
||||
if payload.Header.ParentHash != s.state.LatestExecutionPayloadHeader().BlockHashCL {
|
||||
return fmt.Errorf("ProcessExecutionPayload: invalid eth1 chain. mismatching parent")
|
||||
}
|
||||
}
|
||||
if payload.Header.MixDigest != s.state.GetRandaoMixes(s.state.Epoch()) {
|
||||
return fmt.Errorf("ProcessExecutionPayload: randao mix mismatches with mix digest")
|
||||
}
|
||||
if payload.Header.Time != s.state.ComputeTimestampAtSlot(s.state.Slot()) {
|
||||
return fmt.Errorf("ProcessExecutionPayload: invalid Eth1 timestamp")
|
||||
}
|
||||
s.state.SetLatestExecutionPayloadHeader(payload.Header)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StateTransistor) executionEnabled(payload *cltypes.Eth1Block) bool {
|
||||
return (!s.state.IsMergeTransitionComplete() && payload.Header.Root != libcommon.Hash{}) || s.state.IsMergeTransitionComplete()
|
||||
}
|
||||
|
@ -9,44 +9,14 @@ import (
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
"github.com/ledgerwatch/erigon/cl/fork"
|
||||
"github.com/ledgerwatch/erigon/cl/utils"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
|
||||
)
|
||||
|
||||
func IsSlashableValidator(validator *cltypes.Validator, epoch uint64) bool {
|
||||
return !validator.Slashed && (validator.ActivationEpoch <= epoch) && (epoch < validator.WithdrawableEpoch)
|
||||
func (s *StateTransistor) isSlashableAttestationData(d1, d2 *cltypes.AttestationData) bool {
|
||||
return (!d1.Equal(d2) && d1.Target.Epoch == d2.Target.Epoch) ||
|
||||
(d1.Source.Epoch < d2.Source.Epoch && d2.Target.Epoch < d1.Target.Epoch)
|
||||
}
|
||||
|
||||
func IsSlashableAttestationData(d1, d2 *cltypes.AttestationData) (bool, error) {
|
||||
hash1, err := d1.HashSSZ()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to hash attestation data 1: %v", err)
|
||||
}
|
||||
|
||||
hash2, err := d2.HashSSZ()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to hash attestation data 2: %v", err)
|
||||
}
|
||||
|
||||
return (hash1 != hash2 && d1.Target.Epoch == d2.Target.Epoch) || (d1.Source.Epoch < d2.Source.Epoch && d2.Target.Epoch < d1.Target.Epoch), nil
|
||||
}
|
||||
|
||||
func GetSetIntersection(v1, v2 []uint64) []uint64 {
|
||||
intersection := []uint64{}
|
||||
present := map[uint64]bool{}
|
||||
|
||||
for _, v := range v1 {
|
||||
present[v] = true
|
||||
}
|
||||
|
||||
for _, v := range v2 {
|
||||
if present[v] {
|
||||
intersection = append(intersection, v)
|
||||
}
|
||||
}
|
||||
return intersection
|
||||
}
|
||||
|
||||
func isValidIndexedAttestation(state *state.BeaconState, att *cltypes.IndexedAttestation) (bool, error) {
|
||||
func (s *StateTransistor) isValidIndexedAttestation(att *cltypes.IndexedAttestation) (bool, error) {
|
||||
inds := att.AttestingIndices
|
||||
if len(inds) == 0 || !utils.IsSliceSortedSet(inds) {
|
||||
return false, fmt.Errorf("isValidIndexedAttestation: attesting indices are not sorted or are null")
|
||||
@ -54,14 +24,14 @@ func isValidIndexedAttestation(state *state.BeaconState, att *cltypes.IndexedAtt
|
||||
|
||||
pks := [][]byte{}
|
||||
for _, v := range inds {
|
||||
val, err := state.ValidatorAt(int(v))
|
||||
val, err := s.state.ValidatorAt(int(v))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
pks = append(pks, val.PublicKey[:])
|
||||
}
|
||||
|
||||
domain, err := state.GetDomain(clparams.MainnetBeaconConfig.DomainBeaconAttester, att.Data.Target.Epoch)
|
||||
domain, err := s.state.GetDomain(clparams.MainnetBeaconConfig.DomainBeaconAttester, att.Data.Target.Epoch)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to get the domain: %v", err)
|
||||
}
|
||||
@ -109,7 +79,7 @@ func (s *StateTransistor) ProcessProposerSlashing(propSlashing *cltypes.Proposer
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !IsSlashableValidator(&proposer, s.state.Epoch()) {
|
||||
if !proposer.IsSlashable(s.state.Epoch()) {
|
||||
return fmt.Errorf("proposer is not slashable: %v", proposer)
|
||||
}
|
||||
|
||||
@ -132,7 +102,7 @@ func (s *StateTransistor) ProcessProposerSlashing(propSlashing *cltypes.Proposer
|
||||
}
|
||||
|
||||
// Set whistleblower index to 0 so current proposer gets reward.
|
||||
s.state.SlashValidator(h1.ProposerIndex, 0)
|
||||
s.state.SlashValidator(h1.ProposerIndex, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -140,15 +110,11 @@ func (s *StateTransistor) ProcessAttesterSlashing(attSlashing *cltypes.AttesterS
|
||||
att1 := attSlashing.Attestation_1
|
||||
att2 := attSlashing.Attestation_2
|
||||
|
||||
slashable, err := IsSlashableAttestationData(att1.Data, att2.Data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to determine if attestation data was slashable: %v", err)
|
||||
}
|
||||
if !slashable {
|
||||
if !s.isSlashableAttestationData(att1.Data, att2.Data) {
|
||||
return fmt.Errorf("attestation data not slashable: %+v; %+v", att1.Data, att2.Data)
|
||||
}
|
||||
|
||||
valid, err := isValidIndexedAttestation(s.state, att1)
|
||||
valid, err := s.isValidIndexedAttestation(att1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error calculating indexed attestation 1 validity: %v", err)
|
||||
}
|
||||
@ -156,7 +122,7 @@ func (s *StateTransistor) ProcessAttesterSlashing(attSlashing *cltypes.AttesterS
|
||||
return fmt.Errorf("invalid indexed attestation 1")
|
||||
}
|
||||
|
||||
valid, err = isValidIndexedAttestation(s.state, att2)
|
||||
valid, err = s.isValidIndexedAttestation(att2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error calculating indexed attestation 2 validity: %v", err)
|
||||
}
|
||||
@ -165,14 +131,14 @@ func (s *StateTransistor) ProcessAttesterSlashing(attSlashing *cltypes.AttesterS
|
||||
}
|
||||
|
||||
slashedAny := false
|
||||
indices := GetSetIntersection(att1.AttestingIndices, att2.AttestingIndices)
|
||||
for _, ind := range indices {
|
||||
currentValidator, err := s.state.ValidatorAt(int(ind))
|
||||
currentEpoch := s.state.GetEpochAtSlot(s.state.Slot())
|
||||
for _, ind := range utils.IntersectionOfSortedSets(att1.AttestingIndices, att2.AttestingIndices) {
|
||||
validator, err := s.state.ValidatorAt(int(ind))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if IsSlashableValidator(¤tValidator, s.state.GetEpochAtSlot(s.state.Slot())) {
|
||||
err := s.state.SlashValidator(ind, 0)
|
||||
if validator.IsSlashable(currentEpoch) {
|
||||
err := s.state.SlashValidator(ind, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to slash validator: %d", ind)
|
||||
}
|
||||
@ -197,7 +163,7 @@ func (s *StateTransistor) ProcessDeposit(deposit *cltypes.Deposit) error {
|
||||
depositIndex := s.state.Eth1DepositIndex()
|
||||
eth1Data := s.state.Eth1Data()
|
||||
// Validate merkle proof for deposit leaf.
|
||||
if !s.noValidate && utils.IsValidMerkleBranch(
|
||||
if !s.noValidate && !utils.IsValidMerkleBranch(
|
||||
depositLeaf,
|
||||
deposit.Proof,
|
||||
s.beaconConfig.DepositContractTreeDepth+1,
|
||||
@ -229,10 +195,13 @@ func (s *StateTransistor) ProcessDeposit(deposit *cltypes.Deposit) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if valid {
|
||||
// Append validator
|
||||
s.state.AddValidator(s.state.ValidatorFromDeposit(deposit), amount)
|
||||
// Altair only
|
||||
if !valid {
|
||||
return nil
|
||||
}
|
||||
// Append validator
|
||||
s.state.AddValidator(s.state.ValidatorFromDeposit(deposit), amount)
|
||||
// Altair forward
|
||||
if s.state.Version() >= clparams.AltairVersion {
|
||||
s.state.AddCurrentEpochParticipationFlags(cltypes.ParticipationFlags(0))
|
||||
s.state.AddPreviousEpochParticipationFlags(cltypes.ParticipationFlags(0))
|
||||
s.state.AddInactivityScore(0)
|
||||
@ -241,7 +210,6 @@ func (s *StateTransistor) ProcessDeposit(deposit *cltypes.Deposit) error {
|
||||
}
|
||||
// Increase the balance if exists already
|
||||
return s.state.IncreaseBalance(validatorIndex, amount)
|
||||
|
||||
}
|
||||
|
||||
// ProcessVoluntaryExit takes a voluntary exit and applies state transition.
|
||||
|
@ -94,13 +94,13 @@ type verifyAttestationWorkersResult struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func verifyAttestationWorker(state *state.BeaconState, attestation *cltypes.Attestation, attestingIndicies []uint64, resultCh chan verifyAttestationWorkersResult) {
|
||||
func (s *StateTransistor) verifyAttestationWorker(state *state.BeaconState, attestation *cltypes.Attestation, attestingIndicies []uint64, resultCh chan verifyAttestationWorkersResult) {
|
||||
indexedAttestation, err := state.GetIndexedAttestation(attestation, attestingIndicies)
|
||||
if err != nil {
|
||||
resultCh <- verifyAttestationWorkersResult{err: err}
|
||||
return
|
||||
}
|
||||
success, err := isValidIndexedAttestation(state, indexedAttestation)
|
||||
success, err := s.isValidIndexedAttestation(indexedAttestation)
|
||||
resultCh <- verifyAttestationWorkersResult{success: success, err: err}
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ func (s *StateTransistor) verifyAttestations(attestations []*cltypes.Attestation
|
||||
resultCh := make(chan verifyAttestationWorkersResult, len(attestations))
|
||||
|
||||
for i, attestation := range attestations {
|
||||
go verifyAttestationWorker(s.state, attestation, attestingIndicies[i], resultCh)
|
||||
go s.verifyAttestationWorker(s.state, attestation, attestingIndicies[i], resultCh)
|
||||
}
|
||||
for i := 0; i < len(attestations); i++ {
|
||||
result := <-resultCh
|
||||
|
@ -17,7 +17,9 @@ import (
|
||||
|
||||
func (s *StateTransistor) TransitionState(block *cltypes.SignedBeaconBlock) error {
|
||||
currentBlock := block.Block
|
||||
s.processSlots(currentBlock.Slot)
|
||||
if err := s.processSlots(currentBlock.Slot); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write the block root to the cache
|
||||
if !s.noValidate {
|
||||
valid, err := s.verifyBlockSignature(block)
|
||||
|
Loading…
Reference in New Issue
Block a user