ibc_receiver.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. use serde::{Deserialize, Serialize};
  2. use crate::Chain;
  3. /// Represents a governance action targeted at the wormchain ibc receiver contract.
  4. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  5. pub enum Action {
  6. #[serde(rename = "1")]
  7. UpdateChannelChain {
  8. // an existing IBC channel ID
  9. #[serde(with = "crate::serde_array")]
  10. channel_id: [u8; 64],
  11. // the chain associated with this IBC channel_id
  12. chain_id: Chain,
  13. },
  14. }
  15. // MODULE = "IbcReceiver"
  16. pub const MODULE: [u8; 32] = *b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00IbcReceiver";
  17. /// Represents the payload for a governance VAA targeted at the wormchain ibc receiver contract.
  18. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  19. pub struct GovernancePacket {
  20. /// Describes the chain on which the governance action should be carried out.
  21. pub chain: Chain,
  22. /// The actual governance action to be carried out.
  23. pub action: Action,
  24. }
  25. mod governance_packet_impl {
  26. use std::fmt;
  27. use serde::{
  28. de::{Error, MapAccess, SeqAccess, Visitor},
  29. ser::SerializeStruct,
  30. Deserialize, Deserializer, Serialize, Serializer,
  31. };
  32. use crate::{
  33. ibc_receiver::{Action, GovernancePacket, MODULE},
  34. Chain,
  35. };
  36. struct Module;
  37. impl Serialize for Module {
  38. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  39. where
  40. S: Serializer,
  41. {
  42. MODULE.serialize(serializer)
  43. }
  44. }
  45. impl<'de> Deserialize<'de> for Module {
  46. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  47. where
  48. D: Deserializer<'de>,
  49. {
  50. let arr = <[u8; 32]>::deserialize(deserializer)?;
  51. if arr == MODULE {
  52. Ok(Module)
  53. } else {
  54. Err(Error::custom(
  55. "invalid governance module, expected \"IbcReceiver\"",
  56. ))
  57. }
  58. }
  59. }
  60. // governance actions
  61. #[derive(Serialize, Deserialize)]
  62. struct UpdateChannelChain {
  63. #[serde(with = "crate::serde_array")]
  64. channel_id: [u8; 64],
  65. chain_id: Chain,
  66. }
  67. impl Serialize for GovernancePacket {
  68. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  69. where
  70. S: Serializer,
  71. {
  72. let mut seq = serializer.serialize_struct("GovernancePacket", 4)?;
  73. seq.serialize_field("module", &Module)?;
  74. // The wire format encodes the action before the chain and then appends the actual
  75. // action payload.
  76. match self.action.clone() {
  77. Action::UpdateChannelChain {
  78. channel_id,
  79. chain_id,
  80. } => {
  81. seq.serialize_field("action", &1u8)?;
  82. seq.serialize_field("chain", &self.chain)?;
  83. seq.serialize_field(
  84. "payload",
  85. &UpdateChannelChain {
  86. channel_id,
  87. chain_id,
  88. },
  89. )?;
  90. }
  91. }
  92. seq.end()
  93. }
  94. }
  95. struct GovernancePacketVisitor;
  96. impl<'de> Visitor<'de> for GovernancePacketVisitor {
  97. type Value = GovernancePacket;
  98. fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
  99. f.write_str("struct GovernancePacket")
  100. }
  101. #[inline]
  102. fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
  103. where
  104. A: SeqAccess<'de>,
  105. {
  106. static EXPECTING: &str = "struct GovernancePacket with 4 elements";
  107. let _: Module = seq
  108. .next_element()?
  109. .ok_or_else(|| Error::invalid_length(0, &EXPECTING))?;
  110. let act: u8 = seq
  111. .next_element()?
  112. .ok_or_else(|| Error::invalid_length(1, &EXPECTING))?;
  113. let chain = seq
  114. .next_element()?
  115. .ok_or_else(|| Error::invalid_length(2, &EXPECTING))?;
  116. let action = match act {
  117. 1 => {
  118. let UpdateChannelChain {
  119. channel_id,
  120. chain_id,
  121. } = seq
  122. .next_element()?
  123. .ok_or_else(|| Error::invalid_length(3, &EXPECTING))?;
  124. Action::UpdateChannelChain {
  125. channel_id,
  126. chain_id,
  127. }
  128. }
  129. v => {
  130. return Err(Error::custom(format_args!(
  131. "invalid value: {v}, expected 1"
  132. )))
  133. }
  134. };
  135. Ok(GovernancePacket { chain, action })
  136. }
  137. fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
  138. where
  139. A: MapAccess<'de>,
  140. {
  141. #[derive(Serialize, Deserialize)]
  142. #[serde(rename_all = "snake_case")]
  143. enum Field {
  144. Module,
  145. Action,
  146. Chain,
  147. Payload,
  148. }
  149. let mut module = None;
  150. let mut chain = None;
  151. let mut action = None;
  152. let mut payload = None;
  153. while let Some(key) = map.next_key::<Field>()? {
  154. match key {
  155. Field::Module => {
  156. if module.is_some() {
  157. return Err(Error::duplicate_field("module"));
  158. }
  159. module = map.next_value::<Module>().map(Some)?;
  160. }
  161. Field::Action => {
  162. if action.is_some() {
  163. return Err(Error::duplicate_field("action"));
  164. }
  165. action = map.next_value::<u8>().map(Some)?;
  166. }
  167. Field::Chain => {
  168. if chain.is_some() {
  169. return Err(Error::duplicate_field("chain"));
  170. }
  171. chain = map.next_value().map(Some)?;
  172. }
  173. Field::Payload => {
  174. if payload.is_some() {
  175. return Err(Error::duplicate_field("payload"));
  176. }
  177. let a = action.as_ref().copied().ok_or_else(|| {
  178. Error::custom("`action` must be known before deserializing `payload`")
  179. })?;
  180. let p = match a {
  181. 1 => {
  182. let UpdateChannelChain {
  183. channel_id,
  184. chain_id,
  185. } = map.next_value()?;
  186. Action::UpdateChannelChain {
  187. channel_id,
  188. chain_id,
  189. }
  190. }
  191. v => {
  192. return Err(Error::custom(format_args!(
  193. "invalid action: {v}, expected one of: 1, 2"
  194. )))
  195. }
  196. };
  197. payload = Some(p);
  198. }
  199. }
  200. }
  201. let _ = module.ok_or_else(|| Error::missing_field("module"))?;
  202. let chain = chain.ok_or_else(|| Error::missing_field("chain"))?;
  203. let action = payload.ok_or_else(|| Error::missing_field("payload"))?;
  204. Ok(GovernancePacket { chain, action })
  205. }
  206. }
  207. impl<'de> Deserialize<'de> for GovernancePacket {
  208. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  209. where
  210. D: Deserializer<'de>,
  211. {
  212. const FIELDS: &[&str] = &["module", "action", "chain", "payload"];
  213. deserializer.deserialize_struct("GovernancePacket", FIELDS, GovernancePacketVisitor)
  214. }
  215. }
  216. }
  217. #[cfg(test)]
  218. mod test {
  219. use crate::{vaa::Signature, Chain, Vaa, GOVERNANCE_EMITTER};
  220. use super::{Action, GovernancePacket};
  221. #[test]
  222. fn happy_path() {
  223. let buf = [
  224. // version
  225. 0x01, // guardian set index
  226. 0x00, // signatures
  227. 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c, 0x1d, 0x08,
  228. 0x90, 0x5c, 0x02, 0xe2, 0xb6, 0xb2, 0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6, 0xc8, 0xdb,
  229. 0x4f, 0x77, 0xfe, 0x45, 0x7e, 0xf2, 0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e, 0x92, 0xa9,
  230. 0x19, 0x4d, 0x92, 0x10, 0xdf, 0x24, 0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6, 0xf0, 0xc2,
  231. 0x1c, 0xe9, 0x0f, 0x8b, 0xc1, 0x86, 0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e, 0x98, 0x01,
  232. // timestamp
  233. 0x00, 0x00, 0x00, 0x01, // nonce
  234. 0x00, 0x00, 0x00, 0x01, // emitter chain
  235. 0x00, 0x01, // emitter address
  236. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  238. 0x00, 0x00, 0x00, 0x04, // sequence
  239. 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x1b, 0xfa, // consistency
  240. 0x00, // module = "IbcReceiver"
  241. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  242. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x62, 0x63, 0x52, 0x65, 0x63, 0x65,
  243. 0x69, 0x76, 0x65, 0x72, // action (IbcReceiverActionUpdateChannelChain)
  244. 0x01, // target chain_id (unset)
  245. 0x00, 0x00, // IBC channel_id for the mapping ("channel-0")
  246. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  247. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  248. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  249. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
  250. 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2d, 0x30, // IBC chain_id for the mapping
  251. 0x00, 0x13,
  252. ];
  253. let channel_id_bytes: [u8; 64] =
  254. *b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00channel-0";
  255. let vaa = Vaa {
  256. version: 1,
  257. guardian_set_index: 0,
  258. signatures: vec![Signature {
  259. index: 0,
  260. signature: [
  261. 0xb0, 0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c, 0x1d, 0x08, 0x90, 0x5c, 0x02, 0xe2,
  262. 0xb6, 0xb2, 0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6, 0xc8, 0xdb, 0x4f, 0x77, 0xfe,
  263. 0x45, 0x7e, 0xf2, 0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e, 0x92, 0xa9, 0x19, 0x4d,
  264. 0x92, 0x10, 0xdf, 0x24, 0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6, 0xf0, 0xc2, 0x1c,
  265. 0xe9, 0x0f, 0x8b, 0xc1, 0x86, 0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e, 0x98, 0x01,
  266. ],
  267. }],
  268. timestamp: 1,
  269. nonce: 1,
  270. emitter_chain: Chain::Solana,
  271. emitter_address: GOVERNANCE_EMITTER,
  272. sequence: 20_716_538,
  273. consistency_level: 0,
  274. payload: GovernancePacket {
  275. chain: Chain::Any,
  276. action: Action::UpdateChannelChain {
  277. channel_id: channel_id_bytes,
  278. chain_id: Chain::Injective,
  279. },
  280. },
  281. };
  282. assert_eq!(buf.as_ref(), &serde_wormhole::to_vec(&vaa).unwrap());
  283. assert_eq!(vaa, serde_wormhole::from_slice(&buf).unwrap());
  284. let encoded = serde_json::to_string(&vaa).unwrap();
  285. assert_eq!(vaa, serde_json::from_str(&encoded).unwrap());
  286. }
  287. }