feat: new error for bad term

This commit is contained in:
rvcas 2022-09-19 11:04:21 -04:00
parent 30ed8d9150
commit f10e3836ad
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
4 changed files with 91 additions and 42 deletions

View File

@ -54,7 +54,27 @@ fn main() -> anyhow::Result<()> {
slot_length, slot_length,
}; };
tx::eval_phase_two(tx_babbage, &resolved_inputs, None, &slot_config, true)?; let result = tx::eval_phase_two(
tx_babbage,
&resolved_inputs,
None,
None,
&slot_config,
true,
);
match result {
Ok(redeemers) => {
println!("\nResult\n------\n\n");
for redeemer in redeemers {
println!("{:#?}", redeemer)
}
}
Err(err) => {
eprintln!("\nError\n-----\n\n{}\n", err);
}
}
} }
} }
}, },

View File

@ -526,7 +526,7 @@ impl Program<NamedDeBruijn> {
Vec<String>, Vec<String>,
) { ) {
let budget = match initial_budget { let budget = match initial_budget {
Some(b) => b.clone(), Some(b) => *b,
None => ExBudget::default(), None => ExBudget::default(),
}; };
@ -556,3 +556,9 @@ impl Program<DeBruijn> {
program.eval() program.eval()
} }
} }
impl Term<NamedDeBruijn> {
pub fn is_valid_script_result(&self) -> bool {
matches!(self, Term::Constant(Constant::Unit))
}
}

View File

