From 2523816813d294d8cf9208eb4d246b95ca573312 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Sun, 29 Jan 2023 10:33:50 +0100 Subject: [PATCH] Handle opaque single-variant-single-field special case. --- crates/aiken-project/src/blueprint/schema.rs | 24 +++++++-- .../aiken-project/src/blueprint/validator.rs | 52 +++++++++++++++---- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/crates/aiken-project/src/blueprint/schema.rs b/crates/aiken-project/src/blueprint/schema.rs index 79802433..d4a6508b 100644 --- a/crates/aiken-project/src/blueprint/schema.rs +++ b/crates/aiken-project/src/blueprint/schema.rs @@ -160,12 +160,19 @@ impl Annotated { let generic = Annotated::from_type(modules, args.get(0).unwrap(), type_parameters)?; - let generic = match generic.annotated { + // NOTE: Lists of 2-tuples are treated as Maps. This is an oddity we inherit + // from the PlutusTx / LedgerApi Haskell codebase, which encodes some elements + // as such. We don't have a concept of language maps in Aiken, so we simply + // make all types abide by this convention. + let data = match generic.annotated { Schema::Pair(left, right) => Data::Map(Box::new(left), Box::new(right)), - _ => generic.into_data(type_info)?.annotated, + _ => { + let inner = generic.into_data(type_info)?.annotated; + Data::List(Box::new(inner)) + } }; - Ok(Schema::Data(Some(Data::List(Box::new(generic)))).into()) + Ok(Schema::Data(Some(data)).into()) } _ => Err(Error::UnsupportedType { @@ -284,6 +291,17 @@ impl Data { variants.push(variant); } + + // NOTE: Opaque data-types with a single variant and a single field are transparent, they + // are erased completely at compilation time. + if data_type.opaque { + if let [variant] = &variants[..] { + if let [field] = &variant.annotated.fields[..] { + return Ok(field.annotated.clone()); + } + } + } + Ok(Data::AnyOf(variants)) } } diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index a337d14d..ff6374af 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -531,7 +531,7 @@ mod test { } #[test] - fn validator_phantom_and_opaque_types() { + fn validator_phantom_types() { assert_validator( r#" type Dict { @@ -559,15 +559,12 @@ mod test { "fields": [ { "title": "inner", - "dataType": "list", - "items": { - "dataType": "map", - "keys": { - "dataType": "bytes" - }, - "values": { - "dataType": "integer" - } + "dataType": "map", + "keys": { + "dataType": "bytes" + }, + "values": { + "dataType": "integer" } } ] @@ -579,4 +576,39 @@ mod test { ), ); } + + #[test] + fn validator_opaque_types() { + assert_validator( + r#" + pub opaque type Dict { + inner: List<(ByteArray, value)> + } + + type UUID { UUID } + + fn mint(redeemer: Dict, ctx: Void) { + True + } + "#, + json!( + { + "title": "test_module", + "purpose": "mint", + "hash": "da4a98cee05a17be402b07c414d59bf894c9ebd0487186417121de8f", + "redeemer": { + "title": "Dict", + "dataType": "map", + "keys": { + "dataType": "bytes" + }, + "values": { + "dataType": "integer" + } + }, + "compiledCode": "581d010000210872656465656d657200210363747800533357349445261601" + } + ), + ); + } }