From c493ff917599b85b584da6429aa5a65f8769ec12 Mon Sep 17 00:00:00 2001 From: SIDANWhatever Date: Mon, 27 Nov 2023 00:19:37 +0800 Subject: [PATCH] feat: refactoring code for integration tests --- lib/aiken-content-ownership/types.ak | 14 + .../validators/content_registry_ref_token.ak | 73 +++++ .../validators/one_time_minting_policy.ak | 32 +++ .../validators/oracle_validator.ak | 75 +++++ .../ownership_registry_ref_token.ak | 73 +++++ plutus.json | 80 ++++-- validators/content_registry.ak | 22 ++ validators/content_registry_ref_token.ak | 263 +----------------- validators/one_time_minting_policy.ak | 118 +------- validators/oracle_validator.ak | 73 +---- .../unit-tests/content_registry_ref_token.ak | 202 ++++++++++++++ .../unit-tests/one_time_minting_policy.ak | 92 ++++++ .../tests/unit-tests/oracle_validator.ak | 86 ++++++ .../ownership_registry_ref_token.ak | 202 ++++++++++++++ 14 files changed, 944 insertions(+), 461 deletions(-) create mode 100644 lib/aiken-content-ownership/validators/content_registry_ref_token.ak create mode 100644 lib/aiken-content-ownership/validators/one_time_minting_policy.ak create mode 100644 lib/aiken-content-ownership/validators/oracle_validator.ak create mode 100644 lib/aiken-content-ownership/validators/ownership_registry_ref_token.ak create mode 100644 validators/tests/unit-tests/content_registry_ref_token.ak create mode 100644 validators/tests/unit-tests/one_time_minting_policy.ak create mode 100644 validators/tests/unit-tests/oracle_validator.ak create mode 100644 validators/tests/unit-tests/ownership_registry_ref_token.ak diff --git a/lib/aiken-content-ownership/types.ak b/lib/aiken-content-ownership/types.ak index 04c047b..319bef6 100644 --- a/lib/aiken-content-ownership/types.ak +++ b/lib/aiken-content-ownership/types.ak @@ -32,7 +32,21 @@ pub type ContentRegistryDatum { registry: Dict, } +pub type ContentRegistryRedeemer { + CreateContent { content_hash: ByteArray } + StopContentRegistry +} + pub type OwnershipRegistryDatum { count: Int, registry: Dict, } + +pub type OwnershipRegistryRedeemer { + CreateOwnershipRecord { owner_token: (PolicyId, AssetName) } + TransferOwnership { + new_owner_toen: (PolicyId, AssetName), + content_number: Int, + } + StopOwnershipRegistry +} diff --git a/lib/aiken-content-ownership/validators/content_registry_ref_token.ak b/lib/aiken-content-ownership/validators/content_registry_ref_token.ak new file mode 100644 index 0000000..fe0d32d --- /dev/null +++ b/lib/aiken-content-ownership/validators/content_registry_ref_token.ak @@ -0,0 +1,73 @@ +use aiken/dict +// use aiken/list +use aiken/transaction.{ + InlineDatum, Input, Mint, Output, ScriptContext, Transaction, +} +use aiken/transaction/value.{PolicyId} +use aiken_content_ownership/common.{ + check_policy_only_burn, inputs_with, outputs_at_with, value_length, +} +use aiken_content_ownership/types.{ + ContentRegistryDatum, MintPolarity, OracleDatum, RBurn, RMint, +} +use aiken_content_ownership/utils.{get_registry_token_name} + +pub fn content_registry_ref_token_logic( + oracle_nft: PolicyId, + redeemer: MintPolarity, + context: ScriptContext, +) -> Bool { + let ScriptContext { purpose, transaction } = context + let Transaction { inputs, outputs, mint, .. } = transaction + when purpose is { + Mint(current_policy) -> + when (redeemer, inputs_with(inputs, oracle_nft, "")) is { + (RMint, [oracle_input]) -> { + expect InlineDatum(inline_datum) = oracle_input.output.datum + expect input_datum: OracleDatum = inline_datum + let OracleDatum { + oracle_address, + content_registry_ref_token, + content_registry_address, + content_registry_count, + .. + } = input_datum + when + ( + outputs_at_with(outputs, oracle_address, oracle_nft, ""), + outputs_at_with( + outputs, + content_registry_address, + content_registry_ref_token, + get_registry_token_name(content_registry_count), + ), + ) + is { + ([oracle_output], [registry_output]) -> { + expect InlineDatum(raw_oracle_datum) = oracle_output.datum + expect InlineDatum(raw_registry_datum) = registry_output.datum + expect oracle_datum: OracleDatum = raw_oracle_datum + expect ContentRegistryDatum { count, registry }: ContentRegistryDatum = + raw_registry_datum + let oracle_datum_updated = + oracle_datum == OracleDatum { + ..input_datum, + content_registry_count: content_registry_count + 1, + } + let registry_initial_datum_correct = + count == 0 && registry == dict.new() + let oracle_output_value_clean = + value_length(oracle_output.value) == 2 + let registry_output_value_clean = + value_length(registry_output.value) == 2 + oracle_datum_updated && registry_initial_datum_correct && oracle_output_value_clean && registry_output_value_clean + } + _ -> False + } + } + (RBurn, _) -> check_policy_only_burn(mint, current_policy) + _ -> False + } + _ -> False + } +} diff --git a/lib/aiken-content-ownership/validators/one_time_minting_policy.ak b/lib/aiken-content-ownership/validators/one_time_minting_policy.ak new file mode 100644 index 0000000..060d976 --- /dev/null +++ b/lib/aiken-content-ownership/validators/one_time_minting_policy.ak @@ -0,0 +1,32 @@ +use aiken/list +use aiken/transaction.{Input, Mint, OutputReference, ScriptContext, Transaction} +use aiken_content_ownership/common.{check_policy_only_burn} +use aiken_content_ownership/types.{MintPolarity, RBurn, RMint} + +pub fn one_time_minting_policy_logic( + utxo_ref: OutputReference, + redeemer: MintPolarity, + context: ScriptContext, +) -> Bool { + let ScriptContext { purpose, transaction } = context + when purpose is { + Mint(current_policy) -> + when redeemer is { + RMint -> { + let Transaction { inputs, .. } = transaction + let hash_equal = + fn(input: Input) { + let hash = input.output_reference + utxo_ref == hash + } + let target_input_exist = list.find(inputs, hash_equal) + when target_input_exist is { + Some(_) -> True + None -> False + } + } + RBurn -> check_policy_only_burn(transaction.mint, current_policy) + } + _ -> False + } +} diff --git a/lib/aiken-content-ownership/validators/oracle_validator.ak b/lib/aiken-content-ownership/validators/oracle_validator.ak new file mode 100644 index 0000000..8e89462 --- /dev/null +++ b/lib/aiken-content-ownership/validators/oracle_validator.ak @@ -0,0 +1,75 @@ +use aiken/transaction.{InlineDatum, Output, ScriptContext, Spend, Transaction} +use aiken_content_ownership/common.{ + all_key_signed, key_signed, only_minted_token, outputs_at_with, +} +use aiken_content_ownership/types.{ + CreateContentRegistry, CreateOwnershipRegistry, OracleDatum, RotateKey, + StopApp, +} +use aiken_content_ownership/utils.{get_registry_token_name} + +pub fn oracle_validator_logic(datum, redeemer, context) { + let ScriptContext { purpose, transaction } = context + when purpose is { + Spend(_) -> { + let Transaction { outputs, mint, extra_signatories, .. } = transaction + let OracleDatum { + oracle_nft, + oracle_address, + content_registry_ref_token, + content_registry_count, + ownership_registry_ref_token, + ownership_registry_count, + operation_key, + stop_key, + .. + } = datum + + when redeemer is { + CreateContentRegistry -> + // Ref token is minted + only_minted_token( + mint, + content_registry_ref_token, + get_registry_token_name(content_registry_count), + 1, + ) + + CreateOwnershipRegistry -> + // Ref token is minted + only_minted_token( + mint, + ownership_registry_ref_token, + get_registry_token_name(ownership_registry_count), + 1, + ) + RotateKey { new_operation_key, new_stop_key } -> { + // Sign by both ops and stop key + expect [own_output] = + outputs_at_with(outputs, oracle_address, oracle_nft, "") + expect InlineDatum(dat) = own_output.datum + expect own_datum: OracleDatum = dat + let datum_correct = + own_datum == OracleDatum { + ..datum, + operation_key: new_operation_key, + stop_key: new_stop_key, + } + all_key_signed(extra_signatories, [operation_key, stop_key]) && datum_correct + } + + // datum update correctly (key rotated) + StopApp -> + // signed by stop key + // oracle nft is burned + key_signed(extra_signatories, stop_key) && only_minted_token( + mint, + oracle_nft, + "", + -1, + ) + } + } + _ -> False + } +} diff --git a/lib/aiken-content-ownership/validators/ownership_registry_ref_token.ak b/lib/aiken-content-ownership/validators/ownership_registry_ref_token.ak new file mode 100644 index 0000000..903cc88 --- /dev/null +++ b/lib/aiken-content-ownership/validators/ownership_registry_ref_token.ak @@ -0,0 +1,73 @@ +use aiken/dict +// use aiken/list +use aiken/transaction.{ + InlineDatum, Input, Mint, Output, ScriptContext, Transaction, +} +use aiken/transaction/value.{PolicyId} +use aiken_content_ownership/common.{ + check_policy_only_burn, inputs_with, outputs_at_with, value_length, +} +use aiken_content_ownership/types.{ + MintPolarity, OracleDatum, OwnershipRegistryDatum, RBurn, RMint, +} +use aiken_content_ownership/utils.{get_registry_token_name} + +pub fn ownership_registry_ref_token_logic( + oracle_nft: PolicyId, + redeemer: MintPolarity, + context: ScriptContext, +) -> Bool { + let ScriptContext { purpose, transaction } = context + let Transaction { inputs, outputs, mint, .. } = transaction + when purpose is { + Mint(current_policy) -> + when (redeemer, inputs_with(inputs, oracle_nft, "")) is { + (RMint, [oracle_input]) -> { + expect InlineDatum(inline_datum) = oracle_input.output.datum + expect input_datum: OracleDatum = inline_datum + let OracleDatum { + oracle_address, + ownership_registry_ref_token, + ownership_registry_address, + ownership_registry_count, + .. + } = input_datum + when + ( + outputs_at_with(outputs, oracle_address, oracle_nft, ""), + outputs_at_with( + outputs, + ownership_registry_address, + ownership_registry_ref_token, + get_registry_token_name(ownership_registry_count), + ), + ) + is { + ([oracle_output], [registry_output]) -> { + expect InlineDatum(raw_oracle_datum) = oracle_output.datum + expect InlineDatum(raw_registry_datum) = registry_output.datum + expect oracle_datum: OracleDatum = raw_oracle_datum + expect OwnershipRegistryDatum { count, registry }: OwnershipRegistryDatum = + raw_registry_datum + let oracle_datum_updated = + oracle_datum == OracleDatum { + ..input_datum, + ownership_registry_count: ownership_registry_count + 1, + } + let registry_initial_datum_correct = + count == 0 && registry == dict.new() + let oracle_output_value_clean = + value_length(oracle_output.value) == 2 + let registry_output_value_clean = + value_length(registry_output.value) == 2 + oracle_datum_updated && registry_initial_datum_correct && oracle_output_value_clean && registry_output_value_clean + } + _ -> False + } + } + (RBurn, _) -> check_policy_only_burn(mint, current_policy) + _ -> False + } + _ -> False + } +} diff --git a/plutus.json b/plutus.json index dc39a64..9b252a8 100644 --- a/plutus.json +++ b/plutus.json @@ -11,12 +11,31 @@ "license": "Apache-2.0" }, "validators": [ + { + "title": "content_registry_ref_token.content_registry_ref_token", + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/aiken_content_ownership~1types~1MintPolarity" + } + }, + "parameters": [ + { + "title": "oracle_nft", + "schema": { + "$ref": "#/definitions/ByteArray" + } + } + ], + "compiledCode": "590766010000323232323232323232232223253330083232323232323232323232323253330153370e90000008991919191919191919191919299981099b8748000c08000854ccc09000c0044c94ccc0940044c8c94ccc090cdc3a40086046002264646464646464646464646464646464646464a666074004002264a666076002264a66607800a006264a66607a00226464a66607866e1d2004303b0011323232533303f3370e9002181f0008991919299982119b8748000c1040084c8c8c8c94ccc124c1300084c8c8c8c8c8c8c8c94ccc1394ccc1394ccc13801c401852808010a50100114a066e1cc008dd5981a1825809a400866e1cc004dd59819982500a24008460046060002600200244a66609c00229000099b8048008cc008008c1440054ccc120cdc3802a4000266ebcdd3001a60101a00014a066ebc028c8c8c8c8cdd2a40006609e60a00086609e60a00066609e60a00046609e60a00026609e6ea0cdc000ca400460a260a200260a0002609e002609c002608a044646600200200444a66609600229309919801801982780119191bae304c002375a6094002609a0022c6eacc128004c128008dd6982400098200010b180c8021822800981e8008b1811981e0021821000981d0008b1810181c801981f803002181f802981e801801181e8010a503758606c0046eb0c0d8004c8cdd81ba73333001024008030488100374e666600204800800c66464646464644660046600491010a526567697374727920280033003001330060014800922101290022337140040026002002444a66607466e1c005200213300448810033700004903009980219980180199b8600200133706002900a19b803370600400290301119b8b0010023001001222533303733710004900a0800899980180199b8300248050cdc1000a40280044444660400084a66607066ebcc06cc0d80040104cdc39998101bab301f3036001003002480085281bad3037001303700230350013035002375c6066002606600460620026062002605000a6002008464a66605466e1d200000113232323232323232323232323232323232323232533304130440021323232498c064024c060038c05c04458dd7182100098210011bae30400013040002375a607c002607c004607800260780046eb8c0e8004c0e8008dd6981c000981c001181b000981b0011bae3034001303400230320013032002375c606000260500042c6050002464a66605266e1d20000011323232325333030303300213232498c94ccc0bccdc3a400000226464a666068606e0042649319299981919b87480000044c8c94ccc0dcc0e80084c926300e0011630380013030002153330323370e90010008991919191919299981d981f0010a4c2c6eb4c0f0004c0f0008dd6981d000981d0011bad30380013030002163030001163035001302d0031533302f3370e90010008a99981918168018a4c2c2c605a004600e0062c60620026062004605e002604e0042c604e002464a66605066e1d200000113232533302d3030002149858dd7181700098130010a99981419b87480080044c8c94ccc0b4c0c000852616375c605c002604c0042c604c002605400260440022c6010604260146042002604e008004604e0060022a66604066e1d2002301f001132323300100100222533302600114a226464a66604aa66604a66e3cdd71804001007899b88375a601400490000a5113300400400114a060540046eb0c0a0004c010c8cc004004038894ccc09400452f5bded8c0264646464a66604c66e3d220100002100313302a337606ea4008dd3000998030030019bab3027003375c604a0046052004604e0022940c080014dd6181000211811800919198008008011129998110008a5eb804c8ccc888c8cc00400400c894ccc0a0004400c4c8ccc888cc0b4dd3998169ba90093302d37520066605a6ea00092f5c00026eb8c09c004dd6981400099801801981600118150009bae30210013756604400266006006604c0046048002460426044604400266ec0054dd399801806919b873330033756600460326004603200202e91100480088c07cc080004888c8cc88c94ccc07ccdc3a4004002200426eb4c090c07400cc074008c94ccc074cdc3a40040022980103d87a8000132323300100100222533302300114c103d87a800013232323253330243371e014004266e95200033028375000297ae0133006006003375a604a0066eb8c08c008c09c008c094004dd59811180d801180d800a4000646600200200844a6660400022980103d87a800013232323253330213371e010004266e95200033025374c00297ae0133006006003375660440066eb8c080008c090008c08800488c8cc00400400c894ccc07800452f5c026464a66603a600a00426604200466008008002266008008002604400460400026eb8c06c004c04c02852818098049bab3018001301800130170023758602a002602a00260280046eb0c048004c02800cc040004c040008c038004c018008526136563253330083370e90000008a99980598030018a4c2c2a66601066e1d20020011533300b300600314985858c018008dd7000918029baa001230033754002ae6955ceaab9e5573eae815d0aba21", + "hash": "bbc53b52bb8dabe86bb133a83c7572cb2aeb358220d86eb1bb0a3d45" + }, { "title": "one_time_minting_policy.one_time_minting_policy", "redeemer": { "title": "redeemer", "schema": { - "$ref": "#/definitions/one_time_minting_policy~1Redeemer" + "$ref": "#/definitions/aiken_content_ownership~1types~1MintPolarity" } }, "parameters": [ @@ -27,25 +46,44 @@ } } ], - "compiledCode": "5902020100003232323232323232322223253330073232323232533300c3370e9000000899191919299980819b87480000084c8c8c8c94ccc050cdc3a400000229445281809000991980080080111299980b8008a60103d87a80001323253330163375e026600e6028004266e9520003301a0024bd70099802002000980d801180c8009bac3016001300e008132323300100100222533301600114a226464a66602aa66602a66e3cdd71803001004099b88375a60346036603600490000a5113300400400114a060340046eb0c060004c8c8cc004004008894ccc05800452f5c0264666444646600200200644a6660380022006264666444660426e9ccc084dd4804998109ba900333021375000497ae0001375c60360026eb4c070004cc00c00cc080008c078004dd7180a8009bab301600133003003301a002301800132323300100100222533301600114bd6f7b630099191919299980b99b8f488100002100313301b337606ea4008dd3000998030030019bab3018003375c602c004603400460300026eacc054c058c058c058c058c0380208c054004c034028dd7180900098050010a50300a001300f001300f002300d001300500214984d958c94ccc01ccdc3a40000022a666014600a0062930b0a99980399b874800800454ccc028c01400c52616163005002230053754002460066ea80055cd2ab9d5573caae7d5d02ba157441", - "hash": "be3105aa3627cda80601b9f9d14ffec737fccdaf92c3771c4d013641" + "compiledCode": "5902040100003232323232323232322223253330073232323232533300c3370e9000000899191919299980819b87480000084c8c8c8c94ccc050cdc3a400000229445281809000991980080080111299980b8008a60103d87a80001323253330163375e026600e6028004266e9520003301a0024bd70099802002000980d801180c8009bac3016001300e0081332232323300100100222533301800114a226464a66602ea66602e66e3cdd71804001003099b88375a6038603a603a00490000a5113300400400114a060380046eb0c068004c8c8cc004004008894ccc06000452f5c0264666444646600200200644a66603c0022006264666444660466e9ccc08cdd4804998119ba900333023375000497ae0001375c603a0026eb4c078004cc00c00cc088008c080004dd7180b8009bab301800133003003301c002301a001323300100100322533301700114bd6f7b630099191919299980c19b8f488100002100313301c337606ea4008dd3000998030030019bab3019003375c602e004603600460320026eacc054c058c058c058c058c03802000c8c054004c034028dd7180900098050010a50300a001300f001300f002300d001300500214984d958c94ccc01ccdc3a40000022a666014600a0062930b0a99980399b874800800454ccc028c01400c52616163005002230053754002460066ea80055cd2ab9d5573caae7d5d02ba15745", + "hash": "d8c276927b630e86ea7a787a44db48c13847b674e1ecacf266ed5e9b" }, { "title": "oracle_validator.oracle_validator", "datum": { "title": "datum", "schema": { - "$ref": "#/definitions/oracle_validator~1Datum" + "$ref": "#/definitions/aiken_content_ownership~1types~1OracleDatum" + } + }, + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/aiken_content_ownership~1types~1OracleRedeemer" } }, + "compiledCode": "5907140100003232323232323232322223232323232533300b323232323253330103370e90010008991919191919191919191919191919191919191919191919191919191919191919191919191919299981b99b87480000244cccc004084058c00804d2002153330373370e900100489999800810808980100724004264a66607066e1d200400a132323232323253330413044002132533303f3370e9002181f00089919191929998219919198008008011129998248008a511323253330483301102d00213300400400114a0609a0046eb8c12c004cc11cdd480c198239ba90164bd7008008a503375e0046464646464646466e9520003304d304e0073304d304e0063304d304e0053304d304e0043304d304e0033304d304e0023304d304e0013304d304e304f0013304d37520206609a6ea40392f5c0609c002609a0026098002609600260940026092002608007e6072002608a002607a0022c60866088608860780022c6084002646600200205444a666082002297ae013232533304053330403375e608a607c004042266e1cccc888c8cc88c94ccc11ccdc3a4004002200426eb4c130c11400cc114008c94ccc114cdc3a4004002298103d87a8000132323300100100222533304b00114c103d87a8000132323232533304c3371e014004266e95200033050375000297ae0133006006003375a609a0066eb8c12c008c13c008c134004dd5982518218011821800a4000646600200200844a6660900022980103d87a800013232323253330493371e010004266e9520003304d374c00297ae0133006006003375660940066eb8c120008c130008c128004dd598229823181f001011a45004800852809982200119802002000899802002000982280118218009bae30400013040002375c607c002606c0682a6660706600203a01626666004044036911004800452811191980080080191299981f0008a5013232533303d3371e00400a29444cc010010004c108008dd7182000091111919299981f9821001099191919192999820a99982099b8f00500a13371e00601229404cdc38008040a50375a608a002608a0046eb8c10c004c10c008dd718208008b1bac304000132323300100100222533304000114bd7009919991119198008008019129998230008801899199911198259ba73304b3752012660966ea400ccc12cdd400125eb80004dd718228009bad304600133003003304a0023048001375c607e0026eacc100004cc00c00cc110008c108004c8cc004004014894ccc0fc00452f5bded8c0264646464a66608066e3d2201000021003133044337606ea4008dd3000998030030019bab3041003375c607e00460860046082002466004660049110a526567697374727920280033003001330060014800922101290022337140040026002002444a66606a66e1c005200213300448810033700004903009980219980180199b8600200133706002900a19b803370600400290301119b8b0010023001001222533303233710004900a0800899980180199b8300248050cdc1000a4028605a0546eb8c0c8004c0c8008dd7181800098180011bad302e001302e001302d002375c605600260560046eb4c0a4004c0a4004c0a0008dd718130009813001181200098120011bae3022001301a019375860400026040002603e002603c002603a0046eacc06c004c06c004c068008dd6180c000980c000980b80098070020a50300e001301300130130023011001300900614984d958c94ccc02ccdc3a40000022a66601c601200e2930b0a99980599b874800800454ccc038c02401c526161533300b3370e90020008991919192999809180a8010a4c2c6eb8c04c004c04c008dd7180880098048038a99980599b874801800454ccc038c02401c526161630090063001006232533300a3370e90000008991919191919191919191919191919191919191929998109812001099191924c6032012603001c602e0222c6eb8c088004c088008dd7181000098100011bad301e001301e002301c001301c002375c603400260340046eb4c060004c060008c058004c058008dd7180a000980a001180900098090011bae3010001300800216300800123253330093370e9000000899191919299980818098010991924c64a66601e66e1d20000011323253330143017002132498c94ccc048cdc3a400000226464a66602e60340042649318070008b180c00098080010a99980919b87480080044c8c8c8c8c8c94ccc06cc07800852616375a603800260380046eb4c068004c068008dd6980c00098080010b18080008b180a80098068018a99980799b874800800454ccc048c03400c5261616300d00230070031630110013011002300f001300700216300700123253330083370e900000089919299980698080010a4c2c6eb8c038004c01800854ccc020cdc3a400400226464a66601a60200042930b1bae300e0013006002163006001230053754002460066ea80055cd2ab9d5573caae7d5d02ba15745", + "hash": "f45c93a64fb10cc4ec725353b299d142650305d695ec64e067cf63a7" + }, + { + "title": "ownership_registry_ref_token.ownership_registry_ref_token", "redeemer": { "title": "redeemer", "schema": { - "$ref": "#/definitions/oracle_validator~1Redeemer" + "$ref": "#/definitions/aiken_content_ownership~1types~1MintPolarity" } }, - "compiledCode": "5907070100003232323232323232322223232323232533300b323232323253330103370e900100089919191919191919191919191919191919191919191919191919191919191919191919191919299981b19b87480000204cccc004080050c00803d2002153330363370e9001004099998008100089801006a4004264a66606e66e1d2004009132323232323253330403043002132533303e3370e9002181e80089919191929998211919198008008011129998240008a511323253330473301102c00213300400400114a060980046eb8c128004cc118dd480b998231ba90154bd7008008a503375e0046464646464646466e9520003304c304d0073304c304d0063304c304d0053304c304d0043304c304d0033304c304d0023304c304d0013304c304d304e0013304c3752020660986ea40392f5c0609a00260980026096002609400260920026090002607e07c6070002608800260780022c60846086608660760022c6082002646600200205244a666080002297ae013232533303f533303f3375e6088607a004040266e1cccc888c8cc88c94ccc118cdc3a4004002200426eb4c12cc11000cc110008c94ccc110cdc3a4004002298103d87a8000132323300100100222533304a00114c103d87a8000132323232533304b3371e014004266e9520003304f375000297ae0133006006003375a60980066eb8c128008c138008c130004dd5982498210011821000a4000646600200200844a66608e0022980103d87a800013232323253330483371e010004266e9520003304c374c00297ae0133006006003375660920066eb8c11c008c12c008c124004dd598221822981e801011245004800852809982180119802002000899802002000982200118210009bae303f001303f002375c607a002606a0662a66606e6600203801426666004042034911004800452811191980080080191299981e8008a5013232533303c3371e00400a29444cc010010004c104008dd7181f80091111919299981f1820801099191919192999820299982019b8f00500a13371e00601229404cdc38008040a50375a608800260880046eb8c108004c108008dd718200008b1bac303f00132323300100100222533303f00114bd7009919991119198008008019129998228008801899199911198251ba73304a3752012660946ea400ccc128dd400125eb80004dd718220009bad30450013300300330490023047001375c607c0026eacc0fc004cc00c00cc10c008c104004c8cc004004014894ccc0f800452f5bded8c0264646464a66607e66e3d2201000021003133043337606ea4008dd3000998030030019bab3040003375c607c00460840046080002466e2922010b526567697374727920282900330020013300500148008c0040048894ccc0d4cdc3800a400426600891010033700004903009980219980180199b8600200133706002900a19b803370600400290301119b8b0010023001001222533303233710004900a0800899980180199b8300248050cdc1000a4028605a0546eb8c0c8004c0c8008dd7181800098180011bad302e001302e002375a605800260580046eb8c0a8004c0a8004c0a4008dd7181380098138009813001181200098120011bae3022001301a019375860400026040002603e002603c002603a0046eacc06c004c06c004c068008dd6180c000980c000980b80098070020a50300e001301300130130023011001300900614984d958c94ccc02ccdc3a40000022a66601c601200e2930b0a99980599b874800800454ccc038c02401c526161533300b3370e90020008991919192999809180a8010a4c2c6eb8c04c004c04c008dd7180880098048038a99980599b874801800454ccc038c02401c526161630090063001006232533300a3370e90000008991919191919191919191919191919191919191929998109812001099191924c603201a6030020602e0222c6eb8c088004c088008dd7181000098100011bad301e001301e002375a603800260380046eb8c068004c068008c060004c060008dd7180b000980b001180a000980a001180900098090011bae3010001300800216300800123253330093370e9000000899191919299980818098010991924c64a66601e66e1d20000011323253330143017002132498c94ccc048cdc3a400000226464a66602e60340042649318070008b180c00098080010a99980919b87480080044c8c8c8c8c8c94ccc06cc07800852616375a603800260380046eb4c068004c068008dd6980c00098080010b18080008b180a80098068018a99980799b874800800454ccc048c03400c5261616300d00230070031630110013011002300f001300700216300700123253330083370e900000089919299980698080010a4c2c6eb8c038004c01800854ccc020cdc3a400400226464a66601a60200042930b1bae300e0013006002163006001230053754002460066ea80055cd2ab9d5573caae7d5d02ba15745", - "hash": "63bfdd4bc9cff236160ec45f6fa657861bd0f4e200fc82ff1404073a" + "parameters": [ + { + "title": "oracle_nft", + "schema": { + "$ref": "#/definitions/ByteArray" + } + } + ], + "compiledCode": "5907ab010000323232323232323232232223253330083232323232323232323232323253330153370e90000008991919191919191919191919299981099b8748000c08000854ccc09000c0044c94ccc0940044c8c94ccc090cdc3a40086046002264646464646464646464646464646464646464646464a66607a004002264a66607c002264a66607e00a006264a66608000226464a66607e66e1d2004303e001132323253330423370e900218208008991919299982299b8748000c1100084c8c8c8c94ccc130c13c0084c8c8c8c8c8c8c8c94ccc1454ccc1454ccc14401c401852808010a50100114a066e1cc008dd5981b9827009a400866e1cc004dd5981b182680a24008460046066002600200244a6660a200229000099b8048008cc008008c1500054ccc12ccdc3802a4000266ebcdd3001a60101a00014a066ebc028c8c8c8c8c8c8c8cdd2a4000660aa60ac00e660aa60ac00c660aa60ac00a660aa60ac008660aa60ac006660aa60ac004660aa60ac002660aa6ea0cdc000e2400460ae60ae00260ac00260aa00260a800260a600260a400260a2002609004a646600200200444a66609c002293099198018019829001191919191bae3051002375c609e0026466ec0c14c004c14cc150004dd618278011bad304d0013050001163756609a002609a0046eb4c12c004c10c00858c070010c120004c10000458c098c0fc010c114004c0f400458c08cc0f000cc108018010c108014c10000c008c1000085281bac3039002375860720026466ec0dd39999800813805819a4500374e666600204e00800c66464646464644660046600491010a526567697374727920280033003001330060014800922101290022337140040026002002444a66607a66e1c005200213300448810033700004903009980219980180199b8600200133706002900a19b803370600400290301119b8b0010023001001222533303a33710004900a0800899980180199b8300248050cdc1000a40280044444660460084a66607666ebcc078c0e40040104cdc39998119bab30223039001003002480085281bad303a001303a00230380013038002375c606c002606c002606a0026068002606600460620026062002605000a6002008464a66605466e1d200000113232323232323232323232323232323232323232533304130440021323232498c064024c060038c05c04458dd7182100098210011bae30400013040002375a607c002607c004607800260780046eb8c0e8004c0e8008dd6981c000981c001181b000981b0011bae3034001303400230320013032002375c606000260500042c6050002464a66605266e1d20000011323232325333030303300213232498c94ccc0bccdc3a400000226464a666068606e0042649319299981919b87480000044c8c94ccc0dcc0e80084c926300e0011630380013030002153330323370e90010008991919191919299981d981f0010a4c2c6eb4c0f0004c0f0008dd6981d000981d0011bad30380013030002163030001163035001302d0031533302f3370e90010008a99981918168018a4c2c2c605a004600e0062c60620026062004605e002604e0042c604e002464a66605066e1d200000113232533302d3030002149858dd7181700098130010a99981419b87480080044c8c94ccc0b4c0c000852616375c605c002604c0042c604c002605400260440022c6010604260146042002604e008004604e0060022a66604066e1d2002301f001132323300100100222533302600114a226464a66604aa66604a66e3cdd71804001007899b88375a601400490000a5113300400400114a060540046eb0c0a0004c010c8cc004004038894ccc09400452f5bded8c0264646464a66604c66e3d22100002100313302a337606ea4008dd3000998030030019bab3027003375c604a0046052004604e0022940c080014dd6181000211811800919198008008011129998110008a5eb804c8ccc888c8cc00400400c894ccc0a0004400c4c8ccc888cc0b4dd3998169ba90093302d37520066605a6ea00092f5c00026eb8c09c004dd6981400099801801981600118150009bae30210013756604400266006006604c0046048002460426044604400266ec0054dd399801806919b873330033756600460326004603200202e91100480088c07cc080004888c8cc88c94ccc07ccdc3a4004002200426eb4c090c07400cc074008c94ccc074cdc3a40040022980103d87a8000132323300100100222533302300114c103d87a800013232323253330243371e014004266e95200033028375000297ae0133006006003375a604a0066eb8c08c008c09c008c094004dd59811180d801180d800a4000646600200200844a6660400022980103d87a800013232323253330213371e010004266e95200033025374c00297ae0133006006003375660440066eb8c080008c090008c08800488c8cc00400400c894ccc07800452f5c026464a66603a600a00426604200466008008002266008008002604400460400026eb8c06c004c04c02852818098049bab3018001301800130170023758602a002602a00260280046eb0c048004c02800cc040004c040008c038004c018008526136563253330083370e90000008a99980598030018a4c2c2a66601066e1d20020011533300b300600314985858c018008dd7000918029baa001230033754002ae6955ceaab9e5573eae815d0aba21", + "hash": "0b3446bc6eea7ab5041e1f7470e87aba62382b7124dc97f63c483d0d" } ], "definitions": { @@ -198,8 +236,8 @@ } ] }, - "one_time_minting_policy/Redeemer": { - "title": "Redeemer", + "aiken_content_ownership/types/MintPolarity": { + "title": "MintPolarity", "anyOf": [ { "title": "RMint", @@ -215,11 +253,11 @@ } ] }, - "oracle_validator/Datum": { - "title": "Datum", + "aiken_content_ownership/types/OracleDatum": { + "title": "OracleDatum", "anyOf": [ { - "title": "Datum", + "title": "OracleDatum", "dataType": "constructor", "index": 0, "fields": [ @@ -231,25 +269,25 @@ "title": "oracle_address", "$ref": "#/definitions/aiken~1transaction~1credential~1Address" }, - { - "title": "content_registry_address", - "$ref": "#/definitions/aiken~1transaction~1credential~1Address" - }, { "title": "content_registry_ref_token", "$ref": "#/definitions/ByteArray" }, { - "title": "ownership_registry_address", + "title": "content_registry_address", "$ref": "#/definitions/aiken~1transaction~1credential~1Address" }, + { + "title": "content_registry_count", + "$ref": "#/definitions/Int" + }, { "title": "ownership_registry_ref_token", "$ref": "#/definitions/ByteArray" }, { - "title": "content_registry_count", - "$ref": "#/definitions/Int" + "title": "ownership_registry_address", + "$ref": "#/definitions/aiken~1transaction~1credential~1Address" }, { "title": "ownership_registry_count", @@ -267,8 +305,8 @@ } ] }, - "oracle_validator/Redeemer": { - "title": "Redeemer", + "aiken_content_ownership/types/OracleRedeemer": { + "title": "OracleRedeemer", "anyOf": [ { "title": "CreateContentRegistry", diff --git a/validators/content_registry.ak b/validators/content_registry.ak index 8b13789..145a5f5 100644 --- a/validators/content_registry.ak +++ b/validators/content_registry.ak @@ -1 +1,23 @@ +use aiken/transaction.{ScriptContext, ScriptPurpose, Spend, Transaction} +use aiken/transaction/value.{PolicyId} +use aiken_content_ownership/common.{inputs_with} +use aiken_content_ownership/types.{ + ContentRegistryDatum, ContentRegistryRedeemer, CreateContent, +} +validator(oracle_nft: PolicyId) { + fn content_registry_validator( + datum: ContentRegistryDatum, + redeemer: ContentRegistryRedeemer, + context: ScriptContext, + ) { + let ScriptContext { purpose, transaction } = context + let Transaction { reference_inputs, inputs, outputs, mint, .. } = + transaction + expect Spend(_): ScriptPurpose = purpose + when (redeemer, inputs_with(reference_inputs, oracle_nft, "")) is { + (CreateContent { content_hash }, [oracle_ref_input]) -> True + _ -> False + } + } +} diff --git a/validators/content_registry_ref_token.ak b/validators/content_registry_ref_token.ak index 6295f7a..176ae75 100644 --- a/validators/content_registry_ref_token.ak +++ b/validators/content_registry_ref_token.ak @@ -1,266 +1,15 @@ -use aiken/dict -// use aiken/list -use aiken/transaction.{ - InlineDatum, Input, Mint, Output, ScriptContext, Transaction, placeholder, +use aiken/transaction.{ScriptContext} +use aiken/transaction/value.{PolicyId} +use aiken_content_ownership/types.{MintPolarity} +use aiken_content_ownership/validators/content_registry_ref_token.{ + content_registry_ref_token_logic, } -use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value} -use aiken_content_ownership/common.{ - check_policy_only_burn, inputs_with, outputs_at_with, value_length, -} -use aiken_content_ownership/placeholder.{ - mock_content_registry_datum, mock_content_registry_output, mock_oracle_datum, - mock_oracle_output, mock_policy_id, mock_policy_id_2, mock_policy_id_3, - mock_utxo_ref, -} -use aiken_content_ownership/types.{ - ContentRegistryDatum, MintPolarity, OracleDatum, RBurn, RMint, -} -use aiken_content_ownership/utils.{get_registry_token_name} validator(oracle_nft: PolicyId) { fn content_registry_ref_token( redeemer: MintPolarity, context: ScriptContext, ) -> Bool { - let ScriptContext { purpose, transaction } = context - let Transaction { inputs, outputs, mint, .. } = transaction - when purpose is { - Mint(current_policy) -> - when (redeemer, inputs_with(inputs, oracle_nft, "")) is { - (RMint, [oracle_input]) -> { - expect InlineDatum(inline_datum) = oracle_input.output.datum - expect input_datum: OracleDatum = inline_datum - let OracleDatum { - oracle_address, - content_registry_ref_token, - content_registry_address, - content_registry_count, - .. - } = input_datum - when - ( - outputs_at_with(outputs, oracle_address, oracle_nft, ""), - outputs_at_with( - outputs, - content_registry_address, - content_registry_ref_token, - get_registry_token_name(content_registry_count), - ), - ) - is { - ([oracle_output], [registry_output]) -> { - expect InlineDatum(raw_oracle_datum) = oracle_output.datum - expect InlineDatum(raw_registry_datum) = registry_output.datum - expect oracle_datum: OracleDatum = raw_oracle_datum - expect ContentRegistryDatum { count, registry }: ContentRegistryDatum = - raw_registry_datum - let oracle_datum_updated = - oracle_datum == OracleDatum { - ..input_datum, - content_registry_count: content_registry_count + 1, - } - let registry_initial_datum_correct = - count == 0 && registry == dict.new() - let oracle_output_value_clean = - value_length(oracle_output.value) == 2 - let registry_output_value_clean = - value_length(registry_output.value) == 2 - oracle_datum_updated && registry_initial_datum_correct && oracle_output_value_clean && registry_output_value_clean - } - _ -> False - } - } - (RBurn, _) -> check_policy_only_burn(mint, current_policy) - _ -> False - } - _ -> False - } + content_registry_ref_token_logic(oracle_nft, redeemer, context) } } - -type TestCase { - is_oracle_updated: Bool, - is_registry_initialized: Bool, - is_oracle_value_clean: Bool, - is_registry_value_clean: Bool, -} - -fn default_test_case() -> TestCase { - TestCase { - is_oracle_updated: True, - is_registry_initialized: True, - is_oracle_value_clean: True, - is_registry_value_clean: True, - } -} - -fn make_mock_tx_body(record_count: Int, test_case: TestCase) -> Transaction { - let registry_token_value = - from_asset(mock_policy_id_2(), get_registry_token_name(record_count), 1) - let TestCase { - is_oracle_updated, - is_registry_initialized, - is_oracle_value_clean, - is_registry_value_clean, - } = test_case - let new_count = - if is_oracle_updated { - record_count + 1 - } else { - record_count - } - let new_registry = - if is_registry_initialized { - mock_content_registry_datum(0, dict.new()) - } else { - mock_content_registry_datum(1, dict.new()) - } - let oracle_value = - if is_oracle_value_clean { - from_asset(mock_policy_id(), "", 1) |> add(#"", #"", 2_000_000) - } else { - from_asset(mock_policy_id(), "", 1) - |> add(#"", #"", 2_000_000) - |> add(mock_policy_id_3(), "123", 1) - } - let registry_value = - if is_registry_value_clean { - registry_token_value |> add(#"", #"", 2_000_000) - } else { - registry_token_value - |> add(#"", #"", 2_000_000) - |> add(mock_policy_id_3(), "123", 1) - } - Transaction { - ..placeholder(), - mint: to_minted_value(registry_token_value), - inputs: [ - Input { - output_reference: mock_utxo_ref(1), - output: mock_oracle_output(mock_oracle_datum()), - }, - ], - outputs: [ - Output { - ..mock_oracle_output( - OracleDatum { - ..mock_oracle_datum(), - content_registry_count: new_count, - }, - ), - value: oracle_value, - }, - Output { - ..mock_content_registry_output(record_count, new_registry), - value: registry_value, - }, - ], - } -} - -test success_mint() { - let redeemer = RMint - let tx = make_mock_tx_body(0, default_test_case()) - let ctx = ScriptContext { purpose: Mint(mock_policy_id_2()), transaction: tx } - content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_mint_without_update_oracle() { - let redeemer = RMint - let tx = - make_mock_tx_body( - 0, - TestCase { ..default_test_case(), is_oracle_updated: False }, - ) - let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_mint_without_registry_initialized() { - let redeemer = RMint - let tx = - make_mock_tx_body( - 0, - TestCase { ..default_test_case(), is_registry_initialized: False }, - ) - let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_mint_with_unclean_oracle_value() { - let redeemer = RMint - let tx = - make_mock_tx_body( - 0, - TestCase { ..default_test_case(), is_oracle_value_clean: False }, - ) - let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_mint_with_unclean_registry_value() { - let redeemer = RMint - let tx = - make_mock_tx_body( - 0, - TestCase { ..default_test_case(), is_registry_value_clean: False }, - ) - let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test success_burn() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value(from_asset(policy_id, "", -1)), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test success_burn_with_other_minting() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value( - from_asset(policy_id, "", -1) |> add(mock_policy_id_2(), "", 1), - ), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_burn_with_mint() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value(from_asset(policy_id, "", 1)), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} - -test fail_burn_with_mix() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value( - from_asset(policy_id, "", -1) |> add(policy_id, "1", 1), - ), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - !content_registry_ref_token(mock_policy_id(), redeemer, ctx) -} diff --git a/validators/one_time_minting_policy.ak b/validators/one_time_minting_policy.ak index a3c79e1..811ce6a 100644 --- a/validators/one_time_minting_policy.ak +++ b/validators/one_time_minting_policy.ak @@ -1,122 +1,14 @@ -use aiken/list -use aiken/transaction.{ - Input, Mint, OutputReference, ScriptContext, Transaction, placeholder, +use aiken/transaction.{OutputReference, ScriptContext} +use aiken_content_ownership/types.{MintPolarity} +use aiken_content_ownership/validators/one_time_minting_policy.{ + one_time_minting_policy_logic, } -use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value} -use aiken_content_ownership/common.{check_policy_only_burn} -use aiken_content_ownership/placeholder.{ - mock_output, mock_policy_id, mock_policy_id_2, mock_utxo_ref, -} -use aiken_content_ownership/types.{MintPolarity, RBurn, RMint} validator(utxo_ref: OutputReference) { fn one_time_minting_policy( redeemer: MintPolarity, context: ScriptContext, ) -> Bool { - let ScriptContext { purpose, transaction } = context - when purpose is { - Mint(current_policy) -> - when redeemer is { - RMint -> { - let Transaction { inputs, .. } = transaction - let hash_equal = - fn(input: Input) { - let hash = input.output_reference - utxo_ref == hash - } - let target_input_exist = list.find(inputs, hash_equal) - when target_input_exist is { - Some(_) -> True - None -> False - } - } - RBurn -> check_policy_only_burn(transaction.mint, current_policy) - } - _ -> False - } + one_time_minting_policy_logic(utxo_ref, redeemer, context) } } - -test success_mint() { - let redeemer = RMint - let input_utxo = mock_utxo_ref(1) - let policy_id: PolicyId = - #"1c1b7afe8affbee1505cf3ec5a58bd2734d4ffdfcc9b9f059625bd76" - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value(from_asset(policy_id, "", 1)), - inputs: [Input { output_reference: input_utxo, output: mock_output() }], - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - - one_time_minting_policy(input_utxo, redeemer, ctx) -} - -test fail_mint_no_utxo_ref_supply() { - let redeemer = RMint - let policy_id = mock_policy_id() - - let ctx = - ScriptContext { purpose: Mint(policy_id), transaction: placeholder() } - - !one_time_minting_policy(mock_utxo_ref(0), redeemer, ctx) -} - -test success_burn() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value(from_asset(policy_id, "", -1)), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - one_time_minting_policy(mock_utxo_ref(0), redeemer, ctx) -} - -test success_burn_with_other_minting() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value( - from_asset(policy_id, "", -1) |> add(mock_policy_id_2(), "", 1), - ), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - one_time_minting_policy(mock_utxo_ref(0), redeemer, ctx) -} - -test fail_burn_with_mint() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value(from_asset(policy_id, "", 1)), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - !one_time_minting_policy(mock_utxo_ref(0), redeemer, ctx) -} - -test fail_burn_with_mix() { - let redeemer = RBurn - let policy_id = mock_policy_id() - - let tx = - Transaction { - ..placeholder(), - mint: to_minted_value( - from_asset(policy_id, "", -1) |> add(policy_id, "1", 1), - ), - } - let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } - !one_time_minting_policy(mock_utxo_ref(0), redeemer, ctx) -} diff --git a/validators/oracle_validator.ak b/validators/oracle_validator.ak index ab83a42..6ab4ee5 100644 --- a/validators/oracle_validator.ak +++ b/validators/oracle_validator.ak @@ -1,10 +1,5 @@ -use aiken/transaction.{ - InlineDatum, Input, Output, ScriptContext, Spend, Transaction, placeholder, -} +use aiken/transaction.{Input, ScriptContext, Spend, Transaction, placeholder} use aiken/transaction/value.{PolicyId, from_asset, to_minted_value} -use aiken_content_ownership/common.{ - all_key_signed, key_signed, only_minted_token, outputs_at_with, -} use aiken_content_ownership/placeholder.{ mock_oracle_datum, mock_oracle_output, mock_policy_id, mock_policy_id_2, mock_policy_id_3, mock_utxo_ref, mock_vkey_hex, mock_vkey_hex_2, @@ -13,7 +8,7 @@ use aiken_content_ownership/types.{ CreateContentRegistry, CreateOwnershipRegistry, OracleDatum, OracleRedeemer, RotateKey, StopApp, } -use aiken_content_ownership/utils.{get_registry_token_name} +use aiken_content_ownership/validators/oracle_validator.{oracle_validator_logic} validator { fn oracle_validator( @@ -21,69 +16,7 @@ validator { redeemer: OracleRedeemer, context: ScriptContext, ) { - let ScriptContext { purpose, transaction } = context - when purpose is { - Spend(_) -> { - let Transaction { outputs, mint, extra_signatories, .. } = transaction - let OracleDatum { - oracle_nft, - oracle_address, - content_registry_ref_token, - content_registry_count, - ownership_registry_ref_token, - ownership_registry_count, - operation_key, - stop_key, - .. - } = datum - - when redeemer is { - CreateContentRegistry -> - // Ref token is minted - only_minted_token( - mint, - content_registry_ref_token, - get_registry_token_name(content_registry_count), - 1, - ) - - CreateOwnershipRegistry -> - // Ref token is minted - only_minted_token( - mint, - ownership_registry_ref_token, - get_registry_token_name(ownership_registry_count), - 1, - ) - RotateKey { new_operation_key, new_stop_key } -> { - // Sign by both ops and stop key - expect [own_output] = - outputs_at_with(outputs, oracle_address, oracle_nft, "") - expect InlineDatum(dat) = own_output.datum - expect own_datum: OracleDatum = dat - let datum_correct = - own_datum == OracleDatum { - ..datum, - operation_key: new_operation_key, - stop_key: new_stop_key, - } - all_key_signed(extra_signatories, [operation_key, stop_key]) && datum_correct - } - - // datum update correctly (key rotated) - StopApp -> - // signed by stop key - // oracle nft is burned - key_signed(extra_signatories, stop_key) && only_minted_token( - mint, - oracle_nft, - "", - -1, - ) - } - } - _ -> False - } + oracle_validator_logic(datum, redeemer, context) } } diff --git a/validators/tests/unit-tests/content_registry_ref_token.ak b/validators/tests/unit-tests/content_registry_ref_token.ak new file mode 100644 index 0000000..d2e2d93 --- /dev/null +++ b/validators/tests/unit-tests/content_registry_ref_token.ak @@ -0,0 +1,202 @@ +use aiken/dict +use aiken/transaction.{ + Input, Mint, Output, ScriptContext, Transaction, placeholder, +} +use aiken/transaction/value.{add, from_asset, to_minted_value} +use aiken_content_ownership/placeholder.{ + mock_content_registry_datum, mock_content_registry_output, mock_oracle_datum, + mock_oracle_output, mock_policy_id, mock_policy_id_2, mock_policy_id_3, + mock_utxo_ref, +} +use aiken_content_ownership/types.{OracleDatum, RBurn, RMint} +use aiken_content_ownership/utils.{get_registry_token_name} +use aiken_content_ownership/validators/content_registry_ref_token.{ + content_registry_ref_token_logic, +} + +type TestCase { + is_oracle_updated: Bool, + is_registry_initialized: Bool, + is_oracle_value_clean: Bool, + is_registry_value_clean: Bool, +} + +fn default_test_case() -> TestCase { + TestCase { + is_oracle_updated: True, + is_registry_initialized: True, + is_oracle_value_clean: True, + is_registry_value_clean: True, + } +} + +fn make_mock_tx_body(record_count: Int, test_case: TestCase) -> Transaction { + let registry_token_value = + from_asset(mock_policy_id_2(), get_registry_token_name(record_count), 1) + let TestCase { + is_oracle_updated, + is_registry_initialized, + is_oracle_value_clean, + is_registry_value_clean, + } = test_case + let new_count = + if is_oracle_updated { + record_count + 1 + } else { + record_count + } + let new_registry = + if is_registry_initialized { + mock_content_registry_datum(0, dict.new()) + } else { + mock_content_registry_datum(1, dict.new()) + } + let oracle_value = + if is_oracle_value_clean { + from_asset(mock_policy_id(), "", 1) |> add(#"", #"", 2_000_000) + } else { + from_asset(mock_policy_id(), "", 1) + |> add(#"", #"", 2_000_000) + |> add(mock_policy_id_3(), "123", 1) + } + let registry_value = + if is_registry_value_clean { + registry_token_value |> add(#"", #"", 2_000_000) + } else { + registry_token_value + |> add(#"", #"", 2_000_000) + |> add(mock_policy_id_3(), "123", 1) + } + Transaction { + ..placeholder(), + mint: to_minted_value(registry_token_value), + inputs: [ + Input { + output_reference: mock_utxo_ref(1), + output: mock_oracle_output(mock_oracle_datum()), + }, + ], + outputs: [ + Output { + ..mock_oracle_output( + OracleDatum { + ..mock_oracle_datum(), + content_registry_count: new_count, + }, + ), + value: oracle_value, + }, + Output { + ..mock_content_registry_output(record_count, new_registry), + value: registry_value, + }, + ], + } +} + +test success_mint() { + let redeemer = RMint + let tx = make_mock_tx_body(0, default_test_case()) + let ctx = ScriptContext { purpose: Mint(mock_policy_id_2()), transaction: tx } + content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_without_update_oracle() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_oracle_updated: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_without_registry_initialized() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_registry_initialized: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_with_unclean_oracle_value() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_oracle_value_clean: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_with_unclean_registry_value() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_registry_value_clean: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test success_burn() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", -1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test success_burn_with_other_minting() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(mock_policy_id_2(), "", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_burn_with_mint() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", 1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_burn_with_mix() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(policy_id, "1", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !content_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} diff --git a/validators/tests/unit-tests/one_time_minting_policy.ak b/validators/tests/unit-tests/one_time_minting_policy.ak new file mode 100644 index 0000000..160a921 --- /dev/null +++ b/validators/tests/unit-tests/one_time_minting_policy.ak @@ -0,0 +1,92 @@ +use aiken/transaction.{Input, Mint, ScriptContext, Transaction, placeholder} +use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value} +use aiken_content_ownership/placeholder.{ + mock_output, mock_policy_id, mock_policy_id_2, mock_utxo_ref, +} +use aiken_content_ownership/types.{RBurn, RMint} +use aiken_content_ownership/validators/one_time_minting_policy.{ + one_time_minting_policy_logic, +} + +test success_mint() { + let redeemer = RMint + let input_utxo = mock_utxo_ref(1) + let policy_id: PolicyId = + #"1c1b7afe8affbee1505cf3ec5a58bd2734d4ffdfcc9b9f059625bd76" + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", 1)), + inputs: [Input { output_reference: input_utxo, output: mock_output() }], + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + + one_time_minting_policy_logic(input_utxo, redeemer, ctx) +} + +test fail_mint_no_utxo_ref_supply() { + let redeemer = RMint + let policy_id = mock_policy_id() + + let ctx = + ScriptContext { purpose: Mint(policy_id), transaction: placeholder() } + + !one_time_minting_policy_logic(mock_utxo_ref(0), redeemer, ctx) +} + +test success_burn() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", -1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + one_time_minting_policy_logic(mock_utxo_ref(0), redeemer, ctx) +} + +test success_burn_with_other_minting() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(mock_policy_id_2(), "", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + one_time_minting_policy_logic(mock_utxo_ref(0), redeemer, ctx) +} + +test fail_burn_with_mint() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", 1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !one_time_minting_policy_logic(mock_utxo_ref(0), redeemer, ctx) +} + +test fail_burn_with_mix() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(policy_id, "1", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !one_time_minting_policy_logic(mock_utxo_ref(0), redeemer, ctx) +} diff --git a/validators/tests/unit-tests/oracle_validator.ak b/validators/tests/unit-tests/oracle_validator.ak new file mode 100644 index 0000000..86a4773 --- /dev/null +++ b/validators/tests/unit-tests/oracle_validator.ak @@ -0,0 +1,86 @@ +use aiken/transaction.{Input, ScriptContext, Spend, Transaction, placeholder} +use aiken/transaction/value.{PolicyId, from_asset, to_minted_value} +use aiken_content_ownership/placeholder.{ + mock_oracle_datum, mock_oracle_output, mock_policy_id, mock_policy_id_2, + mock_policy_id_3, mock_utxo_ref, mock_vkey_hex, mock_vkey_hex_2, +} +use aiken_content_ownership/types.{ + CreateContentRegistry, CreateOwnershipRegistry, OracleDatum, RotateKey, + StopApp, +} +use aiken_content_ownership/validators/oracle_validator.{oracle_validator_logic} + +test success_create_content_registry() { + let redeemer = CreateContentRegistry + let policy_id: PolicyId = mock_policy_id_2() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "Registry (0)", 1)), + } + let ctx = ScriptContext { purpose: Spend(mock_utxo_ref(0)), transaction: tx } + + oracle_validator_logic(mock_oracle_datum(), redeemer, ctx) +} + +test success_create_ownership_registry() { + let redeemer = CreateOwnershipRegistry + let policy_id: PolicyId = mock_policy_id_3() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "Registry (0)", 1)), + } + let ctx = ScriptContext { purpose: Spend(mock_utxo_ref(0)), transaction: tx } + + oracle_validator_logic(mock_oracle_datum(), redeemer, ctx) +} + +test success_rotate_key() { + let redeemer = + RotateKey { + new_operation_key: mock_vkey_hex_2(), + new_stop_key: mock_vkey_hex(), + } + + let input_utxo = mock_utxo_ref(0) + let input = + Input { + output_reference: input_utxo, + output: mock_oracle_output(mock_oracle_datum()), + } + let output = + mock_oracle_output( + OracleDatum { + ..mock_oracle_datum(), + operation_key: mock_vkey_hex_2(), + stop_key: mock_vkey_hex(), + }, + ) + + let tx = + Transaction { + ..placeholder(), + inputs: [input], + outputs: [output], + extra_signatories: [mock_vkey_hex(), mock_vkey_hex_2()], + } + let ctx = ScriptContext { purpose: Spend(input_utxo), transaction: tx } + + oracle_validator_logic(mock_oracle_datum(), redeemer, ctx) +} + +test success_stop_app() { + let redeemer = StopApp + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(mock_policy_id(), "", -1)), + extra_signatories: [mock_vkey_hex_2()], + } + let ctx = ScriptContext { purpose: Spend(mock_utxo_ref(0)), transaction: tx } + + oracle_validator_logic(mock_oracle_datum(), redeemer, ctx) +} diff --git a/validators/tests/unit-tests/ownership_registry_ref_token.ak b/validators/tests/unit-tests/ownership_registry_ref_token.ak new file mode 100644 index 0000000..d741bbc --- /dev/null +++ b/validators/tests/unit-tests/ownership_registry_ref_token.ak @@ -0,0 +1,202 @@ +use aiken/dict +use aiken/transaction.{ + Input, Mint, Output, ScriptContext, Transaction, placeholder, +} +use aiken/transaction/value.{add, from_asset, to_minted_value} +use aiken_content_ownership/placeholder.{ + mock_oracle_datum, mock_oracle_output, mock_ownership_registry_datum, + mock_ownership_registry_output, mock_policy_id, mock_policy_id_2, + mock_policy_id_3, mock_utxo_ref, +} +use aiken_content_ownership/types.{OracleDatum, RBurn, RMint} +use aiken_content_ownership/utils.{get_registry_token_name} +use aiken_content_ownership/validators/ownership_registry_ref_token.{ + ownership_registry_ref_token_logic, +} + +type TestCase { + is_oracle_updated: Bool, + is_registry_initialized: Bool, + is_oracle_value_clean: Bool, + is_registry_value_clean: Bool, +} + +fn default_test_case() -> TestCase { + TestCase { + is_oracle_updated: True, + is_registry_initialized: True, + is_oracle_value_clean: True, + is_registry_value_clean: True, + } +} + +fn make_mock_tx_body(record_count: Int, test_case: TestCase) -> Transaction { + let registry_token_value = + from_asset(mock_policy_id_3(), get_registry_token_name(record_count), 1) + let TestCase { + is_oracle_updated, + is_registry_initialized, + is_oracle_value_clean, + is_registry_value_clean, + } = test_case + let new_count = + if is_oracle_updated { + record_count + 1 + } else { + record_count + } + let new_registry = + if is_registry_initialized { + mock_ownership_registry_datum(0, dict.new()) + } else { + mock_ownership_registry_datum(1, dict.new()) + } + let oracle_value = + if is_oracle_value_clean { + from_asset(mock_policy_id(), "", 1) |> add(#"", #"", 2_000_000) + } else { + from_asset(mock_policy_id(), "", 1) + |> add(#"", #"", 2_000_000) + |> add(mock_policy_id_2(), "123", 1) + } + let registry_value = + if is_registry_value_clean { + registry_token_value |> add(#"", #"", 2_000_000) + } else { + registry_token_value + |> add(#"", #"", 2_000_000) + |> add(mock_policy_id_2(), "123", 1) + } + Transaction { + ..placeholder(), + mint: to_minted_value(registry_token_value), + inputs: [ + Input { + output_reference: mock_utxo_ref(1), + output: mock_oracle_output(mock_oracle_datum()), + }, + ], + outputs: [ + Output { + ..mock_oracle_output( + OracleDatum { + ..mock_oracle_datum(), + ownership_registry_count: new_count, + }, + ), + value: oracle_value, + }, + Output { + ..mock_ownership_registry_output(record_count, new_registry), + value: registry_value, + }, + ], + } +} + +test success_mint() { + let redeemer = RMint + let tx = make_mock_tx_body(0, default_test_case()) + let ctx = ScriptContext { purpose: Mint(mock_policy_id_3()), transaction: tx } + ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_without_update_oracle() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_oracle_updated: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_without_registry_initialized() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_registry_initialized: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_with_unclean_oracle_value() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_oracle_value_clean: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_mint_with_unclean_registry_value() { + let redeemer = RMint + let tx = + make_mock_tx_body( + 0, + TestCase { ..default_test_case(), is_registry_value_clean: False }, + ) + let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test success_burn() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", -1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test success_burn_with_other_minting() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(mock_policy_id_2(), "", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_burn_with_mint() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value(from_asset(policy_id, "", 1)), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +} + +test fail_burn_with_mix() { + let redeemer = RBurn + let policy_id = mock_policy_id() + + let tx = + Transaction { + ..placeholder(), + mint: to_minted_value( + from_asset(policy_id, "", -1) |> add(policy_id, "1", 1), + ), + } + let ctx = ScriptContext { purpose: Mint(policy_id), transaction: tx } + !ownership_registry_ref_token_logic(mock_policy_id(), redeemer, ctx) +}