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!: completed throttle v2 (provider changes + migration + testing) #1321

Merged
merged 21 commits into from
Oct 6, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Add an entry to the unreleased provider section whenever merging a PR to main that is not targeted at a specific release. These entries will eventually be included in a provider release.

* (feat!) [#1230](https://github.com/cosmos/interchain-security/pull/1230) Throttle with retries provider changes.
* (feature!) [#1280](https://github.com/cosmos/interchain-security/pull/1280) provider proposal for changing reward denoms
* (feature!) [#1244](https://github.com/cosmos/interchain-security/pull/1244) Update the default consumer unbonding period to 2 weeks.
* (deps) [#1259](https://github.com/cosmos/interchain-security/pull/1259) Bump [cosmos-sdk](https://github.com/cosmos/cosmos-sdk) to [v0.47.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.5).
Expand Down
14 changes: 14 additions & 0 deletions proto/interchain_security/ccv/consumer/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ option go_package = "github.com/cosmos/interchain-security/v3/x/ccv/consumer/typ
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "interchain_security/ccv/consumer/v1/consumer.proto";
import "interchain_security/ccv/v1/wire.proto";

service Query {
// ConsumerGenesis queries the genesis state needed to start a consumer chain
Expand All @@ -24,6 +25,11 @@ service Query {
rpc QueryProviderInfo(QueryProviderInfoRequest) returns (QueryProviderInfoResponse) {
option (google.api.http).get = "/interchain_security/ccv/consumer/provider-info";
}

// QueryThrottleState returns on-chain state relevant to throttled consumer packets
rpc QueryThrottleState(QueryThrottleStateRequest) returns (QueryThrottleStateResponse) {
option (google.api.http).get = "/interchain_security/ccv/consumer/throttle_state";
}
}

// NextFeeDistributionEstimate holds information about next fee distribution
Expand Down Expand Up @@ -65,6 +71,14 @@ message QueryProviderInfoResponse {
ChainInfo provider = 2 [ (gogoproto.nullable) = false ];
}

message QueryThrottleStateRequest {}

message QueryThrottleStateResponse {
SlashRecord slash_record = 1 [ (gogoproto.nullable) = true ];
repeated interchain_security.ccv.v1.ConsumerPacketData packet_data_queue = 2 [ (gogoproto.nullable) = false ];
}


message ChainInfo {
string chainID = 1;
string clientID = 2;
Expand Down
8 changes: 4 additions & 4 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,11 @@
}

// Params defines the parameters for CCV Provider module
message Params {

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present field "8" with name "max_throttled_packets" on message "Params" was deleted.

// Reserve 8th slot for removed max throttled packet param
reserved 8;

ibc.lightclients.tendermint.v1.ClientState template_client = 1;
// TrustingPeriodFraction is used to compute the consumer and provider IBC
// client's TrustingPeriod from the chain defined UnbondingPeriod
Expand Down Expand Up @@ -179,10 +183,6 @@
// total voting power that the slash meter can hold.
string slash_meter_replenish_fraction = 7;

// The maximum amount of throttled slash or vsc matured packets
// that can be queued for a single consumer before the provider chain halts.
int64 max_throttled_packets = 8;

// The fee required to be paid to add a reward denom
cosmos.base.v1beta1.Coin consumer_reward_denom_registration_fee = 9
[ (gogoproto.nullable) = false ];
Expand Down
37 changes: 0 additions & 37 deletions proto/interchain_security/ccv/provider/v1/query.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/query.proto

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "QueryThrottledConsumerPacketDataRequest" was deleted from file.

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "QueryThrottledConsumerPacketDataResponse" was deleted from file.

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "ThrottledPacketDataWrapper" was deleted from file.

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present message "ThrottledSlashPacket" was deleted from file.
package interchain_security.ccv.provider.v1;

option go_package = "github.com/cosmos/interchain-security/v3/x/ccv/provider/types";
Expand All @@ -10,7 +10,7 @@
import "interchain_security/ccv/v1/shared_consumer.proto";
import "interchain_security/ccv/v1/wire.proto";

service Query {

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present RPC "QueryThrottledConsumerPacketData" on service "Query" was deleted.
// ConsumerGenesis queries the genesis state needed to start a consumer chain
// whose proposal has been accepted
rpc QueryConsumerGenesis(QueryConsumerGenesisRequest)
Expand Down Expand Up @@ -65,14 +65,6 @@
"/interchain_security/ccv/provider/throttle_state";
}

// QueryThrottledConsumerPacketData returns a list of pending packet data
// instances (slash packet and vsc matured) for a single consumer chain
rpc QueryThrottledConsumerPacketData(QueryThrottledConsumerPacketDataRequest)
returns (QueryThrottledConsumerPacketDataResponse) {
option (google.api.http).get =
"/interchain_security/ccv/provider/pending_consumer_packets";
}

// QueryRegisteredConsumerRewardDenoms returns a list of consumer reward
// denoms that are registered
rpc QueryRegisteredConsumerRewardDenoms(
Expand Down Expand Up @@ -141,7 +133,7 @@

message QueryThrottleStateRequest {}

message QueryThrottleStateResponse {

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

View workflow job for this annotation

GitHub Actions / break-check

Previously present field "4" with name "packets" on message "QueryThrottleStateResponse" was deleted.
// current slash_meter state
int64 slash_meter = 1;
// allowance of voting power units (int) that the slash meter is given per
Expand All @@ -151,35 +143,6 @@
// full
google.protobuf.Timestamp next_replenish_candidate = 3
[ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ];
// data relevant to currently throttled slash packets
repeated ThrottledSlashPacket packets = 4;
}

message QueryThrottledConsumerPacketDataRequest { string chain_id = 1; }

message QueryThrottledConsumerPacketDataResponse {
string chain_id = 1;
uint64 size = 2;
repeated ThrottledPacketDataWrapper packetDataInstances = 3
[ (gogoproto.nullable) = false ];
}

// A query wrapper type for the global entry and data relevant to a throttled
// slash packet.
message ThrottledSlashPacket {
interchain_security.ccv.provider.v1.GlobalSlashEntry global_entry = 1
[ (gogoproto.nullable) = false ];
interchain_security.ccv.v1.SlashPacketData data = 2
[ (gogoproto.nullable) = false ];
}

// ThrottledPacketDataWrapper contains either SlashPacketData or
// VSCMaturedPacketData
message ThrottledPacketDataWrapper {
oneof data {
interchain_security.ccv.v1.SlashPacketData slash_packet = 1;
interchain_security.ccv.v1.VSCMaturedPacketData vsc_matured_packet = 2;
}
}

message QueryRegisteredConsumerRewardDenomsRequest {}
Expand Down
4 changes: 4 additions & 0 deletions proto/interchain_security/ccv/v1/shared_consumer.proto
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ message ConsumerParams {
// Provider-originated reward denoms. These are denoms coming from the
// provider which are allowed to be used as rewards. e.g. "uatom"
repeated string provider_reward_denoms = 12;

// The period after which a consumer can retry sending a throttled packet.
google.protobuf.Duration retry_delay_period = 13
[ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ];
}

// ConsumerGenesisState defines the CCV consumer chain genesis state.
Expand Down
1 change: 1 addition & 0 deletions tests/difference/core/driver/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ func (b *Builder) createConsumerGenesis(client *ibctmtypes.ClientState) *ccv.Con
"0", // disable soft opt-out
[]string{},
[]string{},
ccv.DefaultRetryDelayPeriod,
)
return ccv.NewInitialConsumerGenesisState(client, providerConsState, valUpdates, params)
}
Expand Down
23 changes: 15 additions & 8 deletions tests/e2e/action_rapid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ func GetActionGen() *rapid.Generator[any] {
GetRegisterRepresentativeActionGen().AsAny(),
GetDoublesignSlashActionGen().AsAny(),
GetAssignConsumerPubKeyActionGen().AsAny(),
GetSlashThrottleDequeueActionGen().AsAny(),
GetCreateIbcClientsActionGen().AsAny(),
GetSlashMeterReplenishmentAction().AsAny(),
GetWaitTimeAction().AsAny(),
CreateCancelUnbondTokensActionGen().AsAny(),
CreateLightClientEquivocationAttackActionGen().AsAny(),
CreateLightClientAmnesiaAttackActionGen().AsAny(),
Expand Down Expand Up @@ -489,13 +490,19 @@ func GetAssignConsumerPubKeyActionGen() *rapid.Generator[assignConsumerPubKeyAct
})
}

func GetSlashThrottleDequeueActionGen() *rapid.Generator[slashThrottleDequeueAction] {
return rapid.Custom(func(t *rapid.T) slashThrottleDequeueAction {
return slashThrottleDequeueAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
CurrentQueueSize: rapid.Int().Draw(t, "CurrentQueueSize"),
NextQueueSize: rapid.Int().Draw(t, "NextQueueSize"),
Timeout: time.Duration(rapid.Int().Draw(t, "Timeout")) * time.Millisecond,
func GetSlashMeterReplenishmentAction() *rapid.Generator[slashMeterReplenishmentAction] {
return rapid.Custom(func(t *rapid.T) slashMeterReplenishmentAction {
return slashMeterReplenishmentAction{
TargetValue: rapid.Int64().Draw(t, "TargetValue"),
Timeout: time.Duration(rapid.Int().Draw(t, "Timeout")) * time.Millisecond,
}
})
}

func GetWaitTimeAction() *rapid.Generator[waitTimeAction] {
return rapid.Custom(func(t *rapid.T) waitTimeAction {
return waitTimeAction{
WaitTime: time.Duration(rapid.Int().Draw(t, "Timeout")) * time.Millisecond,
}
})
}
48 changes: 25 additions & 23 deletions tests/e2e/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2045,50 +2045,52 @@ func (tr TestConfig) assignConsumerPubKey(action assignConsumerPubKeyAction, ver
tr.waitBlocks(ChainID("provi"), 2, 30*time.Second)
}

// slashThrottleDequeueAction polls slash queue sizes until nextQueueSize is achieved
type slashThrottleDequeueAction struct {
Chain ChainID
CurrentQueueSize int
NextQueueSize int
// panic if Timeout is exceeded
// slashMeterReplenishmentAction polls the slash meter on provider until value is achieved
type slashMeterReplenishmentAction struct {
TargetValue int64
// panic if timeout is exceeded
Timeout time.Duration
}

func (tr TestConfig) waitForSlashThrottleDequeue(
action slashThrottleDequeueAction,
func (tr TestConfig) waitForSlashMeterReplenishment(
action slashMeterReplenishmentAction,
verbose bool,
) {
timeout := time.Now().Add(action.Timeout)
initialGlobalQueueSize := int(tr.getGlobalSlashQueueSize())
initialSlashMeter := tr.getSlashMeter()

if initialGlobalQueueSize != action.CurrentQueueSize {
panic(fmt.Sprintf("wrong initial queue size: %d - expected global queue: %d\n", initialGlobalQueueSize, action.CurrentQueueSize))
if initialSlashMeter >= 0 {
panic(fmt.Sprintf("No need to wait for slash meter replenishment, current value: %d", initialSlashMeter))
}

for {
globalQueueSize := int(tr.getGlobalSlashQueueSize())
chainQueueSize := int(tr.getConsumerChainPacketQueueSize(action.Chain))
slashMeter := tr.getSlashMeter()
if verbose {
fmt.Printf("waiting for packed queue size to reach: %d - current: %d\n", action.NextQueueSize, globalQueueSize)
fmt.Printf("waiting for slash meter to be replenished, current value: %d\n", slashMeter)
}

// check if global queue size is equal to chain queue size
if globalQueueSize == chainQueueSize && globalQueueSize == action.NextQueueSize { //nolint:gocritic // this is the comparison that we want here.
// check if meter has reached target value
if slashMeter >= action.TargetValue {
break
}

if time.Now().After(timeout) {
panic(fmt.Sprintf("\n\n\nwaitForSlashThrottleDequeue method has timed out after: %s\n\n", action.Timeout))
panic(fmt.Sprintf("\n\nwaitForSlashMeterReplenishment has timed out after: %s\n\n", action.Timeout))
}

time.Sleep(500 * time.Millisecond)
tr.WaitTime(5 * time.Second)
}
// wair for 2 blocks to be created
// allowing the jailing to be incorporated into voting power
tr.waitBlocks(action.Chain, 2, time.Minute)
}

func uintPointer(i uint) *uint {
return &i
type waitTimeAction struct {
WaitTime time.Duration
}

func (tr TestConfig) waitForTime(
action waitTimeAction,
verbose bool,
) {
tr.WaitTime(action.WaitTime)
}

// GetPathNameForGorelayer returns the name of the path between two given chains used by Gorelayer.
Expand Down
3 changes: 2 additions & 1 deletion tests/e2e/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ func SlashThrottleTestConfig() TestConfig {
".app_state.slashing.params.signed_blocks_window = \"15\" | " +
".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " +
".app_state.slashing.params.downtime_jail_duration = \"60s\" | " +
".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"",
".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\" | " +
".app_state.ccvconsumer.params.retry_delay_period = \"30s\"",
},
},
tendermintConfigOverride: `s/timeout_commit = "5s"/timeout_commit = "1s"/;` +
Expand Down
10 changes: 8 additions & 2 deletions tests/e2e/json_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,14 @@ func UnmarshalMapToActionType(rawAction json.RawMessage, actionTypeString string
if err == nil {
return a, nil
}
case "main.slashThrottleDequeueAction":
var a slashThrottleDequeueAction
case "main.slashMeterReplenishmentAction":
var a slashMeterReplenishmentAction
err := json.Unmarshal(rawAction, &a)
if err == nil {
return a, nil
}
case "main.waitTimeAction":
var a waitTimeAction
err := json.Unmarshal(rawAction, &a)
if err == nil {
return a, nil
Expand Down
6 changes: 4 additions & 2 deletions tests/e2e/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,10 @@ func (tr *TestConfig) runStep(step Step, verbose bool) {
tr.registerRepresentative(action, verbose)
case assignConsumerPubKeyAction:
tr.assignConsumerPubKey(action, verbose)
case slashThrottleDequeueAction:
tr.waitForSlashThrottleDequeue(action, verbose)
case slashMeterReplenishmentAction:
tr.waitForSlashMeterReplenishment(action, verbose)
case waitTimeAction:
tr.waitForTime(action, verbose)
case startRelayerAction:
tr.startRelayer(action, verbose)
case submitChangeRewardDenomsProposalAction:
Expand Down
Loading
Loading