added plutusV1

This commit is contained in:
alessandrokonrad 2022-09-13 11:41:42 +02:00 committed by rvcas
parent d9b34973c7
commit 6e4ff1e282
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
3 changed files with 339 additions and 111 deletions

View File

@ -30,7 +30,7 @@ pub enum TxCommand {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ResolvedInput { pub struct ResolvedInputOld {
pub input: Input, pub input: Input,
pub output: Output, pub output: Output,
} }

View File

@ -16,7 +16,7 @@ mod utils;
use args::{Args, TxCommand, UplcCommand}; use args::{Args, TxCommand, UplcCommand};
use crate::args::ResolvedInput; use crate::args::ResolvedInputOld;
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let args = Args::default(); let args = Args::default();
@ -66,7 +66,8 @@ fn main() -> anyhow::Result<()> {
let file = File::open(&resolved_inputs)?; let file = File::open(&resolved_inputs)?;
let reader = BufReader::new(file); let reader = BufReader::new(file);
let resolved_inputs: Vec<ResolvedInput> = serde_json::from_reader(reader)?; let resolved_inputs: Vec<ResolvedInputOld> =
serde_json::from_reader(reader)?;
let tx_in_info = utils::get_tx_in_info_old(&resolved_inputs)?; let tx_in_info = utils::get_tx_in_info_old(&resolved_inputs)?;
} }

View File

