diff --git a/src/proto_alpha/lib_protocol/ticket_accounting.ml b/src/proto_alpha/lib_protocol/ticket_accounting.ml index 5eaf1ea7de319697dcda475442517cc29f2b344e..2dac9aaa1836a65e26301bab7d48e7682a659be1 100644 --- a/src/proto_alpha/lib_protocol/ticket_accounting.ml +++ b/src/proto_alpha/lib_protocol/ticket_accounting.ml @@ -51,11 +51,13 @@ module Ticket_token_map = struct include Ticket_token_map let balance_diff ctxt token map = - Ticket_token_map.find ctxt token map >|=? fun (amnt_opt, ctxt) -> + let open Lwt_tzresult_syntax in + let+ amnt_opt, ctxt = Ticket_token_map.find ctxt token map in (Option.value ~default:Z.zero amnt_opt, ctxt) let merge_overlap ctxt b1 b2 = - Gas.consume ctxt (Ticket_costs.add_z_cost b1 b2) >|? fun ctxt -> + let open Tzresult_syntax in + let+ ctxt = Gas.consume ctxt (Ticket_costs.add_z_cost b1 b2) in (Z.add b1 b2, ctxt) let of_list ctxt token_amounts = @@ -64,41 +66,53 @@ module Ticket_token_map = struct let add ctxt = Ticket_token_map.merge ctxt ~merge_overlap let sub ctxt m1 m2 = - map_e - ctxt - (fun ctxt _ amount -> - Gas.consume ctxt (Ticket_costs.negate_cost amount) >|? fun ctxt -> - (Z.neg amount, ctxt)) - m2 - >>? fun (m2, ctxt) -> add ctxt m1 m2 + let open Tzresult_syntax in + let* m2, ctxt = + map_e + ctxt + (fun ctxt _ex_token amount -> + let+ ctxt = Gas.consume ctxt (Ticket_costs.negate_cost amount) in + (Z.neg amount, ctxt)) + m2 + in + add ctxt m1 m2 end let ticket_balances_of_value ctxt ~include_lazy ty value = - Ticket_scanner.tickets_of_value ~include_lazy ctxt ty value - >>=? fun (tickets, ctxt) -> - List.fold_left_e - (fun (acc, ctxt) ticket -> - let token, amount = - Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket - in + let open Lwt_tzresult_syntax in + let* tickets, ctxt = + Ticket_scanner.tickets_of_value ~include_lazy ctxt ty value + in + let accum_ticket_balances (acc, ctxt) ticket = + let open Tzresult_syntax in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in + let+ ctxt = Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step - >|? fun ctxt -> - ( (token, Script_int.to_zint (amount :> Script_int.n Script_int.num)) - :: acc, - ctxt )) - ([], ctxt) - tickets - >>?= fun (list, ctxt) -> Ticket_token_map.of_list ctxt list + in + ( (token, Script_int.to_zint (amount :> Script_int.n Script_int.num)) :: acc, + ctxt ) + in + let*? token_amounts, ctxt = + List.fold_left_e accum_ticket_balances ([], ctxt) tickets + in + Ticket_token_map.of_list ctxt token_amounts let update_ticket_balances ctxt ~total_storage_diff token destinations = + let open Lwt_tzresult_syntax in List.fold_left_es (fun (tot_storage_diff, ctxt) (owner, delta) -> - Ticket_balance_key.of_ex_token ctxt ~owner token - >>=? fun (key_hash, ctxt) -> - Ticket_balance.adjust_balance ctxt key_hash ~delta - >>=? fun (storage_diff, ctxt) -> - Gas.consume ctxt (Ticket_costs.add_z_cost total_storage_diff storage_diff) - >>?= fun ctxt -> return (Z.add tot_storage_diff storage_diff, ctxt)) + let* key_hash, ctxt = Ticket_balance_key.of_ex_token ctxt ~owner token in + let* storage_diff, ctxt = + Ticket_balance.adjust_balance ctxt key_hash ~delta + in + let*? ctxt = + Gas.consume + ctxt + (Ticket_costs.add_z_cost total_storage_diff storage_diff) + in + return (Z.add tot_storage_diff storage_diff, ctxt)) (total_storage_diff, ctxt) destinations @@ -109,6 +123,7 @@ let invalid_ticket_transfer_error Invalid_ticket_transfer {ticketer = Contract.to_b58check ticketer; amount} let update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs = + let open Lwt_tzresult_syntax in List.fold_left_es (fun (total_storage_diff, ctxt) (ticket_token, amount) -> (* Diff is valid iff either: @@ -118,10 +133,11 @@ let update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs = let (Ticket_token.Ex_token {ticketer; _}) = ticket_token in Compare.Z.(amount <= Z.zero) || Contract.equal ticketer self_contract in - error_unless - is_valid_balance_update - (invalid_ticket_transfer_error ~ticket_token ~amount) - >>?= fun () -> + let*? () = + error_unless + is_valid_balance_update + (invalid_ticket_transfer_error ~ticket_token ~amount) + in update_ticket_balances ctxt ~total_storage_diff @@ -132,12 +148,15 @@ let update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs = let ticket_diffs_of_lazy_storage_diff ctxt ~storage_type_has_tickets lazy_storage_diff = + let open Lwt_tzresult_syntax in (* Only scan lazy-diffs for tickets in case the storage contains tickets. *) if Ticket_scanner.has_tickets storage_type_has_tickets then - Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff - ctxt - lazy_storage_diff - >>=? fun (diffs, ctxt) -> Ticket_token_map.of_list ctxt diffs + let* diffs, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff + ctxt + lazy_storage_diff + in + Ticket_token_map.of_list ctxt diffs else return (Ticket_token_map.empty, ctxt) (* TODO #2465 @@ -171,39 +190,48 @@ let ticket_diffs_of_lazy_storage_diff ctxt ~storage_type_has_tickets let ticket_diffs ctxt ~self_contract ~arg_type_has_tickets ~storage_type_has_tickets ~arg ~old_storage ~new_storage ~lazy_storage_diff = + let open Lwt_tzresult_syntax in (* Collect ticket-token balances of the incoming parameters. *) - ticket_balances_of_value ctxt ~include_lazy:true arg_type_has_tickets arg - >>=? fun (arg_tickets, ctxt) -> - ticket_diffs_of_lazy_storage_diff - ctxt - ~storage_type_has_tickets - lazy_storage_diff - >>=? fun (lazy_storage_diff, ctxt) -> - ticket_balances_of_value - ctxt - ~include_lazy:false - storage_type_has_tickets - old_storage - >>=? fun (old_storage_strict, ctxt) -> - ticket_balances_of_value - ctxt - ~include_lazy:false - storage_type_has_tickets - new_storage - >>=? fun (new_storage_strict, ctxt) -> - Ticket_token_map.add ctxt new_storage_strict lazy_storage_diff - >>?= fun (additions, ctxt) -> - Ticket_token_map.sub ctxt additions old_storage_strict - >>?= fun (total_storage_diff, ctxt) -> - Ticket_token_map.sub ctxt total_storage_diff arg_tickets - >>?= fun (diff, ctxt) -> - Ticket_token_map.to_ticket_receipt - ctxt - ~owner:Destination.(Contract self_contract) - total_storage_diff - >>=? fun (ticket_receipt, ctxt) -> return (diff, ticket_receipt, ctxt) + let* arg_tickets, ctxt = + ticket_balances_of_value ctxt ~include_lazy:true arg_type_has_tickets arg + in + let* lazy_storage_diff, ctxt = + ticket_diffs_of_lazy_storage_diff + ctxt + ~storage_type_has_tickets + lazy_storage_diff + in + let* old_storage_strict, ctxt = + ticket_balances_of_value + ctxt + ~include_lazy:false + storage_type_has_tickets + old_storage + in + let* new_storage_strict, ctxt = + ticket_balances_of_value + ctxt + ~include_lazy:false + storage_type_has_tickets + new_storage + in + let*? additions, ctxt = + Ticket_token_map.add ctxt new_storage_strict lazy_storage_diff + in + let*? total_storage_diff, ctxt = + Ticket_token_map.sub ctxt additions old_storage_strict + in + let*? diff, ctxt = Ticket_token_map.sub ctxt total_storage_diff arg_tickets in + let* ticket_receipt, ctxt = + Ticket_token_map.to_ticket_receipt + ctxt + ~owner:Destination.(Contract self_contract) + total_storage_diff + in + return (diff, ticket_receipt, ctxt) let update_ticket_balances ctxt ~self_contract ~ticket_diffs operations = + let open Lwt_tzresult_syntax in let validate_spending_budget ctxt (Ticket_token.Ex_token {ticketer; _} as ticket_token) amount = if Contract.equal ticketer self_contract then @@ -212,8 +240,9 @@ let update_ticket_balances ctxt ~self_contract ~ticket_diffs operations = stored in the ticket table and don't need to be updated here. *) return (true, ctxt) else - Ticket_token_map.balance_diff ctxt ticket_token ticket_diffs - >|=? fun (balance_diff, ctxt) -> + let+ balance_diff, ctxt = + Ticket_token_map.balance_diff ctxt ticket_token ticket_diffs + in (* The balance-diff represents the number of units of a ticket-token, that is changed for the [self] contract. A negative diff means that an amount of ticket-tokens were not saved in the storage and are @@ -227,34 +256,41 @@ let update_ticket_balances ctxt ~self_contract ~ticket_diffs operations = (Compare.Z.(Script_int.to_zint amount <= Z.neg balance_diff), ctxt) in (* Collect diffs from operations *) - Ticket_operations_diff.ticket_diffs_of_operations ctxt operations - >>=? fun (ticket_op_diffs, ctxt) -> + let* ticket_op_diffs, ctxt = + Ticket_operations_diff.ticket_diffs_of_operations ctxt operations + in (* Update balances for self-contract. *) - Ticket_token_map.to_list ctxt ticket_diffs >>?= fun (ticket_diffs, ctxt) -> - update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs - >>=? fun (total_storage_diff, ctxt) -> + let*? ticket_diffs, ctxt = Ticket_token_map.to_list ctxt ticket_diffs in + let* total_storage_diff, ctxt = + update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs + in (* Update balances for operations. *) List.fold_left_es (fun (total_storage_diff, ctxt) {Ticket_operations_diff.ticket_token; total_amount; destinations} -> (* Verify that we are able to spend the given amount of ticket-tokens. *) - validate_spending_budget ctxt ticket_token total_amount - >>=? fun (is_valid_balance_update, ctxt) -> - error_unless - is_valid_balance_update - (invalid_ticket_transfer_error - ~ticket_token - ~amount:(Script_int.to_zint total_amount)) - >>?= fun () -> - List.fold_left_e - (fun (acc, ctxt) (token, (amount : Script_typed_ir.ticket_amount)) -> - (* Consume some gas for for traversing the list. *) - Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step - >|? fun ctxt -> - ((token, Script_int.(to_zint (amount :> n num))) :: acc, ctxt)) - ([], ctxt) - destinations - >>?= fun (destinations, ctxt) -> + let* is_valid_balance_update, ctxt = + validate_spending_budget ctxt ticket_token total_amount + in + let*? () = + error_unless + is_valid_balance_update + (invalid_ticket_transfer_error + ~ticket_token + ~amount:(Script_int.to_zint total_amount)) + in + let*? destinations, ctxt = + List.fold_left_e + (fun (acc, ctxt) (token, (amount : Script_typed_ir.ticket_amount)) -> + (* Consume some gas for traversing the list. *) + let open Tzresult_syntax in + let+ ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + ((token, Script_int.(to_zint (amount :> n num))) :: acc, ctxt)) + ([], ctxt) + destinations + in update_ticket_balances ctxt ~total_storage_diff ticket_token destinations) (total_storage_diff, ctxt) ticket_op_diffs