Skip to content

Commit

Permalink
refactor: update the E2E tests to work with Hermes relayer v1.6.0 (#1278
Browse files Browse the repository at this point in the history
)

* save changes

* fix hermes config

* fist successful run

* nit

* nits

* nits

* doc and nits

* lint
  • Loading branch information
sainoe authored Sep 8, 2023
1 parent eb6a079 commit 98af9c0
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 18 deletions.
24 changes: 23 additions & 1 deletion tests/e2e/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ rpc_addr = "%s"
rpc_timeout = "10s"
store_prefix = "ibc"
trusting_period = "14days"
websocket_addr = "%s"
event_source = { mode = "push", url = "%s", batch_delay = "50ms" }
ccv_consumer_chain = %v
[chains.gas_price]
Expand Down Expand Up @@ -1844,3 +1844,25 @@ func (tr TestRun) GetPathNameForGorelayer(chainA, chainB chainID) string {

return pathName
}

// Run an instance of the Hermes relayer using the "evidence" command,
// which detects evidences committed to the blocks of a consumer chain.
// Each infraction detected is reported to the provider chain using
// either a SubmitConsumerDoubleVoting or a SubmitConsumerMisbehaviour message.
type detectConsumerEvidenceAction struct {
chain chainID
}

func (tr TestRun) detectConsumerEvidence(
action detectConsumerEvidenceAction,
verbose bool,
) {
chainConfig := tr.chainConfigs[action.chain]
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
bz, err := exec.Command("docker", "exec", "-d", tr.containerConfig.instanceName,
"hermes", "evidence", "--chain", string(chainConfig.chainId)).CombinedOutput()
if err != nil {
log.Fatal(err, "\n", string(bz))
}
tr.waitBlocks("provi", 10, 2*time.Minute)
}
7 changes: 6 additions & 1 deletion tests/e2e/actions_consumer_misbehaviour.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os/exec"
"strconv"
"time"
)

Expand Down Expand Up @@ -61,6 +62,7 @@ func (tr TestRun) forkConsumerChain(action forkConsumerChainAction, verbose bool
}

