Alpha: keep the storage space in bytes instead of the premultiplied fees

This commit is contained in:
Benjamin Canou 2018-04-22 17:42:13 +02:00 committed by Grégoire Henry
parent 7d73605f5c
commit dd9cd8a1c3
14 changed files with 110 additions and 111 deletions

View File

@ -249,7 +249,7 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
"This delegation was successfully applied"
| Applied (Transaction_result { balance_updates ; consumed_gas ;
operations ; storage ;
originated_contracts ; storage_fees_increment }) ->
originated_contracts ; storage_size_diff }) ->
Format.fprintf ppf
"This transaction was successfully applied" ;
begin match operations with
@ -268,11 +268,10 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
Format.fprintf ppf "@,@[<hv 2>Updated storage:@ %a@]"
Michelson_v1_printer.print_expr expr
end ;
begin if storage_fees_increment <> Tez.zero then
begin if storage_size_diff <> 0L then
Format.fprintf ppf
"@,Storage fees increment: %s%a"
Client_proto_args.tez_sym
Tez.pp storage_fees_increment
"@,Storage size difference: %Ld bytes"
storage_size_diff
end ;
Format.fprintf ppf
"@,Consumed gas: %s"
@ -285,7 +284,7 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
pp_balance_updates balance_updates
end
| Applied (Origination_result { balance_updates ; consumed_gas ;
originated_contracts ; storage_fees_increment }) ->
originated_contracts ; storage_size_diff }) ->
Format.fprintf ppf
"This origination was successfully applied" ;
begin match originated_contracts with
@ -294,11 +293,10 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
Format.fprintf ppf "@,@[<v 2>Originated contracts:@,%a@]"
(Format.pp_print_list Contract.pp) contracts
end ;
begin if storage_fees_increment <> Tez.zero then
begin if storage_size_diff <> 0L then
Format.fprintf ppf
"@,Storage fees increment: %s%a"
Client_proto_args.tez_sym
Tez.pp storage_fees_increment
"@,Storage size used: %Ld bytes"
storage_size_diff
end ;
Format.fprintf ppf
"@,Consumed gas: %s"

View File

@ -337,6 +337,7 @@ module Constants : sig
val endorsers_per_block: context -> int
val hard_gas_limit_per_operation: context -> Z.t
val hard_gas_limit_per_block: context -> Z.t
val cost_per_byte: context -> Tez.t
val proof_of_work_threshold: context -> int64
val dictator_pubkey: context -> Signature.Public_key.t
val max_operation_data_length: context -> int
@ -541,9 +542,9 @@ module Contract : sig
Script.expr -> big_map_diff option ->
context tzresult Lwt.t
val fees: context -> t -> Tez.t tzresult Lwt.t
val paid_fees: context -> t -> Tez.t tzresult Lwt.t
val add_to_paid_fees: context -> t -> Tez.t -> context tzresult Lwt.t
val used_storage_space: context -> t -> Int64.t tzresult Lwt.t
val paid_storage_space_fees: context -> t -> Tez.t tzresult Lwt.t
val pay_for_storage_space: context -> t -> Tez.t -> context tzresult Lwt.t
val increment_counter:
context -> contract -> context tzresult Lwt.t

View File

