fix: it compiles again
This commit is contained in:
parent
348ed3b719
commit
26deb6df10
|
@ -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 {
|
||||||
|
|
|
@ -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!(),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue