From 24deb10c8f0b466352b688c82fe13812c9de02c1 Mon Sep 17 00:00:00 2001 From: Benjamin Canou Date: Sun, 8 Apr 2018 17:56:01 +0200 Subject: [PATCH] Michelson: cleanup big map initialization and account for its fees --- .../lib_protocol/src/alpha_context.mli | 10 ++-- src/proto_alpha/lib_protocol/src/apply.ml | 16 +----- .../lib_protocol/src/contract_storage.ml | 56 +++++++++---------- .../lib_protocol/src/contract_storage.mli | 6 +- .../lib_protocol/src/script_interpreter.ml | 2 +- .../lib_protocol/src/script_ir_translator.mli | 4 +- 6 files changed, 38 insertions(+), 56 deletions(-) diff --git a/src/proto_alpha/lib_protocol/src/alpha_context.mli b/src/proto_alpha/lib_protocol/src/alpha_context.mli index e2c785464..ba4a74a6a 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_context.mli @@ -511,12 +511,14 @@ module Contract : sig val get_balance: context -> contract -> Tez.t tzresult Lwt.t + type big_map_diff = (string * Script.expr option) list + val originate: context -> origination_nonce -> balance: Tez.t -> manager: public_key_hash -> - ?script: Script.t -> + ?script: (Script.t * big_map_diff option) -> delegate: public_key_hash option -> spendable: bool -> delegatable: bool -> (context * contract * origination_nonce) tzresult Lwt.t @@ -533,7 +535,7 @@ module Contract : sig val update_script_storage: context -> contract -> - Script.expr -> (string * Script.expr option) list option -> + Script.expr -> big_map_diff option -> context tzresult Lwt.t val fees: context -> t -> Tez.t tzresult Lwt.t @@ -547,10 +549,6 @@ module Contract : sig context -> contract -> int32 -> unit tzresult Lwt.t module Big_map : sig - val set: - context -> contract -> string -> Script.expr -> context tzresult Lwt.t - val remove: - context -> contract -> string -> context tzresult Lwt.t val mem: context -> contract -> string -> (context * bool) tzresult Lwt.t val get_opt: diff --git a/src/proto_alpha/lib_protocol/src/apply.ml b/src/proto_alpha/lib_protocol/src/apply.ml index b61d89888..b73ad5b2a 100644 --- a/src/proto_alpha/lib_protocol/src/apply.ml +++ b/src/proto_alpha/lib_protocol/src/apply.ml @@ -424,12 +424,12 @@ let apply_manager_operation_content spendable ; delegatable ; credit ; gas_limit } -> Lwt.return (Gas.set_limit ctxt gas_limit) >>=? fun ctxt -> begin match script with - | None -> return (None, None, ctxt) + | None -> return (None, ctxt) | Some script -> Script_ir_translator.parse_script ctxt script >>=? fun (_, ctxt) -> Script_ir_translator.erase_big_map_initialization ctxt script >>=? fun (script, big_map_diff, ctxt) -> - return (Some script, big_map_diff, ctxt) - end >>=? fun (script, big_map, ctxt) -> + return (Some (script, big_map_diff), ctxt) + end >>=? fun (script, ctxt) -> Contract.spend ctxt source credit >>=? fun ctxt -> Contract.originate ctxt origination_nonce @@ -437,16 +437,6 @@ let apply_manager_operation_content ?script ~spendable ~delegatable >>=? fun (ctxt, contract, origination_nonce) -> Fees.origination_burn ctxt ~source contract >>=? fun ctxt -> - begin match big_map with - | None -> return ctxt - | Some diff -> - fold_left_s (fun ctxt (key, value) -> - match value with - | None -> Contract.Big_map.remove ctxt contract key - | Some v -> - Contract.Big_map.set ctxt contract key v) - ctxt diff - end >>=? fun ctxt -> return (ctxt, origination_nonce, None, Tez.zero) | Delegation delegate -> Delegate.set ctxt source delegate >>=? fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/src/contract_storage.ml b/src/proto_alpha/lib_protocol/src/contract_storage.ml index 679633e59..87304f926 100644 --- a/src/proto_alpha/lib_protocol/src/contract_storage.ml +++ b/src/proto_alpha/lib_protocol/src/contract_storage.ml @@ -190,6 +190,27 @@ let add_fees_for_bytes c base added = base +? added end +type big_map_diff = (string * Script_repr.expr option) list + +let update_script_big_map c contract = function + | None -> return (c, Tez_repr.zero, Tez_repr.zero) + | Some diff -> + fold_left_s (fun (c, total_added, total_freed) (key, value) -> + match value with + | None -> + Storage.Contract.Big_map.remove (c, contract) key >>=? fun (c, freed) -> + add_fees_for_bytes c total_freed freed >>=? fun total_freed -> + return (c, total_added, total_freed) + | Some v -> + Storage.Contract.Big_map.init_set (c, contract) key v >>=? fun (c, diff) -> + if Compare.Int.(diff > 0) then + add_fees_for_bytes c total_added diff >>=? fun total_added -> + return (c, total_added, total_freed) + else + add_fees_for_bytes c total_freed (-diff) >>=? fun total_freed -> + return (c, total_added, total_freed)) + (c, Tez_repr.zero, Tez_repr.zero) diff + let create_base c contract ~balance ~manager ~delegate ?script ~spendable ~delegatable = (match Contract_repr.is_implicit contract with @@ -207,12 +228,15 @@ let create_base c contract Storage.Contract.Delegatable.set c contract delegatable >>= fun c -> Storage.Contract.Counter.init c contract counter >>=? fun c -> (match script with - | Some { Script_repr.code ; storage } -> + | Some ({ Script_repr.code ; storage }, big_map_diff) -> let fees = Tez_repr.zero in Storage.Contract.Code.init c contract code >>=? fun (c, code_size) -> add_fees_for_bytes c fees code_size >>=? fun fees -> Storage.Contract.Storage.init c contract storage >>=? fun (c, storage_size) -> add_fees_for_bytes c fees storage_size >>=? fun fees -> + update_script_big_map c contract big_map_diff >>=? fun (c, total_added, total_freed) -> + assert (Tez_repr.equal total_freed Tez_repr.zero) ; + Lwt.return (Tez_repr.(fees +? total_added)) >>=? fun fees -> Storage.Contract.Fees.init c contract fees >>=? fun c -> Storage.Contract.Paid_fees.init c contract Tez_repr.zero | None -> @@ -352,28 +376,8 @@ let is_spendable c contract = | None -> Storage.Contract.Spendable.mem c contract >>= return -type big_map_diff = (string * Script_repr.expr option) list - -let update_script_storage c contract storage big_map = - begin match big_map with - | None -> return (c, Tez_repr.zero, Tez_repr.zero) - | Some diff -> - fold_left_s (fun (c, total_added, total_freed) (key, value) -> - match value with - | None -> - Storage.Contract.Big_map.remove (c, contract) key >>=? fun (c, freed) -> - add_fees_for_bytes c total_freed freed >>=? fun total_freed -> - return (c, total_added, total_freed) - | Some v -> - Storage.Contract.Big_map.init_set (c, contract) key v >>=? fun (c, diff) -> - if Compare.Int.(diff > 0) then - add_fees_for_bytes c total_added diff >>=? fun total_added -> - return (c, total_added, total_freed) - else - add_fees_for_bytes c total_freed (-diff) >>=? fun total_freed -> - return (c, total_added, total_freed)) - (c, Tez_repr.zero, Tez_repr.zero) diff - end >>=? fun (c, total_added, total_freed) -> +let update_script_storage c contract storage big_map_diff = + update_script_big_map c contract big_map_diff >>=? fun (c, total_added, total_freed) -> Storage.Contract.Storage.set c contract storage >>=? fun (c, diff) -> begin if Compare.Int.(diff > 0) then add_fees_for_bytes c total_added diff >>=? fun total_added -> @@ -473,12 +477,6 @@ let add_to_paid_fees c contract fees = Storage.Contract.Paid_fees.set c contract paid_fees module Big_map = struct - let set ctxt contract key value = - Storage.Contract.Big_map.init_set (ctxt, contract) key value >>=? fun (c, _) -> - return c (* ignore the fees*) - let remove ctxt contract key = - Storage.Contract.Big_map.delete (ctxt, contract) key >>=? fun (c, _) -> - return c (* ignore the fees*) let mem ctxt contract key = Storage.Contract.Big_map.mem (ctxt, contract) key let get_opt ctxt contract key = diff --git a/src/proto_alpha/lib_protocol/src/contract_storage.mli b/src/proto_alpha/lib_protocol/src/contract_storage.mli index 2bfd890dc..0ee4aee96 100644 --- a/src/proto_alpha/lib_protocol/src/contract_storage.mli +++ b/src/proto_alpha/lib_protocol/src/contract_storage.mli @@ -86,7 +86,7 @@ val originate: Contract_repr.origination_nonce -> balance:Tez_repr.t -> manager:Signature.Public_key_hash.t -> - ?script:Script_repr.t -> + ?script:(Script_repr.t * big_map_diff option) -> delegate:Signature.Public_key_hash.t option -> spendable:bool -> delegatable:bool -> @@ -101,10 +101,6 @@ val paid_fees: Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t val add_to_paid_fees: Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t module Big_map : sig - val set : - Raw_context.t -> Contract_repr.t -> string -> Script_repr.expr -> Raw_context.t tzresult Lwt.t - val remove : - Raw_context.t -> Contract_repr.t -> string -> Raw_context.t tzresult Lwt.t val mem : Raw_context.t -> Contract_repr.t -> string -> (Raw_context.t * bool) tzresult Lwt.t val get_opt : diff --git a/src/proto_alpha/lib_protocol/src/script_interpreter.ml b/src/proto_alpha/lib_protocol/src/script_interpreter.ml index 144694b2a..fc02a22e9 100644 --- a/src/proto_alpha/lib_protocol/src/script_interpreter.ml +++ b/src/proto_alpha/lib_protocol/src/script_interpreter.ml @@ -169,7 +169,7 @@ let rec interp Contract.originate ctxt origination ~manager ~delegate ~balance:credit - ~script:{ code ; storage } + ~script:({ code ; storage }, None (* TODO: initialize a big map from a map *)) ~spendable ~delegatable >>=? fun (ctxt, contract, origination) -> Fees.origination_burn ctxt ~source:orig contract >>=? fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/src/script_ir_translator.mli b/src/proto_alpha/lib_protocol/src/script_ir_translator.mli index b23a028af..5c7e3b14e 100644 --- a/src/proto_alpha/lib_protocol/src/script_ir_translator.mli +++ b/src/proto_alpha/lib_protocol/src/script_ir_translator.mli @@ -87,7 +87,7 @@ val extract_big_map : 'a Script_typed_ir.ty -> 'a -> Script_typed_ir.ex_big_map val to_serializable_big_map : context -> Script_typed_ir.ex_big_map -> - (Contract_storage.big_map_diff * context) tzresult Lwt.t + (Contract.big_map_diff * context) tzresult Lwt.t val to_printable_big_map : context -> Script_typed_ir.ex_big_map -> @@ -95,4 +95,4 @@ val to_printable_big_map : val erase_big_map_initialization : context -> Script.t -> - (Script.t * Contract_storage.big_map_diff option * context) tzresult Lwt.t + (Script.t * Contract.big_map_diff option * context) tzresult Lwt.t