Skip to content

Commit c16a311

Browse files
committed
feat(core): proof commitments
1 parent 32e56a6 commit c16a311

File tree

10 files changed

+669
-329
lines changed

10 files changed

+669
-329
lines changed

cosmwasm/ibc-union/core/msg/src/msg.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub enum ExecuteMsg {
5151
PacketSend(MsgSendPacket),
5252
WriteAcknowledgement(MsgWriteAcknowledgement),
5353
MigrateState(MsgMigrateState),
54+
CommitMembershipProof(MsgCommitMembershipProof),
55+
CommitNonMembershipProof(MsgCommitNonMembershipProof),
5456
}
5557

5658
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -243,3 +245,22 @@ pub struct MsgSendPacket {
243245
pub timeout_timestamp: Timestamp,
244246
pub data: Bytes,
245247
}
248+
249+
#[derive(Debug, Clone, Serialize, Deserialize)]
250+
#[serde(deny_unknown_fields)]
251+
pub struct MsgCommitMembershipProof {
252+
pub client_id: ClientId,
253+
pub proof_height: u64,
254+
pub proof: Bytes,
255+
pub path: Bytes,
256+
pub value: Bytes,
257+
}
258+
259+
#[derive(Debug, Clone, Serialize, Deserialize)]
260+
#[serde(deny_unknown_fields)]
261+
pub struct MsgCommitNonMembershipProof {
262+
pub client_id: ClientId,
263+
pub proof_height: u64,
264+
pub proof: Bytes,
265+
pub path: Bytes,
266+
}