@ -8,9 +8,9 @@ use pallas_codec::{
use pallas_crypto::hash::{Hash, Hasher}; use pallas_crypto::hash::{Hash, Hasher};
use pallas_primitives::{ use pallas_primitives::{
babbage::{ babbage::{
AddrKeyhash, AssetName, BigInt, Certificate, Constr, CostModel, DatumHash, DatumOption, AddrKeyhash, AssetName, BigInt, Certificate, Coin, Constr, CostModel, DatumHash,
ExUnits, Language, Mint, MintedTx, PlutusV1Script, PlutusV2Script, PolicyId, Redeemer, DatumOption, ExUnits, Language, Mint, MintedTx, PlutusV1Script, PlutusV2Script, PolicyId,
RedeemerTag, RewardAccount, Script, ScriptRef, StakeCredential, TransactionInput, Redeemer, RedeemerTag, RewardAccount, Script, ScriptRef, StakeCredential, TransactionInput,
TransactionOutput, Tx, Value, Withdrawals, TransactionOutput, Tx, Value, Withdrawals,
}, },
Fragment, ToHash, Fragment, ToHash,
@ -19,6 +19,7 @@ use pallas_traverse::{Era, MultiEraTx};
use std::{ use std::{
collections::HashMap, collections::HashMap,
convert::{TryFrom, TryInto}, convert::{TryFrom, TryInto},
ops::Deref,
str::FromStr, str::FromStr,
vec, vec,
}; };
@ -28,9 +29,9 @@ use uplc::{
PlutusData, PlutusData,
}; };
use crate::args::ResolvedInput; use crate::args::ResolvedInputOld;
pub fn get_tx_in_info_old(resolved_inputs: &[ResolvedInput]) -> anyhow::Result<Vec<PlutusData>> { pub fn get_tx_in_info_old(resolved_inputs: &[ResolvedInputOld]) -> anyhow::Result<Vec<PlutusData>> {
let mut tx_in_info = Vec::new(); let mut tx_in_info = Vec::new();
for resolved_input in resolved_inputs { for resolved_input in resolved_inputs {
@ -120,7 +121,7 @@ fn empty_constr(index: u64) -> PlutusData {
}) })
} }
/// Translate constructor index to cbor tag /// Translate constructor index to cbor tag.
fn constr_index(index: u64) -> u64 { fn constr_index(index: u64) -> u64 {
121 + index 121 + index
} }
@ -132,17 +133,6 @@ pub trait ToPlutusData {
impl ToPlutusData for Address { impl ToPlutusData for Address {
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
match self { match self {
Address::Byron(byron_address) => {
wrap_multiple_with_constr(
0,
vec![
//addressCredential
wrap_with_constr(0, byron_address.decode().unwrap().root.to_plutus_data()),
//addressStakeCredential
None::<StakeCredential>.to_plutus_data(),
],
)
}
Address::Shelley(shelley_address) => { Address::Shelley(shelley_address) => {
let payment_part = shelley_address.payment(); let payment_part = shelley_address.payment();
let stake_part = shelley_address.delegation(); let stake_part = shelley_address.delegation();
@ -177,7 +167,7 @@ impl ToPlutusData for Address {
wrap_multiple_with_constr(0, vec![payment_part_plutus_data, stake_part_plutus_data]) wrap_multiple_with_constr(0, vec![payment_part_plutus_data, stake_part_plutus_data])
} }
Address::Stake(_) => unreachable!(), _ => unreachable!(),
} }
} }
} }
@ -206,6 +196,12 @@ impl ToPlutusData for ByteVec {
} }
} }
impl<K: ToPlutusData, V: ToPlutusData> ToPlutusData for (K, V) {
fn to_plutus_data(&self) -> PlutusData {
wrap_multiple_with_constr(0, vec![self.0.to_plutus_data(), self.1.to_plutus_data()])
}
}
impl<A: ToPlutusData> ToPlutusData for MaybeIndefArray<A> { impl<A: ToPlutusData> ToPlutusData for MaybeIndefArray<A> {
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
PlutusData::Array(MaybeIndefArray::Indef( PlutusData::Array(MaybeIndefArray::Indef(
@ -329,31 +325,61 @@ impl ToPlutusData for ScriptRef {
} }
} }
impl ToPlutusData for TransactionOutput { impl ToPlutusData for TxOut {
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
match self { match self {
TransactionOutput::Legacy(legacy_output) => wrap_multiple_with_constr( TxOut::V1(output) => match output {
0, TransactionOutput::Legacy(legacy_output) => wrap_multiple_with_constr(
vec![ 0,
Address::from_bytes(&legacy_output.address) vec![
.unwrap() Address::from_bytes(&legacy_output.address)
.to_plutus_data(), .unwrap()
legacy_output.amount.to_plutus_data(), .to_plutus_data(),
None::<DatumOption>.to_plutus_data(), legacy_output.amount.to_plutus_data(),
None::<ScriptRef>.to_plutus_data(), legacy_output.datum_hash.to_plutus_data(),
], ],
), ),
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr( TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
0, 0,
vec![ vec![
Address::from_bytes(&post_alonzo_output.address) Address::from_bytes(&post_alonzo_output.address)
.unwrap() .unwrap()
.to_plutus_data(), .to_plutus_data(),
post_alonzo_output.value.to_plutus_data(), post_alonzo_output.value.to_plutus_data(),
post_alonzo_output.datum_option.to_plutus_data(), match post_alonzo_output.datum_option {
post_alonzo_output.script_ref.to_plutus_data(), Some(DatumOption::Hash(hash)) => Some(hash).to_plutus_data(),
], _ => None::<DatumOption>.to_plutus_data(),
), },
],
),
},
TxOut::V2(output) => match output {
TransactionOutput::Legacy(legacy_output) => wrap_multiple_with_constr(
0,
vec![
Address::from_bytes(&legacy_output.address)
.unwrap()
.to_plutus_data(),
legacy_output.amount.to_plutus_data(),
match legacy_output.datum_hash {
Some(hash) => wrap_with_constr(1, hash.to_plutus_data()),
_ => empty_constr(0),
},
None::<ScriptRef>.to_plutus_data(),
],
),
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
0,
vec![
Address::from_bytes(&post_alonzo_output.address)
.unwrap()
.to_plutus_data(),
post_alonzo_output.value.to_plutus_data(),
post_alonzo_output.datum_option.to_plutus_data(),
post_alonzo_output.script_ref.to_plutus_data(),
],
),
},
} }
} }
} }
@ -581,23 +607,40 @@ impl ToPlutusData for ScriptPurpose {
impl ToPlutusData for TxInfo { impl ToPlutusData for TxInfo {
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
wrap_multiple_with_constr( match self {
0, TxInfo::V1(tx_info) => wrap_multiple_with_constr(
vec![ 0,
self.inputs.to_plutus_data(), vec![
self.reference_inputs.to_plutus_data(), tx_info.inputs.to_plutus_data(),
self.outputs.to_plutus_data(), tx_info.outputs.to_plutus_data(),
self.fee.to_plutus_data(), tx_info.fee.to_plutus_data(),
self.mint.to_plutus_data(), tx_info.mint.to_plutus_data(),
self.dcert.to_plutus_data(), tx_info.dcert.to_plutus_data(),
self.wdrl.to_plutus_data(), tx_info.wdrl.to_plutus_data(),
self.valid_range.to_plutus_data(), tx_info.valid_range.to_plutus_data(),
self.signatories.to_plutus_data(), tx_info.signatories.to_plutus_data(),
self.redeemers.to_plutus_data(), tx_info.data.to_plutus_data(),
self.data.to_plutus_data(), wrap_with_constr(0, tx_info.id.to_plutus_data()),
wrap_with_constr(0, self.id.to_plutus_data()), ],
], ),
) TxInfo::V2(tx_info) => wrap_multiple_with_constr(
0,
vec![
tx_info.inputs.to_plutus_data(),
tx_info.reference_inputs.to_plutus_data(),
tx_info.outputs.to_plutus_data(),
tx_info.fee.to_plutus_data(),
tx_info.mint.to_plutus_data(),
tx_info.dcert.to_plutus_data(),
tx_info.wdrl.to_plutus_data(),
tx_info.valid_range.to_plutus_data(),
tx_info.signatories.to_plutus_data(),
tx_info.redeemers.to_plutus_data(),
tx_info.data.to_plutus_data(),
wrap_with_constr(0, tx_info.id.to_plutus_data()),
],
),
}
} }
} }
@ -619,12 +662,21 @@ impl ToPlutusData for bool {
} }
} }
// Plutus V2 only for now #[derive(Debug, PartialEq, Clone)]
pub struct ResolvedInput {
input: TransactionInput,
output: TransactionOutput,
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct TxInInfo { pub struct TxInInfo {
out_ref: TransactionInput, out_ref: TransactionInput,
resolved: TransactionOutput, resolved: TxOut,
}
#[derive(Debug, PartialEq, Clone)]
pub enum TxOut {
V1(TransactionOutput),
V2(TransactionOutput),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -636,10 +688,24 @@ pub enum ScriptPurpose {
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct TxInfo { pub struct TxInfoV1 {
inputs: MaybeIndefArray<TxInInfo>,
outputs: MaybeIndefArray<TxOut>,
fee: Value,
mint: Mint,
dcert: MaybeIndefArray<Certificate>,
wdrl: MaybeIndefArray<(RewardAccount, Coin)>,
valid_range: TimeRange,
signatories: MaybeIndefArray<AddrKeyhash>,
data: MaybeIndefArray<(DatumHash, PlutusData)>,
id: Hash<32>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct TxInfoV2 {
inputs: MaybeIndefArray<TxInInfo>, inputs: MaybeIndefArray<TxInInfo>,
reference_inputs: MaybeIndefArray<TxInInfo>, reference_inputs: MaybeIndefArray<TxInInfo>,
outputs: MaybeIndefArray<TransactionOutput>, outputs: MaybeIndefArray<TxOut>,
fee: Value, fee: Value,
mint: Mint, mint: Mint,
dcert: MaybeIndefArray<Certificate>, dcert: MaybeIndefArray<Certificate>,
@ -651,6 +717,12 @@ pub struct TxInfo {
id: Hash<32>, id: Hash<32>,
} }
#[derive(Debug, PartialEq, Clone)]
pub enum TxInfo {
V1(TxInfoV1),
V2(TxInfoV2),
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct ScriptContext { pub struct ScriptContext {
tx_info: TxInfo, tx_info: TxInfo,
@ -689,8 +761,8 @@ fn slot_range_to_posix_time_range(slot_range: TimeRange, sc: &SlotConfig) -> Tim
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
enum ScriptVersion { enum ScriptVersion {
PlutusV1(PlutusV1Script), V1(PlutusV1Script),
PlutusV2(PlutusV2Script), V2(PlutusV2Script),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -704,15 +776,34 @@ struct DataLookupTable {
scripts: HashMap<ScriptHash, ScriptVersion>, scripts: HashMap<ScriptHash, ScriptVersion>,
} }
fn get_tx_in_info( fn get_tx_in_info_v1(
inputs: &MaybeIndefArray<TransactionInput>, inputs: &MaybeIndefArray<TransactionInput>,
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
) -> anyhow::Result<MaybeIndefArray<TxInInfo>> { ) -> anyhow::Result<MaybeIndefArray<TxInInfo>> {
Ok(MaybeIndefArray::Indef( Ok(MaybeIndefArray::Indef(
utxos utxos
.iter() .iter()
.filter(|utxo| inputs.contains(&utxo.out_ref)) .filter(|utxo| inputs.contains(&utxo.input))
.map(|utxo| utxo.clone()) .map(|utxo| TxInInfo {
out_ref: utxo.input.clone(),
resolved: TxOut::V1(utxo.output.clone()),
})
.collect::<Vec<TxInInfo>>(),
))
}
fn get_tx_in_info_v2(
inputs: &MaybeIndefArray<TransactionInput>,
utxos: &MaybeIndefArray<ResolvedInput>,
) -> anyhow::Result<MaybeIndefArray<TxInInfo>> {
Ok(MaybeIndefArray::Indef(
utxos
.iter()
.filter(|utxo| inputs.contains(&utxo.input))
.map(|utxo| TxInInfo {
out_ref: utxo.input.clone(),
resolved: TxOut::V2(utxo.output.clone()),
})
.collect::<Vec<TxInInfo>>(), .collect::<Vec<TxInInfo>>(),
)) ))
} }
@ -770,14 +861,14 @@ fn get_script_purpose(
let addresss = Address::from_bytes(&reward_account)?; let addresss = Address::from_bytes(&reward_account)?;
let credential = match addresss { let credential = match addresss {
Address::Stake(stake_address) => match stake_address.payload() { Address::Stake(stake_address) => match stake_address.payload() {
StakePayload::Stake(stake_keyhash) => {
StakeCredential::AddrKeyhash(stake_keyhash.clone())
}
StakePayload::Script(script_hash) => { StakePayload::Script(script_hash) => {
StakeCredential::Scripthash(script_hash.clone()) StakeCredential::Scripthash(script_hash.clone())
} }
StakePayload::Stake(_) => {
unreachable!();
}
}, },
_ => panic!(), _ => unreachable!(),
}; };
Ok(ScriptPurpose::Rewarding(credential)) Ok(ScriptPurpose::Rewarding(credential))
} }
@ -789,22 +880,94 @@ fn get_script_purpose(
} }
} }
fn get_tx_info( fn get_tx_info_v1(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
slot_config: &SlotConfig, slot_config: &SlotConfig,
) -> anyhow::Result<TxInfo> { ) -> anyhow::Result<TxInfo> {
// Check if outputs do not contain ref scripts or inline datums or byron addresses in outputs
let body = tx.transaction_body.clone(); let body = tx.transaction_body.clone();
let inputs = get_tx_in_info(&body.inputs, &utxos)?; let inputs = get_tx_in_info_v1(&body.inputs, &utxos)?;
let reference_inputs = get_tx_in_info( let outputs = MaybeIndefArray::Indef(
body.outputs
.iter()
.map(|output| TxOut::V1(output.clone()))
.collect(),
);
let fee = Value::Coin(AnyUInt::U64(body.fee));
let mint = body.mint.clone().unwrap_or(KeyValuePairs::Indef(vec![]));
let dcert = body
.certificates
.clone()
.unwrap_or(MaybeIndefArray::Indef(vec![]));
let wdrl = MaybeIndefArray::Indef(
body.withdrawals
.clone()
.unwrap_or(KeyValuePairs::Indef(vec![]))
.deref()
.clone(),
);
let valid_range = slot_range_to_posix_time_range(
TimeRange {
lower_bound: body.validity_interval_start,
upper_bound: body.ttl,
},
&slot_config,
);
let signatories = body
.required_signers
.clone()
.unwrap_or(MaybeIndefArray::Indef(vec![]));
let data = MaybeIndefArray::Indef(
tx.transaction_witness_set
.plutus_data
.as_ref()
.unwrap_or(&MaybeIndefArray::Indef(vec![]))
.iter()
.map(|d| (d.to_hash(), d.clone()))
.collect(),
);
let id = tx.transaction_body.to_hash();
Ok(TxInfo::V1(TxInfoV1 {
inputs,
outputs,
fee,
mint,
dcert,
wdrl,
valid_range,
signatories,
data,
id,
}))
}
fn get_tx_info_v2(
tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>,
slot_config: &SlotConfig,
) -> anyhow::Result<TxInfo> {
//TODO: Check if no byron addresses in outputs
let body = tx.transaction_body.clone();
let inputs = get_tx_in_info_v2(&body.inputs, &utxos)?;
let reference_inputs = get_tx_in_info_v2(
&body &body
.reference_inputs .reference_inputs
.clone() .clone()
.unwrap_or(MaybeIndefArray::Indef(vec![])), .unwrap_or(MaybeIndefArray::Indef(vec![])),
&utxos, &utxos,
)?; )?;
let outputs = body.outputs.clone(); let outputs = MaybeIndefArray::Indef(
body.outputs
.iter()
.map(|output| TxOut::V2(output.clone()))
.collect(),
);
let fee = Value::Coin(AnyUInt::U64(body.fee)); let fee = Value::Coin(AnyUInt::U64(body.fee));
let mint = body.mint.clone().unwrap_or(KeyValuePairs::Indef(vec![])); let mint = body.mint.clone().unwrap_or(KeyValuePairs::Indef(vec![]));
let dcert = body let dcert = body
@ -858,7 +1021,7 @@ fn get_tx_info(
); );
let id = tx.transaction_body.to_hash(); let id = tx.transaction_body.to_hash();
Ok(TxInfo { Ok(TxInfo::V2(TxInfoV2 {
inputs, inputs,
reference_inputs, reference_inputs,
outputs, outputs,
@ -871,11 +1034,11 @@ fn get_tx_info(
redeemers, redeemers,
data, data,
id, id,
}) }))
} }
fn get_execution_purpose( fn get_execution_purpose(
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
script_purpose: &ScriptPurpose, script_purpose: &ScriptPurpose,
lookup_table: &DataLookupTable, lookup_table: &DataLookupTable,
) -> ExecutionPurpose { ) -> ExecutionPurpose {
@ -888,8 +1051,8 @@ fn get_execution_purpose(
ExecutionPurpose::NoDatum(script.clone()) ExecutionPurpose::NoDatum(script.clone())
} }
ScriptPurpose::Spending(out_ref) => { ScriptPurpose::Spending(out_ref) => {
let utxo = utxos.iter().find(|utxo| utxo.out_ref == *out_ref).unwrap(); let utxo = utxos.iter().find(|utxo| utxo.input == *out_ref).unwrap();
match &utxo.resolved { match &utxo.output {
TransactionOutput::Legacy(output) => { TransactionOutput::Legacy(output) => {
let address = Address::from_bytes(&output.address).unwrap(); let address = Address::from_bytes(&output.address).unwrap();
match address { match address {
@ -902,9 +1065,6 @@ fn get_execution_purpose(
let datum = let datum =
lookup_table.datum.get(&output.datum_hash.unwrap()).unwrap(); lookup_table.datum.get(&output.datum_hash.unwrap()).unwrap();
let a = hex::encode(datum.encode_fragment().unwrap());
println!("{:?}", a);
ExecutionPurpose::WithDatum(script.clone(), datum.clone()) ExecutionPurpose::WithDatum(script.clone(), datum.clone())
} }
_ => unreachable!(), _ => unreachable!(),
@ -967,7 +1127,7 @@ fn get_execution_purpose(
fn get_script_and_datum_lookup_table( fn get_script_and_datum_lookup_table(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
) -> DataLookupTable { ) -> DataLookupTable {
let mut datum = HashMap::new(); let mut datum = HashMap::new();
let mut scripts = HashMap::new(); let mut scripts = HashMap::new();
@ -1003,7 +1163,7 @@ fn get_script_and_datum_lookup_table(
prefixed_script.extend(script.0.iter()); prefixed_script.extend(script.0.iter());
let hash = Hasher::<224>::hash(&prefixed_script); let hash = Hasher::<224>::hash(&prefixed_script);
scripts.insert(hash, ScriptVersion::PlutusV1(script.clone())); scripts.insert(hash, ScriptVersion::V1(script.clone()));
} }
for script in scripts_v2_witnesses.iter() { for script in scripts_v2_witnesses.iter() {
@ -1013,13 +1173,13 @@ fn get_script_and_datum_lookup_table(
prefixed_script.extend(script.0.iter()); prefixed_script.extend(script.0.iter());
let hash = Hasher::<224>::hash(&prefixed_script); let hash = Hasher::<224>::hash(&prefixed_script);
scripts.insert(hash, ScriptVersion::PlutusV2(script.clone())); scripts.insert(hash, ScriptVersion::V2(script.clone()));
} }
// discovery in utxos (script ref) // discovery in utxos (script ref)
for utxo in utxos.iter() { for utxo in utxos.iter() {
match &utxo.resolved { match &utxo.output {
TransactionOutput::Legacy(_) => {} TransactionOutput::Legacy(_) => {}
TransactionOutput::PostAlonzo(output) => match &output.script_ref { TransactionOutput::PostAlonzo(output) => match &output.script_ref {
Some(script) => match &script.0 { Some(script) => match &script.0 {
@ -1029,7 +1189,7 @@ fn get_script_and_datum_lookup_table(
prefixed_script.extend(v1.0.iter()); prefixed_script.extend(v1.0.iter());
let hash = Hasher::<224>::hash(&prefixed_script); let hash = Hasher::<224>::hash(&prefixed_script);
scripts.insert(hash, ScriptVersion::PlutusV1(v1.clone())); scripts.insert(hash, ScriptVersion::V1(v1.clone()));
} }
Script::PlutusV2Script(v2) => { Script::PlutusV2Script(v2) => {
// scripts.insert(v2.to_hash(), ScriptVersion::PlutusV2(v2.clone())); // TODO: fix hashing bug in pallas // scripts.insert(v2.to_hash(), ScriptVersion::PlutusV2(v2.clone())); // TODO: fix hashing bug in pallas
@ -1038,7 +1198,7 @@ fn get_script_and_datum_lookup_table(
prefixed_script.extend(v2.0.iter()); prefixed_script.extend(v2.0.iter());
let hash = Hasher::<224>::hash(&prefixed_script); let hash = Hasher::<224>::hash(&prefixed_script);
scripts.insert(hash, ScriptVersion::PlutusV2(v2.clone())); scripts.insert(hash, ScriptVersion::V2(v2.clone()));
} }
_ => {} _ => {}
}, },
@ -1052,7 +1212,7 @@ fn get_script_and_datum_lookup_table(
fn eval_redeemer( fn eval_redeemer(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
slot_config: &SlotConfig, slot_config: &SlotConfig,
redeemer: &Redeemer, redeemer: &Redeemer,
lookup_table: &DataLookupTable, lookup_table: &DataLookupTable,
@ -1069,9 +1229,40 @@ fn eval_redeemer(
match execution_purpose { match execution_purpose {
ExecutionPurpose::WithDatum(script_version, datum) => match script_version { ExecutionPurpose::WithDatum(script_version, datum) => match script_version {
ScriptVersion::PlutusV1(script) => todo!(), ScriptVersion::V1(script) => {
ScriptVersion::PlutusV2(script) => { let tx_info = get_tx_info_v1(tx, utxos, slot_config)?;
let tx_info = get_tx_info(tx, utxos, slot_config)?; let script_context = ScriptContext { tx_info, purpose };
let program: Program<NamedDeBruijn> = {
let mut buffer = Vec::new();
let prog = Program::<FakeNamedDeBruijn>::from_cbor(&script.0, &mut buffer)?;
prog.into()
};
let result = program
.apply_data(datum.clone())
.apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data())
.eval();
result.0.unwrap();
let new_redeemer = Redeemer {
tag: redeemer.tag.clone(),
index: redeemer.index,
data: redeemer.data.clone(),
ex_units: ExUnits {
mem: (ExBudget::default().mem - result.1.mem) as u32,
steps: (ExBudget::default().cpu - result.1.cpu) as u64,
},
};
Ok(new_redeemer)
}
ScriptVersion::V2(script) => {
let tx_info = get_tx_info_v2(tx, utxos, slot_config)?;
let script_context = ScriptContext { tx_info, purpose }; let script_context = ScriptContext { tx_info, purpose };
let program: Program<NamedDeBruijn> = { let program: Program<NamedDeBruijn> = {
@ -1104,9 +1295,39 @@ fn eval_redeemer(
} }
}, },
ExecutionPurpose::NoDatum(script_version) => match script_version { ExecutionPurpose::NoDatum(script_version) => match script_version {
ScriptVersion::PlutusV1(script) => todo!(), ScriptVersion::V1(script) => {
ScriptVersion::PlutusV2(script) => { let tx_info = get_tx_info_v1(tx, utxos, slot_config)?;
let tx_info = get_tx_info(tx, utxos, slot_config)?; let script_context = ScriptContext { tx_info, purpose };
let program: Program<NamedDeBruijn> = {
let mut buffer = Vec::new();
let prog = Program::<FakeNamedDeBruijn>::from_cbor(&script.0, &mut buffer)?;
prog.into()
};
let result = program
.apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data())
.eval();
result.0.unwrap();
let new_redeemer = Redeemer {
tag: redeemer.tag.clone(),
index: redeemer.index,
data: redeemer.data.clone(),
ex_units: ExUnits {
mem: (ExBudget::default().mem - result.1.mem) as u32,
steps: (ExBudget::default().cpu - result.1.cpu) as u64,
},
};
Ok(new_redeemer)
}
ScriptVersion::V2(script) => {
let tx_info = get_tx_info_v2(tx, utxos, slot_config)?;
let script_context = ScriptContext { tx_info, purpose }; let script_context = ScriptContext { tx_info, purpose };
let program: Program<NamedDeBruijn> = { let program: Program<NamedDeBruijn> = {
@ -1154,7 +1375,7 @@ fn eval_redeemer(
fn eval_tx( fn eval_tx(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<TxInInfo>, utxos: &MaybeIndefArray<ResolvedInput>,
//TODO: costMdls //TODO: costMdls
slot_config: &SlotConfig, slot_config: &SlotConfig,
) -> anyhow::Result<MaybeIndefArray<Redeemer>> { ) -> anyhow::Result<MaybeIndefArray<Redeemer>> {
@ -1190,11 +1411,14 @@ mod tests {
use pallas_traverse::{Era, MultiEraTx}; use pallas_traverse::{Era, MultiEraTx};
use uplc::PlutusData; use uplc::PlutusData;
use super::{eval_tx, SlotConfig, TxInInfo}; use super::{eval_tx, ResolvedInput, SlotConfig, TxInInfo};
#[test] #[test]
fn test_eval() { fn test_eval() {
/* /*
PlutusV2
{-# INLINEABLE mintTestValidator #-} {-# INLINEABLE mintTestValidator #-}
mintTestValidator :: () -> Api.ScriptContext -> Bool mintTestValidator :: () -> Api.ScriptContext -> Bool
mintTestValidator _ ctx = Api.txInfoFee txInfo == Api.txInfoFee txInfo && (case Api.txInfoSignatories txInfo of [] -> True) mintTestValidator _ ctx = Api.txInfoFee txInfo == Api.txInfoFee txInfo && (case Api.txInfoSignatories txInfo of [] -> True)
@ -1211,13 +1435,13 @@ mod tests {
let inputs = MaybeIndefArray::<TransactionInput>::decode_fragment(&raw_inputs).unwrap(); let inputs = MaybeIndefArray::<TransactionInput>::decode_fragment(&raw_inputs).unwrap();
let outputs = MaybeIndefArray::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap(); let outputs = MaybeIndefArray::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap();
let utxos: MaybeIndefArray<TxInInfo> = MaybeIndefArray::Indef( let utxos: MaybeIndefArray<ResolvedInput> = MaybeIndefArray::Indef(
inputs inputs
.iter() .iter()
.zip(outputs.iter()) .zip(outputs.iter())
.map(|(input, output)| TxInInfo { .map(|(input, output)| ResolvedInput {
out_ref: input.clone(), input: input.clone(),
resolved: output.clone(), output: output.clone(),
}) })
.collect(), .collect(),
); );
@ -1243,6 +1467,9 @@ mod tests {
#[test] #[test]
fn test_eval_1() { fn test_eval_1() {
/* /*
PlutusV2
{-# INLINEABLE mintTestValidator #-} {-# INLINEABLE mintTestValidator #-}
mintTestValidator :: () -> Api.ScriptContext -> Bool mintTestValidator :: () -> Api.ScriptContext -> Bool
mintTestValidator _ ctx = Api.txInfoFee txInfo == Api.txInfoFee txInfo mintTestValidator _ ctx = Api.txInfoFee txInfo == Api.txInfoFee txInfo
@ -1259,13 +1486,13 @@ mod tests {
let inputs = MaybeIndefArray::<TransactionInput>::decode_fragment(&raw_inputs).unwrap(); let inputs = MaybeIndefArray::<TransactionInput>::decode_fragment(&raw_inputs).unwrap();
let outputs = MaybeIndefArray::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap(); let outputs = MaybeIndefArray::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap();
let utxos: MaybeIndefArray<TxInInfo> = MaybeIndefArray::Indef( let utxos: MaybeIndefArray<ResolvedInput> = MaybeIndefArray::Indef(
inputs inputs
.iter() .iter()
.zip(outputs.iter()) .zip(outputs.iter())
.map(|(input, output)| TxInInfo { .map(|(input, output)| ResolvedInput {
out_ref: input.clone(), input: input.clone(),
resolved: output.clone(), output: output.clone(),
}) })
.collect(), .collect(),
); );