@ -419,7 +419,7 @@ let apply_manager_operation_content ctxt ~payer ~source ~internal operation =
Contract destination, Credited amount ] ;
originated_contracts = [] ;
consumed_gas = gas_difference before_operation ctxt ;
storage_fees_increment = Tez.zero } in
storage_size_diff = 0L } in
return (ctxt, result)
| Some script ->
Lwt.return @@ Script_ir_translator.parse_toplevel script.code >>=? fun (arg_type, _, _) ->
@ -439,10 +439,11 @@ let apply_manager_operation_content ctxt ~payer ~source ~internal operation =
~check_operations:(not internal)
~source ~payer ~self:(destination, script) ~amount ~parameter
>>=? fun { ctxt ; storage ; big_map_diff ; operations } ->
Contract.used_storage_space ctxt destination >>=? fun old_size ->
Contract.update_script_storage
ctxt destination storage big_map_diff >>=? fun ctxt ->
Fees.update_script_storage
ctxt ~payer destination >>=? fun (ctxt, fees) ->
ctxt ~payer destination >>=? fun (ctxt, new_size, fees) ->
new_contracts before_operation ctxt >>=? fun originated_contracts ->
let result =
Transaction_result
@ -455,7 +456,7 @@ let apply_manager_operation_content ctxt ~payer ~source ~internal operation =
Contract destination, Credited amount ] ;
originated_contracts ;
consumed_gas = gas_difference before_operation ctxt ;
storage_fees_increment = fees } in
storage_size_diff = Int64.sub new_size old_size } in
return (ctxt, result)
end
| Origination { manager ; delegate ; script ; preorigination ;
@ -476,7 +477,7 @@ let apply_manager_operation_content ctxt ~payer ~source ~internal operation =
~manager ~delegate ~balance:credit
?script
~spendable ~delegatable >>=? fun ctxt ->
Fees.origination_burn ctxt ~payer contract >>=? fun (ctxt, fees) ->
Fees.origination_burn ctxt ~payer contract >>=? fun (ctxt, size, fees) ->
let result =
Origination_result
{ balance_updates =
@ -486,7 +487,7 @@ let apply_manager_operation_content ctxt ~payer ~source ~internal operation =
Contract contract, Credited credit ] ;
originated_contracts = [ contract ] ;
consumed_gas = gas_difference before_operation ctxt ;
storage_fees_increment = fees } in
storage_size_diff = size } in
return (ctxt, result)
| Delegation delegate ->
set_delegate ctxt source delegate >>=? fun ctxt ->

View File

@ -110,12 +110,12 @@ type successful_manager_operation_result =
balance_updates : balance_updates ;
originated_contracts : Contract.t list ;
consumed_gas : Z.t ;
storage_fees_increment : Tez.t }
storage_size_diff : Int64.t }
| Origination_result of
{ balance_updates : balance_updates ;
originated_contracts : Contract.t list ;
consumed_gas : Z.t ;
storage_fees_increment : Tez.t }
storage_size_diff : Int64.t }
| Delegation_result
type manager_operation_kind =
@ -153,23 +153,23 @@ let manager_operation_result_encoding =
(dft "balance_updates" balance_updates_encoding [])
(dft "originated_contracts" (list Contract.encoding) [])
(dft "consumed_gas" z Z.zero)
(dft "storage_fees_increment" Tez.encoding Tez.zero))
(dft "storage_size_diff" int64 0L))
(function
| Applied (Transaction_result
{ operations ; storage ; balance_updates ;
originated_contracts ; consumed_gas ;
storage_fees_increment }) ->
storage_size_diff }) ->
Some ((), (), operations, storage, balance_updates,
originated_contracts, consumed_gas,
storage_fees_increment)
storage_size_diff)
| _ -> None)
(fun ((), (), operations, storage, balance_updates,
originated_contracts, consumed_gas,
storage_fees_increment) ->
storage_size_diff) ->
Applied (Transaction_result
{ operations ; storage ; balance_updates ;
originated_contracts ; consumed_gas ;
storage_fees_increment })) ;
storage_size_diff })) ;
case Json_only
(obj6
(req "status" (constant "applied"))
@ -177,23 +177,23 @@ let manager_operation_result_encoding =
(dft "balance_updates" balance_updates_encoding [])
(dft "originated_contracts" (list Contract.encoding) [])
(dft "consumed_gas" z Z.zero)
(dft "storage_fees_increment" Tez.encoding Tez.zero))
(dft "storage_size_diff" int64 0L))
(function
| Applied (Origination_result
{ balance_updates ;
originated_contracts ; consumed_gas ;
storage_fees_increment }) ->
storage_size_diff }) ->
Some ((), (), balance_updates,
originated_contracts, consumed_gas,
storage_fees_increment)
storage_size_diff)
| _ -> None)
(fun ((), (), balance_updates,
originated_contracts, consumed_gas,
storage_fees_increment) ->
storage_size_diff) ->
Applied (Origination_result
{ balance_updates ;
originated_contracts ; consumed_gas ;
storage_fees_increment })) ;
storage_size_diff })) ;
case Json_only
(obj2
(req "status" (constant "applied"))

View File

@ -83,12 +83,12 @@ and successful_manager_operation_result =
balance_updates : balance_updates ;
originated_contracts : Contract.t list ;
consumed_gas : Z.t ;
storage_fees_increment : Tez.t }
storage_size_diff : Int64.t }
| Origination_result of
{ balance_updates : balance_updates ;
originated_contracts : Contract.t list ;
consumed_gas : Z.t ;
storage_fees_increment : Tez.t }
storage_size_diff : Int64.t }
| Delegation_result
(** Serializer for {!proto_operation_result}. *)

