Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
decode cmd works for both event and message
save: +output tuned

+decoder for message data and specifier of type to DecodeCommand

removed redundant args to decode cmd
  • Loading branch information
agryaznov committed Mar 29, 2022
commit 1875e5d1632d6309059b088dcb958e255e57a16e
3 changes: 2 additions & 1 deletion src/cmd/extrinsics/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ impl CallCommand {
let (_, contract_metadata) = load_metadata(self.extrinsic_opts.manifest_path.as_ref())?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let call_data = transcoder.encode(&self.message, &self.args)?;
log::debug!("message data: {:?}", hex::encode(&call_data));

let signer = super::pair_signer(self.extrinsic_opts.signer()?);

async_std::task::block_on(async {
Expand Down Expand Up @@ -132,7 +134,6 @@ impl CallCommand {
.to_runtime_api::<RuntimeApi>();

log::debug!("calling contract {:?}", self.contract);
log::debug!("with data: {:?}", hex::encode(&data));
let tx_progress = api
.tx()
.contracts()
Expand Down
40 changes: 31 additions & 9 deletions src/cmd/extrinsics/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,49 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use super::load_metadata;
use crate::cmd::extrinsics::{ExtrinsicOpts, ContractMessageTranscoder};
use crate::cmd::extrinsics::ContractMessageTranscoder;
use crate::DEFAULT_KEY_COL_WIDTH;
use anyhow::Result;
use colored::Colorize as _;


#[derive(Debug, clap::Args)]
#[derive(Debug, Clone, clap::Args)]
#[clap(name = "decode", about = "Decode input_data for a contract")]
pub struct DecodeCommand {
#[clap(flatten)]
extrinsic_opts: ExtrinsicOpts,
/// Type of data
#[clap(arg_enum, short, long)]
r#type: DataType,
/// The data to decode
#[clap(long)]
data: String,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ArgEnum)]
enum DataType {
Event,
Message,
}

impl DecodeCommand {
pub fn run(&self) -> Result<()> {
let (_, contract_metadata) = load_metadata(self.extrinsic_opts.manifest_path.as_ref())?;
let (_, contract_metadata) = load_metadata(None)?;
let transcoder = ContractMessageTranscoder::new(&contract_metadata);
let decoded_data = transcoder.decode_contract_event(&mut &self.data.as_bytes()[..]);

log::debug!("DECODED DATA: {:?}", decoded_data);
Ok(())
let decoded_data = match self.r#type {
DataType::Event => {
transcoder.decode_contract_event(&mut &hex::decode(&self.data).unwrap()[..])
}
DataType::Message => {
transcoder.decode_contract_message(&mut &hex::decode(&self.data).unwrap()[..])
}
};

println!(
"{:>width$} {:?}",
"Decoded data:".bright_green().bold(),
decoded_data,
width = DEFAULT_KEY_COL_WIDTH
);

Ok(())
}
}
4 changes: 1 addition & 3 deletions src/cmd/extrinsics/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ pub fn display_events(
if <ContractEmitted as Event>::is_event(&event.pallet, &event.variant)
&& field.name() == Some(&"data".to_string())
{
// data is a byte vec so the first byte is the length.
log::debug!("EVENT_DATA: {:?}", hex::encode(&event_data));

log::debug!("event data: {:?}", hex::encode(&event_data));
let contract_event = transcoder.decode_contract_event(event_data)?;
maybe_println!(
verbosity,
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/extrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

mod call;
mod decode;
mod events;
mod instantiate;
mod runtime_api;
mod transcode;
mod upload;
mod decode;

#[cfg(test)]
#[cfg(feature = "integration-tests")]
Expand All @@ -39,10 +39,10 @@ use sp_core::{crypto::Pair, sr25519};
use subxt::{Config, DefaultConfig};

pub use call::CallCommand;
pub use decode::DecodeCommand;
pub use instantiate::InstantiateCommand;
pub use runtime_api::api::{DispatchError as RuntimeDispatchError, Event as RuntimeEvent};
pub use upload::UploadCommand;
pub use decode::DecodeCommand;

type Balance = u128;
type CodeHash = <DefaultConfig as Config>::Hash;
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/extrinsics/transcode/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ impl<'a> Decoder<'a> {
) -> Result<Value> {
let i2 = input.clone();
let discriminant = input.read_byte()?;
println!("type is {:?}", &variant_type.clone());
println!("input is {:?}", &i2);
println!("discriminant is {:?}", &discriminant);
println!("type is {:?}", &variant_type.clone());
println!("input is {:?}", &i2);
println!("discriminant is {:?}", &discriminant);
let variant = variant_type
.variants()
.get(discriminant as usize)
Expand Down
45 changes: 44 additions & 1 deletion src/cmd/extrinsics/transcode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ impl<'a> ContractMessageTranscoder<'a> {
// data is an encoded `Vec<u8>` so is prepended with its length `Compact<u32>`, which we
// ignore because the structure of the event data is known for decoding.
let _len = <Compact<u32>>::decode(data)?;

let variant_index = data.read_byte()?;
let event_spec = self
.metadata
Expand Down Expand Up @@ -203,6 +202,37 @@ impl<'a> ContractMessageTranscoder<'a> {
Ok(Value::Map(map))
}

pub fn decode_contract_message(&self, data: &mut &[u8]) -> Result<Value> {
let mut msg_selector = [0u8; 4];
data.read(&mut msg_selector)?;
let msg_spec = self
.metadata
.spec()
.messages()
.iter()
.filter(|x| msg_selector == x.selector().to_bytes())
.next()
.ok_or_else(|| {
anyhow::anyhow!(
"Message with selector {} not found in contract metadata",
hex::encode(&msg_selector)
)
})?;
log::debug!("decoding contract message '{}'", msg_spec.label());

let mut args = Vec::new();
for arg in msg_spec.args() {
let name = arg.label().to_string();
let value = self.transcoder.decode(arg.ty().ty().id(), data)?;
args.push((Value::String(name), value));
}

let name = msg_spec.label().to_string();
let map = Map::new(Some(&name), args.into_iter().collect());

Ok(Value::Map(map))
}

pub fn decode_return(&self, name: &str, data: &mut &[u8]) -> Result<Value> {
let msg_spec = self
.find_message_spec(name)
Expand Down Expand Up @@ -391,4 +421,17 @@ mod tests {

Ok(())
}

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

let encoded = ([0u32; 32], [1u32; 32]).encode();
// encode again as a Vec<u8> which has a len prefix.
let encoded_bytes = encoded.encode();
let _ = transcoder.decode_contract_message(&mut &encoded_bytes[..])?;

Ok(())
}
}
2 changes: 1 addition & 1 deletion src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ pub(crate) use self::{
};
mod extrinsics;

pub(crate) use self::extrinsics::{CallCommand, InstantiateCommand, UploadCommand, DecodeCommand};
pub(crate) use self::extrinsics::{CallCommand, DecodeCommand, InstantiateCommand, UploadCommand};
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ mod workspace;

use self::{
cmd::{
metadata::MetadataResult, BuildCommand, CallCommand, CheckCommand, InstantiateCommand,
TestCommand, UploadCommand, DecodeCommand
metadata::MetadataResult, BuildCommand, CallCommand, CheckCommand, DecodeCommand,
InstantiateCommand, TestCommand, UploadCommand,
},
util::DEFAULT_KEY_COL_WIDTH,
workspace::ManifestPath,
Expand Down