@ -1,17 +1,22 @@
use crate::machine; use crate::{
ast::{NamedDeBruijn, Term},
machine::{self, cost_model::ExBudget},
};
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Error { pub enum Error {
#[error("{0}")] #[error("{0}")]
Address(#[from] pallas_addresses::Error), Address(#[from] pallas_addresses::Error),
#[error("{}\n\n{:#?}\n\n{}", .0, .1, .2.join("\n"))]
BadTerm(Term<NamedDeBruijn>, ExBudget, Vec<String>),
#[error("Only shelley reward addresses can be a part of withdrawals")] #[error("Only shelley reward addresses can be a part of withdrawals")]
BadWithdrawalAddress, BadWithdrawalAddress,
#[error("{0}")] #[error("{0}")]
FlatDecode(#[from] flat_rs::de::Error), FlatDecode(#[from] flat_rs::de::Error),
#[error("{0}")] #[error("{0}")]
FragmentDecode(#[from] pallas_primitives::Error), FragmentDecode(#[from] pallas_primitives::Error),
#[error("{0}")] #[error("{}\n\n{:#?}\n\n{}", .0, .1, .2.join("\n"))]
Machine(#[from] machine::Error), Machine(machine::Error, ExBudget, Vec<String>),
#[error("Native script can't be executed in phase-two")] #[error("Native script can't be executed in phase-two")]
NativeScriptPhaseTwo, NativeScriptPhaseTwo,
#[error("Can't eval without redeemers")] #[error("Can't eval without redeemers")]

View File

@ -168,12 +168,10 @@ fn get_script_purpose(
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)), Some(policy_id) => Ok(ScriptPurpose::Minting(*policy_id)),
None => { None => Err(Error::ExtraneousRedeemer {
return Err(Error::ExtraneousRedeemer {
tag: "Mint".to_string(), tag: "Mint".to_string(),
index, index,
}) }),
}
} }
} }
RedeemerTag::Spend => { RedeemerTag::Spend => {
@ -182,12 +180,10 @@ fn get_script_purpose(
inputs.sort(); inputs.sort();
match inputs.get(index as usize) { match inputs.get(index as usize) {
Some(input) => Ok(ScriptPurpose::Spending(input.clone())), Some(input) => Ok(ScriptPurpose::Spending(input.clone())),
None => { None => Err(Error::ExtraneousRedeemer {
return Err(Error::ExtraneousRedeemer {
tag: "Spend".to_string(), tag: "Spend".to_string(),
index, index,
}) }),
}
} }
} }
RedeemerTag::Reward => { RedeemerTag::Reward => {
@ -228,12 +224,10 @@ fn get_script_purpose(
.get(index as usize) .get(index as usize)
{ {
Some(cert) => Ok(ScriptPurpose::Certifying(cert.clone())), Some(cert) => Ok(ScriptPurpose::Certifying(cert.clone())),
None => { None => Err(Error::ExtraneousRedeemer {
return Err(Error::ExtraneousRedeemer {
tag: "Cert".to_string(), tag: "Cert".to_string(),
index, index,
}) }),
}
} }
} }
} }
@ -436,7 +430,7 @@ fn get_execution_purpose(
Ok(ExecutionPurpose::WithDatum(script, datum)) Ok(ExecutionPurpose::WithDatum(script, datum))
} }
_ => return Err(Error::ScriptKeyHash), _ => Err(Error::ScriptKeyHash),
} }
} }
TransactionOutput::PostAlonzo(output) => { TransactionOutput::PostAlonzo(output) => {
@ -470,7 +464,7 @@ fn get_execution_purpose(
Ok(ExecutionPurpose::WithDatum(script, datum)) Ok(ExecutionPurpose::WithDatum(script, datum))
} }
_ => return Err(Error::ScriptKeyHash), _ => Err(Error::ScriptKeyHash),
} }
} }
} }
@ -527,7 +521,7 @@ fn get_execution_purpose(
Ok(ExecutionPurpose::NoDatum(script)) Ok(ExecutionPurpose::NoDatum(script))
} }
_ => return Err(Error::OnlyStakeDeregAndDelegAllowed), _ => Err(Error::OnlyStakeDeregAndDelegAllowed),
}, },
} }
} }
@ -645,7 +639,7 @@ pub fn eval_redeemer(
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()); .apply_data(script_context.to_plutus_data());
let (result, budget, _) = if let Some(cost_mdls) = cost_mdls_opt { let (result, budget, logs) = if let Some(cost_mdls) = cost_mdls_opt {
let costs = if let Some(costs) = &cost_mdls.plutus_v1 { let costs = if let Some(costs) = &cost_mdls.plutus_v1 {
costs costs
} else { } else {
@ -657,11 +651,17 @@ pub fn eval_redeemer(
program.eval_v1() program.eval_v1()
}; };
// TODO: do we want the logs in the error? match result {
result?; Ok(term) => {
if !term.is_valid_script_result() {
return Err(Error::BadTerm(term, budget, logs));
}
}
Err(err) => return Err(Error::Machine(err, budget, logs)),
}
let initial_budget = match initial_budget { let initial_budget = match initial_budget {
Some(b) => b.clone(), Some(b) => *b,
None => ExBudget::default(), None => ExBudget::default(),
}; };
@ -694,7 +694,7 @@ pub fn eval_redeemer(
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()); .apply_data(script_context.to_plutus_data());
let (result, budget, _) = if let Some(cost_mdls) = cost_mdls_opt { let (result, budget, logs) = if let Some(cost_mdls) = cost_mdls_opt {
let costs = if let Some(costs) = &cost_mdls.plutus_v2 { let costs = if let Some(costs) = &cost_mdls.plutus_v2 {
costs costs
} else { } else {
@ -706,11 +706,17 @@ pub fn eval_redeemer(
program.eval() program.eval()
}; };
// TODO: do we want the logs in the error? match result {
result?; Ok(term) => {
if !term.is_valid_script_result() {
return Err(Error::BadTerm(term, budget, logs));
}
}
Err(err) => return Err(Error::Machine(err, budget, logs)),
}
let initial_budget = match initial_budget { let initial_budget = match initial_budget {
Some(b) => b.clone(), Some(b) => *b,
None => ExBudget::default(), None => ExBudget::default(),
}; };
@ -745,7 +751,7 @@ pub fn eval_redeemer(
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()); .apply_data(script_context.to_plutus_data());
let (result, budget, _) = if let Some(cost_mdls) = cost_mdls_opt { let (result, budget, logs) = if let Some(cost_mdls) = cost_mdls_opt {
let costs = if let Some(costs) = &cost_mdls.plutus_v1 { let costs = if let Some(costs) = &cost_mdls.plutus_v1 {
costs costs
} else { } else {
@ -757,11 +763,17 @@ pub fn eval_redeemer(
program.eval_v1() program.eval_v1()
}; };
// TODO: do we want the logs in the error? match result {
result?; Ok(term) => {
if !term.is_valid_script_result() {
return Err(Error::BadTerm(term, budget, logs));
}
}
Err(err) => return Err(Error::Machine(err, budget, logs)),
}
let initial_budget = match initial_budget { let initial_budget = match initial_budget {
Some(b) => b.clone(), Some(b) => *b,
None => ExBudget::default(), None => ExBudget::default(),
}; };
@ -793,7 +805,7 @@ pub fn eval_redeemer(
.apply_data(redeemer.data.clone()) .apply_data(redeemer.data.clone())
.apply_data(script_context.to_plutus_data()); .apply_data(script_context.to_plutus_data());
let (result, budget, _) = if let Some(cost_mdls) = cost_mdls_opt { let (result, budget, logs) = if let Some(cost_mdls) = cost_mdls_opt {
let costs = if let Some(costs) = &cost_mdls.plutus_v2 { let costs = if let Some(costs) = &cost_mdls.plutus_v2 {
costs costs
} else { } else {
@ -805,11 +817,17 @@ pub fn eval_redeemer(
program.eval() program.eval()
}; };
// TODO: do we want the logs in the error? match result {
result?; Ok(term) => {
if !term.is_valid_script_result() {
return Err(Error::BadTerm(term, budget, logs));
}
}
Err(err) => return Err(Error::Machine(err, budget, logs)),
}
let initial_budget = match initial_budget { let initial_budget = match initial_budget {
Some(b) => b.clone(), Some(b) => *b,
None => ExBudget::default(), None => ExBudget::default(),
}; };