From c0249ea27be54212d7ffe3ff764a6c3c940e1595 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 10 Mar 2023 16:54:51 +0100 Subject: [PATCH 01/40] Prepare for generating light client attacks --- config.toml | 10 +- config_fork.toml | 325 +++++++++++++++++++++++++++++++++++++++++++++++ create_fork.sh | 36 ++++++ 3 files changed, 366 insertions(+), 5 deletions(-) create mode 100644 config_fork.toml create mode 100755 create_fork.sh diff --git a/config.toml b/config.toml index d0fc1c441d..70ff26f9a3 100644 --- a/config.toml +++ b/config.toml @@ -3,7 +3,7 @@ # Specify the verbosity for the relayer logging output. Default: 'info' # Valid options are 'error', 'warn', 'info', 'debug', 'trace'. -log_level = 'info' +log_level = 'debug' # Specify the mode to be used by the relayer. [Required] @@ -24,19 +24,19 @@ enabled = true refresh = true # Whether or not to enable misbehaviour detection for clients. [Default: false] -misbehaviour = false +misbehaviour = true # Specify the connections mode. [mode.connections] # Whether or not to enable the connection workers for handshake completion. [Required] -enabled = false +enabled = true # Specify the channels mode. [mode.channels] # Whether or not to enable the channel workers for handshake completion. [Required] -enabled = false +enabled = true # Specify the packets mode. [mode.packets] @@ -78,7 +78,7 @@ auto_register_counterparty_payee = false [rest] # Whether or not to enable the REST service. Default: false -enabled = true +enabled = false # Specify the IPv4/6 host over which the built-in HTTP server will serve the RESTful # API requests. Default: 127.0.0.1 diff --git a/config_fork.toml b/config_fork.toml new file mode 100644 index 0000000000..127365dc58 --- /dev/null +++ b/config_fork.toml @@ -0,0 +1,325 @@ +# The global section has parameters that apply globally to the relayer operation. +[global] + +# Specify the verbosity for the relayer logging output. Default: 'info' +# Valid options are 'error', 'warn', 'info', 'debug', 'trace'. +log_level = 'debug' + + +# Specify the mode to be used by the relayer. [Required] +[mode] + +# Specify the client mode. +[mode.clients] + +# Whether or not to enable the client workers. [Required] +enabled = true + +# Whether or not to enable periodic refresh of clients. [Default: true] +# This feature only applies to clients that underlie an open channel. +# For Tendermint clients, the frequency at which Hermes refreshes them is 2/3 of their +# trusting period (e.g., refresh every ~9 days if the trusting period is 14 days). +# Note: Even if this is disabled, clients will be refreshed automatically if +# there is activity on a connection or channel they are involved with. +refresh = true + +# Whether or not to enable misbehaviour detection for clients. [Default: false] +misbehaviour = true + +# Specify the connections mode. +[mode.connections] + +# Whether or not to enable the connection workers for handshake completion. [Required] +enabled = true + +# Specify the channels mode. +[mode.channels] + +# Whether or not to enable the channel workers for handshake completion. [Required] +enabled = true + +# Specify the packets mode. +[mode.packets] + +# Whether or not to enable the packet workers. [Required] +enabled = true + +# Parametrize the periodic packet clearing feature. +# Interval (in number of blocks) at which pending packets +# should be periodically cleared. A value of '0' will disable +# periodic packet clearing. [Default: 100] +clear_interval = 100 + +# Whether or not to clear packets on start. [Default: true] +clear_on_start = true + +# Toggle the transaction confirmation mechanism. +# The tx confirmation mechanism periodically queries the `/tx_search` RPC +# endpoint to check that previously-submitted transactions +# (to any chain in this config file) have been successfully delivered. +# If they have not been, and `clear_interval = 0`, then those packets are +# queued up for re-submission. +# If set to `false`, the following telemetry metrics will be disabled: +# `acknowledgment_packets_confirmed`, `receive_packets_confirmed` and `timeout_packets_confirmed`. +# [Default: false] +tx_confirmation = false + +# Auto register the counterparty payee on a destination chain to +# the relayer's address on the source chain. This can be used +# for simple configuration of the relayer to receive fees for +# relaying RecvPacket on fee-enabled channels. +# For more complex configuration, turn this off and use the CLI +# to manually register the payee addresses. +# [Default: false] +auto_register_counterparty_payee = false + +# The REST section defines parameters for Hermes' built-in RESTful API. +# https://hermes.informal.systems/rest.html +[rest] + +# Whether or not to enable the REST service. Default: false +enabled = false + +# Specify the IPv4/6 host over which the built-in HTTP server will serve the RESTful +# API requests. Default: 127.0.0.1 +host = '127.0.0.1' + +# Specify the port over which the built-in HTTP server will serve the restful API +# requests. Default: 3000 +port = 3000 + + +# The telemetry section defines parameters for Hermes' built-in telemetry capabilities. +# https://hermes.informal.systems/telemetry.html +[telemetry] + +# Whether or not to enable the telemetry service. Default: false +enabled = false + +# Specify the IPv4/6 host over which the built-in HTTP server will serve the metrics +# gathered by the telemetry service. Default: 127.0.0.1 +host = '127.0.0.1' + +# Specify the port over which the built-in HTTP server will serve the metrics gathered +# by the telemetry service. Default: 3001 +port = 3001 + + +# A chains section includes parameters related to a chain and the full node to which +# the relayer can send transactions and queries. +[[chains]] + +# Specify the chain ID. Required +id = 'ibc-0' + +# Specify the RPC address and port where the chain RPC server listens on. Required +rpc_addr = 'http://127.0.0.1:26657' + +# Specify the GRPC address and port where the chain GRPC server listens on. Required +grpc_addr = 'http://127.0.0.1:9090' + +# Specify the WebSocket address and port where the chain WebSocket server +# listens on. Required +websocket_addr = 'ws://127.0.0.1:26657/websocket' + +# Specify the maximum amount of time (duration) that the RPC requests should +# take before timing out. Default: 10s (10 seconds) +# Note: Hermes uses this parameter _only_ in `start` mode; for all other CLIs, +# Hermes uses a large preconfigured timeout (on the order of minutes). +rpc_timeout = '10s' + +# Specify the prefix used by the chain. Required +account_prefix = 'cosmos' + +# Specify the name of the private key to use for signing transactions. Required +# See the Adding Keys chapter for more information about managing signing keys: +# https://hermes.informal.systems/commands/keys/index.html#adding-keys +key_name = 'testkey' + +# Specify the address type which determines: +# 1) address derivation; +# 2) how to retrieve and decode accounts and pubkeys; +# 3) the message signing method. +# The current configuration options are for Cosmos SDK and Ethermint. +# +# Example configuration for chains based on Ethermint library: +# +# address_type = { derivation = 'ethermint', proto_type = { pk_type = '/ethermint.crypto.v1.ethsecp256k1.PubKey' } } +# +# Default: { derivation = 'cosmos' }, i.e. address derivation as in Cosmos SDK. +# Warning: This is an advanced feature! Modify with caution. +address_type = { derivation = 'cosmos' } + +# Specify the store prefix used by the on-chain IBC modules. Required +# Recommended value for Cosmos SDK: 'ibc' +store_prefix = 'ibc' + +# Gas Parameters +# +# The term 'gas' is used to denote the amount of computation needed to execute +# and validate a transaction on-chain. It can be thought of as fuel that gets +# spent in order to power the on-chain execution of a transaction. +# +# Hermes attempts to simulate how much gas a transaction will expend on its +# target chain. From that, it calculates the cost of that gas by multiplying the +# amount of estimated gas by the `gas_multiplier` and the `gas_price` +# (estimated gas * `gas_multiplier` * `gas_price`) in order to compute the +# total fee to be deducted from the relayer's wallet. +# +# The `simulate_tx` operation does not always correctly estimate the appropriate +# amount of gas that a transaction requires. In those cases when the operation +# fails, Hermes will attempt to submit the transaction using the specified +# `default_gas` and `max_gas` parameters. In the case that a transaction would +# require more than `max_gas`, it doesn't get submitted and a +# `TxSimulateGasEstimateExceeded` error is returned. + +# Specify the default amount of gas to be used in case the tx simulation fails, +# and Hermes cannot estimate the amount of gas needed. +# Default: 100 000 +default_gas = 100000 + +# Specify the maximum amount of gas to be used as the gas limit for a transaction. +# If `default_gas` is unspecified, then `max_gas` will be used as `default_gas`. +# Default: 400 000 +max_gas = 400000 + +# Specify the price per gas used of the fee to submit a transaction and +# the denomination of the fee. +# +# The specified gas price should always be greater or equal to the `min-gas-price` +# configured on the chain. This is to ensure that at least some minimal price is +# paid for each unit of gas per transaction. +# +# Required +gas_price = { price = 0.001, denom = 'stake' } + +# Multiply this amount with the gas estimate, used to compute the fee +# and account for potential estimation error. +# +# The purpose of multiplying by `gas_multiplier` is to provide a bit of a buffer +# to catch some of the cases when the gas estimation calculation is on the low +# end. +# +# Example: With this setting set to 1.1, then if the estimated gas +# is 80_000, then gas used to compute the fee will be adjusted to +# 80_000 * 1.1 = 88_000. +# +# Default: 1.1, ie. the gas is increased by 10% +# Minimum value: 1.0 +gas_multiplier = 1.1 + +# Specify how many IBC messages at most to include in a single transaction. +# Default: 30 +max_msg_num = 30 + +# Specify the maximum size, in bytes, of each transaction that Hermes will submit. +# Default: 2097152 (2 MiB) +max_tx_size = 2097152 + +# Specify the maximum amount of time to tolerate a clock drift. +# The clock drift parameter defines how much new (untrusted) header's time +# can drift into the future. Default: 5s +clock_drift = '5s' + +# Specify the maximum time per block for this chain. +# The block time together with the clock drift are added to the source drift to estimate +# the maximum clock drift when creating a client on this chain. Default: 30s +# For cosmos-SDK chains a good approximation is `timeout_propose` + `timeout_commit` +# Note: This MUST be the same as the `max_expected_time_per_block` genesis parameter for Tendermint chains. +max_block_time = '30s' + +# Specify the amount of time to be used as the light client trusting period. +# It should be significantly less than the unbonding period +# (e.g. unbonding period = 3 weeks, trusting period = 2 weeks). +# Default: 2/3 of the `unbonding period` for Cosmos SDK chains +trusting_period = '14days' + +# Unbonding period for this chain. +# Required for ICS consumer chains, as they currently do not expose the staking module. +# WARNING: Only specifiy this for ICS consumer chain, but NOT for any other type of chain. +# For other chains, this is fetched via gRPC from the staking parameters. +unbonding_period = '21days' + +# Specify the trust threshold for the light client, ie. the minimum fraction of validators +# which must overlap across two blocks during light client verification. +# Default: { numerator = '2', denominator = '3' }, ie. 2/3. +# Warning: This is an advanced feature! Modify with caution. +trust_threshold = { numerator = '2', denominator = '3' } + +# Specify a string that Hermes will use as a memo for each transaction it submits +# to this chain. The string is limited to 50 characters. Default: '' (empty). +# Note: Hermes will append to the string defined here additional +# operational debugging information, e.g., relayer build version. +memo_prefix = '' + +# This section specifies the filters for policy based relaying. +# +# Default: no policy / filters, allow all packets on all channels. +# +# Only packet filtering based on channel identifier can be specified. +# A channel filter has two fields: +# 1. `policy` - one of two types are supported: +# - 'allow': permit relaying _only on_ the port/channel id in the list below, +# - 'deny': permit relaying on any channel _except for_ the list below. +# 2. `list` - the list of channels specified by the port and channel identifiers. +# Optionally, each element may also contains wildcards, for eg. 'ica*' +# to match all identifiers starting with 'ica' or '*' to match all identifiers. +# +# Example configuration of a channel filter, only allowing packet relaying on +# channel with port ID 'transfer' and channel ID 'channel-0', as well as on +# all ICA channels. +# +# [chains.packet_filter] +# policy = 'allow' +# list = [ +# ['ica*', '*'], +# ['transfer', 'channel-0'], +# ] + +# This section specifies the filters for incentivized packet relaying. +# Default: no filters, will relay all packets even if they +# are not incentivized. +# +# It is possible to specify the channel or use wildcards for the +# channels. +# The only fee which can be parametrized is the `recv_fee`. +# +# Example configuration of a filter which will only relay incentivized +# packets, with no regards for channel and amount. +# +# [chains.packet_filter.min_fees.'*'] +# recv = [ { amount = 0 } ] +# +# Example configuration of a filter which will only relay packets if they are +# from the channel 'channel-0', and they have a `recv_fee` of at least 20 stake +# or 10 uatom. +# +# [chains.packet_filter.min_fees.'channel-0'] +# recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] + +# Specify that the transaction fees should be payed from this fee granter's account. +# Optional. If unspecified (the default behavior), then no fee granter is used, and +# the account specified in `key_name` will pay the tx fees for all transactions +# submitted to this chain. +# fee_granter = '' + +[[chains]] +id = 'ibc-1' +rpc_addr = 'http://127.0.0.1:26457' +grpc_addr = 'http://127.0.0.1:9092' +websocket_addr = 'ws://127.0.0.1:26457/websocket' +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +default_gas = 100000 +max_gas = 400000 +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.1 +max_msg_num = 30 +max_tx_size = 2097152 +clock_drift = '5s' +max_block_time = '30s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'cosmos' } diff --git a/create_fork.sh b/create_fork.sh new file mode 100755 index 0000000000..86109c249d --- /dev/null +++ b/create_fork.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -euo pipefail + +IBC_0_RPC_PORT=26657 +IBC_1_RPC_PORT=26557 +IBC_F_RPC_PORT=26457 + +HERMES="$HOME/.cargo/target/debug/hermes" + +echo "❯ Fetching the latest block height and hash from ibc-0..." +curl -s "localhost:$IBC_0_RPC_PORT/commit" | jq "{height: .result.signed_header.header.height, hash: .result.signed_header.commit.block_id.hash}" + +echo "❯ Creating new channel between ibc-0 and ibc-1..." +$HERMES --config config.toml create channel --a-chain ibc-0 --b-chain ibc-1 --a-port transfer --b-port transfer --new-client-connection --yes + +echo "❯ Killing ibc-1... (waiting 5 seconds)" +pkill -f ibc-1 + +sleep 5 + +echo "❯ Creating ibc-1 fork..." +cp -r data/ibc-1 data/ibc-1-f +sconfig data/ibc-1-f/config/config.toml "rpc.laddr=tcp://0.0.0.0:26457" +sconfig data/ibc-1-f/config/config.toml "p2p.laddr=tcp://0.0.0.0:26456" + +# echo "❯ Creating Hermes configuration for ibc-1 fork..." +# cp config.toml config_fork.toml +# sconfig config_fork.toml "chains.ibc-1.rpc_addr = \"http://localhost:$IBC_F_RPC_PORT\"" + +echo "❯ Starting ibc-1..." +gaiad --home ./data/ibc-1 start --pruning=nothing --grpc.address=0.0.0.0:9091 --log_level error > data/ibc-1.log 2>&1 & + +echo "❯ Starting ibc-1 fork..." +gaiad --home ./data/ibc-1-f start --pruning=nothing --grpc.address=0.0.0.0:9092 --log_level error > data/ibc-1-f.log 2>&1 & + From 78fc720cced0259b0de367377046dce926a8c3e0 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 15 Mar 2023 13:38:58 +0100 Subject: [PATCH 02/40] Remove redundant message --- crates/relayer-cli/src/commands/misbehaviour.rs | 1 + crates/relayer/src/foreign_client.rs | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/relayer-cli/src/commands/misbehaviour.rs b/crates/relayer-cli/src/commands/misbehaviour.rs index a686548fba..dca8647f7b 100644 --- a/crates/relayer-cli/src/commands/misbehaviour.rs +++ b/crates/relayer-cli/src/commands/misbehaviour.rs @@ -131,6 +131,7 @@ fn misbehaviour_handling( let client = ForeignClient::restore(client_id, chain, counterparty_chain); let result = client.detect_misbehaviour_and_submit_evidence(update.as_ref()); + if let MisbehaviourResults::EvidenceSubmitted(events) = result { info!("evidence submission result {}", PrettySlice(&events)); } diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index dc76a6da2d..6e16d08ae2 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -1688,10 +1688,6 @@ impl ForeignClient { - info!( - "evidence submission result: {}", - PrettySlice(&misbehaviour_detection_result) - ); if !misbehaviour_detection_result.is_empty() { info!( "evidence submission result: {}", From 965f065c809ac5dab54b843aeb5470edf2b4d0e2 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 15 Mar 2023 17:28:16 +0100 Subject: [PATCH 03/40] Improve script --- create_fork.sh | 57 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/create_fork.sh b/create_fork.sh index 86109c249d..d458b95cba 100755 --- a/create_fork.sh +++ b/create_fork.sh @@ -2,35 +2,62 @@ set -euo pipefail -IBC_0_RPC_PORT=26657 +# --- Variables --- + +HERMES="cargo run -q --" + +# IBC_0_RPC_PORT=26657 IBC_1_RPC_PORT=26557 -IBC_F_RPC_PORT=26457 +IBC_1_COMMIT_FILE="data/ibc-1-commit.json" + +# --- Helpers --- + +warn() { + echo "WARNING: $*" +} + +info() { + echo "❯ $*" +} -HERMES="$HOME/.cargo/target/debug/hermes" +# --- Checks --- -echo "❯ Fetching the latest block height and hash from ibc-0..." -curl -s "localhost:$IBC_0_RPC_PORT/commit" | jq "{height: .result.signed_header.header.height, hash: .result.signed_header.commit.block_id.hash}" +if [ -z "$(which gaiad)" ]; then + warn "Cannot find 'gaiad', please ensure it is in your \$PATH" + exit 1 +fi +if [ -z "$(which stoml)" ]; then + warn "Missing stoml utility, install it from https://github.com/freshautomations/stoml/releases" + exit 1 +fi +if [ -z "$(which sconfig)" ]; then + warn "Missing sconfig utility, install it from https://github.com/freshautomations/sconfig/releases" + exit 1 +fi -echo "❯ Creating new channel between ibc-0 and ibc-1..." +# --- Main --- + +info "Fetching the latest block height and hash from ibc-1..." +curl -s "localhost:$IBC_1_RPC_PORT/commit" | \ + jq "{height: .result.signed_header.header.height, hash: .result.signed_header.commit.block_id.hash}" | \ + tee "$IBC_1_COMMIT_FILE" + +info "Creating new channel between ibc-0 and ibc-1..." $HERMES --config config.toml create channel --a-chain ibc-0 --b-chain ibc-1 --a-port transfer --b-port transfer --new-client-connection --yes -echo "❯ Killing ibc-1... (waiting 5 seconds)" +info "Killing ibc-1..." pkill -f ibc-1 +info "Waiting for ibc-1 to stop..." sleep 5 -echo "❯ Creating ibc-1 fork..." +info "Creating ibc-1 fork..." cp -r data/ibc-1 data/ibc-1-f sconfig data/ibc-1-f/config/config.toml "rpc.laddr=tcp://0.0.0.0:26457" sconfig data/ibc-1-f/config/config.toml "p2p.laddr=tcp://0.0.0.0:26456" -# echo "❯ Creating Hermes configuration for ibc-1 fork..." -# cp config.toml config_fork.toml -# sconfig config_fork.toml "chains.ibc-1.rpc_addr = \"http://localhost:$IBC_F_RPC_PORT\"" - -echo "❯ Starting ibc-1..." +info "Starting ibc-1..." gaiad --home ./data/ibc-1 start --pruning=nothing --grpc.address=0.0.0.0:9091 --log_level error > data/ibc-1.log 2>&1 & -echo "❯ Starting ibc-1 fork..." +info "Starting ibc-1 fork..." gaiad --home ./data/ibc-1-f start --pruning=nothing --grpc.address=0.0.0.0:9092 --log_level error > data/ibc-1-f.log 2>&1 & - From e255cdd45f7f5a88d0ed94c1e9b2055dc4ea5327 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 21 Mar 2023 12:24:19 +0100 Subject: [PATCH 04/40] Use tendermint-rs with new misbehavior detector --- Cargo.lock | 16 ++-------------- Cargo.toml | 12 ++++++------ 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 319e4b5ea8..8984b2346e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3991,8 +3991,6 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90c3c1e32352551f0f1639ce765e4c66ce250c733d4b9ba1aff81130437465c" dependencies = [ "bytes", "digest 0.10.6", @@ -4022,8 +4020,6 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74efd33bcb53413b77cbe90ccb2cf0403930a5c1f300725deb87a61f7c4fab90" dependencies = [ "flex-error", "serde", @@ -4036,8 +4032,6 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac7f5273471fbeaad69e196146dd459f3857c021141a67287aedd0504429e4f0" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4047,19 +4041,19 @@ dependencies = [ "serde", "serde_cbor", "serde_derive", + "serde_json", "static_assertions", "tendermint", "tendermint-light-client-verifier", "tendermint-rpc", "time", "tokio", + "tracing", ] [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36e9193521a81e4c824faedc5eb31926f8918ebb21a1fa9cee9b3dbe5164a93" dependencies = [ "derive_more", "flex-error", @@ -4071,8 +4065,6 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e553ed65874c3f35a71eb60d255edfea956274b5af37a0297d54bba039fe45e3" dependencies = [ "bytes", "flex-error", @@ -4089,8 +4081,6 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d79bd426571d6a805be5c0b6749707ede6c6ee5e55dd45baef46857a1baa9f54" dependencies = [ "async-trait", "async-tungstenite", @@ -4124,8 +4114,6 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2a14868d694e25443ae9dd8b8a49c77a835a191a51b727134c2418ae110ec" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/Cargo.toml b/Cargo.toml index 02e52f3290..4c05167273 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ members = [ [patch.crates-io] # ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs.git", branch = "main" } -# tendermint = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } -# tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } -# tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } -# tendermint-light-client = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } -# tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } -# tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs", branch = "main" } +tendermint = { path = "../tendermint-rs/tendermint" } +tendermint-rpc = { path = "../tendermint-rs/rpc" } +tendermint-proto = { path = "../tendermint-rs/proto" } +tendermint-light-client = { path = "../tendermint-rs/light-client" } +tendermint-light-client-verifier = { path = "../tendermint-rs/light-client-verifier" } +tendermint-testgen = { path = "../tendermint-rs/testgen" } From 484b47fd33ecb37d5a92aeb091323f8f4db20495 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 21 Mar 2023 12:45:01 +0100 Subject: [PATCH 05/40] Small refactor in client worker --- crates/relayer/src/worker/client.rs | 205 ++++++++++++++++------------ 1 file changed, 116 insertions(+), 89 deletions(-) diff --git a/crates/relayer/src/worker/client.rs b/crates/relayer/src/worker/client.rs index 9323a57ebc..32d3fcc0d0 100644 --- a/crates/relayer/src/worker/client.rs +++ b/crates/relayer/src/worker/client.rs @@ -1,12 +1,13 @@ use core::convert::Infallible; use core::time::Duration; use crossbeam_channel::Receiver; +use retry::delay::Fibonacci; +use retry::retry_with_index; use std::time::Instant; -use tracing::{debug, span, trace, warn}; +use tracing::{debug, debug_span, error_span, trace, warn}; +use ibc_relayer_types::core::ics02_client::events::UpdateClient; use ibc_relayer_types::events::IbcEvent; -use retry::delay::Fibonacci; -use retry::retry_with_index; use crate::util::retry::clamp_total; use crate::util::task::{spawn_background_task, Next, TaskError, TaskHandle}; @@ -17,10 +18,10 @@ use crate::{ use super::WorkerCmd; -const REFRESH_INTERVAL_SECONDS: u64 = 2; -const INITIAL_FIBONACCI_VALUE: u64 = 1; -const MAX_REFRESH_DELAY_SECONDS: u64 = 60 * 60; // 1 hour -const MAX_REFRESH_TOTAL_DELAY_SECONDS: u64 = 60 * 60 * 24; // 1 day +const REFRESH_INTERVAL: Duration = Duration::from_secs(2); // 2 seconds +const INITIAL_BACKOFF: Duration = Duration::from_secs(1); // 1 second +const MAX_REFRESH_DELAY: Duration = Duration::from_secs(60 * 60); // 1 hour +const MAX_REFRESH_TOTAL_DELAY: Duration = Duration::from_secs(60 * 60 * 24); // 1 day pub fn spawn_refresh_client( mut client: ForeignClient, @@ -30,51 +31,44 @@ pub fn spawn_refresh_client( client = %client.id, "skipping refresh client task on frozen client", ); - None - } else { - // Compute the refresh interval as a fraction of the client's trusting period - // If the trusting period or the client state is not retrieved, fallback to a default value. - let mut next_refresh = Instant::now() + Duration::from_secs(REFRESH_INTERVAL_SECONDS); - Some(spawn_background_task( - span!( - tracing::Level::ERROR, - "worker.client.refresh", - client = %client.id, - src_chain = %client.src_chain.id(), - dst_chain = %client.dst_chain.id(), - ), - Some(Duration::from_secs(1)), - move || { - // This is used for integration tests until `spawn_background_task` - // uses async instead of threads - if Instant::now() < next_refresh { - return Ok(Next::Continue); - } - // Use retry mechanism only if `client.refresh()` fails. - let res = retry_with_index( - clamp_total( - Fibonacci::from(Duration::from_secs(INITIAL_FIBONACCI_VALUE)), - Duration::from_secs(MAX_REFRESH_DELAY_SECONDS), - Duration::from_secs(MAX_REFRESH_TOTAL_DELAY_SECONDS), - ), - |_| client.refresh(), - ); - - match res { - // If `client.refresh()` was successful, update the `next_refresh` call. - Ok(_) => { - next_refresh = - Instant::now() + Duration::from_secs(REFRESH_INTERVAL_SECONDS); - Ok(Next::Continue) - } - // If `client.refresh()` failed and the retry mechanism - // exceeded the maximum delay, return a fatal error. - Err(e) => Err(TaskError::Fatal(e)), - } - }, - )) + return None; } + + // Compute the refresh interval as a fraction of the client's trusting period + // If the trusting period or the client state is not retrieved, fallback to a default value. + let mut next_refresh = Instant::now() + REFRESH_INTERVAL; + Some(spawn_background_task( + error_span!( + "worker.client.refresh", + client = %client.id, + src_chain = %client.src_chain.id(), + dst_chain = %client.dst_chain.id(), + ), + Some(Duration::from_secs(1)), + move || { + // This is used for integration tests until `spawn_background_task` + // uses async instead of threads + if Instant::now() < next_refresh { + return Ok(Next::Continue); + } + + // Use retry mechanism only if `client.refresh()` fails. + let res = retry_with_index(refresh_strategy(), |_| client.refresh()); + + match res { + // If `client.refresh()` was successful, update the `next_refresh` call. + Ok(_) => { + next_refresh = Instant::now() + REFRESH_INTERVAL; + + Ok(Next::Continue) + } + // If `client.refresh()` failed and the retry mechanism + // exceeded the maximum delay, return a fatal error. + Err(e) => Err(TaskError::Fatal(e)), + } + }, + )) } pub fn detect_misbehavior_task( @@ -84,16 +78,18 @@ pub fn detect_misbehavior_task( if client.is_expired_or_frozen() { warn!( client = %client.id(), + src_chain = %client.src_chain.id(), + dst_chain = %client.dst_chain.id(), "skipping detect misbehavior task on frozen client", ); + return None; } - let mut first_check_done = false; + let mut initial_check_done = false; let handle = spawn_background_task( - span!( - tracing::Level::ERROR, + error_span!( "worker.client.misbehaviour", client = %client.id, src_chain = %client.src_chain.id(), @@ -101,46 +97,24 @@ pub fn detect_misbehavior_task( ), Some(Duration::from_millis(600)), move || -> Result> { - if !first_check_done { - first_check_done = true; - debug!("doing first check"); - let misbehavior_result = client.detect_misbehaviour_and_submit_evidence(None); - trace!("detect misbehavior result: {:?}", misbehavior_result); + if !initial_check_done { + initial_check_done = true; + + debug!("doing initial misbehavior check"); + let result = client.detect_misbehaviour_and_submit_evidence(None); + debug!("misbehavior detection result: {:?}", result); } - if let Ok(cmd) = receiver.try_recv() { - match cmd { - WorkerCmd::IbcEvents { batch } => { - trace!("received batch: {:?}", batch); - - for event_with_height in batch.events { - if let IbcEvent::UpdateClient(ref update) = event_with_height.event { - debug!("checking misbehavior for updated client"); - let misbehavior_result = - client.detect_misbehaviour_and_submit_evidence(Some(update)); - trace!("detect misbehavior result: {:?}", misbehavior_result); - - match misbehavior_result { - MisbehaviourResults::ValidClient => {} - MisbehaviourResults::VerificationError => { - // can retry in next call - } - MisbehaviourResults::EvidenceSubmitted(_) => { - // if evidence was submitted successfully then exit - return Ok(Next::Abort); - } - MisbehaviourResults::CannotExecute => { - // skip misbehaviour checking if chain does not have support for it (i.e. client - // update event does not include the header) - return Ok(Next::Abort); - } - } - } + if let Ok(WorkerCmd::IbcEvents { batch }) = receiver.try_recv() { + trace!("received batch: {:?}", batch); + + for event_with_height in batch.events { + if let IbcEvent::UpdateClient(ref update) = event_with_height.event { + match on_client_update(&client, update) { + Next::Continue => continue, + Next::Abort => return Ok(Next::Abort), } } - - WorkerCmd::NewBlock { .. } => {} - WorkerCmd::ClearPendingPackets => {} } } @@ -150,3 +124,56 @@ pub fn detect_misbehavior_task( Some(handle) } + +fn on_client_update( + client: &ForeignClient, + update: &UpdateClient, +) -> Next { + let _span = debug_span!( + "on_client_update", + client = %update.client_id(), + client_type = %update.client_type(), + height = %update.consensus_height(), + ); + + debug!("checking misbehavior for updated client"); + + let result = client.detect_misbehaviour_and_submit_evidence(Some(update)); + + trace!("misbehavior detection result: {:?}", result); + + match result { + MisbehaviourResults::ValidClient => { + debug!("client is valid"); + + Next::Continue + } + MisbehaviourResults::VerificationError => { + // can retry in next call + debug!("client verification error, will retry in next call"); + + Next::Continue + } + MisbehaviourResults::EvidenceSubmitted(_) => { + // if evidence was submitted successfully then exit + debug!("misbehavior detected! Evidence succesfully submitted, exiting"); + + Next::Abort + } + MisbehaviourResults::CannotExecute => { + // skip misbehaviour checking if chain does not have support for it (i.e. client + // update event does not include the header) + debug!("cannot execute misbehavior detection, exiting"); + + Next::Abort + } + } +} + +fn refresh_strategy() -> impl Iterator { + clamp_total( + Fibonacci::from(INITIAL_BACKOFF), + MAX_REFRESH_DELAY, + MAX_REFRESH_TOTAL_DELAY, + ) +} From 8b58222667b0896e091022b00e63ec657c247bb2 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 21 Mar 2023 12:52:59 +0100 Subject: [PATCH 06/40] Cleanup and notes in ForeignClient --- crates/relayer/src/foreign_client.rs | 32 ++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index 6e16d08ae2..87812ca709 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -1441,6 +1441,7 @@ impl ForeignClient, ) -> Result, ForeignClientError> { + // FIXME: Why do we need this, and shouldn't we wait somewhere else up the call stack? thread::sleep(Duration::from_millis(200)); // Get the latest client state on destination. @@ -1523,10 +1524,11 @@ impl ForeignClient evidence_opt, @@ -1560,7 +1562,7 @@ impl ForeignClient MAX_MISBEHAVIOUR_CHECK_DURATION { trace!( "finished misbehaviour verification after {:?}", @@ -1681,22 +1683,13 @@ impl ForeignClient { - warn!("misbehaviour checking is being disabled, reason: {}", s); - - MisbehaviourResults::CannotExecute - } - - Ok(misbehaviour_detection_result) => { - if !misbehaviour_detection_result.is_empty() { - info!( - "evidence submission result: {}", - PrettySlice(&misbehaviour_detection_result) - ); + Ok(events) => { + if !events.is_empty() { + info!("evidence submission result: {}", PrettySlice(&events)); - MisbehaviourResults::EvidenceSubmitted(misbehaviour_detection_result) + MisbehaviourResults::EvidenceSubmitted(events) } else { - info!("client is valid",); + info!("client is valid"); MisbehaviourResults::ValidClient } @@ -1708,14 +1701,17 @@ impl ForeignClient { error!("cannot check misbehavior on frozen or expired client",); MisbehaviourResults::CannotExecute } + // FIXME: This is fishy _ if update_event.is_some() => MisbehaviourResults::CannotExecute, + // FIXME: This is fishy _ => { warn!("misbehaviour checking result: {}", e); From cb1bfaa285792d6bcd521e665fe4f86f1e3976ca Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 21 Mar 2023 15:43:20 +0100 Subject: [PATCH 07/40] Some more cleanup --- .../relayer-cli/src/commands/misbehaviour.rs | 20 ++++++++++++++++--- crates/relayer/src/foreign_client.rs | 6 +++--- crates/relayer/src/worker/client.rs | 4 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/crates/relayer-cli/src/commands/misbehaviour.rs b/crates/relayer-cli/src/commands/misbehaviour.rs index dca8647f7b..8400d11ad9 100644 --- a/crates/relayer-cli/src/commands/misbehaviour.rs +++ b/crates/relayer-cli/src/commands/misbehaviour.rs @@ -130,10 +130,24 @@ fn misbehaviour_handling( })?; let client = ForeignClient::restore(client_id, chain, counterparty_chain); - let result = client.detect_misbehaviour_and_submit_evidence(update.as_ref()); + let result = client.detect_misbehaviour_and_submit_evidence(update); - if let MisbehaviourResults::EvidenceSubmitted(events) = result { - info!("evidence submission result {}", PrettySlice(&events)); + match result { + MisbehaviourResults::ValidClient => { + info!("client is valid"); + } + MisbehaviourResults::CannotExecute => { + warn!("could not perform misbehaviour detection"); + } + MisbehaviourResults::EvidenceSubmitted(events) => { + info!( + "misbehavior detected, evidence submitted: {}", + PrettySlice(&events) + ); + } + MisbehaviourResults::VerificationError => { + warn!("verification error during misbehavior detection"); + } } Ok(()) diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index 87812ca709..233620a4ce 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -1441,7 +1441,7 @@ impl ForeignClient, ) -> Result, ForeignClientError> { - // FIXME: Why do we need this, and shouldn't we wait somewhere else up the call stack? + // FIXME(romac): Why do we need this, and shouldn't we wait somewhere else up the call stack? thread::sleep(Duration::from_millis(200)); // Get the latest client state on destination. @@ -1655,10 +1655,10 @@ impl ForeignClient, + update_event: Option, ) -> MisbehaviourResults { // check evidence of misbehaviour for all updates or one - let result = match self.detect_misbehaviour(update_event) { + let result = match self.detect_misbehaviour(update_event.as_ref()) { Err(e) => Err(e), Ok(None) => Ok(vec![]), // no evidence found Ok(Some(detected)) => { diff --git a/crates/relayer/src/worker/client.rs b/crates/relayer/src/worker/client.rs index 32d3fcc0d0..a8e7b498d6 100644 --- a/crates/relayer/src/worker/client.rs +++ b/crates/relayer/src/worker/client.rs @@ -109,7 +109,7 @@ pub fn detect_misbehavior_task( trace!("received batch: {:?}", batch); for event_with_height in batch.events { - if let IbcEvent::UpdateClient(ref update) = event_with_height.event { + if let IbcEvent::UpdateClient(update) = event_with_height.event { match on_client_update(&client, update) { Next::Continue => continue, Next::Abort => return Ok(Next::Abort), @@ -127,7 +127,7 @@ pub fn detect_misbehavior_task( fn on_client_update( client: &ForeignClient, - update: &UpdateClient, + update: UpdateClient, ) -> Next { let _span = debug_span!( "on_client_update", From 3857dbfdd8dd76c19520c2913ee1b41dabeb2455 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 22 Mar 2023 16:06:19 +0100 Subject: [PATCH 08/40] Call to the new attack detector --- .../clients/ics07_tendermint/client_state.rs | 16 +--- .../src/core/ics02_client/height.rs | 49 ++++++----- .../src/core/ics02_client/trust_threshold.rs | 14 ++- crates/relayer/src/chain/cosmos.rs | 3 +- crates/relayer/src/error.rs | 6 ++ crates/relayer/src/foreign_client.rs | 1 + crates/relayer/src/light_client/tendermint.rs | 70 +++++++-------- .../src/light_client/tendermint/detector.rs | 88 +++++++++++++++++++ 8 files changed, 165 insertions(+), 82 deletions(-) create mode 100644 crates/relayer/src/light_client/tendermint/detector.rs diff --git a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs index 443a133de8..ffdadf107a 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs @@ -10,7 +10,6 @@ use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientStat use ibc_proto::protobuf::Protobuf; use tendermint_light_client_verifier::options::Options; -use tendermint_light_client_verifier::ProdVerifier; use crate::clients::ics07_tendermint::error::Error; use crate::clients::ics07_tendermint::header::Header as TmHeader; @@ -40,8 +39,6 @@ pub struct ClientState { pub upgrade_path: Vec, pub allow_update: AllowUpdate, pub frozen_height: Option, - #[serde(skip)] - pub verifier: ProdVerifier, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -117,7 +114,6 @@ impl ClientState { upgrade_path, allow_update, frozen_height: None, - verifier: ProdVerifier::default(), }) } @@ -150,15 +146,12 @@ impl ClientState { /// Helper method to produce a [`Options`] struct for use in /// Tendermint-specific light client verification. - pub fn as_light_client_options(&self) -> Result { - Ok(Options { - trust_threshold: self - .trust_threshold - .try_into() - .map_err(|e: Ics02Error| Error::invalid_trust_threshold(e.to_string()))?, + pub fn as_light_client_options(&self) -> Options { + Options { + trust_threshold: self.trust_threshold.into(), trusting_period: self.trusting_period, clock_drift: self.max_clock_drift, - }) + } } /// Verify the time and height delays @@ -312,7 +305,6 @@ impl TryFrom for ClientState { after_misbehaviour: raw.allow_update_after_misbehaviour, }, proof_specs: raw.proof_specs.into(), - verifier: ProdVerifier::default(), }) } } diff --git a/crates/relayer-types/src/core/ics02_client/height.rs b/crates/relayer-types/src/core/ics02_client/height.rs index 09409bcb4a..2d9d468262 100644 --- a/crates/relayer-types/src/core/ics02_client/height.rs +++ b/crates/relayer-types/src/core/ics02_client/height.rs @@ -117,6 +117,13 @@ impl From for RawHeight { } } +impl From for tendermint::block::Height { + fn from(height: Height) -> Self { + tendermint::block::Height::try_from(height.revision_height) + .expect("revision height is a valid height") + } +} + impl core::fmt::Debug for Height { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { f.debug_struct("Height") @@ -139,42 +146,40 @@ define_error! { HeightConversion { height: String } [ TraceError ] - | e | { - format_args!("cannot convert into a `Height` type from string {0}", - e.height) - }, + |e| { format_args!("cannot convert into a `Height` type from string {0}", e.height) }, + + InvalidHeight + { height: String } + |e| { format_args!("invalid height {0}", e.height) }, + ZeroHeight - |_| { "attempted to parse an invalid zero height" } + |_| { "attempted to parse invalid height 0-0" } } } -impl TryFrom<&str> for Height { - type Error = HeightError; +impl FromStr for Height { + type Err = HeightError; - fn try_from(value: &str) -> Result { + fn from_str(value: &str) -> Result { let split: Vec<&str> = value.split('-').collect(); + if split.len() != 2 { + return Err(HeightError::invalid_height(value.to_owned())); + } + let revision_number = split[0] .parse::() .map_err(|e| HeightError::height_conversion(value.to_owned(), e))?; + let revision_height = split[1] .parse::() .map_err(|e| HeightError::height_conversion(value.to_owned(), e))?; - Height::new(revision_number, revision_height).map_err(|_| HeightError::zero_height()) - } -} - -impl From for String { - fn from(height: Height) -> Self { - format!("{}-{}", height.revision_number, height.revision_height) - } -} - -impl FromStr for Height { - type Err = HeightError; + if revision_number == 0 && revision_height == 0 { + return Err(HeightError::zero_height()); + } - fn from_str(s: &str) -> Result { - Height::try_from(s) + Height::new(revision_number, revision_height) + .map_err(|_| HeightError::invalid_height(value.to_owned())) } } diff --git a/crates/relayer-types/src/core/ics02_client/trust_threshold.rs b/crates/relayer-types/src/core/ics02_client/trust_threshold.rs index 93f701719a..02e131f567 100644 --- a/crates/relayer-types/src/core/ics02_client/trust_threshold.rs +++ b/crates/relayer-types/src/core/ics02_client/trust_threshold.rs @@ -75,22 +75,18 @@ impl TrustThreshold { } } -/// Conversion from Tendermint domain type into -/// IBC domain type. +/// Conversion from Tendermint domain type into IBC domain type. impl From for TrustThreshold { fn from(t: TrustThresholdFraction) -> Self { Self(Ratio::new_raw(t.numerator(), t.denominator())) } } -/// Conversion from IBC domain type into -/// Tendermint domain type. -impl TryFrom for TrustThresholdFraction { - type Error = Error; - - fn try_from(t: TrustThreshold) -> Result { +/// Conversion from IBC domain type into Tendermint domain type. +impl From for TrustThresholdFraction { + fn from(t: TrustThreshold) -> TrustThresholdFraction { TrustThresholdFraction::new(t.numerator(), t.denominator()) - .map_err(|_| Error::failed_trust_threshold_conversion(t.numerator(), t.denominator())) + .expect("trust threshold should have been valid") } } diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index f790b3b412..701d61117d 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -831,8 +831,7 @@ impl ChainEndpoint for CosmosSdkChain { .map(|v| v.target) } - /// Given a client update event that includes the header used in a client update, - /// look for misbehaviour by fetching a header at same or latest height. + /// Perform misbehavior detection for the given client state and update event. fn check_misbehaviour( &mut self, update: &UpdateClient, diff --git a/crates/relayer/src/error.rs b/crates/relayer/src/error.rs index 1bf4992981..bab49bee59 100644 --- a/crates/relayer/src/error.rs +++ b/crates/relayer/src/error.rs @@ -10,6 +10,7 @@ use prost::{DecodeError, EncodeError}; use regex::Regex; use tendermint::abci; use tendermint::Error as TendermintError; +use tendermint_light_client::builder::error::Error as LightClientBuilderError; use tendermint_light_client::components::io::IoError as LightClientIoError; use tendermint_light_client::errors::{ Error as LightClientError, ErrorDetail as LightClientErrorDetail, @@ -109,6 +110,11 @@ define_error! { [ TendermintProtoError ] |_| { "error decoding protobuf" }, + LightClientBuilder + [ LightClientBuilderError ] + |_| { "light client builder error" }, + + LightClientVerification { chain_id: String } [ LightClientError ] diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index 233620a4ce..f525ea9daa 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -1480,6 +1480,7 @@ impl ForeignClient for LightClient { self.fetch_light_block(AtHeight::At(height)) } - /// Given a client update event that includes the header used in a client update, - /// look for misbehaviour by fetching a header at same or latest height. - /// - /// ## TODO - /// - [ ] Return intermediate headers as well + /// Perform misbehavior detection on the given client state and update client event. fn check_misbehaviour( &mut self, update: &UpdateClient, @@ -102,7 +103,7 @@ impl super::LightClient for LightClient { ) -> Result, Error> { crate::time!("light client check_misbehaviour"); - let update_header = update.header.clone().ok_or_else(|| { + let update_header = update.header.as_ref().ok_or_else(|| { Error::misbehaviour(format!( "missing header in update client event {}", self.chain_id @@ -117,16 +118,25 @@ impl super::LightClient for LightClient { )) })?; + let client_state = + downcast!(client_state => AnyClientState::Tendermint).ok_or_else(|| { + Error::misbehaviour(format!( + "client type incompatible for chain {}", + self.chain_id + )) + })?; + let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?; + let latest_chain_height = ICSHeight::new(self.chain_id.version(), latest_chain_block.height().into()) .map_err(|_| Error::invalid_height_no_source())?; - // set the target height to the minimum between the update height and latest chain height + // Set the target height to the minimum between the update height and latest chain height let target_height = core::cmp::min(update.consensus_height(), latest_chain_height); let trusted_height = update_header.trusted_height; - // TODO - check that a consensus state at trusted_height still exists on-chain, + // TODO: Check that a consensus state at trusted_height still exists on-chain, // currently we don't have access to Cosmos chain query from here if trusted_height >= latest_chain_height { @@ -139,26 +149,20 @@ impl super::LightClient for LightClient { return Ok(None); } - let Verified { target, supporting } = - self.verify(trusted_height, target_height, client_state)?; + let target_block: LightBlock = todo!(); // FIXME: How do I compute this? + let trusted_block = self.fetch(trusted_height)?; // FIXME: Is that ok? + let now = latest_chain_block.time(); // FIXME: Is that right? - if !headers_compatible(&target.signed_header, &update_header.signed_header) { - let (witness, supporting) = self.adjust_headers(trusted_height, target, supporting)?; + detector::detect( + self.peer_id, + self.rpc_client.clone(), + target_block, + trusted_block, + client_state, + now, + ); - let misbehaviour = TmMisbehaviour { - client_id: update.client_id().clone(), - header1: update_header.clone(), - header2: witness, - } - .into(); - - Ok(Some(MisbehaviourEvidence { - misbehaviour, - supporting_headers: supporting.into_iter().map(Into::into).collect(), - })) - } else { - Ok(None) - } + todo!() } } @@ -167,11 +171,12 @@ impl LightClient { let rpc_client = rpc::HttpClient::new(config.rpc_addr.clone()) .map_err(|e| Error::rpc(config.rpc_addr.clone(), e))?; - let io = components::io::ProdIo::new(peer_id, rpc_client, Some(config.rpc_timeout)); + let io = components::io::ProdIo::new(peer_id, rpc_client.clone(), Some(config.rpc_timeout)); Ok(Self { chain_id: config.id.clone(), peer_id, + rpc_client, io, }) } @@ -186,18 +191,9 @@ impl LightClient { Error::client_type_mismatch(ClientType::Tendermint, client_state.client_type()) })?; - let params = TmOptions { - trust_threshold: client_state - .trust_threshold - .try_into() - .map_err(Error::light_client_state)?, - trusting_period: client_state.trusting_period, - clock_drift: client_state.max_clock_drift, - }; - Ok(TmLightClient::new( self.peer_id, - params, + client_state.as_light_client_options(), clock, scheduler, verifier, diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs new file mode 100644 index 0000000000..406536425f --- /dev/null +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -0,0 +1,88 @@ +use ibc_relayer_types::{ + clients::ics07_tendermint::client_state::ClientState, core::ics24_host::identifier::ChainId, + Height, +}; +use tendermint::{evidence::LightClientAttackEvidence, hash::Hash, Time}; +use tendermint_light_client::{ + builder::LightClientBuilder, + light_client::Options, + misbehavior::{detect_divergence, Provider}, + store::{memory::MemoryStore, LightStore}, + types::{LightBlock, PeerId, Status}, +}; +use tendermint_rpc::{Client, HttpClient}; +use tracing::{error, info}; + +use crate::{error::Error, util::block_on}; + +pub fn detect( + peer_id: PeerId, + rpc_client: HttpClient, + target_block: LightBlock, + trusted_block: LightBlock, + client_state: &ClientState, + now: Time, +) -> Result, Error> { + let primary_trace = vec![trusted_block.clone(), target_block]; + let options = client_state.as_light_client_options(); + let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block)?; + + let evidence = block_on(detect_divergence( + &mut provider, + primary_trace, + options.clock_drift, + options.trusting_period, + now, + )); + + match evidence { + Ok(None) => { + info!( + "No evidence of misbehavior detected for chain {}", + client_state.chain_id + ); + + Ok(None) + } + Ok(Some(evidence)) => { + info!( + "Evidence of misbehavior detected for chain {}", + client_state.chain_id + ); + + Ok(Some(evidence)) + } + Err(e) => { + error!( + "Error while detecting misbehavior for chain {}: {}", + client_state.chain_id, e + ); + + Ok(None) + } + } +} + +fn make_provider( + peer_id: PeerId, + rpc_client: HttpClient, + client_state: &ClientState, + trusted_block: LightBlock, +) -> Result { + let mut light_store = Box::new(MemoryStore::new()); + light_store.insert(trusted_block, Status::Trusted); + + let options = client_state.as_light_client_options(); + + let instance = + LightClientBuilder::prod(peer_id, rpc_client.clone(), light_store, options, None) + .trust_from_store() + .map_err(Error::light_client_builder)? + .build(); + + Ok(Provider::new( + client_state.chain_id.to_string(), + instance, + rpc_client, + )) +} From fff78c08e75a47c41c5b8161cd37b85ce1665e61 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 29 Mar 2023 12:38:30 +0200 Subject: [PATCH 09/40] Build evidence to report to the chain --- crates/relayer/src/chain/cosmos.rs | 2 +- crates/relayer/src/error.rs | 1 - crates/relayer/src/light_client.rs | 4 +- crates/relayer/src/light_client/tendermint.rs | 108 +++++++++++++----- .../src/light_client/tendermint/detector.rs | 56 ++++++--- 5 files changed, 120 insertions(+), 51 deletions(-) diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 701d61117d..74b74697ee 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -837,7 +837,7 @@ impl ChainEndpoint for CosmosSdkChain { update: &UpdateClient, client_state: &AnyClientState, ) -> Result, Error> { - self.light_client.check_misbehaviour(update, client_state) + self.light_client.detect_misbehaviour(update, client_state) } // Queries diff --git a/crates/relayer/src/error.rs b/crates/relayer/src/error.rs index bab49bee59..973e802e6c 100644 --- a/crates/relayer/src/error.rs +++ b/crates/relayer/src/error.rs @@ -114,7 +114,6 @@ define_error! { [ LightClientBuilderError ] |_| { "light client builder error" }, - LightClientVerification { chain_id: String } [ LightClientError ] diff --git a/crates/relayer/src/light_client.rs b/crates/relayer/src/light_client.rs index 8e337046fd..b63f67ad51 100644 --- a/crates/relayer/src/light_client.rs +++ b/crates/relayer/src/light_client.rs @@ -53,8 +53,8 @@ pub trait LightClient: Send + Sync { ) -> Result, error::Error>; /// Given a client update event that includes the header used in a client update, - /// look for misbehaviour by fetching a header at same or latest height. - fn check_misbehaviour( + /// run the light client attack detector. + fn detect_misbehaviour( &mut self, update: &UpdateClient, client_state: &AnyClientState, diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index e3baa7758b..c7678e005a 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -1,8 +1,7 @@ -#![allow(unused)] - mod detector; use itertools::Itertools; +use tracing::{debug, error, trace, warn}; use tendermint_light_client::{ components::{self, io::AtHeight}, @@ -10,15 +9,13 @@ use tendermint_light_client::{ state::State as LightClientState, store::{memory::MemoryStore, LightStore}, }; -use tendermint_light_client_verifier::options::Options as TmOptions; use tendermint_light_client_verifier::types::{Height as TMHeight, LightBlock, PeerId, Status}; use tendermint_light_client_verifier::ProdVerifier; use tendermint_rpc as rpc; use ibc_relayer_types::{ clients::ics07_tendermint::{ - header::{headers_compatible, Header as TmHeader}, - misbehaviour::Misbehaviour as TmMisbehaviour, + header::Header as TmHeader, misbehaviour::Misbehaviour as TmMisbehaviour, }, core::{ ics02_client::{client_type::ClientType, events::UpdateClient, header::downcast_header}, @@ -26,11 +23,13 @@ use ibc_relayer_types::{ }, downcast, Height as ICSHeight, }; -use tracing::trace; use crate::{ - chain::cosmos::CosmosSdkChain, client_state::AnyClientState, config::ChainConfig, error::Error, - misbehaviour::MisbehaviourEvidence, + chain::cosmos::CosmosSdkChain, + client_state::AnyClientState, + config::ChainConfig, + error::Error, + misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}, }; use super::Verified; @@ -96,7 +95,7 @@ impl super::LightClient for LightClient { } /// Perform misbehavior detection on the given client state and update client event. - fn check_misbehaviour( + fn detect_misbehaviour( &mut self, update: &UpdateClient, client_state: &AnyClientState, @@ -128,41 +127,92 @@ impl super::LightClient for LightClient { let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?; - let latest_chain_height = - ICSHeight::new(self.chain_id.version(), latest_chain_block.height().into()) - .map_err(|_| Error::invalid_height_no_source())?; + // let latest_chain_height = + // ICSHeight::new(self.chain_id.version(), latest_chain_block.height().into()) + // .map_err(|_| Error::invalid_height_no_source())?; - // Set the target height to the minimum between the update height and latest chain height - let target_height = core::cmp::min(update.consensus_height(), latest_chain_height); - let trusted_height = update_header.trusted_height; + // // Set the target height to the minimum between the update height and latest chain height + // let target_height = core::cmp::min(update.consensus_height(), latest_chain_height); + // let trusted_height = update_header.trusted_height; // TODO: Check that a consensus state at trusted_height still exists on-chain, // currently we don't have access to Cosmos chain query from here - if trusted_height >= latest_chain_height { - // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in - // the next iteration. e.g: - // existing consensus states: 1000, 900, 300, 200 (only known by the caller) - // latest_chain_height = 300 - // target_height = 1000 - // trusted_height = 900 - return Ok(None); - } + // if trusted_height >= latest_chain_height { + // // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in + // // the next iteration. e.g: + // // existing consensus states: 1000, 900, 300, 200 (only known by the caller) + // // latest_chain_height = 300 + // // target_height = 1000 + // // trusted_height = 900 + // return Ok(None); + // } + + let next_validators = self + .io + .fetch_validator_set( + AtHeight::At(update_header.signed_header.header.height.increment()), + Some(update_header.signed_header.header.proposer_address), + ) + .map_err(|e| Error::light_client_io(self.chain_id.to_string(), e))?; + + let target_block: LightBlock = LightBlock { + signed_header: update_header.signed_header.clone(), + validators: update_header.validator_set.clone(), + next_validators, + provider: self.peer_id, + }; - let target_block: LightBlock = todo!(); // FIXME: How do I compute this? - let trusted_block = self.fetch(trusted_height)?; // FIXME: Is that ok? let now = latest_chain_block.time(); // FIXME: Is that right? - detector::detect( + let trusted_block = self.fetch(update_header.trusted_height)?; // FIXME: Is that ok? + // TODO: Check validator sets match + + let attack = detector::detect( self.peer_id, self.rpc_client.clone(), target_block, - trusted_block, + trusted_block.clone(), client_state, now, ); - todo!() + dbg!(&attack); + + match attack { + Ok(None) => { + debug!("no misbehavior detected"); + Ok(None) + } + Ok(Some(attack)) => { + warn!("misbehavior detected, reporting evidence to RPC witness node and primary chain"); + + match detector::report_evidence(self.rpc_client.clone(), attack.clone()) { + Ok(hash) => warn!("evidence reported to RPC witness node with hash: {hash}"), + Err(e) => error!("failed to report evidence to RPC witness node: {}", e), + } + + let evidence = MisbehaviourEvidence { + misbehaviour: AnyMisbehaviour::Tendermint(TmMisbehaviour { + client_id: update.client_id().clone(), + header1: update_header.clone(), + header2: TmHeader { + signed_header: attack.conflicting_block.signed_header, + validator_set: attack.conflicting_block.validator_set, + trusted_height: update_header.trusted_height, + trusted_validator_set: trusted_block.next_validators, + }, + }), + supporting_headers: vec![], // FIXME: What do we put here? + }; + + Ok(Some(evidence)) + } + Err(e) => { + error!("could not detect misbehavior: {}", e); + Err(e) + } + } } } diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index 406536425f..d75620d37c 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -1,17 +1,20 @@ -use ibc_relayer_types::{ - clients::ics07_tendermint::client_state::ClientState, core::ics24_host::identifier::ChainId, - Height, +use tracing::{error, info}; + +use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState; +use tendermint::{ + evidence::{Evidence, LightClientAttackEvidence}, + Hash, Time, }; -use tendermint::{evidence::LightClientAttackEvidence, hash::Hash, Time}; use tendermint_light_client::{ builder::LightClientBuilder, - light_client::Options, + components::{clock::FixedClock, io::ProdIo, scheduler}, misbehavior::{detect_divergence, Provider}, - store::{memory::MemoryStore, LightStore}, - types::{LightBlock, PeerId, Status}, + predicates::ProdPredicates, + store::memory::MemoryStore, + types::{LightBlock, PeerId}, }; +use tendermint_light_client_verifier::ProdVerifier; use tendermint_rpc::{Client, HttpClient}; -use tracing::{error, info}; use crate::{error::Error, util::block_on}; @@ -25,14 +28,13 @@ pub fn detect( ) -> Result, Error> { let primary_trace = vec![trusted_block.clone(), target_block]; let options = client_state.as_light_client_options(); - let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block)?; + let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block, now)?; let evidence = block_on(detect_divergence( &mut provider, primary_trace, options.clock_drift, options.trusting_period, - now, )); match evidence { @@ -68,17 +70,26 @@ fn make_provider( rpc_client: HttpClient, client_state: &ClientState, trusted_block: LightBlock, + now: Time, ) -> Result { - let mut light_store = Box::new(MemoryStore::new()); - light_store.insert(trusted_block, Status::Trusted); - let options = client_state.as_light_client_options(); + let light_store = Box::new(MemoryStore::new()); - let instance = - LightClientBuilder::prod(peer_id, rpc_client.clone(), light_store, options, None) - .trust_from_store() - .map_err(Error::light_client_builder)? - .build(); + let builder = LightClientBuilder::custom( + peer_id, + options, + light_store, + Box::new(ProdIo::new(peer_id, rpc_client.clone(), None)), + Box::new(FixedClock::new(now)), + Box::::default(), + Box::new(scheduler::basic_bisecting_schedule), + Box::new(ProdPredicates), + ); + + let instance = builder + .trust_light_block(trusted_block) + .map_err(Error::light_client_builder)? + .build(); Ok(Provider::new( client_state.chain_id.to_string(), @@ -86,3 +97,12 @@ fn make_provider( rpc_client, )) } + +pub fn report_evidence( + rpc_client: HttpClient, + attack: LightClientAttackEvidence, +) -> Result { + block_on(rpc_client.broadcast_evidence(Evidence::from(attack))) + .map(|response| response.hash) + .map_err(|e| Error::rpc_response(e.to_string())) +} From 199ce6c84640f74fa15466c12aa4decf76545ea3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 30 Mar 2023 09:59:26 +0200 Subject: [PATCH 10/40] Fix client updates --- crates/relayer/src/light_client/tendermint.rs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index c7678e005a..807b3274ad 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -55,17 +55,19 @@ impl super::LightClient for LightClient { fn verify( &mut self, - trusted: ICSHeight, - target: ICSHeight, + trusted_height: ICSHeight, + target_height: ICSHeight, client_state: &AnyClientState, ) -> Result, Error> { - trace!(%trusted, %target, "light client verification"); - - let target_height = - TMHeight::try_from(target.revision_height()).map_err(Error::invalid_height)?; + trace!(%trusted_height, %target_height, "light client verification"); let client = self.prepare_client(client_state)?; - let mut state = self.prepare_state(trusted)?; + let mut state = self.prepare_state(trusted_height)?; + + let target_height = + TMHeight::try_from(target_height.revision_height()).map_err(Error::invalid_height)?; + let trusted_height = + TMHeight::try_from(trusted_height.revision_height()).map_err(Error::invalid_height)?; // Verify the target header let target = client @@ -75,10 +77,11 @@ impl super::LightClient for LightClient { // Collect the verification trace for the target block let target_trace = state.get_trace(target.height()); - // Compute the minimal supporting set, sorted by ascending height + // Compute the minimal supporting set, sorted by ascending height, + // skip the target header and the trusted header if present in the trace let supporting = target_trace .into_iter() - .filter(|lb| lb.height() != target.height()) + .filter(|lb| lb.height() != target.height() && lb.height() != trusted_height) .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) .collect_vec(); From e92b04070a5e3e49c37a2823effff5c74638293b Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 30 Mar 2023 10:38:01 +0200 Subject: [PATCH 11/40] It's working, I think --- crates/relayer/src/light_client/tendermint.rs | 41 ++++++------------- .../src/light_client/tendermint/detector.rs | 12 +++--- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 807b3274ad..9d57399120 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -6,6 +6,7 @@ use tracing::{debug, error, trace, warn}; use tendermint_light_client::{ components::{self, io::AtHeight}, light_client::LightClient as TmLightClient, + misbehavior::Divergence, state::State as LightClientState, store::{memory::MemoryStore, LightStore}, }; @@ -130,27 +131,6 @@ impl super::LightClient for LightClient { let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?; - // let latest_chain_height = - // ICSHeight::new(self.chain_id.version(), latest_chain_block.height().into()) - // .map_err(|_| Error::invalid_height_no_source())?; - - // // Set the target height to the minimum between the update height and latest chain height - // let target_height = core::cmp::min(update.consensus_height(), latest_chain_height); - // let trusted_height = update_header.trusted_height; - - // TODO: Check that a consensus state at trusted_height still exists on-chain, - // currently we don't have access to Cosmos chain query from here - - // if trusted_height >= latest_chain_height { - // // Can happen with multiple FLA attacks, we return no evidence and hope to catch this in - // // the next iteration. e.g: - // // existing consensus states: 1000, 900, 300, 200 (only known by the caller) - // // latest_chain_height = 300 - // // target_height = 1000 - // // trusted_height = 900 - // return Ok(None); - // } - let next_validators = self .io .fetch_validator_set( @@ -171,7 +151,7 @@ impl super::LightClient for LightClient { let trusted_block = self.fetch(update_header.trusted_height)?; // FIXME: Is that ok? // TODO: Check validator sets match - let attack = detector::detect( + let divergence = detector::detect( self.peer_id, self.rpc_client.clone(), target_block, @@ -180,17 +160,20 @@ impl super::LightClient for LightClient { now, ); - dbg!(&attack); + dbg!(&divergence); - match attack { + match divergence { Ok(None) => { debug!("no misbehavior detected"); Ok(None) } - Ok(Some(attack)) => { + Ok(Some(Divergence { + evidence, + challenging_block, + })) => { warn!("misbehavior detected, reporting evidence to RPC witness node and primary chain"); - match detector::report_evidence(self.rpc_client.clone(), attack.clone()) { + match detector::report_evidence(self.rpc_client.clone(), evidence) { Ok(hash) => warn!("evidence reported to RPC witness node with hash: {hash}"), Err(e) => error!("failed to report evidence to RPC witness node: {}", e), } @@ -200,10 +183,10 @@ impl super::LightClient for LightClient { client_id: update.client_id().clone(), header1: update_header.clone(), header2: TmHeader { - signed_header: attack.conflicting_block.signed_header, - validator_set: attack.conflicting_block.validator_set, + signed_header: challenging_block.signed_header, + validator_set: challenging_block.validators, trusted_height: update_header.trusted_height, - trusted_validator_set: trusted_block.next_validators, + trusted_validator_set: trusted_block.validators, }, }), supporting_headers: vec![], // FIXME: What do we put here? diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index d75620d37c..cca347fdcc 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -8,7 +8,7 @@ use tendermint::{ use tendermint_light_client::{ builder::LightClientBuilder, components::{clock::FixedClock, io::ProdIo, scheduler}, - misbehavior::{detect_divergence, Provider}, + misbehavior::{detect_divergence, Divergence, Provider}, predicates::ProdPredicates, store::memory::MemoryStore, types::{LightBlock, PeerId}, @@ -25,19 +25,19 @@ pub fn detect( trusted_block: LightBlock, client_state: &ClientState, now: Time, -) -> Result, Error> { +) -> Result, Error> { let primary_trace = vec![trusted_block.clone(), target_block]; let options = client_state.as_light_client_options(); let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block, now)?; - let evidence = block_on(detect_divergence( + let divergence = block_on(detect_divergence( &mut provider, primary_trace, options.clock_drift, options.trusting_period, )); - match evidence { + match divergence { Ok(None) => { info!( "No evidence of misbehavior detected for chain {}", @@ -46,13 +46,13 @@ pub fn detect( Ok(None) } - Ok(Some(evidence)) => { + Ok(Some(divergence)) => { info!( "Evidence of misbehavior detected for chain {}", client_state.chain_id ); - Ok(Some(evidence)) + Ok(Some(divergence)) } Err(e) => { error!( From 63072171649aa215259669da6c463aba9a28fcf3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 30 Mar 2023 16:45:44 +0200 Subject: [PATCH 12/40] Move create_fork.sh to scripts folder --- create_fork.sh => scripts/create_fork.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename create_fork.sh => scripts/create_fork.sh (100%) diff --git a/create_fork.sh b/scripts/create_fork.sh similarity index 100% rename from create_fork.sh rename to scripts/create_fork.sh From f7093e89eab8c5d634ed2ed33ae2ac6f6eb290a6 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 4 Apr 2023 15:35:24 +0200 Subject: [PATCH 13/40] Use tendermint-rs branch --- Cargo.lock | 7 +++++++ Cargo.toml | 12 ++++++------ crates/relayer/src/light_client/tendermint.rs | 2 +- .../relayer/src/light_client/tendermint/detector.rs | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8984b2346e..51dfaaa6b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3991,6 +3991,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "bytes", "digest 0.10.6", @@ -4020,6 +4021,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "flex-error", "serde", @@ -4032,6 +4034,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4054,6 +4057,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "derive_more", "flex-error", @@ -4065,6 +4069,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "bytes", "flex-error", @@ -4081,6 +4086,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "async-trait", "async-tungstenite", @@ -4114,6 +4120,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/Cargo.toml b/Cargo.toml index 4c05167273..f0cb443696 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ members = [ [patch.crates-io] # ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs.git", branch = "main" } -tendermint = { path = "../tendermint-rs/tendermint" } -tendermint-rpc = { path = "../tendermint-rs/rpc" } -tendermint-proto = { path = "../tendermint-rs/proto" } -tendermint-light-client = { path = "../tendermint-rs/light-client" } -tendermint-light-client-verifier = { path = "../tendermint-rs/light-client-verifier" } -tendermint-testgen = { path = "../tendermint-rs/testgen" } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-light-client = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 9d57399120..4973687ee6 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -5,8 +5,8 @@ use tracing::{debug, error, trace, warn}; use tendermint_light_client::{ components::{self, io::AtHeight}, + detector::Divergence, light_client::LightClient as TmLightClient, - misbehavior::Divergence, state::State as LightClientState, store::{memory::MemoryStore, LightStore}, }; diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index cca347fdcc..2caebda0f0 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -8,7 +8,7 @@ use tendermint::{ use tendermint_light_client::{ builder::LightClientBuilder, components::{clock::FixedClock, io::ProdIo, scheduler}, - misbehavior::{detect_divergence, Divergence, Provider}, + detector::{detect_divergence, Divergence, Provider}, predicates::ProdPredicates, store::memory::MemoryStore, types::{LightBlock, PeerId}, From b0460643c6e1a13bec7cc58fbf9f9904d2160295 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 11 Apr 2023 13:38:15 +0200 Subject: [PATCH 14/40] Use new light client detector crate --- Cargo.lock | 38 +++++++++++++++---- Cargo.toml | 1 + crates/relayer/Cargo.toml | 4 ++ crates/relayer/src/light_client/tendermint.rs | 2 +- .../src/light_client/tendermint/detector.rs | 7 ++-- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51dfaaa6b5..3162352aba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1839,6 +1839,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-light-client", + "tendermint-light-client-detector", "tendermint-light-client-verifier", "tendermint-rpc", "tendermint-testgen", @@ -3991,7 +3992,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "bytes", "digest 0.10.6", @@ -4021,7 +4022,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "flex-error", "serde", @@ -4034,7 +4035,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4054,10 +4055,33 @@ dependencies = [ "tracing", ] +[[package]] +name = "tendermint-light-client-detector" +version = "0.30.0" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#640789e0153e1622063c7ed1ccb89a882c963fe3" +dependencies = [ + "contracts", + "crossbeam-channel 0.4.4", + "derive_more", + "flex-error", + "futures", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "static_assertions", + "tendermint", + "tendermint-light-client", + "tendermint-proto", + "tendermint-rpc", + "time", + "tracing", +] + [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "derive_more", "flex-error", @@ -4069,7 +4093,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#640789e0153e1622063c7ed1ccb89a882c963fe3" dependencies = [ "bytes", "flex-error", @@ -4086,7 +4110,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "async-trait", "async-tungstenite", @@ -4120,7 +4144,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#d4e10f5bf18b4956bba90fa7cdeaca8971761d88" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/Cargo.toml b/Cargo.toml index f0cb443696..a3ccecb492 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,5 @@ tendermint-rpc = { git = "https://github.com/informalsystems/t tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } tendermint-light-client = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +tendermint-light-client-detector = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index a2f00d197c..dc12427986 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -94,6 +94,10 @@ features = ["rpc-client", "secp256k1", "unstable"] version = "0.30.0" default-features = false +[dependencies.tendermint-light-client-detector] +version = "0.30.0" +default-features = false + [dev-dependencies] ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["mocks"] } serial_test = "1.0.0" diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 4973687ee6..01b904a4b2 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -5,11 +5,11 @@ use tracing::{debug, error, trace, warn}; use tendermint_light_client::{ components::{self, io::AtHeight}, - detector::Divergence, light_client::LightClient as TmLightClient, state::State as LightClientState, store::{memory::MemoryStore, LightStore}, }; +use tendermint_light_client_detector::Divergence; use tendermint_light_client_verifier::types::{Height as TMHeight, LightBlock, PeerId, Status}; use tendermint_light_client_verifier::ProdVerifier; use tendermint_rpc as rpc; diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index 2caebda0f0..9d93fcdae9 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -1,6 +1,5 @@ use tracing::{error, info}; -use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState; use tendermint::{ evidence::{Evidence, LightClientAttackEvidence}, Hash, Time, @@ -8,14 +7,16 @@ use tendermint::{ use tendermint_light_client::{ builder::LightClientBuilder, components::{clock::FixedClock, io::ProdIo, scheduler}, - detector::{detect_divergence, Divergence, Provider}, predicates::ProdPredicates, store::memory::MemoryStore, types::{LightBlock, PeerId}, + verifier::ProdVerifier, }; -use tendermint_light_client_verifier::ProdVerifier; +use tendermint_light_client_detector::{detect_divergence, Divergence, Provider}; use tendermint_rpc::{Client, HttpClient}; +use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState; + use crate::{error::Error, util::block_on}; pub fn detect( From b8f47b9071f847aa4a19b4ef4aa8a2ade9ef38ef Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 11 Apr 2023 13:40:04 +0200 Subject: [PATCH 15/40] Remove explicit dependency on `tendermint-light-client-verifier` --- Cargo.lock | 1 - crates/relayer/Cargo.toml | 4 ---- crates/relayer/src/chain/cosmos.rs | 2 +- crates/relayer/src/config.rs | 7 ++++--- crates/relayer/src/light_client/tendermint.rs | 4 ++-- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3162352aba..a635d5ae18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1840,7 +1840,6 @@ dependencies = [ "tendermint", "tendermint-light-client", "tendermint-light-client-detector", - "tendermint-light-client-verifier", "tendermint-rpc", "tendermint-testgen", "test-log", diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index dc12427986..955d4f55f5 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -90,10 +90,6 @@ version = "0.30.0" default-features = false features = ["rpc-client", "secp256k1", "unstable"] -[dependencies.tendermint-light-client-verifier] -version = "0.30.0" -default-features = false - [dependencies.tendermint-light-client-detector] version = "0.30.0" default-features = false diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 74b74697ee..77d1a291c0 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -52,7 +52,7 @@ use ibc_relayer_types::Height as ICSHeight; use tendermint::block::Height as TmHeight; use tendermint::node::{self, info::TxIndexStatus}; -use tendermint_light_client_verifier::types::LightBlock as TmLightBlock; +use tendermint_light_client::verifier::types::LightBlock as TmLightBlock; use tendermint_rpc::client::CompatMode; use tendermint_rpc::endpoint::broadcast::tx_sync::Response; use tendermint_rpc::endpoint::status; diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index ed6146cda9..ba3893a9cf 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -14,12 +14,13 @@ use core::{ time::Duration, }; use std::{fs, fs::File, io::Write, path::Path}; -use tendermint_rpc::{Url, WebSocketClientUrl}; -use ibc_proto::google::protobuf::Any; use serde_derive::{Deserialize, Serialize}; -use tendermint_light_client_verifier::types::TrustThreshold; +use tendermint_light_client::verifier::types::TrustThreshold; +use tendermint_rpc::{Url, WebSocketClientUrl}; + +use ibc_proto::google::protobuf::Any; use ibc_relayer_types::core::ics23_commitment::specs::ProofSpecs; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use ibc_relayer_types::timestamp::ZERO_DURATION; diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 01b904a4b2..563c3f1087 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -8,10 +8,10 @@ use tendermint_light_client::{ light_client::LightClient as TmLightClient, state::State as LightClientState, store::{memory::MemoryStore, LightStore}, + verifier::types::{Height as TMHeight, LightBlock, PeerId, Status}, + verifier::ProdVerifier, }; use tendermint_light_client_detector::Divergence; -use tendermint_light_client_verifier::types::{Height as TMHeight, LightBlock, PeerId, Status}; -use tendermint_light_client_verifier::ProdVerifier; use tendermint_rpc as rpc; use ibc_relayer_types::{ From 0c71c03842c318bfb98692fa4ec06277ace3f09c Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 13 Apr 2023 12:46:13 +0200 Subject: [PATCH 16/40] Update to latest detector --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a635d5ae18..4bc1da5bb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3991,7 +3991,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "bytes", "digest 0.10.6", @@ -4021,7 +4021,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "flex-error", "serde", @@ -4034,7 +4034,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4057,7 +4057,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#640789e0153e1622063c7ed1ccb89a882c963fe3" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4080,7 +4080,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "derive_more", "flex-error", @@ -4092,7 +4092,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#640789e0153e1622063c7ed1ccb89a882c963fe3" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "bytes", "flex-error", @@ -4109,7 +4109,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "async-trait", "async-tungstenite", @@ -4143,7 +4143,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f7683646b4e438fcd055d9137ad4811c9ddc89d7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#6b33ad2901757eae11ae1d813ba42a9d88b03724" dependencies = [ "ed25519-consensus", "gumdrop", From 22229c5582f5764769c66f83cca80f7192dbeda6 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 13 Apr 2023 14:10:03 +0200 Subject: [PATCH 17/40] Add integration test for misbehavior detection --- .github/workflows/misbehaviour.yml | 96 ++++++ ci/misbehaviour/.gitignore | 1 + ci/misbehaviour/config.toml | 325 ++++++++++++++++++ .../misbehaviour/config_fork.toml | 0 {scripts => ci/misbehaviour}/create_fork.sh | 9 +- ci/misbehaviour/misbehaviour_test.sh | 61 ++++ scripts/dev-env | 26 +- scripts/setup-chains | 21 +- 8 files changed, 522 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/misbehaviour.yml create mode 100644 ci/misbehaviour/.gitignore create mode 100644 ci/misbehaviour/config.toml rename config_fork.toml => ci/misbehaviour/config_fork.toml (100%) rename {scripts => ci/misbehaviour}/create_fork.sh (80%) create mode 100755 ci/misbehaviour/misbehaviour_test.sh diff --git a/.github/workflows/misbehaviour.yml b/.github/workflows/misbehaviour.yml new file mode 100644 index 0000000000..ae83ef0338 --- /dev/null +++ b/.github/workflows/misbehaviour.yml @@ -0,0 +1,96 @@ +name: Misbehaviour +on: + pull_request: + paths: + - .github/workflows/misbehaviour.yaml + - Cargo.toml + - Cargo.lock + - flake.nix + - flake.lock + - ci/** + - scripts/** + - crates/** + push: + branches: master + paths: + - .github/workflows/misbehaviour.yaml + - Cargo.toml + - Cargo.lock + - flake.nix + - flake.lock + - ci/** + - scripts/** + - crates/** + +env: + CARGO_INCREMENTAL: 0 + CARGO_PROFILE_DEV_DEBUG: 1 + CARGO_PROFILE_RELEASE_DEBUG: 1 + RUST_BACKTRACE: short + CARGO_NET_RETRY: 10 + RUSTUP_MAX_RETRIES: 10 + +# Cancel previous runs of this workflow when a new commit is added to the PR, branch or tag +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + misbehaviour: + runs-on: ubuntu-20.04 + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + chain: + - package: gaia8 + command: gaiad + account_prefix: cosmos + - package: gaia9 + command: gaiad + account_prefix: cosmos + steps: + - uses: actions/checkout@v2 + - name: Install Nix + uses: cachix/install-nix-action@v20 + with: + extra_nix_config: | + experimental-features = nix-command flakes + - name: Use cachix cache + uses: cachix/cachix-action@v12 + with: + name: cosmos + - name: Install sconfig + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/sconfig + platform: linux + arch: amd64 + extension-matching: disable + rename-to: sconfig + chmod: 0755 + - name: Install stoml + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/stoml + platform: linux + arch: amd64 + extension-matching: disable + rename-to: stoml + chmod: 0755 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Use Rust cache + uses: Swatinem/rust-cache@v1 + - name: Build Hermes + uses: actions-rs/cargo@v1 + with: + command: build + - name: Run test + working-directory: ci/misbehaviour + run: | + nix shell .#${{ matrix.chain.package }} -c bash misbehaviour_test.sh + diff --git a/ci/misbehaviour/.gitignore b/ci/misbehaviour/.gitignore new file mode 100644 index 0000000000..1269488f7f --- /dev/null +++ b/ci/misbehaviour/.gitignore @@ -0,0 +1 @@ +data diff --git a/ci/misbehaviour/config.toml b/ci/misbehaviour/config.toml new file mode 100644 index 0000000000..70ff26f9a3 --- /dev/null +++ b/ci/misbehaviour/config.toml @@ -0,0 +1,325 @@ +# The global section has parameters that apply globally to the relayer operation. +[global] + +# Specify the verbosity for the relayer logging output. Default: 'info' +# Valid options are 'error', 'warn', 'info', 'debug', 'trace'. +log_level = 'debug' + + +# Specify the mode to be used by the relayer. [Required] +[mode] + +# Specify the client mode. +[mode.clients] + +# Whether or not to enable the client workers. [Required] +enabled = true + +# Whether or not to enable periodic refresh of clients. [Default: true] +# This feature only applies to clients that underlie an open channel. +# For Tendermint clients, the frequency at which Hermes refreshes them is 2/3 of their +# trusting period (e.g., refresh every ~9 days if the trusting period is 14 days). +# Note: Even if this is disabled, clients will be refreshed automatically if +# there is activity on a connection or channel they are involved with. +refresh = true + +# Whether or not to enable misbehaviour detection for clients. [Default: false] +misbehaviour = true + +# Specify the connections mode. +[mode.connections] + +# Whether or not to enable the connection workers for handshake completion. [Required] +enabled = true + +# Specify the channels mode. +[mode.channels] + +# Whether or not to enable the channel workers for handshake completion. [Required] +enabled = true + +# Specify the packets mode. +[mode.packets] + +# Whether or not to enable the packet workers. [Required] +enabled = true + +# Parametrize the periodic packet clearing feature. +# Interval (in number of blocks) at which pending packets +# should be periodically cleared. A value of '0' will disable +# periodic packet clearing. [Default: 100] +clear_interval = 100 + +# Whether or not to clear packets on start. [Default: true] +clear_on_start = true + +# Toggle the transaction confirmation mechanism. +# The tx confirmation mechanism periodically queries the `/tx_search` RPC +# endpoint to check that previously-submitted transactions +# (to any chain in this config file) have been successfully delivered. +# If they have not been, and `clear_interval = 0`, then those packets are +# queued up for re-submission. +# If set to `false`, the following telemetry metrics will be disabled: +# `acknowledgment_packets_confirmed`, `receive_packets_confirmed` and `timeout_packets_confirmed`. +# [Default: false] +tx_confirmation = false + +# Auto register the counterparty payee on a destination chain to +# the relayer's address on the source chain. This can be used +# for simple configuration of the relayer to receive fees for +# relaying RecvPacket on fee-enabled channels. +# For more complex configuration, turn this off and use the CLI +# to manually register the payee addresses. +# [Default: false] +auto_register_counterparty_payee = false + +# The REST section defines parameters for Hermes' built-in RESTful API. +# https://hermes.informal.systems/rest.html +[rest] + +# Whether or not to enable the REST service. Default: false +enabled = false + +# Specify the IPv4/6 host over which the built-in HTTP server will serve the RESTful +# API requests. Default: 127.0.0.1 +host = '127.0.0.1' + +# Specify the port over which the built-in HTTP server will serve the restful API +# requests. Default: 3000 +port = 3000 + + +# The telemetry section defines parameters for Hermes' built-in telemetry capabilities. +# https://hermes.informal.systems/telemetry.html +[telemetry] + +# Whether or not to enable the telemetry service. Default: false +enabled = false + +# Specify the IPv4/6 host over which the built-in HTTP server will serve the metrics +# gathered by the telemetry service. Default: 127.0.0.1 +host = '127.0.0.1' + +# Specify the port over which the built-in HTTP server will serve the metrics gathered +# by the telemetry service. Default: 3001 +port = 3001 + + +# A chains section includes parameters related to a chain and the full node to which +# the relayer can send transactions and queries. +[[chains]] + +# Specify the chain ID. Required +id = 'ibc-0' + +# Specify the RPC address and port where the chain RPC server listens on. Required +rpc_addr = 'http://127.0.0.1:26657' + +# Specify the GRPC address and port where the chain GRPC server listens on. Required +grpc_addr = 'http://127.0.0.1:9090' + +# Specify the WebSocket address and port where the chain WebSocket server +# listens on. Required +websocket_addr = 'ws://127.0.0.1:26657/websocket' + +# Specify the maximum amount of time (duration) that the RPC requests should +# take before timing out. Default: 10s (10 seconds) +# Note: Hermes uses this parameter _only_ in `start` mode; for all other CLIs, +# Hermes uses a large preconfigured timeout (on the order of minutes). +rpc_timeout = '10s' + +# Specify the prefix used by the chain. Required +account_prefix = 'cosmos' + +# Specify the name of the private key to use for signing transactions. Required +# See the Adding Keys chapter for more information about managing signing keys: +# https://hermes.informal.systems/commands/keys/index.html#adding-keys +key_name = 'testkey' + +# Specify the address type which determines: +# 1) address derivation; +# 2) how to retrieve and decode accounts and pubkeys; +# 3) the message signing method. +# The current configuration options are for Cosmos SDK and Ethermint. +# +# Example configuration for chains based on Ethermint library: +# +# address_type = { derivation = 'ethermint', proto_type = { pk_type = '/ethermint.crypto.v1.ethsecp256k1.PubKey' } } +# +# Default: { derivation = 'cosmos' }, i.e. address derivation as in Cosmos SDK. +# Warning: This is an advanced feature! Modify with caution. +address_type = { derivation = 'cosmos' } + +# Specify the store prefix used by the on-chain IBC modules. Required +# Recommended value for Cosmos SDK: 'ibc' +store_prefix = 'ibc' + +# Gas Parameters +# +# The term 'gas' is used to denote the amount of computation needed to execute +# and validate a transaction on-chain. It can be thought of as fuel that gets +# spent in order to power the on-chain execution of a transaction. +# +# Hermes attempts to simulate how much gas a transaction will expend on its +# target chain. From that, it calculates the cost of that gas by multiplying the +# amount of estimated gas by the `gas_multiplier` and the `gas_price` +# (estimated gas * `gas_multiplier` * `gas_price`) in order to compute the +# total fee to be deducted from the relayer's wallet. +# +# The `simulate_tx` operation does not always correctly estimate the appropriate +# amount of gas that a transaction requires. In those cases when the operation +# fails, Hermes will attempt to submit the transaction using the specified +# `default_gas` and `max_gas` parameters. In the case that a transaction would +# require more than `max_gas`, it doesn't get submitted and a +# `TxSimulateGasEstimateExceeded` error is returned. + +# Specify the default amount of gas to be used in case the tx simulation fails, +# and Hermes cannot estimate the amount of gas needed. +# Default: 100 000 +default_gas = 100000 + +# Specify the maximum amount of gas to be used as the gas limit for a transaction. +# If `default_gas` is unspecified, then `max_gas` will be used as `default_gas`. +# Default: 400 000 +max_gas = 400000 + +# Specify the price per gas used of the fee to submit a transaction and +# the denomination of the fee. +# +# The specified gas price should always be greater or equal to the `min-gas-price` +# configured on the chain. This is to ensure that at least some minimal price is +# paid for each unit of gas per transaction. +# +# Required +gas_price = { price = 0.001, denom = 'stake' } + +# Multiply this amount with the gas estimate, used to compute the fee +# and account for potential estimation error. +# +# The purpose of multiplying by `gas_multiplier` is to provide a bit of a buffer +# to catch some of the cases when the gas estimation calculation is on the low +# end. +# +# Example: With this setting set to 1.1, then if the estimated gas +# is 80_000, then gas used to compute the fee will be adjusted to +# 80_000 * 1.1 = 88_000. +# +# Default: 1.1, ie. the gas is increased by 10% +# Minimum value: 1.0 +gas_multiplier = 1.1 + +# Specify how many IBC messages at most to include in a single transaction. +# Default: 30 +max_msg_num = 30 + +# Specify the maximum size, in bytes, of each transaction that Hermes will submit. +# Default: 2097152 (2 MiB) +max_tx_size = 2097152 + +# Specify the maximum amount of time to tolerate a clock drift. +# The clock drift parameter defines how much new (untrusted) header's time +# can drift into the future. Default: 5s +clock_drift = '5s' + +# Specify the maximum time per block for this chain. +# The block time together with the clock drift are added to the source drift to estimate +# the maximum clock drift when creating a client on this chain. Default: 30s +# For cosmos-SDK chains a good approximation is `timeout_propose` + `timeout_commit` +# Note: This MUST be the same as the `max_expected_time_per_block` genesis parameter for Tendermint chains. +max_block_time = '30s' + +# Specify the amount of time to be used as the light client trusting period. +# It should be significantly less than the unbonding period +# (e.g. unbonding period = 3 weeks, trusting period = 2 weeks). +# Default: 2/3 of the `unbonding period` for Cosmos SDK chains +trusting_period = '14days' + +# Unbonding period for this chain. +# Required for ICS consumer chains, as they currently do not expose the staking module. +# WARNING: Only specifiy this for ICS consumer chain, but NOT for any other type of chain. +# For other chains, this is fetched via gRPC from the staking parameters. +unbonding_period = '21days' + +# Specify the trust threshold for the light client, ie. the minimum fraction of validators +# which must overlap across two blocks during light client verification. +# Default: { numerator = '2', denominator = '3' }, ie. 2/3. +# Warning: This is an advanced feature! Modify with caution. +trust_threshold = { numerator = '2', denominator = '3' } + +# Specify a string that Hermes will use as a memo for each transaction it submits +# to this chain. The string is limited to 50 characters. Default: '' (empty). +# Note: Hermes will append to the string defined here additional +# operational debugging information, e.g., relayer build version. +memo_prefix = '' + +# This section specifies the filters for policy based relaying. +# +# Default: no policy / filters, allow all packets on all channels. +# +# Only packet filtering based on channel identifier can be specified. +# A channel filter has two fields: +# 1. `policy` - one of two types are supported: +# - 'allow': permit relaying _only on_ the port/channel id in the list below, +# - 'deny': permit relaying on any channel _except for_ the list below. +# 2. `list` - the list of channels specified by the port and channel identifiers. +# Optionally, each element may also contains wildcards, for eg. 'ica*' +# to match all identifiers starting with 'ica' or '*' to match all identifiers. +# +# Example configuration of a channel filter, only allowing packet relaying on +# channel with port ID 'transfer' and channel ID 'channel-0', as well as on +# all ICA channels. +# +# [chains.packet_filter] +# policy = 'allow' +# list = [ +# ['ica*', '*'], +# ['transfer', 'channel-0'], +# ] + +# This section specifies the filters for incentivized packet relaying. +# Default: no filters, will relay all packets even if they +# are not incentivized. +# +# It is possible to specify the channel or use wildcards for the +# channels. +# The only fee which can be parametrized is the `recv_fee`. +# +# Example configuration of a filter which will only relay incentivized +# packets, with no regards for channel and amount. +# +# [chains.packet_filter.min_fees.'*'] +# recv = [ { amount = 0 } ] +# +# Example configuration of a filter which will only relay packets if they are +# from the channel 'channel-0', and they have a `recv_fee` of at least 20 stake +# or 10 uatom. +# +# [chains.packet_filter.min_fees.'channel-0'] +# recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] + +# Specify that the transaction fees should be payed from this fee granter's account. +# Optional. If unspecified (the default behavior), then no fee granter is used, and +# the account specified in `key_name` will pay the tx fees for all transactions +# submitted to this chain. +# fee_granter = '' + +[[chains]] +id = 'ibc-1' +rpc_addr = 'http://127.0.0.1:26557' +grpc_addr = 'http://127.0.0.1:9091' +websocket_addr = 'ws://127.0.0.1:26557/websocket' +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +default_gas = 100000 +max_gas = 400000 +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.1 +max_msg_num = 30 +max_tx_size = 2097152 +clock_drift = '5s' +max_block_time = '30s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'cosmos' } diff --git a/config_fork.toml b/ci/misbehaviour/config_fork.toml similarity index 100% rename from config_fork.toml rename to ci/misbehaviour/config_fork.toml diff --git a/scripts/create_fork.sh b/ci/misbehaviour/create_fork.sh similarity index 80% rename from scripts/create_fork.sh rename to ci/misbehaviour/create_fork.sh index d458b95cba..66092298d0 100755 --- a/scripts/create_fork.sh +++ b/ci/misbehaviour/create_fork.sh @@ -4,11 +4,9 @@ set -euo pipefail # --- Variables --- -HERMES="cargo run -q --" +HERMES="cargo run --bin hermes -q --" -# IBC_0_RPC_PORT=26657 IBC_1_RPC_PORT=26557 -IBC_1_COMMIT_FILE="data/ibc-1-commit.json" # --- Helpers --- @@ -37,11 +35,6 @@ fi # --- Main --- -info "Fetching the latest block height and hash from ibc-1..." -curl -s "localhost:$IBC_1_RPC_PORT/commit" | \ - jq "{height: .result.signed_header.header.height, hash: .result.signed_header.commit.block_id.hash}" | \ - tee "$IBC_1_COMMIT_FILE" - info "Creating new channel between ibc-0 and ibc-1..." $HERMES --config config.toml create channel --a-chain ibc-0 --b-chain ibc-1 --a-port transfer --b-port transfer --new-client-connection --yes diff --git a/ci/misbehaviour/misbehaviour_test.sh b/ci/misbehaviour/misbehaviour_test.sh new file mode 100755 index 0000000000..5bf84af92e --- /dev/null +++ b/ci/misbehaviour/misbehaviour_test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# --- Variables --- + +HERMES="cargo run --bin hermes -q --" +DEV_ENV="../../scripts/dev-env" + +IBC_1_RPC_PORT=26557 + +# --- Helpers --- + +warn() { + echo "WARNING: $*" +} + +info() { + echo "❯ $*" +} + +# --- Main --- + +info "Starting chains" +"$DEV_ENV" config.toml ibc-0 ibc-1 --non-interactive + +info "Waiting for the chains to produce a few blocks..." +sleep 10 + +info "Creating forked chain ibc-1-f" +bash ./create_fork.sh + +info "Starting Hermes for ibc-0 and ibc-1" +$HERMES --config config.toml start > hermes.log 2>&1 & +HERMES_PID=$! + +info "Waiting for Hermes to start" +sleep 10 + +info "Update client on ibc-0 against the forked chain ibc-1-f" +$HERMES --config config_fork.toml update client --client 07-tendermint-0 --host-chain ibc-0 + +info "Wait for chain ibc-1 to stop..." +sleep 5 + +info "Killing Hermes" +kill -9 "$HERMES_PID" + +STOPPED_HEIGHT="$(curl -s http://localhost:$IBC_1_RPC_PORT/status | jq -r .result.sync_info.latest_block_height)" + +info "Chain ibc-1 stopped at height $STOPPED_HEIGHT" + +info "Fetch evidence from block $STOPPED_HEIGHT on ibc-1" +EVIDENCE="$(curl -s http://localhost:$IBC_1_RPC_PORT/block?height=$STOPPED_HEIGHT | jq .result.block.evidence)" + +info "Found evidence at height $STOPPED_HEIGHT: $EVIDENCE" + +if [ "$EVIDENCE" = "null" ]; then + warn "No evidence found in the latest block on ibc-1" + exit 1 +fi diff --git a/scripts/dev-env b/scripts/dev-env index eeb3dd87ba..15026cece5 100755 --- a/scripts/dev-env +++ b/scripts/dev-env @@ -1,7 +1,7 @@ #!/bin/bash -e usage() { - echo "Usage: $0 CONFIG_FILE CHAIN_0_ID CHAIN_1_ID [CHAIN_2_ID]" + echo "Usage: $0 CONFIG_FILE CHAIN_0_ID CHAIN_1_ID [CHAIN_2_ID] [--non-interactive]" echo "Example: $0 ./config.toml ibc-0 ibc-1 ibc-2" exit 1 } @@ -23,19 +23,35 @@ if [ -z "$3" ]; then missing "CHAIN_1_ID" fi - -if [ "$#" -gt 4 ]; then +if [ "$#" -gt 5 ]; then echo "Incorrect number of parameters." usage fi +NON_INTERACTIVE="" + +if [ "$#" -eq 4 ]; then + if [ "$4" == "--non-interactive" ]; then + NON_INTERACTIVE="--non-interactive" + else + CHAIN_2_ID="$4" + fi +fi + +if [ "$#" -eq 5 ]; then + CHAIN_2_ID="$4" + + if [ "$5" == "--non-interactive" ]; then + NON_INTERACTIVE="--non-interactive" + fi +fi + CONFIG_FILE="$1" CHAIN_0_ID="$2" CHAIN_1_ID="$3" -CHAIN_2_ID="$4" SETUP_CHAINS="$(dirname "$0")/setup-chains" INIT_CLIENTS="$(dirname "$0")/init-hermes" -"$SETUP_CHAINS" "$CHAIN_0_ID" "$CHAIN_1_ID" "$CHAIN_2_ID" +"$SETUP_CHAINS" "$CHAIN_0_ID" "$CHAIN_1_ID" "$CHAIN_2_ID" "$NON_INTERACTIVE" "$INIT_CLIENTS" "$CONFIG_FILE" "$CHAIN_0_ID" "$CHAIN_1_ID" "$CHAIN_2_ID" diff --git a/scripts/setup-chains b/scripts/setup-chains index a95e84db3d..85d9139972 100755 --- a/scripts/setup-chains +++ b/scripts/setup-chains @@ -3,7 +3,7 @@ # Copied from https://github.com/cosmos/relayer and modified to initialize Gaia chains. usage() { - echo "Usage: $0 CHAIN_0_ID CHAIN_1_ID [CHAIN_2_ID]" + echo "Usage: $0 CHAIN_0_ID CHAIN_1_ID [CHAIN_2_ID] [--non-interactive]" echo "Example: $0 ibc-0 ibc-1 ibc-2" exit 1 } @@ -21,12 +21,25 @@ if [ -z "$2" ]; then missing "CHAIN_1_ID" fi - -if [ "$#" -gt 3 ]; then +if [ "$#" -gt 4 ]; then echo "Incorrect number of parameters." usage fi +NON_INTERACTIVE=false + +if [ "$#" -eq 3 ]; then + if [ "$3" == "--non-interactive" ]; then + NON_INTERACTIVE=true + fi +fi + +if [ "$#" -eq 4 ]; then + if [ "$4" == "--non-interactive" ]; then + NON_INTERACTIVE=true + fi +fi + CHAIN_0_ID="$1" CHAIN_1_ID="$2" CHAIN_2_ID="$3" @@ -34,7 +47,7 @@ CHAIN_2_ID="$3" GAIA_DATA="$(pwd)/data" # Ensure user understands what will be deleted -if [[ -d $GAIA_DATA ]] && [[ ! "$3" == "skip" ]]; then +if [[ -d $GAIA_DATA ]] && [[ $NON_INTERACTIVE == false ]]; then echo "WARNING: $0 will DELETE the '$(pwd)/data' folder." read -p "> Do you wish to continue? (y/n): " -n 1 -r echo From 84ed103a461b0bfcc84ce1430f8276d50d4274e5 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 13 Apr 2023 15:25:16 +0200 Subject: [PATCH 18/40] Fix clippy warnings --- crates/relayer/src/light_client/tendermint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index bf409b0c62..71316f99a0 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -215,7 +215,7 @@ fn io_for_addr( timeout: Option, ) -> Result { let rpc_client = rpc::HttpClient::new(addr.clone()).map_err(|e| Error::rpc(addr.clone(), e))?; - Ok(ProdIo::new(peer_id, rpc_client.clone(), timeout)) + Ok(ProdIo::new(peer_id, rpc_client, timeout)) } impl LightClient { From 83b8a9ba00d4a8f0a06ce6bf7e5615bc0a443d37 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 13 Apr 2023 15:30:14 +0200 Subject: [PATCH 19/40] Print Hermes logs --- ci/misbehaviour/misbehaviour_test.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ci/misbehaviour/misbehaviour_test.sh b/ci/misbehaviour/misbehaviour_test.sh index 5bf84af92e..569fb3cf3a 100755 --- a/ci/misbehaviour/misbehaviour_test.sh +++ b/ci/misbehaviour/misbehaviour_test.sh @@ -5,6 +5,7 @@ set -euo pipefail # --- Variables --- HERMES="cargo run --bin hermes -q --" +HERMES_LOG="hermes.log" DEV_ENV="../../scripts/dev-env" IBC_1_RPC_PORT=26557 @@ -31,7 +32,7 @@ info "Creating forked chain ibc-1-f" bash ./create_fork.sh info "Starting Hermes for ibc-0 and ibc-1" -$HERMES --config config.toml start > hermes.log 2>&1 & +$HERMES --config config.toml start > "$HERMES_LOG" 2>&1 & HERMES_PID=$! info "Waiting for Hermes to start" @@ -46,12 +47,20 @@ sleep 5 info "Killing Hermes" kill -9 "$HERMES_PID" +info "" +info "--------------------------------------------------" +info "Hermes log:" +info "--------------------------------------------------" +cat "$HERMES_LOG" +info "--------------------------------------------------" +info "" + STOPPED_HEIGHT="$(curl -s http://localhost:$IBC_1_RPC_PORT/status | jq -r .result.sync_info.latest_block_height)" info "Chain ibc-1 stopped at height $STOPPED_HEIGHT" info "Fetch evidence from block $STOPPED_HEIGHT on ibc-1" -EVIDENCE="$(curl -s http://localhost:$IBC_1_RPC_PORT/block?height=$STOPPED_HEIGHT | jq .result.block.evidence)" +EVIDENCE="$(curl -s "http://localhost:$IBC_1_RPC_PORT/block?height=$STOPPED_HEIGHT" | jq .result.block.evidence)" info "Found evidence at height $STOPPED_HEIGHT: $EVIDENCE" From 421e4b6e7765182203c3fefa70aa8bf1751ac353 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 14 Apr 2023 15:49:19 +0200 Subject: [PATCH 20/40] Update to latest detector --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03696d98af..f12d9d0cda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3886,7 +3886,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "bytes", "digest 0.10.6", @@ -3916,7 +3916,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "flex-error", "serde", @@ -3929,7 +3929,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -3952,7 +3952,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -3975,7 +3975,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "derive_more", "flex-error", @@ -3987,7 +3987,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "bytes", "flex-error", @@ -4004,7 +4004,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "async-trait", "async-tungstenite", @@ -4038,7 +4038,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#c8b875b061d46bca85f97b9402d0aa7552dbd2af" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" dependencies = [ "ed25519-consensus", "gumdrop", From c0617a0e7bfc1757dae84393d38949d2a27748b3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 14 Apr 2023 17:27:28 +0200 Subject: [PATCH 21/40] Update to latest detector --- Cargo.lock | 122 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f12d9d0cda..fc467b8513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "base16ct" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" @@ -287,6 +287,12 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bech32" version = "0.9.1" @@ -741,9 +747,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.4.9" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -855,11 +861,12 @@ dependencies = [ [[package]] name = "der" -version = "0.6.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "82b10af9f9f9f2134a42d3f8aa74658660f2e0234b0eb81bd171df8aa32779ed" dependencies = [ "const-oid", + "zeroize", ] [[package]] @@ -907,6 +914,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -940,14 +948,15 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecdsa" -version = "0.14.8" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "a48e5d537b8a30c0b023116d981b16334be1485af7ca68db3a2b7024cbc957fd" dependencies = [ "der", + "digest 0.10.6", "elliptic-curve", "rfc6979", - "signature", + "signature 2.1.0", ] [[package]] @@ -957,7 +966,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "serde", - "signature", + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963" +dependencies = [ + "pkcs8", + "signature 2.1.0", ] [[package]] @@ -980,7 +999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ "curve25519-dalek", - "ed25519", + "ed25519 1.5.3", "rand 0.7.3", "serde", "serde_bytes", @@ -1020,17 +1039,17 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.12.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7" dependencies = [ "base16ct", "crypto-bigint", - "der", "digest 0.10.6", "ff", "generic-array", "group", + "pkcs8", "rand_core 0.6.4", "sec1", "subtle", @@ -1148,9 +1167,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", "subtle", @@ -1325,6 +1344,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1374,9 +1394,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", @@ -1771,7 +1791,7 @@ dependencies = [ "crossbeam-channel 0.5.8", "digest 0.10.6", "dirs-next", - "ed25519", + "ed25519 1.5.3", "ed25519-dalek", "ed25519-dalek-bip32", "env_logger 0.10.0", @@ -1801,7 +1821,7 @@ dependencies = [ "serde_json", "serial_test", "sha2 0.10.6", - "signature", + "signature 1.6.4", "strum", "subtle-encoding", "tendermint", @@ -2099,9 +2119,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.11.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if 1.0.0", "ecdsa", @@ -2781,6 +2801,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3122,13 +3152,12 @@ checksum = "9166d72162de3575f950507683fac47e30f6f2c3836b71b7fbc61aa517c9c5f4" [[package]] name = "rfc6979" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "crypto-bigint", "hmac", - "zeroize", + "subtle", ] [[package]] @@ -3396,13 +3425,14 @@ dependencies = [ [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" dependencies = [ "base16ct", "der", "generic-array", + "pkcs8", "subtle", "zeroize", ] @@ -3680,6 +3710,12 @@ name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.6", "rand_core 0.6.4", @@ -3743,6 +3779,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -3886,11 +3932,11 @@ dependencies = [ [[package]] name = "tendermint" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "bytes", "digest 0.10.6", - "ed25519", + "ed25519 2.2.1", "ed25519-consensus", "flex-error", "futures", @@ -3905,7 +3951,7 @@ dependencies = [ "serde_json", "serde_repr", "sha2 0.10.6", - "signature", + "signature 2.1.0", "subtle", "subtle-encoding", "tendermint-proto", @@ -3916,7 +3962,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "flex-error", "serde", @@ -3929,7 +3975,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -3952,7 +3998,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -3975,7 +4021,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "derive_more", "flex-error", @@ -3987,7 +4033,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "bytes", "flex-error", @@ -4004,7 +4050,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "async-trait", "async-tungstenite", @@ -4038,7 +4084,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f33040f9b6b1e8d9232d9821da32b965d6ad3ae7" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" dependencies = [ "ed25519-consensus", "gumdrop", From 80ebe7aa7bcccffdf8ecd99b31d4b57864232977 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 14 Apr 2023 17:30:41 +0200 Subject: [PATCH 22/40] Remove unused `headers_compatible` --- .../src/clients/ics07_tendermint/header.rs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/crates/relayer-types/src/clients/ics07_tendermint/header.rs b/crates/relayer-types/src/clients/ics07_tendermint/header.rs index fb0ee9721a..7c499fdc8d 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/header.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/header.rs @@ -51,30 +51,6 @@ impl Header { ) .expect("malformed tendermint header domain type has an illegal height of 0") } - - pub fn compatible_with(&self, other_header: &Header) -> bool { - headers_compatible(&self.signed_header, &other_header.signed_header) - } -} - -pub fn headers_compatible(header: &SignedHeader, other: &SignedHeader) -> bool { - let ibc_client_height = other.header.height; - let self_header_height = header.header.height; - - match self_header_height.cmp(&ibc_client_height) { - Ordering::Equal => { - // 1 - fork - header.commit.block_id == other.commit.block_id - } - Ordering::Greater => { - // 2 - BFT time violation - header.header.time > other.header.time - } - Ordering::Less => { - // 3 - BFT time violation - header.header.time < other.header.time - } - } } impl crate::core::ics02_client::header::Header for Header { From 5061e6ad5a0af23c394ddc1307ac7ff09e17606f Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 14 Apr 2023 17:35:33 +0200 Subject: [PATCH 23/40] Remove unused import --- crates/relayer-types/src/clients/ics07_tendermint/header.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/relayer-types/src/clients/ics07_tendermint/header.rs b/crates/relayer-types/src/clients/ics07_tendermint/header.rs index 7c499fdc8d..cb8a4bd282 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/header.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/header.rs @@ -1,5 +1,4 @@ use alloc::string::ToString; -use core::cmp::Ordering; use core::fmt::{Display, Error as FmtError, Formatter}; use bytes::Buf; From 9b9ffce8cf5372c3d66fb6f5271d65c8c55c92ea Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 14 Apr 2023 17:35:53 +0200 Subject: [PATCH 24/40] Get current time from chain's sync status --- crates/relayer/src/chain/cosmos.rs | 20 ++++++++++++++----- crates/relayer/src/chain/endpoint.rs | 3 +++ crates/relayer/src/light_client.rs | 3 +++ crates/relayer/src/light_client/tendermint.rs | 20 +++++++++++-------- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 01d838fd06..2c28c06230 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -28,7 +28,7 @@ use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryRespons use ibc_relayer_types::clients::ics07_tendermint::client_state::{ AllowUpdate, ClientState as TmClientState, }; -use ibc_relayer_types::clients::ics07_tendermint::consensus_state::ConsensusState as TMConsensusState; +use ibc_relayer_types::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; use ibc_relayer_types::clients::ics07_tendermint::header::Header as TmHeader; use ibc_relayer_types::core::ics02_client::client_type::ClientType; use ibc_relayer_types::core::ics02_client::error::Error as ClientError; @@ -55,6 +55,7 @@ use ibc_relayer_types::Height as ICSHeight; use tendermint::block::Height as TmHeight; use tendermint::node::{self, info::TxIndexStatus}; +use tendermint::time::Time as TmTime; use tendermint_light_client::verifier::types::LightBlock as TmLightBlock; use tendermint_rpc::client::CompatMode; use tendermint_rpc::endpoint::broadcast::tx_sync::Response; @@ -759,8 +760,9 @@ impl CosmosSdkChain { impl ChainEndpoint for CosmosSdkChain { type LightBlock = TmLightBlock; type Header = TmHeader; - type ConsensusState = TMConsensusState; + type ConsensusState = TmConsensusState; type ClientState = TmClientState; + type Time = TmTime; type SigningKeyPair = Secp256k1KeyPair; fn bootstrap(config: ChainConfig, rt: Arc) -> Result { @@ -871,8 +873,10 @@ impl ChainEndpoint for CosmosSdkChain { target: ICSHeight, client_state: &AnyClientState, ) -> Result { + let now = self.chain_status()?.sync_info.latest_block_time; + self.light_client - .verify(trusted, target, client_state) + .verify(trusted, target, client_state, now) .map(|v| v.target) } @@ -882,7 +886,10 @@ impl ChainEndpoint for CosmosSdkChain { update: &UpdateClient, client_state: &AnyClientState, ) -> Result, Error> { - self.light_client.detect_misbehaviour(update, client_state) + let now = self.chain_status()?.sync_info.latest_block_time; + + self.light_client + .detect_misbehaviour(update, client_state, now) } // Queries @@ -1878,7 +1885,7 @@ impl ChainEndpoint for CosmosSdkChain { ) -> Result { crate::time!("build_consensus_state"); - Ok(TMConsensusState::from(light_block.signed_header.header)) + Ok(TmConsensusState::from(light_block.signed_header.header)) } fn build_header( @@ -1889,11 +1896,14 @@ impl ChainEndpoint for CosmosSdkChain { ) -> Result<(Self::Header, Vec), Error> { crate::time!("build_header"); + let now = self.chain_status()?.sync_info.latest_block_time; + // Get the light block at target_height from chain. let Verified { target, supporting } = self.light_client.header_and_minimal_set( trusted_height, target_height, client_state, + now, )?; Ok((target, supporting)) diff --git a/crates/relayer/src/chain/endpoint.rs b/crates/relayer/src/chain/endpoint.rs index 10a3e5ed3a..70ac77f2e4 100644 --- a/crates/relayer/src/chain/endpoint.rs +++ b/crates/relayer/src/chain/endpoint.rs @@ -75,6 +75,9 @@ pub trait ChainEndpoint: Sized { /// Type of the client state for this chain type ClientState: ClientState + Into; + /// The type of time for this chain + type Time; + /// Type of the key pair used for signatures of messages on chain type SigningKeyPair: SigningKeyPairSized + Into; diff --git a/crates/relayer/src/light_client.rs b/crates/relayer/src/light_client.rs index deeaa4773c..5f19bba177 100644 --- a/crates/relayer/src/light_client.rs +++ b/crates/relayer/src/light_client.rs @@ -43,6 +43,7 @@ pub trait LightClient: Send + Sync { trusted: Height, target: Height, client_state: &AnyClientState, + now: C::Time, ) -> Result, error::Error>; /// Fetch a header from the chain at the given height and verify it. @@ -51,6 +52,7 @@ pub trait LightClient: Send + Sync { trusted: Height, target: Height, client_state: &AnyClientState, + now: C::Time, ) -> Result, error::Error>; /// Given a client update event that includes the header used in a client update, @@ -59,6 +61,7 @@ pub trait LightClient: Send + Sync { &mut self, update: &UpdateClient, client_state: &AnyClientState, + now: C::Time, ) -> Result, error::Error>; /// Fetch a header from the chain at the given height, without verifying it diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 71316f99a0..0a07970097 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -3,6 +3,7 @@ mod detector; use std::time::Duration; use itertools::Itertools; +use tendermint::Time; use tracing::{debug, error, trace, warn}; use tendermint_light_client::{ @@ -55,8 +56,9 @@ impl super::LightClient for LightClient { trusted: ICSHeight, target: ICSHeight, client_state: &AnyClientState, + now: Time, ) -> Result, Error> { - let Verified { target, supporting } = self.verify(trusted, target, client_state)?; + let Verified { target, supporting } = self.verify(trusted, target, client_state, now)?; let (target, supporting) = self.adjust_headers(trusted, target, supporting)?; Ok(Verified { target, supporting }) @@ -67,10 +69,11 @@ impl super::LightClient for LightClient { trusted_height: ICSHeight, target_height: ICSHeight, client_state: &AnyClientState, + now: Time, ) -> Result, Error> { trace!(%trusted_height, %target_height, "light client verification"); - let client = self.prepare_client(client_state)?; + let client = self.prepare_client(client_state, now)?; let mut state = self.prepare_state(trusted_height)?; let target_height = @@ -110,6 +113,7 @@ impl super::LightClient for LightClient { &mut self, update: &UpdateClient, client_state: &AnyClientState, + now: Time, ) -> Result, Error> { crate::time!("light client check_misbehaviour"); @@ -136,8 +140,6 @@ impl super::LightClient for LightClient { )) })?; - let latest_chain_block = self.fetch_light_block(AtHeight::Highest)?; - let next_validators = self .io .fetch_validator_set( @@ -153,8 +155,6 @@ impl super::LightClient for LightClient { provider: self.peer_id, }; - let now = latest_chain_block.time(); // FIXME: Is that right? - let trusted_block = self.fetch(update_header.trusted_height)?; // FIXME: Is that ok? // TODO: Check validator sets match @@ -246,8 +246,12 @@ impl LightClient { }) } - fn prepare_client(&self, client_state: &AnyClientState) -> Result { - let clock = components::clock::SystemClock; + fn prepare_client( + &self, + client_state: &AnyClientState, + now: Time, + ) -> Result { + let clock = components::clock::FixedClock::new(now); let verifier = ProdVerifier::default(); let scheduler = components::scheduler::basic_bisecting_schedule; From 5515b264fb9e91e367741a13cfbfbd7fdbc24b80 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 10:17:09 +0200 Subject: [PATCH 25/40] Compute proper supporting headers --- crates/relayer/src/light_client/tendermint.rs | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 0a07970097..248951c743 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -36,6 +36,7 @@ use crate::{ client_state::AnyClientState, config::ChainConfig, error::Error, + light_client::AnyHeader, misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}, }; @@ -78,8 +79,8 @@ impl super::LightClient for LightClient { let target_height = TMHeight::try_from(target_height.revision_height()).map_err(Error::invalid_height)?; - let trusted_height = - TMHeight::try_from(trusted_height.revision_height()).map_err(Error::invalid_height)?; + // let trusted_height = + // TMHeight::try_from(trusted_height.revision_height()).map_err(Error::invalid_height)?; // Verify the target header let target = client @@ -90,10 +91,12 @@ impl super::LightClient for LightClient { let target_trace = state.get_trace(target.height()); // Compute the minimal supporting set, sorted by ascending height, - // skip the target header and the trusted header if present in the trace + // skip the target header if present in the trace let supporting = target_trace .into_iter() - .filter(|lb| lb.height() != target.height() && lb.height() != trusted_height) + .filter( + |lb| lb.height() != target.height(), /* && lb.height() != trusted_height */ + ) .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) .collect_vec(); @@ -155,14 +158,13 @@ impl super::LightClient for LightClient { provider: self.peer_id, }; - let trusted_block = self.fetch(update_header.trusted_height)?; // FIXME: Is that ok? - // TODO: Check validator sets match + let trusted_block = self.fetch(update_header.trusted_height)?; // TODO: Check validator sets match let divergence = detector::detect( self.peer_id, self.io.rpc_client().clone(), target_block, - trusted_block.clone(), + trusted_block, client_state, now, ); @@ -185,6 +187,22 @@ impl super::LightClient for LightClient { Err(e) => error!("failed to report evidence to RPC witness node: {}", e), } + // We redo verification one more time to get the trace of supporting headers + let redo_verif = self.verify( + update_header.trusted_height, + update_header.height(), // FIXME: Is that right? + &AnyClientState::Tendermint(client_state.clone()), + now, + )?; + + let (_, trace) = self.adjust_headers( + update_header.trusted_height, + redo_verif.target, + redo_verif.supporting, + )?; + + let last_trace_block = trace.last().expect("trace cannot be empty"); + let evidence = MisbehaviourEvidence { misbehaviour: AnyMisbehaviour::Tendermint(TmMisbehaviour { client_id: update.client_id().clone(), @@ -192,11 +210,11 @@ impl super::LightClient for LightClient { header2: TmHeader { signed_header: challenging_block.signed_header, validator_set: challenging_block.validators, - trusted_height: update_header.trusted_height, - trusted_validator_set: trusted_block.validators, + trusted_height: last_trace_block.height(), + trusted_validator_set: last_trace_block.trusted_validator_set.clone(), }, }), - supporting_headers: vec![], // FIXME: What do we put here? + supporting_headers: trace.into_iter().map(AnyHeader::Tendermint).collect(), }; Ok(Some(evidence)) From 3c4776aa525a728d456904497d7284669e6f2c5a Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 14:05:05 +0200 Subject: [PATCH 26/40] Infallible height conversions --- crates/relayer/src/chain/cosmos.rs | 20 +++++++------------- crates/relayer/src/chain/requests.rs | 16 ++++++---------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 2c28c06230..ed3d9a7fee 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -226,9 +226,8 @@ impl CosmosSdkChain { )); } - // Get the latest height and convert to tendermint Height - let latest_height = TmHeight::try_from(self.query_chain_latest_height()?.revision_height()) - .map_err(Error::invalid_height)?; + // Get the latest height + let latest_height = self.query_chain_latest_height()?; // Check on the configured max_tx_size against the consensus parameters at latest height let result = self @@ -477,10 +476,6 @@ impl CosmosSdkChain { ) -> Result { crate::time!("query"); - let path = IBC_QUERY_PATH.into(); - - let height = TmHeight::try_from(height_query)?; - let data = data.into(); if !data.is_provable() & prove { return Err(Error::private_store()); @@ -489,9 +484,9 @@ impl CosmosSdkChain { let response = self.block_on(abci_query( &self.rpc_client, &self.config.rpc_addr, - path, + IBC_QUERY_PATH.to_string(), data.to_string(), - height, + height_query.into(), prove, ))?; @@ -530,7 +525,7 @@ impl CosmosSdkChain { &self.config.rpc_addr, path, Path::Upgrade(query_data).to_string(), - TmHeight::try_from(query_height.revision_height()).map_err(Error::invalid_height)?, + query_height.into(), true, ))?; @@ -1409,6 +1404,7 @@ impl ChainEndpoint for CosmosSdkChain { .ok() }) .collect(); + Ok(channels) } @@ -1823,9 +1819,7 @@ impl ChainEndpoint for CosmosSdkChain { ) -> Result { let height = match request.height { QueryHeight::Latest => TmHeight::from(0u32), - QueryHeight::Specific(ibc_height) => { - TmHeight::try_from(ibc_height.revision_height()).map_err(Error::invalid_height)? - } + QueryHeight::Specific(ibc_height) => TmHeight::from(ibc_height), }; let header = if height.value() == 0 { diff --git a/crates/relayer/src/chain/requests.rs b/crates/relayer/src/chain/requests.rs index bb771e0429..42c533e6bd 100644 --- a/crates/relayer/src/chain/requests.rs +++ b/crates/relayer/src/chain/requests.rs @@ -43,16 +43,12 @@ pub enum QueryHeight { Specific(Height), } -impl TryFrom for TMBlockHeight { - type Error = Error; - - fn try_from(height_query: QueryHeight) -> Result { - let height = match height_query { - QueryHeight::Latest => 0u64, - QueryHeight::Specific(height) => height.revision_height(), - }; - - Self::try_from(height).map_err(Error::invalid_height) +impl From for TMBlockHeight { + fn from(height_query: QueryHeight) -> Self { + match height_query { + QueryHeight::Latest => Self::from(0_u32), + QueryHeight::Specific(height) => Self::from(height), + } } } From a0779e3dc9fd5b152405e26e5ea533180ccb3416 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 14:10:10 +0200 Subject: [PATCH 27/40] Refactor to include trusted and target headers in supporting headers but omit them from minimal set --- crates/relayer/src/light_client/tendermint.rs | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 248951c743..cd69caf5dc 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -54,13 +54,25 @@ pub struct LightClient { impl super::LightClient for LightClient { fn header_and_minimal_set( &mut self, - trusted: ICSHeight, - target: ICSHeight, + trusted_height: ICSHeight, + target_height: ICSHeight, client_state: &AnyClientState, now: Time, ) -> Result, Error> { - let Verified { target, supporting } = self.verify(trusted, target, client_state, now)?; - let (target, supporting) = self.adjust_headers(trusted, target, supporting)?; + let Verified { target, supporting } = + self.verify(trusted_height, target_height, client_state, now)?; + + let supporting = { + let target_height = TMHeight::from(target_height); + let trusted_height = TMHeight::from(trusted_height); + + supporting + .into_iter() + .filter(|lb| lb.height() != target_height && lb.height() != trusted_height) + .collect() + }; + + let (target, supporting) = self.adjust_headers(trusted_height, target, supporting)?; Ok(Verified { target, supporting }) } @@ -77,26 +89,17 @@ impl super::LightClient for LightClient { let client = self.prepare_client(client_state, now)?; let mut state = self.prepare_state(trusted_height)?; - let target_height = - TMHeight::try_from(target_height.revision_height()).map_err(Error::invalid_height)?; - // let trusted_height = - // TMHeight::try_from(trusted_height.revision_height()).map_err(Error::invalid_height)?; - // Verify the target header let target = client - .verify_to_target(target_height, &mut state) + .verify_to_target(target_height.into(), &mut state) .map_err(|e| Error::light_client_verification(self.chain_id.to_string(), e))?; // Collect the verification trace for the target block let target_trace = state.get_trace(target.height()); - // Compute the minimal supporting set, sorted by ascending height, - // skip the target header if present in the trace + // Compute the supporting set, sorted by ascending height let supporting = target_trace .into_iter() - .filter( - |lb| lb.height() != target.height(), /* && lb.height() != trusted_height */ - ) .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) .collect_vec(); @@ -107,8 +110,7 @@ impl super::LightClient for LightClient { fn fetch(&mut self, height: ICSHeight) -> Result { trace!(%height, "fetching header"); - let height = TMHeight::try_from(height.revision_height()).map_err(Error::invalid_height)?; - self.fetch_light_block(AtHeight::At(height)) + self.fetch_light_block(AtHeight::At(height.into())) } /// Perform misbehavior detection on the given client state and update client event. @@ -203,6 +205,14 @@ impl super::LightClient for LightClient { let last_trace_block = trace.last().expect("trace cannot be empty"); + debug!("update_header {:#?}", update_header.height()); + debug!("challenging_block {:#?}", challenging_block.height()); + debug!( + "trace {:#?}", + trace.iter().map(|x| x.height()).collect::>() + ); + debug!("last_trace_block {:#?}", last_trace_block.height()); + let evidence = MisbehaviourEvidence { misbehaviour: AnyMisbehaviour::Tendermint(TmMisbehaviour { client_id: update.client_id().clone(), @@ -288,11 +298,8 @@ impl LightClient { )) } - fn prepare_state(&self, trusted: ICSHeight) -> Result { - let trusted_height = - TMHeight::try_from(trusted.revision_height()).map_err(Error::invalid_height)?; - - let trusted_block = self.fetch_light_block(AtHeight::At(trusted_height))?; + fn prepare_state(&self, trusted_height: ICSHeight) -> Result { + let trusted_block = self.fetch_light_block(AtHeight::At(trusted_height.into()))?; let mut store = MemoryStore::new(); store.insert(trusted_block, Status::Trusted); From 4ced5615bece143e7f4b6500f0832c7ed06d4b92 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 14:18:08 +0200 Subject: [PATCH 28/40] Always omit target header from supporting set --- crates/relayer/src/light_client/tendermint.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index cd69caf5dc..07c798d6b6 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -63,12 +63,11 @@ impl super::LightClient for LightClient { self.verify(trusted_height, target_height, client_state, now)?; let supporting = { - let target_height = TMHeight::from(target_height); let trusted_height = TMHeight::from(trusted_height); supporting .into_iter() - .filter(|lb| lb.height() != target_height && lb.height() != trusted_height) + .filter(|lb| lb.height() != trusted_height) .collect() }; @@ -97,11 +96,12 @@ impl super::LightClient for LightClient { // Collect the verification trace for the target block let target_trace = state.get_trace(target.height()); - // Compute the supporting set, sorted by ascending height + // Compute the supporting set, sorted by ascending height, and filter out the target header let supporting = target_trace .into_iter() .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) + .filter(|lb| lb.height() != target.height()) .collect_vec(); Ok(Verified { target, supporting }) From 1ef7067befb950e2b99b4ac8b55e0b1a2134feaa Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 14:39:51 +0200 Subject: [PATCH 29/40] Use trusted height and not height of last supporting header --- crates/relayer/src/light_client/tendermint.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 07c798d6b6..e0da3b908c 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -63,11 +63,12 @@ impl super::LightClient for LightClient { self.verify(trusted_height, target_height, client_state, now)?; let supporting = { + let target_height = TMHeight::from(target_height); let trusted_height = TMHeight::from(trusted_height); supporting .into_iter() - .filter(|lb| lb.height() != trusted_height) + .filter(|lb| lb.height() != target_height && lb.height() != trusted_height) .collect() }; @@ -96,12 +97,11 @@ impl super::LightClient for LightClient { // Collect the verification trace for the target block let target_trace = state.get_trace(target.height()); - // Compute the supporting set, sorted by ascending height, and filter out the target header + // Compute the supporting set, sorted by ascending height let supporting = target_trace .into_iter() .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) - .filter(|lb| lb.height() != target.height()) .collect_vec(); Ok(Verified { target, supporting }) @@ -220,7 +220,7 @@ impl super::LightClient for LightClient { header2: TmHeader { signed_header: challenging_block.signed_header, validator_set: challenging_block.validators, - trusted_height: last_trace_block.height(), + trusted_height: last_trace_block.trusted_height, trusted_validator_set: last_trace_block.trusted_validator_set.clone(), }, }), From 9469be45420828bb3abd1cc328f863da6bd60178 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 18 Apr 2023 15:23:30 +0200 Subject: [PATCH 30/40] Use target header of new round of verification to get trusted height and validators --- ci/misbehaviour/misbehaviour_test.sh | 11 +++++- crates/relayer/src/light_client/tendermint.rs | 38 +++++++------------ crates/relayer/src/worker/client.rs | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/ci/misbehaviour/misbehaviour_test.sh b/ci/misbehaviour/misbehaviour_test.sh index 569fb3cf3a..d79b8ca854 100755 --- a/ci/misbehaviour/misbehaviour_test.sh +++ b/ci/misbehaviour/misbehaviour_test.sh @@ -47,13 +47,20 @@ sleep 5 info "Killing Hermes" kill -9 "$HERMES_PID" -info "" +echo "" info "--------------------------------------------------" info "Hermes log:" info "--------------------------------------------------" cat "$HERMES_LOG" info "--------------------------------------------------" -info "" +echo "" + +if grep -q "Evidence succesfully submitted" "$HERMES_LOG"; then + warn "Misbehaviour detection failed!" + exit 1 +else + info "Misbehaviour detected and submitted successfully!" +fi STOPPED_HEIGHT="$(curl -s http://localhost:$IBC_1_RPC_PORT/status | jq -r .result.sync_info.latest_block_height)" diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index e0da3b908c..7250e4dba5 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -62,13 +62,14 @@ impl super::LightClient for LightClient { let Verified { target, supporting } = self.verify(trusted_height, target_height, client_state, now)?; + // Omit the trusted header from the minimal supporting set, as it is not + // needed when submitting the update client message. let supporting = { - let target_height = TMHeight::from(target_height); let trusted_height = TMHeight::from(trusted_height); supporting .into_iter() - .filter(|lb| lb.height() != target_height && lb.height() != trusted_height) + .filter(|lb| lb.height() != trusted_height) .collect() }; @@ -97,11 +98,12 @@ impl super::LightClient for LightClient { // Collect the verification trace for the target block let target_trace = state.get_trace(target.height()); - // Compute the supporting set, sorted by ascending height + // Compute the supporting set, sorted by ascending height, omitting the target header let supporting = target_trace .into_iter() .unique_by(LightBlock::height) .sorted_by_key(LightBlock::height) + .filter(|lb| lb.height() != target.height()) .collect_vec(); Ok(Verified { target, supporting }) @@ -190,29 +192,13 @@ impl super::LightClient for LightClient { } // We redo verification one more time to get the trace of supporting headers - let redo_verif = self.verify( + let verified = self.header_and_minimal_set( update_header.trusted_height, - update_header.height(), // FIXME: Is that right? + update_header.height(), &AnyClientState::Tendermint(client_state.clone()), now, )?; - let (_, trace) = self.adjust_headers( - update_header.trusted_height, - redo_verif.target, - redo_verif.supporting, - )?; - - let last_trace_block = trace.last().expect("trace cannot be empty"); - - debug!("update_header {:#?}", update_header.height()); - debug!("challenging_block {:#?}", challenging_block.height()); - debug!( - "trace {:#?}", - trace.iter().map(|x| x.height()).collect::>() - ); - debug!("last_trace_block {:#?}", last_trace_block.height()); - let evidence = MisbehaviourEvidence { misbehaviour: AnyMisbehaviour::Tendermint(TmMisbehaviour { client_id: update.client_id().clone(), @@ -220,11 +206,15 @@ impl super::LightClient for LightClient { header2: TmHeader { signed_header: challenging_block.signed_header, validator_set: challenging_block.validators, - trusted_height: last_trace_block.trusted_height, - trusted_validator_set: last_trace_block.trusted_validator_set.clone(), + trusted_height: verified.target.trusted_height, + trusted_validator_set: verified.target.trusted_validator_set, }, }), - supporting_headers: trace.into_iter().map(AnyHeader::Tendermint).collect(), + supporting_headers: verified + .supporting + .into_iter() + .map(AnyHeader::Tendermint) + .collect(), }; Ok(Some(evidence)) diff --git a/crates/relayer/src/worker/client.rs b/crates/relayer/src/worker/client.rs index a8e7b498d6..71fe470355 100644 --- a/crates/relayer/src/worker/client.rs +++ b/crates/relayer/src/worker/client.rs @@ -156,7 +156,7 @@ fn on_client_update( } MisbehaviourResults::EvidenceSubmitted(_) => { // if evidence was submitted successfully then exit - debug!("misbehavior detected! Evidence succesfully submitted, exiting"); + debug!("misbehavior detected! Evidence successfully submitted, exiting"); Next::Abort } From b23a5a394c222016f67a1b400ac96993552a0c5f Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 20 Apr 2023 12:48:09 +0200 Subject: [PATCH 31/40] Update tendermint-rs to v0.31.1 --- Cargo.lock | 56 +++++++++++++++++++++----------- crates/chain-registry/Cargo.toml | 2 +- crates/relayer-cli/Cargo.toml | 6 ++-- crates/relayer-types/Cargo.toml | 12 +++---- crates/relayer/Cargo.toml | 10 +++--- crates/telemetry/Cargo.toml | 2 +- tools/query-events/Cargo.toml | 4 +-- tools/test-framework/Cargo.toml | 2 +- 8 files changed, 56 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc467b8513..d0fceaadc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1774,7 +1774,7 @@ dependencies = [ "prost", "serde", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.30.0", "tonic", ] @@ -1919,7 +1919,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-light-client-verifier", - "tendermint-proto", + "tendermint-proto 0.31.1", "tendermint-rpc", "tendermint-testgen", "test-log", @@ -3931,8 +3931,8 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "bytes", "digest 0.10.6", @@ -3954,15 +3954,15 @@ dependencies = [ "signature 2.1.0", "subtle", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.31.1", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "flex-error", "serde", @@ -3974,8 +3974,8 @@ dependencies = [ [[package]] name = "tendermint-light-client" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -3997,8 +3997,8 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4012,7 +4012,7 @@ dependencies = [ "static_assertions", "tendermint", "tendermint-light-client", - "tendermint-proto", + "tendermint-proto 0.31.1", "tendermint-rpc", "time", "tracing", @@ -4020,8 +4020,8 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "derive_more", "flex-error", @@ -4033,7 +4033,25 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e553ed65874c3f35a71eb60d255edfea956274b5af37a0297d54bba039fe45e3" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "bytes", "flex-error", @@ -4049,8 +4067,8 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "async-trait", "async-tungstenite", @@ -4083,8 +4101,8 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.30.0" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#9df10d652ba92b26bccdc1c1ebdeaea67708c10e" +version = "0.31.1" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index 093403c92b..b691f7396b 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -14,7 +14,7 @@ description = """ [dependencies] ibc-proto = { version = "0.29.0" } ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["std"] } -tendermint-rpc = { version = "0.30.0", features = ["http-client", "websocket-client"] } +tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } async-trait = "0.1.67" flex-error = { version = "0.4.4", default-features = false } diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index cb356bd3c0..2a831aa42f 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -58,15 +58,15 @@ tracing = "0.1.36" tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"]} [dependencies.tendermint] -version = "0.30.0" +version = "0.31.1" features = ["secp256k1"] [dependencies.tendermint-rpc] -version = "0.30.0" +version = "0.31.1" features = ["http-client", "websocket-client"] [dependencies.tendermint-light-client-verifier] -version = "0.30.0" +version = "0.31.1" [dependencies.abscissa_core] version = "=0.6.0" diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 76c31f103a..381c2c8e7e 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -47,20 +47,20 @@ dyn-clone = "1.0.8" num-rational = "0.4.1" [dependencies.tendermint] -version = "0.30.0" +version = "0.31.1" default-features = false [dependencies.tendermint-proto] -version = "0.30.0" +version = "0.31.1" default-features = false [dependencies.tendermint-light-client-verifier] -version = "0.30.0" +version = "0.31.1" default-features = false features = ["rust-crypto"] [dependencies.tendermint-testgen] -version = "0.30.0" +version = "0.31.1" optional = true default-features = false @@ -69,5 +69,5 @@ env_logger = "0.10.0" tracing = { version = "0.1.36", default-features = false } tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } test-log = { version = "0.2.10", features = ["trace"] } -tendermint-rpc = { version = "0.30.0", features = ["http-client", "websocket-client"] } -tendermint-testgen = { version = "0.30.0" } # Needed for generating (synthetic) light blocks. +tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } +tendermint-testgen = { version = "0.31.1" } # Needed for generating (synthetic) light blocks. diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 1f6d8897a5..629dd85511 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -78,20 +78,20 @@ version = "0.4.1" features = ["num-bigint", "serde"] [dependencies.tendermint] -version = "0.30.0" +version = "0.31.1" features = ["secp256k1"] [dependencies.tendermint-rpc] -version = "0.30.0" +version = "0.31.1" features = ["http-client", "websocket-client"] [dependencies.tendermint-light-client] -version = "0.30.0" +version = "0.31.1" default-features = false features = ["rpc-client", "secp256k1", "unstable"] [dependencies.tendermint-light-client-detector] -version = "0.30.0" +version = "0.31.1" default-features = false [dev-dependencies] @@ -102,4 +102,4 @@ tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "jso test-log = { version = "0.2.10", features = ["trace"] } # Needed for generating (synthetic) light blocks. -tendermint-testgen = { version = "0.30.0" } +tendermint-testgen = { version = "0.31.1" } diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index 7bef9ab1b8..a68d69618e 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -27,5 +27,5 @@ axum = "0.6.12" tokio = "1.26.0" [dependencies.tendermint] -version = "0.30.0" +version = "0.31.1" default-features = false diff --git a/tools/query-events/Cargo.toml b/tools/query-events/Cargo.toml index 3df87de5f6..cf1b80fd5c 100644 --- a/tools/query-events/Cargo.toml +++ b/tools/query-events/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -tendermint = { version = "0.30.0" } -tendermint-rpc = { version = "0.30.0", features = ["http-client"] } +tendermint = { version = "0.31.1" } +tendermint-rpc = { version = "0.31.1", features = ["http-client"] } clap = { version = "3.2", features = ["derive"] } futures = "0.3.27" diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index a98fc8ad69..e8fbe28f39 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -18,7 +18,7 @@ ibc-relayer-types = { version = "=0.23.0", path = "../../crates/relayer-type ibc-relayer = { version = "=0.23.0", path = "../../crates/relayer" } ibc-relayer-cli = { version = "=1.4.0", path = "../../crates/relayer-cli" } ibc-proto = { version = "0.29.0" } -tendermint-rpc = { version = "0.30.0", features = ["http-client", "websocket-client"] } +tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } http = "0.2.9" tokio = { version = "1.0", features = ["full"] } From 558d0b0e521f2cdc9fa0b8f0741818cc5409f458 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 20 Apr 2023 15:01:28 +0200 Subject: [PATCH 32/40] Update `ibc-proto` to v0.30.0 --- Cargo.lock | 30 ++++++------------------------ crates/chain-registry/Cargo.toml | 2 +- crates/relayer-types/Cargo.toml | 2 +- crates/relayer/Cargo.toml | 2 +- tools/test-framework/Cargo.toml | 2 +- 5 files changed, 10 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0fceaadc7..1e791e947a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1764,9 +1764,9 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364c9dad4c898411ddfdcc990800c229cd7018c16ab1360395e4637458032198" +checksum = "f844ebc1ddf70f2ad7cd5981a2feba261fff55e1ad6482c27551ee3c6cec7df4" dependencies = [ "base64 0.21.0", "bytes", @@ -1774,7 +1774,7 @@ dependencies = [ "prost", "serde", "subtle-encoding", - "tendermint-proto 0.30.0", + "tendermint-proto", "tonic", ] @@ -1919,7 +1919,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-light-client-verifier", - "tendermint-proto 0.31.1", + "tendermint-proto", "tendermint-rpc", "tendermint-testgen", "test-log", @@ -3954,7 +3954,7 @@ dependencies = [ "signature 2.1.0", "subtle", "subtle-encoding", - "tendermint-proto 0.31.1", + "tendermint-proto", "time", "zeroize", ] @@ -4012,7 +4012,7 @@ dependencies = [ "static_assertions", "tendermint", "tendermint-light-client", - "tendermint-proto 0.31.1", + "tendermint-proto", "tendermint-rpc", "time", "tracing", @@ -4030,24 +4030,6 @@ dependencies = [ "time", ] -[[package]] -name = "tendermint-proto" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e553ed65874c3f35a71eb60d255edfea956274b5af37a0297d54bba039fe45e3" -dependencies = [ - "bytes", - "flex-error", - "num-derive", - "num-traits", - "prost", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - [[package]] name = "tendermint-proto" version = "0.31.1" diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index b691f7396b..51640603f0 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -12,7 +12,7 @@ description = """ """ [dependencies] -ibc-proto = { version = "0.29.0" } +ibc-proto = { version = "0.30.0" } ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["std"] } tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 381c2c8e7e..768362dd54 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -27,7 +27,7 @@ mocks = ["tendermint-testgen", "clock", "std"] [dependencies] # Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.29.0", default-features = false } +ibc-proto = { version = "0.30.0", default-features = false } ics23 = { version = "=0.9.0", default-features = false, features = ["host-functions"] } time = { version = ">=0.3.0, <0.3.21", default-features = false } serde_derive = { version = "1.0.104", default-features = false } diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 629dd85511..c67bf7b5db 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -21,7 +21,7 @@ profiling = [] telemetry = ["ibc-telemetry"] [dependencies] -ibc-proto = { version = "0.29.0" } +ibc-proto = { version = "0.30.0" } ibc-telemetry = { version = "0.23.0", path = "../telemetry", optional = true } ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["mocks"] } diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index e8fbe28f39..8b681f7417 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -17,7 +17,7 @@ description = """ ibc-relayer-types = { version = "=0.23.0", path = "../../crates/relayer-types" } ibc-relayer = { version = "=0.23.0", path = "../../crates/relayer" } ibc-relayer-cli = { version = "=1.4.0", path = "../../crates/relayer-cli" } -ibc-proto = { version = "0.29.0" } +ibc-proto = { version = "0.30.0" } tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } http = "0.2.9" From 17ba1b5e3720fb6d80376cca618b7827e65c4d93 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 20 Apr 2023 15:12:02 +0200 Subject: [PATCH 33/40] Compilation fixes after detector update --- crates/relayer/src/light_client/tendermint.rs | 5 ++++- crates/relayer/src/light_client/tendermint/detector.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 7250e4dba5..9cbfc0aa5a 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -186,7 +186,10 @@ impl super::LightClient for LightClient { })) => { warn!("misbehavior detected, reporting evidence to RPC witness node and primary chain"); - match detector::report_evidence(self.io.rpc_client().clone(), evidence) { + match detector::report_evidence( + self.io.rpc_client().clone(), + evidence.against_primary, + ) { Ok(hash) => warn!("evidence reported to RPC witness node with hash: {hash}"), Err(e) => error!("failed to report evidence to RPC witness node: {}", e), } diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index 9d93fcdae9..14be91bfbf 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -32,6 +32,7 @@ pub fn detect( let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block, now)?; let divergence = block_on(detect_divergence( + None, &mut provider, primary_trace, options.clock_drift, From 032a894b490c1f1c00eddafbc829b6de3bd030b3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 26 Apr 2023 21:42:55 +0200 Subject: [PATCH 34/40] Use witness trace computed by the detector instead of verifying again (#3277) --- crates/relayer/src/light_client/tendermint.rs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 9cbfc0aa5a..d4034391f9 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -194,13 +194,19 @@ impl super::LightClient for LightClient { Err(e) => error!("failed to report evidence to RPC witness node: {}", e), } - // We redo verification one more time to get the trace of supporting headers - let verified = self.header_and_minimal_set( - update_header.trusted_height, - update_header.height(), - &AnyClientState::Tendermint(client_state.clone()), - now, - )?; + let target_block = self.fetch(update_header.height())?; + let trusted_height = TMHeight::from(update_header.trusted_height); + let trace = evidence + .witness_trace + .into_vec() + .into_iter() + .filter(|lb| { + lb.height() != target_block.height() && lb.height() != trusted_height + }) + .collect(); + + let (target_header, supporting_headers) = + self.adjust_headers(update_header.trusted_height, target_block, trace)?; let evidence = MisbehaviourEvidence { misbehaviour: AnyMisbehaviour::Tendermint(TmMisbehaviour { @@ -209,12 +215,11 @@ impl super::LightClient for LightClient { header2: TmHeader { signed_header: challenging_block.signed_header, validator_set: challenging_block.validators, - trusted_height: verified.target.trusted_height, - trusted_validator_set: verified.target.trusted_validator_set, + trusted_height: target_header.trusted_height, + trusted_validator_set: target_header.trusted_validator_set, }, }), - supporting_headers: verified - .supporting + supporting_headers: supporting_headers .into_iter() .map(AnyHeader::Tendermint) .collect(), From 65df0ec5e18b1ddcdc4ef83cf57691c454ed4610 Mon Sep 17 00:00:00 2001 From: Anca Zamfir Date: Thu, 27 Apr 2023 07:50:41 +0200 Subject: [PATCH 35/40] Fix merge issues --- crates/relayer-types/Cargo.toml | 2 +- crates/relayer/src/config.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index d7a3bd6488..1c22918cd0 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -27,7 +27,7 @@ mocks = ["tendermint-testgen", "clock", "std"] [dependencies] # Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.29.0", default-features = false } +ibc-proto = { version = "0.30.0", default-features = false } ics23 = { version = "0.10.0", default-features = false, features = ["host-functions"] } time = { version = ">=0.3.0, <0.3.21", default-features = false } serde_derive = { version = "1.0.104", default-features = false } diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 3b000ec0a4..f0913452f0 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -13,6 +13,7 @@ use core::{ str::FromStr, time::Duration, }; +use serde_derive::{Deserialize, Serialize}; use std::{ fs, fs::File, From cfbc186b568ead4c2a1aee02cdac8668c36bcb28 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Thu, 27 Apr 2023 16:46:27 +0200 Subject: [PATCH 36/40] Update to latest detector --- Cargo.lock | 17 +++++++++-------- .../src/light_client/tendermint/detector.rs | 4 +++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b2a66908f..d05d517789 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3941,7 +3941,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "bytes", "digest 0.10.6", @@ -3971,7 +3971,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "flex-error", "serde", @@ -3984,13 +3984,14 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "contracts", "crossbeam-channel 0.4.4", "derive_more", "flex-error", "futures", + "regex", "serde", "serde_cbor", "serde_derive", @@ -4007,7 +4008,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4030,7 +4031,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "derive_more", "flex-error", @@ -4042,7 +4043,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "bytes", "flex-error", @@ -4059,7 +4060,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "async-trait", "async-tungstenite", @@ -4093,7 +4094,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#2033c2288da6ec483d0c4eda9e09e84ba5ca379e" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index 14be91bfbf..628c6c14c6 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -19,6 +19,8 @@ use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState; use crate::{error::Error, util::block_on}; +type Hasher = tendermint::crypto::default::Sha256; + pub fn detect( peer_id: PeerId, rpc_client: HttpClient, @@ -31,7 +33,7 @@ pub fn detect( let options = client_state.as_light_client_options(); let mut provider = make_provider(peer_id, rpc_client, client_state, trusted_block, now)?; - let divergence = block_on(detect_divergence( + let divergence = block_on(detect_divergence::( None, &mut provider, primary_trace, From 5f253fef11815fa30838d01b5dbc67e2689012cd Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 28 Apr 2023 10:20:25 +0200 Subject: [PATCH 37/40] Ensure trusted validator set matches the fetched one --- crates/relayer/src/light_client/tendermint.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index d4034391f9..3669412c40 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -162,7 +162,16 @@ impl super::LightClient for LightClient { provider: self.peer_id, }; - let trusted_block = self.fetch(update_header.trusted_height)?; // TODO: Check validator sets match + let trusted_block = self.fetch(update_header.trusted_height)?; + if trusted_block.validators.hash() != update_header.trusted_validator_set.hash() { + return Err(Error::misbehaviour(format!( + "mismatch between the trusted validator set of the update \ + header ({}) and that of the trusted block that was fetched ({}), \ + aborting misbehaviour detection.", + trusted_block.validators.hash(), + update_header.trusted_validator_set.hash() + ))); + } let divergence = detector::detect( self.peer_id, From db293c8e12384b763fb2bdaaefac161e50e4abd0 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 28 Apr 2023 15:37:58 +0200 Subject: [PATCH 38/40] Update to latest detector --- Cargo.lock | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d05d517789..d02823c4c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3941,7 +3941,7 @@ dependencies = [ [[package]] name = "tendermint" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "bytes", "digest 0.10.6", @@ -3971,7 +3971,7 @@ dependencies = [ [[package]] name = "tendermint-config" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "flex-error", "serde", @@ -3984,7 +3984,7 @@ dependencies = [ [[package]] name = "tendermint-light-client" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4008,7 +4008,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4031,7 +4031,7 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "derive_more", "flex-error", @@ -4043,7 +4043,7 @@ dependencies = [ [[package]] name = "tendermint-proto" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "bytes", "flex-error", @@ -4060,7 +4060,7 @@ dependencies = [ [[package]] name = "tendermint-rpc" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "async-trait", "async-tungstenite", @@ -4082,6 +4082,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-config", + "tendermint-proto", "thiserror", "time", "tokio", @@ -4094,7 +4095,7 @@ dependencies = [ [[package]] name = "tendermint-testgen" version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#f3f6f0f66c2624e6dd91b33580e50b36124e12ad" +source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" dependencies = [ "ed25519-consensus", "gumdrop", From fa406fdbe930a14e6a1461bee0912ae7d280a518 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 3 May 2023 20:21:42 +0200 Subject: [PATCH 39/40] Update to tendermint-rs v0.32.0 and `ibc-proto` v0.31.0-alpha.2 --- Cargo.lock | 61 +++++--- Cargo.toml | 14 +- crates/chain-registry/Cargo.toml | 4 +- crates/relayer-cli/Cargo.toml | 6 +- crates/relayer-types/Cargo.toml | 14 +- .../clients/ics07_tendermint/client_state.rs | 2 +- .../src/core/ics23_commitment/commitment.rs | 13 +- .../src/core/ics23_commitment/merkle.rs | 28 +--- .../src/core/ics23_commitment/specs.rs | 135 +++--------------- crates/relayer/Cargo.toml | 12 +- crates/relayer/src/chain/counterparty.rs | 2 +- crates/relayer/src/client_state.rs | 4 +- crates/telemetry/Cargo.toml | 2 +- tools/query-events/Cargo.toml | 4 +- tools/test-framework/Cargo.toml | 4 +- 15 files changed, 104 insertions(+), 201 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d02823c4c0..d560bc318c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1764,13 +1764,14 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.30.0" +version = "0.31.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f844ebc1ddf70f2ad7cd5981a2feba261fff55e1ad6482c27551ee3c6cec7df4" +checksum = "ed65b85a5f119da1cc16c7482a8331befca4a1034095e729dddcf93be1b3415a" dependencies = [ "base64 0.21.0", "bytes", "flex-error", + "ics23", "prost", "serde", "subtle-encoding", @@ -1981,15 +1982,17 @@ dependencies = [ [[package]] name = "ics23" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352b6bbf6a07602cf8def05362987835a255d3312eae59c1af358af3ac57e0cc" +checksum = "af9e8f569c5cc88e08b8d076dc207e0748aa1f52d4b84910ec919c8f2bed6ea7" dependencies = [ "anyhow", "bytes", "hex", + "pbjson", "prost", "ripemd", + "serde", "sha2 0.10.6", "sha3", ] @@ -2645,6 +2648,16 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +[[package]] +name = "pbjson" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048f9ac93c1eab514f9470c4bc8d97ca2a0a236b84f45cc19d69a59fc11467f6" +dependencies = [ + "base64 0.13.1", + "serde", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -3940,8 +3953,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ec6b25b028097ab682ffae11d09d64fe1e2535833b902f26a278a0f88a705" dependencies = [ "bytes", "digest 0.10.6", @@ -3970,8 +3984,9 @@ dependencies = [ [[package]] name = "tendermint-config" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dbb7610ef8422d5886116868e48ab6a9ea72859b3bf9021c6d87318e5600225" dependencies = [ "flex-error", "serde", @@ -3983,8 +3998,9 @@ dependencies = [ [[package]] name = "tendermint-light-client" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9940a1376b5c1e3e5759143bc4308a7114f6293167ca5f05365d3386389de0ff" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4007,8 +4023,9 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765f272201f8dd04067498421b68a449a48623bf8f4df69b7e50071bec193daf" dependencies = [ "contracts", "crossbeam-channel 0.4.4", @@ -4030,8 +4047,9 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4bc4c47cf36e740645e04128bd14ff5723aef86f5377fbd4d3b0149198dfc7e" dependencies = [ "derive_more", "flex-error", @@ -4042,8 +4060,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23c8ff0e6634eb4c3c4aeed45076dc97dac91aac5501a905a67fa222e165b" dependencies = [ "bytes", "flex-error", @@ -4059,8 +4078,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2cc789170db5a35d4e0bb2490035c03ef96df08f119bee25fd8dab5a09aa25" dependencies = [ "async-trait", "async-tungstenite", @@ -4094,8 +4114,9 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.31.1" -source = "git+https://github.com/informalsystems/tendermint-rs.git?branch=romac/new-misbehavior-detector#be556506503ac75026683c54bdf89361ce3534a1" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023911e751fea64f20cd13bb9e15b5aae283aa3c7aaeb7e9bec1512032b32c99" dependencies = [ "ed25519-consensus", "gumdrop", diff --git a/Cargo.toml b/Cargo.toml index a3ccecb492..7afead91cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,10 @@ members = [ [patch.crates-io] # ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs.git", branch = "main" } -tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-light-client = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-light-client-detector = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } -tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-rpc = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-light-client = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-light-client-detector = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } +# tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "romac/new-misbehavior-detector" } diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index 51640603f0..fd3b49bfea 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -12,9 +12,9 @@ description = """ """ [dependencies] -ibc-proto = { version = "0.30.0" } +ibc-proto = { version = "0.31.0-alpha.2" } ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["std"] } -tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } +tendermint-rpc = { version = "0.32.0", features = ["http-client", "websocket-client"] } async-trait = "0.1.67" flex-error = { version = "0.4.4", default-features = false } diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index 2a831aa42f..5659989456 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -58,15 +58,15 @@ tracing = "0.1.36" tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"]} [dependencies.tendermint] -version = "0.31.1" +version = "0.32.0" features = ["secp256k1"] [dependencies.tendermint-rpc] -version = "0.31.1" +version = "0.32.0" features = ["http-client", "websocket-client"] [dependencies.tendermint-light-client-verifier] -version = "0.31.1" +version = "0.32.0" [dependencies.abscissa_core] version = "=0.6.0" diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 1c22918cd0..71eab7d0a0 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -27,7 +27,7 @@ mocks = ["tendermint-testgen", "clock", "std"] [dependencies] # Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.30.0", default-features = false } +ibc-proto = { version = "0.31.0-alpha.2", default-features = false } ics23 = { version = "0.10.0", default-features = false, features = ["host-functions"] } time = { version = ">=0.3.0, <0.3.21", default-features = false } serde_derive = { version = "1.0.104", default-features = false } @@ -47,20 +47,20 @@ dyn-clone = "1.0.8" num-rational = "0.4.1" [dependencies.tendermint] -version = "0.31.1" +version = "0.32.0" default-features = false [dependencies.tendermint-proto] -version = "0.31.1" +version = "0.32.0" default-features = false [dependencies.tendermint-light-client-verifier] -version = "0.31.1" +version = "0.32.0" default-features = false features = ["rust-crypto"] [dependencies.tendermint-testgen] -version = "0.31.1" +version = "0.32.0" optional = true default-features = false @@ -69,5 +69,5 @@ env_logger = "0.10.0" tracing = { version = "0.1.36", default-features = false } tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } test-log = { version = "0.2.10", features = ["trace"] } -tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } -tendermint-testgen = { version = "0.31.1" } # Needed for generating (synthetic) light blocks. +tendermint-rpc = { version = "0.32.0", features = ["http-client", "websocket-client"] } +tendermint-testgen = { version = "0.32.0" } # Needed for generating (synthetic) light blocks. diff --git a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs index 1ad048dfc6..16d467f692 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs @@ -27,7 +27,7 @@ use crate::Height; pub const TENDERMINT_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.ClientState"; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ClientState { pub chain_id: ChainId, pub trust_threshold: TrustThreshold, diff --git a/crates/relayer-types/src/core/ics23_commitment/commitment.rs b/crates/relayer-types/src/core/ics23_commitment/commitment.rs index 82c105538a..6b559d7517 100644 --- a/crates/relayer-types/src/core/ics23_commitment/commitment.rs +++ b/crates/relayer-types/src/core/ics23_commitment/commitment.rs @@ -1,13 +1,14 @@ -use crate::core::ics23_commitment::error::Error; -use crate::prelude::*; -use crate::proofs::ProofError; -use crate::tx_msg::encode_message; - use core::{convert::TryFrom, fmt}; -use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; use serde::{Deserialize, Serialize}; use subtle_encoding::{Encoding, Hex}; +use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; + +use crate::prelude::*; +use crate::proofs::ProofError; +use crate::tx_msg::encode_message; + +use super::error::Error; use super::merkle::MerkleProof; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/crates/relayer-types/src/core/ics23_commitment/merkle.rs b/crates/relayer-types/src/core/ics23_commitment/merkle.rs index 365b0e5554..55ac966f1c 100644 --- a/crates/relayer-types/src/core/ics23_commitment/merkle.rs +++ b/crates/relayer-types/src/core/ics23_commitment/merkle.rs @@ -34,35 +34,18 @@ pub struct MerkleProof { } /// Convert to ics23::CommitmentProof -/// The encoding and decoding shouldn't fail since ics23::CommitmentProof and ibc_proto::ics23::CommitmentProof should be the same -/// Ref. impl From for MerkleProof { fn from(proof: RawMerkleProof) -> Self { - let proofs: Vec = proof - .proofs - .into_iter() - .map(|p| { - let mut encoded = Vec::new(); - prost::Message::encode(&p, &mut encoded).unwrap(); - prost::Message::decode(&*encoded).unwrap() - }) - .collect(); - Self { proofs } + Self { + proofs: proof.proofs, + } } } impl From for RawMerkleProof { fn from(proof: MerkleProof) -> Self { Self { - proofs: proof - .proofs - .into_iter() - .map(|p| { - let mut encoded = Vec::new(); - prost::Message::encode(&p, &mut encoded).unwrap(); - prost::Message::decode(&*encoded).unwrap() - }) - .collect(), + proofs: proof.proofs, } } } @@ -253,7 +236,8 @@ pub fn convert_tm_to_ics_merkle_proof(tm_proof: &TendermintProof) -> Result); impl ProofSpecs { /// Returns the specification for Cosmos-SDK proofs pub fn cosmos() -> Self { - vec![ + Self(vec![ ics23::iavl_spec(), // Format of proofs-iavl (iavl merkle proofs) ics23::tendermint_spec(), // Format of proofs-tendermint (crypto/ merkle SimpleProof) - ] - .into() + ]) } pub fn is_empty(&self) -> bool { self.0.is_empty() } -} -impl Default for ProofSpecs { - fn default() -> Self { - Self::cosmos() + pub fn into_vec(self) -> Vec { + self.0 } } -impl From> for ProofSpecs { - fn from(ibc_specs: Vec) -> Self { - Self(ibc_specs.into_iter().map(ProofSpec).collect()) +impl From for Vec { + fn from(proof_specs: ProofSpecs) -> Self { + proof_specs.into_vec() } } -impl From> for ProofSpecs { - fn from(ics23_specs: Vec) -> Self { - Self( - ics23_specs - .into_iter() - .map(|ics23_spec| ics23_spec.into()) - .collect(), - ) +impl From> for ProofSpecs { + fn from(proof_specs: Vec) -> Self { + Self(proof_specs) } } -impl From for Vec { - fn from(specs: ProofSpecs) -> Self { - specs.0.into_iter().map(|spec| spec.into()).collect() - } -} - -impl From for Vec { - fn from(specs: ProofSpecs) -> Self { - specs.0.into_iter().map(|spec| spec.0).collect() - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -struct ProofSpec(IbcProofSpec); - -impl From for ProofSpec { - fn from(spec: Ics23ProofSpec) -> Self { - Self(IbcProofSpec { - leaf_spec: spec.leaf_spec.map(|lop| LeafOp::from(lop).0), - inner_spec: spec.inner_spec.map(|ispec| InnerSpec::from(ispec).0), - max_depth: spec.max_depth, - min_depth: spec.min_depth, - }) - } -} - -impl From for Ics23ProofSpec { - fn from(spec: ProofSpec) -> Self { - let spec = spec.0; - - Ics23ProofSpec { - leaf_spec: spec.leaf_spec.map(|lop| LeafOp(lop).into()), - inner_spec: spec.inner_spec.map(|ispec| InnerSpec(ispec).into()), - max_depth: spec.max_depth, - min_depth: spec.min_depth, - prehash_key_before_comparison: false, - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -struct LeafOp(IbcLeafOp); - -impl From for LeafOp { - fn from(leaf_op: Ics23LeafOp) -> Self { - Self(IbcLeafOp { - hash: leaf_op.hash, - prehash_key: leaf_op.prehash_key, - prehash_value: leaf_op.prehash_value, - length: leaf_op.length, - prefix: leaf_op.prefix, - }) - } -} - -impl From for Ics23LeafOp { - fn from(leaf_op: LeafOp) -> Self { - let leaf_op = leaf_op.0; - Ics23LeafOp { - hash: leaf_op.hash, - prehash_key: leaf_op.prehash_key, - prehash_value: leaf_op.prehash_value, - length: leaf_op.length, - prefix: leaf_op.prefix, - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -struct InnerSpec(IbcInnerSpec); - -impl From for InnerSpec { - fn from(inner_spec: Ics23InnerSpec) -> Self { - Self(IbcInnerSpec { - child_order: inner_spec.child_order, - child_size: inner_spec.child_size, - min_prefix_length: inner_spec.min_prefix_length, - max_prefix_length: inner_spec.max_prefix_length, - empty_child: inner_spec.empty_child, - hash: inner_spec.hash, - }) - } -} - -impl From for Ics23InnerSpec { - fn from(inner_spec: InnerSpec) -> Self { - let inner_spec = inner_spec.0; - Ics23InnerSpec { - child_order: inner_spec.child_order, - child_size: inner_spec.child_size, - min_prefix_length: inner_spec.min_prefix_length, - max_prefix_length: inner_spec.max_prefix_length, - empty_child: inner_spec.empty_child, - hash: inner_spec.hash, - } +impl Default for ProofSpecs { + fn default() -> Self { + Self::cosmos() } } diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index eed540f979..3234a66ca7 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -21,7 +21,7 @@ profiling = [] telemetry = ["ibc-telemetry"] [dependencies] -ibc-proto = { version = "0.30.0" } +ibc-proto = { version = "0.31.0-alpha.2" } ibc-telemetry = { version = "0.23.0", path = "../telemetry", optional = true } ibc-relayer-types = { version = "0.23.0", path = "../relayer-types", features = ["mocks"] } @@ -78,20 +78,20 @@ version = "0.4.1" features = ["num-bigint", "serde"] [dependencies.tendermint] -version = "0.31.1" +version = "0.32.0" features = ["secp256k1"] [dependencies.tendermint-rpc] -version = "0.31.1" +version = "0.32.0" features = ["http-client", "websocket-client"] [dependencies.tendermint-light-client] -version = "0.31.1" +version = "0.32.0" default-features = false features = ["rpc-client", "secp256k1", "unstable"] [dependencies.tendermint-light-client-detector] -version = "0.31.1" +version = "0.32.0" default-features = false [dev-dependencies] @@ -102,4 +102,4 @@ tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "jso test-log = { version = "0.2.10", features = ["trace"] } # Needed for generating (synthetic) light blocks. -tendermint-testgen = { version = "0.31.1" } +tendermint-testgen = { version = "0.32.0" } diff --git a/crates/relayer/src/chain/counterparty.rs b/crates/relayer/src/chain/counterparty.rs index 8cc561b2e9..bc84564d78 100644 --- a/crates/relayer/src/chain/counterparty.rs +++ b/crates/relayer/src/chain/counterparty.rs @@ -132,7 +132,7 @@ pub fn connection_state_on_destination( } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ChannelConnectionClient { pub channel: IdentifiedChannelEnd, pub connection: IdentifiedConnectionEnd, diff --git a/crates/relayer/src/client_state.rs b/crates/relayer/src/client_state.rs index dacbe5bf4b..8c5eff288b 100644 --- a/crates/relayer/src/client_state.rs +++ b/crates/relayer/src/client_state.rs @@ -48,7 +48,7 @@ impl AnyUpgradeOptions { impl UpgradeOptions for AnyUpgradeOptions {} -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum AnyClientState { Tendermint(TmClientState), @@ -239,7 +239,7 @@ impl From<&dyn ClientState> for AnyClientState { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub struct IdentifiedAnyClientState { pub client_id: ClientId, diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index a68d69618e..f350894f1f 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -27,5 +27,5 @@ axum = "0.6.12" tokio = "1.26.0" [dependencies.tendermint] -version = "0.31.1" +version = "0.32.0" default-features = false diff --git a/tools/query-events/Cargo.toml b/tools/query-events/Cargo.toml index cf1b80fd5c..2c2e4a8b35 100644 --- a/tools/query-events/Cargo.toml +++ b/tools/query-events/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -tendermint = { version = "0.31.1" } -tendermint-rpc = { version = "0.31.1", features = ["http-client"] } +tendermint = { version = "0.32.0" } +tendermint-rpc = { version = "0.32.0", features = ["http-client"] } clap = { version = "3.2", features = ["derive"] } futures = "0.3.27" diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index 11d9381cbf..02f9a6b6c4 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -17,8 +17,8 @@ description = """ ibc-relayer-types = { version = "=0.23.0", path = "../../crates/relayer-types" } ibc-relayer = { version = "=0.23.0", path = "../../crates/relayer" } ibc-relayer-cli = { version = "=1.4.0", path = "../../crates/relayer-cli" } -ibc-proto = { version = "0.30.0" } -tendermint-rpc = { version = "0.31.1", features = ["http-client", "websocket-client"] } +ibc-proto = { version = "0.31.0-alpha.2" } +tendermint-rpc = { version = "0.32.0", features = ["http-client", "websocket-client"] } http = "0.2.9" tokio = { version = "1.0", features = ["full"] } From 237a52c56087e4712c09d5000cd8f399268324ea Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Tue, 16 May 2023 12:23:35 +0200 Subject: [PATCH 40/40] Add changelog entry --- .../features/ibc-relayer/3224-light-attacks-detector.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/unreleased/features/ibc-relayer/3224-light-attacks-detector.md diff --git a/.changelog/unreleased/features/ibc-relayer/3224-light-attacks-detector.md b/.changelog/unreleased/features/ibc-relayer/3224-light-attacks-detector.md new file mode 100644 index 0000000000..11748f753c --- /dev/null +++ b/.changelog/unreleased/features/ibc-relayer/3224-light-attacks-detector.md @@ -0,0 +1,7 @@ +- When enabled for misbehaviour (ie. when `mode.misbehaviour.enabled = true`), + Hermes will now monitors on-chain client updates and verify the submitted + headers comparing with headers it retrieves from its RPC node. + If it detects conflicting headers, it will now submit a `MisbehaviourMsg` + to the chain hosting the IBC client. + In addition, Hermes will also submit the evidence to the reference chain. + ([\#3224](https://github.com/informalsystems/hermes/issues/3224))