Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(blobstream): utilizes sdk.Dec type for power difference calculation (backport #2719) #2735

Merged
merged 4 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions x/qgb/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ import (
)

const (
// SignificantPowerDifferenceThreshold is the threshold of change in the
// validator set power that would trigger the creation of a new valset
// request.
SignificantPowerDifferenceThreshold = 0.05

oneDay = 24 * time.Hour
oneWeek = 7 * oneDay
// AttestationExpiryTime is the expiration time of an attestation. When this
Expand All @@ -25,6 +20,11 @@ const (
AttestationExpiryTime = 3 * oneWeek // 3 weeks
)

// SignificantPowerDifferenceThreshold is the threshold of change in the
// validator set power that would trigger the creation of a new valset
// request.
var SignificantPowerDifferenceThreshold = sdk.NewDecWithPrec(5, 2) // 0.05

// EndBlocker is called at the end of every block.
func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
// we always want to create the valset at first so that if there is a new
Expand Down Expand Up @@ -117,7 +117,8 @@ func handleValsetRequest(ctx sdk.Context, k keeper.Keeper) {
panic(sdkerrors.Wrap(err, "invalid latest valset members"))
}

significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers) > SignificantPowerDifferenceThreshold
significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers).GT(SignificantPowerDifferenceThreshold)

}

if (latestValset == nil) || (latestUnbondingHeight == uint64(ctx.BlockHeight())) || significantPowerDiff {
Expand Down
14 changes: 9 additions & 5 deletions x/qgb/types/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
mrand "math/rand"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/celestiaorg/celestia-app/x/qgb/types"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
Expand All @@ -14,7 +16,7 @@ func TestValsetPowerDiff(t *testing.T) {
specs := map[string]struct {
start types.BridgeValidators
diff types.BridgeValidators
exp float64
exp sdk.Dec
}{
"no diff": {
start: types.BridgeValidators{
Expand All @@ -27,7 +29,7 @@ func TestValsetPowerDiff(t *testing.T) {
{Power: 2, EvmAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"},
{Power: 3, EvmAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"},
},
exp: 0.0,
exp: sdk.NewDecWithPrec(0, 1), // 0.0
},
"one": {
start: types.BridgeValidators{
Expand All @@ -40,7 +42,7 @@ func TestValsetPowerDiff(t *testing.T) {
{Power: 858993459, EvmAddress: "0x8E91960d704Df3fF24ECAb78AB9df1B5D9144140"},
{Power: 2576980377, EvmAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"},
},
exp: 0.2,
exp: sdk.NewDecWithPrec(2, 1), // 0.2
},
"real world": {
start: types.BridgeValidators{
Expand All @@ -63,14 +65,16 @@ func TestValsetPowerDiff(t *testing.T) {
{Power: 291759231, EvmAddress: "0xF14879a175A2F1cEFC7c616f35b6d9c2b0Fd8326"},
{Power: 6785098, EvmAddress: "0x37A0603dA2ff6377E5C7f75698dabA8EE4Ba97B8"},
},
exp: 0.010000000011641532,
exp: sdk.NewDecWithPrec(10000000011641532, 18), // 0.010000000011641532
},
}

for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
startInternal, _ := spec.start.ToInternal()
diffInternal, _ := spec.diff.ToInternal()
assert.Equal(t, spec.exp, startInternal.PowerDiff(*diffInternal))
obtained := startInternal.PowerDiff(*diffInternal)
assert.True(t, spec.exp.Equal(obtained))
})
}
}
Expand Down
28 changes: 18 additions & 10 deletions x/qgb/types/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package types

import (
"bytes"
math "math"
"math"
"math/big"
"sort"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/ethereum/go-ethereum/common"

"cosmossdk.io/errors"
Expand Down Expand Up @@ -32,7 +35,7 @@ func (b BridgeValidators) ToInternal() (*InternalBridgeValidators, error) {
return &ret, nil
}

// Bridge Validator but with validated EVMAddress.
// InternalBridgeValidator bridges Validator but with validated EVMAddress.
type InternalBridgeValidator struct {
Power uint64
EVMAddress common.Address
Expand Down Expand Up @@ -112,30 +115,35 @@ func EVMAddrLessThan(e common.Address, o common.Address) bool {
// increases by 1% due to inflation, we shouldn't have to generate a new
// validator set, after all the validators retained their relative percentages
// during inflation and normalized QGB power shows no difference.
func (ibv InternalBridgeValidators) PowerDiff(c InternalBridgeValidators) float64 {
powers := map[string]int64{}
func (ibv InternalBridgeValidators) PowerDiff(c InternalBridgeValidators) sdk.Dec {
powers := map[string]sdk.Dec{}
// loop over ibv and initialize the map with their powers
for _, bv := range ibv {
powers[bv.EVMAddress.Hex()] = int64(bv.Power)
powers[bv.EVMAddress.Hex()] = sdk.NewDecFromBigInt(new(big.Int).SetUint64(bv.Power))
}

// subtract c powers from powers in the map, initializing
// uninitialized keys with negative numbers
for _, bv := range c {
bvPower := sdk.NewDecFromBigInt(new(big.Int).SetUint64(bv.Power))
if val, ok := powers[bv.EVMAddress.Hex()]; ok {
powers[bv.EVMAddress.Hex()] = val - int64(bv.Power)
powers[bv.EVMAddress.Hex()] = val.Sub(bvPower)
} else {
powers[bv.EVMAddress.Hex()] = -int64(bv.Power)
powers[bv.EVMAddress.Hex()] = bvPower.Neg() // -int64(bv.Power)
}
}

var delta float64
delta := sdk.NewDec(0)
for _, v := range powers {
// NOTE: we care about the absolute value of the changes
delta += math.Abs(float64(v))
v = v.Abs()
delta = delta.Add(v)
}

return math.Abs(delta / float64(math.MaxUint32))
decMaxUint32 := sdk.NewDec(math.MaxUint32)
q := delta.Quo(decMaxUint32)

return q.Abs()
}

// TotalPower returns the total power in the bridge validator set.
Expand Down
Loading