From e15459006367f87e0ac2ee8356cd19578ea2e9e8 Mon Sep 17 00:00:00 2001 From: Shane Bammel Date: Tue, 13 Dec 2022 15:58:32 -0600 Subject: [PATCH] Gracefully handle balance overflow --- beacon-chain/core/helpers/rewards_penalties.go | 9 ++++++++- beacon-chain/core/helpers/rewards_penalties_test.go | 7 +++++-- .../transition/altair_transition_no_verify_sig_test.go | 8 ++++++-- .../bellatrix_transition_no_verify_sig_test.go | 8 ++++++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/beacon-chain/core/helpers/rewards_penalties.go b/beacon-chain/core/helpers/rewards_penalties.go index b567bfa70..28e06d3c8 100644 --- a/beacon-chain/core/helpers/rewards_penalties.go +++ b/beacon-chain/core/helpers/rewards_penalties.go @@ -2,6 +2,7 @@ package helpers import ( "errors" + "math" "math/big" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" @@ -10,6 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" mathutil "github.com/prysmaticlabs/prysm/v5/math" "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/sirupsen/logrus" ) var balanceCache = cache.NewEffectiveBalanceCache() @@ -128,7 +130,12 @@ func IncreaseBalance(state state.BeaconState, idx primitives.ValidatorIndex, del // """ // state.balances[index] += delta func IncreaseBalanceWithVal(currBalance, delta uint64) (uint64, error) { - return mathutil.Add64(currBalance, delta) + res, err := mathutil.Add64(currBalance, delta) + if err != nil { + logrus.Warn("validator balance overflow detected") + res = math.MaxUint64 + } + return res, nil } // DecreaseBalance decreases validator with the given 'index' balance by 'delta' in Gwei. diff --git a/beacon-chain/core/helpers/rewards_penalties_test.go b/beacon-chain/core/helpers/rewards_penalties_test.go index bc1ce2bd3..32192297b 100644 --- a/beacon-chain/core/helpers/rewards_penalties_test.go +++ b/beacon-chain/core/helpers/rewards_penalties_test.go @@ -275,7 +275,7 @@ func buildState(slot primitives.Slot, validatorCount uint64) *ethpb.BeaconState } } -func TestIncreaseBadBalance_NotOK(t *testing.T) { +func TestIncreaseBalance_OverflowCapped(t *testing.T) { tests := []struct { i primitives.ValidatorIndex b []uint64 @@ -293,6 +293,9 @@ func TestIncreaseBadBalance_NotOK(t *testing.T) { Balances: test.b, }) require.NoError(t, err) - require.ErrorContains(t, "addition overflows", IncreaseBalance(state, test.i, test.nb)) + require.NoError(t, IncreaseBalance(state, test.i, test.nb)) + for _, bal := range state.Balances() { + require.Equal(t, bal, uint64(math.MaxUint64)) + } } } diff --git a/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go b/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go index b49a6c62f..5af6b9f26 100644 --- a/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/altair_transition_no_verify_sig_test.go @@ -226,8 +226,12 @@ func TestProcessEpoch_BadBalanceAltair(t *testing.T) { epochParticipation[0] = participation assert.NoError(t, s.SetCurrentParticipationBits(epochParticipation)) assert.NoError(t, s.SetPreviousParticipationBits(epochParticipation)) - _, err = altair.ProcessEpoch(context.Background(), s) - assert.ErrorContains(t, "addition overflows", err) + s, err = altair.ProcessEpoch(context.Background(), s) + assert.NoError(t, err) + // verify overflow prevented + bal, err := s.BalanceAtIndex(0) + assert.NoError(t, err) + assert.Equal(t, uint64(math.MaxUint64), bal) } func createFullAltairBlockWithOperations(t *testing.T) (state.BeaconState, diff --git a/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go b/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go index 68cde2f90..ae4d9eec0 100644 --- a/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/bellatrix_transition_no_verify_sig_test.go @@ -216,8 +216,12 @@ func TestProcessEpoch_BadBalanceBellatrix(t *testing.T) { epochParticipation[0] = participation assert.NoError(t, s.SetCurrentParticipationBits(epochParticipation)) assert.NoError(t, s.SetPreviousParticipationBits(epochParticipation)) - _, err = altair.ProcessEpoch(context.Background(), s) - assert.ErrorContains(t, "addition overflows", err) + s, err = altair.ProcessEpoch(context.Background(), s) + assert.NoError(t, err) + // verify overflow prevented + bal, err := s.BalanceAtIndex(0) + assert.NoError(t, err) + assert.Equal(t, uint64(math.MaxUint64), bal) } func createFullBellatrixBlockWithOperations(t *testing.T) (state.BeaconState,