diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index 5ed44461..09e45680 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -415,8 +415,8 @@ mod test { "$ref": "#/definitions/test_module~1Input" } }, - "compiledCode": "5902aa01000032323232323232323232323232322223232533300c4a22930b1980619299980619b87480000044c8c8c8c8c8c94ccc05cc0640084cc04cc94ccc04ccdc3a400000226464a66603460380042930a9980ba481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a6034002602200c2a6602a9212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e7400163011005330133300c003232498dd7000a4c2a660289201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c602e002602e0046eb0c054004c054008c04c004c02801454cc0392412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300a0040043300b32533300b3370e90000008a99980818048018a4c2a6601a92011d4578706563746564206e6f206669656c647320666f7220436f6e73747200161533300b3370e90010008a99980818048018a4c2a6601a92011d4578706563746564206e6f206669656c647320666f7220436f6e73747200161533300b3370e90020008a99980818048018a4c2a6601a92011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300d4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e74001630090020023001001222533300d00214984cc024c004c038008ccc00c00cc03c008004cc0040052000222233330073370e00200601a4666600a00a66e000112002300f0010020022300737540024600a6ea80055cd2b9b5738aae7555cf2ab9f5742ae89", - "hash": "bef7fc82378088fbd29dda8c16b018424b5d73bfed7aaf591c7fbfc1", + "compiledCode": "5902ad0100003232323232323232323232322223232533300a4a22930b1980519919119299980699b87480000044c8c8c8c8c8c94ccc060c0680084cc050c94ccc050cdc3a400000226464a666036603a0042930a9980c2481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a6036002602400c2a6602c9212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e74001630120053301433009003232498dd7000a4c2a6602a9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c603000260300046eb0c058004c058008c050004c02c00854cc03d2412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300b0013001001222533301100214984cc034c004c048008ccc00c00cc04c008004010010cc024c94ccc024cdc3a40000022a66601c600e0062930a99805a4811d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153330093370e90010008a99980718038018a4c2a6601692011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153330093370e90020008a99980718038018a4c2a6601692011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300b4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300700200233001001480008888cccc01ccdc38008018069199980280299b8000448008c03c0040080088c01cdd5000918029baa0015734ae6d5ce2ab9d5573caae7d5d0aba201", + "hash": "dfd982261c46e048a8d2a7ffb45258d2e98ab88b563709a47d69e37d", "definitions": { "ByteArray": { "dataType": "bytes" @@ -680,8 +680,8 @@ mod test { "$ref": "#/definitions/test_module~1Dict$test_module~1UUID_Int" } }, - "compiledCode": "590119010000323232323232323232323232223253330084a22930b1980419299980419b87480000044c8c94ccc03cc0440084cc02ccc0180048c8c926375a60200046eb8c03800526153300c491334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163756601e00260186ea800c54cc0292412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300a37540040046002002444a66601600429309980398009806001199801801980680100099800800a40004444666600a66e1c00400c02c8cccc014014cdc000224004601a002004004ae695cdab9c5573aaae7955cfaba15745", - "hash": "7404377d39dac5f1daa00e60bb22397d81944d036a2466e3d51c10ba", + "compiledCode": "59011c01000032323232323232323232223253330064a22930b1980319919119299980499b87480000044c8c94ccc040c0480084cc030cc0140048c8c926375a60220046eb8c03c00526153300d491334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001637566020002601a6ea800854cc02d2412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300b37540026002002444a66601a00429309980498009807001199801801980780100080100119800800a40004444666600a66e1c00400c02c8cccc014014cdc000224004601a002004004ae695cdab9c5573aaae7955cfaba157441", + "hash": "6f4ac35fb024ddddca4ea209d49943096c735c1b2348d63983c5bf08", "definitions": { "ByteArray": { "dataType": "bytes" @@ -743,8 +743,8 @@ mod test { "$ref": "#/definitions/test_module~1Dict$test_module~1UUID_Int" } }, - "compiledCode": "585d010000323232323232323232223253330064a22930b1919803998020009191924c6eb4c02c008dd718048008009bab0023001001222533300800214984cc014c004c024008ccc00c00cc0280080055cd2b9b5573aaae7955cfaba15745", - "hash": "0d852f5a9ad295b4067d434fcfede80a56661e687e07424fad11c281", + "compiledCode": "585b01000032323232323232223253330044a22930b19198029999180080091129998058010a4c26601060026018004666006006601a00400200246464931bad3009002375c600e0020026eac0095cd2b9b5573aaae7955cfaba157441", + "hash": "96974ac55a06ba32cec8ba5d1f603a1c4e82a4ec9ef13b7bb838d7d9", "definitions": { "ByteArray": { "dataType": "bytes" @@ -850,8 +850,8 @@ mod test { "$ref": "#/definitions/test_module~1Expr" } }, - "compiledCode": "5901d601000032323232323232323232323232223253330094a22930b19804980180100118008009119299980399b87480000044c8c94ccc038c040008526153300b4901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a601c002600c0042a66600e66e1d20020011323232325333010301200213300c330070070033300c3300700700149854cc0352401334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630100013010002300e0013006002153330073370e900200089919191929998081809001099806198038038019980619803803800a4c2a6601a9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630100013010002300e001300600215330094912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300937540026600200290001111199980319b8700100300c233330050053370000890011807000801001118031baa0015734ae6d5ce2ab9d5573caae7d5d0aba21", - "hash": "c312bfeaf481c336f851eaf80acb056c0a26175e558b094a60de4cb3", + "compiledCode": "5901d30100003232323232323232323232223253330074a22930b1980399918008009119299980499b87480000044c8c94ccc040c048008526153300d491334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602000260100042a66601266e1d20020011323232325333012301400213300e330070070033300e3300700700149854cc03d2401334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163012001301200230100013008002153330093370e90020008991919192999809180a001099807198038038019980719803803800a4c2a6601e9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163012001301200230100013008002153300b4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300b37540020040046600200290001111199980319b8700100300c233330050053370000890011807000801001118031baa0015734ae6d5ce2ab9d5573caae7d5d0aba21", + "hash": "2fffd5b9f5a372ec180ebec76cecd630c7bfdf680a5ffd7353b67c18", "definitions": { "Int": { "dataType": "integer" @@ -941,8 +941,8 @@ mod test { "$ref": "#/definitions/test_module~1LinkedList$Int" } }, - "compiledCode": "590373010000323232323232323232323232323232323232222323253330104a22930b1980819299980819b87480000044c8c94ccc05cc0640084cc04cc0200052615330144901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163017001300e005153330103370e9001000899191919299980c980d801099191980b9980700091980c1808800a4c931bac3019002375c602e0022a6602c9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163232337606036004603600260360026eb0c064004c064008dd6980b80098070028a9980924812b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e0040043300f300800200230010012232533300c3370e9000000899191919299980a980b80109980899803803800a4c2a66024921334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016301500130150023370e900118081baa3013001300a0021533300c3370e90010008a99980898050010a4c2a6601c9211d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300e4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300a0013001001222533300f00214984cc02cc004c040008ccc00c00cc044008004c00400488c94ccc020cdc3a4000002264646464a666022602600426601a6600e00e002930a998072481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630110013011002375a601e002600c0042a66601066e1d20020011533300d3006002149854cc02924011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300a4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300600133001001480008888cccc01ccdc38008018069199980280299b8000448008c03c0040080088c01cdd5000918029baa0015734ae6d5ce2ab9d5573caae7d5d0aba21", - "hash": "39f12c7e94363986531f5661c912d91f99ecdd50955e1d6d049a1489", + "compiledCode": "59037601000032323232323232323232323222232323232533300c4a22930b19806199191919119299980899b87480000044c8c94ccc060c0680084cc050c01c0052615330154901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163018001300f002153330113370e9001000899191919299980d180e001099191980c1980480091980c9807800a4c931bac301a002375c60300022a6602e9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163232337606038004603800260380026eb0c068004c068008dd6980c00098078010a99809a4812b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300f0013001001222533301500214984cc044c004c058008ccc00c00cc05c008004c00400488c94ccc038cdc3a4000002264646464a66602e60320042660266600e00e002930a9980a2481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016301700130170023370e900118091baa3015001300c0021533300e3370e90010008a99980998060010a4c2a660209211d4578706563746564206e6f206669656c647320666f7220436f6e737472001615330104912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300c0010060063300b300100400430010012232533300b3370e9000000899191919299980a180b00109980819803803800a4c2a660229201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630140013014002375a602400260120042a66601666e1d2002001153330103009002149854cc03524011d4578706563746564206e6f206669656c647320666f7220436f6e7374720016153300d4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300900133001001480008888cccc01ccdc38008018069199980280299b8000448008c03c0040080088c01cdd5000918029baa0015734ae6d5ce2ab9d5573caae7d5d0aba21", + "hash": "2e61d226dd9f4d5cafda093e8156f7f574ca95d10bee886581dd4bc2", "definitions": { "Bool": { "title": "Bool", diff --git a/crates/aiken-project/src/tests/gen_uplc.rs b/crates/aiken-project/src/tests/gen_uplc.rs index 9e56b190..ff9f6858 100644 --- a/crates/aiken-project/src/tests/gen_uplc.rs +++ b/crates/aiken-project/src/tests/gen_uplc.rs @@ -1,16 +1,27 @@ +use std::sync::Arc; + use pretty_assertions::assert_eq; -use aiken_lang::ast::{Definition, Function}; +use aiken_lang::{ + ast::{Definition, Function, Validator}, + expr::TypedExpr, + tipo::Type as AikenType, +}; use uplc::{ - ast::{Constant, DeBruijn, Name, Program, Term, Type}, + ast::{Constant, Data, DeBruijn, Name, Program, Term, Type}, machine::cost_model::ExBudget, - optimize, BigInt, Constr, PlutusData, + optimize, }; use crate::module::CheckedModules; use super::TestProject; +enum TestType { + Func(Function, TypedExpr>), + Validator(Validator, TypedExpr>), +} + fn assert_uplc(source_code: &str, expected: Term, should_fail: bool) { let mut project = TestProject::new(); @@ -33,7 +44,13 @@ fn assert_uplc(source_code: &str, expected: Term, should_fail: bool) { scripts.push(( checked_module.input_path.clone(), checked_module.name.clone(), - func, + TestType::Func(func.clone()), + )); + } else if let Definition::Validator(func) = def { + scripts.push(( + checked_module.input_path.clone(), + checked_module.name.clone(), + TestType::Validator(func.clone()), )); } } @@ -42,31 +59,56 @@ fn assert_uplc(source_code: &str, expected: Term, should_fail: bool) { let script = &scripts[0]; - let Function { body, .. } = script.2; + match &script.2 { + TestType::Func(Function { body: func, .. }) => { + let program = generator.generate_test(func); - let program = generator.generate_test(body); + let debruijn_program: Program = program.try_into().unwrap(); - let debruijn_program: Program = program.try_into().unwrap(); + let expected = Program { + version: (1, 0, 0), + term: expected, + }; - let expected = Program { - version: (1, 0, 0), - term: expected, - }; + let expected = optimize::aiken_optimize_and_intern(expected); + println!("EXP {}", expected.to_pretty()); - let expected = optimize::aiken_optimize_and_intern(expected); + let expected: Program = expected.try_into().unwrap(); - let expected: Program = expected.try_into().unwrap(); + assert_eq!(debruijn_program.to_pretty(), expected.to_pretty()); - assert_eq!(debruijn_program.to_pretty(), expected.to_pretty()); + let mut eval = debruijn_program.eval(ExBudget::default()); - let mut eval = debruijn_program.eval(ExBudget::default()); + assert_eq!( + eval.failed(), + should_fail, + "logs - {}\n", + format!("{:#?}", eval.logs()) + ); - assert_eq!( - eval.failed(), - should_fail, - "logs - {}\n", - format!("{:#?}", eval.logs()) - ) + if !should_fail { + assert_eq!(eval.result().unwrap(), Term::bool(true)); + } + } + TestType::Validator(func) => { + let program = generator.generate(func); + + let debruijn_program: Program = program.try_into().unwrap(); + + let expected = Program { + version: (1, 0, 0), + term: expected, + }; + + let expected = optimize::aiken_optimize_and_intern(expected); + + println!("EXP {}", expected.to_pretty()); + + let expected: Program = expected.try_into().unwrap(); + + assert_eq!(debruijn_program.to_pretty(), expected.to_pretty()); + } + } } #[test] @@ -112,9 +154,9 @@ fn acceptance_test_1_length() { .lambda("length"), ) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), ])), ) .apply(Term::integer(3.into())), @@ -175,8 +217,8 @@ fn acceptance_test_2_repeat() { ), ) .apply(Term::list_data().apply(Term::list_values(vec![ - Constant::Data(PlutusData::BoundedBytes("aiken".as_bytes().to_vec().into())), - Constant::Data(PlutusData::BoundedBytes("aiken".as_bytes().to_vec().into())), + Constant::Data(Data::bytestring("aiken".as_bytes().to_vec())), + Constant::Data(Data::bytestring("aiken".as_bytes().to_vec())), ]))), false, ); @@ -254,24 +296,24 @@ fn acceptance_test_3_concat() { .lambda("foldr"), ) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), ])) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(4.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(5.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(6.into()))), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(5.into())), + Constant::Data(Data::integer(6.into())), ])), ), ) .apply(Term::list_data().apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(4.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(5.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(6.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(5.into())), + Constant::Data(Data::integer(6.into())), ]))), false, ); @@ -355,24 +397,24 @@ fn acceptance_test_4_concat_no_anon_func() { .lambda("foldr"), ) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), ])) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(4.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(5.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(6.into()))), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(5.into())), + Constant::Data(Data::integer(6.into())), ])), ), ) .apply(Term::list_data().apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(4.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(5.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(6.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(5.into())), + Constant::Data(Data::integer(6.into())), ]))), false, ); @@ -404,14 +446,7 @@ fn acceptance_test_5_head_not_empty() { .apply( Term::var("xs") .delayed_choose_list( - Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), - ), + Term::Constant(Constant::Data(Data::constr(1, vec![])).into()), Term::constr_data().apply(Term::integer(0.into())).apply( Term::mk_cons() .apply(Term::head_list().apply(Term::var("xs"))) @@ -421,18 +456,13 @@ fn acceptance_test_5_head_not_empty() { .lambda("xs"), ) .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), ])), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 121, - any_constructor: None, - fields: vec![PlutusData::BigInt(BigInt::Int(1.into()))], - })) - .into(), + Constant::Data(Data::constr(0, vec![Data::integer(1.into())])).into(), )), false, ); @@ -464,14 +494,7 @@ fn acceptance_test_5_head_empty() { .apply( Term::var("xs") .delayed_choose_list( - Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), - ), + Term::Constant(Constant::Data(Data::constr(1, vec![])).into()), Term::constr_data().apply(Term::integer(0.into())).apply( Term::mk_cons() .apply(Term::head_list().apply(Term::var("xs"))) @@ -483,12 +506,7 @@ fn acceptance_test_5_head_empty() { .apply(Term::list_values(vec![])), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), + Constant::Data(Data::constr(1, vec![])).into(), )), false, ); @@ -535,8 +553,8 @@ fn acceptance_test_6_equals() { Constant::ProtoPair( Type::Data, Type::Data, - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))).into(), - Constant::Data(PlutusData::Array(vec![])).into(), + Constant::Data(Data::integer(1.into())).into(), + Constant::Data(Data::list(vec![])).into(), ) .into(), )) @@ -550,8 +568,8 @@ fn acceptance_test_6_equals() { Constant::ProtoPair( Type::Data, Type::Data, - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))).into(), - Constant::Data(PlutusData::Array(vec![])).into(), + Constant::Data(Data::integer(1.into())).into(), + Constant::Data(Data::list(vec![])).into(), ) .into(), )) @@ -596,16 +614,9 @@ fn acceptance_test_7_unzip() { .apply( Term::var("xs") .delayed_choose_list( - Term::Constant( - Constant::ProtoPair( - Type::Data, - Type::Data, - Constant::Data(PlutusData::Array(vec![])) - .into(), - Constant::Data(PlutusData::Array(vec![])) - .into(), - ) - .into(), + Term::pair_values( + Constant::Data(Data::list(vec![])), + Constant::Data(Data::list(vec![])), ), Term::mk_pair_data() .apply( @@ -666,47 +677,34 @@ fn acceptance_test_7_unzip() { .apply( Term::map_data().apply( Term::mk_cons() - .apply(Term::Constant( - Constant::ProtoPair( - Type::Data, - Type::Data, - Constant::Data(PlutusData::Array(vec![ - PlutusData::BigInt(BigInt::Int(3.into())), - PlutusData::BigInt(BigInt::Int(4.into())), - ])) - .into(), - Constant::Data(PlutusData::Array(vec![ - PlutusData::BoundedBytes(vec![85].into()), - PlutusData::BoundedBytes(vec![119, 153].into()), - ])) - .into(), - ) - .into(), + .apply(Term::pair_values( + Constant::Data(Data::list(vec![ + Data::integer(3.into()), + Data::integer(4.into()), + ])), + Constant::Data(Data::list(vec![ + Data::bytestring(vec![85]), + Data::bytestring(vec![119, 153]), + ])), )) .apply(Term::empty_map()), ), ) .lambda("x") - .apply(Term::Constant( - Constant::ProtoList( - Type::Pair(Type::Data.into(), Type::Data.into()), - vec![ - Constant::ProtoPair( - Type::Data, - Type::Data, - Constant::Data(PlutusData::BigInt(BigInt::Int(3.into()))).into(), - Constant::Data(PlutusData::BoundedBytes(vec![85].into())).into(), - ), - Constant::ProtoPair( - Type::Data, - Type::Data, - Constant::Data(PlutusData::BigInt(BigInt::Int(4.into()))).into(), - Constant::Data(PlutusData::BoundedBytes(vec![119, 153].into())).into(), - ), - ], - ) - .into(), - )), + .apply(Term::map_values(vec![ + Constant::ProtoPair( + Type::Data, + Type::Data, + Constant::Data(Data::integer(3.into())).into(), + Constant::Data(Data::bytestring(vec![85])).into(), + ), + Constant::ProtoPair( + Type::Data, + Type::Data, + Constant::Data(Data::integer(4.into())).into(), + Constant::Data(Data::bytestring(vec![119, 153])).into(), + ), + ])), false, ); } @@ -842,14 +840,7 @@ fn acceptance_test_10_map_none() { .apply(Term::integer(1.into())) .apply(Term::var("constr_index")) .delayed_if_else( - Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), - ), + Term::Constant(Constant::Data(Data::constr(1, vec![])).into()), Term::constr_data() .apply(Term::integer(0.into())) .apply( @@ -881,12 +872,7 @@ fn acceptance_test_10_map_none() { .lambda("opt"), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), + Constant::Data(Data::constr(1, vec![])).into(), )) .apply( Term::var("add_one").lambda("add_one").apply( @@ -898,12 +884,7 @@ fn acceptance_test_10_map_none() { ), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), + Constant::Data(Data::constr(1, vec![])).into(), )) .constr_get_field(), false, @@ -942,14 +923,7 @@ fn acceptance_test_10_map_some() { .apply(Term::integer(1.into())) .apply(Term::var("constr_index")) .delayed_if_else( - Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 122, - any_constructor: None, - fields: vec![], - })) - .into(), - ), + Term::Constant(Constant::Data(Data::constr(1, vec![])).into()), Term::constr_data() .apply(Term::integer(0.into())) .apply( @@ -981,12 +955,7 @@ fn acceptance_test_10_map_some() { .lambda("opt"), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 121, - any_constructor: None, - fields: vec![PlutusData::BigInt(BigInt::Int(1.into()))], - })) - .into(), + Constant::Data(Data::constr(0, vec![Data::integer(1.into())])).into(), )) .apply( Term::var("add_one").lambda("add_one").apply( @@ -998,12 +967,7 @@ fn acceptance_test_10_map_some() { ), ) .apply(Term::Constant( - Constant::Data(PlutusData::Constr(Constr { - tag: 121, - any_constructor: None, - fields: vec![PlutusData::BigInt(BigInt::Int(2.into()))], - })) - .into(), + Constant::Data(Data::constr(0, vec![Data::integer(2.into())])).into(), )) .constr_get_field(), false, @@ -1030,8 +994,8 @@ fn expect_empty_list_on_filled_list() { ) .lambda("x") .apply(Term::list_values(vec![ - Constant::Data(PlutusData::BigInt(BigInt::Int(1.into()))), - Constant::Data(PlutusData::BigInt(BigInt::Int(2.into()))), + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), ])), true, ); @@ -1129,3 +1093,510 @@ fn when_bool_is_false() { true, ); } + +#[test] +fn acceptance_test_11_map_empty() { + let src = r#" + pub fn map(xs: List, f: fn(a) -> result) -> List { + when xs is { + [] -> + [] + [x, ..rest] -> + [f(x), ..map(rest, f)] + } + } + + test map_1() { + map([], fn(n) { n + 1 }) == [] + } + "#; + + assert_uplc( + src, + Term::equals_data() + .apply( + Term::list_data().apply( + Term::var("map") + .lambda("map") + .apply(Term::var("map").apply(Term::var("map"))) + .lambda("map") + .apply( + Term::var("xs") + .delayed_choose_list( + Term::empty_list(), + Term::mk_cons() + .apply( + Term::i_data() + .apply(Term::var("f").apply(Term::var("x"))), + ) + .apply( + Term::var("map") + .apply(Term::var("map")) + .apply(Term::var("rest")) + .apply(Term::var("f")), + ) + .lambda("rest") + .apply(Term::tail_list().apply(Term::var("xs"))) + .lambda("x") + .apply( + Term::un_i_data() + .apply(Term::head_list().apply(Term::var("xs"))), + ), + ) + .lambda("f") + .lambda("xs") + .lambda("map"), + ) + .apply(Term::empty_list()) + .apply( + Term::add_integer() + .apply(Term::var("n")) + .apply(Term::integer(1.into())) + .lambda("n"), + ), + ), + ) + .apply(Term::list_data().apply(Term::empty_list())), + false, + ); +} + +#[test] +fn acceptance_test_11_map_filled() { + let src = r#" + pub fn map(xs: List, f: fn(a) -> result) -> List { + when xs is { + [] -> + [] + [x, ..rest] -> + [f(x), ..map(rest, f)] + } + } + + test map_1() { + map([6, 7, 8], fn(n) { n + 1 }) == [7, 8, 9] + } + "#; + + assert_uplc( + src, + Term::equals_data() + .apply( + Term::list_data().apply( + Term::var("map") + .lambda("map") + .apply(Term::var("map").apply(Term::var("map"))) + .lambda("map") + .apply( + Term::var("xs") + .delayed_choose_list( + Term::empty_list(), + Term::mk_cons() + .apply( + Term::i_data() + .apply(Term::var("f").apply(Term::var("x"))), + ) + .apply( + Term::var("map") + .apply(Term::var("map")) + .apply(Term::var("rest")) + .apply(Term::var("f")), + ) + .lambda("rest") + .apply(Term::tail_list().apply(Term::var("xs"))) + .lambda("x") + .apply( + Term::un_i_data() + .apply(Term::head_list().apply(Term::var("xs"))), + ), + ) + .lambda("f") + .lambda("xs") + .lambda("map"), + ) + .apply(Term::list_values(vec![ + Constant::Data(Data::integer(6.into())), + Constant::Data(Data::integer(7.into())), + Constant::Data(Data::integer(8.into())), + ])) + .apply( + Term::add_integer() + .apply(Term::var("n")) + .apply(Term::integer(1.into())) + .lambda("n"), + ), + ), + ) + .apply(Term::list_data().apply(Term::list_values(vec![ + Constant::Data(Data::integer(7.into())), + Constant::Data(Data::integer(8.into())), + Constant::Data(Data::integer(9.into())), + ]))), + false, + ); +} + +#[test] +fn acceptance_test_12_filter_even() { + let src = r#" + use aiken/builtin + + pub fn filter(xs: List, f: fn(a) -> Bool) -> List { + when xs is { + [] -> + [] + [x, ..rest] -> + if f(x) { + [x, ..filter(rest, f)] + } else { + filter(rest, f) + } + } + } + + test filter_1() { + filter([1, 2, 3, 4, 5, 6], fn(x) { builtin.mod_integer(x, 2) == 0 }) == [2, 4, 6] + } + "#; + + assert_uplc( + src, + Term::equals_data() + .apply( + Term::list_data().apply( + Term::var("filter") + .lambda("filter") + .apply(Term::var("filter").apply(Term::var("filter"))) + .lambda("filter") + .apply( + Term::var("xs") + .delayed_choose_list( + Term::empty_list(), + Term::var("f") + .apply(Term::var("x")) + .delayed_if_else( + Term::mk_cons() + .apply(Term::i_data().apply(Term::var("x"))) + .apply( + Term::var("filter") + .apply(Term::var("filter")) + .apply(Term::var("rest")) + .apply(Term::var("f")), + ), + Term::var("filter") + .apply(Term::var("filter")) + .apply(Term::var("rest")) + .apply(Term::var("f")), + ) + .lambda("rest") + .apply(Term::tail_list().apply(Term::var("xs"))) + .lambda("x") + .apply( + Term::un_i_data() + .apply(Term::head_list().apply(Term::var("xs"))), + ), + ) + .lambda("f") + .lambda("xs") + .lambda("filter"), + ) + .apply(Term::list_values(vec![ + Constant::Data(Data::integer(1.into())), + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(3.into())), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(5.into())), + Constant::Data(Data::integer(6.into())), + ])) + .apply( + Term::equals_integer() + .apply( + Term::mod_integer() + .apply(Term::var("x")) + .apply(Term::integer(2.into())), + ) + .apply(Term::integer(0.into())) + .lambda("x"), + ), + ), + ) + .apply(Term::list_data().apply(Term::list_values(vec![ + Constant::Data(Data::integer(2.into())), + Constant::Data(Data::integer(4.into())), + Constant::Data(Data::integer(6.into())), + ]))), + false, + ); +} + +// #[test] +// fn acceptance_test_14_list_creation() { +// let src = r#" +// test foo() { +// [0 - 2, 0 - 1, 0] == [-2, -1, 0] +// } +// "#; + +// assert_uplc( +// src, +// Term::equals_data() +// .apply( +// Term::list_data().apply( +// Term::mk_cons() +// .apply( +// Term::i_data().apply( +// Term::sub_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::integer(2.into())), +// ), +// ) +// .apply( +// Term::mk_cons().apply( +// Term::i_data().apply( +// Term::sub_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::integer(1.into())), +// ), +// ), +// ) +// .apply( +// Term::mk_cons() +// .apply(Term::i_data().apply(Term::integer(0.into()))) +// .apply(Term::empty_list()), +// ), +// ), +// ) +// .apply(Term::list_data().apply(Term::list_values(vec![ +// Constant::Data(Data::integer((-2).into())), +// Constant::Data(Data::integer((-1).into())), +// Constant::Data(Data::integer(0.into())), +// ]))), +// false, +// ); +// } + +// #[test] +// fn when_tuple_deconstruction() { +// let src = r#" +// type Thing { +// idx: Int, +// } + +// type Datum { +// A(Thing) +// B +// } + +// type RedSpend { +// Spend(Int) +// Buy +// } + +// validator { +// fn spend(dat: Datum, red: RedSpend, ctx: Data) { +// when (dat, red) is { +// (A(a), Spend(x)) -> +// (a.idx == x)? +// (_, _) -> +// True +// } +// } +// } +// "#; + +// assert_uplc( +// src, +// Term::equals_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::var("constr_index_exposer").apply(Term::var("dat"))) +// .if_else( +// Term::equals_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::var("constr_index_exposer").apply(Term::var("red"))) +// .if_else( +// Term::equals_integer() +// .apply( +// Term::un_i_data().apply( +// Term::var("constr_get_field") +// .apply( +// Term::var("constr_fields_exposer") +// .apply(Term::var("a")), +// ) +// .apply(Term::integer(0.into())), +// ), +// ) +// .apply(Term::var("x")) +// .lambda("x") +// .apply( +// Term::un_i_data() +// .apply(Term::head_list().apply(Term::var("red_constr_fields"))), +// ) +// .lambda("red_constr_fields") +// .apply(Term::var("constr_fields_exposer").apply(Term::var("red"))) +// .delay(), +// Term::var("other_clauses"), +// ) +// .force() +// .lambda("a") +// .apply(Term::head_list().apply(Term::var("dat_constr_fields"))) +// .lambda("dat_constr_fields") +// .apply(Term::var("constr_fields_exposer").apply(Term::var("dat"))) +// .delay(), +// Term::var("other_clauses"), +// ) +// .force() +// .lambda("other_clauses") +// .apply(Term::bool(true).delay()) +// .lambda("dat") +// .apply(Term::fst_pair().apply(Term::var("pair_subject"))) +// .lambda("red") +// .apply(Term::snd_pair().apply(Term::var("pair_subject"))) +// .lambda("pair_subject") +// .apply( +// Term::mk_pair_data() +// .apply(Term::var("dat")) +// .apply(Term::var("red")), +// ) +// .delayed_if_else(Term::unit(), Term::Error) +// .lambda("dat") +// .apply( +// Term::var("expect_Datum") +// .lambda("expect_Datum") +// .apply( +// Term::equals_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::var("constr_index_exposer").apply(Term::var("dat"))) +// .delayed_if_else( +// Term::tail_list() +// .apply(Term::var("dat_constr_fields")) +// .delayed_choose_list( +// Term::var("expect_Thing") +// .apply(Term::var("field_1")) +// .choose_unit(Term::unit()) +// .lambda("field_1") +// .apply( +// Term::head_list() +// .apply(Term::var("dat_constr_fields")), +// ), +// Term::Error.trace(Term::string("Expected...")), +// ) +// .lambda("dat_constr_fields") +// .apply( +// Term::var("constr_fields_exposer").apply(Term::var("dat")), +// ), +// Term::equals_integer() +// .apply(Term::integer(1.into())) +// .apply( +// Term::var("constr_index_exposer").apply(Term::var("dat")), +// ) +// .delayed_if_else( +// Term::unit().lambda("_").apply( +// Term::var("constr_fields_exposer") +// .apply(Term::var("dat")) +// .delayed_choose_list( +// Term::unit(), +// Term::Error +// .trace(Term::string("Expected......")), +// ), +// ), +// Term::Error.trace(Term::string("Expected...")), +// ), +// ) +// .lambda("dat"), +// ) +// .lambda("expect_Thing") +// .apply( +// Term::equals_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::var("constr_index_exposer").apply(Term::var("field_1"))) +// .delayed_if_else( +// Term::tail_list() +// .apply(Term::var("field_1_constr_fields")) +// .delayed_choose_list( +// Term::unit().lambda("_").apply( +// Term::un_i_data().apply( +// Term::head_list() +// .apply(Term::var("field_1_constr_fields")), +// ), +// ), +// Term::Error.trace(Term::string("Expected...")), +// ) +// .lambda("field_1_constr_fields") +// .apply( +// Term::var("constr_fields_exposer") +// .apply(Term::var("field_1")), +// ), +// Term::Error.trace(Term::string("Expected...")), +// ) +// .lambda("field_1"), +// ) +// .apply(Term::var("dat")) +// .choose_unit(Term::var("dat")), +// ) +// .lambda("red") +// .apply( +// Term::var("expect_RedSpend") +// .lambda("expect_RedSpend") +// .apply( +// Term::equals_integer() +// .apply(Term::integer(0.into())) +// .apply(Term::var("constr_index_exposer").apply(Term::var("red"))) +// .delayed_if_else( +// Term::tail_list() +// .apply(Term::var("red_constr_fields")) +// .delayed_choose_list( +// Term::unit().lambda("_").apply(Term::un_i_data().apply( +// Term::head_list().apply(Term::var("red_constr_fields")), +// )), +// Term::Error.trace(Term::string("Too many items")), +// ) +// .lambda("red_constr_fields") +// .apply( +// Term::var("constr_fields_exposer").apply(Term::var("red")), +// ), +// Term::equals_integer() +// .apply(Term::integer(1.into())) +// .apply( +// Term::var("constr_index_exposer").apply(Term::var("red")), +// ) +// .delayed_if_else( +// Term::var("constr_fields_exposer") +// .apply(Term::var("red")) +// .delayed_choose_list( +// Term::unit(), +// Term::Error.trace(Term::string("Expected......")), +// ), +// Term::Error.trace(Term::string("Expected...")), +// ), +// ) +// .lambda("red"), +// ) +// .apply(Term::var("red")) +// .choose_unit(Term::var("red")), +// ) +// .lambda("ctx") +// .lambda("red") +// .lambda("dat") +// .lambda("constr_get_field") +// .apply( +// Term::var("constr_get_field") +// .apply(Term::var("constr_get_field")) +// .apply(Term::integer(0.into())), +// ) +// .lambda("constr_get_field") +// .apply(Term::bool(false).lambda("x")) +// .lambda("constr_fields_exposer") +// .apply( +// Term::snd_pair() +// .apply(Term::unconstr_data().apply(Term::var("x"))) +// .lambda("x"), +// ) +// .lambda("constr_index_exposer") +// .apply( +// Term::fst_pair() +// .apply(Term::unconstr_data().apply(Term::var("x"))) +// .lambda("x"), +// ), +// false, +// ); +// } diff --git a/crates/uplc/src/builder.rs b/crates/uplc/src/builder.rs index b24e0280..02831aca 100644 --- a/crates/uplc/src/builder.rs +++ b/crates/uplc/src/builder.rs @@ -63,6 +63,18 @@ impl Term { ) } + pub fn map_values(vals: Vec) -> Self { + Term::Constant( + Constant::ProtoList(Type::Pair(Type::Data.into(), Type::Data.into()), vals).into(), + ) + } + + pub fn pair_values(fst_val: Constant, snd_val: Constant) -> Self { + Term::Constant( + Constant::ProtoPair(Type::Data, Type::Data, fst_val.into(), snd_val.into()).into(), + ) + } + pub fn constr_data() -> Self { Term::Builtin(DefaultFunction::ConstrData) } @@ -135,6 +147,14 @@ impl Term { Term::Builtin(DefaultFunction::SubtractInteger) } + pub fn div_integer() -> Self { + Term::Builtin(DefaultFunction::DivideInteger) + } + + pub fn mod_integer() -> Self { + Term::Builtin(DefaultFunction::ModInteger) + } + pub fn length_of_bytearray() -> Self { Term::Builtin(DefaultFunction::LengthOfByteString) } diff --git a/examples/acceptance_tests/071/plutus.json b/examples/acceptance_tests/071/plutus.json index 69f75a1d..4b39fedf 100644 --- a/examples/acceptance_tests/071/plutus.json +++ b/examples/acceptance_tests/071/plutus.json @@ -19,8 +19,8 @@ "$ref": "#/definitions/spend~1PoolRedeemer" } }, - "compiledCode": "59073201000032323232323232323232323232322223232533300b3232323232323253330123370e90000008992513010007153330123370e9001000899191919299980b19b87480080044c8c8c8c8c8c8c9289811800980c99299980e19b8748000c06c004400454cc07924012a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300d0130033021001301732533301a3370e9000180c80088008a9980e24812a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300a011001300848901ff00301e001301400214a060280026602060240189001180d0009808003899191919299980b19b87480080044c8c8c8c8c8c8c9289811800980c99299980e19b8748000c06c004400454cc0792412a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300d0130033021001301732533301a3370e9000180c80088008a9980e24812a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300a011001300848901ff00301e001301400214a060280026602060240189001180d00098080039808003119ba548000cc05ccdd2a40046602e6ea40052f5c06602e98103d87a80004bd7011198021bac3300d300f3300d300f00248001200423375e6601c6020002900000111198019bac3300c300e3300c300e00248001200023375e6601a601e6601a601e0029001240000046002002444a6660280042980103d87a8000132325333011300300213374a90001980b80125eb804ccc01401400400cc06000cc058008cc01cc0240092000149858cc02cc94ccc02ccdc3a40000022646464646464a66602c6032004266024601800a930a99809a481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602e002602e0046eb4c054004c054008c04c004c02401454cc0352412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e74001630090040043300a32533300a3370e9000000899192999808980a00109980699299980699b87480000044c8c94ccc050c05c00852615330114901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602a00260160042a66601a66e1d200200113232533301430170021330103253330103370e9000000899191919299980c980e00109980a9807801a4c2a6602c9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a603400260340046030002601c0042a660249212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e00149854cc045241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163015001300b0021533300d3370e900200089919299980a180b80109980819299980819b87480000044c8c8c8c94ccc064c0700084cc054c03c00d2615330164901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a603400260340046030002601c0042a660249212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e00149854cc045241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163015001300b002153300f4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300b00149854cc039241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630120013008003153300c4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300800200223253330073370e9000000899191919299980818098010a4c2a6601a9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c602200260220046eb8c03c004c01400854cc0252412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300500133001001480008888cccc01ccdc38008018071199980280299b8000448008c0400040080088c01cdd5000918029baa0015734ae6d5ce2ab9d5573caae7d5d02ba157441", - "hash": "29d411f954df2e5843e8d4ba7cb8561302b0971fb346c02a9a61956b" + "compiledCode": "59073201000032323232323232323232323232222323232533300b3232323232323253330123370e90000008992513010007153330123370e9001000899191919299980b19b87480080044c8c8c8c8c8c8c9289811800980c99299980e19b8748000c06c004400454cc07924012a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300d0140033021001301732533301a3370e9000180c80088008a9980e24812a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300a012001300848901ff00301e001301400214a0602800266020602401a9001180d0009808003899191919299980b19b87480080044c8c8c8c8c8c8c9289811800980c99299980e19b8748000c06c004400454cc0792412a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300d0140033021001301732533301a3370e9000180c80088008a9980e24812a4578706563746564206f6e20696e636f727265637420636f6e7374727563746f722076617269616e742e00163300a012001300848901ff00301e001301400214a0602800266020602401a9001180d00098080039808003119ba548000cc05ccdd2a40046602e6ea40052f5c06602e98103d87a80004bd7011198021bac3300d300f3300d300f00248001200423375e6601c6020002900000111198019bac3300c300e3300c300e00248001200023375e6601a601e6601a601e0029001240000046002002444a6660280042980103d87a8000132325333011300300213374a90001980b80125eb804ccc01401400400cc06000cc058008cc01cc0240092000149858cc02cc94ccc02ccdc3a40000022646464646464a66602c6032004266024601200a930a99809a481334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602e002602e0046eb4c054004c054008c04c004c02401854cc0352412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e74001630090050053300a32533300a3370e9000000899192999808980a00109980699299980699b87480000044c8c94ccc050c05c00852615330114901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a602a00260160042a66601a66e1d200200113232533301430170021330103253330103370e9000000899191919299980c980e00109980a9806001a4c2a6602c9201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a603400260340046030002601c0042a660249212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e00149854cc045241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163015001300b0021533300d3370e900200089919299980a180b80109980819299980819b87480000044c8c8c8c94ccc064c0700084cc054c03000d2615330164901334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375a603400260340046030002601c0042a660249212b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300e00149854cc045241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e20657870656374656400163015001300b002153300f4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300b00149854cc039241334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e206578706563746564001630120013008004153300c4912b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e7400163008003003232533300a3370e90000008991919192999809980b0010a4c2a660209201334c6973742f5475706c652f436f6e73747220636f6e7461696e73206d6f7265206974656d73207468616e2065787065637465640016375c602800260280046eb8c048004c02000854cc0312412b436f6e73747220696e64657820646964206e6f74206d6174636820616e7920747970652076617269616e740016300800133001001480008888cccc01ccdc38008018071199980280299b8000448008c0400040080088c01cdd5000918029baa0015734ae6d5ce2ab9d5573caae7d5d02ba157441", + "hash": "e5eb76a233e7d81172fb991975806b3adcc16ddf1cc3297ab5cf9a7a" } ], "definitions": {