From 7be7807766d9414f8d3df011f1b4733046fe1cc2 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Mon, 9 Sep 2024 16:15:21 +0200 Subject: [PATCH 1/9] save --- tests/e2e/actions.go | 49 +++++++++++++++++++++++++++++---- tests/e2e/test_runner.go | 2 +- x/ccv/provider/client/cli/tx.go | 15 ++++++---- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index a47219b5af..0ee74cf532 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -15,6 +15,8 @@ import ( "sync" "time" + evidencetypes "cosmossdk.io/x/evidence/types" + ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" "github.com/tidwall/gjson" @@ -2872,16 +2874,53 @@ type StartConsumerEvidenceDetectorAction struct { func (tr Chain) startConsumerEvidenceDetector( action StartConsumerEvidenceDetectorAction, + useRelayer bool, verbose bool, ) { chainConfig := tr.testConfig.chainConfigs[action.Chain] - // run in detached mode so it will keep running in the background - bz, err := tr.target.ExecDetachedCommand( - "hermes", "evidence", "--chain", string(chainConfig.ChainId)).CombinedOutput() + // the Hermes doesn't support evidence handling for Permissionless ICS yet + // TODO: @Simon refactor once https://github.com/informalsystems/hermes/pull/4182 is merged. + if useRelayer { + // run in detached mode so it will keep running in the background + bz, err := tr.target.ExecDetachedCommand( + "hermes", "evidence", "--chain", string(chainConfig.ChainId)).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + tr.waitBlocks("provi", 10, 2*time.Minute) + } + + // Get the evidence' infraction height by querying the SDK evidence module + // state on the consumer + queryEv := fmt.Sprintf( + `%s q evidence list %s --node %s -o json`, + tr.testConfig.chainConfigs[ChainID("consu")].BinaryName, + tr.target.GetQueryNodeRPCAddress(ChainID("consu")), + ) + + cmd := tr.target.ExecCommand( + "/bin/bash", "-c", + queryEv, + ) + + if verbose { + fmt.Println("queryEv cmd:", cmd.String()) + } + + bz, err := cmd.CombinedOutput() if err != nil { - log.Fatal(err, "\n", string(bz)) + panic(err) + } + + ev := evidencetypes.Equivocation{} + + err = json.Unmarshal(bz, &ev) + if err != nil { + log.Fatalf("unmarshalling tx containing create-consumer: %s, json: %s", err.Error(), string(bz)) } - tr.waitBlocks("provi", 10, 2*time.Minute) + + fmt.Println(ev.String()) + } type OptInAction struct { diff --git a/tests/e2e/test_runner.go b/tests/e2e/test_runner.go index c3ced5ab61..bc2367a12b 100644 --- a/tests/e2e/test_runner.go +++ b/tests/e2e/test_runner.go @@ -94,7 +94,7 @@ func (tr *TestRunner) Run() error { } tr.result.Passed() - err = tr.teardownEnvironment() + // err = tr.teardownEnvironment() fmt.Printf("==========================================\n") return err } diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 2bd46f5cd3..27e43b35ab 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -170,24 +170,27 @@ Example: txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) submitter := clientCtx.GetFromAddress() + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - ev := tmproto.DuplicateVoteEvidence{} - evidenceJson, err := os.ReadFile(args[0]) + evidenceJson, err := os.ReadFile(args[1]) if err != nil { return err } - if err := json.Unmarshal(evidenceJson, &ev); err != nil { + // if err := json.Unmarshal(evidenceJson, &ev); err != nil { + // return fmt.Errorf("duplicate vote evidence unmarshalling failed: %s", err) + // } + + ev := tmproto.DuplicateVoteEvidence{} + if err := cdc.UnmarshalJSON(evidenceJson, &ev); err != nil { return fmt.Errorf("duplicate vote evidence unmarshalling failed: %s", err) } - headerJson, err := os.ReadFile(args[1]) + headerJson, err := os.ReadFile(args[2]) if err != nil { return err } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - header := ibctmtypes.Header{} if err := cdc.UnmarshalJSON(headerJson, &header); err != nil { return fmt.Errorf("infraction IBC header unmarshalling failed: %s", err) From dea81ec44312129c3a9caafd7afae92ac466cccf Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Tue, 10 Sep 2024 15:29:42 +0200 Subject: [PATCH 2/9] save --- tests/e2e/actions.go | 146 ++++++++++++++++++++++++++------- tests/e2e/steps_double_sign.go | 3 +- tests/e2e/test_driver.go | 2 +- x.json | 64 +++++++++++++++ 4 files changed, 185 insertions(+), 30 deletions(-) create mode 100644 x.json diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 0ee74cf532..ae4db0efce 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -15,8 +15,6 @@ import ( "sync" "time" - evidencetypes "cosmossdk.io/x/evidence/types" - ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" "github.com/tidwall/gjson" @@ -2869,7 +2867,8 @@ func (tr Chain) GetPathNameForGorelayer(chainA, chainB ChainID) string { // Each infraction detected is reported to the provider chain using // either a SubmitConsumerDoubleVoting or a SubmitConsumerMisbehaviour message. type StartConsumerEvidenceDetectorAction struct { - Chain ChainID + Chain ChainID + Submitter ValidatorID } func (tr Chain) startConsumerEvidenceDetector( @@ -2888,39 +2887,130 @@ func (tr Chain) startConsumerEvidenceDetector( log.Fatal(err, "\n", string(bz)) } tr.waitBlocks("provi", 10, 2*time.Minute) - } + } else { - // Get the evidence' infraction height by querying the SDK evidence module - // state on the consumer - queryEv := fmt.Sprintf( - `%s q evidence list %s --node %s -o json`, - tr.testConfig.chainConfigs[ChainID("consu")].BinaryName, - tr.target.GetQueryNodeRPCAddress(ChainID("consu")), - ) + consumerBinaryName := tr.testConfig.chainConfigs[action.Chain].BinaryName + + now := time.Now() + timeout := now.Add(30 * time.Second) + var bz []byte + var err error + for { + cmd := tr.target.ExecCommand( + consumerBinaryName, + "query", "evidence", "list", + `--node`, tr.target.GetQueryNode(action.Chain), + `-o`, `json`, + ) - cmd := tr.target.ExecCommand( - "/bin/bash", "-c", - queryEv, - ) + if verbose { + fmt.Println("query evidence cmd:", cmd.String()) + } - if verbose { - fmt.Println("queryEv cmd:", cmd.String()) - } + bz, err = cmd.CombinedOutput() + if err == nil { + break + } - bz, err := cmd.CombinedOutput() - if err != nil { - panic(err) - } + if time.Now().After(timeout) { + log.Print("Failed running command: ", cmd) + log.Fatal(err, "\n", string(bz)) + } + time.Sleep(2 * time.Second) + } - ev := evidencetypes.Equivocation{} + evidence := gjson.Get(string(bz), "evidence") - err = json.Unmarshal(bz, &ev) - if err != nil { - log.Fatalf("unmarshalling tx containing create-consumer: %s, json: %s", err.Error(), string(bz)) - } + if len(evidence.Array()) != 1 { + log.Fatal("no evidence found") + } + + infractionHeight := evidence.Array()[0].Get("value").Get("height").Int() + + cmd := tr.target.ExecCommand( + consumerBinaryName, + "query", "block", "--type=height", strconv.Itoa(int(infractionHeight+1)), + `--node`, tr.target.GetQueryNode(action.Chain), + `-o`, `json`, + ) - fmt.Println(ev.String()) + if verbose { + fmt.Println("query evidence cmd:", cmd.String()) + } + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // persist evidence in the json format + evidenceJson := gjson.Get(string(bz), "evidence.evidence").Array()[0].Get("duplicate_vote_evidence").Raw + evidencePath := "/temp-evidence.json" + bz, err = tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, evidenceJson, evidencePath), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // query IBC header at the infraction height + cmd = tr.target.ExecCommand( + consumerBinaryName, + "query", "ibc", "client", "header", "--height", strconv.Itoa(int(infractionHeight)), + `--node`, tr.target.GetQueryNode(action.Chain), + `-o`, `json`, + ) + + if verbose { + fmt.Println("query IBC header cmd:", cmd.String()) + } + + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + fmt.Println(string(bz)) + + // persist IBC header in json format + headerPath := "/temp-header.json" + bz, err = tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, string(bz), headerPath), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // Submit consumer equivocation + gas := "auto" + submitEquivocation := fmt.Sprintf( + `%s tx provider submit-consumer-double-voting %s %s %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].ConsumerId), + evidencePath, + headerPath, + action.Submitter, + tr.testConfig.chainConfigs[ChainID("provi")].ChainId, + tr.getValidatorHome(ChainID("provi"), action.Submitter), + tr.getValidatorNode(ChainID("provi"), action.Submitter), + gas, + ) + + cmd = tr.target.ExecCommand( + "/bin/bash", "-c", + submitEquivocation, + ) + + if verbose { + fmt.Println("submit consumer equivocation cmd:", cmd.String()) + } + + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + } } type OptInAction struct { diff --git a/tests/e2e/steps_double_sign.go b/tests/e2e/steps_double_sign.go index bdc4a68cb4..328e92d7bf 100644 --- a/tests/e2e/steps_double_sign.go +++ b/tests/e2e/steps_double_sign.go @@ -89,7 +89,8 @@ func stepsCauseDoubleSignOnConsumer(consumerName, providerName string) []Step { // and jail and slashing of bob on the provider { Action: StartConsumerEvidenceDetectorAction{ - Chain: ChainID(consumerName), + Chain: ChainID(consumerName), + Submitter: ValidatorID("bob"), }, State: State{ ChainID(providerName): ChainState{ diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go index 95550daa18..7d7bedd39f 100644 --- a/tests/e2e/test_driver.go +++ b/tests/e2e/test_driver.go @@ -219,7 +219,7 @@ func (td *DefaultDriver) runAction(action interface{}) error { case UpdateLightClientAction: target.updateLightClient(action, td.verbose) case StartConsumerEvidenceDetectorAction: - target.startConsumerEvidenceDetector(action, td.verbose) + target.startConsumerEvidenceDetector(action, false, td.verbose) case SubmitChangeRewardDenomsProposalAction: target = td.getTargetDriver(action.Chain) version := target.testConfig.providerVersion diff --git a/x.json b/x.json new file mode 100644 index 0000000000..c1317c2239 --- /dev/null +++ b/x.json @@ -0,0 +1,64 @@ +{ + "header": { + "version": { + "block": "11", + "app": "0" + }, + "chain_id": "consu", + "height": "82", + "time": "2024-09-10T09:58:36.846480718Z", + "last_block_id": { + "hash": "jBeLoZ9Ewe1zMp1xfHN3omTZEy40wSZ8D2KZ7eR+bHE=", + "part_set_header": { + "total": 1, + "hash": "ZhbDc/5PMZmYXRXwYp54N21NP5AzmPCT72eSHBnns9U=" + } + }, + "last_commit_hash": "EapvsjpYvqefPQjwA13Nm0qk+oao5I43oMfu7NnT+ag=", + "data_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "validators_hash": "D26N3CL1zQt7yn+JUQ8Dcb2vCYG7QmHMiMfY+nGxhts=", + "next_validators_hash": "D26N3CL1zQt7yn+JUQ8Dcb2vCYG7QmHMiMfY+nGxhts=", + "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=", + "app_hash": "yniKouNstqZBLzOesgHaHu06LJmGqCYMZaYL1+p+T+Y=", + "last_results_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", + "proposer_address": "BsDz5HzFx0gmkIjcLzZBHTqqJ8Y=" + }, + "data": { + "txs": [] + }, + "evidence": { + "evidence": [] + }, + "last_commit": { + "height": "81", + "round": 0, + "block_id": { + "hash": "jBeLoZ9Ewe1zMp1xfHN3omTZEy40wSZ8D2KZ7eR+bHE=", + "part_set_header": { + "total": 1, + "hash": "ZhbDc/5PMZmYXRXwYp54N21NP5AzmPCT72eSHBnns9U=" + } + }, + "signatures": [ + { + "block_id_flag": "BLOCK_ID_FLAG_COMMIT", + "validator_address": "BsDz5HzFx0gmkIjcLzZBHTqqJ8Y=", + "timestamp": "2024-09-10T09:58:36.845718260Z", + "signature": "MmI3eHB6SBytSV5oAmpE2fEfTymw/UA6kRYk/VbMe5EV2XnvArasdzqazvZ3cjDghfahBdBVxnJMGLl7Ik6eAg==" + }, + { + "block_id_flag": "BLOCK_ID_FLAG_COMMIT", + "validator_address": "mb06cu8SzQJOdYSzrJAK43Q8at8=", + "timestamp": "2024-09-10T09:58:36.846981926Z", + "signature": "2JzfyybKN7SCC5Qc3UBAjtZvf2FBYqSJ/BdHkZQGptxKJJw6pTkTIsSsMZcx5XxwkD67CSsYbh5Nrq1lYk/SAQ==" + }, + { + "block_id_flag": "BLOCK_ID_FLAG_COMMIT", + "validator_address": "tBw6QBQpY6pbEt3RxOWJDAs5JrE=", + "timestamp": "2024-09-10T09:58:36.846480718Z", + "signature": "dc7rzUBNf5Y6UGu86h2bSwnTfFo+OYgWJVy6qxmn59BURR+FkiT6oVzSI0XLWYRNOrHuumWKC0mFz5sYTn7yBw==" + } + ] + } +} \ No newline at end of file From 2a92ebb2fa2db8fa9e789f3d75a0fddea9382397 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Tue, 10 Sep 2024 17:04:45 +0200 Subject: [PATCH 3/9] rm file --- tests/e2e/actions.go | 42 +++++++++++++---------------- x.json | 64 -------------------------------------------- 2 files changed, 19 insertions(+), 87 deletions(-) delete mode 100644 x.json diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index ae4db0efce..dd3fec6770 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2862,8 +2862,9 @@ func (tr Chain) 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. +// detect evidences committed to the blocks of a consumer chain +// either by running an instance of the Hermes relayer using the "evidence" command, +// or by queyring manually the consumer chain. // Each infraction detected is reported to the provider chain using // either a SubmitConsumerDoubleVoting or a SubmitConsumerMisbehaviour message. type StartConsumerEvidenceDetectorAction struct { @@ -2888,13 +2889,12 @@ func (tr Chain) startConsumerEvidenceDetector( } tr.waitBlocks("provi", 10, 2*time.Minute) } else { - + // detect and the evidence on the consumer chain consumerBinaryName := tr.testConfig.chainConfigs[action.Chain].BinaryName - now := time.Now() - timeout := now.Add(30 * time.Second) - var bz []byte - var err error + // get the infraction height by querying the SDK evidence module of the consumer + timeout := time.Now().Add(30 * time.Second) + infractionHeight := int64(0) for { cmd := tr.target.ExecCommand( consumerBinaryName, @@ -2907,26 +2907,24 @@ func (tr Chain) startConsumerEvidenceDetector( fmt.Println("query evidence cmd:", cmd.String()) } - bz, err = cmd.CombinedOutput() + bz, err := cmd.CombinedOutput() if err == nil { - break + evidence := gjson.Get(string(bz), "evidence") + if len(evidence.Array()) > 0 { + infractionHeight = evidence.Array()[0].Get("value.height").Int() + break + } } - if time.Now().After(timeout) { + if err != nil || time.Now().After(timeout) { log.Print("Failed running command: ", cmd) log.Fatal(err, "\n", string(bz)) } time.Sleep(2 * time.Second) } - evidence := gjson.Get(string(bz), "evidence") - - if len(evidence.Array()) != 1 { - log.Fatal("no evidence found") - } - - infractionHeight := evidence.Array()[0].Get("value").Get("height").Int() - + // get the evidence data from the block + // note that the the evidence is added to the next block after the infraction height cmd := tr.target.ExecCommand( consumerBinaryName, "query", "block", "--type=height", strconv.Itoa(int(infractionHeight+1)), @@ -2935,10 +2933,10 @@ func (tr Chain) startConsumerEvidenceDetector( ) if verbose { - fmt.Println("query evidence cmd:", cmd.String()) + fmt.Println("query block for evidence cmd:", cmd.String()) } - bz, err = cmd.CombinedOutput() + bz, err := cmd.CombinedOutput() if err != nil { log.Fatal(err, "\n", string(bz)) } @@ -2970,8 +2968,6 @@ func (tr Chain) startConsumerEvidenceDetector( log.Fatal(err, "\n", string(bz)) } - fmt.Println(string(bz)) - // persist IBC header in json format headerPath := "/temp-header.json" bz, err = tr.target.ExecCommand( @@ -3002,7 +2998,7 @@ func (tr Chain) startConsumerEvidenceDetector( ) if verbose { - fmt.Println("submit consumer equivocation cmd:", cmd.String()) + fmt.Println("submit consumer equivocation cmd:", cmd.String()) } bz, err = cmd.CombinedOutput() diff --git a/x.json b/x.json deleted file mode 100644 index c1317c2239..0000000000 --- a/x.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "header": { - "version": { - "block": "11", - "app": "0" - }, - "chain_id": "consu", - "height": "82", - "time": "2024-09-10T09:58:36.846480718Z", - "last_block_id": { - "hash": "jBeLoZ9Ewe1zMp1xfHN3omTZEy40wSZ8D2KZ7eR+bHE=", - "part_set_header": { - "total": 1, - "hash": "ZhbDc/5PMZmYXRXwYp54N21NP5AzmPCT72eSHBnns9U=" - } - }, - "last_commit_hash": "EapvsjpYvqefPQjwA13Nm0qk+oao5I43oMfu7NnT+ag=", - "data_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", - "validators_hash": "D26N3CL1zQt7yn+JUQ8Dcb2vCYG7QmHMiMfY+nGxhts=", - "next_validators_hash": "D26N3CL1zQt7yn+JUQ8Dcb2vCYG7QmHMiMfY+nGxhts=", - "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=", - "app_hash": "yniKouNstqZBLzOesgHaHu06LJmGqCYMZaYL1+p+T+Y=", - "last_results_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", - "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", - "proposer_address": "BsDz5HzFx0gmkIjcLzZBHTqqJ8Y=" - }, - "data": { - "txs": [] - }, - "evidence": { - "evidence": [] - }, - "last_commit": { - "height": "81", - "round": 0, - "block_id": { - "hash": "jBeLoZ9Ewe1zMp1xfHN3omTZEy40wSZ8D2KZ7eR+bHE=", - "part_set_header": { - "total": 1, - "hash": "ZhbDc/5PMZmYXRXwYp54N21NP5AzmPCT72eSHBnns9U=" - } - }, - "signatures": [ - { - "block_id_flag": "BLOCK_ID_FLAG_COMMIT", - "validator_address": "BsDz5HzFx0gmkIjcLzZBHTqqJ8Y=", - "timestamp": "2024-09-10T09:58:36.845718260Z", - "signature": "MmI3eHB6SBytSV5oAmpE2fEfTymw/UA6kRYk/VbMe5EV2XnvArasdzqazvZ3cjDghfahBdBVxnJMGLl7Ik6eAg==" - }, - { - "block_id_flag": "BLOCK_ID_FLAG_COMMIT", - "validator_address": "mb06cu8SzQJOdYSzrJAK43Q8at8=", - "timestamp": "2024-09-10T09:58:36.846981926Z", - "signature": "2JzfyybKN7SCC5Qc3UBAjtZvf2FBYqSJ/BdHkZQGptxKJJw6pTkTIsSsMZcx5XxwkD67CSsYbh5Nrq1lYk/SAQ==" - }, - { - "block_id_flag": "BLOCK_ID_FLAG_COMMIT", - "validator_address": "tBw6QBQpY6pbEt3RxOWJDAs5JrE=", - "timestamp": "2024-09-10T09:58:36.846480718Z", - "signature": "dc7rzUBNf5Y6UGu86h2bSwnTfFo+OYgWJVy6qxmn59BURR+FkiT6oVzSI0XLWYRNOrHuumWKC0mFz5sYTn7yBw==" - } - ] - } -} \ No newline at end of file From 085ad725dc049bdf4d8a9fc5582884c88468d477 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Tue, 10 Sep 2024 17:30:03 +0200 Subject: [PATCH 4/9] reformat --- tests/e2e/actions.go | 118 +++++++++++++++++++++------------------ tests/e2e/test_runner.go | 2 +- 2 files changed, 64 insertions(+), 56 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index dd3fec6770..48619b5e7f 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2941,71 +2941,79 @@ func (tr Chain) startConsumerEvidenceDetector( log.Fatal(err, "\n", string(bz)) } - // persist evidence in the json format - evidenceJson := gjson.Get(string(bz), "evidence.evidence").Array()[0].Get("duplicate_vote_evidence").Raw - evidencePath := "/temp-evidence.json" - bz, err = tr.target.ExecCommand( - "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, evidenceJson, evidencePath), - ).CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) + evidence := gjson.Get(string(bz), "evidence.evidence").Array() + if len(evidence) == 0 { + log.Fatal("expected at least one evidence in block but found zero") } - // query IBC header at the infraction height - cmd = tr.target.ExecCommand( - consumerBinaryName, - "query", "ibc", "client", "header", "--height", strconv.Itoa(int(infractionHeight)), - `--node`, tr.target.GetQueryNode(action.Chain), - `-o`, `json`, - ) + if equivocation := evidence[0].Get("duplicate_vote_evidence"); equivocation.String() != "" { - if verbose { - fmt.Println("query IBC header cmd:", cmd.String()) - } + // persist evidence in the json format + evidenceJson := equivocation.Raw + evidencePath := "/temp-evidence.json" + bz, err = tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, evidenceJson, evidencePath), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } - bz, err = cmd.CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) - } + // query IBC header at the infraction height + cmd = tr.target.ExecCommand( + consumerBinaryName, + "query", "ibc", "client", "header", "--height", strconv.Itoa(int(infractionHeight)), + `--node`, tr.target.GetQueryNode(action.Chain), + `-o`, `json`, + ) - // persist IBC header in json format - headerPath := "/temp-header.json" - bz, err = tr.target.ExecCommand( - "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, string(bz), headerPath), - ).CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) - } + if verbose { + fmt.Println("query IBC header cmd:", cmd.String()) + } - // Submit consumer equivocation - gas := "auto" - submitEquivocation := fmt.Sprintf( - `%s tx provider submit-consumer-double-voting %s %s %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].ConsumerId), - evidencePath, - headerPath, - action.Submitter, - tr.testConfig.chainConfigs[ChainID("provi")].ChainId, - tr.getValidatorHome(ChainID("provi"), action.Submitter), - tr.getValidatorNode(ChainID("provi"), action.Submitter), - gas, - ) + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } - cmd = tr.target.ExecCommand( - "/bin/bash", "-c", - submitEquivocation, - ) + // persist IBC header in json format + headerPath := "/temp-header.json" + bz, err = tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, string(bz), headerPath), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } - if verbose { - fmt.Println("submit consumer equivocation cmd:", cmd.String()) - } + // Submit consumer equivocation + gas := "auto" + submitEquivocation := fmt.Sprintf( + `%s tx provider submit-consumer-double-voting %s %s %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].ConsumerId), + evidencePath, + headerPath, + action.Submitter, + tr.testConfig.chainConfigs[ChainID("provi")].ChainId, + tr.getValidatorHome(ChainID("provi"), action.Submitter), + tr.getValidatorNode(ChainID("provi"), action.Submitter), + gas, + ) - bz, err = cmd.CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) - } + cmd = tr.target.ExecCommand( + "/bin/bash", "-c", + submitEquivocation, + ) + + if verbose { + fmt.Println("submit consumer equivocation cmd:", cmd.String()) + } + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + } + tr.waitBlocks("provi", 3, 1*time.Minute) } } diff --git a/tests/e2e/test_runner.go b/tests/e2e/test_runner.go index bc2367a12b..c3ced5ab61 100644 --- a/tests/e2e/test_runner.go +++ b/tests/e2e/test_runner.go @@ -94,7 +94,7 @@ func (tr *TestRunner) Run() error { } tr.result.Passed() - // err = tr.teardownEnvironment() + err = tr.teardownEnvironment() fmt.Printf("==========================================\n") return err } From 307edc940fbe86a2543de48462232a54cbcc0d66 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Tue, 10 Sep 2024 17:36:03 +0200 Subject: [PATCH 5/9] reformat --- tests/e2e/actions.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 48619b5e7f..26a0ebd346 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2947,7 +2947,6 @@ func (tr Chain) startConsumerEvidenceDetector( } if equivocation := evidence[0].Get("duplicate_vote_evidence"); equivocation.String() != "" { - // persist evidence in the json format evidenceJson := equivocation.Raw evidencePath := "/temp-evidence.json" @@ -2984,7 +2983,7 @@ func (tr Chain) startConsumerEvidenceDetector( log.Fatal(err, "\n", string(bz)) } - // Submit consumer equivocation + // submit consumer equivocation to provider gas := "auto" submitEquivocation := fmt.Sprintf( `%s tx provider submit-consumer-double-voting %s %s %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, @@ -3013,6 +3012,10 @@ func (tr Chain) startConsumerEvidenceDetector( log.Fatal(err, "\n", string(bz)) } } + + // TODO: @sainoe handle misbehaviour + // else if misb := evidence[0].Get("light_client_attack_evidence"); misb.String() != "" { + //} tr.waitBlocks("provi", 3, 1*time.Minute) } } From adb51ffd25f2f2c376e6802cb74559833207dff3 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Tue, 10 Sep 2024 17:42:07 +0200 Subject: [PATCH 6/9] nit --- x/ccv/provider/client/cli/tx.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 27e43b35ab..c3153ee0fd 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -177,10 +177,6 @@ Example: return err } - // if err := json.Unmarshal(evidenceJson, &ev); err != nil { - // return fmt.Errorf("duplicate vote evidence unmarshalling failed: %s", err) - // } - ev := tmproto.DuplicateVoteEvidence{} if err := cdc.UnmarshalJSON(evidenceJson, &ev); err != nil { return fmt.Errorf("duplicate vote evidence unmarshalling failed: %s", err) From 778e47851146898da96849ab01351b068d372782 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Wed, 11 Sep 2024 16:11:20 +0200 Subject: [PATCH 7/9] Update tests/e2e/actions.go Co-authored-by: insumity --- tests/e2e/actions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 26a0ebd346..ccba653b21 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2889,7 +2889,7 @@ func (tr Chain) startConsumerEvidenceDetector( } tr.waitBlocks("provi", 10, 2*time.Minute) } else { - // detect and the evidence on the consumer chain + // detect the evidence on the consumer chain consumerBinaryName := tr.testConfig.chainConfigs[action.Chain].BinaryName // get the infraction height by querying the SDK evidence module of the consumer From 386bd565b8dc36e4f533893f43f17be4b69a2684 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Wed, 11 Sep 2024 16:42:29 +0200 Subject: [PATCH 8/9] Update tests/e2e/actions.go Co-authored-by: bernd-m <43466467+bermuell@users.noreply.github.com> --- tests/e2e/actions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index e85193e646..c44fd80a50 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2914,7 +2914,7 @@ func (tr Chain) detectConsumerEvidence( } // get the evidence data from the block - // note that the the evidence is added to the next block after the infraction height + // note that the evidence is added to the next block after the infraction height cmd := tr.target.ExecCommand( consumerBinaryName, "query", "block", "--type=height", strconv.Itoa(int(infractionHeight+1)), From 315d06b6a0b5b7d0e28d2dcf986158240edd3a42 Mon Sep 17 00:00:00 2001 From: Simon Noetzlin Date: Wed, 11 Sep 2024 17:10:07 +0200 Subject: [PATCH 9/9] address comments --- tests/e2e/actions.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index c44fd80a50..53f22b6a64 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2900,7 +2900,8 @@ func (tr Chain) detectConsumerEvidence( bz, err := cmd.CombinedOutput() if err == nil { evidence := gjson.Get(string(bz), "evidence") - if len(evidence.Array()) > 0 { + // we only expect only one evidence + if len(evidence.Array()) == 1 { infractionHeight = evidence.Array()[0].Get("value.height").Int() break }