use crate::prelude::*;
use core::str::FromStr;
use ibc_proto::{
google::protobuf::Any,
ibc::core::{
client::v1::MsgUpgradeClient as RawMsgUpgradeClient,
commitment::v1::MerkleProof as RawMerkleProof,
},
};
use ibc_types_domain_type::{DomainType, TypeUrl};
use prost::Message;
use crate::{error::Error, ClientId};
#[derive(Clone, Debug, PartialEq)]
pub struct MsgUpgradeClient {
pub client_id: ClientId,
pub client_state: Any,
pub consensus_state: Any,
pub proof_upgrade_client: RawMerkleProof,
pub proof_upgrade_consensus_state: RawMerkleProof,
pub signer: String,
}
impl TypeUrl for MsgUpgradeClient {
const TYPE_URL: &'static str = "/ibc.core.client.v1.MsgUpgradeClient";
}
impl DomainType for MsgUpgradeClient {
type Proto = RawMsgUpgradeClient;
}
impl From<MsgUpgradeClient> for RawMsgUpgradeClient {
fn from(dm_msg: MsgUpgradeClient) -> RawMsgUpgradeClient {
RawMsgUpgradeClient {
client_id: dm_msg.client_id.to_string(),
client_state: Some(dm_msg.client_state),
consensus_state: Some(dm_msg.consensus_state),
proof_upgrade_client: dm_msg.proof_upgrade_client.encode_to_vec(),
proof_upgrade_consensus_state: dm_msg.proof_upgrade_consensus_state.encode_to_vec(),
signer: dm_msg.signer,
}
}
}
impl TryFrom<RawMsgUpgradeClient> for MsgUpgradeClient {
type Error = Error;
fn try_from(proto_msg: RawMsgUpgradeClient) -> Result<Self, Self::Error> {
let raw_client_state = proto_msg.client_state.ok_or(Error::MissingRawClientState)?;
let raw_consensus_state = proto_msg
.consensus_state
.ok_or(Error::MissingRawConsensusState)?;
Ok(MsgUpgradeClient {
client_id: ClientId::from_str(&proto_msg.client_id)
.map_err(Error::InvalidClientIdentifier)?,
client_state: raw_client_state,
consensus_state: raw_consensus_state,
proof_upgrade_client: RawMerkleProof::decode(proto_msg.proof_upgrade_client.as_ref())
.map_err(Error::InvalidUpgradeClientProof)?,
proof_upgrade_consensus_state: RawMerkleProof::decode(
proto_msg.proof_upgrade_consensus_state.as_ref(),
)
.map_err(Error::InvalidUpgradeConsensusStateProof)?,
signer: proto_msg.signer,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Height;
use crate::mock::{
client_state::MockClientState, consensus_state::MockConsensusState, header::MockHeader,
};
pub fn get_dummy_merkle_proof() -> RawMerkleProof {
use ibc_proto::ics23::CommitmentProof;
let parsed = CommitmentProof { proof: None };
let mproofs: Vec<CommitmentProof> = vec![parsed];
RawMerkleProof { proofs: mproofs }
}
#[test]
fn msg_upgrade_client_serialization() {
let client_id: ClientId = "tendermint".parse().unwrap();
let signer = "dummy_signer".to_string();
let height = Height::new(1, 1).unwrap();
let client_state = MockClientState::new(MockHeader::new(height));
let consensus_state = MockConsensusState::new(MockHeader::new(height));
let proof = get_dummy_merkle_proof();
let msg = MsgUpgradeClient {
client_id,
client_state: client_state.into(),
consensus_state: consensus_state.into(),
proof_upgrade_client: proof.clone(),
proof_upgrade_consensus_state: proof,
signer,
};
let raw: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg.clone());
let msg_back = MsgUpgradeClient::try_from(raw.clone()).unwrap();
let raw_back: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg_back.clone());
assert_eq!(msg, msg_back);
assert_eq!(raw, raw_back);
}
}