View File

@ -88,6 +88,13 @@ module S = struct
~output: (obj2 (req "per_block" z) (req "per_operation" z))
RPC_path.(custom_root / "hard_gas_limits")
let cost_per_byte =
RPC_service.post_service
~description: "The cost per bytes added to the storage"
~query: RPC_query.empty
~input: empty
~output: (obj1 (req "cost_per_byte" Tez.encoding))
RPC_path.(custom_root / "cost_per_byte")
let proof_of_work_threshold =
RPC_service.post_service
@ -194,6 +201,9 @@ let () =
return (Constants.hard_gas_limit_per_block ctxt,
Constants.hard_gas_limit_per_operation ctxt)
end ;
register0 S.cost_per_byte begin fun ctxt () () ->
return (Constants.cost_per_byte ctxt)
end ;
register0 S.proof_of_work_threshold begin fun ctxt () () ->
return (Constants.proof_of_work_threshold ctxt)
end ;
@ -242,6 +252,8 @@ let endorsers_per_block ctxt block =
RPC_context.make_call0 S.endorsers_per_block ctxt block () ()
let hard_gas_limits ctxt block =
RPC_context.make_call0 S.hard_gas_limits ctxt block () ()
let cost_per_byte ctxt block =
RPC_context.make_call0 S.cost_per_byte ctxt block () ()
let proof_of_work_threshold ctxt block =
RPC_context.make_call0 S.proof_of_work_threshold ctxt block () ()
let seed_nonce_revelation_tip ctxt block =

View File

@ -36,6 +36,10 @@ val endorsers_per_block:
val hard_gas_limits:
'a #RPC_context.simple -> 'a -> (Z.t * Z.t) shell_tzresult Lwt.t
val cost_per_byte:
'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t
val proof_of_work_threshold:
'a #RPC_context.simple -> 'a -> Int64.t shell_tzresult Lwt.t

View File

@ -37,6 +37,9 @@ let hard_gas_limit_per_operation c =
let hard_gas_limit_per_block c =
let constants = Raw_context.constants c in
constants.hard_gas_limit_per_block
let cost_per_byte c =
let constants = Raw_context.constants c in
constants.cost_per_byte
let proof_of_work_threshold c =
let constants = Raw_context.constants c in
constants.proof_of_work_threshold

View File

