Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: verify commitment proofs as secp256k1 signatures #8

Merged
merged 11 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 14 additions & 24 deletions .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ jobs:
test-msrv:
name: Test MSRV for `ibc` libraries
timeout-minutes: 30
env:
CARGO_MSRV_VERSION: 0.16.3
MSRV: 1.75.0
strategy:
matrix:
param:
Expand All @@ -100,30 +97,23 @@ jobs:
runs-on: ${{ matrix.param.os }}
steps:
- uses: actions/checkout@v4

- name: Download cargo-msrv
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: foresterre/cargo-msrv
version: "tags/v${{ env.CARGO_MSRV_VERSION }}"
file: "cargo-msrv-x86_64-${{ matrix.param.system }}-v${{ env.CARGO_MSRV_VERSION }}.tgz"

- uses: actions-rust-lang/setup-rust-toolchain@v1
- uses: taiki-e/install-action@v2
with:
toolchain: ${{ env.MSRV }}
tool: cargo-hack,cargo-binstall

- name: Install cargo-msrv
run: |
tar -xzf "cargo-msrv-x86_64-${{ matrix.param.system }}-v${{ env.CARGO_MSRV_VERSION }}.tgz"
mv "cargo-msrv-x86_64-${{ matrix.param.system }}-v${{ env.CARGO_MSRV_VERSION }}/cargo-msrv" ~/.cargo/bin
cargo msrv --version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: cargo binstall --no-confirm cargo-msrv --force

- name: Calculate MSRV
run: cargo msrv find --output-format minimal --min 1.68.0
- name: Verify and Test Rust version
run: |
cargo hack msrv verify --output-format=minimal --all-features
cargo hack --rust-version test --all-targets --all-features

- name: Build with MSRV
uses: actions-rs/cargo@v1
with:
toolchain: ${{ env.MSRV }}
command: build
args: --all-features
- name: Find MSRV
if: ${{ failure() }}
run: |
cargo hack msrv find --min=1.75 --output-format=minimal --all-features
exit 1
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ibc-clients/cw-context/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ prost = { workspace = true }
# ibc dependencies
ibc-core = { workspace = true }
ibc-client-wasm-types = { workspace = true, features = [ "schema" ] }
ibc-client-tendermint = { workspace = true }

# cosmwasm dependencies
cosmwasm-schema = { workspace = true }
Expand Down
20 changes: 20 additions & 0 deletions ibc-clients/cw-context/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use core::fmt::Display;

use ibc_client_tendermint::client_state::ClientState as TmClientState;
use ibc_core::client::context::client_state::ClientStateExecution;
use ibc_core::client::context::consensus_state::ConsensusState as ConsensusStateTrait;
use ibc_core::primitives::proto::Any;

use crate::context::client_ctx::CwClientExecution;
use crate::context::Context;

/// Enables users to integrate their implemented light client by introducing
Expand All @@ -17,3 +19,21 @@ where
type ClientState: ClientStateExecution<Context<'a, Self>>;
type ConsensusState: ConsensusStateTrait;
}

pub trait CwClientStateExecution<'a, E: CwClientExecution<'a>>: ClientStateExecution<E> {
fn public_key(&self) -> Option<Vec<u8>>;
}

