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!: compute partial sets #1702

Merged
merged 15 commits into from
Mar 25, 2024
13 changes: 0 additions & 13 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
syntax = "proto3";

Check failure on line 1 in proto/interchain_security/ccv/provider/v1/provider.proto

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "OptedInValidator" was deleted from file.

package interchain_security.ccv.provider.v1;

Expand Down Expand Up @@ -326,16 +326,3 @@
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"
];
}

// OptedInValidator is used to store a opted-in validator
// to a consumer chain with the following mapping: (chainID, providerAddr) -> optedInValidator
message OptedInValidator {
// validator address
bytes provider_addr = 1;
// block height at which the validator opted-in
int64 block_height = 2;
// validator voting power at the block it opted-in
int64 power = 3;
// public key used by the validator on the consumer
bytes public_key = 4;
}
1 change: 1 addition & 0 deletions tests/e2e/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ func (tr TestConfig) submitConsumerAdditionProposal(
UnbondingPeriod: params.UnbondingPeriod,
Deposit: fmt.Sprint(action.Deposit) + `stake`,
DistributionTransmissionChannel: action.DistributionChannel,
TopN: 100,
}

bz, err := json.Marshal(prop)
Expand Down
3 changes: 2 additions & 1 deletion tests/mbt/driver/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC
stakingValidators = append(stakingValidators, v)
}

nextValidators := s.providerKeeper().ComputeNextEpochConsumerValSet(s.providerCtx(), string(consumerChainId), stakingValidators)
considerAll := func(validator stakingtypes.Validator) bool { return true }
nextValidators := s.providerKeeper().ComputeNextEpochConsumerValSet(s.providerCtx(), string(consumerChainId), stakingValidators, considerAll)
s.providerKeeper().SetConsumerValSet(s.providerCtx(), string(consumerChainId), nextValidators)

err = s.providerKeeper().SetConsumerGenesis(
Expand Down
29 changes: 0 additions & 29 deletions testutil/keeper/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 0 additions & 56 deletions x/ccv/provider/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package keeper
import (
"fmt"

"cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkgov "github.com/cosmos/cosmos-sdk/x/gov/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
Expand Down Expand Up @@ -177,61 +175,7 @@ func (h Hooks) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64
func (h Hooks) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) {
}

// AfterProposalVote opts in validators that vote YES (with 100% weight) on a `ConsumerAdditionProposal`. If a
// validator votes multiple times, only the last vote would be considered on whether the validator is opted in or not.
func (h Hooks) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
validator, found := h.k.stakingKeeper.GetValidator(ctx, voterAddr.Bytes())
if !found {
return
}

consAddr, err := validator.GetConsAddr()
if err != nil {
h.k.Logger(ctx).Error("could not extract validator's consensus address",
"error", err.Error(),
"validator acc addr", voterAddr,
)
return
}

chainID, found := h.k.GetProposedConsumerChain(ctx, proposalID)
if !found {
return
}

vote, found := h.k.govKeeper.GetVote(ctx, proposalID, voterAddr)
if !found {
h.k.Logger(ctx).Error("could not find vote for validator",
"validator acc addr", voterAddr,
"proposalID", proposalID,
)
return
}

if len(vote.Options) == 1 && vote.Options[0].Option == v1.VoteOption_VOTE_OPTION_YES {
// only consider votes that vote YES with 100% weight
weight, err := sdk.NewDecFromStr(vote.Options[0].Weight)
if err != nil {
h.k.Logger(ctx).Error("could not extract decimal value from vote's weight",
"vote", vote,
"error", err.Error(),
)
return
}
if !weight.Equal(math.LegacyNewDec(1)) {
h.k.Logger(ctx).Error("single vote does not have a weight of 1",
"vote", vote,
)
return
}

// in the validator is already to-be-opted in, the `SetToBeOptedIn` is a no-op
h.k.SetToBeOptedIn(ctx, chainID, providertypes.NewProviderConsAddress(consAddr))
} else {
// if vote is not a YES vote with 100% weight, we delete the validator from to-be-opted in
// if the validator is not to-be-opted in, the `DeleteToBeOptedIn` is a no-op
h.k.DeleteToBeOptedIn(ctx, chainID, providertypes.NewProviderConsAddress(consAddr))
}
}

