fix: it compiles again

This commit is contained in:
rvcas 2022-09-15 11:27:33 -04:00
parent 348ed3b719
commit 26deb6df10
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
2 changed files with 129 additions and 282 deletions

View File

@ -36,46 +36,10 @@ fn main() -> anyhow::Result<()> {
hex::decode(cbor_hex.trim())? hex::decode(cbor_hex.trim())?
}; };
let tx = MultiEraTx::decode(Era::Alonzo, &tx_bytes) let tx = MultiEraTx::decode(Era::Babbage, &tx_bytes)
.or_else(|_| MultiEraTx::decode(Era::Byron, &tx_bytes))?; .or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))?;
println!("Simulating: {}", tx.hash()); println!("Simulating: {}", tx.hash());
let witnesses = tx.witnesses();
if let Some(((datums, redeemers), scripts)) = witnesses
.plutus_data()
.zip(witnesses.redeemer())
.zip(witnesses.plutus_v1_script())
{
for ((datum, redeemer), script) in
datums.iter().zip(redeemers.iter()).zip(scripts.iter())
{
let program: Program<NamedDeBruijn> = {
let mut buffer = Vec::new();
let prog =
Program::<FakeNamedDeBruijn>::from_cbor(&script.0, &mut buffer)?;
prog.into()
};
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<ResolvedInputOld> =
serde_json::from_reader(reader)?;
let tx_in_info = utils::get_tx_in_info_old(&resolved_inputs)?;
}
}
println!("\nPlutus V2 Script:");
println!("{:#?}", tx.witnesses().plutus_v2_script());
} }
}, },
Args::Uplc(uplc_cmd) => match uplc_cmd { Args::Uplc(uplc_cmd) => match uplc_cmd {

View File

@ -1,102 +1,21 @@
use pallas_addresses::{ use pallas_addresses::{
Address, ScriptHash, ShelleyDelegationPart, ShelleyPaymentPart, StakePayload, Address, ScriptHash, ShelleyDelegationPart, ShelleyPaymentPart, StakePayload,
}; };
use pallas_codec::{ use pallas_codec::utils::{AnyUInt, Bytes, Int, KeyValuePairs, MaybeIndefArray};
minicbor::{bytes::ByteVec}, use pallas_crypto::hash::Hash;
utils::{AnyUInt, KeyValuePairs, MaybeIndefArray, Bytes, Int}, use pallas_primitives::babbage::{
}; AddrKeyhash, AssetName, BigInt, Certificate, Coin, Constr, DatumHash, DatumOption, ExUnits,
use pallas_crypto::hash::{Hash, Hasher}; Mint, MintedTx, PlutusV1Script, PlutusV2Script, PolicyId, Redeemer, RedeemerTag, RewardAccount,
use pallas_primitives::{ Script, ScriptRef, StakeCredential, TransactionInput, TransactionOutput, Value, Withdrawals,
babbage::{
AddrKeyhash, AssetName, BigInt, Certificate, Coin, Constr, CostModel, DatumHash,
DatumOption, ExUnits, Language, Mint, MintedTx, PlutusV1Script, PlutusV2Script, PolicyId,
Redeemer, RedeemerTag, RewardAccount, Script, ScriptRef, StakeCredential, TransactionInput,
TransactionOutput, Tx, Value, Withdrawals,
},
Fragment,
};
use pallas_traverse::{Era, MultiEraTx, OriginalHash, ComputeHash};
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
ops::Deref,
str::FromStr,
vec,
}; };
use pallas_traverse::{ComputeHash, OriginalHash};
use std::{collections::HashMap, convert::TryInto, ops::Deref, vec};
use uplc::{ use uplc::{
ast::{FakeNamedDeBruijn, NamedDeBruijn, Program}, ast::{FakeNamedDeBruijn, NamedDeBruijn, Program},
machine::cost_model::ExBudget, machine::cost_model::ExBudget,
PlutusData, PlutusData,
}; };
use crate::args::ResolvedInputOld;
pub fn get_tx_in_info_old(resolved_inputs: &[ResolvedInputOld]) -> anyhow::Result<Vec<PlutusData>> {
let mut tx_in_info = Vec::new();
for resolved_input in resolved_inputs {
let tx_out_ref = TransactionInput {
transaction_id: Hash::from_str(resolved_input.input.tx_hash.as_str())?,
index: resolved_input.input.index,
}
.to_plutus_data();
let address = Address::from_bech32(&resolved_input.output.address)?;
let lovelace = resolved_input.output.value.0;
let mut assets = resolved_input.output.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: vec![
// txOutAddress
address.to_plutus_data(),
// 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 as i64).into())),
)
})
.collect(),
));
(currency_symbol, token_map)
})
.collect(),
)),
],
});
tx_in_info.push(PlutusData::Constr(Constr {
tag: 0,
any_constructor: None,
fields: vec![tx_out_ref, tx_out],
}));
}
Ok(tx_in_info)
}
// ---------------
fn wrap_with_constr(index: u64, data: PlutusData) -> PlutusData { fn wrap_with_constr(index: u64, data: PlutusData) -> PlutusData {
PlutusData::Constr(Constr { PlutusData::Constr(Constr {
tag: constr_index(index), tag: constr_index(index),
@ -148,10 +67,10 @@ impl ToPlutusData for Address {
let stake_part_plutus_data = match stake_part { let stake_part_plutus_data = match stake_part {
ShelleyDelegationPart::Key(stake_keyhash) => { ShelleyDelegationPart::Key(stake_keyhash) => {
Some(StakeCredential::AddrKeyhash(stake_keyhash.clone())).to_plutus_data() Some(StakeCredential::AddrKeyhash(*stake_keyhash)).to_plutus_data()
} }
ShelleyDelegationPart::Script(script_hash) => { ShelleyDelegationPart::Script(script_hash) => {
Some(StakeCredential::Scripthash(script_hash.clone())).to_plutus_data() Some(StakeCredential::Scripthash(*script_hash)).to_plutus_data()
} }
ShelleyDelegationPart::Pointer(pointer) => Some(wrap_multiple_with_constr( ShelleyDelegationPart::Pointer(pointer) => Some(wrap_multiple_with_constr(
1, 1,
@ -202,15 +121,20 @@ impl<K: ToPlutusData, V: ToPlutusData> ToPlutusData for (K, V) {
} }
} }
impl<A> ToPlutusData for Vec<A> where A: ToPlutusData { impl<A> ToPlutusData for Vec<A>
where
A: ToPlutusData,
{
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
PlutusData::Array( PlutusData::Array(self.iter().map(|p| p.to_plutus_data()).collect())
self.iter().map(|p| p.to_plutus_data()).collect(),
)
} }
} }
impl<K, V> ToPlutusData for KeyValuePairs<K, V> where K: ToPlutusData + Clone, V: ToPlutusData + Clone { impl<K, V> ToPlutusData for KeyValuePairs<K, V>
where
K: ToPlutusData + Clone,
V: ToPlutusData + Clone,
{
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
let mut data_vec: Vec<(PlutusData, PlutusData)> = vec![]; let mut data_vec: Vec<(PlutusData, PlutusData)> = vec![];
for (key, value) in self.iter() { for (key, value) in self.iter() {
@ -257,7 +181,7 @@ impl ToPlutusData for AnyUInt {
impl ToPlutusData for Int { impl ToPlutusData for Int {
fn to_plutus_data(&self) -> PlutusData { fn to_plutus_data(&self) -> PlutusData {
PlutusData::BigInt(BigInt::Int(self.clone())) PlutusData::BigInt(BigInt::Int(*self))
} }
} }
@ -679,7 +603,7 @@ pub enum TxOut {
V2(TransactionOutput), V2(TransactionOutput),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum ScriptPurpose { pub enum ScriptPurpose {
Minting(PolicyId), Minting(PolicyId),
Spending(TransactionInput), Spending(TransactionInput),
@ -748,14 +672,12 @@ fn slot_to_begin_posix_time(slot: u64, sc: &SlotConfig) -> u64 {
fn slot_range_to_posix_time_range(slot_range: TimeRange, sc: &SlotConfig) -> TimeRange { fn slot_range_to_posix_time_range(slot_range: TimeRange, sc: &SlotConfig) -> TimeRange {
TimeRange { TimeRange {
lower_bound: match slot_range.lower_bound { lower_bound: slot_range
Some(lower_bound) => Some(slot_to_begin_posix_time(lower_bound, sc)), .lower_bound
None => None, .map(|lower_bound| slot_to_begin_posix_time(lower_bound, sc)),
}, upper_bound: slot_range
upper_bound: match slot_range.upper_bound { .upper_bound
Some(upper_bound) => Some(slot_to_begin_posix_time(upper_bound, sc)), .map(|upper_bound| slot_to_begin_posix_time(upper_bound, sc)),
None => None,
},
} }
} }
@ -771,12 +693,12 @@ enum ExecutionPurpose {
NoDatum(ScriptVersion), // Minting, Wdrl, DCert NoDatum(ScriptVersion), // Minting, Wdrl, DCert
} }
struct DataLookupTable { pub struct DataLookupTable {
datum: HashMap<DatumHash, PlutusData>, datum: HashMap<DatumHash, PlutusData>,
scripts: HashMap<ScriptHash, ScriptVersion>, scripts: HashMap<ScriptHash, ScriptVersion>,
} }
fn get_tx_in_info_v1( pub fn get_tx_in_info_v1(
inputs: &[TransactionInput], inputs: &[TransactionInput],
utxos: &[ResolvedInput], utxos: &[ResolvedInput],
) -> anyhow::Result<Vec<TxInInfo>> { ) -> anyhow::Result<Vec<TxInInfo>> {
@ -804,12 +726,10 @@ fn get_tx_in_info_v1(
match &utxo.output { match &utxo.output {
TransactionOutput::Legacy(_) => {} TransactionOutput::Legacy(_) => {}
TransactionOutput::PostAlonzo(output) => { TransactionOutput::PostAlonzo(output) => {
match output.datum_option { if let Some(DatumOption::Data(_)) = output.datum_option {
Some(DatumOption::Data(_)) => { unreachable!("Inline datum not allowed in PlutusV1.")
unreachable!("Inline datum not allowed in PlutusV1.") }
}
_ => {}
};
if output.script_ref.is_some() { if output.script_ref.is_some() {
unreachable!("Reference scripts not allowed in PlutusV1.") unreachable!("Reference scripts not allowed in PlutusV1.")
} }
@ -876,20 +796,17 @@ fn get_script_purpose(
.as_ref() .as_ref()
.unwrap_or(&KeyValuePairs::Indef(vec![])) .unwrap_or(&KeyValuePairs::Indef(vec![]))
.iter() .iter()
.map(|(policy_id, _)| policy_id.clone()) .map(|(policy_id, _)| *policy_id)
.collect::<Vec<PolicyId>>(); .collect::<Vec<PolicyId>>();
policy_ids.sort(); policy_ids.sort();
match policy_ids.get(index as usize) { match policy_ids.get(index as usize) {
Some(policy_id) => Ok(ScriptPurpose::Minting(policy_id.clone())), Some(policy_id) => Ok(ScriptPurpose::Minting(*policy_id)),
None => unreachable!("Script purpose not found for redeemer."), None => unreachable!("Script purpose not found for redeemer."),
} }
} }
RedeemerTag::Spend => { RedeemerTag::Spend => {
// sort lexical by tx_hash and index // sort lexical by tx_hash and index
let mut inputs = inputs let mut inputs = inputs.to_vec();
.iter()
.map(|input| input.clone())
.collect::<Vec<TransactionInput>>();
// is this correct? Does this sort lexical from low to high? maybe get Ordering into pallas for TransactionInput? // is this correct? Does this sort lexical from low to high? maybe get Ordering into pallas for TransactionInput?
inputs.sort_by( inputs.sort_by(
|i_a, i_b| match i_a.transaction_id.cmp(&i_b.transaction_id) { |i_a, i_b| match i_a.transaction_id.cmp(&i_b.transaction_id) {
@ -920,7 +837,7 @@ fn get_script_purpose(
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::Script(script_hash) => { StakePayload::Script(script_hash) => {
StakeCredential::Scripthash(script_hash.clone()) StakeCredential::Scripthash(*script_hash)
} }
StakePayload::Stake(_) => { StakePayload::Stake(_) => {
unreachable!( unreachable!(
@ -950,7 +867,7 @@ fn get_script_purpose(
fn get_tx_info_v1( fn get_tx_info_v1(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>, utxos: &[ResolvedInput],
slot_config: &SlotConfig, slot_config: &SlotConfig,
) -> anyhow::Result<TxInfo> { ) -> anyhow::Result<TxInfo> {
let body = tx.transaction_body.clone(); let body = tx.transaction_body.clone();
@ -961,45 +878,39 @@ fn get_tx_info_v1(
let inputs = get_tx_in_info_v1(&body.inputs, &utxos)?; let inputs = get_tx_in_info_v1(&body.inputs, &utxos)?;
let outputs = let outputs = body
body.outputs .outputs
.iter() .iter()
.map(|output| TxOut::V1(output.clone())) .map(|output| TxOut::V1(output.clone()))
.collect(); .collect();
let fee = Value::Coin(body.fee); let fee = Value::Coin(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.certificates.clone().unwrap_or_default();
.certificates let wdrl = body
.withdrawals
.clone() .clone()
.unwrap_or(vec![]); .unwrap_or(KeyValuePairs::Indef(vec![]))
let wdrl = .deref()
body.withdrawals .clone();
.clone()
.unwrap_or(KeyValuePairs::Indef(vec![]))
.deref()
.clone();
let valid_range = slot_range_to_posix_time_range( let valid_range = slot_range_to_posix_time_range(
TimeRange { TimeRange {
lower_bound: body.validity_interval_start, lower_bound: body.validity_interval_start,
upper_bound: body.ttl, upper_bound: body.ttl,
}, },
&slot_config, slot_config,
); );
let signatories = body let signatories = body.required_signers.clone().unwrap_or_default();
.required_signers
.clone()
.unwrap_or(vec![]);
let data = let data = tx
tx.transaction_witness_set .transaction_witness_set
.plutus_data .plutus_data
.as_ref() .as_ref()
.unwrap_or(&vec![]) .unwrap_or(&vec![])
.iter() .iter()
.map(|d| (d.original_hash(), d.unwrap())) .map(|d| (d.original_hash(), d.clone().unwrap()))
.collect(); .collect();
let id = tx.transaction_body.compute_hash(); let id = tx.transaction_body.compute_hash();
@ -1019,30 +930,22 @@ fn get_tx_info_v1(
fn get_tx_info_v2( fn get_tx_info_v2(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>, utxos: &[ResolvedInput],
slot_config: &SlotConfig, slot_config: &SlotConfig,
) -> anyhow::Result<TxInfo> { ) -> anyhow::Result<TxInfo> {
let body = tx.transaction_body.clone(); let body = tx.transaction_body.clone();
let inputs = get_tx_in_info_v2(&body.inputs, &utxos)?; let inputs = get_tx_in_info_v2(&body.inputs, utxos)?;
let reference_inputs = get_tx_in_info_v2( let reference_inputs =
&body get_tx_in_info_v2(&body.reference_inputs.clone().unwrap_or_default(), utxos)?;
.reference_inputs let outputs = body
.clone() .outputs
.unwrap_or(vec![]), .iter()
&utxos, .map(|output| TxOut::V2(output.clone()))
)?; .collect();
let outputs =
body.outputs
.iter()
.map(|output| TxOut::V2(output.clone()))
.collect();
let fee = Value::Coin(body.fee); let fee = Value::Coin(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.certificates.clone().unwrap_or_default();
.certificates
.clone()
.unwrap_or(vec![]);
let wdrl = body let wdrl = body
.withdrawals .withdrawals
.clone() .clone()
@ -1052,12 +955,9 @@ fn get_tx_info_v2(
lower_bound: body.validity_interval_start, lower_bound: body.validity_interval_start,
upper_bound: body.ttl, upper_bound: body.ttl,
}, },
&slot_config, slot_config,
); );
let signatories = body let signatories = body.required_signers.clone().unwrap_or_default();
.required_signers
.clone()
.unwrap_or(vec![]);
let redeemers = KeyValuePairs::Indef( let redeemers = KeyValuePairs::Indef(
tx.transaction_witness_set tx.transaction_witness_set
.redeemer .redeemer
@ -1067,7 +967,7 @@ fn get_tx_info_v2(
.map(|r| { .map(|r| {
( (
get_script_purpose( get_script_purpose(
&r, r,
&tx.transaction_body.inputs, &tx.transaction_body.inputs,
&tx.transaction_body.mint, &tx.transaction_body.mint,
&tx.transaction_body.certificates, &tx.transaction_body.certificates,
@ -1085,7 +985,7 @@ fn get_tx_info_v2(
.as_ref() .as_ref()
.unwrap_or(&vec![]) .unwrap_or(&vec![])
.iter() .iter()
.map(|d| (d.original_hash(), d.unwrap())) .map(|d| (d.original_hash(), d.clone().unwrap()))
.collect(), .collect(),
); );
let id = tx.transaction_body.compute_hash(); let id = tx.transaction_body.compute_hash();
@ -1107,7 +1007,7 @@ fn get_tx_info_v2(
} }
fn get_execution_purpose( fn get_execution_purpose(
utxos: &MaybeIndefArray<ResolvedInput>, utxos: &[ResolvedInput],
script_purpose: &ScriptPurpose, script_purpose: &ScriptPurpose,
lookup_table: &DataLookupTable, lookup_table: &DataLookupTable,
) -> ExecutionPurpose { ) -> ExecutionPurpose {
@ -1120,7 +1020,7 @@ fn get_execution_purpose(
Some(s) => s.clone(), Some(s) => s.clone(),
None => unreachable!("Missing required scripts.") None => unreachable!("Missing required scripts.")
}; };
ExecutionPurpose::NoDatum(script.clone()) ExecutionPurpose::NoDatum(script)
} }
ScriptPurpose::Spending(out_ref) => { ScriptPurpose::Spending(out_ref) => {
let utxo = utxos.iter().find(|utxo| utxo.input == *out_ref).unwrap(); let utxo = utxos.iter().find(|utxo| utxo.input == *out_ref).unwrap();
@ -1129,22 +1029,19 @@ fn get_execution_purpose(
let address = Address::from_bytes(&output.address).unwrap(); let address = Address::from_bytes(&output.address).unwrap();
match address { match address {
Address::Shelley(shelley_address) => { Address::Shelley(shelley_address) => {
let script = match lookup_table let script = match lookup_table
.scripts .scripts
.get(&shelley_address.payment().as_hash()) { .get(shelley_address.payment().as_hash()) {
Some(s) => s.clone(), Some(s) => s.clone(),
None => unreachable!("Missing required scripts.") None => unreachable!("Missing required scripts.")
}; };
let datum = match lookup_table.datum.get(&output.datum_hash.unwrap_or_else(|| unreachable!("Missing datum hash in input."))) { let datum = match lookup_table.datum.get(&output.datum_hash.unwrap_or_else(|| unreachable!("Missing datum hash in input."))) {
Some(d) => d.clone(), Some(d) => d.clone(),
None => unreachable!("Missing datum in witness set.") None => unreachable!("Missing datum in witness set.")
}; };
ExecutionPurpose::WithDatum(script.clone(), datum.clone()) ExecutionPurpose::WithDatum(script, datum)
} }
_ => unreachable!( _ => unreachable!(
"This is impossible. Only shelley addresses can contain a script hash." "This is impossible. Only shelley addresses can contain a script hash."
@ -1158,7 +1055,7 @@ fn get_execution_purpose(
let script = match lookup_table let script = match lookup_table
.scripts .scripts
.get(&shelley_address.payment().as_hash()) { .get(shelley_address.payment().as_hash()) {
Some(s) => s.clone(), Some(s) => s.clone(),
None => unreachable!("Missing required scripts.") None => unreachable!("Missing required scripts.")
}; };
@ -1166,13 +1063,13 @@ fn get_execution_purpose(
let datum = match &output.datum_option { let datum = match &output.datum_option {
Some(DatumOption::Hash(hash)) => { Some(DatumOption::Hash(hash)) => {
lookup_table.datum.get(&hash).unwrap().clone() lookup_table.datum.get(hash).unwrap().clone()
} }
Some(DatumOption::Data(data)) => data.0.clone(), Some(DatumOption::Data(data)) => data.0.clone(),
_ => unreachable!( "Missing datum hash or inline datum in input."), _ => unreachable!( "Missing datum hash or inline datum in input."),
}; };
ExecutionPurpose::WithDatum(script.clone(), datum) ExecutionPurpose::WithDatum(script, datum)
} }
_ => unreachable!( _ => unreachable!(
"This is impossible. Only shelley addresses can contain a script hash." "This is impossible. Only shelley addresses can contain a script hash."
@ -1183,7 +1080,7 @@ fn get_execution_purpose(
} }
ScriptPurpose::Rewarding(stake_credential) => { ScriptPurpose::Rewarding(stake_credential) => {
let script_hash = match stake_credential { let script_hash = match stake_credential {
StakeCredential::Scripthash(hash) => hash.clone(), StakeCredential::Scripthash(hash) => *hash,
_ => unreachable!("This is impossible. A key hash cannot be the hash of a script."), _ => unreachable!("This is impossible. A key hash cannot be the hash of a script."),
}; };
@ -1198,7 +1095,7 @@ fn get_execution_purpose(
// StakeRegistration doesn't require a witness from a stake key/script. So I assume it doesn't need to be handled in Plutus either? // StakeRegistration doesn't require a witness from a stake key/script. So I assume it doesn't need to be handled in Plutus either?
Certificate::StakeDeregistration(stake_credential) => { Certificate::StakeDeregistration(stake_credential) => {
let script_hash = match stake_credential { let script_hash = match stake_credential {
StakeCredential::Scripthash(hash) => hash.clone(), StakeCredential::Scripthash(hash) => *hash,
_ => unreachable!( _ => unreachable!(
"This is impossible. A key hash cannot be the hash of a script." "This is impossible. A key hash cannot be the hash of a script."
), ),
@ -1213,7 +1110,7 @@ fn get_execution_purpose(
} }
Certificate::StakeDelegation(stake_credential, _) => { Certificate::StakeDelegation(stake_credential, _) => {
let script_hash = match stake_credential { let script_hash = match stake_credential {
StakeCredential::Scripthash(hash) => hash.clone(), StakeCredential::Scripthash(hash) => *hash,
_ => unreachable!( _ => unreachable!(
"This is impossible. A key hash cannot be the hash of a script." "This is impossible. A key hash cannot be the hash of a script."
), ),
@ -1231,10 +1128,7 @@ fn get_execution_purpose(
} }
} }
fn get_script_and_datum_lookup_table( fn get_script_and_datum_lookup_table(tx: &MintedTx, utxos: &[ResolvedInput]) -> DataLookupTable {
tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>,
) -> DataLookupTable {
let mut datum = HashMap::new(); let mut datum = HashMap::new();
let mut scripts = HashMap::new(); let mut scripts = HashMap::new();
@ -1244,30 +1138,32 @@ fn get_script_and_datum_lookup_table(
.transaction_witness_set .transaction_witness_set
.plutus_data .plutus_data
.clone() .clone()
.unwrap_or(vec![]); .unwrap_or_default();
let scripts_v1_witnesses = tx let scripts_v1_witnesses = tx
.transaction_witness_set .transaction_witness_set
.plutus_v1_script .plutus_v1_script
.clone() .clone()
.unwrap_or(vec![]); .unwrap_or_default();
let scripts_v2_witnesses = tx let scripts_v2_witnesses = tx
.transaction_witness_set .transaction_witness_set
.plutus_v2_script .plutus_v2_script
.clone() .clone()
.unwrap_or(vec![]); .unwrap_or_default();
for plutus_data in plutus_data_witnesses.iter() { for plutus_data in plutus_data_witnesses.iter() {
datum.insert(plutus_data.original_hash(), plutus_data.clone()); datum.insert(plutus_data.original_hash(), plutus_data.clone().unwrap());
} }
for script in scripts_v1_witnesses.iter() { for script in scripts_v1_witnesses.iter() {
scripts.insert(script.compute_hash(), ScriptVersion::V1(script.clone())); // TODO: fix hashing bug in pallas scripts.insert(script.compute_hash(), ScriptVersion::V1(script.clone()));
// TODO: fix hashing bug in pallas
} }
for script in scripts_v2_witnesses.iter() { for script in scripts_v2_witnesses.iter() {
scripts.insert(script.compute_hash(), ScriptVersion::V2(script.clone())); // TODO: fix hashing bug in pallas scripts.insert(script.compute_hash(), ScriptVersion::V2(script.clone()));
// TODO: fix hashing bug in pallas
} }
// discovery in utxos (script ref) // discovery in utxos (script ref)
@ -1275,38 +1171,28 @@ fn get_script_and_datum_lookup_table(
for utxo in utxos.iter() { for utxo in utxos.iter() {
match &utxo.output { match &utxo.output {
TransactionOutput::Legacy(_) => {} TransactionOutput::Legacy(_) => {}
TransactionOutput::PostAlonzo(output) => match &output.script_ref { TransactionOutput::PostAlonzo(output) => {
Some(script) => match &script.0 { if let Some(script) = &output.script_ref {
Script::PlutusV1Script(v1) => { match &script.0 {
// scripts.insert(v1.to_hash(), ScriptVersion::PlutusV1(v1.clone())); // TODO: fix hashing bug in pallas Script::PlutusV1Script(v1) => {
let mut prefixed_script: Vec<u8> = vec![0x01]; scripts.insert(v1.compute_hash(), ScriptVersion::V1(v1.clone()));
prefixed_script.extend(v1.0.iter()); }
Script::PlutusV2Script(v2) => {
let hash = Hasher::<224>::hash(&prefixed_script); scripts.insert(v2.compute_hash(), ScriptVersion::V2(v2.clone()));
scripts.insert(hash, ScriptVersion::V1(v1.clone())); }
_ => {}
} }
Script::PlutusV2Script(v2) => { }
// scripts.insert(v2.to_hash(), ScriptVersion::PlutusV2(v2.clone())); // TODO: fix hashing bug in pallas }
let mut prefixed_script: Vec<u8> = vec![0x02];
prefixed_script.extend(v2.0.iter());
let hash = Hasher::<224>::hash(&prefixed_script);
scripts.insert(hash, ScriptVersion::V2(v2.clone()));
}
_ => {}
},
_ => {}
},
} }
} }
DataLookupTable { datum, scripts } DataLookupTable { datum, scripts }
} }
fn eval_redeemer( pub fn eval_redeemer(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>, utxos: &[ResolvedInput],
slot_config: &SlotConfig, slot_config: &SlotConfig,
redeemer: &Redeemer, redeemer: &Redeemer,
lookup_table: &DataLookupTable, lookup_table: &DataLookupTable,
@ -1336,7 +1222,7 @@ fn eval_redeemer(
}; };
let result = program let result = program
.apply_data(datum.clone()) .apply_data(datum)
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()) .apply_data(script_context.to_plutus_data())
.eval(); .eval();
@ -1371,7 +1257,7 @@ fn eval_redeemer(
}; };
let result = program let result = program
.apply_data(datum.clone()) .apply_data(datum)
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()) .apply_data(script_context.to_plutus_data())
.eval(); .eval();
@ -1467,12 +1353,12 @@ fn eval_redeemer(
} }
} }
fn eval_tx( pub fn eval_tx(
tx: &MintedTx, tx: &MintedTx,
utxos: &MaybeIndefArray<ResolvedInput>, utxos: &[ResolvedInput],
//TODO: costMdls //TODO: costMdls
slot_config: &SlotConfig, slot_config: &SlotConfig,
) -> anyhow::Result<MaybeIndefArray<Redeemer>> { ) -> anyhow::Result<Vec<Redeemer>> {
let redeemers = tx.transaction_witness_set.redeemer.as_ref(); let redeemers = tx.transaction_witness_set.redeemer.as_ref();
let lookup_table = get_script_and_datum_lookup_table(tx, utxos); let lookup_table = get_script_and_datum_lookup_table(tx, utxos);
@ -1489,9 +1375,9 @@ fn eval_tx(
&lookup_table, &lookup_table,
)?) )?)
} }
Ok(MaybeIndefArray::Indef(collected_redeemers)) Ok(collected_redeemers)
} }
None => Ok(MaybeIndefArray::Indef(vec![])), None => Ok(vec![]),
} }
} }
@ -1500,12 +1386,11 @@ mod tests {
use pallas_codec::utils::MaybeIndefArray; use pallas_codec::utils::MaybeIndefArray;
use pallas_primitives::{ use pallas_primitives::{
babbage::{TransactionInput, TransactionOutput}, babbage::{TransactionInput, TransactionOutput},
Fragment, ToHash, Fragment,
}; };
use pallas_traverse::{Era, MultiEraTx}; use pallas_traverse::{Era, MultiEraTx};
use uplc::PlutusData;
use super::{eval_tx, ResolvedInput, SlotConfig, TxInInfo}; use super::{eval_tx, ResolvedInput, SlotConfig};
#[test] #[test]
fn test_eval() { fn test_eval() {
@ -1526,19 +1411,17 @@ mod tests {
let raw_inputs = hex::decode("84825820b16778c9cf065d9efeefe37ec269b4fc5107ecdbd0dd6bf3274b224165c2edd9008258206c732139de33e916342707de2aebef2252c781640326ff37b86ec99d97f1ba8d01825820975c17a4fed0051be622328efa548e206657d2b65a19224bf6ff8132571e6a500282582018f86700660fc88d0370a8f95ea58f75507e6b27a18a17925ad3b1777eb0d77600").unwrap(); let raw_inputs = hex::decode("84825820b16778c9cf065d9efeefe37ec269b4fc5107ecdbd0dd6bf3274b224165c2edd9008258206c732139de33e916342707de2aebef2252c781640326ff37b86ec99d97f1ba8d01825820975c17a4fed0051be622328efa548e206657d2b65a19224bf6ff8132571e6a500282582018f86700660fc88d0370a8f95ea58f75507e6b27a18a17925ad3b1777eb0d77600").unwrap();
let raw_outputs = hex::decode("8482581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f67235821a000f8548a1581c15be994a64bdb79dde7fe080d8e7ff81b33a9e4860e9ee0d857a8e85a144576177610182581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351b00000001af14b8b482581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351a0098968082581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351a00acd8c6").unwrap(); let raw_outputs = hex::decode("8482581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f67235821a000f8548a1581c15be994a64bdb79dde7fe080d8e7ff81b33a9e4860e9ee0d857a8e85a144576177610182581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351b00000001af14b8b482581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351a0098968082581d60b6c8794e9a7a26599440a4d0fd79cd07644d15917ff13694f1f672351a00acd8c6").unwrap();
let inputs = MaybeIndefArray::<TransactionInput>::decode_fragment(&raw_inputs).unwrap(); let inputs = Vec::<TransactionInput>::decode_fragment(&raw_inputs).unwrap();
let outputs = MaybeIndefArray::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap(); let outputs = Vec::<TransactionOutput>::decode_fragment(&raw_outputs).unwrap();
let utxos: MaybeIndefArray<ResolvedInput> = MaybeIndefArray::Indef( let utxos: Vec<ResolvedInput> = inputs
inputs .iter()
.iter() .zip(outputs.iter())
.zip(outputs.iter()) .map(|(input, output)| ResolvedInput {
.map(|(input, output)| ResolvedInput { input: input.clone(),
input: input.clone(), output: output.clone(),
output: output.clone(), })
}) .collect();
.collect(),
);
let slot_config = SlotConfig { let slot_config = SlotConfig {
zero_time: 1660003200000, // Preview network zero_time: 1660003200000, // Preview network
@ -1552,7 +1435,7 @@ mod tests {
MultiEraTx::Babbage(tx) => { MultiEraTx::Babbage(tx) => {
let redeemers = eval_tx(&tx, &utxos, &slot_config).unwrap(); let redeemers = eval_tx(&tx, &utxos, &slot_config).unwrap();
println!("{:?}", redeemers.len()); assert_eq!(redeemers.len(), 1)
} }
_ => unreachable!(), _ => unreachable!(),
}; };