From 7e52f6410ad32fa5a8919b1462a102111934881e Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Wed, 20 Oct 2021 17:21:24 +0200 Subject: [PATCH 01/26] Add first impl using prost --- Cargo.lock | 1 + packages/cw0/Cargo.toml | 2 + packages/cw0/src/lib.rs | 2 + packages/cw0/src/parse_reply.rs | 83 +++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 packages/cw0/src/parse_reply.rs diff --git a/Cargo.lock b/Cargo.lock index 7c6babd47..ece3ee7ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -283,6 +283,7 @@ version = "0.10.0" dependencies = [ "cosmwasm-std", "cw-storage-plus", + "prost", "schemars", "serde", "thiserror", diff --git a/packages/cw0/Cargo.toml b/packages/cw0/Cargo.toml index e6717137a..3055e51b2 100644 --- a/packages/cw0/Cargo.toml +++ b/packages/cw0/Cargo.toml @@ -17,5 +17,7 @@ schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.21" } +prost = "0.8.0" + [dev-dependencies] cw-storage-plus = { path = "../../packages/storage-plus", version = "0.10.0" } diff --git a/packages/cw0/src/lib.rs b/packages/cw0/src/lib.rs index fbb000906..13236d328 100644 --- a/packages/cw0/src/lib.rs +++ b/packages/cw0/src/lib.rs @@ -2,11 +2,13 @@ mod balance; mod event; mod expiration; mod pagination; +mod parse_reply; mod payment; pub use pagination::{ calc_range_end, calc_range_start, calc_range_start_string, maybe_addr, maybe_canonical, }; +pub use parse_reply::parse_reply_instantiate_data; pub use payment::{may_pay, must_pay, nonpayable, one_coin, PaymentError}; pub use crate::balance::NativeBalance; diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs new file mode 100644 index 000000000..2d48094d5 --- /dev/null +++ b/packages/cw0/src/parse_reply.rs @@ -0,0 +1,83 @@ +use prost::Message; +use thiserror::Error; + +use cosmwasm_std::Reply; + +#[derive(Clone, PartialEq, Message)] +pub struct MsgInstantiateContractResponse { + #[prost(string, tag = "1")] + pub contract_address: ::prost::alloc::string::String, + #[prost(bytes, tag = "2")] + pub data: ::prost::alloc::vec::Vec, +} + +pub fn parse_reply_instantiate_data( + msg: Reply, +) -> Result { + let id = msg.id; + let res: MsgInstantiateContractResponse = Message::decode( + msg.result + .into_result() + .map_err(ParseReplyError::SubMsgFailure)? + .data + .ok_or_else(|| ParseReplyError::ParseFailure { + id, + err: "Missing reply data".to_owned(), + })? + .as_slice(), + ) + .map_err(|err| ParseReplyError::ParseFailure { + id, + err: err.to_string(), + })?; + + Ok(res) +} + +#[derive(Error, Debug, PartialEq)] +pub enum ParseReplyError { + #[error("Failure response from sub-message: {0}")] + SubMsgFailure(String), + + #[error("Invalid reply from sub-message {id}: {err}")] + ParseFailure { id: u64, err: String }, +} + +#[cfg(test)] +mod test { + use super::*; + use cosmwasm_std::{ContractResult, SubMsgExecutionResponse}; + + #[test] + fn parse_reply_instantiate_data_works() { + let instantiate_reply_data: &str = "Contract #1"; + let instantiate_reply = MsgInstantiateContractResponse { + contract_address: instantiate_reply_data.to_string(), + data: vec![], + }; + let mut encoded_instantiate_reply = + Vec::::with_capacity(instantiate_reply.encoded_len()); + // The data must encode successfully + instantiate_reply + .encode(&mut encoded_instantiate_reply) + .unwrap(); + + // Build reply message + let msg = Reply { + id: 1, + result: ContractResult::Ok(SubMsgExecutionResponse { + events: vec![], + data: Some(encoded_instantiate_reply.into()), + }), + }; + + let res = parse_reply_instantiate_data(msg).unwrap(); + assert_eq!( + res, + MsgInstantiateContractResponse { + contract_address: instantiate_reply_data.into(), + data: vec![], + } + ); + } +} From 18ddb76bababab71a093ba83ab076b833cee6d86 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Wed, 20 Oct 2021 18:16:06 +0200 Subject: [PATCH 02/26] Add manual protobuf decoding --- packages/cw0/Cargo.toml | 3 +- packages/cw0/src/parse_reply.rs | 84 +++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/packages/cw0/Cargo.toml b/packages/cw0/Cargo.toml index 3055e51b2..4b6e13cf8 100644 --- a/packages/cw0/Cargo.toml +++ b/packages/cw0/Cargo.toml @@ -17,7 +17,6 @@ schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.21" } -prost = "0.8.0" - [dev-dependencies] cw-storage-plus = { path = "../../packages/storage-plus", version = "0.10.0" } +prost = "0.8.0" diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 2d48094d5..a3137f0af 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -1,35 +1,57 @@ -use prost::Message; use thiserror::Error; -use cosmwasm_std::Reply; +use cosmwasm_std::{Binary, Reply}; -#[derive(Clone, PartialEq, Message)] +#[derive(Clone, Debug, PartialEq)] pub struct MsgInstantiateContractResponse { - #[prost(string, tag = "1")] - pub contract_address: ::prost::alloc::string::String, - #[prost(bytes, tag = "2")] - pub data: ::prost::alloc::vec::Vec, + pub contract_address: String, + pub data: Option, // FIXME: Confirm if Option } pub fn parse_reply_instantiate_data( msg: Reply, ) -> Result { let id = msg.id; - let res: MsgInstantiateContractResponse = Message::decode( - msg.result - .into_result() - .map_err(ParseReplyError::SubMsgFailure)? - .data - .ok_or_else(|| ParseReplyError::ParseFailure { - id, - err: "Missing reply data".to_owned(), - })? - .as_slice(), - ) - .map_err(|err| ParseReplyError::ParseFailure { - id, - err: err.to_string(), - })?; + let data = msg + .result + .into_result() + .map_err(ParseReplyError::SubMsgFailure)? + .data + .ok_or_else(|| ParseReplyError::ParseFailure { + id, + err: "Missing reply data".to_owned(), + })?; + // Manual protobuf decoding + let data = data.0; + println!("reply data 0: {:#?}", data); + // FIXME: avoid panics + let (wire_type, data) = data.as_slice().split_at(1); + println!("reply data 1: {:#?}", data); + if wire_type[0] != b'\x0a' { + return Err(ParseReplyError::ParseFailure { id, err: "failed to decode Protobuf message: MsgInstantiateContractResponse.contract_address: invalid wire type".to_owned() }); + } + let (len, data) = data.split_at(1); + println!("reply data 2: {:#?}", data); + let (contract_addr, data) = data.split_at(len[0] as usize); + println!("reply data 3: {:#?}", data); + let (wire_type, data) = data.split_at(1); + if wire_type[0] != b'\x12' { + return Err(ParseReplyError::ParseFailure { id, err: "failed to decode Protobuf message: MsgInstantiateContractResponse.data: invalid wire type".to_owned() }); + } + let (len, data) = data.split_at(1); + println!("reply data 4: {:#?}", data); + let (data, _rest) = data.split_at(len[0] as usize); + println!("reply data 5: {:#?}", data); + let data = if data.is_empty() { + None + } else { + Some(Binary(data.to_vec())) + }; + + let res = MsgInstantiateContractResponse { + contract_address: String::from_utf8(contract_addr.to_vec())?, + data, + }; Ok(res) } @@ -41,19 +63,31 @@ pub enum ParseReplyError { #[error("Invalid reply from sub-message {id}: {err}")] ParseFailure { id: u64, err: String }, + + #[error("Error occurred while converting from UTF-8")] + FromUtf8(#[from] std::string::FromUtf8Error), } #[cfg(test)] mod test { use super::*; use cosmwasm_std::{ContractResult, SubMsgExecutionResponse}; + use prost::Message; + + #[derive(Clone, PartialEq, Message)] + pub struct MsgInstantiateContractResponse { + #[prost(string, tag = "1")] + pub contract_address: ::prost::alloc::string::String, + #[prost(bytes, tag = "2")] + pub data: ::prost::alloc::vec::Vec, + } #[test] fn parse_reply_instantiate_data_works() { let instantiate_reply_data: &str = "Contract #1"; let instantiate_reply = MsgInstantiateContractResponse { contract_address: instantiate_reply_data.to_string(), - data: vec![], + data: vec![1u8, 2, 3, 4], }; let mut encoded_instantiate_reply = Vec::::with_capacity(instantiate_reply.encoded_len()); @@ -74,9 +108,9 @@ mod test { let res = parse_reply_instantiate_data(msg).unwrap(); assert_eq!( res, - MsgInstantiateContractResponse { + super::MsgInstantiateContractResponse { contract_address: instantiate_reply_data.into(), - data: vec![], + data: Some(Binary(vec![1u8, 2, 3, 4])), } ); } From ce22a9cf7bcc06bc4fa1f31f21888f555694ebc0 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Wed, 20 Oct 2021 22:02:43 +0200 Subject: [PATCH 03/26] Add protobuf parsing helpers --- packages/cw0/src/parse_reply.rs | 79 +++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index a3137f0af..078c8de28 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -2,54 +2,67 @@ use thiserror::Error; use cosmwasm_std::{Binary, Reply}; +// Protobuf wire types (https://developers.google.com/protocol-buffers/docs/encoding) +const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2; + #[derive(Clone, Debug, PartialEq)] pub struct MsgInstantiateContractResponse { pub contract_address: String, pub data: Option, // FIXME: Confirm if Option } +fn parse_protobuf_string(data: &mut Vec) -> Result { + // FIXME: don't panic + let mut rest_1 = data.split_off(1); + if data[0] & 0x03 != WIRE_TYPE_LENGTH_DELIMITED { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: string field: invalid wire type".to_owned(), + )); + } + let mut rest_2 = rest_1.split_off(1); + let rest_3 = rest_2.split_off(rest_1[0] as usize); + + *data = rest_3; + Ok(String::from_utf8(rest_2.to_owned())?) +} + +fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReplyError> { + if data.is_empty() { + return Ok(None); + } + let mut rest_1 = data.split_off(1); + if data[0] & 0x03 != WIRE_TYPE_LENGTH_DELIMITED { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: bytes field: invalid wire type".to_owned(), + )); + } + // FIXME: don't panic + let mut rest_2 = rest_1.split_off(1); + let rest_3 = rest_2.split_off(rest_1[0] as usize); + + *data = rest_3; + Ok(Some(Binary(rest_2.to_vec()))) +} + pub fn parse_reply_instantiate_data( msg: Reply, ) -> Result { - let id = msg.id; let data = msg .result .into_result() .map_err(ParseReplyError::SubMsgFailure)? .data - .ok_or_else(|| ParseReplyError::ParseFailure { - id, - err: "Missing reply data".to_owned(), - })?; + .ok_or_else(|| ParseReplyError::ParseFailure("Missing reply data".to_owned()))?; // Manual protobuf decoding - let data = data.0; - println!("reply data 0: {:#?}", data); - // FIXME: avoid panics - let (wire_type, data) = data.as_slice().split_at(1); - println!("reply data 1: {:#?}", data); - if wire_type[0] != b'\x0a' { - return Err(ParseReplyError::ParseFailure { id, err: "failed to decode Protobuf message: MsgInstantiateContractResponse.contract_address: invalid wire type".to_owned() }); - } - let (len, data) = data.split_at(1); - println!("reply data 2: {:#?}", data); - let (contract_addr, data) = data.split_at(len[0] as usize); - println!("reply data 3: {:#?}", data); - let (wire_type, data) = data.split_at(1); - if wire_type[0] != b'\x12' { - return Err(ParseReplyError::ParseFailure { id, err: "failed to decode Protobuf message: MsgInstantiateContractResponse.data: invalid wire type".to_owned() }); - } - let (len, data) = data.split_at(1); - println!("reply data 4: {:#?}", data); - let (data, _rest) = data.split_at(len[0] as usize); - println!("reply data 5: {:#?}", data); - let data = if data.is_empty() { - None - } else { - Some(Binary(data.to_vec())) - }; + let mut data = data.0; + // Parse contract addr + let contract_addr = parse_protobuf_string(&mut data)?; + + // Parse (optional) data + let data = parse_protobuf_bytes(&mut data)?; let res = MsgInstantiateContractResponse { - contract_address: String::from_utf8(contract_addr.to_vec())?, + contract_address: contract_addr, data, }; @@ -61,8 +74,8 @@ pub enum ParseReplyError { #[error("Failure response from sub-message: {0}")] SubMsgFailure(String), - #[error("Invalid reply from sub-message {id}: {err}")] - ParseFailure { id: u64, err: String }, + #[error("Invalid reply from sub-message: {0}")] + ParseFailure(String), #[error("Error occurred while converting from UTF-8")] FromUtf8(#[from] std::string::FromUtf8Error), From 16dbb2d42c75d181abbd0765326cf152702c96b4 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Wed, 20 Oct 2021 22:24:31 +0200 Subject: [PATCH 04/26] Add length checks / avoid panic --- packages/cw0/src/parse_reply.rs | 35 ++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 078c8de28..32ff1bdda 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -12,18 +12,33 @@ pub struct MsgInstantiateContractResponse { } fn parse_protobuf_string(data: &mut Vec) -> Result { - // FIXME: don't panic + if data.is_empty() { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: string field: message too short".to_owned(), + )); + } let mut rest_1 = data.split_off(1); if data[0] & 0x03 != WIRE_TYPE_LENGTH_DELIMITED { return Err(ParseReplyError::ParseFailure( "failed to decode Protobuf message: string field: invalid wire type".to_owned(), )); } + if rest_1.is_empty() { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: string field: message too short".to_owned(), + )); + } let mut rest_2 = rest_1.split_off(1); - let rest_3 = rest_2.split_off(rest_1[0] as usize); + let len = rest_1[0] as usize; + if rest_2.len() < len { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: string field: message too short".to_owned(), + )); + } + let rest_3 = rest_2.split_off(len); *data = rest_3; - Ok(String::from_utf8(rest_2.to_owned())?) + Ok(String::from_utf8(rest_2)?) } fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReplyError> { @@ -36,9 +51,19 @@ fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReply "failed to decode Protobuf message: bytes field: invalid wire type".to_owned(), )); } - // FIXME: don't panic + if rest_1.is_empty() { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: bytes field: message too short".to_owned(), + )); + } let mut rest_2 = rest_1.split_off(1); - let rest_3 = rest_2.split_off(rest_1[0] as usize); + let len = rest_1[0] as usize; + if rest_2.len() < len { + return Err(ParseReplyError::ParseFailure( + "failed to decode Protobuf message: bytes field: message too short".to_owned(), + )); + } + let rest_3 = rest_2.split_off(len); *data = rest_3; Ok(Some(Binary(rest_2.to_vec()))) From f14dec1a765ad29de7419122769d49ae8ed1233c Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 10:01:57 +0200 Subject: [PATCH 05/26] Add length-prefixed field protobuf parser --- packages/cw0/src/parse_reply.rs | 75 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 32ff1bdda..f1a6d38ef 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -8,65 +8,62 @@ const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2; #[derive(Clone, Debug, PartialEq)] pub struct MsgInstantiateContractResponse { pub contract_address: String, - pub data: Option, // FIXME: Confirm if Option + pub data: Option, } -fn parse_protobuf_string(data: &mut Vec) -> Result { +/// Helper function to parse length-prefixed protobuf fields. +/// The remaining of the data is kept in the data parameter. +fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseReplyError> { if data.is_empty() { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: string field: message too short".to_owned(), - )); - } + return Ok(vec![]); + }; let mut rest_1 = data.split_off(1); - if data[0] & 0x03 != WIRE_TYPE_LENGTH_DELIMITED { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: string field: invalid wire type".to_owned(), - )); + let wire_type = data[0] & 0b11; + let field = data[0] >> 3; + + if wire_type != WIRE_TYPE_LENGTH_DELIMITED { + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: field #{}: invalid wire type {}", + field, wire_type + ))); } if rest_1.is_empty() { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: string field: message too short".to_owned(), - )); + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: field #{}: message too short", + field + ))); } let mut rest_2 = rest_1.split_off(1); let len = rest_1[0] as usize; if rest_2.len() < len { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: string field: message too short".to_owned(), - )); + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: field #{}: message too short", + field + ))); } let rest_3 = rest_2.split_off(len); *data = rest_3; - Ok(String::from_utf8(rest_2)?) + Ok(rest_2) } -fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReplyError> { - if data.is_empty() { - return Ok(None); - } - let mut rest_1 = data.split_off(1); - if data[0] & 0x03 != WIRE_TYPE_LENGTH_DELIMITED { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: bytes field: invalid wire type".to_owned(), - )); - } - if rest_1.is_empty() { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: bytes field: message too short".to_owned(), - )); - } - let mut rest_2 = rest_1.split_off(1); - let len = rest_1[0] as usize; - if rest_2.len() < len { +fn parse_protobuf_string(data: &mut Vec) -> Result { + let str_field = parse_protobuf_length_prefixed(data)?; + if str_field.is_empty() { return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: bytes field: message too short".to_owned(), + "failed to decode Protobuf message: string field: message too short".to_owned(), )); } - let rest_3 = rest_2.split_off(len); + Ok(String::from_utf8(str_field)?) +} - *data = rest_3; - Ok(Some(Binary(rest_2.to_vec()))) +fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReplyError> { + let bytes_field = parse_protobuf_length_prefixed(data)?; + if bytes_field.is_empty() { + Ok(None) + } else { + Ok(Some(Binary(bytes_field))) + } } pub fn parse_reply_instantiate_data( From bb4baad8a86bb6b789f6dd367ccf5c6b0a56a4d1 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 12:10:10 +0200 Subject: [PATCH 06/26] Add parse_reply_execute_data helper --- packages/cw0/src/lib.rs | 2 +- packages/cw0/src/parse_reply.rs | 61 +++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/packages/cw0/src/lib.rs b/packages/cw0/src/lib.rs index 13236d328..d84e61a3f 100644 --- a/packages/cw0/src/lib.rs +++ b/packages/cw0/src/lib.rs @@ -8,7 +8,7 @@ mod payment; pub use pagination::{ calc_range_end, calc_range_start, calc_range_start_string, maybe_addr, maybe_canonical, }; -pub use parse_reply::parse_reply_instantiate_data; +pub use parse_reply::{parse_reply_execute_data, parse_reply_instantiate_data}; pub use payment::{may_pay, must_pay, nonpayable, one_coin, PaymentError}; pub use crate::balance::NativeBalance; diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index f1a6d38ef..943b46b72 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -11,6 +11,11 @@ pub struct MsgInstantiateContractResponse { pub data: Option, } +#[derive(Clone, Debug, PartialEq)] +pub struct MsgExecuteContractResponse { + pub data: Option, +} + /// Helper function to parse length-prefixed protobuf fields. /// The remaining of the data is kept in the data parameter. fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseReplyError> { @@ -83,12 +88,25 @@ pub fn parse_reply_instantiate_data( // Parse (optional) data let data = parse_protobuf_bytes(&mut data)?; - let res = MsgInstantiateContractResponse { + Ok(MsgInstantiateContractResponse { contract_address: contract_addr, data, - }; + }) +} + +pub fn parse_reply_execute_data(msg: Reply) -> Result { + let data = msg + .result + .into_result() + .map_err(ParseReplyError::SubMsgFailure)? + .data + .ok_or_else(|| ParseReplyError::ParseFailure("Missing reply data".to_owned()))?; + // Manual protobuf decoding + let mut data = data.0; + // Parse (optional) data + let data = parse_protobuf_bytes(&mut data)?; - Ok(res) + Ok(MsgExecuteContractResponse { data }) } #[derive(Error, Debug, PartialEq)] @@ -117,6 +135,12 @@ mod test { pub data: ::prost::alloc::vec::Vec, } + #[derive(Clone, PartialEq, Message)] + pub struct MsgExecuteContractResponse { + #[prost(bytes, tag = "1")] + pub data: ::prost::alloc::vec::Vec, + } + #[test] fn parse_reply_instantiate_data_works() { let instantiate_reply_data: &str = "Contract #1"; @@ -149,4 +173,35 @@ mod test { } ); } + + #[test] + fn parse_reply_execute_data_works() { + for data in [vec![], vec![1u8, 2, 3, 127]] { + let expected = if data.is_empty() { + super::MsgExecuteContractResponse { data: None } + } else { + super::MsgExecuteContractResponse { + data: Some(Binary(data.clone())), + } + }; + + let execute_reply = MsgExecuteContractResponse { data }; + let mut encoded_execute_reply = Vec::::with_capacity(execute_reply.encoded_len()); + // The data must encode successfully + execute_reply.encode(&mut encoded_execute_reply).unwrap(); + + // Build reply message + let msg = Reply { + id: 1, + result: ContractResult::Ok(SubMsgExecutionResponse { + events: vec![], + data: Some(encoded_execute_reply.into()), + }), + }; + + let res = parse_reply_execute_data(msg).unwrap(); + + assert_eq!(res, expected); + } + } } From 0cee15ae1be1cbd49ae7b191e6d1ab9f690c4a53 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 12:25:43 +0200 Subject: [PATCH 07/26] Add empty instantiate data check --- packages/cw0/src/parse_reply.rs | 65 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 943b46b72..58c5393f9 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -143,35 +143,42 @@ mod test { #[test] fn parse_reply_instantiate_data_works() { - let instantiate_reply_data: &str = "Contract #1"; - let instantiate_reply = MsgInstantiateContractResponse { - contract_address: instantiate_reply_data.to_string(), - data: vec![1u8, 2, 3, 4], - }; - let mut encoded_instantiate_reply = - Vec::::with_capacity(instantiate_reply.encoded_len()); - // The data must encode successfully - instantiate_reply - .encode(&mut encoded_instantiate_reply) - .unwrap(); - - // Build reply message - let msg = Reply { - id: 1, - result: ContractResult::Ok(SubMsgExecutionResponse { - events: vec![], - data: Some(encoded_instantiate_reply.into()), - }), - }; - - let res = parse_reply_instantiate_data(msg).unwrap(); - assert_eq!( - res, - super::MsgInstantiateContractResponse { - contract_address: instantiate_reply_data.into(), - data: Some(Binary(vec![1u8, 2, 3, 4])), - } - ); + let contract_addr: &str = "Contract #1"; + for data in [vec![], vec![1u8, 2, 255, 7, 5]] { + let expected = if data.is_empty() { + super::MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data: None, + } + } else { + super::MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data: Some(Binary(data.clone())), + } + }; + let instantiate_reply = MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data, + }; + let mut encoded_instantiate_reply = + Vec::::with_capacity(instantiate_reply.encoded_len()); + // The data must encode successfully + instantiate_reply + .encode(&mut encoded_instantiate_reply) + .unwrap(); + + // Build reply message + let msg = Reply { + id: 1, + result: ContractResult::Ok(SubMsgExecutionResponse { + events: vec![], + data: Some(encoded_instantiate_reply.into()), + }), + }; + + let res = parse_reply_instantiate_data(msg).unwrap(); + assert_eq!(res, expected); + } } #[test] From ad1cc93c6fee6c875424064f4cb01b8fed9323c2 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 17:11:35 +0200 Subject: [PATCH 08/26] Add field number to parse protobuf helpers --- packages/cw0/src/parse_reply.rs | 41 ++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 58c5393f9..91b8501a8 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -18,7 +18,10 @@ pub struct MsgExecuteContractResponse { /// Helper function to parse length-prefixed protobuf fields. /// The remaining of the data is kept in the data parameter. -fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseReplyError> { +fn parse_protobuf_length_prefixed( + data: &mut Vec, + field_number: u8, +) -> Result, ParseReplyError> { if data.is_empty() { return Ok(vec![]); }; @@ -26,16 +29,22 @@ fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseRe let wire_type = data[0] & 0b11; let field = data[0] >> 3; + if field != field_number { + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: invalid field #{} for field #{}", + field, field_number + ))); + } if wire_type != WIRE_TYPE_LENGTH_DELIMITED { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: invalid wire type {}", - field, wire_type + field_number, wire_type ))); } if rest_1.is_empty() { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: message too short", - field + field_number ))); } let mut rest_2 = rest_1.split_off(1); @@ -43,7 +52,7 @@ fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseRe if rest_2.len() < len { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: message too short", - field + field_number ))); } let rest_3 = rest_2.split_off(len); @@ -52,18 +61,22 @@ fn parse_protobuf_length_prefixed(data: &mut Vec) -> Result, ParseRe Ok(rest_2) } -fn parse_protobuf_string(data: &mut Vec) -> Result { - let str_field = parse_protobuf_length_prefixed(data)?; +fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { + let str_field = parse_protobuf_length_prefixed(data, field_number)?; if str_field.is_empty() { - return Err(ParseReplyError::ParseFailure( - "failed to decode Protobuf message: string field: message too short".to_owned(), - )); + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: string field #{}: message too short", + field_number + ))); } Ok(String::from_utf8(str_field)?) } -fn parse_protobuf_bytes(data: &mut Vec) -> Result, ParseReplyError> { - let bytes_field = parse_protobuf_length_prefixed(data)?; +fn parse_protobuf_bytes( + data: &mut Vec, + field_number: u8, +) -> Result, ParseReplyError> { + let bytes_field = parse_protobuf_length_prefixed(data, field_number)?; if bytes_field.is_empty() { Ok(None) } else { @@ -83,10 +96,10 @@ pub fn parse_reply_instantiate_data( // Manual protobuf decoding let mut data = data.0; // Parse contract addr - let contract_addr = parse_protobuf_string(&mut data)?; + let contract_addr = parse_protobuf_string(&mut data, 1)?; // Parse (optional) data - let data = parse_protobuf_bytes(&mut data)?; + let data = parse_protobuf_bytes(&mut data, 2)?; Ok(MsgInstantiateContractResponse { contract_address: contract_addr, @@ -104,7 +117,7 @@ pub fn parse_reply_execute_data(msg: Reply) -> Result Date: Thu, 21 Oct 2021 18:09:15 +0200 Subject: [PATCH 09/26] Add protobuf base128 varint decoding --- packages/cw0/src/parse_reply.rs | 50 +++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 91b8501a8..c65ebb715 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -4,6 +4,8 @@ use cosmwasm_std::{Binary, Reply}; // Protobuf wire types (https://developers.google.com/protocol-buffers/docs/encoding) const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2; +// Up to 9 bytes of varints as a practical limit (https://github.com/multiformats/unsigned-varint#practical-maximum-of-9-bytes-for-security) +const VARINT_MAX_BYTES: usize = 9; #[derive(Clone, Debug, PartialEq)] pub struct MsgInstantiateContractResponse { @@ -16,6 +18,37 @@ pub struct MsgExecuteContractResponse { pub data: Option, } +/// Base128 varint decoding. +/// The remaining of the data is kept in the data parameter. +fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result { + let data_len = data.len(); + let mut len: u64 = 0; + let mut i = 0; + while i < VARINT_MAX_BYTES { + if data_len == i { + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: field #{}: varint data too short", + field_number + ))); + } + len <<= 7; + len += (data[i] & 0x7f) as u64; + if data[i] & 0x80 == 0 { + break; + } + i += 1; + } + if i == VARINT_MAX_BYTES { + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: field #{}: varint data too long", + field_number + ))); + } + *data = data.split_off(i + 1); + + Ok(len as usize) // Gently fall back to the arch's max addressable size +} + /// Helper function to parse length-prefixed protobuf fields. /// The remaining of the data is kept in the data parameter. fn parse_protobuf_length_prefixed( @@ -41,24 +74,17 @@ fn parse_protobuf_length_prefixed( field_number, wire_type ))); } - if rest_1.is_empty() { - return Err(ParseReplyError::ParseFailure(format!( - "failed to decode Protobuf message: field #{}: message too short", - field_number - ))); - } - let mut rest_2 = rest_1.split_off(1); - let len = rest_1[0] as usize; - if rest_2.len() < len { + + let len = parse_protobuf_varint(&mut rest_1, field_number)?; + if rest_1.len() < len { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: message too short", field_number ))); } - let rest_3 = rest_2.split_off(len); + *data = rest_1.split_off(len); - *data = rest_3; - Ok(rest_2) + Ok(rest_1) } fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { From 9b69ce06737a4032eb5ecdbde27c3d9eac37b604 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 19:41:23 +0200 Subject: [PATCH 10/26] Fix protobuf base128 varint decoding Add high-level varint decoding tests --- packages/cw0/src/parse_reply.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index c65ebb715..c1aca25e6 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -31,8 +31,8 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= 7; + len += ((data[i] & 0x7f) as u64) << 57; if data[i] & 0x80 == 0 { break; } @@ -44,7 +44,9 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= (VARINT_MAX_BYTES - i) * 7 + 1; + *data = data.split_off(i); Ok(len as usize) // Gently fall back to the arch's max addressable size } @@ -76,6 +78,7 @@ fn parse_protobuf_length_prefixed( } let len = parse_protobuf_varint(&mut rest_1, field_number)?; + println!("field #{}: len: {}", field_number, len); if rest_1.len() < len { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: message too short", @@ -183,7 +186,13 @@ mod test { #[test] fn parse_reply_instantiate_data_works() { let contract_addr: &str = "Contract #1"; - for data in [vec![], vec![1u8, 2, 255, 7, 5]] { + for data in [ + vec![], + vec![1u8, 2, 255, 7, 5], + vec![1u8; 127], + vec![2u8; 128], + vec![3u8; 257], + ] { let expected = if data.is_empty() { super::MsgInstantiateContractResponse { contract_address: contract_addr.to_string(), @@ -222,7 +231,13 @@ mod test { #[test] fn parse_reply_execute_data_works() { - for data in [vec![], vec![1u8, 2, 3, 127]] { + for data in [ + vec![], + vec![1u8, 2, 3, 127, 15], + vec![0u8; 255], + vec![1u8; 256], + vec![2u8; 32769], + ] { let expected = if data.is_empty() { super::MsgExecuteContractResponse { data: None } } else { From 82449ebb15f1ad517b56e3458f67244949f2e98d Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 19:53:14 +0200 Subject: [PATCH 11/26] Define the expected data explicitly --- packages/cw0/src/parse_reply.rs | 85 ++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index c1aca25e6..b71df3a78 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -186,24 +186,43 @@ mod test { #[test] fn parse_reply_instantiate_data_works() { let contract_addr: &str = "Contract #1"; - for data in [ - vec![], - vec![1u8, 2, 255, 7, 5], - vec![1u8; 127], - vec![2u8; 128], - vec![3u8; 257], - ] { - let expected = if data.is_empty() { + for (data, expected) in [ + ( + vec![], super::MsgInstantiateContractResponse { contract_address: contract_addr.to_string(), data: None, - } - } else { + }, + ), + ( + vec![1u8, 2, 255, 7, 5], super::MsgInstantiateContractResponse { contract_address: contract_addr.to_string(), - data: Some(Binary(data.clone())), - } - }; + data: Some(Binary(vec![1u8, 2, 255, 7, 5])), + }, + ), + ( + vec![1u8; 127], + super::MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data: Some(Binary(vec![1u8; 127])), + }, + ), + ( + vec![2u8; 128], + super::MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data: Some(Binary(vec![2u8; 128])), + }, + ), + ( + vec![3u8; 257], + super::MsgInstantiateContractResponse { + contract_address: contract_addr.to_string(), + data: Some(Binary(vec![3u8; 257])), + }, + ), + ] { let instantiate_reply = MsgInstantiateContractResponse { contract_address: contract_addr.to_string(), data, @@ -231,21 +250,33 @@ mod test { #[test] fn parse_reply_execute_data_works() { - for data in [ - vec![], - vec![1u8, 2, 3, 127, 15], - vec![0u8; 255], - vec![1u8; 256], - vec![2u8; 32769], - ] { - let expected = if data.is_empty() { - super::MsgExecuteContractResponse { data: None } - } else { + for (data, expected) in [ + (vec![], super::MsgExecuteContractResponse { data: None }), + ( + vec![1u8, 2, 3, 127, 15], super::MsgExecuteContractResponse { - data: Some(Binary(data.clone())), - } - }; - + data: Some(Binary(vec![1u8, 2, 3, 127, 15])), + }, + ), + ( + vec![0u8; 255], + super::MsgExecuteContractResponse { + data: Some(Binary(vec![0u8; 255])), + }, + ), + ( + vec![1u8; 256], + super::MsgExecuteContractResponse { + data: Some(Binary(vec![1u8; 256])), + }, + ), + ( + vec![2u8; 32769], + super::MsgExecuteContractResponse { + data: Some(Binary(vec![2u8; 32769])), + }, + ), + ] { let execute_reply = MsgExecuteContractResponse { data }; let mut encoded_execute_reply = Vec::::with_capacity(execute_reply.encoded_len()); // The data must encode successfully From 1e1e19bc12494af45c374612436c3cb5925cd83a Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 21 Oct 2021 20:11:06 +0200 Subject: [PATCH 12/26] Remove unnecessary / extra bit shifts --- packages/cw0/src/parse_reply.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index b71df3a78..908fe26d6 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -32,7 +32,7 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= 7; - len += ((data[i] & 0x7f) as u64) << 57; + len += ((data[i] & 0x7f) as u64) << 56; if data[i] & 0x80 == 0 { break; } @@ -45,7 +45,7 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= (VARINT_MAX_BYTES - i) * 7 + 1; + len >>= (VARINT_MAX_BYTES - i) * 7; *data = data.split_off(i); Ok(len as usize) // Gently fall back to the arch's max addressable size From ff259711928eb7b592510539119c6f0dbe04e7e4 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Fri, 22 Oct 2021 19:36:39 +0200 Subject: [PATCH 13/26] Add string works tests --- packages/cw0/src/parse_reply.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 908fe26d6..bb63875e3 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -92,12 +92,6 @@ fn parse_protobuf_length_prefixed( fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { let str_field = parse_protobuf_length_prefixed(data, field_number)?; - if str_field.is_empty() { - return Err(ParseReplyError::ParseFailure(format!( - "failed to decode Protobuf message: string field #{}: message too short", - field_number - ))); - } Ok(String::from_utf8(str_field)?) } @@ -183,6 +177,26 @@ mod test { pub data: ::prost::alloc::vec::Vec, } + #[test] + fn parse_protobuf_string_works() { + for (i, (mut data, field_number, expected, rest)) in (1..).zip([ + (b"\x0a\x00".to_vec(), 1, "", vec![0u8; 0]), + (b"\x0a\x01a".to_vec(), 1, "a", vec![0u8; 0]), + (b"\x0a\x06testf1".to_vec(), 1, "testf1", vec![0u8; 0]), + (b"\x12\x09testingf2".to_vec(), 2, "testingf2", vec![0u8; 0]), + ( + b"\x0a\x04test_remainder".to_vec(), + 1, + "test", + b"_remainder".to_vec(), + ), + ]) { + let res = parse_protobuf_string(&mut data, field_number).unwrap(); + assert_eq!(res, expected, "test #{}", i); + assert_eq!(data, rest, "test #{}", i); + } + } + #[test] fn parse_reply_instantiate_data_works() { let contract_addr: &str = "Contract #1"; From 489133b50d5da20e89f0812103f9d9c8aaf55dbe Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 11:48:37 +0200 Subject: [PATCH 14/26] Add string errs tests Fix protobuf string parser: message too short --- packages/cw0/src/parse_reply.rs | 61 +++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index bb63875e3..bc619de6d 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -78,7 +78,6 @@ fn parse_protobuf_length_prefixed( } let len = parse_protobuf_varint(&mut rest_1, field_number)?; - println!("field #{}: len: {}", field_number, len); if rest_1.len() < len { return Err(ParseReplyError::ParseFailure(format!( "failed to decode Protobuf message: field #{}: message too short", @@ -91,6 +90,12 @@ fn parse_protobuf_length_prefixed( } fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { + if data.is_empty() { + return Err(ParseReplyError::ParseFailure(format!( + "failed to decode Protobuf message: string field #{}: message too short", + field_number + ))); + } let str_field = parse_protobuf_length_prefixed(data, field_number)?; Ok(String::from_utf8(str_field)?) } @@ -154,12 +159,13 @@ pub enum ParseReplyError { ParseFailure(String), #[error("Error occurred while converting from UTF-8")] - FromUtf8(#[from] std::string::FromUtf8Error), + BrokenUtf8(#[from] std::string::FromUtf8Error), } #[cfg(test)] mod test { use super::*; + use crate::parse_reply::ParseReplyError::{BrokenUtf8, ParseFailure}; use cosmwasm_std::{ContractResult, SubMsgExecutionResponse}; use prost::Message; @@ -197,6 +203,57 @@ mod test { } } + #[test] + fn parse_protobuf_string_errs() { + // Correct for reference + let field_number = 1; + let mut data = b"\x0a\x01a".to_vec(); + let res = parse_protobuf_string(&mut data, field_number).unwrap(); + assert_eq!(res, "a".to_string()); + + // message too short. Non-optional string + let mut data = vec![]; + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // varint data too short + let mut data = b"\x0a".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // varint data too short + let mut data = b"\x0a\x80".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // varint data too long + let mut data = b"\x0a\x80\x80\x80\x80\x80\x80\x80\x80\x80".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // message too short + let mut data = b"\x0a\x01".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // invalid wire type + let mut data = b"\x0b\x01a".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // invalid field number + let field_number = 2; + let mut data = b"\x0a\x01a".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // FromUtf8Error + let field_number = 1; + let mut data = b"\x0a\x04abc\xd3".to_vec(); + let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + assert!(matches!(err, BrokenUtf8(..))); + } + #[test] fn parse_reply_instantiate_data_works() { let contract_addr: &str = "Contract #1"; From 68f2121b5e82bb69670a0f06166ea4f20525d82f Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 12:20:03 +0200 Subject: [PATCH 15/26] Add bytes works tests --- packages/cw0/src/parse_reply.rs | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index bc619de6d..4db6023b3 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -183,6 +183,42 @@ mod test { pub data: ::prost::alloc::vec::Vec, } + #[test] + fn parse_protobuf_bytes_works() { + for (i, (mut data, field_number, expected, rest)) in (1..).zip([ + (vec![0u8; 0], 1, None, vec![0u8; 0]), + (b"\x0a\x00".to_vec(), 1, None, vec![0u8; 0]), + ( + b"\x0a\x01a".to_vec(), + 1, + Some(Binary(b"a".to_vec())), + vec![0u8; 0], + ), + ( + b"\x0a\x06testf1".to_vec(), + 1, + Some(Binary(b"testf1".to_vec())), + vec![0u8; 0], + ), + ( + b"\x12\x09testingf2".to_vec(), + 2, + Some(Binary(b"testingf2".to_vec())), + vec![0u8; 0], + ), + ( + b"\x0a\x04test_remainder".to_vec(), + 1, + Some(Binary(b"test".to_vec())), + b"_remainder".to_vec(), + ), + ]) { + let res = parse_protobuf_bytes(&mut data, field_number).unwrap(); + assert_eq!(res, expected, "test #{}", i); + assert_eq!(data, rest, "test #{}", i); + } + } + #[test] fn parse_protobuf_string_works() { for (i, (mut data, field_number, expected, rest)) in (1..).zip([ From 4d29b4c9739ad0c114e8e90f5b840b54dda7f9de Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 13:14:37 +0200 Subject: [PATCH 16/26] Add varint and length prefixed tests --- packages/cw0/src/parse_reply.rs | 130 +++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 35 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 4db6023b3..e6f01e048 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -92,8 +92,8 @@ fn parse_protobuf_length_prefixed( fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { if data.is_empty() { return Err(ParseReplyError::ParseFailure(format!( - "failed to decode Protobuf message: string field #{}: message too short", - field_number + "failed to decode Protobuf message: string field #{}: message too short", + field_number ))); } let str_field = parse_protobuf_length_prefixed(data, field_number)?; @@ -183,10 +183,101 @@ mod test { pub data: ::prost::alloc::vec::Vec, } + #[test] + fn parse_protobuf_varint_tests() { + let field_number = 1; + // Single-byte varint works + let mut data = b"\x0a".to_vec(); + let len = parse_protobuf_varint(&mut data, field_number).unwrap(); + assert_eq!(len, 10); + + // Rest is returned + let mut data = b"\x0a\x0b".to_vec(); + let len = parse_protobuf_varint(&mut data, field_number).unwrap(); + assert_eq!(len, 10); + assert_eq!(data, b"\x0b".to_vec()); + + // Multi-byte varint works + // 300 % 128 = 44. 44 + 128 = 172 (0xac) (1st byte) + // 300 / 128 = 2 (x02) (2nd byte) + let mut data = b"\xac\x02".to_vec(); + let len = parse_protobuf_varint(&mut data, field_number).unwrap(); + assert_eq!(len, 300); + + // Rest is returned + let mut data = b"\xac\x02\x0c".to_vec(); + let len = parse_protobuf_varint(&mut data, field_number).unwrap(); + assert_eq!(len, 300); + assert_eq!(data, b"\x0c".to_vec()); + + // varint data too short (Empty varint) + let mut data = vec![]; + let err = parse_protobuf_varint(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // varint data too short (Incomplete varint) + let mut data = b"\x80".to_vec(); + let err = parse_protobuf_varint(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // varint data too long + let mut data = b"\x80\x81\x82\x83\x84\x83\x82\x81\x80".to_vec(); + let err = parse_protobuf_varint(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + } + + #[test] + fn parse_protobuf_length_prefixed_tests() { + let field_number = 1; + // Single-byte length-prefixed works + let mut data = b"\x0a\x03abc".to_vec(); + let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap(); + assert_eq!(res, b"abc".to_vec()); + assert_eq!(data, vec![0u8; 0]); + + // Rest is returned + let mut data = b"\x0a\x03abcd".to_vec(); + let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap(); + assert_eq!(res, b"abc".to_vec()); + assert_eq!(data, b"d".to_vec()); + + // Multi-byte length-prefixed works + let mut data = [b"\x0a\xac\x02", vec![65u8; 300].as_slice()] + .concat() + .to_vec(); + let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap(); + assert_eq!(res, vec![65u8; 300]); + assert_eq!(data, vec![0u8; 0]); + + // Rest is returned + let mut data = [b"\x0a\xac\x02", vec![65u8; 300].as_slice(), b"rest"] + .concat() + .to_vec(); + let res = parse_protobuf_length_prefixed(&mut data, field_number).unwrap(); + assert_eq!(res, vec![65u8; 300]); + assert_eq!(data, b"rest"); + + // message too short + let mut data = b"\x0a\x01".to_vec(); + let field_number = 1; + let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // invalid wire type + let mut data = b"\x0b\x01a".to_vec(); + let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + + // invalid field number + let field_number = 2; + let mut data = b"\x0a\x01a".to_vec(); + let err = parse_protobuf_length_prefixed(&mut data, field_number).unwrap_err(); + assert!(matches!(err, ParseFailure(..))); + } + #[test] fn parse_protobuf_bytes_works() { for (i, (mut data, field_number, expected, rest)) in (1..).zip([ - (vec![0u8; 0], 1, None, vec![0u8; 0]), (b"\x0a\x00".to_vec(), 1, None, vec![0u8; 0]), ( b"\x0a\x01a".to_vec(), @@ -247,42 +338,11 @@ mod test { let res = parse_protobuf_string(&mut data, field_number).unwrap(); assert_eq!(res, "a".to_string()); - // message too short. Non-optional string + // string message too short. Non-optional string let mut data = vec![]; let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); assert!(matches!(err, ParseFailure(..))); - // varint data too short - let mut data = b"\x0a".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - - // varint data too short - let mut data = b"\x0a\x80".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - - // varint data too long - let mut data = b"\x0a\x80\x80\x80\x80\x80\x80\x80\x80\x80".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - - // message too short - let mut data = b"\x0a\x01".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - - // invalid wire type - let mut data = b"\x0b\x01a".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - - // invalid field number - let field_number = 2; - let mut data = b"\x0a\x01a".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - // FromUtf8Error let field_number = 1; let mut data = b"\x0a\x04abc\xd3".to_vec(); From 4abee6a405ace2b6d6cc9d91b7c1bad10cd4f7e1 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 18:54:21 +0200 Subject: [PATCH 17/26] Use protobuf encoding helper for bytes tests --- packages/cw0/src/parse_reply.rs | 93 +++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index e6f01e048..59d2181c9 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -169,8 +169,24 @@ mod test { use cosmwasm_std::{ContractResult, SubMsgExecutionResponse}; use prost::Message; + fn encode_bytes(data: &Vec) -> Vec { + #[derive(Clone, PartialEq, Message)] + struct ProtobufBytes { + #[prost(bytes, tag = "1")] + pub data: Vec, + } + + let data = ProtobufBytes { + data: data.to_vec(), + }; + let mut encoded_data = Vec::::with_capacity(data.encoded_len()); + data.encode(&mut encoded_data).unwrap(); + + encoded_data + } + #[derive(Clone, PartialEq, Message)] - pub struct MsgInstantiateContractResponse { + struct MsgInstantiateContractResponse { #[prost(string, tag = "1")] pub contract_address: ::prost::alloc::string::String, #[prost(bytes, tag = "2")] @@ -178,7 +194,7 @@ mod test { } #[derive(Clone, PartialEq, Message)] - pub struct MsgExecuteContractResponse { + struct MsgExecuteContractResponse { #[prost(bytes, tag = "1")] pub data: ::prost::alloc::vec::Vec, } @@ -277,37 +293,48 @@ mod test { #[test] fn parse_protobuf_bytes_works() { - for (i, (mut data, field_number, expected, rest)) in (1..).zip([ - (b"\x0a\x00".to_vec(), 1, None, vec![0u8; 0]), - ( - b"\x0a\x01a".to_vec(), - 1, - Some(Binary(b"a".to_vec())), - vec![0u8; 0], - ), - ( - b"\x0a\x06testf1".to_vec(), - 1, - Some(Binary(b"testf1".to_vec())), - vec![0u8; 0], - ), - ( - b"\x12\x09testingf2".to_vec(), - 2, - Some(Binary(b"testingf2".to_vec())), - vec![0u8; 0], - ), - ( - b"\x0a\x04test_remainder".to_vec(), - 1, - Some(Binary(b"test".to_vec())), - b"_remainder".to_vec(), - ), - ]) { - let res = parse_protobuf_bytes(&mut data, field_number).unwrap(); - assert_eq!(res, expected, "test #{}", i); - assert_eq!(data, rest, "test #{}", i); - } + let field_number = 1; + + // Empty works + let data = vec![]; + let mut encoded_data = encode_bytes(&data); + + let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, None); + + // Simple works + let data = b"test".to_vec(); + let mut encoded_data = encode_bytes(&data.to_vec()); + + let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, Some(Binary(data.to_vec()))); + + // Large works + let data = vec![0x40; 300]; + let mut encoded_data = encode_bytes(&data.to_vec()); + + let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, Some(Binary(data.to_vec()))); + + // Field number works + let field_number = 5; + let data = b"test field2".to_vec(); + let mut encoded_data = encode_bytes(&data.to_vec()); + encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED; + + let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, Some(Binary(data.to_vec()))); + + // Remainder is kept + let field_number = 1; + let test_len: usize = 4; + let data = b"test_remainder".to_vec(); + let mut encoded_data = encode_bytes(&data.to_vec()); + encoded_data[1] = test_len as u8; + + let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, Some(Binary(data[..test_len].to_owned()))); + assert_eq!(encoded_data, data[test_len..].to_owned()); } #[test] From ed54fb8fad6b1f2d439a827c4f9581401fff9529 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 19:16:04 +0200 Subject: [PATCH 18/26] Use protobuf encoding helper for string --- packages/cw0/src/parse_reply.rs | 78 ++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 59d2181c9..b4da3cb4f 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -168,6 +168,7 @@ mod test { use crate::parse_reply::ParseReplyError::{BrokenUtf8, ParseFailure}; use cosmwasm_std::{ContractResult, SubMsgExecutionResponse}; use prost::Message; + use std::str::from_utf8; fn encode_bytes(data: &Vec) -> Vec { #[derive(Clone, PartialEq, Message)] @@ -185,6 +186,22 @@ mod test { encoded_data } + fn encode_string(data: &str) -> Vec { + #[derive(Clone, PartialEq, Message)] + struct ProtobufString { + #[prost(string, tag = "1")] + pub data: String, + } + + let data = ProtobufString { + data: data.to_string(), + }; + let mut encoded_data = Vec::::with_capacity(data.encoded_len()); + data.encode(&mut encoded_data).unwrap(); + + encoded_data + } + #[derive(Clone, PartialEq, Message)] struct MsgInstantiateContractResponse { #[prost(string, tag = "1")] @@ -318,7 +335,7 @@ mod test { // Field number works let field_number = 5; - let data = b"test field2".to_vec(); + let data = b"test field 5".to_vec(); let mut encoded_data = encode_bytes(&data.to_vec()); encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED; @@ -339,22 +356,49 @@ mod test { #[test] fn parse_protobuf_string_works() { - for (i, (mut data, field_number, expected, rest)) in (1..).zip([ - (b"\x0a\x00".to_vec(), 1, "", vec![0u8; 0]), - (b"\x0a\x01a".to_vec(), 1, "a", vec![0u8; 0]), - (b"\x0a\x06testf1".to_vec(), 1, "testf1", vec![0u8; 0]), - (b"\x12\x09testingf2".to_vec(), 2, "testingf2", vec![0u8; 0]), - ( - b"\x0a\x04test_remainder".to_vec(), - 1, - "test", - b"_remainder".to_vec(), - ), - ]) { - let res = parse_protobuf_string(&mut data, field_number).unwrap(); - assert_eq!(res, expected, "test #{}", i); - assert_eq!(data, rest, "test #{}", i); - } + let field_number = 1; + + // Empty works + let data = ""; + let mut encoded_data = encode_string(data); + + let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, data); + + // Simple works + let data = "test"; + let mut encoded_data = encode_string(data); + + let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, data); + + // Large works + let data = vec![0x40; 300]; + let str_data = from_utf8(data.as_slice()).unwrap(); + let mut encoded_data = encode_string(str_data); + + let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, str_data); + + // Field number works + let field_number = 5; + let data = "test field 5"; + let mut encoded_data = encode_string(data); + encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED; + + let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, data); + + // Remainder is kept + let field_number = 1; + let test_len: usize = 4; + let data = "test_remainder"; + let mut encoded_data = encode_string(data); + encoded_data[1] = test_len as u8; + + let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); + assert_eq!(res, data[..test_len]); + assert_eq!(encoded_data, data[test_len..].as_bytes()); } #[test] From 6885041a06087b806e5c592642675f3c875053d4 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 19:17:11 +0200 Subject: [PATCH 19/26] Fix empty string case --- packages/cw0/src/parse_reply.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index b4da3cb4f..5fb26494a 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -90,12 +90,6 @@ fn parse_protobuf_length_prefixed( } fn parse_protobuf_string(data: &mut Vec, field_number: u8) -> Result { - if data.is_empty() { - return Err(ParseReplyError::ParseFailure(format!( - "failed to decode Protobuf message: string field #{}: message too short", - field_number - ))); - } let str_field = parse_protobuf_length_prefixed(data, field_number)?; Ok(String::from_utf8(str_field)?) } @@ -409,11 +403,6 @@ mod test { let res = parse_protobuf_string(&mut data, field_number).unwrap(); assert_eq!(res, "a".to_string()); - // string message too short. Non-optional string - let mut data = vec![]; - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); - assert!(matches!(err, ParseFailure(..))); - // FromUtf8Error let field_number = 1; let mut data = b"\x0a\x04abc\xd3".to_vec(); From 2c81a96b4513c2b6eb67257dc55ea0ea2f21d0ec Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 19:25:42 +0200 Subject: [PATCH 20/26] Consolidate string tests --- packages/cw0/src/parse_reply.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 5fb26494a..ede1be056 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -349,7 +349,7 @@ mod test { } #[test] - fn parse_protobuf_string_works() { + fn parse_protobuf_string_tests() { let field_number = 1; // Empty works @@ -393,20 +393,14 @@ mod test { let res = parse_protobuf_string(&mut encoded_data, field_number).unwrap(); assert_eq!(res, data[..test_len]); assert_eq!(encoded_data, data[test_len..].as_bytes()); - } - - #[test] - fn parse_protobuf_string_errs() { - // Correct for reference - let field_number = 1; - let mut data = b"\x0a\x01a".to_vec(); - let res = parse_protobuf_string(&mut data, field_number).unwrap(); - assert_eq!(res, "a".to_string()); - // FromUtf8Error + // Broken utf-8 errs let field_number = 1; - let mut data = b"\x0a\x04abc\xd3".to_vec(); - let err = parse_protobuf_string(&mut data, field_number).unwrap_err(); + let data = "test_X"; + let mut encoded_data = encode_string(data); + let encoded_len = encoded_data.len(); + encoded_data[encoded_len - 1] = 0xd3; + let err = parse_protobuf_string(&mut encoded_data, field_number).unwrap_err(); assert!(matches!(err, BrokenUtf8(..))); } From 36e4e10da5400fad8fa6ba81d2b901abe8703369 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Sat, 23 Oct 2021 19:26:37 +0200 Subject: [PATCH 21/26] Use slice instead of vec --- packages/cw0/src/parse_reply.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index ede1be056..9a2b56631 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -164,7 +164,7 @@ mod test { use prost::Message; use std::str::from_utf8; - fn encode_bytes(data: &Vec) -> Vec { + fn encode_bytes(data: &[u8]) -> Vec { #[derive(Clone, PartialEq, Message)] struct ProtobufBytes { #[prost(bytes, tag = "1")] From ec2f741f5432da7f95a9d6f728c89e5b6b1ed773 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Mon, 25 Oct 2021 21:56:19 +0200 Subject: [PATCH 22/26] Simplify varint computation --- packages/cw0/src/parse_reply.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 9a2b56631..ca8fbfd07 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -31,8 +31,7 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= 7; - len += ((data[i] & 0x7f) as u64) << 56; + len += ((data[i] & 0x7f) as u64) << (i * 7); if data[i] & 0x80 == 0 { break; } @@ -44,9 +43,7 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result>= (VARINT_MAX_BYTES - i) * 7; - *data = data.split_off(i); + *data = data.split_off(i + 1); Ok(len as usize) // Gently fall back to the arch's max addressable size } From 2153df7659fcdec353540cdcadf94e507b6eb7ab Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Mon, 25 Oct 2021 22:15:51 +0200 Subject: [PATCH 23/26] Avoid split_off when possible --- packages/cw0/src/parse_reply.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index ca8fbfd07..327325e3d 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -43,7 +43,7 @@ fn parse_protobuf_varint(data: &mut Vec, field_number: u8) -> Result Date: Mon, 25 Oct 2021 22:18:30 +0200 Subject: [PATCH 24/26] Avoid unnecessary conversion --- packages/cw0/src/parse_reply.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cw0/src/parse_reply.rs b/packages/cw0/src/parse_reply.rs index 327325e3d..2778a4a68 100644 --- a/packages/cw0/src/parse_reply.rs +++ b/packages/cw0/src/parse_reply.rs @@ -312,32 +312,32 @@ mod test { // Simple works let data = b"test".to_vec(); - let mut encoded_data = encode_bytes(&data.to_vec()); + let mut encoded_data = encode_bytes(&data); let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); - assert_eq!(res, Some(Binary(data.to_vec()))); + assert_eq!(res, Some(Binary(data))); // Large works let data = vec![0x40; 300]; - let mut encoded_data = encode_bytes(&data.to_vec()); + let mut encoded_data = encode_bytes(&data); let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); - assert_eq!(res, Some(Binary(data.to_vec()))); + assert_eq!(res, Some(Binary(data))); // Field number works let field_number = 5; let data = b"test field 5".to_vec(); - let mut encoded_data = encode_bytes(&data.to_vec()); + let mut encoded_data = encode_bytes(&data); encoded_data[0] = (field_number << 3) + WIRE_TYPE_LENGTH_DELIMITED; let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); - assert_eq!(res, Some(Binary(data.to_vec()))); + assert_eq!(res, Some(Binary(data))); // Remainder is kept let field_number = 1; let test_len: usize = 4; let data = b"test_remainder".to_vec(); - let mut encoded_data = encode_bytes(&data.to_vec()); + let mut encoded_data = encode_bytes(&data); encoded_data[1] = test_len as u8; let res = parse_protobuf_bytes(&mut encoded_data, field_number).unwrap(); From ad1aa5fbac3c681da81ac474e50c04b420649c8e Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Tue, 26 Oct 2021 19:12:43 +0200 Subject: [PATCH 25/26] Update prost to latest version Co-authored-by: Jakub Bogucki --- packages/cw0/Cargo.toml | 2 +- packages/multi-test/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cw0/Cargo.toml b/packages/cw0/Cargo.toml index 4b6e13cf8..f54307163 100644 --- a/packages/cw0/Cargo.toml +++ b/packages/cw0/Cargo.toml @@ -19,4 +19,4 @@ thiserror = { version = "1.0.21" } [dev-dependencies] cw-storage-plus = { path = "../../packages/storage-plus", version = "0.10.0" } -prost = "0.8.0" +prost = "0.9" diff --git a/packages/multi-test/Cargo.toml b/packages/multi-test/Cargo.toml index 734ad221a..bae1b4325 100644 --- a/packages/multi-test/Cargo.toml +++ b/packages/multi-test/Cargo.toml @@ -25,7 +25,7 @@ cosmwasm-storage = { version = "1.0.0-beta" } itertools = "0.10.1" schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -prost = "0.8.0" +prost = "0.9" anyhow = "1" thiserror = "1" derivative = "2" From a442d7c96c24270cf9c79c596427b0e722efec8d Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Tue, 26 Oct 2021 19:15:00 +0200 Subject: [PATCH 26/26] Update lock file --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8157d9486..d5854b923 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,9 +915,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes", "prost-derive", @@ -925,9 +925,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", "itertools",