Improve / fix machine and uplc error reporting.
This commit is contained in:
parent
f56b9bbbc7
commit
b158469144
|
@ -149,7 +149,14 @@ pub fn exec(
|
|||
);
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("{}", display_tx_error(&err));
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
" Error"
|
||||
.if_supports_color(Stderr, |s| s.red())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
err.red()
|
||||
);
|
||||
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -157,46 +164,3 @@ pub fn exec(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_tx_error(err: &tx::error::Error) -> String {
|
||||
let mut msg = format!(
|
||||
"{} {}",
|
||||
" Error"
|
||||
.if_supports_color(Stderr, |s| s.red())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
err.red()
|
||||
);
|
||||
match err {
|
||||
tx::error::Error::RedeemerError { err, .. } => {
|
||||
msg.push_str(&format!(
|
||||
"\n{}",
|
||||
display_tx_error(err)
|
||||
.lines()
|
||||
.skip(1)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
));
|
||||
msg
|
||||
}
|
||||
tx::error::Error::Machine(_, _, traces) => {
|
||||
msg.push_str(
|
||||
traces
|
||||
.iter()
|
||||
.map(|s| {
|
||||
format!(
|
||||
"\n{} {}",
|
||||
" Trace"
|
||||
.if_supports_color(Stderr, |s| s.yellow())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
s.if_supports_color(Stderr, |s| s.yellow())
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
.as_str(),
|
||||
);
|
||||
msg
|
||||
}
|
||||
_ => msg,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ pub enum Error {
|
|||
InvalidStepKind(u8),
|
||||
#[error("Cannot evaluate an open term:\\n\\n{}", .0.to_pretty())]
|
||||
OpenTermEvaluated(Term<NamedDeBruijn>),
|
||||
#[error("The provided Plutus code called 'error'.")]
|
||||
#[error("The validator crashed / exited prematurely")]
|
||||
EvaluationFailure,
|
||||
#[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")]
|
||||
NonPolymorphicInstantiation(Value),
|
||||
|
@ -29,9 +29,13 @@ pub enum Error {
|
|||
PairTypeMismatch(Type),
|
||||
#[error("Empty List:\n\n{0:#?}")]
|
||||
EmptyList(Value),
|
||||
#[error("A builtin received a term argument when something else was expected:\n\n{0}\n\nYou probably forgot to wrap the builtin with a force.")]
|
||||
#[error(
|
||||
"A builtin received a term argument when something else was expected:\n\n{0}\n\nYou probably forgot to wrap the builtin with a force."
|
||||
)]
|
||||
UnexpectedBuiltinTermArgument(Term<NamedDeBruijn>),
|
||||
#[error("A builtin expected a term argument, but something else was received:\n\n{0}\n\nYou probably have an extra force wrapped around a builtin")]
|
||||
#[error(
|
||||
"A builtin expected a term argument, but something else was received:\n\n{0}\n\nYou probably have an extra force wrapped around a builtin"
|
||||
)]
|
||||
BuiltinTermArgumentExpected(Term<NamedDeBruijn>),
|
||||
#[error("Unable to unlift value because it is not a constant:\n\n{0:#?}")]
|
||||
NotAConstant(Value),
|
||||
|
|
|
@ -8,59 +8,93 @@ use pallas_primitives::conway::Language;
|
|||
pub enum Error {
|
||||
#[error("{0}")]
|
||||
Address(#[from] pallas_addresses::Error),
|
||||
#[error("Only shelley reward addresses can be a part of withdrawals")]
|
||||
#[error("only shelley reward addresses can be a part of withdrawals")]
|
||||
BadWithdrawalAddress,
|
||||
#[error("{0}")]
|
||||
FlatDecode(#[from] pallas_codec::flat::de::Error),
|
||||
#[error("{0}")]
|
||||
FragmentDecode(#[from] pallas_primitives::Error),
|
||||
#[error("{}\n\n{:#?}\n\n{}", .0, .1, .2.join("\n"))]
|
||||
#[error("{}{}", .0, .2.iter()
|
||||
.map(|trace| {
|
||||
format!(
|
||||
"\n{:>13} {}",
|
||||
"Trace",
|
||||
if trace.contains("\n") {
|
||||
trace.lines()
|
||||
.enumerate()
|
||||
.map(|(ix, row)| {
|
||||
if ix == 0 {
|
||||
row.to_string()
|
||||
} else {
|
||||
format!("{:>13} {}", "",
|
||||
row
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
} else {
|
||||
trace.to_string()
|
||||
}
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
.as_str()
|
||||
)]
|
||||
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,
|
||||
#[error("Can't eval without redeemers")]
|
||||
#[error("can't eval without redeemers")]
|
||||
NoRedeemers,
|
||||
#[error("Mismatch in required redeemers: {} {}", .missing.join(" "), .extra.join(" "))]
|
||||
#[error(
|
||||
"mismatch in expected redeemers\n{:>13} {}\n{:>13} {}",
|
||||
"Missing",
|
||||
if .missing.is_empty() { "ø".to_string() } else { .missing.join(&format!("\n{:>13}", "")) },
|
||||
"Unexpected",
|
||||
if .extra.is_empty() { "ø".to_string() } else { .extra.join(&format!("\n{:>13}", "")) },
|
||||
)]
|
||||
RequiredRedeemersMismatch {
|
||||
missing: Vec<String>,
|
||||
extra: Vec<String>,
|
||||
},
|
||||
#[error("Extraneous redeemer")]
|
||||
#[error("extraneous redeemer")]
|
||||
ExtraneousRedeemer,
|
||||
#[error("Resolved Input not found.")]
|
||||
#[error("resolved Input not found")]
|
||||
ResolvedInputNotFound(TransactionInput),
|
||||
#[error("Redeemer points to a non-script withdrawal.")]
|
||||
#[error("redeemer points to a non-script withdrawal")]
|
||||
NonScriptWithdrawal,
|
||||
#[error("Stake credential points to a non-script withdrawal.")]
|
||||
#[error("stake credential points to a non-script withdrawal")]
|
||||
NonScriptStakeCredential,
|
||||
#[error("Cost model not found for language: {:?}.", .0)]
|
||||
#[error("cost model not found for language\n{:>13} {:?}", "Language", .0)]
|
||||
CostModelNotFound(Language),
|
||||
#[error("Wrong era, Please use Babbage or Alonzo: {0}")]
|
||||
#[error("unsupported era, please use Conway\n{:>13} {0}", "Decoder error")]
|
||||
WrongEra(#[from] pallas_codec::minicbor::decode::Error),
|
||||
#[error("Byron address not allowed in Plutus.")]
|
||||
#[error("byron address not allowed when PlutusV2 scripts are present")]
|
||||
ByronAddressNotAllowed,
|
||||
#[error("Inline datum not allowed in PlutusV1.")]
|
||||
#[error("inline datum not allowed when PlutusV1 scripts are present")]
|
||||
InlineDatumNotAllowed,
|
||||
#[error("Script and input reference not allowed in PlutusV1.")]
|
||||
#[error("script and input reference not allowed in PlutusV1")]
|
||||
ScriptAndInputRefNotAllowed,
|
||||
#[error("Address doesn't contain a payment credential.")]
|
||||
#[error("address doesn't contain a payment credential")]
|
||||
NoPaymentCredential,
|
||||
#[error("Missing required datum: {}", hash)]
|
||||
#[error("missing required datum\n{:>13} {}", "Datum", hash)]
|
||||
MissingRequiredDatum { hash: String },
|
||||
#[error("Missing required script: {}", hash)]
|
||||
#[error("missing required script\n{:>13} {}", "Script", hash)]
|
||||
MissingRequiredScript { hash: String },
|
||||
#[error("Missing required inline datum or datum hash in script input.")]
|
||||
#[error("missing required inline datum or datum hash in script input")]
|
||||
MissingRequiredInlineDatumOrHash,
|
||||
#[error("Redeemer points to an unsupported certificate type.")]
|
||||
#[error("redeemer points to an unsupported certificate type")]
|
||||
UnsupportedCertificateType,
|
||||
#[error("Redeemer ({}, {}): {}", tag, index, err)]
|
||||
#[error("failed script execution\n{:>13} {}", format!("{}({})", tag, index), err)]
|
||||
RedeemerError {
|
||||
tag: String,
|
||||
index: u32,
|
||||
err: Box<Error>,
|
||||
},
|
||||
#[error("Missing script for redeemer")]
|
||||
#[error("missing script for redeemer")]
|
||||
MissingScriptForRedeemer,
|
||||
#[error("Failed to apply parameters to Plutus script.")]
|
||||
#[error("failed to apply parameters to Plutus script")]
|
||||
ApplyParamsError,
|
||||
}
|
||||
|
|
|
@ -39,23 +39,17 @@ pub fn validate_missing_scripts(
|
|||
.clone()
|
||||
.into_iter()
|
||||
.filter(|x| !received_hashes.contains(x))
|
||||
.map(|x| format!("[Missing (sh: {x})]"))
|
||||
.map(|x| x.to_string())
|
||||
.collect();
|
||||
|
||||
let extra: Vec<_> = received_hashes
|
||||
.into_iter()
|
||||
.filter(|x| !needed_hashes.contains(x))
|
||||
.map(|x| format!("[Extraneous (sh: {x:?})]"))
|
||||
.map(|x| x.to_string())
|
||||
.collect();
|
||||
|
||||
if !missing.is_empty() || !extra.is_empty() {
|
||||
let missing_errors = missing.join(" ");
|
||||
let extra_errors = extra.join(" ");
|
||||
|
||||
unreachable!(
|
||||
"Mismatch in required scripts: {} {}",
|
||||
missing_errors, extra_errors
|
||||
);
|
||||
return Err(Error::RequiredRedeemersMismatch { missing, extra });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -191,18 +185,13 @@ pub fn has_exact_set_of_redeemers(
|
|||
let missing: Vec<_> = redeemers_needed
|
||||
.into_iter()
|
||||
.filter(|x| !wits_redeemer_keys.contains(&&x.0))
|
||||
.map(|x| {
|
||||
format!(
|
||||
"[Missing (redeemer_key: {:?}, script_purpose: {:?}, script_hash: {})]",
|
||||
x.0, x.1, x.2,
|
||||
)
|
||||
})
|
||||
.map(|x| format!("{} (key: {:?}, purpose: {:?})", x.2, x.0, x.1,))
|
||||
.collect();
|
||||
|
||||
let extra: Vec<_> = wits_redeemer_keys
|
||||
.into_iter()
|
||||
.filter(|x| !needed_redeemer_keys.contains(x))
|
||||
.map(|x| format!("[Extraneous (redeemer_key: {x:?})]"))
|
||||
.map(|x| format!("{x:?}"))
|
||||
.collect();
|
||||
|
||||
if !missing.is_empty() || !extra.is_empty() {
|
||||
|
|
Loading…
Reference in New Issue