@ -182,34 +182,20 @@ let () =
let failwith msg = fail (Failure msg)
let add_fees_for_bytes c base added =
let open Tez_repr in
let cost_per_byte = (Raw_context.constants c).cost_per_byte in
Lwt.return begin
cost_per_byte *? Int64.of_int added >>? fun 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)
| None -> return (c, 0L)
| Some diff ->
fold_left_s (fun (c, total_added, total_freed) (key, value) ->
fold_left_s (fun (c, total) (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)
return (c, Int64.sub total (Int64.of_int 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
Storage.Contract.Big_map.init_set (c, contract) key v >>=? fun (c, size_diff) ->
return (c, Int64.add total (Int64.of_int size_diff)))
(c, 0L) diff
let create_base c contract
~balance ~manager ~delegate ?script ~spendable ~delegatable =
@ -229,16 +215,13 @@ let create_base c contract
Storage.Contract.Counter.init c contract counter >>=? fun c ->
(match script with
| 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
update_script_big_map c contract big_map_diff >>=? fun (c, big_map_size) ->
let total_size = Int64.add (Int64.add (Int64.of_int code_size) (Int64.of_int storage_size)) big_map_size in
assert Compare.Int64.(total_size >= 0L) ;
Storage.Contract.Used_storage_space.init c contract total_size >>=? fun c ->
Storage.Contract.Paid_storage_space_fees.init c contract Tez_repr.zero
| None ->
return c) >>=? fun c ->
return c
@ -260,8 +243,8 @@ let delete c contract =
Storage.Contract.Counter.delete c contract >>=? fun c ->
Storage.Contract.Code.remove c contract >>=? fun (c, _) ->
Storage.Contract.Storage.remove c contract >>=? fun (c, _) ->
Storage.Contract.Paid_fees.remove c contract >>= fun c ->
Storage.Contract.Fees.remove c contract >>= fun c ->
Storage.Contract.Paid_storage_space_fees.remove c contract >>= fun c ->
Storage.Contract.Used_storage_space.remove c contract >>= fun c ->
Storage.Contract.Big_map.clear (c, contract) >>=? fun (c, _) ->
return c
@ -387,20 +370,11 @@ let is_spendable c contract =
Storage.Contract.Spendable.mem c contract >>= return
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 ->
return (c, total_added, total_freed)
else
add_fees_for_bytes c total_freed (-diff) >>=? fun total_freed ->
return (c, total_added, total_freed)
end >>=? fun (c, total_added, total_freed) ->
Storage.Contract.Fees.get c contract >>=? fun fees ->
Lwt.return (Tez_repr.(fees +? total_added)) >>=? fun fees ->
Lwt.return (Tez_repr.(fees -? total_freed)) >>=? fun fees ->
Storage.Contract.Fees.set c contract fees >>=? fun c ->
return c
update_script_big_map c contract big_map_diff >>=? fun (c, big_map_size_diff) ->
Storage.Contract.Storage.set c contract storage >>=? fun (c, size_diff) ->
Storage.Contract.Used_storage_space.get c contract >>=? fun previous_size ->
let new_size = Int64.add previous_size (Int64.add big_map_size_diff (Int64.of_int size_diff)) in
Storage.Contract.Used_storage_space.set c contract new_size
let spend_from_script c contract amount =
Storage.Contract.Balance.get c contract >>=? fun balance ->
@ -467,23 +441,23 @@ let spend c contract amount =
let init c =
Storage.Contract.Global_counter.init c 0l
let fees c contract =
Storage.Contract.Fees.get_option c contract >>=? function
| None -> return Tez_repr.zero
let used_storage_space c contract =
Storage.Contract.Used_storage_space.get_option c contract >>=? function
| None -> return 0L
| Some fees -> return fees
let paid_fees c contract =
Storage.Contract.Paid_fees.get_option c contract >>=? function
let paid_storage_space_fees c contract =
Storage.Contract.Paid_storage_space_fees.get_option c contract >>=? function
| None -> return Tez_repr.zero
| Some paid_fees -> return paid_fees
let add_to_paid_fees c contract fees =
let pay_for_storage_space c contract fees =
if Tez_repr.equal fees Tez_repr.zero then
return c
else
Storage.Contract.Paid_fees.get c contract >>=? fun paid_fees ->
Storage.Contract.Paid_storage_space_fees.get c contract >>=? fun paid_fees ->
Lwt.return (Tez_repr.(paid_fees +? fees)) >>=? fun paid_fees ->
Storage.Contract.Paid_fees.set c contract paid_fees
Storage.Contract.Paid_storage_space_fees.set c contract paid_fees
module Big_map = struct
let mem ctxt contract key =

View File

@ -100,10 +100,9 @@ val originated_from_current_nonce :
val init:
Raw_context.t -> Raw_context.t tzresult Lwt.t
val fees: Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t
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
val used_storage_space: Raw_context.t -> Contract_repr.t -> Int64.t tzresult Lwt.t
val paid_storage_space_fees: Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t
val pay_for_storage_space: Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t
module Big_map : sig
val mem :

View File

@ -26,22 +26,26 @@ let () =
let origination_burn c ~payer contract =
let origination_burn = Constants.origination_burn c in
Contract.spend_from_script c payer origination_burn >>=? fun c ->
Contract.fees c contract >>=? fun fees ->
Contract.used_storage_space c contract >>=? fun size ->
let cost_per_byte = Constants.cost_per_byte c in
Lwt.return (Tez.(cost_per_byte *? size)) >>=? fun fees ->
trace Cannot_pay_storage_fee
(Contract.spend_from_script c payer fees >>=? fun c ->
Contract.add_to_paid_fees c contract fees) >>=? fun c ->
return (c, fees)
Contract.pay_for_storage_space c contract fees) >>=? fun c ->
return (c, size, fees)
let update_script_storage c ~payer contract =
Contract.paid_fees c contract >>=? fun paid_fees ->
Contract.fees c contract >>=? fun fees ->
Contract.paid_storage_space_fees c contract >>=? fun paid_fees ->
Contract.used_storage_space c contract >>=? fun size ->
let cost_per_byte = Constants.cost_per_byte c in
Lwt.return (Tez.(cost_per_byte *? size)) >>=? fun fees ->
match Tez.(fees -? paid_fees) with
| Error _ ->
(* Previously paid fees are greater than required fees. *)
return (c, Tez.zero)
return (c, size, Tez.zero)
| Ok to_be_paid ->
(* Burning the fees... *)
trace Cannot_pay_storage_fee
(Contract.spend_from_script c payer to_be_paid >>=? fun c ->
Contract.add_to_paid_fees c contract to_be_paid) >>=? fun c ->
return (c, to_be_paid)
Contract.pay_for_storage_space c contract to_be_paid) >>=? fun c ->
return (c, size, to_be_paid)

View File

@ -13,9 +13,9 @@ type error += Cannot_pay_storage_fee
val origination_burn:
Alpha_context.t -> payer:Contract.t ->
Contract.t -> (Alpha_context.t * Tez.t) tzresult Lwt.t
Contract.t -> (Alpha_context.t * Int64.t * Tez.t) tzresult Lwt.t
val update_script_storage:
Alpha_context.t -> payer:Contract.t ->
Contract.t -> (Alpha_context.t * Tez.t) tzresult Lwt.t
Contract.t -> (Alpha_context.t * Int64.t * Tez.t) tzresult Lwt.t

View File

@ -19,6 +19,11 @@ module Int32 = struct
let encoding = Data_encoding.int32
end
module Int64 = struct
type t = Int64.t
let encoding = Data_encoding.int64
end
module Int_index = struct
type t = int
let path_length = 1
@ -161,15 +166,15 @@ module Contract = struct
let encoding = Script_repr.expr_encoding
end))
module Paid_fees =
module Paid_storage_space_fees =
Indexed_context.Make_map
(struct let name = ["paid_fees"] end)
(struct let name = ["paid_bytes"] end)
(Make_value(Tez_repr))
module Fees =
module Used_storage_space =
Indexed_context.Make_map
(struct let name = ["fees"] end)
(Make_value(Tez_repr))
(struct let name = ["used_bytes"] end)
(Make_value(Int64))
module Roll_list =
Indexed_context.Make_map

View File

@ -172,17 +172,15 @@ module Contract : sig
and type value = Script_repr.expr
and type t := Raw_context.t
(** Exact cost of current storage.
Includes code, global storage and big map elements.
Always less than or equal to {!Paid_fees}. *)
module Fees : Indexed_data_storage
(** Current storage space in bytes.
Includes code, global storage and big map elements. *)
module Used_storage_space : Indexed_data_storage
with type key = Contract_repr.t
and type value = Tez_repr.t
and type value = Int64.t
and type t := Raw_context.t
(** Maximum cost of storage since the contract's origination.
Always greater than or equal to {!Fees}. *)
module Paid_fees : Indexed_data_storage
(** Total fees burnt for storage space. *)
module Paid_storage_space_fees : Indexed_data_storage
with type key = Contract_repr.t
and type value = Tez_repr.t
and type t := Raw_context.t