Skip to content

Commit

Permalink
extrinsics: fix Vec<AccountId> args (#519)
Browse files Browse the repository at this point in the history
* Add failing account id vec args test

* Fix AccountId seq encoding

* Add some error context and logging

* Fmt
  • Loading branch information
ascjones authored Apr 26, 2022
1 parent 50eaf2a commit 6c0d521
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 49 deletions.
7 changes: 5 additions & 2 deletions src/cmd/extrinsics/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ impl<'a> Exec<'a> {
}

async fn exec(&self, code: Code, dry_run: bool) -> Result<()> {
log::debug!("instantiate data {:?}", self.args.data);
if dry_run {
let result = self.instantiate_dry_run(code).await?;
match result.result {
Expand Down Expand Up @@ -335,8 +336,10 @@ impl<'a> Exec<'a> {
salt: self.args.salt.clone(),
};
let params = rpc_params![call_request];
let result: ContractInstantiateResult =
cli.request("contracts_instantiate", params).await?;
let result: ContractInstantiateResult = cli
.request("contracts_instantiate", params)
.await
.context("contracts_instantiate RPC error")?;
Ok(result)
}
}
Expand Down
59 changes: 23 additions & 36 deletions src/cmd/extrinsics/transcode/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,42 +80,32 @@ impl<'a> Encoder<'a> {
ty.type_def(),
);
if !self.env_types.try_encode(type_id, value, output)? {
self.encode_type(ty.type_def(), value, output)
.map_err(|e| {
anyhow::anyhow!("Error encoding value for {:?}: {}", ty, e)
})?
match ty.type_def() {
TypeDef::Composite(composite) => {
self.encode_composite(composite.fields(), value, output)
}
TypeDef::Variant(variant) => {
self.encode_variant_type(variant, value, output)
}
TypeDef::Array(array) => {
self.encode_seq(array.type_param(), value, false, output)
}
TypeDef::Tuple(tuple) => self.encode_tuple(tuple, value, output),
TypeDef::Sequence(sequence) => {
self.encode_seq(sequence.type_param(), value, true, output)
}
TypeDef::Primitive(primitive) => {
self.encode_primitive(primitive, value, output)
}
TypeDef::Compact(compact) => self.encode_compact(compact, value, output),
TypeDef::BitSequence(_) => {
Err(anyhow::anyhow!("bitvec encoding not yet supported"))
}
}?;
}
Ok(())
}

fn encode_type<O: Output + Debug>(
&self,
type_def: &TypeDef<PortableForm>,
value: &Value,
output: &mut O,
) -> Result<()> {
match type_def {
TypeDef::Composite(composite) => {
self.encode_composite(composite.fields(), value, output)
}
TypeDef::Variant(variant) => self.encode_variant_type(variant, value, output),
TypeDef::Array(array) => {
self.encode_seq(array.type_param(), value, false, output)
}
TypeDef::Tuple(tuple) => self.encode_tuple(tuple, value, output),
TypeDef::Sequence(sequence) => {
self.encode_seq(sequence.type_param(), value, true, output)
}
TypeDef::Primitive(primitive) => {
self.encode_primitive(primitive, value, output)
}
TypeDef::Compact(compact) => self.encode_compact(compact, value, output),
TypeDef::BitSequence(_) => {
Err(anyhow::anyhow!("bitvec encoding not yet supported"))
}
}
}

fn encode_composite<O: Output + Debug>(
&self,
fields: &[Field<PortableForm>],
Expand Down Expand Up @@ -249,16 +239,13 @@ impl<'a> Encoder<'a> {
encode_len: bool,
output: &mut O,
) -> Result<()> {
let ty = self.registry.resolve(ty.id()).ok_or_else(|| {
anyhow::anyhow!("Failed to find type with id '{}'", ty.id())
})?;
match value {
Value::Seq(values) => {
if encode_len {
Compact(values.len() as u32).encode_to(output);
}
for value in values.elems() {
self.encode_type(ty.type_def(), value, output)?;
self.encode(ty.id(), value, output)?;
}
}
Value::Bytes(bytes) => {
Expand Down
9 changes: 7 additions & 2 deletions src/cmd/extrinsics/transcode/env_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use super::scon::Value;
use anyhow::Result;
use anyhow::{
Context,
Result,
};
use scale::{
Decode,
Encode,
Expand Down Expand Up @@ -68,7 +71,9 @@ impl EnvTypesTranscoder {
match self.transcoders.get(&type_id) {
Some(transcoder) => {
log::debug!("Encoding type {:?} with custom encoder", type_id);
let encoded_env_type = transcoder.encode_value(value)?;
let encoded_env_type = transcoder
.encode_value(value)
.context("Error encoding custom type")?;
output.write(&encoded_env_type);
Ok(true)
}
Expand Down
63 changes: 55 additions & 8 deletions src/cmd/extrinsics/transcode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,9 @@ mod tests {
use ink_lang as ink;

#[ink::contract]
pub mod flipper {
pub mod transcode {
#[ink(storage)]
pub struct Flipper {
pub struct Transcode {
value: bool,
}

Expand All @@ -363,36 +363,41 @@ mod tests {
from: AccountId,
}

impl Flipper {
/// Creates a new flipper smart contract initialized with the given value.
impl Transcode {
#[ink(constructor)]
pub fn new(init_value: bool) -> Self {
Self { value: init_value }
}

/// Creates a new flipper smart contract initialized to `false`.
#[ink(constructor)]
pub fn default() -> Self {
Self::new(Default::default())
}

/// Flips the current value of the Flipper's bool.
#[ink(message)]
pub fn flip(&mut self) {
self.value = !self.value;
}

/// Returns the current value of the Flipper's bool.
#[ink(message)]
pub fn get(&self) -> bool {
self.value
}

/// Dummy setter which receives the env type AccountId.
#[ink(message)]
pub fn set_account_id(&self, account_id: AccountId) {
let _ = account_id;
}

#[ink(message)]
pub fn set_account_ids_vec(&self, account_ids: Vec<AccountId>) {
let _ = account_ids;
}

#[ink(message)]
pub fn primitive_vec_args(&self, args: Vec<u32>) {
let _ = args;
}
}
}

Expand Down Expand Up @@ -442,6 +447,48 @@ mod tests {
Ok(())
}

#[test]
fn encode_account_ids_vec_args() -> Result<()> {
let metadata = generate_metadata();
let transcoder = ContractMessageTranscoder::new(&metadata);

let encoded = transcoder.encode(
"set_account_ids_vec",
&["[5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty]"],
)?;

// encoded args follow the 4 byte selector
let encoded_args = &encoded[4..];

let expected = vec![
sp_core::crypto::AccountId32::from_str(
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
)
.unwrap(),
sp_core::crypto::AccountId32::from_str(
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
)
.unwrap(),
];
assert_eq!(expected.encode(), encoded_args);
Ok(())
}

#[test]
fn encode_primitive_vec_args() -> Result<()> {
let metadata = generate_metadata();
let transcoder = ContractMessageTranscoder::new(&metadata);

let encoded = transcoder.encode("primitive_vec_args", &["[1, 2]"])?;

// encoded args follow the 4 byte selector
let encoded_args = &encoded[4..];

let expected = vec![1, 2];
assert_eq!(expected.encode(), encoded_args);
Ok(())
}

#[test]
fn decode_primitive_return() -> Result<()> {
let metadata = generate_metadata();
Expand Down
34 changes: 33 additions & 1 deletion src/cmd/extrinsics/transcode/transcoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,16 @@ mod tests {
super::scon::{
self,
Map,
Seq,
Tuple,
Value,
},
*,
};
use crate::cmd::extrinsics::transcode;
use crate::cmd::extrinsics::{
transcode,
transcode::scon::Bytes,
};
use scale::Encode;
use scale_info::{
MetaType,
Expand Down Expand Up @@ -605,6 +609,34 @@ mod tests {
)
}

#[test]
fn transcode_account_id_custom_ss58_encoding_seq() -> Result<()> {
transcode_roundtrip::<Vec<sp_runtime::AccountId32>>(
r#"[
5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,
5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty,
]"#,
Value::Seq(Seq::new(
vec![
Value::Tuple(
Tuple::new(
Some("AccountId32"),
vec![Value::Bytes(Bytes::from_hex_string("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").unwrap())]
)
),
Value::Tuple(
Tuple::new(
Some("AccountId32"),
vec![Value::Bytes(Bytes::from_hex_string("0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48").unwrap())]
)
)
]
.into_iter()
.collect(),
)),
)
}

#[test]
fn transcode_compact_primitives() -> Result<()> {
transcode_roundtrip::<scale::Compact<u8>>(r#"33"#, Value::UInt(33))?;
Expand Down

0 comments on commit 6c0d521

Please sign in to comment.