ibc_types_core_client/msgs/
upgrade_client.rs

1//! Definition of domain type msg `MsgUpgradeAnyClient`.
2
3use crate::prelude::*;
4
5use core::str::FromStr;
6
7use ibc_proto::{
8    google::protobuf::Any,
9    ibc::core::{
10        client::v1::MsgUpgradeClient as RawMsgUpgradeClient,
11        commitment::v1::MerkleProof as RawMerkleProof,
12    },
13};
14use ibc_types_domain_type::DomainType;
15use prost::Message;
16
17use crate::{error::Error, ClientId};
18
19/// A type of message that triggers the upgrade of an on-chain (IBC) client.
20#[derive(Clone, Debug, PartialEq)]
21pub struct MsgUpgradeClient {
22    // client unique identifier
23    pub client_id: ClientId,
24    // Upgraded client state
25    pub client_state: Any,
26    // Upgraded consensus state, only contains enough information
27    // to serve as a basis of trust in update logic
28    pub consensus_state: Any,
29    // proof that old chain committed to new client
30    pub proof_upgrade_client: RawMerkleProof,
31    // proof that old chain committed to new consensus state
32    pub proof_upgrade_consensus_state: RawMerkleProof,
33    // signer address
34    pub signer: String,
35}
36
37impl DomainType for MsgUpgradeClient {
38    type Proto = RawMsgUpgradeClient;
39}
40
41impl From<MsgUpgradeClient> for RawMsgUpgradeClient {
42    fn from(dm_msg: MsgUpgradeClient) -> RawMsgUpgradeClient {
43        RawMsgUpgradeClient {
44            client_id: dm_msg.client_id.to_string(),
45            client_state: Some(dm_msg.client_state),
46            consensus_state: Some(dm_msg.consensus_state),
47            proof_upgrade_client: dm_msg.proof_upgrade_client.encode_to_vec(),
48            proof_upgrade_consensus_state: dm_msg.proof_upgrade_consensus_state.encode_to_vec(),
49            signer: dm_msg.signer,
50        }
51    }
52}
53
54impl TryFrom<RawMsgUpgradeClient> for MsgUpgradeClient {
55    type Error = Error;
56
57    fn try_from(proto_msg: RawMsgUpgradeClient) -> Result<Self, Self::Error> {
58        let raw_client_state = proto_msg.client_state.ok_or(Error::MissingRawClientState)?;
59
60        let raw_consensus_state = proto_msg
61            .consensus_state
62            .ok_or(Error::MissingRawConsensusState)?;
63
64        Ok(MsgUpgradeClient {
65            client_id: ClientId::from_str(&proto_msg.client_id)
66                .map_err(Error::InvalidClientIdentifier)?,
67            client_state: raw_client_state,
68            consensus_state: raw_consensus_state,
69            proof_upgrade_client: RawMerkleProof::decode(proto_msg.proof_upgrade_client.as_ref())
70                .map_err(Error::InvalidUpgradeClientProof)?,
71            proof_upgrade_consensus_state: RawMerkleProof::decode(
72                proto_msg.proof_upgrade_consensus_state.as_ref(),
73            )
74            .map_err(Error::InvalidUpgradeConsensusStateProof)?,
75            signer: proto_msg.signer,
76        })
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    use crate::Height;
85
86    use crate::mock::{
87        client_state::MockClientState, consensus_state::MockConsensusState, header::MockHeader,
88    };
89
90    /// Returns a dummy `RawMerkleProof`, for testing only!
91    pub fn get_dummy_merkle_proof() -> RawMerkleProof {
92        use ibc_proto::ics23::CommitmentProof;
93
94        let parsed = CommitmentProof { proof: None };
95        let mproofs: vec::Vec<CommitmentProof> = vec![parsed];
96        RawMerkleProof { proofs: mproofs }
97    }
98
99    /*
100       pub fn get_dummy_proof() -> Vec<u8> {
101           "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy"
102               .as_bytes()
103               .to_vec()
104       }
105
106       /// Returns a dummy `RawMsgUpgradeClient`, for testing only!
107       pub fn get_dummy_raw_msg_upgrade_client(height: Height) -> RawMsgUpgradeClient {
108           RawMsgUpgradeClient {
109               client_id: "tendermint".parse().unwrap(),
110               client_state: Some(MockClientState::new(MockHeader::new(height)).into()),
111               consensus_state: Some(MockConsensusState::new(MockHeader::new(height)).into()),
112               proof_upgrade_client: get_dummy_proof(),
113               proof_upgrade_consensus_state: get_dummy_proof(),
114               signer: "dummy_signer".to_string(),
115           }
116       }
117    */
118
119    #[test]
120    fn msg_upgrade_client_serialization() {
121        let client_id: ClientId = "tendermint".parse().unwrap();
122        let signer = "dummy_signer".to_string();
123
124        let height = Height::new(1, 1).unwrap();
125
126        let client_state = MockClientState::new(MockHeader::new(height));
127        let consensus_state = MockConsensusState::new(MockHeader::new(height));
128
129        let proof = get_dummy_merkle_proof();
130
131        let msg = MsgUpgradeClient {
132            client_id,
133            client_state: client_state.into(),
134            consensus_state: consensus_state.into(),
135            proof_upgrade_client: proof.clone(),
136            proof_upgrade_consensus_state: proof,
137            signer,
138        };
139
140        let raw: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg.clone());
141        let msg_back = MsgUpgradeClient::try_from(raw.clone()).unwrap();
142        let raw_back: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg_back.clone());
143        assert_eq!(msg, msg_back);
144        assert_eq!(raw, raw_back);
145    }
146}