From d5f8b749ae096f03907125588138eefa4a732bca Mon Sep 17 00:00:00 2001 From: Kasey White Date: Sat, 3 Sep 2022 18:48:51 -0400 Subject: [PATCH] add txininfo plutus data to main --- Cargo.lock | 26 ++++++-- crates/cli/Cargo.toml | 4 ++ crates/cli/src/args.rs | 22 +++++- crates/cli/src/main.rs | 148 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 192 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3ec7045..d453dad5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,8 +9,12 @@ dependencies = [ "anyhow", "clap", "hex", + "pallas-addresses", + "pallas-codec", "pallas-primitives", "pallas-traverse", + "serde", + "serde_json", "uplc", ] @@ -577,15 +581,29 @@ checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" -version = "1.0.142" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 8d3e11a7..469ce34d 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -15,5 +15,9 @@ anyhow = "1.0.57" clap = { version = "3.1.14", features = ["derive"] } hex = "0.4.3" pallas-primitives = "0.13.2" +pallas-codec = "0.13.2" pallas-traverse = "0.13.2" +serde = { version = "1.0.144", features = ["derive"] } +serde_json = "1.0.85" uplc = { path = '../uplc', version = "0.0.12" } +pallas-addresses = "0.13.2" diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs index 15f0436f..00af0c52 100644 --- a/crates/cli/src/args.rs +++ b/crates/cli/src/args.rs @@ -1,6 +1,7 @@ -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf}; use clap::{Parser, Subcommand}; +use serde::{de, Deserialize}; /// Cardano smart contract toolchain #[derive(Parser)] @@ -23,9 +24,28 @@ pub enum TxCommand { input: PathBuf, #[clap(short, long)] cbor: bool, + resolved_inputs: PathBuf, }, } +#[derive(Deserialize)] +pub struct ResolvedInput { + pub input: Input, + pub ouput: Output, +} + +#[derive(Deserialize)] +pub struct Input { + pub tx_hash: String, + pub index: u64, +} + +#[derive(Deserialize)] +pub struct Output { + pub address: String, + pub value: (u64, HashMap>), +} + /// Commands for working with Untyped Plutus Core #[derive(Subcommand)] pub enum UplcCommand { diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index f53d53e5..ce65e8b5 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,22 +1,35 @@ -use std::{fmt::Write as _, fs}; +use std::{ + fmt::Write as _, + fs::{self, File}, + io::BufReader, collections::HashMap, thread::LocalKey, +}; +use pallas_addresses::Address; +use pallas_codec::{minicbor::bytes::ByteVec, utils::{MaybeIndefArray, KeyValuePairs}}; +use pallas_primitives::babbage::{BigInt, Constr}; use pallas_traverse::{Era, MultiEraTx}; use uplc::{ ast::{Constant, DeBruijn, FakeNamedDeBruijn, Name, NamedDeBruijn, Program, Term}, machine::cost_model::ExBudget, - parser, + parser, PlutusData, }; mod args; use args::{Args, TxCommand, UplcCommand}; +use crate::args::ResolvedInput; + fn main() -> anyhow::Result<()> { let args = Args::default(); match args { Args::Tx(tx_cmd) => match tx_cmd { - TxCommand::Simulate { input, cbor } => { + TxCommand::Simulate { + input, + cbor, + resolved_inputs, + } => { let tx_bytes = if cbor { fs::read(input)? } else { @@ -52,6 +65,135 @@ fn main() -> anyhow::Result<()> { program .apply_data(datum.clone()) .apply_data(redeemer.data.clone()); + + let file = File::open(&resolved_inputs)?; + let reader = BufReader::new(file); + let resolved_inputs: Vec = serde_json::from_reader(reader)?; + let tx_in_info: Vec = resolved_inputs + .iter() + .map(|resolved_input| { + let tx_out_ref = PlutusData::Constr(Constr { + tag: 0, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + PlutusData::BoundedBytes( + hex::decode(resolved_input.input.tx_hash.clone()) + .unwrap() + .into(), + ), + PlutusData::BigInt(BigInt::Int( + resolved_input.input.index.into(), + )), + ]), + }); + + let address = + Address::from_bech32(&resolved_input.ouput.address).unwrap(); + + let payment_tag = match address.typeid() % 2 { + 0 => 0, + 1 => 1, + _ => unreachable!(), + }; + let stake_tag = match address.typeid() { + 0 | 1 => Some(0), + 2 | 3 => Some(1), + _ => None, + }; + + let (payment_part, stake_part) = match address { + Address::Shelley(s) => { + (s.payment().to_vec(), s.delegation().to_vec()) + } + _ => unreachable!(), + }; + + let lovelace = resolved_input.ouput.value.0; + + let mut assets = resolved_input.ouput.value.1.clone(); + + assets.insert("".to_string(), vec![("".to_string(), lovelace)].into_iter().collect()); + + let tx_out = PlutusData::Constr(Constr { + tag: 0, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + // txOutAddress + PlutusData::Constr(Constr { + tag: 0, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + // addressCredential + PlutusData::Constr(Constr { + tag: payment_tag, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + PlutusData::BoundedBytes( + payment_part.into(), + ), + ]), + }), + // addressStakingCredential + PlutusData::Constr(Constr { + tag: if stake_tag.is_some() { 0 } else { 1 }, + any_constructor: None, + fields: MaybeIndefArray::Indef( + if stake_tag.is_some() { + vec![ + // StakingCredential + PlutusData::Constr(Constr { + tag: 0, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + // StakingHash + PlutusData::Constr(Constr { + tag: stake_tag.unwrap(), + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + PlutusData::BoundedBytes( + stake_part.into(), + ), + ]), + }), + ]), + }), + ] + + } else { + vec![] + }, + ), + }), + ]), + }), + + // txOutValue + PlutusData::Map(KeyValuePairs::Def( + assets.iter().map(|val| { + let currency_symbol = PlutusData::BoundedBytes(hex::decode(val.0).unwrap().into()); + let token_map = PlutusData::Map(KeyValuePairs::Def( + val.1.iter().map(|token| { + ( PlutusData::BoundedBytes(token.0.as_bytes().to_vec().into()), PlutusData::BigInt(BigInt::Int((*token.1).into()))) + }).collect() + + )); + (currency_symbol, token_map) + }).collect() + ) ), + + + ]), + }); + PlutusData::Constr(Constr{ + tag: 0, + any_constructor: None, + fields: MaybeIndefArray::Indef(vec![ + tx_out_ref, + tx_out + ]) + }) + }) + .collect(); } }