From 513ca27717b573d48a17f211c05991a15007fdce Mon Sep 17 00:00:00 2001 From: KtorZ Date: Tue, 1 Oct 2024 19:03:34 +0200 Subject: [PATCH] Generate empty redeemer for `else` handler, to keep full compliance with the blueprint spec --- CHANGELOG.md | 1 + .../aiken-project/src/blueprint/parameter.rs | 27 ++++---- ...rint__validator__tests__else_redeemer.snap | 12 ++++ .../aiken-project/src/blueprint/validator.rs | 63 +++++++++++++------ crates/aiken-project/src/export.rs | 4 +- 5 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__else_redeemer.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 00830753..0f639af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed +- **aiken-project**: Generate empty redeemer for `else` handler, to keep full compliance with the blueprint spec. @KtorZ - **aiken-lang**: Forbid constants evaluating to generic or unbound functions. Same restrictions as for validators or any exported UPLC programs apply here. @KtorZ & @MicroProofs - **aiken-lang**: Fix compiler crash on trace + expect as last expression of a clause. See #1029. @KtorZ - **aiken-lang**: Fix redundant warning on introduced identifiers when destructuring validator params. @KtorZ diff --git a/crates/aiken-project/src/blueprint/parameter.rs b/crates/aiken-project/src/blueprint/parameter.rs index 56b145b8..340eea96 100644 --- a/crates/aiken-project/src/blueprint/parameter.rs +++ b/crates/aiken-project/src/blueprint/parameter.rs @@ -14,14 +14,14 @@ pub struct Parameter { #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, - pub schema: Reference, + pub schema: Declaration, } impl From for Parameter { fn from(schema: Reference) -> Parameter { Parameter { title: None, - schema, + schema: Declaration::Referenced(schema), } } } @@ -32,15 +32,20 @@ impl Parameter { definitions: &Definitions>, constant: &Constant, ) -> Result<(), Error> { - let schema = &definitions - .lookup(&self.schema) - .map(Ok) - .unwrap_or_else(|| { - Err(Error::UnresolvedSchemaReference { - reference: self.schema.clone(), - }) - })? - .annotated; + let schema = match &self.schema { + Declaration::Inline(schema) => schema, + Declaration::Referenced(ref link) => { + &definitions + .lookup(link) + .map(Ok) + .unwrap_or_else(|| { + Err(Error::UnresolvedSchemaReference { + reference: link.clone(), + }) + })? + .annotated + } + }; validate_schema(schema, definitions, constant) } diff --git a/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__else_redeemer.snap b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__else_redeemer.snap new file mode 100644 index 00000000..5b8fce4e --- /dev/null +++ b/crates/aiken-project/src/blueprint/snapshots/aiken_project__blueprint__validator__tests__else_redeemer.snap @@ -0,0 +1,12 @@ +--- +source: crates/aiken-project/src/blueprint/validator.rs +description: "Code:\n\nvalidator always_true {\n else(_) {\n True\n }\n}\n" +--- +{ + "title": "test_module.always_true.else", + "redeemer": { + "schema": {} + }, + "compiledCode": "", + "hash": "" +} diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index 0c36f8ae..e433df7e 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -3,7 +3,7 @@ use super::{ error::Error, memo_program::MemoProgram, parameter::Parameter, - schema::{Annotated, Schema}, + schema::{Annotated, Data, Declaration, Schema}, }; use crate::module::{CheckedModule, CheckedModules}; use aiken_lang::{ @@ -111,7 +111,7 @@ impl Validator { ) .map(|schema| Parameter { title: Some(param.arg_name.get_label()), - schema, + schema: Declaration::Referenced(schema), }) .map_err(|error| Error::Schema { error, @@ -173,7 +173,7 @@ impl Validator { .transpose()? .map(|schema| Parameter { title: datum.map(|datum| datum.arg_name.get_label()), - schema, + schema: Declaration::Referenced(schema), }); let redeemer = Annotated::from_type( @@ -191,12 +191,17 @@ impl Validator { }) .map(|schema| Parameter { title: Some(redeemer.arg_name.get_label()), - schema, + schema: Declaration::Referenced(schema), })?; (datum, Some(redeemer)) }; + let redeemer = redeemer.or(Some(Parameter { + title: None, + schema: Declaration::Inline(Box::new(Schema::Data(Data::Opaque))), + })); + Ok(Validator { title: format!("{}.{}.{}", &module.name, &def.name, &func.name,), description: func.doc.clone(), @@ -266,20 +271,27 @@ impl Validator { match self.parameters.split_first() { None => Err(Error::NoParametersToApply), Some((head, _)) => { - let schema = definitions - .lookup(&head.schema) - .map(|s| { - Ok(Annotated { - title: s.title.clone().or_else(|| head.title.clone()), - description: s.description.clone(), - annotated: s.annotated.clone(), + let schema = match &head.schema { + Declaration::Inline(schema) => Annotated { + title: head.title.clone(), + description: None, + annotated: schema.as_ref().clone(), + }, + Declaration::Referenced(ref link) => definitions + .lookup(link) + .map(|s| { + Ok(Annotated { + title: s.title.clone().or_else(|| head.title.clone()), + description: s.description.clone(), + annotated: s.annotated.clone(), + }) }) - }) - .unwrap_or_else(|| { - Err(Error::UnresolvedSchemaReference { - reference: head.schema.clone(), - }) - })?; + .unwrap_or_else(|| { + Err(Error::UnresolvedSchemaReference { + reference: link.clone(), + }) + })?, + }; let data = ask(&schema, definitions)?; @@ -724,6 +736,19 @@ mod tests { ); } + #[test] + fn else_redeemer() { + assert_validator!( + r#" + validator always_true { + else(_) { + True + } + } + "# + ); + } + #[test] fn validate_arguments_integer() { let definitions = fixture_definitions(); @@ -732,7 +757,7 @@ mod tests { let param = Parameter { title: None, - schema: Reference::new("Int"), + schema: Declaration::Referenced(Reference::new("Int")), }; assert!(matches!(param.validate(&definitions, &term), Ok { .. })) @@ -746,7 +771,7 @@ mod tests { let param = Parameter { title: None, - schema: Reference::new("ByteArray"), + schema: Declaration::Referenced(Reference::new("ByteArray")), }; assert!(matches!(param.validate(&definitions, &term), Ok { .. })) diff --git a/crates/aiken-project/src/export.rs b/crates/aiken-project/src/export.rs index 99d3b3f2..45b4892e 100644 --- a/crates/aiken-project/src/export.rs +++ b/crates/aiken-project/src/export.rs @@ -3,7 +3,7 @@ use crate::{ self, definitions::Definitions, parameter::Parameter, - schema::{Annotated, Schema}, + schema::{Annotated, Declaration, Schema}, }, module::{CheckedModule, CheckedModules}, }; @@ -51,7 +51,7 @@ impl Export { ) .map(|schema| Parameter { title: Some(param.arg_name.get_label()), - schema, + schema: Declaration::Referenced(schema), }) .map_err(|error| blueprint::Error::Schema { error,