hpl_interface/types/
metadata.rs1use std::collections::BTreeMap;
2
3use cosmwasm_schema::cw_serde;
4use cosmwasm_std::{Addr, HexBinary, Uint256};
5
6use super::bech32_encode;
7
8const SIGNATURE_LENGTH: usize = 65;
9
10#[cw_serde]
11pub struct MerkleRootMultisigIsmMetadata {
12 pub origin_mailbox: HexBinary,
13 pub checkpoint_index: u32,
15 pub message_id: HexBinary,
16 pub proof: HexBinary,
18 pub signatures: HexBinary, }
21
22impl From<MerkleRootMultisigIsmMetadata> for HexBinary {
23 fn from(v: MerkleRootMultisigIsmMetadata) -> Self {
24 v.origin_mailbox
25 .to_vec()
26 .iter()
27 .chain(v.checkpoint_index.to_be_bytes().iter())
28 .chain(v.message_id.to_vec().iter())
29 .chain(v.proof.to_vec().iter())
30 .chain(v.signatures.to_vec().iter())
31 .cloned()
32 .collect::<Vec<u8>>()
33 .into()
34 }
35}
36
37impl From<HexBinary> for MerkleRootMultisigIsmMetadata {
38 fn from(v: HexBinary) -> Self {
39 Self {
40 origin_mailbox: v[0..32].to_vec().into(),
41 checkpoint_index: u32::from_be_bytes(v[32..36].try_into().unwrap()),
42 message_id: v[36..68].to_vec().into(),
43 proof: v[68..1092].to_vec().into(),
44 signatures: v[1092..].to_vec().into(),
45 }
46 }
47}
48
49impl MerkleRootMultisigIsmMetadata {
50 pub fn signatures_len(&self) -> Result<usize, &'static str> {
51 if self.signatures.len() % SIGNATURE_LENGTH != 0 {
52 return Err("Invalid signatures length");
53 }
54
55 Ok(self.signatures.len() / SIGNATURE_LENGTH)
56 }
57
58 pub fn signature_at(&self, index: usize) -> HexBinary {
59 self.signatures[index * SIGNATURE_LENGTH..(index + 1) * SIGNATURE_LENGTH]
61 .to_vec()
62 .into()
63 }
64}
65
66#[cw_serde]
67pub struct MessageIdMultisigIsmMetadata {
68 pub origin_merkle_tree: HexBinary,
69
70 pub merkle_root: HexBinary,
71
72 pub merkle_index: HexBinary,
73
74 pub signatures: Vec<HexBinary>,
75}
76
77impl From<MessageIdMultisigIsmMetadata> for HexBinary {
78 fn from(v: MessageIdMultisigIsmMetadata) -> Self {
79 let mut origin_merkle_tree = [0u8; 32];
80 origin_merkle_tree[32 - v.origin_merkle_tree.len()..]
81 .copy_from_slice(&v.origin_merkle_tree);
82
83 origin_merkle_tree
84 .to_vec()
85 .iter()
86 .chain(v.merkle_root.to_vec().iter())
87 .chain(v.merkle_index.to_vec().iter())
88 .chain(
89 v.signatures
90 .iter()
91 .flat_map(|x| x.to_vec())
92 .collect::<Vec<_>>()
93 .iter(),
94 )
95 .cloned()
96 .collect::<Vec<u8>>()
97 .into()
98 }
99}
100
101impl From<HexBinary> for MessageIdMultisigIsmMetadata {
102 fn from(v: HexBinary) -> Self {
103 let signatures = v[68..]
104 .to_vec()
105 .chunks_exact(SIGNATURE_LENGTH)
106 .map(|v| v.into())
107 .collect::<Vec<HexBinary>>();
108
109 Self {
110 origin_merkle_tree: v[0..32].to_vec().into(),
111 merkle_root: v[32..64].to_vec().into(),
112 merkle_index: v[64..68].to_vec().into(),
113 signatures,
114 }
115 }
116}
117
118impl MessageIdMultisigIsmMetadata {
119 pub fn merkle_index(&self) -> u32 {
120 u32::from_be_bytes(self.merkle_index.to_vec().try_into().unwrap())
121 }
122}
123
124use std::convert::AsMut;
125
126fn clone_into_array<A, T>(slice: &[T]) -> A
127where
128 A: Sized + Default + AsMut<[T]>,
129 T: Clone,
130{
131 let mut a = Default::default();
132 <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
133 a
134}
135
136#[cw_serde]
137pub struct AggregateMetadata(BTreeMap<Addr, HexBinary>);
138
139impl AggregateMetadata {
140 pub const RANGE_SIZE: usize = 4;
141
142 pub fn new(set: Vec<(Addr, HexBinary)>) -> Self {
143 Self(set.into_iter().collect())
144 }
145}
146
147impl Iterator for AggregateMetadata {
148 type Item = (Addr, HexBinary);
149
150 fn next(&mut self) -> Option<Self::Item> {
151 self.0.pop_first()
152 }
153}
154
155impl AggregateMetadata {
156 pub fn from_hex(v: HexBinary, addrs: Vec<Addr>) -> Self {
157 Self(
158 addrs
159 .into_iter()
160 .enumerate()
161 .map(|(i, ism)| {
162 let start = i * Self::RANGE_SIZE * 2;
163 let mid = start + Self::RANGE_SIZE;
164 let end = mid + Self::RANGE_SIZE;
165
166 let mut meta_start = [0u8; 4];
167 meta_start.copy_from_slice(&v[start..mid]);
168 let mut meta_end = [0u8; 4];
169 meta_end.copy_from_slice(&v[mid..end]);
170
171 let meta_start = u32::from_be_bytes(meta_start) as usize;
172 let meta_end = u32::from_be_bytes(meta_end) as usize;
173
174 (ism, v[meta_start..meta_end].to_vec().into())
175 })
176 .collect(),
177 )
178 }
179}
180
181impl From<AggregateMetadata> for HexBinary {
182 fn from(v: AggregateMetadata) -> Self {
183 let pos_start = v.0.len() * AggregateMetadata::RANGE_SIZE * 2;
184
185 let ls: Vec<(
186 [u8; AggregateMetadata::RANGE_SIZE],
187 [u8; AggregateMetadata::RANGE_SIZE],
188 HexBinary,
189 )> =
190 v.0.values()
191 .fold(vec![] as Vec<(usize, usize, HexBinary)>, |mut acc, m| {
192 let l = acc.last().map(|v| v.1).unwrap_or(pos_start);
193
194 acc.push((l, l + m.len(), m.clone()));
195 acc
196 })
197 .into_iter()
198 .map(|(start, end, metadata)| {
199 (
200 clone_into_array(&start.to_be_bytes()[AggregateMetadata::RANGE_SIZE..]),
201 clone_into_array(&end.to_be_bytes()[AggregateMetadata::RANGE_SIZE..]),
202 metadata,
203 )
204 })
205 .collect();
206
207 let mut pos = vec![];
208 let mut metadata = vec![];
209
210 for (start, end, meta) in ls {
211 pos.extend_from_slice(&start);
212 pos.extend_from_slice(&end);
213 metadata.extend_from_slice(meta.as_slice());
214 }
215
216 [pos, metadata].concat().into()
217 }
218}
219
220#[cw_serde]
221pub struct IGPMetadata {
222 pub gas_limit: Uint256,
223 pub refund_address: HexBinary,
224}
225
226impl From<IGPMetadata> for HexBinary {
227 fn from(v: IGPMetadata) -> Self {
228 v.gas_limit
229 .to_be_bytes()
230 .iter()
231 .chain(v.refund_address.to_vec().iter())
232 .cloned()
233 .collect::<Vec<u8>>()
234 .into()
235 }
236}
237
238impl From<HexBinary> for IGPMetadata {
239 fn from(v: HexBinary) -> Self {
240 Self {
241 gas_limit: Uint256::from_be_bytes(v[0..32].try_into().unwrap()),
242 refund_address: v[32..].to_vec().into(),
243 }
244 }
245}
246
247impl IGPMetadata {
248 pub fn get_refund_address(&self, hrp: &str, default: Addr) -> Addr {
249 if self.refund_address.to_vec().len() != 20 && self.refund_address.to_vec().len() != 32 {
250 return default;
251 }
252
253 let raw_addr = match self
254 .refund_address
255 .to_vec()
256 .iter()
257 .take(16)
258 .all(|&byte| byte == 0)
259 {
260 true => self.refund_address.to_vec()[16..].to_vec(),
261 false => self.refund_address.to_vec(),
262 };
263
264 bech32_encode(hrp, &raw_addr).unwrap()
265 }
266}
267
268#[cfg(test)]
269mod test {
270 use ibcx_test_utils::{addr, gen_bz, hex};
271
272 use super::*;
273
274 #[test]
275 fn test_aggregate() {
276 let set = vec![
277 (addr("test1"), gen_bz(12)),
278 (addr("test2"), gen_bz(12)),
279 (addr("test3"), gen_bz(12)),
280 ];
281
282 let metadata = AggregateMetadata::new(set);
283 let isms = metadata.0.clone().into_keys().collect();
284
285 let metadata_bz: HexBinary = metadata.clone().into();
286
287 let new_metadata = AggregateMetadata::from_hex(metadata_bz, isms);
288 assert_eq!(metadata, new_metadata);
289 }
290
291 #[test]
292 fn test_message_id_multisig_metadata() {
293 let testdata = hex("fadafdf4db5e6264d450bafa5951b2180b8fe8aac2e012f280784ae841e9a7f732a2601709a27a5e370a59f98a67b5da6baa522b6421edf2ea240d94d84511a800000000df4eaf1947af0858139b90054561d5ab2a423b4ad8d75a5ec7f9e860fd3de1bb3924e2593e29b595aae2717538c0af6d6ae9fc20477da49d223a0d928a1efb311bdf4eaf1947af0858139b90054561d5ab2a423b4ad8d75a5ec7f9e860fd3de1bb3924e2593e29b595aae2717538c0af6d6ae9fc20477da49d223a0d928a1efb311b");
294
295 let metadata: MessageIdMultisigIsmMetadata = testdata.clone().into();
296
297 assert_eq!(metadata.signatures.len(), 2);
298 assert_eq!(
299 metadata.signatures.iter().flat_map(|v| v.to_vec()).count(),
300 SIGNATURE_LENGTH * 2
301 );
302
303 let recovered: HexBinary = metadata.into();
304
305 assert_eq!(recovered, testdata);
306 }
307}