cosmwasm/ibc-union/core/msg/src/query.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use ibc_union_spec::{ChannelId, ClientId, ConnectionId};
2-
use unionlabs_primitives::H256;
2+
use unionlabs_primitives::{Bytes, H256};
33
#[derive(serde::Serialize, serde::Deserialize, Debug)]
44
#[serde(deny_unknown_fields, rename_all = "snake_case")]
55
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@@ -30,6 +30,18 @@ pub enum QueryMsg {
3030
GetBatchPackets { batch_hash: H256 },
3131
#[cfg_attr(feature = "cw-orch-interface", returns(Option<H256>))]
3232
GetBatchReceipts { batch_hash: H256 },
33+
#[cfg_attr(feature = "cw-orch-interface", returns(Option<H256>))]
34+
GetCommittedMembershipProof {
35+
client_id: ClientId,
36+
proof_height: u64,
37+
path: Bytes,
38+
},
39+
#[cfg_attr(feature = "cw-orch-interface", returns(bool))]
40+
GetCommittedNonMembershipProof {
41+
client_id: ClientId,
42+
proof_height: u64,
43+
path: Bytes,
44+
},
3345
#[cfg_attr(feature = "cw-orch-interface", returns(cosmwasm_std::Addr))]
3446
GetClientImpl { client_id: ClientId },
3547
#[cfg_attr(feature = "cw-orch-interface", returns(String))]

cosmwasm/ibc-union/core/src/contract.rs

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use ibc_union_msg::{
1818
msg::{
1919
ExecuteMsg, InitMsg, MsgBatchAcks, MsgBatchSend, MsgChannelCloseConfirm,
2020
MsgChannelCloseInit, MsgChannelOpenAck, MsgChannelOpenConfirm, MsgChannelOpenInit,
21-
MsgChannelOpenTry, MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit,
21+
MsgChannelOpenTry, MsgCommitMembershipProof, MsgCommitNonMembershipProof,
22+
MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit,
2223
MsgConnectionOpenTry, MsgCreateClient, MsgForceUpdateClient, MsgIntentPacketRecv,
2324
MsgMigrateState, MsgPacketAcknowledgement, MsgPacketRecv, MsgPacketTimeout,
2425
MsgRegisterClient, MsgSendPacket, MsgUpdateClient, MsgWriteAcknowledgement,
@@ -28,7 +29,8 @@ use ibc_union_msg::{
2829
use ibc_union_spec::{
2930
path::{
3031
commit_packets, BatchPacketsPath, BatchReceiptsPath, ChannelPath, ClientStatePath,
31-
ConnectionPath, ConsensusStatePath, COMMITMENT_MAGIC, COMMITMENT_MAGIC_ACK,
32+
ConnectionPath, ConsensusStatePath, MembershipProofPath, NonMembershipProofPath,
33+
COMMITMENT_MAGIC, COMMITMENT_MAGIC_ACK, NON_MEMBERSHIP_COMMITMENT_VALUE,
3234
},
3335
Channel, ChannelId, ChannelState, ClientId, Connection, ConnectionId, ConnectionState,
3436
MustBeZero, Packet, Status, Timestamp,
@@ -80,6 +82,10 @@ pub mod events {
8082
pub const BATCH_ACKS: &str = "batch_acks";
8183
pub const WRITE_ACK: &str = "write_ack";
8284
}
85+
pub mod proof {
86+
pub const COMMIT_MEMBERSHIP: &str = "commit_membership_proof";
87+
pub const COMMIT_NON_MEMBERSHIP: &str = "commit_non_membership_proof";
88+
}
8389
pub mod attribute {
8490
pub const CLIENT_ID: &str = "client_id";
8591
pub const CONNECTION_ID: &str = "connection_id";
@@ -105,6 +111,9 @@ pub mod events {
105111
pub const PORT_ID: &str = "port_id";
106112
pub const COUNTERPARTY_PORT_ID: &str = "counterparty_port_id";
107113
pub const VERSION: &str = "version";
114+
pub const PATH: &str = "path";
115+
pub const VALUE: &str = "value";
116+
pub const PROOF_HEIGHT: &str = "proof_height";
108117
}
109118
}
110119

@@ -623,6 +632,25 @@ pub fn execute(
623632
.add_attribute("relayer", relayer),
624633
))
625634
}
635+
ExecuteMsg::CommitMembershipProof(MsgCommitMembershipProof {
636+
client_id,
637+
proof_height,
638+
proof,
639+
path,
640+
value,
641+
}) => {
642+
ensure_relayer(deps.storage, &info.sender)?;
643+
commit_membership_proof(deps, client_id, proof_height, proof, path, value)
644+
}
645+
ExecuteMsg::CommitNonMembershipProof(MsgCommitNonMembershipProof {
646+
client_id,
647+
proof_height,
648+
proof,
649+
path,
650+
}) => {
651+
ensure_relayer(deps.storage, &info.sender)?;
652+
commit_non_membership_proof(deps, client_id, proof_height, proof, path)
653+
}
626654
}
627655
}
628656

@@ -2206,6 +2234,45 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, ContractErr
22062234
let commit = read_commit(deps, &BatchReceiptsPath { batch_hash }.key());
22072235
Ok(to_json_binary(&commit)?)
22082236
}
2237+
QueryMsg::GetCommittedMembershipProof {
2238+
client_id,
2239+
proof_height,
2240+
path,
2241+
} => {
2242+
let commit = read_commit(
2243+
deps,
2244+
&MembershipProofPath {
2245+
client_id,
2246+
proof_height,
2247+
path,
2248+
}
2249+
.key(),
2250+
);
2251+
Ok(to_json_binary(&commit)?)
2252+
}
2253+
QueryMsg::GetCommittedNonMembershipProof {
2254+
client_id,
2255+
proof_height,
2256+
path,
2257+
} => {
2258+
let commit = read_commit(
2259+
deps,
2260+
&NonMembershipProofPath {
2261+
client_id,
2262+
proof_height,
2263+
path,
2264+
}
2265+
.key(),
2266+
);
2267+
2268+
if commit.is_none() {
2269+
Ok(to_json_binary(&false)?)
2270+
} else if commit == Some(NON_MEMBERSHIP_COMMITMENT_VALUE) {
2271+
Ok(to_json_binary(&true)?)
2272+
} else {
2273+
unreachable!()
2274+
}
2275+
}
22092276
}
22102277
}
22112278

@@ -2238,6 +2305,87 @@ fn make_verify_creation_event(client_id: ClientId, event: VerifyCreationResponse
22382305
}
22392306
}
22402307

