1use thiserror::Error;
2
3use cosmwasm_std::Binary;
4
5const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2;
7const VARINT_MAX_BYTES: usize = 9;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct MsgInstantiateContractResponse {
12 pub contract_address: String,
13 pub data: Option<Binary>,
14}
15
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct MsgExecuteContractResponse {
18 pub data: Option<Binary>,
19}
20
21fn parse_protobuf_varint(data: &mut Vec<u8>, field_number: u8) -> Result<usize, ParseReplyError> {
24 let data_len = data.len();
25 let mut len: u64 = 0;
26 let mut i = 0;
27 while i < VARINT_MAX_BYTES {
28 if data_len == i {
29 return Err(ParseReplyError::ParseFailure(format!(
30 "failed to decode Protobuf message: field #{}: varint data too short",
31 field_number
32 )));
33 }
34 len += ((data[i] & 0x7f) as u64) << (i * 7);
35 if data[i] & 0x80 == 0 {
36 break;
37 }
38 i += 1;
39 }
40 if i == VARINT_MAX_BYTES {
41 return Err(ParseReplyError::ParseFailure(format!(
42 "failed to decode Protobuf message: field #{}: varint data too long",
43 field_number
44 )));
45 }
46 let _ = data.drain(..=i);
47
48 Ok(len as usize) }
50
51fn parse_protobuf_length_prefixed(
54 data: &mut Vec<u8>,
55 field_number: u8,
56) -> Result<Vec<u8>, ParseReplyError> {
57 if data.is_empty() {
58 return Ok(vec![]);
59 };
60 let mut rest_1 = data.split_off(1);
61 let wire_type = data[0] & 0b11;
62 let field = data[0] >> 3;
63
64 if field != field_number {
65 return Err(ParseReplyError::ParseFailure(format!(
66 "failed to decode Protobuf message: invalid field #{} for field #{}",
67 field, field_number
68 )));
69 }
70 if wire_type != WIRE_TYPE_LENGTH_DELIMITED {
71 return Err(ParseReplyError::ParseFailure(format!(
72 "failed to decode Protobuf message: field #{}: invalid wire type {}",
73 field_number, wire_type
74 )));
75 }
76
77 let len = parse_protobuf_varint(&mut rest_1, field_number)?;
78 if rest_1.len() < len {
79 return Err(ParseReplyError::ParseFailure(format!(
80 "failed to decode Protobuf message: field #{}: message too short",
81 field_number
82 )));
83 }
84 *data = rest_1.split_off(len);
85
86 Ok(rest_1)
87}
88
89fn parse_protobuf_string(data: &mut Vec<u8>, field_number: u8) -> Result<String, ParseReplyError> {
90 let str_field = parse_protobuf_length_prefixed(data, field_number)?;
91 Ok(String::from_utf8(str_field)?)
92}
93
94fn parse_protobuf_bytes(
95 data: &mut Vec<u8>,
96 field_number: u8,
97) -> Result<Option<Binary>, ParseReplyError> {
98 let bytes_field = parse_protobuf_length_prefixed(data, field_number)?;
99 if bytes_field.is_empty() {
100 Ok(None)
101 } else {
102 Ok(Some(Binary::new(bytes_field)))
103 }
104}
105
106pub fn parse_instantiate_response_data(
107 data: &[u8],
108) -> Result<MsgInstantiateContractResponse, ParseReplyError> {
109 let mut data = data.to_vec();
111 let contract_addr = parse_protobuf_string(&mut data, 1)?;
113
114 let data = parse_protobuf_bytes(&mut data, 2)?;
116
117 Ok(MsgInstantiateContractResponse {
118 contract_address: contract_addr,
119 data,
120 })
121}
122
123pub fn parse_execute_response_data(
124 data: &[u8],
125) -> Result<MsgExecuteContractResponse, ParseReplyError> {
126 let mut data = data.to_vec();
128 let inner_data = parse_protobuf_bytes(&mut data, 1)?;
129
130 Ok(MsgExecuteContractResponse { data: inner_data })
131}
132
133#[derive(Error, Debug, PartialEq, Eq)]
134pub enum ParseReplyError {
135 #[error("Failure response from sub-message: {0}")]
136 SubMsgFailure(String),
137
138 #[error("Invalid reply from sub-message: {0}")]
139 ParseFailure(String),
140
141 #[error("Error occurred while converting from UTF-8")]
142 BrokenUtf8(#[from] std::string::FromUtf8Error),
143}
144
145#[cfg(test)]
146mod test {
147 use super::*;
148 use crate::parse_reply::ParseReplyError::{BrokenUtf8, ParseFailure};
149 use prost::Message;
150 use std::str::from_utf8;
151
152 fn encode_bytes(data: &[u8]) -> Vec<u8> {
153 #[derive(Clone, PartialEq, Message)]
154 struct ProtobufBytes {
155 #[prost(bytes, tag = "1")]
156 pub data: Vec<u8>,
157 }
158
159 let data = ProtobufBytes {
160 data: data.to_vec(),
161 };
162 let mut encoded_data = Vec::<u8>::with_capacity(data.encoded_len());
163 data.encode(&mut encoded_data).unwrap();
164
165 encoded_data
166 }
167
168 fn encode_string(data: &str) -> Vec<u8> {
169 #[derive(Clone, PartialEq, Message)]
170 struct ProtobufString {
171 #[prost(string, tag = "1")]
172 pub data: String,
173 }
174
175 let data = ProtobufString {
176 data: data.to_string(),
177 };
178 let mut encoded_data = Vec::<u8>::with_capacity(data.encoded_len());
179 data.encode(&mut encoded_data).unwrap();
180
181 encoded_data
182 }
183
184 #[derive(Clone, PartialEq, Message)]
185 struct MsgInstantiateContractResponse {
186 #[prost(string, tag = "1")]
187 pub contract_address: ::prost::alloc::string::String,
188 #[prost(bytes, tag = "2")]
189 pub data: ::prost::alloc::vec::Vec<u8>,
190 }
191
192 #[derive(Clone, PartialEq, Message)]
193 struct MsgExecuteContractResponse {
194 #[prost(bytes, tag = "1")]
195 pub data: ::prost::alloc::vec::Vec<u8>,
196 }
197
198 #[test]
199 fn parse_protobuf_varint_tests() {
200 let field_number = 1;
201 let mut data = b"\x0a".to_vec();
203 let len = parse_protobuf_varint(&mut data, field_number).unwrap();
204 assert_eq!(len, 10);
205
206 let mut data = b"\x0a\x0b".to_vec();
208 let len = parse_protobuf_varint(&mut data, field_number).unwrap();
209 assert_eq!(len, 10);
210 assert_eq!(data, b"\x0b".to_vec());
211
212 let mut data = b"\xac\x02".to_vec();
216 let len = parse_protobuf_varint(&mut data, field_number).unwrap();
217 assert_eq!(len, 300);
218
219 let mut data = b"\xac\x02\x0c".to_vec();
221 let len = parse_protobuf_varint(&mut data, field_number).unwrap();
222 assert_eq!(len, 300);
223 assert_eq!(data, b"\x0c".to_vec());
224
225 let mut data = vec![];
227 let err = parse_protobuf_varint(&mut data, field_number).unwrap_err();
228 assert!(matches!(err, ParseFailure(..)));
229
230 let mut data = b"\x80".to_vec();
232 let err = parse_protobuf_varint(&mut data, field_number).unwrap_err();
233 assert!(matches!(err, ParseFailure(..)));
234
235 let mut data = b"\x80\x81\x82\x83\x84\x83\x82\x81\x80".to_vec();
237 let err = parse_protobuf_varint(&mut data, field_number).unwrap_err();
238 assert!(matches!(err, ParseFailure(..)));
239 }
240
241 #[test]
242 fn parse_protobuf_length_prefixed_tests() {
243 let field_number = 1;
244 let mut data = b"\x0a\x03abc".to_vec();
246 let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap();
247 assert_eq!(res, b"abc".to_vec());
248 assert_eq!(data, vec![0u8; 0]);
249
250 let mut data = b"\x0a\x03abcd".to_vec();
252 let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap();
253 assert_eq!(res, b"abc".to_vec());
254 assert_eq!(data, b"d".to_vec());
255
256 let mut data = [b"\x0a\xac\x02", vec![65u8; 300].as_slice()]
258 .concat()
259 .to_vec();
260 let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap();
261 assert_eq!(res, vec![65u8; 300]);
262 assert_eq!(data, vec![0u8; 0]);
263
264 let mut data = [b"\x0a\xac\x02", vec![65u8; 300].as_slice(), b"rest"]
266 .concat()
267 .to_vec();
268 let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap();
269 assert_eq!(res, vec![65u8; 300]);
270 assert_eq!(data, b"rest");
271
272 let mut data = b"\x0a\x01".to_vec();
274 let field_number = 1;
275 let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err();
276 assert!(matches!(err, ParseFailure(..)));
277
278 let mut data = b"\x0b\x01a".to_vec();
280 let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err();
281 assert!(matches!(err, ParseFailure(..)));
282
283 let field_number = 2;
285 let mut data = b"\x0a\x01a".to_vec();
286 let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err();
287 assert!(matches!(err, ParseFailure(..)));
288 }
289
290 #[test]
291 fn parse_protobuf_bytes_works() {
292 let field_number = 1;
293
294 let data = vec![];
296 let mut encoded_data = encode_bytes(&data);
297
298 let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap();
299 assert_eq!(res, None);
300
301 let data = b"test".to_vec();
303 let mut encoded_data = encode_bytes(&data);
304
305 let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap();
306 assert_eq!(res, Some(Binary::new(data)));
307
308 let data = vec![0x40; 300];
310 let mut encoded_data = encode_bytes(&data);
311
312 let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap();
313 assert_eq!(res, Some(Binary::new(data)));
314
315 let field_number = 5;
317 let data = b"test field 5".to_vec();
318 let mut encoded_data = encode_bytes(&data);
319 encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED;
320
321 let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap();
322 assert_eq!(res, Some(Binary::new(data)));
323
324 let field_number = 1;
326 let test_len: usize = 4;
327 let data = b"test_remainder".to_vec();
328 let mut encoded_data = encode_bytes(&data);
329 encoded_data[1] = test_len as u8;
330
331 let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap();
332 assert_eq!(res, Some(Binary::new(data[..test_len].to_owned())));
333 assert_eq!(encoded_data, data[test_len..].to_owned());
334 }
335
336 #[test]
337 fn parse_protobuf_string_tests() {
338 let field_number = 1;
339
340 let data = "";
342 let mut encoded_data = encode_string(data);
343
344 let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap();
345 assert_eq!(res, data);
346
347 let data = "test";
349 let mut encoded_data = encode_string(data);
350
351 let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap();
352 assert_eq!(res, data);
353
354 let data = vec![0x40; 300];
356 let str_data = from_utf8(data.as_slice()).unwrap();
357 let mut encoded_data = encode_string(str_data);
358
359 let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap();
360 assert_eq!(res, str_data);
361
362 let field_number = 5;
364 let data = "test field 5";
365 let mut encoded_data = encode_string(data);
366 encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED;
367
368 let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap();
369 assert_eq!(res, data);
370
371 let field_number = 1;
373 let test_len: usize = 4;
374 let data = "test_remainder";
375 let mut encoded_data = encode_string(data);
376 encoded_data[1] = test_len as u8;
377
378 let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap();
379 assert_eq!(res, data[..test_len]);
380 assert_eq!(encoded_data, &data.as_bytes()[test_len..]);
381
382 let field_number = 1;
384 let data = "test_X";
385 let mut encoded_data = encode_string(data);
386 let encoded_len = encoded_data.len();
387 encoded_data[encoded_len - 1] = 0xd3;
388 let err = parse_protobuf_string(&mut encoded_data, field_number).unwrap_err();
389 assert!(matches!(err, BrokenUtf8(..)));
390 }
391
392 #[test]
393 fn parse_instantiate_response_data_works() {
394 let contract_addr: &str = "Contract #1";
395 for (data, expected) in [
396 (
397 vec![],
398 super::MsgInstantiateContractResponse {
399 contract_address: contract_addr.to_string(),
400 data: None,
401 },
402 ),
403 (
404 vec![1u8, 2, 255, 7, 5],
405 super::MsgInstantiateContractResponse {
406 contract_address: contract_addr.to_string(),
407 data: Some(Binary::new(vec![1u8, 2, 255, 7, 5])),
408 },
409 ),
410 (
411 vec![1u8; 127],
412 super::MsgInstantiateContractResponse {
413 contract_address: contract_addr.to_string(),
414 data: Some(Binary::new(vec![1u8; 127])),
415 },
416 ),
417 (
418 vec![2u8; 128],
419 super::MsgInstantiateContractResponse {
420 contract_address: contract_addr.to_string(),
421 data: Some(Binary::new(vec![2u8; 128])),
422 },
423 ),
424 (
425 vec![3u8; 257],
426 super::MsgInstantiateContractResponse {
427 contract_address: contract_addr.to_string(),
428 data: Some(Binary::new(vec![3u8; 257])),
429 },
430 ),
431 ] {
432 let instantiate_reply = MsgInstantiateContractResponse {
433 contract_address: contract_addr.to_string(),
434 data,
435 };
436 let mut encoded_instantiate_reply =
437 Vec::<u8>::with_capacity(instantiate_reply.encoded_len());
438 instantiate_reply
440 .encode(&mut encoded_instantiate_reply)
441 .unwrap();
442
443 let res = parse_instantiate_response_data(&encoded_instantiate_reply).unwrap();
444
445 assert_eq!(res, expected);
446 }
447 }
448
449 #[test]
450 fn parse_execute_response_data_works() {
451 for (data, expected) in [
452 (vec![], super::MsgExecuteContractResponse { data: None }),
453 (
454 vec![1u8, 2, 3, 127, 15],
455 super::MsgExecuteContractResponse {
456 data: Some(Binary::new(vec![1u8, 2, 3, 127, 15])),
457 },
458 ),
459 (
460 vec![0u8; 255],
461 super::MsgExecuteContractResponse {
462 data: Some(Binary::new(vec![0u8; 255])),
463 },
464 ),
465 (
466 vec![1u8; 256],
467 super::MsgExecuteContractResponse {
468 data: Some(Binary::new(vec![1u8; 256])),
469 },
470 ),
471 (
472 vec![2u8; 32769],
473 super::MsgExecuteContractResponse {
474 data: Some(Binary::new(vec![2u8; 32769])),
475 },
476 ),
477 ] {
478 let execute_reply = MsgExecuteContractResponse { data };
479 let mut encoded_execute_reply = Vec::<u8>::with_capacity(execute_reply.encoded_len());
480 execute_reply.encode(&mut encoded_execute_reply).unwrap();
482
483 let res = parse_execute_response_data(&encoded_execute_reply).unwrap();
484
485 assert_eq!(res, expected);
486 }
487 }
488}