impl<'a, T> CwClientStateExecution<'a, Context<'a, T>> for TmClientState
where
T: ClientType<'a>,
<T as ClientType<'a>>::ClientState: From<ibc_client_tendermint::types::ClientState>,
<T as ClientType<'a>>::ConsensusState: From<ibc_client_tendermint::types::ConsensusState>,
ibc_client_tendermint::types::ConsensusState: From<<T as ClientType<'a>>::ConsensusState>,
<<T as ClientType<'a>>::ClientState as TryFrom<Any>>::Error: Display,
<<T as ClientType<'a>>::ConsensusState as TryFrom<Any>>::Error: Display,
{
fn public_key(&self) -> Option<Vec<u8>> {
None
}
}
4 changes: 2 additions & 2 deletions ibc-clients/cw-context/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ where
<C::ClientState as TryFrom<Any>>::Error: Display,
<C::ConsensusState as TryFrom<Any>>::Error: Display,
{
deps: Option<Deps<'a, Q>>,
deps_mut: Option<DepsMut<'a, Q>>,
pub deps: Option<Deps<'a, Q>>,
pub deps_mut: Option<DepsMut<'a, Q>>,
env: Env,
client_id: ClientId,
checksum: Option<Binary>,
Expand Down
89 changes: 87 additions & 2 deletions ibc-clients/cw-context/src/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use core::fmt::Display;

use cosmwasm_std::{to_json_binary, Binary};
use cosmwasm_std::{to_json_binary, Binary, Checksum};
use ibc_core::client::context::prelude::*;
use ibc_core::host::types::error::DecodingError;
use ibc_core::host::types::path::ClientConsensusStatePath;
use ibc_core::primitives::proto::Any;
use prost::Message;

use crate::api::ClientType;
use crate::api::{ClientType, CwClientStateExecution};
use crate::context::Context;
use crate::types::{
CheckForMisbehaviourMsg, CheckForMisbehaviourResponse, ContractError, ContractResult,
Expand All @@ -17,10 +17,45 @@ use crate::types::{
VerifyUpgradeAndUpdateStateMsg,
};

#[derive(Debug)]
pub struct MembershipVerifierContainer {
pub state_root: Vec<u8>,
pub prefix: Vec<u8>,
pub path: Vec<u8>,
pub value: Option<Vec<u8>>,
}

impl MembershipVerifierContainer {
pub fn canonical_bytes(self) -> Vec<u8> {
let mut bytes = Vec::new();

let encode_bytes = |mut data: Vec<u8>, output: &mut Vec<u8>| {
let len = data.len() as u64;
output.extend(len.to_be_bytes());
output.append(&mut data);
};

encode_bytes(self.state_root, &mut bytes);
encode_bytes(self.prefix, &mut bytes);
encode_bytes(self.path, &mut bytes);

if let Some(v) = self.value {
encode_bytes(v, &mut bytes);
}

bytes
}
Farhad-Shabani marked this conversation as resolved.
Show resolved Hide resolved

pub fn checksum(self) -> Checksum {
Checksum::generate(&self.canonical_bytes())
}
}

impl<'a, C: ClientType<'a>> Context<'a, C>
where
<C::ClientState as TryFrom<Any>>::Error: Display,
<C::ConsensusState as TryFrom<Any>>::Error: Display,
C::ClientState: CwClientStateExecution<'a, Self>,
{
/// Instantiates a new client with the given [`InstantiateMsg`] message.
pub fn instantiate(&mut self, msg: InstantiateMsg) -> Result<Binary, ContractError> {
Expand Down Expand Up @@ -74,6 +109,31 @@ where

let consensus_state = self.consensus_state(&client_cons_state_path)?;

if let Some(pub_key) = client_state.public_key() {
let deps_mut = self
.deps_mut
.as_mut()
.expect("no error because of sudo message")
.branch();

let message = MembershipVerifierContainer {
state_root: consensus_state.root().as_bytes().to_vec(),
prefix: msg.prefix.as_bytes().to_vec(),
path: msg.path.as_ref().to_vec(),
value: Some(msg.value.clone()),
};

match deps_mut.api.secp256k1_verify(
message.checksum().as_slice(),
msg.proof.as_ref(),
&pub_key,
) {
Ok(true) => {}
Ok(false) => panic!("secp256k1_verify failed for {:?}", msg),
Err(e) => panic!("secp256k1_verify error: {:?}", e),
}
}

client_state.verify_membership_raw(
&msg.prefix,
&msg.proof,
Expand All @@ -95,6 +155,31 @@ where

let consensus_state = self.consensus_state(&client_cons_state_path)?;

if let Some(pub_key) = client_state.public_key() {
let deps_mut = self
.deps_mut
.as_mut()
.expect("no error because of sudo message")
.branch();

let message = MembershipVerifierContainer {
state_root: consensus_state.root().as_bytes().to_vec(),
prefix: msg.prefix.as_bytes().to_vec(),
path: msg.path.as_ref().to_vec(),
value: None,
};

match deps_mut.api.secp256k1_verify(
message.checksum().as_slice(),
msg.proof.as_ref(),
&pub_key,
) {
Ok(true) => {}
Ok(false) => panic!("secp256k1_verify failed for {:?}", msg),
Err(e) => panic!("secp256k1_verify error: {:?}", e),
}
}

client_state.verify_non_membership_raw(
&msg.prefix,
&msg.proof,
Expand Down
2 changes: 2 additions & 0 deletions ibc-clients/cw-context/src/types/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ pub struct VerifyMembershipMsgRaw {
pub delay_time_period: u64,
}

#[derive(Debug)]
Farhad-Shabani marked this conversation as resolved.
Show resolved Hide resolved
pub struct VerifyMembershipMsg {
pub prefix: CommitmentPrefix,
pub proof: CommitmentProofBytes,
Expand Down Expand Up @@ -169,6 +170,7 @@ pub struct VerifyNonMembershipMsgRaw {
pub delay_time_period: u64,
}

#[derive(Debug)]
Farhad-Shabani marked this conversation as resolved.
Show resolved Hide resolved
pub struct VerifyNonMembershipMsg {
pub prefix: CommitmentPrefix,
pub proof: CommitmentProofBytes,
Expand Down
Loading