Skip to content

Commit

Permalink
Validator downtime integration tests (#313)
Browse files Browse the repository at this point in the history
  • Loading branch information
shaspitz authored Sep 2, 2022
1 parent 5a02cd3 commit 8e36fdb
Show file tree
Hide file tree
Showing 9 changed files with 411 additions and 79 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/cosmos/interchain-security
go 1.18

require (
github.com/cosmos/cosmos-sdk v0.45.2-0.20220811130336-846d0158765e
github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808
github.com/cosmos/ibc-go v1.2.2
github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220210141024-fb2f0416254b
github.com/gogo/protobuf v1.3.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ github.com/cosmos/cosmos-sdk v0.44.3/go.mod h1:bA3+VenaR/l/vDiYzaiwbWvRPWHMBX2jG
github.com/cosmos/cosmos-sdk v0.45.0/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ=
github.com/cosmos/cosmos-sdk v0.45.2-0.20220811130336-846d0158765e h1:aKKTrqI9mNCQpLkul4S6BHdWYrdNrFNhiHfy2Oh2yhM=
github.com/cosmos/cosmos-sdk v0.45.2-0.20220811130336-846d0158765e/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ=
github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808 h1:PW5p0/qt5iJZS7f4bDjo/OYhMhzlmCewh8PZrpBluxo=
github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
Expand Down
131 changes: 106 additions & 25 deletions integration-tests/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,13 @@ func (tr TestRun) startChain(
log.Fatal(err)
}

tr.addChainToRelayer(AddChainToRelayerAction{
tr.addChainToRelayer(addChainToRelayerAction{
chain: action.chain,
validator: action.validators[0].id,
}, verbose)
}

type SubmitTextProposalAction struct {
type submitTextProposalAction struct {
chain chainID
from validatorID
deposit uint
Expand All @@ -156,7 +156,7 @@ type SubmitTextProposalAction struct {
}

func (tr TestRun) submitTextProposal(
action SubmitTextProposalAction,
action submitTextProposalAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand All @@ -182,7 +182,7 @@ func (tr TestRun) submitTextProposal(
}
}

type SubmitConsumerProposalAction struct {
type submitConsumerProposalAction struct {
chain chainID
from validatorID
deposit uint
Expand All @@ -192,7 +192,7 @@ type SubmitConsumerProposalAction struct {
}

// TODO: import this directly from the module once it is merged
type CreateConsumerChainProposalJSON struct {
type createConsumerChainProposalJSON struct {
Title string `json:"title"`
Description string `json:"description"`
ChainId string `json:"chain_id"`
Expand All @@ -204,11 +204,11 @@ type CreateConsumerChainProposalJSON struct {
}

func (tr TestRun) submitConsumerProposal(
action SubmitConsumerProposalAction,
action submitConsumerProposalAction,
verbose bool,
) {
spawnTime := tr.containerConfig.now.Add(time.Duration(action.spawnTime) * time.Millisecond)
prop := CreateConsumerChainProposalJSON{
prop := createConsumerChainProposalJSON{
Title: "Create a chain",
Description: "Gonna be a great chain",
ChainId: string(tr.chainConfigs[action.consumerChain].chainId),
Expand Down Expand Up @@ -257,15 +257,15 @@ func (tr TestRun) submitConsumerProposal(
}
}

type VoteGovProposalAction struct {
type voteGovProposalAction struct {
chain chainID
from []validatorID
vote []string
propNumber uint
}

func (tr TestRun) voteGovProposal(
action VoteGovProposalAction,
action voteGovProposalAction,
verbose bool,
) {
var wg sync.WaitGroup
Expand Down Expand Up @@ -299,14 +299,14 @@ func (tr TestRun) voteGovProposal(
time.Sleep(time.Duration(tr.chainConfigs[action.chain].votingWaitTime) * time.Second)
}

type StartConsumerChainAction struct {
type startConsumerChainAction struct {
consumerChain chainID
providerChain chainID
validators []StartChainValidator
}

func (tr TestRun) startConsumerChain(
action StartConsumerChainAction,
action startConsumerChainAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand Down Expand Up @@ -337,7 +337,7 @@ func (tr TestRun) startConsumerChain(
}, verbose)
}

type AddChainToRelayerAction struct {
type addChainToRelayerAction struct {
chain chainID
validator validatorID
}
Expand Down Expand Up @@ -368,7 +368,7 @@ websocket_addr = "%s"
`

func (tr TestRun) addChainToRelayer(
action AddChainToRelayerAction,
action addChainToRelayerAction,
verbose bool,
) {
valIp := tr.getValidatorIP(action.chain, action.validator)
Expand Down Expand Up @@ -418,7 +418,7 @@ func (tr TestRun) addChainToRelayer(
}
}

type AddIbcConnectionAction struct {
type addIbcConnectionAction struct {
chainA chainID
chainB chainID
clientA uint
Expand All @@ -427,7 +427,7 @@ type AddIbcConnectionAction struct {
}

func (tr TestRun) addIbcConnection(
action AddIbcConnectionAction,
action addIbcConnectionAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand Down Expand Up @@ -464,7 +464,7 @@ func (tr TestRun) addIbcConnection(
}
}

type AddIbcChannelAction struct {
type addIbcChannelAction struct {
chainA chainID
chainB chainID
connectionA uint
Expand All @@ -474,7 +474,7 @@ type AddIbcChannelAction struct {
}

func (tr TestRun) addIbcChannel(
action AddIbcChannelAction,
action addIbcChannelAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand Down Expand Up @@ -518,14 +518,14 @@ func (tr TestRun) addIbcChannel(
}
}

type RelayPacketsAction struct {
type relayPacketsAction struct {
chain chainID
port string
channel uint
}

func (tr TestRun) relayPackets(
action RelayPacketsAction,
action relayPacketsAction,
verbose bool,
) {
// hermes clear packets ibc0 transfer channel-13
Expand All @@ -545,15 +545,15 @@ func (tr TestRun) relayPackets(
}
}

type DelegateTokensAction struct {
type delegateTokensAction struct {
chain chainID
from validatorID
to validatorID
amount uint
}

func (tr TestRun) delegateTokens(
action DelegateTokensAction,
action delegateTokensAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand Down Expand Up @@ -581,15 +581,15 @@ func (tr TestRun) delegateTokens(
}
}

type UnbondTokensAction struct {
type unbondTokensAction struct {
chain chainID
sender validatorID
unbondFrom validatorID
amount uint
}

func (tr TestRun) unbondTokens(
action UnbondTokensAction,
action unbondTokensAction,
verbose bool,
) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
Expand Down Expand Up @@ -617,15 +617,15 @@ func (tr TestRun) unbondTokens(
}
}

type RedelegateTokensAction struct {
type redelegateTokensAction struct {
chain chainID
src validatorID
dst validatorID
txSender validatorID
amount uint
}

func (tr TestRun) redelegateTokens(action RedelegateTokensAction, verbose bool) {
func (tr TestRun) redelegateTokens(action redelegateTokensAction, verbose bool) {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command("docker", "exec",
tr.containerConfig.instanceName,
Expand Down Expand Up @@ -655,3 +655,84 @@ func (tr TestRun) redelegateTokens(action RedelegateTokensAction, verbose bool)
log.Fatal(err, "\n", string(bz))
}
}

type downtimeSlashAction struct {
chain chainID
validator validatorID
}

func (tr TestRun) invokeDowntimeSlash(action downtimeSlashAction, verbose bool) {
// Bring validator down
tr.setValidatorDowntime(action.chain, action.validator, true, verbose)
// Wait appropriate amount of blocks for validator to be slashed
tr.waitBlocks(action.chain, 3, time.Minute)
// Bring validator back up
tr.setValidatorDowntime(action.chain, action.validator, false, verbose)
}

// Sets validator downtime by setting the virtual ethernet interface of a node to "up" or "down"
func (tr TestRun) setValidatorDowntime(chain chainID, validator validatorID, down bool, verbose bool) {

var lastArg string
if down {
lastArg = "down"
} else {
lastArg = "up"
}

//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command(
"docker",
"exec",
tr.containerConfig.instanceName,
"ip",
"link",
"set",
string(chain)+"-"+string(validator)+"-out",
lastArg,
)

if verbose {
fmt.Println("toggle downtime cmd:", cmd.String())
}

bz, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err, "\n", string(bz))
}
}

type unjailValidatorAction struct {
provider chainID
validator validatorID
}

// Sends an unjail transaction to the provider chain
func (tr TestRun) unjailValidator(action unjailValidatorAction, verbose bool) {

// Wait just past the downtime_jail_duration set in config.go
time.Sleep(3 * time.Second)

//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command("docker", "exec",
tr.containerConfig.instanceName,
tr.chainConfigs[action.provider].binaryName,
"tx", "slashing", "unjail",
// Validator is sender here
`--from`, `validator`+fmt.Sprint(action.validator),
`--chain-id`, string(tr.chainConfigs[action.provider].chainId),
`--home`, tr.getValidatorHome(action.provider, action.validator),
`--node`, tr.getValidatorNode(action.provider, action.validator),
`--keyring-backend`, `test`,
`-b`, `block`,
`-y`,
)
if verbose {
fmt.Println("unjail cmd:", cmd.String())
}

bz, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err, "\n", string(bz))
}
}
22 changes: 16 additions & 6 deletions integration-tests/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,24 @@ func DefaultTestRun() TestRun {
binaryName: "interchain-security-pd",
ipPrefix: "7.7.7",
votingWaitTime: 5,
genesisChanges: ".app_state.gov.voting_params.voting_period = \"5s\"",
genesisChanges: ".app_state.gov.voting_params.voting_period = \"5s\" | " +
// Custom slashing parameters for testing validator downtime functionality
// See https://docs.cosmos.network/main/modules/slashing/04_begin_block.html#uptime-tracking
".app_state.slashing.params.signed_blocks_window = \"2\" | " +
".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " +
".app_state.slashing.params.downtime_jail_duration = \"2s\" | " +
".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"",
},
chainID("consu"): {
chainId: chainID("consu"),
binaryName: "interchain-security-cd",
ipPrefix: "7.7.8",
votingWaitTime: 10,
genesisChanges: ".app_state.gov.voting_params.voting_period = \"10s\"",
genesisChanges: ".app_state.gov.voting_params.voting_period = \"10s\" | " +
".app_state.slashing.params.signed_blocks_window = \"2\" | " +
".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " +
".app_state.slashing.params.downtime_jail_duration = \"2s\" | " +
".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"",
},
},
}
Expand All @@ -121,10 +131,10 @@ func (s *TestRun) ParseCLIFlags() {
// ValidateStringLiterals enforces that configs follow the constraints
// necessary to to execute the tests
//
// Note: Network interfaces within the container will be named as
// "$CHAIN_ID-$VAL_ID-out" etc. where this name is constrained to 15 bytes or less.
// Therefore each string literal used as a validatorID or chainID
// needs to be 5 char or less.
// Note: Network interfaces (name of virtual ethernet interfaces for ip link)
// within the container will be named as "$CHAIN_ID-$VAL_ID-out" etc.
// where this name is constrained to 15 bytes or less. Therefore each string literal
// used as a validatorID or chainID needs to be 5 char or less.
func (s *TestRun) ValidateStringLiterals() {
for valID, valConfig := range s.validatorConfigs {

Expand Down
Loading

0 comments on commit 8e36fdb

Please sign in to comment.