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

Add time and block advancement #1017

Merged
merged 13 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
101 changes: 96 additions & 5 deletions tests/e2e/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"log"
"math"
"os/exec"
"strconv"
"strings"
Expand Down Expand Up @@ -72,7 +73,7 @@ type StartChainValidator struct {
stake uint
}

func (tr TestRun) startChain(
func (tr *TestRun) startChain(
action StartChainAction,
verbose bool,
) {
Expand Down Expand Up @@ -171,6 +172,17 @@ func (tr TestRun) startChain(
chain: action.chain,
validator: action.validators[0].id,
}, verbose)

// store the fact that we started the chain
if tr.runningChains == nil {
p-offtermatt marked this conversation as resolved.
Show resolved Hide resolved
tr.runningChains = make(map[chainID]bool)
}
tr.runningChains[action.chain] = true
fmt.Println("Started chain", action.chain)
if tr.timeOffset != 0 {
// advance time for this chain so that it is in sync with the rest of the network
tr.AdvanceTimeForChain(action.chain, tr.timeOffset)
}
}

type submitTextProposalAction struct {
Expand Down Expand Up @@ -486,7 +498,7 @@ type voteGovProposalAction struct {
propNumber uint
}

func (tr TestRun) voteGovProposal(
func (tr *TestRun) voteGovProposal(
action voteGovProposalAction,
verbose bool,
) {
Expand Down Expand Up @@ -518,7 +530,7 @@ func (tr TestRun) voteGovProposal(
}

wg.Wait()
time.Sleep(time.Duration(tr.chainConfigs[action.chain].votingWaitTime) * time.Second)
tr.WaitTime(time.Duration(tr.chainConfigs[action.chain].votingWaitTime) * time.Second)
}

type startConsumerChainAction struct {
Expand All @@ -528,7 +540,7 @@ type startConsumerChainAction struct {
genesisChanges string
}

func (tr TestRun) startConsumerChain(
func (tr *TestRun) startConsumerChain(
action startConsumerChainAction,
verbose bool,
) {
Expand Down Expand Up @@ -1035,7 +1047,7 @@ func (tr TestRun) transferChannelComplete(
executeCommand(chanOpenConfirmCmd, "transferChanOpenConfirm")
}

func executeCommand(cmd *exec.Cmd, cmdName string) {
func executeCommandWithVerbosity(cmd *exec.Cmd, cmdName string, verbose *bool) {
p-offtermatt marked this conversation as resolved.
Show resolved Hide resolved
if verbose != nil && *verbose {
fmt.Println(cmdName+" cmd:", cmd.String())
}
Expand Down Expand Up @@ -1063,6 +1075,10 @@ func executeCommand(cmd *exec.Cmd, cmdName string) {
}
}

func executeCommand(cmd *exec.Cmd, cmdName string) {
p-offtermatt marked this conversation as resolved.
Show resolved Hide resolved
executeCommandWithVerbosity(cmd, cmdName, verbose)
}

type relayPacketsAction struct {
chainA chainID
chainB chainID
Expand Down Expand Up @@ -1100,6 +1116,8 @@ func (tr TestRun) relayPacketsGorelayer(
if err != nil {
log.Fatal(err, "\n", string(bz))
}

tr.waitBlocks(action.chainA, 1, 30*time.Second)
}

func (tr TestRun) relayPacketsHermes(
Expand Down Expand Up @@ -1282,13 +1300,29 @@ func (tr TestRun) redelegateTokens(action redelegateTokensAction, verbose bool)
if err != nil {
log.Fatal(err, "\n", string(bz))
}

tr.waitBlocks(action.chain, 1, 10*time.Second)
}

type downtimeSlashAction struct {
chain chainID
validator validatorID
}

// takes a string representation of the private key like
// `{"address":"DF090A4880B54CD57B2A79E64D9E969BD7514B09","pub_key":{"type":"tendermint/PubKeyEd25519","value":"ujY14AgopV907IYgPAk/5x8c9267S4fQf89nyeCPTes="},"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"TRJgf7lkTjs/sj43pyweEOanyV7H7fhnVivOi0A4yjW6NjXgCCilX3TshiA8CT/nHxz3brtLh9B/z2fJ4I9N6w=="}}`
// and returns the value of the "address" field
func (tr TestRun) getValidatorKeyAddressFromString(keystring string) string {
var key struct {
Address string `json:"address"`
}
err := json.Unmarshal([]byte(keystring), &key)
if err != nil {
log.Fatal(err)
}
return key.Address
}

func (tr TestRun) invokeDowntimeSlash(action downtimeSlashAction, verbose bool) {
// Bring validator down
tr.setValidatorDowntime(action.chain, action.validator, true, verbose)
Expand All @@ -1307,6 +1341,30 @@ func (tr TestRun) setValidatorDowntime(chain chainID, validator validatorID, dow
lastArg = "up"
}

if tr.useCometmock {
// send set_signing_status either to down or up for validator
var validatorAddress string
if chain == chainID("provi") {
validatorAddress = tr.getValidatorKeyAddressFromString(tr.validatorConfigs[validator].privValidatorKey)
} else {
var valAddressString string
if tr.validatorConfigs[validator].useConsumerKey {
valAddressString = tr.validatorConfigs[validator].consumerPrivValidatorKey
} else {
valAddressString = tr.validatorConfigs[validator].privValidatorKey
}
validatorAddress = tr.getValidatorKeyAddressFromString(valAddressString)
}

method := "set_signing_status"
params := fmt.Sprintf(`{"private_key_address":"%s","status":"%s"}`, validatorAddress, lastArg)
address := tr.getQueryNodeRPCAddress(chain)

tr.curlJsonRPCRequest(method, params, address)
tr.waitBlocks(chain, 1, 10*time.Second)
return
}

//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command(
"docker",
Expand Down Expand Up @@ -1580,6 +1638,8 @@ func (tr TestRun) assignConsumerPubKey(action assignConsumerPubKeyAction, verbos

// TODO: @MSalopek refactor this so test config is not changed at runtime
// make the validator use consumer key
// @POfftermatt I am currently using this for downtime slashing with cometmock
// (I need to find the currently used validator key address)Í
valCfg.useConsumerKey = true
tr.validatorConfigs[action.validator] = valCfg
}
Expand Down Expand Up @@ -1644,3 +1704,34 @@ func (tr TestRun) GetPathNameForGorelayer(chainA, chainB chainID) string {

return pathName
}

// WaitTime waits for the given duration.
// The CometMock version of this takes a pointer to the TestRun as it needs to manipulate
// information in the testrun that stores how much each chain has waited, to keep times in sync.
// Be careful that all functions calling WaitTime should therefore also take a pointer to the TestRun.
func (tr *TestRun) WaitTime(duration time.Duration) {
if !tr.useCometmock {
time.Sleep(duration)
} else {
tr.timeOffset += duration
for chain, running := range tr.runningChains {
if !running {
continue
}
tr.AdvanceTimeForChain(chain, duration)
}
}
}

func (tr TestRun) AdvanceTimeForChain(chain chainID, duration time.Duration) {
// cometmock avoids sleeping, and instead advances time for all chains
method := "advance_time"
params := fmt.Sprintf(`{"duration_in_seconds": "%d"}`, int(math.Ceil(duration.Seconds())))

address := tr.getQueryNodeRPCAddress(chain)

tr.curlJsonRPCRequest(method, params, address)

// wait for 1 block of the chain to get a block with the advanced timestamp
tr.waitBlocks(chain, 1, time.Minute)
}
4 changes: 4 additions & 0 deletions tests/e2e/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ type TestRun struct {
useCometmock bool // if false, nodes run CometBFT
useGorelayer bool // if false, Hermes is used as the relayer
gaiaTag string
// chains which are running, i.e. producing blocks, at the moment
runningChains map[chainID]bool
// Used with CometMock. The time by which chains have been advanced. Used to keep chains in sync: when a new chain is started, advance its time by this value to keep chains in sync.
timeOffset time.Duration

name string
}
Expand Down
26 changes: 25 additions & 1 deletion tests/e2e/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ func (tr TestRun) getBlockHeight(chain chainID) uint {
}

func (tr TestRun) waitBlocks(chain chainID, blocks uint, timeout time.Duration) {
p-offtermatt marked this conversation as resolved.
Show resolved Hide resolved
if tr.useCometmock {
// call advance_blocks method on cometmock
// curl -H 'Content-Type: application/json' -H 'Accept:application/json' --data '{"jsonrpc":"2.0","method":"advance_blocks","params":{"num_blocks": "36000000"},"id":1}' 127.0.0.1:22331
tcpAddress := tr.getQueryNodeRPCAddress(chain)
method := "advance_blocks"
params := fmt.Sprintf(`{"num_blocks": "%d"}`, blocks)

tr.curlJsonRPCRequest(method, params, tcpAddress)
return
}
startBlock := tr.getBlockHeight(chain)

start := time.Now()
Expand Down Expand Up @@ -687,11 +697,25 @@ func (tr TestRun) getValidatorHome(chain chainID, validator validatorID) string

// getQueryNode returns query node tcp address on chain.
func (tr TestRun) getQueryNode(chain chainID) string {
return fmt.Sprintf("tcp://%s:26658", tr.getQueryNodeIP(chain))
return fmt.Sprintf("tcp://%s", tr.getQueryNodeRPCAddress(chain))
}

func (tr TestRun) getQueryNodeRPCAddress(chain chainID) string {
return fmt.Sprintf("%s:26658", tr.getQueryNodeIP(chain))
}

// getQueryNodeIP returns query node IP for chain,
// ipSuffix is hardcoded to be 253 on all query nodes.
func (tr TestRun) getQueryNodeIP(chain chainID) string {
return fmt.Sprintf("%s.253", tr.chainConfigs[chain].ipPrefix)
}

func (tr TestRun) curlJsonRPCRequest(method, params, address string) {
cmd_template := `curl -H 'Content-Type: application/json' -H 'Accept:application/json' --data '{"jsonrpc":"2.0","method":"%s","params":%s,"id":1}' %s`

//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command("docker", "exec", tr.containerConfig.instanceName, "bash", "-c", fmt.Sprintf(cmd_template, method, params, address))

verbosity := false
executeCommandWithVerbosity(cmd, "curlJsonRPCRequest", &verbosity)
}
1 change: 1 addition & 0 deletions tests/e2e/steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var shortHappyPathSteps = concatSteps(
stepsDelegate("consu"),
stepsUnbond("consu"),
stepsRedelegateShort("consu"),
stepsDowntime("consu"),
stepsStartRelayer(),
stepsConsumerRemovalPropNotPassing("consu", 2), // submit removal prop but vote no on it - chain should stay
stepsStopChain("consu", 3), // stop chain
Expand Down