type updateLightClientAction struct {
chain chainID
hostChain chainID
relayerConfig string
clientID string
Expand All @@ -70,14 +72,17 @@ func (tr TestRun) updateLightClient(
action updateLightClientAction,
verbose bool,
) {
// hermes clear packets ibc0 transfer channel-13
// retrieve a trusted height of the consumer light client
trustedHeight := tr.getTrustedHeight(action.hostChain, action.clientID, 2)

//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
cmd := exec.Command("docker", "exec", tr.containerConfig.instanceName, "hermes",
"--config", action.relayerConfig,
"update",
"client",
"--client", action.clientID,
"--host-chain", string(action.hostChain),
"--trusted-height", strconv.Itoa(int(trustedHeight.RevisionHeight)),
)
if verbose {
log.Println("updateLightClientAction cmd:", cmd.String())
Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ func (tr *TestRun) runStep(step Step, verbose bool) {
tr.updateLightClient(action, verbose)
case assertChainIsHaltedAction:
tr.assertChainIsHalted(action, verbose)
case detectConsumerEvidenceAction:
tr.detectConsumerEvidence(action, verbose)
default:
log.Fatalf("unknown action in testRun %s: %#v", tr.name, action)
}
Expand Down
48 changes: 48 additions & 0 deletions tests/e2e/state.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bufio"
"fmt"
"log"
"os/exec"
Expand Down Expand Up @@ -776,3 +777,50 @@ func (tr TestRun) getClientFrozenHeight(chain chainID, clientID string) clientty

return clienttypes.Height{RevisionHeight: uint64(revHeight), RevisionNumber: uint64(revNumber)}
}

func (tr TestRun) getTrustedHeight(
chain chainID,
clientID string,
index int,
) clienttypes.Height {
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
configureNodeCmd := exec.Command("docker", "exec", tr.containerConfig.instanceName, "hermes",
"--json", "query", "client", "consensus", "--chain", string(chain),
`--client`, clientID,
)

cmdReader, err := configureNodeCmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}

configureNodeCmd.Stderr = configureNodeCmd.Stdout

if err := configureNodeCmd.Start(); err != nil {
log.Fatal(err)
}

scanner := bufio.NewScanner(cmdReader)

var trustedHeight gjson.Result
// iterate on the relayer's response
// and parse the the command "result"
for scanner.Scan() {
out := scanner.Text()
if len(gjson.Get(out, "result").Array()) > 0 {
trustedHeight = gjson.Get(out, "result").Array()[index]
break
}
}

revHeight, err := strconv.Atoi(trustedHeight.Get("revision_height").String())
if err != nil {
log.Fatal(err)
}

revNumber, err := strconv.Atoi(trustedHeight.Get("revision_number").String())
if err != nil {
log.Fatal(err)
}
return clienttypes.Height{RevisionHeight: uint64(revHeight), RevisionNumber: uint64(revNumber)}
}
50 changes: 36 additions & 14 deletions tests/e2e/steps_consumer_misbehaviour.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,43 +213,65 @@ func stepsCauseConsumerMisbehaviour(consumerName string) []Step {
},
state: State{},
},
// start relayer to detect IBC misbehaviour
{
// start relayer to detect ICS misbehaviour
action: startRelayerAction{},
state: State{},
},
// detect the ICS misbehaviour
// and jail alice on the provider
{
action: detectConsumerEvidenceAction{
chain: chainID(consumerName),
},
state: State{
chainID("provi"): ChainState{
ValPowers: &map[validatorID]uint{
validatorID("alice"): 511,
validatorID("bob"): 20,
},
},
chainID(consumerName): ChainState{
ValPowers: &map[validatorID]uint{
validatorID("alice"): 511,
validatorID("bob"): 20,
},
},
},
},
{
// update the fork consumer client to create a light client attack
// which should trigger a ICS misbehaviour message
action: updateLightClientAction{
chain: chainID(consumerName),
clientID: consumerClientID,
hostChain: chainID("provi"),
relayerConfig: forkRelayerConfig, // this relayer config uses the "forked" consumer
clientID: consumerClientID,
},
state: State{
chainID("provi"): ChainState{
// validator should be jailed on the provider
// alice should be jailed on the provider
ValPowers: &map[validatorID]uint{
validatorID("alice"): 0,
validatorID("bob"): 20,
},
// The consumer light client should not be frozen
// The consumer light client should be frozen on the provider
ClientsFrozenHeights: &map[string]clienttypes.Height{
"07-tendermint-0": {
consumerClientID: {
RevisionNumber: 0,
RevisionHeight: 0,
RevisionHeight: 1,
},
},
},
chainID(consumerName): ChainState{
// consumer should not have learned the jailing of alice
// since its light client is frozen on the provider
ValPowers: &map[validatorID]uint{
validatorID("alice"): 511,
validatorID("bob"): 20,
},
},
},
},
// we expect the consumer chain to be halted since the last VSC packet should
// have updated the alice validator power to 0.
{
action: assertChainIsHaltedAction{
chain: chainID("consu"),
},
state: State{},
},
}
}
6 changes: 4 additions & 2 deletions tests/e2e/testnet-scripts/fork-consumer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ rpc_addr = "http://$CONS_CHAIN_PREFIX.252:26658"
rpc_timeout = "10s"
store_prefix = "ibc"
trusting_period = "2days"
websocket_addr = "ws://$CONS_CHAIN_PREFIX.252:26658/websocket"
event_source = { mode = 'push', url = 'ws://$CONS_CHAIN_PREFIX.252:26658/websocket' , batch_delay = '50ms' }
[chains.gas_price]
denom = "stake"
Expand All @@ -85,7 +85,9 @@ rpc_addr = "http://$PROV_CHAIN_PREFIX.4:26658"
rpc_timeout = "10s"
store_prefix = "ibc"
trusting_period = "2days"
websocket_addr = "ws://$PROV_CHAIN_PREFIX.4:26658/websocket"
event_source = { mode = 'push', url = 'ws://$PROV_CHAIN_PREFIX.4:26658/websocket' , batch_delay = '50ms' }
[chains.gas_price]
denom = "stake"
Expand Down

0 comments on commit 98af9c0

Please sign in to comment.