diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index b7207d72c8..9a0ff5d647 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2393,7 +2393,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool } // Use: "opt-out [consumer-chain-id]", - optIn := fmt.Sprintf( + optOut := fmt.Sprintf( `%s tx provider opt-out %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, string(tr.testConfig.chainConfigs[action.Chain].ChainId), @@ -2406,7 +2406,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool cmd := target.ExecCommand( "/bin/bash", "-c", - optIn, + optOut, ) if verbose { @@ -2432,6 +2432,71 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool tr.waitBlocks(ChainID("provi"), 2, 30*time.Second) } +type SetConsumerCommissionRateAction struct { + Chain ChainID + Validator ValidatorID + CommissionRate float64 + + // depending on the execution, this action might throw an error (e.g., when no consumer chain exists) + ExpectError bool + ExpectedError string +} + +func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction, target ExecutionTarget, verbose bool) { + // Note: to get error response reported back from this command '--gas auto' needs to be set. + gas := "auto" + // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then + if tr.testConfig.useCometmock { + gas = "9000000" + } + + // Use: "set-consumer-commission-rate [consumer-chain-id] [commission-rate]" + setCommissionRate := fmt.Sprintf( + `%s tx provider set-consumer-commission-rate %s %f --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, + tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, + string(tr.testConfig.chainConfigs[action.Chain].ChainId), + action.CommissionRate, + action.Validator, + tr.testConfig.chainConfigs[ChainID("provi")].ChainId, + tr.getValidatorHome(ChainID("provi"), action.Validator), + tr.getValidatorNode(ChainID("provi"), action.Validator), + gas, + ) + + cmd := target.ExecCommand( + "/bin/bash", "-c", + setCommissionRate, + ) + + if verbose { + fmt.Println("setConsumerCommissionRate cmd:", cmd.String()) + } + + bz, err := cmd.CombinedOutput() + if err != nil && !action.ExpectError { + log.Fatalf("unexpected error during commssion rate set - output: %s, err: %s", string(bz), err) + } + + if action.ExpectError && !tr.testConfig.useCometmock { // error report only works with --gas auto, which does not work with CometMock, so ignore + if err == nil || !strings.Contains(string(bz), action.ExpectedError) { + log.Fatalf("expected error not raised: expected: '%s', got '%s'", action.ExpectedError, (bz)) + } + + if verbose { + fmt.Printf("got expected error during commssion rate set | err: %s | output: %s \n", err, string(bz)) + } + } + + if !tr.testConfig.useCometmock { // error report only works with --gas auto, which does not work with CometMock, so ignore + if err != nil && verbose { + fmt.Printf("got error during commssion rate set | err: %s | output: %s \n", err, string(bz)) + } + } + + // wait for inclusion in a block -> '--broadcast-mode block' is deprecated + tr.waitBlocks(ChainID("provi"), 2, 30*time.Second) +} + // WaitTime waits for the given duration. // To make sure that the new timestamp is visible on-chain, it also waits until at least one block has been // produced on each chain after waiting. diff --git a/tests/e2e/state.go b/tests/e2e/state.go index b9618a3964..f38fde6814 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -116,6 +116,11 @@ func (tr Chain) GetChainState(chain ChainID, modelState ChainState) ChainState { chainState.HasToValidate = &hasToValidate } + if modelState.ConsumerCommissionRates != nil { + consumerCommissionRates := tr.GetConsumerCommissionRates(chain, *modelState.ConsumerCommissionRates) + chainState.ConsumerCommissionRates = &consumerCommissionRates + } + if modelState.ConsumerPendingPacketQueueSize != nil { pendingPacketQueueSize := tr.target.GetPendingPacketQueueSize(chain) chainState.ConsumerPendingPacketQueueSize = &pendingPacketQueueSize @@ -951,3 +956,33 @@ func (tr Commands) GetQueryNodeIP(chain ChainID) string { } return fmt.Sprintf("%s.253", tr.chainConfigs[chain].IpPrefix) } + +// GetConsumerCommissionRate returns the commission rate of the given validator on the given consumerChain +func (tr Commands) GetConsumerCommissionRate(consumerChain ChainID, validator ValidatorID) float64 { + binaryName := tr.chainConfigs[ChainID("provi")].BinaryName + cmd := tr.target.ExecCommand(binaryName, + "query", "provider", "validator-consumer-commission-rate", + string(consumerChain), tr.validatorConfigs[validator].ValconsAddress, + `--node`, tr.GetQueryNode(ChainID("provi")), + `-o`, `json`, + ) + bz, err := cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + rate, err := strconv.ParseFloat(gjson.Get(string(bz), "rate").String(), 64) + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + return rate +} + +func (tr Chain) GetConsumerCommissionRates(chain ChainID, modelState map[ValidatorID]float64) map[ValidatorID]float64 { + actualState := map[ValidatorID]float64{} + for k := range modelState { + actualState[k] = tr.target.GetConsumerCommissionRate(chain, k) + } + + return actualState +} diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 98316f45bb..80eff1aedd 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -29,6 +29,16 @@ func stepsOptInChain() []Step { }, }, }, + { + Action: SetConsumerCommissionRateAction{ + Chain: ChainID("consu"), + Validator: ValidatorID("bob"), + CommissionRate: 0.123, + ExpectError: true, + ExpectedError: "unknown consumer chain", + }, + State: State{}, + }, { Action: SubmitConsumerAdditionProposalAction{ Chain: ChainID("provi"), @@ -89,6 +99,31 @@ func stepsOptInChain() []Step { ValidatorID("carol"): {}, }, }, + ChainID("consu"): ChainState{ + // no consumer commission rates were set and hence we get + // the default (i.e., 0.1) commission rate the validators have on the provider + ConsumerCommissionRates: &map[ValidatorID]float64{ + ValidatorID("alice"): 0.1, + ValidatorID("bob"): 0.1, + ValidatorID("carol"): 0.1, + }, + }, + }, + }, + { + Action: SetConsumerCommissionRateAction{ + Chain: ChainID("consu"), + Validator: ValidatorID("bob"), + CommissionRate: 0.123, + }, + State: State{ + ChainID("consu"): ChainState{ + ConsumerCommissionRates: &map[ValidatorID]float64{ + ValidatorID("alice"): 0.1, + ValidatorID("bob"): 0.123, + ValidatorID("carol"): 0.1, + }, + }, }, }, { diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go index 9c59411ac7..18140a49f6 100644 --- a/tests/e2e/test_driver.go +++ b/tests/e2e/test_driver.go @@ -207,6 +207,8 @@ func (td *DefaultDriver) runAction(action interface{}) error { target.optIn(action, td.target, td.verbose) case OptOutAction: target.optOut(action, td.target, td.verbose) + case SetConsumerCommissionRateAction: + target.setConsumerCommissionRate(action, td.target, td.verbose) default: log.Fatalf("unknown action in testRun %s: %#v", td.testCfg.name, action) } diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index 135f07a6a8..0fe6061f4a 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -37,6 +37,7 @@ type ChainCommands interface { GetValPower(chain ChainID, validator ValidatorID) uint GetValStakedTokens(chain ChainID, validatorAddress string) uint GetQueryNodeIP(chain ChainID) string + GetConsumerCommissionRate(chain ChainID, validator ValidatorID) float64 } // TODO: replace ExecutionTarget with new TargetDriver interface @@ -170,6 +171,7 @@ type ChainState struct { RegisteredConsumerRewardDenoms *[]string ClientsFrozenHeights *map[string]clienttypes.Height HasToValidate *map[ValidatorID][]ChainID // only relevant to provider chain + ConsumerCommissionRates *map[ValidatorID]float64 } // custom marshal and unmarshal functions for the chainstate that convert proposals to/from the auxiliary type with type info diff --git a/tests/e2e/v4/state.go b/tests/e2e/v4/state.go index 70ca8afe7c..9c8a0f2d58 100644 --- a/tests/e2e/v4/state.go +++ b/tests/e2e/v4/state.go @@ -650,7 +650,11 @@ func (tr Commands) GetIBCTransferParams(chain ChainID) IBCTransferParams { } func (tr Commands) GetHasToValidate(validator ValidatorID) []ChainID { - panic("''GetHasToValidate' is not implemented in this version") + panic("'GetHasToValidate' is not implemented in this version") +} + +func (tr Commands) GetConsumerCommissionRate(chain ChainID, validator ValidatorID) float64 { + panic("'GetConsumerCommissionRate' is not implemented in this version") } func uintPtr(i uint) *uint {