mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 17:44:29 +00:00
Added process slashings (#6728)
This commit is contained in:
parent
6933b0d169
commit
a0d236df31
@ -91,6 +91,14 @@ func (b *BeaconState) GetTotalActiveBalance() (uint64, error) {
|
|||||||
return b.GetTotalBalance(b.GetActiveValidatorsIndices(b.Epoch()))
|
return b.GetTotalBalance(b.GetActiveValidatorsIndices(b.Epoch()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTotalSlashingAmount return the sum of all slashings.
|
||||||
|
func (b *BeaconState) GetTotalSlashingAmount() (t uint64) {
|
||||||
|
for _, slash := range &b.slashings {
|
||||||
|
t += slash
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockRoot returns blook root at start of a given epoch
|
// GetBlockRoot returns blook root at start of a given epoch
|
||||||
func (b *BeaconState) GetBlockRoot(epoch uint64) (libcommon.Hash, error) {
|
func (b *BeaconState) GetBlockRoot(epoch uint64) (libcommon.Hash, error) {
|
||||||
return b.GetBlockRootAtSlot(epoch * b.beaconConfig.SlotsPerEpoch)
|
return b.GetBlockRootAtSlot(epoch * b.beaconConfig.SlotsPerEpoch)
|
||||||
|
@ -95,6 +95,11 @@ func (b *BeaconState) SetBalances(balances []uint64) {
|
|||||||
b.balances = balances
|
b.balances = balances
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BeaconState) AddBalance(balance uint64) {
|
||||||
|
b.touchedLeaves[BalancesLeafIndex] = true
|
||||||
|
b.balances = append(b.balances, balance)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BeaconState) SetValidatorBalance(index int, balance uint64) {
|
func (b *BeaconState) SetValidatorBalance(index int, balance uint64) {
|
||||||
b.touchedLeaves[BalancesLeafIndex] = true
|
b.touchedLeaves[BalancesLeafIndex] = true
|
||||||
b.balances[index] = balance
|
b.balances[index] = balance
|
||||||
|
@ -32,3 +32,9 @@ func GetEmptyBeaconState() *BeaconState {
|
|||||||
b.initBeaconState()
|
b.initBeaconState()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetEmptyBeaconStateWithVersion(v clparams.StateVersion) *BeaconState {
|
||||||
|
b := GetEmptyBeaconState()
|
||||||
|
b.version = v
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
47
cmd/erigon-cl/core/transition/process_slashings.go
Normal file
47
cmd/erigon-cl/core/transition/process_slashings.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package transition
|
||||||
|
|
||||||
|
import "github.com/ledgerwatch/erigon/cl/clparams"
|
||||||
|
|
||||||
|
func (s *StateTransistor) processSlashings(slashingMultiplier uint64) error {
|
||||||
|
// Get the current epoch
|
||||||
|
epoch := s.state.Epoch()
|
||||||
|
// Get the total active balance
|
||||||
|
totalBalance, err := s.state.GetTotalActiveBalance()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Calculate the total slashing amount
|
||||||
|
// by summing all slashings and multiplying by the provided multiplier
|
||||||
|
slashing := s.state.GetTotalSlashingAmount() * slashingMultiplier
|
||||||
|
// Adjust the total slashing amount to be no greater than the total active balance
|
||||||
|
if totalBalance < slashing {
|
||||||
|
slashing = totalBalance
|
||||||
|
}
|
||||||
|
// Apply penalties to validators who have been slashed and reached the withdrawable epoch
|
||||||
|
for i, validator := range s.state.Validators() {
|
||||||
|
if !validator.Slashed || epoch+s.beaconConfig.EpochsPerSlashingsVector/2 != validator.WithdrawableEpoch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Get the effective balance increment
|
||||||
|
increment := s.beaconConfig.EffectiveBalanceIncrement
|
||||||
|
// Calculate the penalty numerator by multiplying the validator's effective balance by the total slashing amount
|
||||||
|
penaltyNumerator := validator.EffectiveBalance / increment * slashing
|
||||||
|
// Calculate the penalty by dividing the penalty numerator by the total balance and multiplying by the increment
|
||||||
|
penalty := penaltyNumerator / totalBalance * increment
|
||||||
|
// Decrease the validator's balance by the calculated penalty
|
||||||
|
s.state.DecreaseBalance(uint64(i), penalty)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StateTransistor) ProcessSlashings() error {
|
||||||
|
// Depending on the version of the state, use different multipliers
|
||||||
|
switch s.state.Version() {
|
||||||
|
case clparams.Phase0Version:
|
||||||
|
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplier)
|
||||||
|
case clparams.AltairVersion:
|
||||||
|
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplierAltair)
|
||||||
|
default:
|
||||||
|
return s.processSlashings(s.beaconConfig.ProportionalSlashingMultiplierBellatrix)
|
||||||
|
}
|
||||||
|
}
|
97
cmd/erigon-cl/core/transition/process_slashings_test.go
Normal file
97
cmd/erigon-cl/core/transition/process_slashings_test.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package transition_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||||
|
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||||
|
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
|
||||||
|
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/transition"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProcessSlashingsNoSlash(t *testing.T) {
|
||||||
|
base := state.GetEmptyBeaconStateWithVersion(clparams.AltairVersion)
|
||||||
|
base.AddValidator(&cltypes.Validator{
|
||||||
|
Slashed: true,
|
||||||
|
})
|
||||||
|
base.AddBalance(clparams.MainnetBeaconConfig.MaxEffectiveBalance)
|
||||||
|
base.SetSlashingSegmentAt(0, 0)
|
||||||
|
base.SetSlashingSegmentAt(1, 1e9)
|
||||||
|
s := transition.New(base, &clparams.MainnetBeaconConfig, nil)
|
||||||
|
require.NoError(t, s.ProcessSlashings())
|
||||||
|
wanted := clparams.MainnetBeaconConfig.MaxEffectiveBalance
|
||||||
|
require.Equal(t, wanted, base.Balances()[0], "Unexpected slashed balance")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestStateSlashings1() *state.BeaconState {
|
||||||
|
state := state.GetEmptyBeaconStateWithVersion(clparams.AltairVersion)
|
||||||
|
state.AddValidator(&cltypes.Validator{Slashed: true,
|
||||||
|
WithdrawableEpoch: clparams.MainnetBeaconConfig.EpochsPerSlashingsVector / 2,
|
||||||
|
EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance})
|
||||||
|
state.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance})
|
||||||
|
state.SetBalances([]uint64{clparams.MainnetBeaconConfig.MaxEffectiveBalance, clparams.MainnetBeaconConfig.MaxEffectiveBalance})
|
||||||
|
state.SetSlashingSegmentAt(0, 0)
|
||||||
|
state.SetSlashingSegmentAt(1, 1e9)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestStateSlashings2() *state.BeaconState {
|
||||||
|
state := getTestStateSlashings1()
|
||||||
|
state.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance})
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestStateSlashings3() *state.BeaconState {
|
||||||
|
state := getTestStateSlashings2()
|
||||||
|
state.SetSlashingSegmentAt(1, 2*1e9)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestStateSlashings4() *state.BeaconState {
|
||||||
|
state := getTestStateSlashings1()
|
||||||
|
state.SetValidatorAt(1, &cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement})
|
||||||
|
state.SetBalances([]uint64{clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement, clparams.MainnetBeaconConfig.MaxEffectiveBalance - clparams.MainnetBeaconConfig.EffectiveBalanceIncrement})
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessSlashingsSlash(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
state *state.BeaconState
|
||||||
|
want uint64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
state: getTestStateSlashings1(),
|
||||||
|
want: uint64(30000000000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: getTestStateSlashings2(),
|
||||||
|
want: uint64(31000000000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: getTestStateSlashings3(),
|
||||||
|
want: uint64(30000000000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: getTestStateSlashings4(),
|
||||||
|
want: uint64(29000000000),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||||
|
transitistor := transition.New(tt.state, &clparams.MainnetBeaconConfig, nil)
|
||||||
|
require.NoError(t, transitistor.ProcessSlashings())
|
||||||
|
assert.Equal(t, tt.want, tt.state.Balances()[0])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user