diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 5765ec4b..2d1644aa 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -156,17 +156,18 @@ impl<'a> CodeGenerator<'a> { let other_term = self.uplc_code_gen(full_vec_other); - let (spend, mint) = if other.arguments.len() > fun.arguments.len() { - (other_term, term) - } else { - (term, other_term) - }; + let (spend, spend_name, mint, mint_name) = + if other.arguments.len() > fun.arguments.len() { + (other_term, other.name.clone(), term, fun.name.clone()) + } else { + (term, fun.name.clone(), other_term, other.name.clone()) + }; // Special Case with multi_validators self.special_functions.use_function(CONSTR_FIELDS_EXPOSER); self.special_functions.use_function(CONSTR_INDEX_EXPOSER); - term = wrap_as_multi_validator(spend, mint); + term = wrap_as_multi_validator(spend, mint, self.tracing, spend_name, mint_name); } term = cast_validator_args(term, params); diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index 3fd3e979..f899173e 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -1699,20 +1699,68 @@ pub fn special_case_builtin( } } -pub fn wrap_as_multi_validator(spend: Term, mint: Term) -> Term { - Term::equals_integer() - .apply(Term::integer(0.into())) - .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg"))) - .delayed_if_else( - mint.apply(Term::var("__first_arg")) - .apply(Term::var("__second_arg")), - spend.apply(Term::var("__first_arg")).apply( - Term::head_list() - .apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("__second_arg"))), - ), - ) - .lambda("__second_arg") - .lambda("__first_arg") +pub fn wrap_as_multi_validator( + spend: Term, + mint: Term, + trace: bool, + spend_name: String, + mint_name: String, +) -> Term { + if trace { + let trace_string = format!( + "Incorrect redeemer type for validator {}. + Double check you have wrapped the redeemer type as specified in your plutus.json", + spend_name + ); + + let error_term = Term::Error.trace(Term::var("__incorrect_second_arg_type")); + + Term::var("__second_arg") + .delayed_choose_data( + Term::equals_integer() + .apply(Term::integer(0.into())) + .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg"))) + .delayed_if_else( + mint.apply(Term::var("__first_arg")) + .apply(Term::var("__second_arg")) + .trace(Term::string(format!( + "Running 2 arg validator {}", + mint_name + ))), + spend + .apply(Term::var("__first_arg")) + .apply(Term::head_list().apply( + Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("__second_arg")), + )) + .trace(Term::string(format!( + "Running 3 arg validator {}", + spend_name + ))), + ), + error_term.clone(), + error_term.clone(), + error_term.clone(), + error_term, + ) + .lambda("__incorrect_second_arg_type") + .apply(Term::string(trace_string)) + .lambda("__second_arg") + .lambda("__first_arg") + } else { + Term::equals_integer() + .apply(Term::integer(0.into())) + .apply(Term::var(CONSTR_INDEX_EXPOSER).apply(Term::var("__second_arg"))) + .delayed_if_else( + mint.apply(Term::var("__first_arg")) + .apply(Term::var("__second_arg")), + spend.apply(Term::var("__first_arg")).apply( + Term::head_list() + .apply(Term::var(CONSTR_FIELDS_EXPOSER).apply(Term::var("__second_arg"))), + ), + ) + .lambda("__second_arg") + .lambda("__first_arg") + } } /// If the pattern is a list the return the number of elements and if it has a tail diff --git a/crates/uplc/src/builder.rs b/crates/uplc/src/builder.rs index 43bbd173..02085b2c 100644 --- a/crates/uplc/src/builder.rs +++ b/crates/uplc/src/builder.rs @@ -296,6 +296,25 @@ impl Term { .force() } + pub fn delayed_choose_data( + self, + constr_case: Self, + map_case: Self, + array_case: Self, + int_case: Self, + bytes_case: Self, + ) -> Self { + Term::Builtin(DefaultFunction::ChooseData) + .force() + .apply(self) + .apply(constr_case.delay()) + .apply(map_case.delay()) + .apply(array_case.delay()) + .apply(int_case.delay()) + .apply(bytes_case.delay()) + .force() + } + pub fn trace(self, msg_term: Self) -> Self { Term::Builtin(DefaultFunction::Trace) .force()