Generate empty redeemer for `else` handler, to keep full compliance with the blueprint spec

This commit is contained in:
KtorZ 2024-10-01 19:03:34 +02:00
parent e8d97028ad
commit 513ca27717
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
5 changed files with 75 additions and 32 deletions

View File

@ -8,6 +8,7 @@
### Changed ### 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**: 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 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 - **aiken-lang**: Fix redundant warning on introduced identifiers when destructuring validator params. @KtorZ

View File

@ -14,14 +14,14 @@ pub struct Parameter {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>, pub title: Option<String>,
pub schema: Reference, pub schema: Declaration<Schema>,
} }
impl From<Reference> for Parameter { impl From<Reference> for Parameter {
fn from(schema: Reference) -> Parameter { fn from(schema: Reference) -> Parameter {
Parameter { Parameter {
title: None, title: None,
schema, schema: Declaration::Referenced(schema),
} }
} }
} }
@ -32,15 +32,20 @@ impl Parameter {
definitions: &Definitions<Annotated<Schema>>, definitions: &Definitions<Annotated<Schema>>,
constant: &Constant, constant: &Constant,
) -> Result<(), Error> { ) -> Result<(), Error> {
let schema = &definitions let schema = match &self.schema {
.lookup(&self.schema) Declaration::Inline(schema) => schema,
Declaration::Referenced(ref link) => {
&definitions
.lookup(link)
.map(Ok) .map(Ok)
.unwrap_or_else(|| { .unwrap_or_else(|| {
Err(Error::UnresolvedSchemaReference { Err(Error::UnresolvedSchemaReference {
reference: self.schema.clone(), reference: link.clone(),
}) })
})? })?
.annotated; .annotated
}
};
validate_schema(schema, definitions, constant) validate_schema(schema, definitions, constant)
} }

View File

@ -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": "<redacted>",
"hash": "<redacted>"
}

View File

@ -3,7 +3,7 @@ use super::{
error::Error, error::Error,
memo_program::MemoProgram, memo_program::MemoProgram,
parameter::Parameter, parameter::Parameter,
schema::{Annotated, Schema}, schema::{Annotated, Data, Declaration, Schema},
}; };
use crate::module::{CheckedModule, CheckedModules}; use crate::module::{CheckedModule, CheckedModules};
use aiken_lang::{ use aiken_lang::{
@ -111,7 +111,7 @@ impl Validator {
) )
.map(|schema| Parameter { .map(|schema| Parameter {
title: Some(param.arg_name.get_label()), title: Some(param.arg_name.get_label()),
schema, schema: Declaration::Referenced(schema),
}) })
.map_err(|error| Error::Schema { .map_err(|error| Error::Schema {
error, error,
@ -173,7 +173,7 @@ impl Validator {
.transpose()? .transpose()?
.map(|schema| Parameter { .map(|schema| Parameter {
title: datum.map(|datum| datum.arg_name.get_label()), title: datum.map(|datum| datum.arg_name.get_label()),
schema, schema: Declaration::Referenced(schema),
}); });
let redeemer = Annotated::from_type( let redeemer = Annotated::from_type(
@ -191,12 +191,17 @@ impl Validator {
}) })
.map(|schema| Parameter { .map(|schema| Parameter {
title: Some(redeemer.arg_name.get_label()), title: Some(redeemer.arg_name.get_label()),
schema, schema: Declaration::Referenced(schema),
})?; })?;
(datum, Some(redeemer)) (datum, Some(redeemer))
}; };
let redeemer = redeemer.or(Some(Parameter {
title: None,
schema: Declaration::Inline(Box::new(Schema::Data(Data::Opaque))),
}));
Ok(Validator { Ok(Validator {
title: format!("{}.{}.{}", &module.name, &def.name, &func.name,), title: format!("{}.{}.{}", &module.name, &def.name, &func.name,),
description: func.doc.clone(), description: func.doc.clone(),
@ -266,8 +271,14 @@ impl Validator {
match self.parameters.split_first() { match self.parameters.split_first() {
None => Err(Error::NoParametersToApply), None => Err(Error::NoParametersToApply),
Some((head, _)) => { Some((head, _)) => {
let schema = definitions let schema = match &head.schema {
.lookup(&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| { .map(|s| {
Ok(Annotated { Ok(Annotated {
title: s.title.clone().or_else(|| head.title.clone()), title: s.title.clone().or_else(|| head.title.clone()),
@ -277,9 +288,10 @@ impl Validator {
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
Err(Error::UnresolvedSchemaReference { Err(Error::UnresolvedSchemaReference {
reference: head.schema.clone(), reference: link.clone(),
}) })
})?; })?,
};
let data = ask(&schema, definitions)?; let data = ask(&schema, definitions)?;
@ -724,6 +736,19 @@ mod tests {
); );
} }
#[test]
fn else_redeemer() {
assert_validator!(
r#"
validator always_true {
else(_) {
True
}
}
"#
);
}
#[test] #[test]
fn validate_arguments_integer() { fn validate_arguments_integer() {
let definitions = fixture_definitions(); let definitions = fixture_definitions();
@ -732,7 +757,7 @@ mod tests {
let param = Parameter { let param = Parameter {
title: None, title: None,
schema: Reference::new("Int"), schema: Declaration::Referenced(Reference::new("Int")),
}; };
assert!(matches!(param.validate(&definitions, &term), Ok { .. })) assert!(matches!(param.validate(&definitions, &term), Ok { .. }))
@ -746,7 +771,7 @@ mod tests {
let param = Parameter { let param = Parameter {
title: None, title: None,
schema: Reference::new("ByteArray"), schema: Declaration::Referenced(Reference::new("ByteArray")),
}; };
assert!(matches!(param.validate(&definitions, &term), Ok { .. })) assert!(matches!(param.validate(&definitions, &term), Ok { .. }))

View File

@ -3,7 +3,7 @@ use crate::{
self, self,
definitions::Definitions, definitions::Definitions,
parameter::Parameter, parameter::Parameter,
schema::{Annotated, Schema}, schema::{Annotated, Declaration, Schema},
}, },
module::{CheckedModule, CheckedModules}, module::{CheckedModule, CheckedModules},
}; };
@ -51,7 +51,7 @@ impl Export {
) )
.map(|schema| Parameter { .map(|schema| Parameter {
title: Some(param.arg_name.get_label()), title: Some(param.arg_name.get_label()),
schema, schema: Declaration::Referenced(schema),
}) })
.map_err(|error| blueprint::Error::Schema { .map_err(|error| blueprint::Error::Schema {
error, error,