implement a strict subset of PlutusV3 transaction info
More specifically, that is simply mimicking the script context from v2, minus the new governance features.
This commit is contained in:
parent
c454dc72eb
commit
fdf7a81288
|
@ -96,7 +96,8 @@ pub fn eval_phase_two_raw(
|
||||||
run_phase_one: bool,
|
run_phase_one: bool,
|
||||||
with_redeemer: fn(&Redeemer) -> (),
|
with_redeemer: fn(&Redeemer) -> (),
|
||||||
) -> Result<Vec<Vec<u8>>, Error> {
|
) -> Result<Vec<Vec<u8>>, Error> {
|
||||||
let multi_era_tx = MultiEraTx::decode_for_era(Era::Babbage, tx_bytes)
|
let multi_era_tx = MultiEraTx::decode_for_era(Era::Conway, tx_bytes)
|
||||||
|
.or_else(|_| MultiEraTx::decode_for_era(Era::Babbage, tx_bytes))
|
||||||
.or_else(|_| MultiEraTx::decode_for_era(Era::Alonzo, tx_bytes))?;
|
.or_else(|_| MultiEraTx::decode_for_era(Era::Alonzo, tx_bytes))?;
|
||||||
|
|
||||||
let cost_mdls = CostMdls::decode_fragment(cost_mdls_bytes)?;
|
let cost_mdls = CostMdls::decode_fragment(cost_mdls_bytes)?;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use super::{
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{FakeNamedDeBruijn, NamedDeBruijn, Program},
|
ast::{FakeNamedDeBruijn, NamedDeBruijn, Program},
|
||||||
machine::cost_model::ExBudget,
|
machine::cost_model::ExBudget,
|
||||||
tx::script_context::{DataLookupTable, ScriptVersion, TxInfoV1, TxInfoV2},
|
tx::script_context::{DataLookupTable, ScriptVersion, TxInfoV1, TxInfoV2, TxInfoV3},
|
||||||
PlutusData,
|
PlutusData,
|
||||||
};
|
};
|
||||||
use pallas_codec::utils::Bytes;
|
use pallas_codec::utils::Bytes;
|
||||||
|
@ -116,7 +116,22 @@ pub fn eval_redeemer(
|
||||||
program(script.0)?,
|
program(script.0)?,
|
||||||
),
|
),
|
||||||
|
|
||||||
(ScriptVersion::V3(_script), _datum) => todo!(),
|
(ScriptVersion::V3(script), datum) => do_eval_redeemer(
|
||||||
|
cost_mdls_opt
|
||||||
|
.map(|cost_mdls| {
|
||||||
|
cost_mdls
|
||||||
|
.plutus_v3
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(Error::CostModelNotFound(Language::PlutusV3))
|
||||||
|
})
|
||||||
|
.transpose()?,
|
||||||
|
initial_budget,
|
||||||
|
&Language::PlutusV3,
|
||||||
|
datum,
|
||||||
|
redeemer,
|
||||||
|
TxInfoV3::from_transaction(tx, utxos, slot_config)?,
|
||||||
|
program(script.0)?,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
.map_err(|err| Error::RedeemerError {
|
.map_err(|err| Error::RedeemerError {
|
||||||
tag: redeemer_tag_to_string(&redeemer.tag),
|
tag: redeemer_tag_to_string(&redeemer.tag),
|
||||||
|
|
|
@ -10,7 +10,7 @@ use pallas_primitives::conway::{
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
type AlonzoScriptsNeeded = Vec<(ScriptPurpose, ScriptHash)>;
|
type ScriptsNeeded = Vec<(ScriptPurpose, ScriptHash)>;
|
||||||
|
|
||||||
// subset of phase-1 ledger checks related to scripts
|
// subset of phase-1 ledger checks related to scripts
|
||||||
pub fn eval_phase_one(
|
pub fn eval_phase_one(
|
||||||
|
@ -28,7 +28,7 @@ pub fn eval_phase_one(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_missing_scripts(
|
pub fn validate_missing_scripts(
|
||||||
needed: &AlonzoScriptsNeeded,
|
needed: &ScriptsNeeded,
|
||||||
txscripts: HashMap<ScriptHash, ScriptVersion>,
|
txscripts: HashMap<ScriptHash, ScriptVersion>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let received_hashes = txscripts.keys().copied().collect::<Vec<ScriptHash>>();
|
let received_hashes = txscripts.keys().copied().collect::<Vec<ScriptHash>>();
|
||||||
|
@ -61,10 +61,7 @@ pub fn validate_missing_scripts(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scripts_needed(
|
pub fn scripts_needed(tx: &MintedTx, utxos: &[ResolvedInput]) -> Result<ScriptsNeeded, Error> {
|
||||||
tx: &MintedTx,
|
|
||||||
utxos: &[ResolvedInput],
|
|
||||||
) -> Result<AlonzoScriptsNeeded, Error> {
|
|
||||||
let mut needed = Vec::new();
|
let mut needed = Vec::new();
|
||||||
|
|
||||||
let txb = tx.transaction_body.clone();
|
let txb = tx.transaction_body.clone();
|
||||||
|
@ -106,7 +103,7 @@ pub fn scripts_needed(
|
||||||
|
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
.collect::<AlonzoScriptsNeeded>()
|
.collect::<ScriptsNeeded>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -127,7 +124,7 @@ pub fn scripts_needed(
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<AlonzoScriptsNeeded>()
|
.collect::<ScriptsNeeded>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -137,7 +134,7 @@ pub fn scripts_needed(
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
m.iter()
|
m.iter()
|
||||||
.map(|(policy_id, _)| (ScriptPurpose::Minting(*policy_id), *policy_id))
|
.map(|(policy_id, _)| (ScriptPurpose::Minting(*policy_id), *policy_id))
|
||||||
.collect::<AlonzoScriptsNeeded>()
|
.collect::<ScriptsNeeded>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
@ -156,7 +153,7 @@ pub fn scripts_needed(
|
||||||
/// hasExactSetOfRedeemers in Ledger Spec, but we pass `txscripts` directly
|
/// hasExactSetOfRedeemers in Ledger Spec, but we pass `txscripts` directly
|
||||||
pub fn has_exact_set_of_redeemers(
|
pub fn has_exact_set_of_redeemers(
|
||||||
tx: &MintedTx,
|
tx: &MintedTx,
|
||||||
needed: &AlonzoScriptsNeeded,
|
needed: &ScriptsNeeded,
|
||||||
tx_scripts: HashMap<ScriptHash, ScriptVersion>,
|
tx_scripts: HashMap<ScriptHash, ScriptVersion>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut redeemers_needed = Vec::new();
|
let mut redeemers_needed = Vec::new();
|
||||||
|
|
|
@ -27,6 +27,7 @@ pub struct TxInInfo {
|
||||||
pub out_ref: TransactionInput,
|
pub out_ref: TransactionInput,
|
||||||
pub resolved: TxOut,
|
pub resolved: TxOut,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum TxOut {
|
pub enum TxOut {
|
||||||
V1(TransactionOutput),
|
V1(TransactionOutput),
|
||||||
|
@ -290,15 +291,51 @@ impl TxInfoV2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TxInfoV3 {}
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct TxInfoV3 {
|
||||||
|
pub inputs: Vec<TxInInfo>,
|
||||||
|
pub reference_inputs: Vec<TxInInfo>,
|
||||||
|
pub outputs: Vec<TxOut>,
|
||||||
|
pub fee: Value,
|
||||||
|
pub mint: MintValue,
|
||||||
|
pub certificates: Vec<Certificate>,
|
||||||
|
pub withdrawals: KeyValuePairs<Address, Coin>,
|
||||||
|
pub valid_range: TimeRange,
|
||||||
|
pub signatories: Vec<AddrKeyhash>,
|
||||||
|
pub redeemers: KeyValuePairs<ScriptPurpose, Redeemer>,
|
||||||
|
pub data: KeyValuePairs<DatumHash, PlutusData>,
|
||||||
|
// TODO:
|
||||||
|
// votes : KeyValuePairs<Voter, KeyValuePairs<GovernanceActionId, Vote>>
|
||||||
|
// proposalProcedures : Vec<ProposalProcedure>
|
||||||
|
// currentTreasuryAmount : Option<Coin>
|
||||||
|
// treasuryDonation : Option<Coin>
|
||||||
|
pub id: Hash<32>,
|
||||||
|
}
|
||||||
|
|
||||||
impl TxInfoV3 {
|
impl TxInfoV3 {
|
||||||
pub fn from_transaction(
|
pub fn from_transaction(
|
||||||
_tx: &MintedTx,
|
tx: &MintedTx,
|
||||||
_utxos: &[ResolvedInput],
|
utxos: &[ResolvedInput],
|
||||||
_slot_config: &SlotConfig,
|
slot_config: &SlotConfig,
|
||||||
) -> Result<TxInfo, Error> {
|
) -> Result<TxInfo, Error> {
|
||||||
todo!("TxInfoV3")
|
if let TxInfo::V2(tx_info_v2) = TxInfoV2::from_transaction(tx, utxos, slot_config)? {
|
||||||
|
Ok(TxInfo::V3(TxInfoV3 {
|
||||||
|
inputs: tx_info_v2.inputs,
|
||||||
|
reference_inputs: tx_info_v2.reference_inputs,
|
||||||
|
outputs: tx_info_v2.outputs,
|
||||||
|
fee: tx_info_v2.fee,
|
||||||
|
mint: tx_info_v2.mint,
|
||||||
|
certificates: tx_info_v2.certificates,
|
||||||
|
withdrawals: tx_info_v2.withdrawals,
|
||||||
|
valid_range: tx_info_v2.valid_range,
|
||||||
|
signatories: tx_info_v2.signatories,
|
||||||
|
redeemers: tx_info_v2.redeemers,
|
||||||
|
data: tx_info_v2.data,
|
||||||
|
id: tx_info_v2.id,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,12 +343,15 @@ impl TxInfoV3 {
|
||||||
pub enum TxInfo {
|
pub enum TxInfo {
|
||||||
V1(TxInfoV1),
|
V1(TxInfoV1),
|
||||||
V2(TxInfoV2),
|
V2(TxInfoV2),
|
||||||
|
V3(TxInfoV3),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxInfo {
|
impl TxInfo {
|
||||||
pub fn purpose(&self, needle: &Redeemer) -> Option<ScriptPurpose> {
|
pub fn purpose(&self, needle: &Redeemer) -> Option<ScriptPurpose> {
|
||||||
match self {
|
match self {
|
||||||
TxInfo::V1(TxInfoV1 { redeemers, .. }) | TxInfo::V2(TxInfoV2 { redeemers, .. }) => {
|
TxInfo::V1(TxInfoV1 { redeemers, .. })
|
||||||
|
| TxInfo::V2(TxInfoV2 { redeemers, .. })
|
||||||
|
| TxInfo::V3(TxInfoV3 { redeemers, .. }) => {
|
||||||
redeemers.iter().find_map(|(purpose, redeemer)| {
|
redeemers.iter().find_map(|(purpose, redeemer)| {
|
||||||
if redeemer == needle {
|
if redeemer == needle {
|
||||||
Some(purpose.clone())
|
Some(purpose.clone())
|
||||||
|
@ -327,6 +367,7 @@ impl TxInfo {
|
||||||
match self {
|
match self {
|
||||||
TxInfo::V1(info) => &info.inputs,
|
TxInfo::V1(info) => &info.inputs,
|
||||||
TxInfo::V2(info) => &info.inputs,
|
TxInfo::V2(info) => &info.inputs,
|
||||||
|
TxInfo::V3(info) => &info.inputs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +375,7 @@ impl TxInfo {
|
||||||
match self {
|
match self {
|
||||||
TxInfo::V1(info) => &info.mint,
|
TxInfo::V1(info) => &info.mint,
|
||||||
TxInfo::V2(info) => &info.mint,
|
TxInfo::V2(info) => &info.mint,
|
||||||
|
TxInfo::V3(info) => &info.mint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +383,7 @@ impl TxInfo {
|
||||||
match self {
|
match self {
|
||||||
TxInfo::V1(info) => &info.withdrawals[..],
|
TxInfo::V1(info) => &info.withdrawals[..],
|
||||||
TxInfo::V2(info) => &info.withdrawals[..],
|
TxInfo::V2(info) => &info.withdrawals[..],
|
||||||
|
TxInfo::V3(info) => &info.withdrawals[..],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +391,7 @@ impl TxInfo {
|
||||||
match self {
|
match self {
|
||||||
TxInfo::V1(info) => &info.certificates[..],
|
TxInfo::V1(info) => &info.certificates[..],
|
||||||
TxInfo::V2(info) => &info.certificates[..],
|
TxInfo::V2(info) => &info.certificates[..],
|
||||||
|
TxInfo::V3(info) => &info.certificates[..],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ fn empty_constr(index: u64) -> PlutusData {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WithWrappedTransactionId<'a, T>(&'a T);
|
||||||
|
|
||||||
pub trait ToPlutusData {
|
pub trait ToPlutusData {
|
||||||
fn to_plutus_data(&self) -> PlutusData;
|
fn to_plutus_data(&self) -> PlutusData;
|
||||||
}
|
}
|
||||||
|
@ -98,12 +100,24 @@ impl ToPlutusData for Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ToPlutusData for WithWrappedTransactionId<'a, TransactionInput> {
|
||||||
|
fn to_plutus_data(&self) -> PlutusData {
|
||||||
|
wrap_multiple_with_constr(
|
||||||
|
0,
|
||||||
|
vec![
|
||||||
|
wrap_with_constr(0, self.0.transaction_id.to_plutus_data()),
|
||||||
|
PlutusData::BigInt(BigInt::Int((self.0.index as i128).try_into().unwrap())),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToPlutusData for TransactionInput {
|
impl ToPlutusData for TransactionInput {
|
||||||
fn to_plutus_data(&self) -> PlutusData {
|
fn to_plutus_data(&self) -> PlutusData {
|
||||||
wrap_multiple_with_constr(
|
wrap_multiple_with_constr(
|
||||||
0,
|
0,
|
||||||
vec![
|
vec![
|
||||||
wrap_with_constr(0, self.transaction_id.to_plutus_data()),
|
self.transaction_id.to_plutus_data(),
|
||||||
PlutusData::BigInt(BigInt::Int((self.index as i128).try_into().unwrap())),
|
PlutusData::BigInt(BigInt::Int((self.index as i128).try_into().unwrap())),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -299,7 +313,7 @@ impl ToPlutusData for TxOut {
|
||||||
// legacy_output.datum_hash.to_plutus_data(),
|
// legacy_output.datum_hash.to_plutus_data(),
|
||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
TransactionOutput::Legacy(..) => todo!("TransactionOutput::Legacy"),
|
TransactionOutput::Legacy(..) => unimplemented!("TransactionOutput::Legacy"),
|
||||||
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
|
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
|
||||||
0,
|
0,
|
||||||
vec![
|
vec![
|
||||||
|
@ -329,7 +343,7 @@ impl ToPlutusData for TxOut {
|
||||||
// None::<ScriptRef>.to_plutus_data(),
|
// None::<ScriptRef>.to_plutus_data(),
|
||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
TransactionOutput::Legacy(..) => todo!("TransactionOutput::Legacy"),
|
TransactionOutput::Legacy(..) => unimplemented!("TransactionOutput::Legacy"),
|
||||||
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
|
TransactionOutput::PostAlonzo(post_alonzo_output) => wrap_multiple_with_constr(
|
||||||
0,
|
0,
|
||||||
vec![
|
vec![
|
||||||
|
@ -556,6 +570,29 @@ impl ToPlutusData for TimeRange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ToPlutusData for WithWrappedTransactionId<'a, Vec<TxInInfo>> {
|
||||||
|
fn to_plutus_data(&self) -> PlutusData {
|
||||||
|
PlutusData::Array(
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(|p| WithWrappedTransactionId(p).to_plutus_data())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToPlutusData for WithWrappedTransactionId<'a, TxInInfo> {
|
||||||
|
fn to_plutus_data(&self) -> PlutusData {
|
||||||
|
wrap_multiple_with_constr(
|
||||||
|
0,
|
||||||
|
vec![
|
||||||
|
WithWrappedTransactionId(&self.0.out_ref).to_plutus_data(),
|
||||||
|
self.0.resolved.to_plutus_data(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToPlutusData for TxInInfo {
|
impl ToPlutusData for TxInInfo {
|
||||||
fn to_plutus_data(&self) -> PlutusData {
|
fn to_plutus_data(&self) -> PlutusData {
|
||||||
wrap_multiple_with_constr(
|
wrap_multiple_with_constr(
|
||||||
|
@ -587,7 +624,7 @@ impl ToPlutusData for TxInfo {
|
||||||
TxInfo::V1(tx_info) => wrap_multiple_with_constr(
|
TxInfo::V1(tx_info) => wrap_multiple_with_constr(
|
||||||
0,
|
0,
|
||||||
vec![
|
vec![
|
||||||
tx_info.inputs.to_plutus_data(),
|
WithWrappedTransactionId(&tx_info.inputs).to_plutus_data(),
|
||||||
tx_info.outputs.to_plutus_data(),
|
tx_info.outputs.to_plutus_data(),
|
||||||
tx_info.fee.to_plutus_data(),
|
tx_info.fee.to_plutus_data(),
|
||||||
tx_info.mint.to_plutus_data(),
|
tx_info.mint.to_plutus_data(),
|
||||||
|
@ -600,6 +637,23 @@ impl ToPlutusData for TxInfo {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
TxInfo::V2(tx_info) => wrap_multiple_with_constr(
|
TxInfo::V2(tx_info) => wrap_multiple_with_constr(
|
||||||
|
0,
|
||||||
|
vec![
|
||||||
|
WithWrappedTransactionId(&tx_info.inputs).to_plutus_data(),
|
||||||
|
WithWrappedTransactionId(&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.certificates.to_plutus_data(),
|
||||||
|
tx_info.withdrawals.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()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
TxInfo::V3(tx_info) => wrap_multiple_with_constr(
|
||||||
0,
|
0,
|
||||||
vec![
|
vec![
|
||||||
tx_info.inputs.to_plutus_data(),
|
tx_info.inputs.to_plutus_data(),
|
||||||
|
@ -613,7 +667,7 @@ impl ToPlutusData for TxInfo {
|
||||||
tx_info.signatories.to_plutus_data(),
|
tx_info.signatories.to_plutus_data(),
|
||||||
tx_info.redeemers.to_plutus_data(),
|
tx_info.redeemers.to_plutus_data(),
|
||||||
tx_info.data.to_plutus_data(),
|
tx_info.data.to_plutus_data(),
|
||||||
wrap_with_constr(0, tx_info.id.to_plutus_data()),
|
tx_info.id.to_plutus_data(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue