From 8d781eebca3bd17727c01a00e65f2da9ba901302 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Tue, 25 Feb 2020 00:04:52 -0800 Subject: [PATCH] Refactor id layer contract to use records instead of tuples --- src/test/contracts/id.mligo | 189 ++++++++++++++++++----------- src/test/id_tests.ml | 234 +++++++++++++++++++++--------------- 2 files changed, 256 insertions(+), 167 deletions(-) diff --git a/src/test/contracts/id.mligo b/src/test/contracts/id.mligo index e23f8d841..67233ce56 100644 --- a/src/test/contracts/id.mligo +++ b/src/test/contracts/id.mligo @@ -6,9 +6,21 @@ type id_details = { profile: bytes } -type buy = bytes * address option -type update_owner = id * address -type update_details = id * bytes option * address option +type buy = { + profile: bytes; + initial_controller: address option; +} + +type update_owner = { + id: id; + new_owner: address; +} + +type update_details = { + id: id; + new_profile: bytes option; + new_controller: address option; +} type action = | Buy of buy @@ -19,7 +31,14 @@ type action = (* The prices kept in storage can be changed by bakers, though they should only be adjusted down over time, not up. *) -type storage = (id, id_details) big_map * int * (tez * tez) +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage = { + identities: (id, id_details) big_map; + next_id: int; + name_price: tez; + skip_price: tez; +} type return = operation list * storage @@ -38,13 +57,17 @@ a lot that could be eaten up. Should probably do some napkin calculations for how expensive skipping needs to be to deter people from doing it just to chew up address space. *) -let buy (parameter, storage: (bytes * address option) * storage) = - let void : unit = - if Tezos.amount <> storage.2.0 - then (failwith "Incorrect amount paid.": unit) in - let profile, initial_controller = parameter in - let identities, new_id, prices = storage in - let controller : address = +let buy (parameter, storage: buy * storage) = + let void: unit = + if amount = storage.name_price + then () + else (failwith "Incorrect amount paid.": unit) + in + let profile = parameter.profile in + let initial_controller = parameter.initial_controller in + let identities = storage.identities in + let new_id = storage.next_id in + let controller: address = match initial_controller with | Some addr -> addr | None -> sender in @@ -54,74 +77,98 @@ let buy (parameter, storage: (bytes * address option) * storage) = profile = profile} in let updated_identities : (id, id_details) big_map = Big_map.update new_id (Some new_id_details) identities - in ([]: operation list), (updated_identities, new_id + 1, prices) + in + ([]: operation list), {identities = updated_identities; + next_id = new_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -let update_owner (parameter, storage : (id * address) * storage) = - if amount <> 0tez - then (failwith "Updating owner doesn't cost anything.": return) +let update_owner (parameter, storage: update_owner * storage) = + if (amount <> 0mutez) + then (failwith "Updating owner doesn't cost anything.": (operation list) * storage) else - let id, new_owner = parameter in - let identities, last_id, prices = storage in - let current_id_details : id_details = - match Big_map.find_opt id identities with - | Some id_details -> id_details - | None -> (failwith "This ID does not exist." : id_details) in - let is_allowed : bool = - if Tezos.sender = current_id_details.owner - then true - else (failwith "You are not the owner of this ID." : bool) in - let updated_id_details : id_details = { + let id = parameter.id in + let new_owner = parameter.new_owner in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if sender = current_id_details.owner + then true + else (failwith "You are not the owner of this ID.": bool) + in + let updated_id_details: id_details = { owner = new_owner; controller = current_id_details.controller; - profile = current_id_details.profile} in - let updated_identities = - Big_map.update id (Some updated_id_details) identities - in ([]: operation list), (updated_identities, last_id, prices) + profile = current_id_details.profile; + } + in + let updated_identities = Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -let update_details (parameter, storage: (id * bytes option * address option) * storage) = - if Tezos.amount <> 0tez - then - (failwith "Updating details doesn't cost anything." : return) +let update_details (parameter, storage: update_details * storage) = + if (amount <> 0mutez) + then (failwith "Updating details doesn't cost anything.": (operation list) * storage) else - let id, new_profile, new_controller = parameter in - let identities, last_id, prices = storage in - let current_id_details: id_details = - match Big_map.find_opt id identities with - | Some id_details -> id_details - | None -> (failwith "This ID does not exist.": id_details) in - let is_allowed : bool = - if Tezos.sender = current_id_details.controller - || Tezos.sender = current_id_details.owner - then true - else - (failwith ("You are not the owner or controller of this ID.") - : bool) in - let owner : address = current_id_details.owner in - let profile : bytes = - match new_profile with - | None -> (* Default *) current_id_details.profile - | Some new_profile -> new_profile in - let controller : address = - match new_controller with - | None -> (* Default *) current_id_details.controller - | Some new_controller -> new_controller in - let updated_id_details: id_details = { - owner = owner; - controller = controller; - profile = profile} in + let id = parameter.id in + let new_profile = parameter.new_profile in + let new_controller = parameter.new_controller in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if (sender = current_id_details.controller) || (sender = current_id_details.owner) + then true + else (failwith ("You are not the owner or controller of this ID."): bool) + in + let owner: address = current_id_details.owner in + let profile: bytes = + match new_profile with + | None -> (* Default *) current_id_details.profile + | Some new_profile -> new_profile + in + let controller: address = + match new_controller with + | None -> (* Default *) current_id_details.controller + | Some new_controller -> new_controller + in + let updated_id_details: id_details = { + owner = owner; + controller = controller; + profile = profile; + } + in let updated_identities: (id, id_details) big_map = - Big_map.update id (Some updated_id_details) identities - in ([]: operation list), (updated_identities, last_id, prices) + Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -(* Let someone skip the next identity so nobody has to take one that's -undesirable *) - -let skip (p, storage: unit * storage) = - let void : unit = - if Tezos.amount <> storage.2.1 - then (failwith "Incorrect amount paid." : unit) in - let identities, last_id, prices = storage in - ([]: operation list), (identities, last_id + 1, prices) +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +let skip (p,storage: unit * storage) = + let void: unit = + if amount = storage.skip_price + then () + else (failwith "Incorrect amount paid.": unit) + in + ([]: operation list), {identities = storage.identities; + next_id = storage.next_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } let main (action, storage : action * storage) : return = match action with diff --git a/src/test/id_tests.ml b/src/test/id_tests.ml index a1fca2a62..d65f9675d 100644 --- a/src/test/id_tests.ml +++ b/src/test/id_tests.ml @@ -40,9 +40,10 @@ let buy_id () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options @@ -54,11 +55,15 @@ let buy_id () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let param = e_pair owner_website (e_some (e_address new_addr)) in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr))) ; + ] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "buy" (e_pair param storage) @@ -73,9 +78,10 @@ let buy_id_sender_addr () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options @@ -87,11 +93,14 @@ let buy_id_sender_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let param = e_pair owner_website (e_typed_none (t_address ())) in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_typed_none (t_address ())))] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "buy" (e_pair param storage) @@ -107,18 +116,20 @@ let buy_id_wrong_amount () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options ~sender:first_contract ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () in - let param = e_pair owner_website (e_some (e_address new_addr)) in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr)))] in let%bind () = expect_string_failwith ~options (program, state) "buy" - (e_pair param storage) + (e_pair param storage) "Incorrect amount paid." in ok () @@ -133,7 +144,7 @@ let update_details_owner () = let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options ~sender:first_contract - ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) () in let new_website = e_bytes_string "ligolang.org" in @@ -144,20 +155,24 @@ let update_details_owner () = let id_details_2_diff = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 1 ; - e_some details ; - e_some (e_address new_addr)] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address new_addr))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -185,20 +200,24 @@ let update_details_controller () = let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; ("controller", e_address owner_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 1 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -224,15 +243,17 @@ let update_details_nonexistent () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 2 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 2) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_string_failwith ~options (program, state) "update_details" (e_pair param storage) "This ID does not exist." @@ -257,15 +278,17 @@ let update_details_wrong_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 0 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 0) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_string_failwith ~options (program, state) "update_details" (e_pair param storage) "You are not the owner or controller of this ID." @@ -291,14 +314,16 @@ let update_details_unchanged () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_tuple [e_int 1 ; - e_typed_none (t_bytes ()) ; - e_typed_none (t_address ())] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_typed_none (t_bytes ())) ; + ("new_controller", e_typed_none (t_address ()))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) storage) @@ -326,17 +351,22 @@ let update_owner () = let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 1) (e_address owner_addr) in + let param = e_record_ez [("id", e_int 1) ; + ("new_owner", e_address owner_addr)] in let%bind () = expect_eq ~options (program, state) "update_owner" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -362,12 +392,15 @@ let update_owner_nonexistent () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 2) (e_address new_addr) in + let param = e_record_ez [("id", e_int 2); + ("new_owner", e_address new_addr)] in let%bind () = expect_string_failwith ~options (program, state) "update_owner" (e_pair param storage) "This ID does not exist." @@ -393,12 +426,15 @@ let update_owner_wrong_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 0) (e_address new_addr) in + let param = e_record_ez [("id", e_int 0); + ("new_owner", e_address new_addr)] in let%bind () = expect_string_failwith ~options (program, state) "update_owner" (e_pair param storage) "You are not the owner of this ID." @@ -422,15 +458,19 @@ let skip () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 3; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 3) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "skip" (e_pair (e_unit ()) storage) @@ -456,10 +496,12 @@ let skip_wrong_amount () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_string_failwith ~options (program, state) "skip" (e_pair (e_unit ()) storage)