2308+
fn commit_membership_proof(
2309+
deps: DepsMut,
2310+
client_id: ClientId,
2311+
proof_height: u64,
2312+
proof: Bytes,
2313+
path: Bytes,
2314+
value: Bytes,
2315+
) -> Result<Response, ContractError> {
2316+
let client_impl = client_impl(deps.as_ref(), client_id)?;
2317+
2318+
query_light_client::<()>(
2319+
deps.as_ref(),
2320+
client_impl,
2321+
LightClientQuery::VerifyMembership {
2322+
client_id,
2323+
height: proof_height,
2324+
proof: proof.to_vec().into(),
2325+
path: path.clone(),
2326+
value: value.clone(),
2327+
},
2328+
)?;
2329+
2330+
store_commit(
2331+
deps,
2332+
&MembershipProofPath {
2333+
client_id,
2334+
proof_height,
2335+
path: path.clone(),
2336+
}
2337+
.key(),
2338+
&commit(&value),
2339+
);
2340+
2341+
Ok(Response::new().add_event(
2342+
Event::new(events::proof::COMMIT_MEMBERSHIP)
2343+
.add_attribute(events::attribute::CLIENT_ID, client_id.to_string())
2344+
.add_attribute(events::attribute::PROOF_HEIGHT, proof_height.to_string())
2345+
.add_attribute(events::attribute::PATH, path.to_string())
2346+
.add_attribute(events::attribute::VALUE, value.to_string()),
2347+
))
2348+
}
2349+
2350+
fn commit_non_membership_proof(
2351+
deps: DepsMut,
2352+
client_id: ClientId,
2353+
proof_height: u64,
2354+
proof: Bytes,
2355+
path: Bytes,
2356+
) -> Result<Response, ContractError> {
2357+
let client_impl = client_impl(deps.as_ref(), client_id)?;
2358+
2359+
query_light_client::<()>(
2360+
deps.as_ref(),
2361+
client_impl,
2362+
LightClientQuery::VerifyNonMembership {
2363+
client_id,
2364+
height: proof_height,
2365+
proof: proof.to_vec().into(),
2366+
path: path.clone(),
2367+
},
2368+
)?;
2369+
2370+
store_commit(
2371+
deps,
2372+
&NonMembershipProofPath {
2373+
client_id,
2374+
proof_height,
2375+
path: path.clone(),
2376+
}
2377+
.key(),
2378+
&commit(NON_MEMBERSHIP_COMMITMENT_VALUE),
2379+
);
2380+
2381+
Ok(Response::new().add_event(
2382+
Event::new(events::proof::COMMIT_NON_MEMBERSHIP)
2383+
.add_attribute(events::attribute::CLIENT_ID, client_id.to_string())
2384+
.add_attribute(events::attribute::PROOF_HEIGHT, proof_height.to_string())
2385+
.add_attribute(events::attribute::PATH, path.to_string()),
2386+
))
2387+
}
2388+
22412389
#[cfg(test)]
22422390
mod tests {
22432391
use hex_literal::hex;

lib/ibc-union-spec/src/datagram.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum Datagram {
3434
IntentPacketRecv(MsgIntentPacketRecv),
3535
BatchSend(MsgBatchSend),
3636
BatchAcks(MsgBatchAcks),
37+
CommitMembershipProof(MsgCommitMembershipProof),
38+
CommitNonMembershipProof(MsgCommitNonMembershipProof),
3739
}
3840

3941
impl Datagram {
@@ -59,6 +61,8 @@ impl Datagram {
5961
Self::IntentPacketRecv(_msg) => todo!(),
6062
Self::BatchSend(_msg) => todo!(),
6163
Self::BatchAcks(_msg) => todo!(),
64+
Self::CommitMembershipProof(msg) => Some(Height::new(msg.proof_height)),
65+
Self::CommitNonMembershipProof(msg) => Some(Height::new(msg.proof_height)),
6266
}
6367
}
6468

@@ -82,6 +86,8 @@ impl Datagram {
8286
Self::IntentPacketRecv(_) => "intent_packet_recv",
8387
Self::BatchSend(_) => "batch_send",
8488
Self::BatchAcks(_) => "batch_acks",
89+
Self::CommitMembershipProof(_) => "commit_membership_proof",
90+
Self::CommitNonMembershipProof(_) => "commit_non_membership_proof",
8591
}
8692
}
8793
}
@@ -319,3 +325,32 @@ pub struct MsgBatchAcks {
319325
// TODO: Ensure same length as packets somehow (maybe zip the lists into one field?)
320326
pub acks: Vec<Bytes>,
321327
}
328+
329+
#[derive(Debug, Clone, PartialEq, Eq)]
330+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
331+
#[cfg_attr(
332+
feature = "serde",
333+
derive(serde::Serialize, serde::Deserialize),
334+
serde(rename_all = "snake_case", deny_unknown_fields)
335+
)]
336+
pub struct MsgCommitMembershipProof {
337+
pub client_id: ClientId,
338+
pub proof_height: u64,
339+
pub proof: Bytes,
340+
pub path: Bytes,
341+
pub value: Bytes,
342+
}
343+
344+
#[derive(Debug, Clone, PartialEq, Eq)]
345+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
346+
#[cfg_attr(
347+
feature = "serde",
348+
derive(serde::Serialize, serde::Deserialize),
349+
serde(rename_all = "snake_case", deny_unknown_fields)
350+
)]
351+
pub struct MsgCommitNonMembershipProof {
352+
pub client_id: ClientId,
353+
pub proof_height: u64,
354+
pub proof: Bytes,
355+
pub path: Bytes,
356+
}

0 commit comments

Comments
 (0)