func (h Hooks) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) {
Expand Down
89 changes: 0 additions & 89 deletions x/ccv/provider/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ import (

"cosmossdk.io/math"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

cryptotestutil "github.com/cosmos/interchain-security/v4/testutil/crypto"
testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper"
providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
"github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
)

func TestValidatorConsensusKeyInUse(t *testing.T) {
Expand Down Expand Up @@ -229,87 +224,3 @@ func TestGetConsumerAdditionLegacyPropFromProp(t *testing.T) {
})
}
}

func TestAfterProposalVoteWithYesVote(t *testing.T) {
k, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{1}).PubKey()
pkAny, _ := codectypes.NewAnyWithValue(providerConsPubKey)
providerAddr := types.NewProviderConsAddress(providerConsPubKey.Address().Bytes())

options := []*v1.WeightedVoteOption{{Option: v1.OptionYes, Weight: "1"}}
k.SetProposedConsumerChain(ctx, "chainID", 1)

gomock.InOrder(
mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, gomock.Any()).Return(
stakingtypes.Validator{ConsensusPubkey: pkAny}, true),
mocks.MockGovKeeper.EXPECT().GetVote(ctx, gomock.Any(), gomock.Any()).Return(
v1.Vote{ProposalId: 1, Voter: "voter", Options: options}, true,
),
)

require.False(t, k.IsToBeOptedIn(ctx, "chainID", providerAddr))
k.Hooks().AfterProposalVote(ctx, 1, sdk.AccAddress{})
require.True(t, k.IsToBeOptedIn(ctx, "chainID", providerAddr))
}

func TestAfterProposalVoteWithNoVote(t *testing.T) {
testCases := []struct {
name string
options []*v1.WeightedVoteOption
setup func(sdk.Context, []*v1.WeightedVoteOption, testkeeper.MockedKeepers, *codectypes.Any)
}{
{
"Weighted vote with 100% NO",
[]*v1.WeightedVoteOption{{Option: v1.OptionNo, Weight: "1"}},
func(ctx sdk.Context, options []*v1.WeightedVoteOption,
mocks testkeeper.MockedKeepers, pubKey *codectypes.Any,
) {
gomock.InOrder(
mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, gomock.Any()).Return(
stakingtypes.Validator{ConsensusPubkey: pubKey}, true),
mocks.MockGovKeeper.EXPECT().GetVote(ctx, gomock.Any(), gomock.Any()).Return(
v1.Vote{ProposalId: 1, Voter: "voter", Options: options}, true,
),
)
},
},
{
"Weighted vote with 99.9% YES and 0.1% NO",
[]*v1.WeightedVoteOption{{Option: v1.OptionYes, Weight: "0.999"}, {Option: v1.OptionNo, Weight: "0.001"}},
func(ctx sdk.Context, options []*v1.WeightedVoteOption,
mocks testkeeper.MockedKeepers, pubKey *codectypes.Any,
) {
gomock.InOrder(
mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, gomock.Any()).Return(
stakingtypes.Validator{ConsensusPubkey: pubKey}, true),
mocks.MockGovKeeper.EXPECT().GetVote(ctx, gomock.Any(), gomock.Any()).Return(
v1.Vote{ProposalId: 1, Voter: "voter", Options: options}, true,
),
)
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
k, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{1}).PubKey()
pkAny, _ := codectypes.NewAnyWithValue(providerConsPubKey)
providerAddr := types.NewProviderConsAddress(providerConsPubKey.Address().Bytes())

k.SetProposedConsumerChain(ctx, "chainID", 1)

tc.setup(ctx, tc.options, mocks, pkAny)

// set the validator to-be-opted in first to assert that a NO vote removes the validator from to-be-opted in
k.SetToBeOptedIn(ctx, "chainID", providerAddr)
require.True(t, k.IsToBeOptedIn(ctx, "chainID", providerAddr))
k.Hooks().AfterProposalVote(ctx, 1, sdk.AccAddress{})
require.False(t, k.IsToBeOptedIn(ctx, "chainID", providerAddr))
})
}
}
Loading
Loading