Alpha: add storage limits

This commit is contained in:
Benjamin Canou 2018-04-22 19:57:49 +02:00 committed by Grégoire Henry
parent dd9cd8a1c3
commit 23f9949e70
29 changed files with 401 additions and 100 deletions

View File

@ -163,6 +163,20 @@ let gas_limit_arg =
return v return v
with _ -> failwith "invalid gas limit (must be a positive number)")) with _ -> failwith "invalid gas limit (must be a positive number)"))
let storage_limit_arg =
arg
~long:"storage-limit"
~short:'S'
~placeholder:"amount"
~doc:"Set the storage limit of the transaction instead \
of letting the client decide based on a simulation"
(parameter (fun _ s ->
try
let v = Int64.of_string s in
assert Compare.Int64.(v >= 0L) ;
return v
with _ -> failwith "invalid storage limit (must be a positive number of bytes)"))
let max_priority_arg = let max_priority_arg =
arg arg
~long:"max-priority" ~long:"max-priority"

View File

@ -15,6 +15,7 @@ val tez_sym: string
val init_arg: (string, Proto_alpha.full) Clic.arg val init_arg: (string, Proto_alpha.full) Clic.arg
val fee_arg: (Tez.t, Proto_alpha.full) Clic.arg val fee_arg: (Tez.t, Proto_alpha.full) Clic.arg
val gas_limit_arg: (Z.t option, Proto_alpha.full) Clic.arg val gas_limit_arg: (Z.t option, Proto_alpha.full) Clic.arg
val storage_limit_arg: (Int64.t option, Proto_alpha.full) Clic.arg
val arg_arg: (string, Proto_alpha.full) Clic.arg val arg_arg: (string, Proto_alpha.full) Clic.arg
val source_arg: (string option, Proto_alpha.full) Clic.arg val source_arg: (string option, Proto_alpha.full) Clic.arg

View File

@ -39,7 +39,7 @@ let append_reveal
let transfer (cctxt : #Proto_alpha.full) let transfer (cctxt : #Proto_alpha.full)
block ?confirmations block ?confirmations
?branch ~source ~src_pk ~src_sk ~destination ?arg ?branch ~source ~src_pk ~src_sk ~destination ?arg
~amount ~fee ?(gas_limit = Z.minus_one) () = ~amount ~fee ?(gas_limit = Z.minus_one) ?(storage_limit = -1L) () =
begin match arg with begin match arg with
| Some arg -> | Some arg ->
parse_expression arg >>=? fun { expanded = arg } -> parse_expression arg >>=? fun { expanded = arg } ->
@ -54,7 +54,7 @@ let transfer (cctxt : #Proto_alpha.full)
let contents = let contents =
Sourced_operation Sourced_operation
(Manager_operations { source ; fee ; counter ; (Manager_operations { source ; fee ; counter ;
gas_limit ; operations }) in gas_limit ; storage_limit ; operations }) in
Injection.inject_operation cctxt block ?confirmations Injection.inject_operation cctxt block ?confirmations
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) -> ?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> Lwt.return (Injection.originated_contracts result) >>=? fun contracts ->
@ -70,18 +70,19 @@ let reveal cctxt
| [] -> | [] ->
failwith "The manager key was previously revealed." failwith "The manager key was previously revealed."
| _ :: _ -> | _ :: _ ->
let gas_limit = Z.zero in
let contents = let contents =
Sourced_operation Sourced_operation
(Manager_operations { source ; fee ; counter ; (Manager_operations { source ; fee ; counter ;
gas_limit ; operations }) in gas_limit = Z.zero ; storage_limit = 0L ;
operations }) in
Injection.inject_operation cctxt block ?confirmations Injection.inject_operation cctxt block ?confirmations
?branch ~src_sk contents >>=? fun res -> ?branch ~src_sk contents >>=? fun res ->
return res return res
let originate let originate
cctxt block ?confirmations cctxt block ?confirmations
?branch ~source ~src_pk ~src_sk ~fee ?(gas_limit = Z.minus_one) origination = ?branch ~source ~src_pk ~src_sk ~fee
?(gas_limit = Z.minus_one) ?(storage_limit = -1L) origination =
Alpha_services.Contract.counter cctxt block source >>=? fun pcounter -> Alpha_services.Contract.counter cctxt block source >>=? fun pcounter ->
let counter = Int32.succ pcounter in let counter = Int32.succ pcounter in
let operations = [origination] in let operations = [origination] in
@ -90,7 +91,7 @@ let originate
let contents = let contents =
Sourced_operation Sourced_operation
(Manager_operations { source ; fee ; counter ; (Manager_operations { source ; fee ; counter ;
gas_limit ; operations }) in gas_limit ; storage_limit ; operations }) in
Injection.inject_operation cctxt block ?confirmations Injection.inject_operation cctxt block ?confirmations
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) -> ?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
Lwt.return (Injection.originated_contracts result) >>=? function Lwt.return (Injection.originated_contracts result) >>=? function
@ -129,7 +130,8 @@ let delegate_contract cctxt
let contents = let contents =
Sourced_operation Sourced_operation
(Manager_operations { source ; fee ; counter ; (Manager_operations { source ; fee ; counter ;
gas_limit = Z.zero ; operations }) in gas_limit = Z.zero ; storage_limit = 0L ;
operations }) in
Injection.inject_operation cctxt block ?confirmations Injection.inject_operation cctxt block ?confirmations
?branch ~src_sk contents >>=? fun res -> ?branch ~src_sk contents >>=? fun res ->
return res return res
@ -204,6 +206,7 @@ let originate_contract
block ?confirmations ?branch block ?confirmations ?branch
~fee ~fee
?gas_limit ?gas_limit
?storage_limit
~delegate ~delegate
?(delegatable=true) ?(delegatable=true)
?(spendable=false) ?(spendable=false)
@ -227,7 +230,7 @@ let originate_contract
credit = balance ; credit = balance ;
preorigination = None } in preorigination = None } in
originate cctxt block ?confirmations originate cctxt block ?confirmations
?branch ~source ~src_pk ~src_sk ~fee ?gas_limit origination ?branch ~source ~src_pk ~src_sk ~fee ?gas_limit ?storage_limit origination
type activation_key = type activation_key =
{ pkh : Ed25519.Public_key_hash.t ; { pkh : Ed25519.Public_key_hash.t ;

View File

@ -89,6 +89,7 @@ val originate_contract:
?branch:int -> ?branch:int ->
fee:Tez.t -> fee:Tez.t ->
?gas_limit:Z.t -> ?gas_limit:Z.t ->
?storage_limit:Int64.t ->
delegate:public_key_hash option -> delegate:public_key_hash option ->
?delegatable:bool -> ?delegatable:bool ->
?spendable:bool -> ?spendable:bool ->
@ -114,6 +115,7 @@ val transfer :
amount:Tez.t -> amount:Tez.t ->
fee:Tez.t -> fee:Tez.t ->
?gas_limit:Z.t -> ?gas_limit:Z.t ->
?storage_limit:Int64.t ->
unit -> unit ->
(Injection.result * Contract.t list) tzresult Lwt.t (Injection.result * Contract.t list) tzresult Lwt.t

View File

@ -72,6 +72,22 @@ let estimated_gas = function
(Ok Z.zero) operation_results (Ok Z.zero) operation_results
| _ -> Ok Z.zero | _ -> Ok Z.zero
let estimated_storage = function
| Sourced_operation_result (Manager_operations_result { operation_results }) ->
List.fold_left
(fun acc (_, r) -> acc >>? fun acc ->
match r with
| Applied (Transaction_result { storage_size_diff }
| Origination_result { storage_size_diff }) ->
Ok (Int64.add storage_size_diff acc)
| Applied Reveal_result -> Ok acc
| Applied Delegation_result -> Ok acc
| Skipped -> assert false
| Failed errs -> Alpha_environment.wrap_error (Error errs))
(Ok 0L) operation_results >>? fun diff ->
Ok (max 0L diff)
| _ -> Ok 0L
let originated_contracts = function let originated_contracts = function
| Sourced_operation_result (Manager_operations_result { operation_results }) -> | Sourced_operation_result (Manager_operations_result { operation_results }) ->
List.fold_left List.fold_left
@ -87,16 +103,19 @@ let originated_contracts = function
(Ok []) operation_results (Ok []) operation_results
| _ -> Ok [] | _ -> Ok []
let may_patch_gas_limit let may_patch_limits
(cctxt : #Proto_alpha.full) block ?branch (cctxt : #Proto_alpha.full) block ?branch
?src_sk contents = ?src_sk contents =
Alpha_services.Constants.hard_gas_limits cctxt block >>=? fun (_, gas_limit) -> Alpha_services.Constants.hard_gas_limits cctxt block >>=? fun (_, gas_limit) ->
Alpha_services.Constants.hard_storage_limits cctxt block >>=? fun (_, storage_limit) ->
match contents with match contents with
| Sourced_operation (Manager_operations c) | Sourced_operation (Manager_operations c)
when c.gas_limit < Z.zero || gas_limit < c.gas_limit -> when c.gas_limit < Z.zero || gas_limit < c.gas_limit
|| c.storage_limit < 0L || storage_limit < c.storage_limit ->
let contents = let contents =
Sourced_operation (Manager_operations { c with gas_limit }) in Sourced_operation (Manager_operations { c with gas_limit ; storage_limit }) in
preapply cctxt block ?branch ?src_sk contents >>=? fun (_, _, result) -> preapply cctxt block ?branch ?src_sk contents >>=? fun (_, _, result) ->
begin if c.gas_limit < Z.zero || gas_limit < c.gas_limit then
Lwt.return (estimated_gas result) >>=? fun gas -> Lwt.return (estimated_gas result) >>=? fun gas ->
begin begin
if Z.equal gas Z.zero then if Z.equal gas Z.zero then
@ -107,14 +126,30 @@ let may_patch_gas_limit
"Estimated gas: %s units (will add 100 for safety)" "Estimated gas: %s units (will add 100 for safety)"
(Z.to_string gas) >>= fun () -> (Z.to_string gas) >>= fun () ->
return (Z.add gas (Z.of_int 100)) return (Z.add gas (Z.of_int 100))
end
else return c.gas_limit
end >>=? fun gas_limit -> end >>=? fun gas_limit ->
return (Sourced_operation (Manager_operations { c with gas_limit })) begin if c.storage_limit < 0L || storage_limit < c.storage_limit then
Lwt.return (estimated_storage result) >>=? fun storage ->
begin
if Int64.equal storage 0L then
cctxt#message "Estimated storage: no bytes added" >>= fun () ->
return 0L
else
cctxt#message
"Estimated storage: %Ld bytes added (will add 20 for safety)"
storage >>= fun () ->
return (Int64.add storage 20L)
end
else return c.storage_limit
end >>=? fun storage_limit ->
return (Sourced_operation (Manager_operations { c with gas_limit ; storage_limit }))
| op -> return op | op -> return op
let inject_operation let inject_operation
cctxt block cctxt block
?confirmations ?branch ?src_sk contents = ?confirmations ?branch ?src_sk contents =
may_patch_gas_limit may_patch_limits
cctxt block ?branch ?src_sk contents >>=? fun contents -> cctxt block ?branch ?src_sk contents >>=? fun contents ->
preapply cctxt block preapply cctxt block
?branch ?src_sk contents >>=? fun (_oph, op, result) -> ?branch ?src_sk contents >>=? fun (_oph, op, result) ->

View File

@ -204,9 +204,14 @@ let report_errors ~details ~show_source ?parsed ppf errs =
print_source (parsed, hilights) ; print_source (parsed, hilights) ;
if rest <> [] then Format.fprintf ppf "@," ; if rest <> [] then Format.fprintf ppf "@," ;
print_trace (parsed_locations parsed) rest print_trace (parsed_locations parsed) rest
| Alpha_environment.Ecoproto_error Gas.Gas_limit_too_high :: rest ->
Format.fprintf ppf
"Gas limit for the block is out of the protocol hard bounds." ;
if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest
| Alpha_environment.Ecoproto_error Gas.Block_quota_exceeded :: rest -> | Alpha_environment.Ecoproto_error Gas.Block_quota_exceeded :: rest ->
Format.fprintf ppf Format.fprintf ppf
"@[<v 0>Gas limit for the block exceeded during typechecking or execution.@]" ; "Gas limit for the block exceeded during typechecking or execution." ;
if rest <> [] then Format.fprintf ppf "@," ; if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest print_trace locations rest
| Alpha_environment.Ecoproto_error Gas.Operation_quota_exceeded :: rest -> | Alpha_environment.Ecoproto_error Gas.Operation_quota_exceeded :: rest ->
@ -214,6 +219,21 @@ let report_errors ~details ~show_source ?parsed ppf errs =
"@[<v 0>Gas limit exceeded during typechecking or execution.@,Try again with a higher gas limit.@]" ; "@[<v 0>Gas limit exceeded during typechecking or execution.@,Try again with a higher gas limit.@]" ;
if rest <> [] then Format.fprintf ppf "@," ; if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest print_trace locations rest
| Alpha_environment.Ecoproto_error Contract.Storage_limit_too_high :: rest ->
Format.fprintf ppf
"Storage limit for the block is out of the protocol hard bounds." ;
if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest
| Alpha_environment.Ecoproto_error Contract.Block_storage_quota_exceeded :: rest ->
Format.fprintf ppf
"Storage limit for the block exceeded during typechecking or execution." ;
if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest
| Alpha_environment.Ecoproto_error Contract.Operation_storage_quota_exceeded :: rest ->
Format.fprintf ppf
"@[<v 0>Storage limit exceeded during typechecking or execution.@,Try again with a higher storage limit.@]" ;
if rest <> [] then Format.fprintf ppf "@," ;
print_trace locations rest
| Alpha_environment.Ecoproto_error err :: rest -> | Alpha_environment.Ecoproto_error err :: rest ->
begin match err with begin match err with
| Apply.Bad_contract_parameter (c, None, _) -> | Apply.Bad_contract_parameter (c, None, _) ->

View File

@ -229,7 +229,7 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
"@[<v 2>Dictator test protocol activation:@,\ "@[<v 2>Dictator test protocol activation:@,\
Protocol: %a@]" Protocol: %a@]"
Protocol_hash.pp protocol Protocol_hash.pp protocol
| Sourced_operation (Manager_operations { source ; fee ; counter ; operations ; gas_limit }), | Sourced_operation (Manager_operations { source ; fee ; counter ; operations ; gas_limit ; storage_limit }),
Sourced_operation_result (Manager_operations_result { balance_updates ; operation_results }) -> Sourced_operation_result (Manager_operations_result { balance_updates ; operation_results }) ->
let pp_result ppf result = let pp_result ppf result =
Format.fprintf ppf "@," ; Format.fprintf ppf "@," ;
@ -237,10 +237,9 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
| Skipped -> | Skipped ->
Format.fprintf ppf Format.fprintf ppf
"This operation was skipped" "This operation was skipped"
| Failed errs -> | Failed _errs ->
Format.fprintf ppf Format.fprintf ppf
"@[<v 2>This operation FAILED with the folllowing error:@,%a@]" "This operation FAILED."
(Format.pp_print_list Alpha_environment.Error_monad.pp) errs
| Applied Reveal_result -> | Applied Reveal_result ->
Format.fprintf ppf Format.fprintf ppf
"This revelation was successfully applied" "This revelation was successfully applied"
@ -325,12 +324,14 @@ let pp_operation_result ppf ({ contents ; _ }, operation_result) =
From: %a@,\ From: %a@,\
Fee to the baker: %s%a@,\ Fee to the baker: %s%a@,\
Expected counter: %ld@,\ Expected counter: %ld@,\
Gas limit: %s" Gas limit: %s@,\
Storage limit: %Ld bytes"
Contract.pp source Contract.pp source
Client_proto_args.tez_sym Client_proto_args.tez_sym
Tez.pp fee Tez.pp fee
counter counter
(Z.to_string gas_limit) ; (Z.to_string gas_limit)
storage_limit ;
begin match balance_updates with begin match balance_updates with
| [] -> () | [] -> ()
| balance_updates -> | balance_updates ->

View File

@ -197,8 +197,8 @@ let commands () =
end ; end ;
command ~group ~desc: "Launch a smart contract on the blockchain." command ~group ~desc: "Launch a smart contract on the blockchain."
(args8 (args9
fee_arg gas_limit_arg delegate_arg (Client_keys.force_switch ()) fee_arg gas_limit_arg storage_limit_arg delegate_arg (Client_keys.force_switch ())
delegatable_switch spendable_switch init_arg no_print_source_flag) delegatable_switch spendable_switch init_arg no_print_source_flag)
(prefixes [ "originate" ; "contract" ] (prefixes [ "originate" ; "contract" ]
@@ RawContractAlias.fresh_alias_param @@ RawContractAlias.fresh_alias_param
@ -217,13 +217,13 @@ let commands () =
~name:"prg" ~desc: "script of the account\n\ ~name:"prg" ~desc: "script of the account\n\
Combine with -init if the storage type is not unit." Combine with -init if the storage type is not unit."
@@ stop) @@ stop)
begin fun (fee, gas_limit, delegate, force, delegatable, spendable, initial_storage, no_print_source) begin fun (fee, gas_limit, storage_limit, delegate, force, delegatable, spendable, initial_storage, no_print_source)
alias_name manager balance (_, source) program (cctxt : Proto_alpha.full) -> alias_name manager balance (_, source) program (cctxt : Proto_alpha.full) ->
RawContractAlias.of_fresh cctxt force alias_name >>=? fun alias_name -> RawContractAlias.of_fresh cctxt force alias_name >>=? fun alias_name ->
Lwt.return (Micheline_parser.no_parsing_error program) >>=? fun { expanded = code } -> Lwt.return (Micheline_parser.no_parsing_error program) >>=? fun { expanded = code } ->
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) -> source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
originate_contract cctxt cctxt#block ?confirmations:cctxt#confirmations originate_contract cctxt cctxt#block ?confirmations:cctxt#confirmations
~fee ?gas_limit ~delegate ~delegatable ~spendable ~initial_storage ~fee ?gas_limit ?storage_limit ~delegate ~delegatable ~spendable ~initial_storage
~manager ~balance ~source ~src_pk ~src_sk ~code () >>= fun errors -> ~manager ~balance ~source ~src_pk ~src_sk ~code () >>= fun errors ->
report_michelson_errors ~no_print_source ~msg:"origination simulation failed" cctxt errors >>= function report_michelson_errors ~no_print_source ~msg:"origination simulation failed" cctxt errors >>= function
| None -> return () | None -> return ()
@ -233,7 +233,7 @@ let commands () =
end ; end ;
command ~group ~desc: "Transfer tokens / call a smart contract." command ~group ~desc: "Transfer tokens / call a smart contract."
(args4 fee_arg gas_limit_arg arg_arg no_print_source_flag) (args5 fee_arg gas_limit_arg storage_limit_arg arg_arg no_print_source_flag)
(prefixes [ "transfer" ] (prefixes [ "transfer" ]
@@ tez_param @@ tez_param
~name: "qty" ~desc: "amount taken from source" ~name: "qty" ~desc: "amount taken from source"
@ -244,10 +244,10 @@ let commands () =
@@ ContractAlias.destination_param @@ ContractAlias.destination_param
~name: "dst" ~desc: "name/literal of the destination contract" ~name: "dst" ~desc: "name/literal of the destination contract"
@@ stop) @@ stop)
begin fun (fee, gas_limit, arg, no_print_source) amount (_, source) (_, destination) cctxt -> begin fun (fee, gas_limit, storage_limit, arg, no_print_source) amount (_, source) (_, destination) cctxt ->
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) -> source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
transfer cctxt cctxt#block ?confirmations:cctxt#confirmations transfer cctxt cctxt#block ?confirmations:cctxt#confirmations
~source ~fee ~src_pk ~src_sk ~destination ~arg ~amount ?gas_limit () >>= ~source ~fee ~src_pk ~src_sk ~destination ~arg ~amount ?gas_limit ?storage_limit () >>=
report_michelson_errors ~no_print_source ~msg:"transfer simulation failed" cctxt >>= function report_michelson_errors ~no_print_source ~msg:"transfer simulation failed" cctxt >>= function
| None -> return () | None -> return ()
| Some (_res, _contracts) -> | Some (_res, _contracts) ->

View File

@ -20,7 +20,8 @@
"Cycle_repr", "Cycle_repr",
"Level_repr", "Level_repr",
"Seed_repr", "Seed_repr",
"Gas_repr", "Gas_limit_repr",
"Storage_limit_repr",
"Script_int_repr", "Script_int_repr",
"Script_timestamp_repr", "Script_timestamp_repr",
"Michelson_v1_primitives", "Michelson_v1_primitives",

View File

@ -62,7 +62,8 @@ end
module Voting_period = Voting_period_repr module Voting_period = Voting_period_repr
module Gas = struct module Gas = struct
include Gas_repr include Gas_limit_repr
type error += Gas_limit_too_high = Raw_context.Gas_limit_too_high
let set_limit = Raw_context.set_gas_limit let set_limit = Raw_context.set_gas_limit
let set_unlimited = Raw_context.set_gas_unlimited let set_unlimited = Raw_context.set_gas_unlimited
let consume = Raw_context.consume_gas let consume = Raw_context.consume_gas
@ -78,6 +79,11 @@ module Contract = struct
include Contract_storage include Contract_storage
let init_origination_nonce = Raw_context.init_origination_nonce let init_origination_nonce = Raw_context.init_origination_nonce
let unset_origination_nonce = Raw_context.unset_origination_nonce let unset_origination_nonce = Raw_context.unset_origination_nonce
type error += Block_storage_quota_exceeded = Storage_limit_repr.Block_quota_exceeded
type error += Operation_storage_quota_exceeded = Storage_limit_repr.Operation_quota_exceeded
type error += Storage_limit_too_high = Raw_context.Storage_limit_too_high
let set_storage_limit = Raw_context.set_storage_limit
let set_storage_unlimited = Raw_context.set_storage_unlimited
end end
module Delegate = Delegate_storage module Delegate = Delegate_storage
module Roll = struct module Roll = struct

View File

@ -121,6 +121,7 @@ module Gas : sig
type error += Block_quota_exceeded (* `Temporary *) type error += Block_quota_exceeded (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *) type error += Operation_quota_exceeded (* `Temporary *)
type error += Gas_limit_too_high (* `Permanent *)
val free : cost val free : cost
val step_cost : int -> cost val step_cost : int -> cost
@ -323,6 +324,8 @@ module Constants : sig
block_reward: Tez.t ; block_reward: Tez.t ;
endorsement_reward: Tez.t ; endorsement_reward: Tez.t ;
cost_per_byte: Tez.t ; cost_per_byte: Tez.t ;
hard_storage_limit_per_operation: Int64.t ;
hard_storage_limit_per_block: Int64.t ;
} }
val parametric_encoding: parametric Data_encoding.t val parametric_encoding: parametric Data_encoding.t
val parametric: context -> parametric val parametric: context -> parametric
@ -338,6 +341,8 @@ module Constants : sig
val hard_gas_limit_per_operation: context -> Z.t val hard_gas_limit_per_operation: context -> Z.t
val hard_gas_limit_per_block: context -> Z.t val hard_gas_limit_per_block: context -> Z.t
val cost_per_byte: context -> Tez.t val cost_per_byte: context -> Tez.t
val hard_storage_limit_per_operation: context -> Int64.t
val hard_storage_limit_per_block: context -> Int64.t
val proof_of_work_threshold: context -> int64 val proof_of_work_threshold: context -> int64
val dictator_pubkey: context -> Signature.Public_key.t val dictator_pubkey: context -> Signature.Public_key.t
val max_operation_data_length: context -> int val max_operation_data_length: context -> int
@ -542,6 +547,13 @@ module Contract : sig
Script.expr -> big_map_diff option -> Script.expr -> big_map_diff option ->
context tzresult Lwt.t context tzresult Lwt.t
type error += Block_storage_quota_exceeded (* `Temporary *)
type error += Operation_storage_quota_exceeded (* `Temporary *)
type error += Storage_limit_too_high (* `Permanent *)
val set_storage_limit: context -> Int64.t -> context tzresult
val set_storage_unlimited: context -> context
val used_storage_space: context -> t -> Int64.t 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 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 pay_for_storage_space: context -> t -> Tez.t -> context tzresult Lwt.t
@ -750,6 +762,7 @@ and sourced_operation =
counter: counter ; counter: counter ;
operations: manager_operation list ; operations: manager_operation list ;
gas_limit: Z.t ; gas_limit: Z.t ;
storage_limit: Int64.t;
} }
| Dictator_operation of dictator_operation | Dictator_operation of dictator_operation

View File

@ -542,7 +542,7 @@ let apply_manager_operations ctxt source ops =
let apply_sourced_operation ctxt pred_block operation ops = let apply_sourced_operation ctxt pred_block operation ops =
match ops with match ops with
| Manager_operations { source ; fee ; counter ; operations ; gas_limit } -> | Manager_operations { source ; fee ; counter ; operations ; gas_limit ; storage_limit } ->
let revealed_public_keys = let revealed_public_keys =
List.fold_left (fun acc op -> List.fold_left (fun acc op ->
match op with match op with
@ -564,6 +564,7 @@ let apply_sourced_operation ctxt pred_block operation ops =
Contract.spend ctxt source fee >>=? fun ctxt -> Contract.spend ctxt source fee >>=? fun ctxt ->
add_fees ctxt fee >>=? fun ctxt -> add_fees ctxt fee >>=? fun ctxt ->
Lwt.return (Gas.set_limit ctxt gas_limit) >>=? fun ctxt -> Lwt.return (Gas.set_limit ctxt gas_limit) >>=? fun ctxt ->
Lwt.return (Contract.set_storage_limit ctxt storage_limit) >>=? fun ctxt ->
apply_manager_operations ctxt source operations >>= begin function apply_manager_operations ctxt source operations >>= begin function
| Ok (ctxt, operation_results) -> return (ctxt, operation_results) | Ok (ctxt, operation_results) -> return (ctxt, operation_results)
| Error operation_results -> return (ctxt (* backtracked *), operation_results) | Error operation_results -> return (ctxt (* backtracked *), operation_results)
@ -716,6 +717,7 @@ let apply_operation ctxt pred_block hash operation =
return (ctxt, Sourced_operation_result result) return (ctxt, Sourced_operation_result result)
end >>=? fun (ctxt, result) -> end >>=? fun (ctxt, result) ->
let ctxt = Gas.set_unlimited ctxt in let ctxt = Gas.set_unlimited ctxt in
let ctxt = Contract.set_storage_unlimited ctxt in
let ctxt = Contract.unset_origination_nonce ctxt in let ctxt = Contract.unset_origination_nonce ctxt in
return (ctxt, result) return (ctxt, result)

View File

@ -66,6 +66,8 @@ type parametric = {
block_reward: Tez_repr.t ; block_reward: Tez_repr.t ;
endorsement_reward: Tez_repr.t ; endorsement_reward: Tez_repr.t ;
cost_per_byte: Tez_repr.t ; cost_per_byte: Tez_repr.t ;
hard_storage_limit_per_operation: Int64.t ;
hard_storage_limit_per_block: Int64.t ;
} }
let default = { let default = {
@ -100,6 +102,8 @@ let default = {
endorsement_security_deposit = Tez_repr.(mul_exn one 64) ; endorsement_security_deposit = Tez_repr.(mul_exn one 64) ;
block_reward = Tez_repr.(mul_exn one 16) ; block_reward = Tez_repr.(mul_exn one 16) ;
endorsement_reward = Tez_repr.(mul_exn one 2) ; endorsement_reward = Tez_repr.(mul_exn one 2) ;
hard_storage_limit_per_operation = 60_000L ;
hard_storage_limit_per_block = 1_000_000L ;
cost_per_byte = Tez_repr.of_mutez_exn 1_000L ; cost_per_byte = Tez_repr.of_mutez_exn 1_000L ;
} }
@ -130,7 +134,9 @@ let parametric_encoding =
c.endorsement_security_deposit, c.endorsement_security_deposit,
c.block_reward), c.block_reward),
(c.endorsement_reward, (c.endorsement_reward,
c.cost_per_byte))) ) c.cost_per_byte,
c.hard_storage_limit_per_operation,
c.hard_storage_limit_per_block))) )
(fun (( preserved_cycles, (fun (( preserved_cycles,
blocks_per_cycle, blocks_per_cycle,
blocks_per_commitment, blocks_per_commitment,
@ -152,7 +158,9 @@ let parametric_encoding =
endorsement_security_deposit, endorsement_security_deposit,
block_reward), block_reward),
(endorsement_reward, (endorsement_reward,
cost_per_byte))) -> cost_per_byte,
hard_storage_limit_per_operation,
hard_storage_limit_per_block))) ->
{ preserved_cycles ; { preserved_cycles ;
blocks_per_cycle ; blocks_per_cycle ;
blocks_per_commitment ; blocks_per_commitment ;
@ -175,6 +183,8 @@ let parametric_encoding =
block_reward ; block_reward ;
endorsement_reward ; endorsement_reward ;
cost_per_byte ; cost_per_byte ;
hard_storage_limit_per_operation ;
hard_storage_limit_per_block ;
} ) } )
(merge_objs (merge_objs
(obj10 (obj10
@ -200,9 +210,11 @@ let parametric_encoding =
(req "block_security_deposit" Tez_repr.encoding) (req "block_security_deposit" Tez_repr.encoding)
(req "endorsement_security_deposit" Tez_repr.encoding) (req "endorsement_security_deposit" Tez_repr.encoding)
(req "block_reward" Tez_repr.encoding)) (req "block_reward" Tez_repr.encoding))
(obj2 (obj4
(req "endorsement_reward" Tez_repr.encoding) (req "endorsement_reward" Tez_repr.encoding)
(req "cost_per_byte" Tez_repr.encoding)))) (req "cost_per_byte" Tez_repr.encoding)
(req "hard_storage_limit_per_operation" int64)
(req "hard_storage_limit_per_block" int64))))
type t = { type t = {
fixed : fixed ; fixed : fixed ;

View File

@ -88,6 +88,14 @@ module S = struct
~output: (obj2 (req "per_block" z) (req "per_operation" z)) ~output: (obj2 (req "per_block" z) (req "per_operation" z))
RPC_path.(custom_root / "hard_gas_limits") RPC_path.(custom_root / "hard_gas_limits")
let hard_storage_limits =
RPC_service.post_service
~description: "Hard maximum amount of bytes stored per operation and per block"
~query: RPC_query.empty
~input: empty
~output: (obj2 (req "per_block" int64) (req "per_operation" int64))
RPC_path.(custom_root / "hard_storage_limits")
let cost_per_byte = let cost_per_byte =
RPC_service.post_service RPC_service.post_service
~description: "The cost per bytes added to the storage" ~description: "The cost per bytes added to the storage"
@ -201,6 +209,10 @@ let () =
return (Constants.hard_gas_limit_per_block ctxt, return (Constants.hard_gas_limit_per_block ctxt,
Constants.hard_gas_limit_per_operation ctxt) Constants.hard_gas_limit_per_operation ctxt)
end ; end ;
register0 S.hard_storage_limits begin fun ctxt () () ->
return (Constants.hard_storage_limit_per_block ctxt,
Constants.hard_storage_limit_per_operation ctxt)
end ;
register0 S.cost_per_byte begin fun ctxt () () -> register0 S.cost_per_byte begin fun ctxt () () ->
return (Constants.cost_per_byte ctxt) return (Constants.cost_per_byte ctxt)
end ; end ;
@ -254,6 +266,8 @@ let hard_gas_limits ctxt block =
RPC_context.make_call0 S.hard_gas_limits ctxt block () () RPC_context.make_call0 S.hard_gas_limits ctxt block () ()
let cost_per_byte ctxt block = let cost_per_byte ctxt block =
RPC_context.make_call0 S.cost_per_byte ctxt block () () RPC_context.make_call0 S.cost_per_byte ctxt block () ()
let hard_storage_limits ctxt block =
RPC_context.make_call0 S.hard_storage_limits ctxt block () ()
let proof_of_work_threshold ctxt block = let proof_of_work_threshold ctxt block =
RPC_context.make_call0 S.proof_of_work_threshold ctxt block () () RPC_context.make_call0 S.proof_of_work_threshold ctxt block () ()
let seed_nonce_revelation_tip ctxt block = let seed_nonce_revelation_tip ctxt block =

View File

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

View File

@ -40,6 +40,12 @@ let hard_gas_limit_per_block c =
let cost_per_byte c = let cost_per_byte c =
let constants = Raw_context.constants c in let constants = Raw_context.constants c in
constants.cost_per_byte constants.cost_per_byte
let hard_storage_limit_per_operation c =
let constants = Raw_context.constants c in
constants.hard_storage_limit_per_operation
let hard_storage_limit_per_block c =
let constants = Raw_context.constants c in
constants.hard_storage_limit_per_block
let proof_of_work_threshold c = let proof_of_work_threshold c =
let constants = Raw_context.constants c in let constants = Raw_context.constants c in
constants.proof_of_work_threshold constants.proof_of_work_threshold

View File

@ -89,9 +89,9 @@ let consume block_gas operation_gas cost = match operation_gas with
Z.sub remaining weighted_cost in Z.sub remaining weighted_cost in
let block_remaining = let block_remaining =
Z.sub block_gas weighted_cost in Z.sub block_gas weighted_cost in
if Compare.Z.(remaining <= Z.zero) if Compare.Z.(remaining < Z.zero)
then error Operation_quota_exceeded then error Operation_quota_exceeded
else if Compare.Z.(block_remaining <= Z.zero) else if Compare.Z.(block_remaining < Z.zero)
then error Block_quota_exceeded then error Block_quota_exceeded
else ok (block_remaining, Limited { remaining }) else ok (block_remaining, Limited { remaining })

View File

@ -300,7 +300,8 @@ module Forge = struct
module Manager = struct module Manager = struct
let operations ctxt let operations ctxt
block ~branch ~source ?sourcePubKey ~counter ~fee ~gas_limit operations = block ~branch ~source ?sourcePubKey ~counter ~fee
~gas_limit ~storage_limit operations =
Contract_services.manager_key ctxt block source >>= function Contract_services.manager_key ctxt block source >>= function
| Error _ as e -> Lwt.return e | Error _ as e -> Lwt.return e
| Ok (_, revealed) -> | Ok (_, revealed) ->
@ -313,18 +314,22 @@ module Forge = struct
| Some pk -> Reveal pk :: operations in | Some pk -> Reveal pk :: operations in
let ops = let ops =
Manager_operations { source ; Manager_operations { source ;
counter ; operations ; fee ; gas_limit } in counter ; operations ; fee ;
gas_limit ; storage_limit } in
(RPC_context.make_call0 S.operations ctxt block (RPC_context.make_call0 S.operations ctxt block
() ({ branch }, Sourced_operation ops)) () ({ branch }, Sourced_operation ops))
let reveal ctxt let reveal ctxt
block ~branch ~source ~sourcePubKey ~counter ~fee ()= block ~branch ~source ~sourcePubKey ~counter ~fee ()=
operations ctxt block ~branch ~source ~sourcePubKey ~counter ~fee ~gas_limit:Z.zero [] operations ctxt block ~branch ~source ~sourcePubKey ~counter ~fee
~gas_limit:Z.zero ~storage_limit:0L []
let transaction ctxt let transaction ctxt
block ~branch ~source ?sourcePubKey ~counter block ~branch ~source ?sourcePubKey ~counter
~amount ~destination ?parameters ~gas_limit ~fee ()= ~amount ~destination ?parameters
operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee ~gas_limit ~gas_limit ~storage_limit ~fee ()=
operations ctxt block ~branch ~source ?sourcePubKey ~counter
~fee ~gas_limit ~storage_limit
Alpha_context.[Transaction { amount ; parameters ; destination }] Alpha_context.[Transaction { amount ; parameters ; destination }]
let origination ctxt let origination ctxt
@ -334,8 +339,9 @@ module Forge = struct
?(spendable = true) ?(spendable = true)
?(delegatable = true) ?(delegatable = true)
?delegatePubKey ?script ?delegatePubKey ?script
~gas_limit ~fee () = ~gas_limit ~storage_limit ~fee () =
operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee ~gas_limit operations ctxt block ~branch ~source ?sourcePubKey ~counter
~fee ~gas_limit ~storage_limit
Alpha_context.[ Alpha_context.[
Origination { manager = managerPubKey ; Origination { manager = managerPubKey ;
delegate = delegatePubKey ; delegate = delegatePubKey ;
@ -348,7 +354,8 @@ module Forge = struct
let delegation ctxt let delegation ctxt
block ~branch ~source ?sourcePubKey ~counter ~fee delegate = block ~branch ~source ?sourcePubKey ~counter ~fee delegate =
operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee ~gas_limit:Z.zero operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee
~gas_limit:Z.zero ~storage_limit:0L
Alpha_context.[Delegation delegate] Alpha_context.[Delegation delegate]
end end

View File

@ -72,6 +72,7 @@ module Forge : sig
counter:int32 -> counter:int32 ->
fee:Tez.t -> fee:Tez.t ->
gas_limit:Z.t -> gas_limit:Z.t ->
storage_limit:Int64.t ->
manager_operation list -> MBytes.t shell_tzresult Lwt.t manager_operation list -> MBytes.t shell_tzresult Lwt.t
val reveal: val reveal:
@ -93,6 +94,7 @@ module Forge : sig
destination:Contract.t -> destination:Contract.t ->
?parameters:Script.expr -> ?parameters:Script.expr ->
gas_limit:Z.t -> gas_limit:Z.t ->
storage_limit:Int64.t ->
fee:Tez.t -> fee:Tez.t ->
unit -> MBytes.t shell_tzresult Lwt.t unit -> MBytes.t shell_tzresult Lwt.t
@ -109,6 +111,7 @@ module Forge : sig
?delegatePubKey: public_key_hash -> ?delegatePubKey: public_key_hash ->
?script:Script.t -> ?script:Script.t ->
gas_limit:Z.t -> gas_limit:Z.t ->
storage_limit:Int64.t ->
fee:Tez.t-> fee:Tez.t->
unit -> MBytes.t shell_tzresult Lwt.t unit -> MBytes.t shell_tzresult Lwt.t

View File

@ -56,6 +56,7 @@ and sourced_operation =
counter: counter ; counter: counter ;
operations: manager_operation list ; operations: manager_operation list ;
gas_limit: Z.t; gas_limit: Z.t;
storage_limit: Int64.t;
} }
| Dictator_operation of dictator_operation | Dictator_operation of dictator_operation
@ -186,7 +187,7 @@ module Encoding = struct
(fun ((), key) -> Delegation key) (fun ((), key) -> Delegation key)
let manager_kind_encoding = let manager_kind_encoding =
obj6 obj7
(req "kind" (constant "manager")) (req "kind" (constant "manager"))
(req "source" Contract_repr.encoding) (req "source" Contract_repr.encoding)
(req "fee" Tez_repr.encoding) (req "fee" Tez_repr.encoding)
@ -199,15 +200,16 @@ module Encoding = struct
delegation_case (Tag 3) ; delegation_case (Tag 3) ;
]))) ])))
(req "gas_limit" z) (req "gas_limit" z)
(req "storage_limit" int64)
let manager_kind_case tag = let manager_kind_case tag =
case tag ~name:"Manager operations" manager_kind_encoding case tag ~name:"Manager operations" manager_kind_encoding
(function (function
| Manager_operations { source; fee ; counter ; operations ; gas_limit } -> | Manager_operations { source; fee ; counter ; operations ; gas_limit ; storage_limit } ->
Some ((), source, fee, counter, operations, gas_limit) Some ((), source, fee, counter, operations, gas_limit, storage_limit)
| _ -> None) | _ -> None)
(fun ((), source, fee, counter, operations, gas_limit) -> (fun ((), source, fee, counter, operations, gas_limit, storage_limit) ->
Manager_operations { source; fee ; counter ; operations ; gas_limit }) Manager_operations { source; fee ; counter ; operations ; gas_limit ; storage_limit })
let endorsement_encoding = let endorsement_encoding =
(* describe ~title:"Endorsement operation" @@ *) (* describe ~title:"Endorsement operation" @@ *)

View File

@ -56,6 +56,7 @@ and sourced_operation =
counter: counter ; counter: counter ;
operations: manager_operation list ; operations: manager_operation list ;
gas_limit: Z.t ; gas_limit: Z.t ;
storage_limit: Int64.t;
} }
| Dictator_operation of dictator_operation | Dictator_operation of dictator_operation

View File

@ -105,6 +105,12 @@ let constants_encoding =
and cost_per_byte = and cost_per_byte =
opt Tez_repr.(=) opt Tez_repr.(=)
default.cost_per_byte c.cost_per_byte default.cost_per_byte c.cost_per_byte
and hard_storage_limit_per_operation =
opt Compare.Int64.(=)
default.hard_storage_limit_per_operation c.hard_storage_limit_per_operation
and hard_storage_limit_per_block =
opt Compare.Int64.(=)
default.hard_storage_limit_per_block c.hard_storage_limit_per_block
in in
(( preserved_cycles, (( preserved_cycles,
blocks_per_cycle, blocks_per_cycle,
@ -127,7 +133,9 @@ let constants_encoding =
endorsement_security_deposit, endorsement_security_deposit,
block_reward), block_reward),
(endorsement_reward, (endorsement_reward,
cost_per_byte)))) cost_per_byte,
hard_storage_limit_per_operation,
hard_storage_limit_per_block))))
(fun (( preserved_cycles, (fun (( preserved_cycles,
blocks_per_cycle, blocks_per_cycle,
blocks_per_commitment, blocks_per_commitment,
@ -149,7 +157,9 @@ let constants_encoding =
endorsement_security_deposit, endorsement_security_deposit,
block_reward), block_reward),
(endorsement_reward, (endorsement_reward,
cost_per_byte))) -> cost_per_byte,
hard_storage_limit_per_operation,
hard_storage_limit_per_block))) ->
let unopt def = function None -> def | Some v -> v in let unopt def = function None -> def | Some v -> v in
let default = Constants_repr.default in let default = Constants_repr.default in
{ Constants_repr.preserved_cycles = { Constants_repr.preserved_cycles =
@ -197,6 +207,10 @@ let constants_encoding =
unopt default.endorsement_reward endorsement_reward ; unopt default.endorsement_reward endorsement_reward ;
cost_per_byte = cost_per_byte =
unopt default.cost_per_byte cost_per_byte ; unopt default.cost_per_byte cost_per_byte ;
hard_storage_limit_per_operation =
unopt default.hard_storage_limit_per_operation hard_storage_limit_per_operation ;
hard_storage_limit_per_block =
unopt default.hard_storage_limit_per_block hard_storage_limit_per_block ;
} ) } )
(merge_objs (merge_objs
(obj10 (obj10
@ -222,9 +236,11 @@ let constants_encoding =
(opt "block_security_deposit" Tez_repr.encoding) (opt "block_security_deposit" Tez_repr.encoding)
(opt "endorsement_security_deposit" Tez_repr.encoding) (opt "endorsement_security_deposit" Tez_repr.encoding)
(opt "block_reward" Tez_repr.encoding)) (opt "block_reward" Tez_repr.encoding))
(obj2 (obj4
(opt "endorsement_reward" Tez_repr.encoding) (opt "endorsement_reward" Tez_repr.encoding)
(opt "cost_per_byte" Tez_repr.encoding)))) (opt "cost_per_byte" Tez_repr.encoding)
(opt "hard_storage_limit_per_operation" int64)
(opt "hard_storage_limit_per_block" int64))))
let encoding = let encoding =
let open Data_encoding in let open Data_encoding in

View File

@ -20,7 +20,9 @@ type t = {
fees: Tez_repr.t ; fees: Tez_repr.t ;
rewards: Tez_repr.t ; rewards: Tez_repr.t ;
block_gas: Z.t ; block_gas: Z.t ;
operation_gas: Gas_repr.t ; operation_gas: Gas_limit_repr.t ;
block_storage: Int64.t ;
operation_storage: Storage_limit_repr.t ;
origination_nonce: Contract_repr.origination_nonce option ; origination_nonce: Contract_repr.origination_nonce option ;
} }
@ -92,7 +94,7 @@ let () =
register_error_kind register_error_kind
`Permanent `Permanent
~id:"gas_limit_too_high" ~id:"gas_limit_too_high"
~title: "Gas limit higher than the hard limit" ~title: "Gas limit out of protocol hard bounds"
~description: ~description:
"A transaction tried to exceed the hard limit on gas" "A transaction tried to exceed the hard limit on gas"
empty empty
@ -100,18 +102,44 @@ let () =
(fun () -> Gas_limit_too_high) (fun () -> Gas_limit_too_high)
let set_gas_limit ctxt remaining = let set_gas_limit ctxt remaining =
if Compare.Z.(remaining > ctxt.constants.hard_gas_limit_per_operation) then if Compare.Z.(remaining > ctxt.constants.hard_gas_limit_per_operation)
|| Compare.Z.(remaining < Z.zero) then
error Gas_limit_too_high error Gas_limit_too_high
else else
ok { ctxt with operation_gas = Limited { remaining } } ok { ctxt with operation_gas = Limited { remaining } }
let set_gas_unlimited ctxt = let set_gas_unlimited ctxt =
{ ctxt with operation_gas = Unaccounted } { ctxt with operation_gas = Unaccounted }
let consume_gas ctxt cost = let consume_gas ctxt cost =
Gas_repr.consume ctxt.block_gas ctxt.operation_gas cost >>? fun (block_gas, operation_gas) -> Gas_limit_repr.consume ctxt.block_gas ctxt.operation_gas cost >>? fun (block_gas, operation_gas) ->
ok { ctxt with block_gas ; operation_gas } ok { ctxt with block_gas ; operation_gas }
let gas_level ctxt = ctxt.operation_gas let gas_level ctxt = ctxt.operation_gas
let block_gas_level ctxt = ctxt.block_gas let block_gas_level ctxt = ctxt.block_gas
type error += Storage_limit_too_high (* `Permanent *)
let () =
let open Data_encoding in
register_error_kind
`Permanent
~id:"storage_limit_too_high"
~title: "Storage limit out of protocol hard bounds"
~description:
"A transaction tried to exceed the hard limit on storage"
empty
(function Storage_limit_too_high -> Some () | _ -> None)
(fun () -> Storage_limit_too_high)
let set_storage_limit ctxt remaining =
if Compare.Int64.(remaining > ctxt.constants.hard_storage_limit_per_operation)
|| Compare.Int64.(remaining < 0L)then
error Storage_limit_too_high
else
ok { ctxt with operation_storage = Limited { remaining } }
let set_storage_unlimited ctxt =
{ ctxt with operation_storage = Unaccounted }
let record_bytes_stored ctxt bytes =
Storage_limit_repr.consume ctxt.block_storage ctxt.operation_storage ~bytes >>? fun (block_storage, operation_storage) ->
ok { ctxt with block_storage ; operation_storage }
type storage_error = type storage_error =
| Incompatible_protocol_version of string | Incompatible_protocol_version of string
@ -331,6 +359,8 @@ let prepare ~level ~timestamp ~fitness ctxt =
rewards = Tez_repr.zero ; rewards = Tez_repr.zero ;
operation_gas = Unaccounted ; operation_gas = Unaccounted ;
block_gas = constants.Constants_repr.hard_gas_limit_per_block ; block_gas = constants.Constants_repr.hard_gas_limit_per_block ;
operation_storage = Unaccounted ;
block_storage = constants.Constants_repr.hard_storage_limit_per_block ;
origination_nonce = None ; origination_nonce = None ;
} }
@ -378,6 +408,8 @@ let register_resolvers enc resolve =
rewards = Tez_repr.zero ; rewards = Tez_repr.zero ;
block_gas = Constants_repr.default.hard_gas_limit_per_block ; block_gas = Constants_repr.default.hard_gas_limit_per_block ;
operation_gas = Unaccounted ; operation_gas = Unaccounted ;
block_storage = Constants_repr.default.hard_storage_limit_per_block ;
operation_storage = Unaccounted ;
origination_nonce = None ; origination_nonce = None ;
} in } in
resolve faked_context str in resolve faked_context str in
@ -421,7 +453,9 @@ module type T = sig
val absolute_key: context -> key -> key val absolute_key: context -> key -> key
val consume_gas: context -> Gas_repr.cost -> context tzresult val consume_gas: context -> Gas_limit_repr.cost -> context tzresult
val record_bytes_stored: context -> Int64.t -> context tzresult
end end

View File

@ -79,9 +79,14 @@ type error += Gas_limit_too_high (* `Permanent *)
val set_gas_limit: t -> Z.t -> t tzresult val set_gas_limit: t -> Z.t -> t tzresult
val set_gas_unlimited: t -> t val set_gas_unlimited: t -> t
val gas_level: t -> Gas_repr.t val gas_level: t -> Gas_limit_repr.t
val block_gas_level: t -> Z.t val block_gas_level: t -> Z.t
type error += Storage_limit_too_high (* `Permanent *)
val set_storage_limit: t -> Int64.t -> t tzresult
val set_storage_unlimited: t -> t
type error += Undefined_operation_nonce (* `Permanent *) type error += Undefined_operation_nonce (* `Permanent *)
val init_origination_nonce: t -> Operation_hash.t -> t val init_origination_nonce: t -> Operation_hash.t -> t
@ -171,7 +176,11 @@ module type T = sig
(** Internally used in {!Storage_functors} to consume gas from (** Internally used in {!Storage_functors} to consume gas from
within a view. *) within a view. *)
val consume_gas: context -> Gas_repr.cost -> context tzresult val consume_gas: context -> Gas_limit_repr.cost -> context tzresult
(** Internally used in {!Storage_functors} to consume storage from
within a view. *)
val record_bytes_stored: context -> Int64.t -> context tzresult
end end

View File

@ -89,6 +89,7 @@ module Make_subcontext (C : Raw_context.T) (N : NAME)
let project = C.project let project = C.project
let absolute_key c k = C.absolute_key c (to_key k) let absolute_key c k = C.absolute_key c (to_key k)
let consume_gas = C.consume_gas let consume_gas = C.consume_gas
let record_bytes_stored = C.record_bytes_stored
end end
module Make_single_data_storage (C : Raw_context.T) (N : NAME) (V : VALUE) module Make_single_data_storage (C : Raw_context.T) (N : NAME) (V : VALUE)
@ -139,7 +140,7 @@ module Make_single_carbonated_data_storage
type context = t type context = t
type value = V.t type value = V.t
let consume_mem_gas c = let consume_mem_gas c =
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost Z.zero)) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost Z.zero))
let existing_size c = let existing_size c =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
@ -152,26 +153,26 @@ module Make_single_carbonated_data_storage
let consume_read_gas get c = let consume_read_gas get c =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
| Variable -> | Variable ->
get c (len_name N.name) >>=? fun len -> get c (len_name N.name) >>=? fun len ->
decode_len_value N.name len >>=? fun len -> decode_len_value N.name len >>=? fun len ->
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
let consume_write_gas set c v = let consume_write_gas set c v =
match V.size with match V.size with
| Fixed s -> | Fixed s ->
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int s))) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int s))) >>=? fun c ->
return (c, V.to_bytes v) return (c, V.to_bytes v)
| Variable -> | Variable ->
let bytes = V.to_bytes v in let bytes = V.to_bytes v in
let len = MBytes.length bytes in let len = MBytes.length bytes in
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int len))) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int len))) >>=? fun c ->
set c (len_name N.name) (encode_len_value bytes) >>=? fun c -> set c (len_name N.name) (encode_len_value bytes) >>=? fun c ->
return (c, bytes) return (c, bytes)
let consume_remove_gas del c = let consume_remove_gas del c =
match V.size with match V.size with
| Fixed _ | Variable -> | Fixed _ | Variable ->
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost Z.zero)) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost Z.zero)) >>=? fun c ->
del c (len_name N.name) del c (len_name N.name)
let mem c = let mem c =
consume_mem_gas c >>=? fun c -> consume_mem_gas c >>=? fun c ->
@ -192,30 +193,38 @@ module Make_single_carbonated_data_storage
else else
return (C.project c, None) return (C.project c, None)
let init c v = let init c v =
consume_write_gas C.set c v >>=? fun (c, bytes) ->
C.init c N.name bytes >>=? fun c ->
let size = MBytes.length bytes in
Lwt.return (C.record_bytes_stored c (Int64.of_int size)) >>=? fun c ->
return (C.project c, size)
let set c v =
consume_write_gas C.init c v >>=? fun (c, bytes) -> consume_write_gas C.init c v >>=? fun (c, bytes) ->
existing_size c >>=? fun prev_size -> existing_size c >>=? fun prev_size ->
C.init c N.name bytes >>=? fun c ->
return (C.project c, MBytes.length bytes - prev_size)
let set c v =
consume_write_gas C.set c v >>=? fun (c, bytes) ->
C.set c N.name bytes >>=? fun c -> C.set c N.name bytes >>=? fun c ->
return (C.project c, MBytes.length bytes) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (C.record_bytes_stored c (Int64.of_int size_diff)) >>=? fun c ->
return (C.project c, size_diff)
let init_set c v = let init_set c v =
let init_set c k v = C.init_set c k v >>= return in let init_set c k v = C.init_set c k v >>= return in
consume_write_gas init_set c v >>=? fun (c, bytes) -> consume_write_gas init_set c v >>=? fun (c, bytes) ->
existing_size c >>=? fun prev_size -> existing_size c >>=? fun prev_size ->
init_set c N.name bytes >>=? fun c -> init_set c N.name bytes >>=? fun c ->
return (C.project c, MBytes.length bytes - prev_size) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (C.record_bytes_stored c (Int64.of_int size_diff)) >>=? fun c ->
return (C.project c, size_diff)
let remove c = let remove c =
let remove c k = C.remove c k >>= return in let remove c k = C.remove c k >>= return in
consume_remove_gas remove c >>=? fun c -> consume_remove_gas remove c >>=? fun c ->
existing_size c >>=? fun prev_size -> existing_size c >>=? fun prev_size ->
remove c N.name >>=? fun c -> remove c N.name >>=? fun c ->
Lwt.return (C.record_bytes_stored c (Int64.of_int ~-prev_size)) >>=? fun c ->
return (C.project c, prev_size) return (C.project c, prev_size)
let delete c = let delete c =
consume_remove_gas C.delete c >>=? fun c -> consume_remove_gas C.delete c >>=? fun c ->
existing_size c >>=? fun prev_size -> existing_size c >>=? fun prev_size ->
C.delete c N.name >>=? fun c -> C.delete c N.name >>=? fun c ->
Lwt.return (C.record_bytes_stored c (Int64.of_int ~-prev_size)) >>=? fun c ->
return (C.project c, prev_size) return (C.project c, prev_size)
let set_option c v = let set_option c v =
match v with match v with
@ -392,7 +401,7 @@ module Make_indexed_carbonated_data_storage
| [ last ] -> Compare.Char.(=) (String.get last (String.length last - 1)) '$' | [ last ] -> Compare.Char.(=) (String.get last (String.length last - 1)) '$'
| _ :: rest -> is_len_name rest | _ :: rest -> is_len_name rest
let consume_mem_gas c = let consume_mem_gas c =
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost Z.zero)) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost Z.zero))
let existing_size c i = let existing_size c i =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
@ -405,26 +414,26 @@ module Make_indexed_carbonated_data_storage
let consume_read_gas get c i = let consume_read_gas get c i =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
| Variable -> | Variable ->
get c (len_name i) >>=? fun len -> get c (len_name i) >>=? fun len ->
decode_len_value (name i) len >>=? fun len -> decode_len_value (name i) len >>=? fun len ->
Lwt.return (C.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (C.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
let consume_write_gas set c i v = let consume_write_gas set c i v =
match V.size with match V.size with
| Fixed s -> | Fixed s ->
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int s))) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int s))) >>=? fun c ->
return (c, V.to_bytes v) return (c, V.to_bytes v)
| Variable -> | Variable ->
let bytes = V.to_bytes v in let bytes = V.to_bytes v in
let len = MBytes.length bytes in let len = MBytes.length bytes in
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int len))) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int len))) >>=? fun c ->
set c (len_name i) (encode_len_value bytes) >>=? fun c -> set c (len_name i) (encode_len_value bytes) >>=? fun c ->
return (c, bytes) return (c, bytes)
let consume_remove_gas del c i = let consume_remove_gas del c i =
match V.size with match V.size with
| Fixed _ | Variable -> | Fixed _ | Variable ->
Lwt.return (C.consume_gas c (Gas_repr.write_bytes_cost Z.zero)) >>=? fun c -> Lwt.return (C.consume_gas c (Gas_limit_repr.write_bytes_cost Z.zero)) >>=? fun c ->
del c (len_name i) del c (len_name i)
let mem s i = let mem s i =
consume_mem_gas s >>=? fun s -> consume_mem_gas s >>=? fun s ->
@ -448,27 +457,35 @@ module Make_indexed_carbonated_data_storage
consume_write_gas C.set s i v >>=? fun (s, bytes) -> consume_write_gas C.set s i v >>=? fun (s, bytes) ->
existing_size s i >>=? fun prev_size -> existing_size s i >>=? fun prev_size ->
C.set s (name i) bytes >>=? fun t -> C.set s (name i) bytes >>=? fun t ->
return (C.project t, MBytes.length bytes - prev_size) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (C.record_bytes_stored t (Int64.of_int size_diff)) >>=? fun t ->
return (C.project t, size_diff)
let init s i v = let init s i v =
consume_write_gas C.init s i v >>=? fun (s, bytes) -> consume_write_gas C.init s i v >>=? fun (s, bytes) ->
C.init s (name i) bytes >>=? fun t -> C.init s (name i) bytes >>=? fun t ->
return (C.project t, MBytes.length bytes) let size = MBytes.length bytes in
Lwt.return (C.record_bytes_stored t (Int64.of_int size)) >>=? fun t ->
return (C.project t, size)
let init_set s i v = let init_set s i v =
let init_set s i v = C.init_set s i v >>= return in let init_set s i v = C.init_set s i v >>= return in
consume_write_gas init_set s i v >>=? fun (s, bytes) -> consume_write_gas init_set s i v >>=? fun (s, bytes) ->
existing_size s i >>=? fun prev_size -> existing_size s i >>=? fun prev_size ->
init_set s (name i) bytes >>=? fun t -> init_set s (name i) bytes >>=? fun t ->
return (C.project t, MBytes.length bytes - prev_size) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (C.record_bytes_stored t (Int64.of_int size_diff)) >>=? fun t ->
return (C.project t, size_diff)
let remove s i = let remove s i =
let remove s i = C.remove s i >>= return in let remove s i = C.remove s i >>= return in
consume_remove_gas remove s i >>=? fun s -> consume_remove_gas remove s i >>=? fun s ->
existing_size s i >>=? fun prev_size -> existing_size s i >>=? fun prev_size ->
remove s (name i) >>=? fun t -> remove s (name i) >>=? fun t ->
Lwt.return (C.record_bytes_stored t (Int64.of_int ~-prev_size)) >>=? fun t ->
return (C.project t, prev_size) return (C.project t, prev_size)
let delete s i = let delete s i =
consume_remove_gas C.delete s i >>=? fun s -> consume_remove_gas C.delete s i >>=? fun s ->
existing_size s i >>=? fun prev_size -> existing_size s i >>=? fun prev_size ->
C.delete s (name i) >>=? fun t -> C.delete s (name i) >>=? fun t ->
Lwt.return (C.record_bytes_stored t (Int64.of_int ~-prev_size)) >>=? fun t ->
return (C.project t, prev_size) return (C.project t, prev_size)
let set_option s i v = let set_option s i v =
match v with match v with
@ -512,6 +529,7 @@ module Make_indexed_carbonated_data_storage
consume_remove_gas C.delete s path >>=? fun s -> consume_remove_gas C.delete s path >>=? fun s ->
existing_size s path >>=? fun prev_size -> existing_size s path >>=? fun prev_size ->
C.delete s (name path) >>=? fun s -> C.delete s (name path) >>=? fun s ->
Lwt.return (C.record_bytes_stored s (Int64.of_int ~-prev_size)) >>=? fun s ->
return (s, Z.add (Z.of_int prev_size) total) in return (s, Z.add (Z.of_int prev_size) total) in
fold_keys_unaccounted s ~init:Z.zero ~f fold_keys_unaccounted s ~init:Z.zero ~f
let fold s ~init ~f = let fold s ~init ~f =
@ -610,6 +628,7 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX)
let project (t, _) = C.project t let project (t, _) = C.project t
let absolute_key (t, i) k = C.absolute_key t (to_key i k) let absolute_key (t, i) k = C.absolute_key t (to_key i k)
let consume_gas (t, k) c = C.consume_gas t c >>? fun t -> ok (t, k) let consume_gas (t, k) c = C.consume_gas t c >>? fun t -> ok (t, k)
let record_bytes_stored (t, k) c = C.record_bytes_stored t c >>? fun t -> ok (t, k)
end end
let fold_keys t ~init ~f = let fold_keys t ~init ~f =
@ -766,7 +785,7 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX)
type key = I.t type key = I.t
type value = V.t type value = V.t
let consume_mem_gas c = let consume_mem_gas c =
Lwt.return (Raw_context.consume_gas c (Gas_repr.read_bytes_cost Z.zero)) Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost Z.zero))
let existing_size c = let existing_size c =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
@ -779,26 +798,26 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX)
let consume_read_gas get c = let consume_read_gas get c =
match V.size with match V.size with
| Fixed len -> | Fixed len ->
Lwt.return (Raw_context.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
| Variable -> | Variable ->
get c (len_name N.name) >>=? fun len -> get c (len_name N.name) >>=? fun len ->
decode_len_value N.name len >>=? fun len -> decode_len_value N.name len >>=? fun len ->
Lwt.return (Raw_context.consume_gas c (Gas_repr.read_bytes_cost (Z.of_int len))) Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost (Z.of_int len)))
let consume_write_gas set c v = let consume_write_gas set c v =
match V.size with match V.size with
| Fixed s -> | Fixed s ->
Lwt.return (Raw_context.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int s))) >>=? fun c -> Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int s))) >>=? fun c ->
return (c, V.to_bytes v) return (c, V.to_bytes v)
| Variable -> | Variable ->
let bytes = V.to_bytes v in let bytes = V.to_bytes v in
let len = MBytes.length bytes in let len = MBytes.length bytes in
Lwt.return (Raw_context.consume_gas c (Gas_repr.write_bytes_cost (Z.of_int len))) >>=? fun c -> Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.write_bytes_cost (Z.of_int len))) >>=? fun c ->
set c (len_name N.name) (encode_len_value bytes) >>=? fun c -> set c (len_name N.name) (encode_len_value bytes) >>=? fun c ->
return (c, bytes) return (c, bytes)
let consume_remove_gas del c = let consume_remove_gas del c =
match V.size with match V.size with
| Fixed _ | Variable -> | Fixed _ | Variable ->
Lwt.return (Raw_context.consume_gas c (Gas_repr.write_bytes_cost Z.zero)) >>=? fun c -> Lwt.return (Raw_context.consume_gas c (Gas_limit_repr.write_bytes_cost Z.zero)) >>=? fun c ->
del c (len_name N.name) del c (len_name N.name)
let mem s i = let mem s i =
consume_mem_gas (s, i) >>=? fun c -> consume_mem_gas (s, i) >>=? fun c ->
@ -822,27 +841,35 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX)
consume_write_gas Raw_context.set (s, i) v >>=? fun (c, bytes) -> consume_write_gas Raw_context.set (s, i) v >>=? fun (c, bytes) ->
existing_size (s, i) >>=? fun prev_size -> existing_size (s, i) >>=? fun prev_size ->
Raw_context.set c N.name bytes >>=? fun c -> Raw_context.set c N.name bytes >>=? fun c ->
return (Raw_context.project c, MBytes.length bytes - prev_size) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (Raw_context.record_bytes_stored c (Int64.of_int size_diff)) >>=? fun c ->
return (Raw_context.project c, size_diff)
let init s i v = let init s i v =
consume_write_gas Raw_context.init (s, i) v >>=? fun (c, bytes) -> consume_write_gas Raw_context.init (s, i) v >>=? fun (c, bytes) ->
Raw_context.init c N.name bytes >>=? fun c -> Raw_context.init c N.name bytes >>=? fun c ->
return (Raw_context.project c, MBytes.length bytes) let size = MBytes.length bytes in
Lwt.return (Raw_context.record_bytes_stored c (Int64.of_int size)) >>=? fun c ->
return (Raw_context.project c, size)
let init_set s i v = let init_set s i v =
let init_set c k v = Raw_context.init_set c k v >>= return in let init_set c k v = Raw_context.init_set c k v >>= return in
consume_write_gas init_set (s, i) v >>=? fun (c, bytes) -> consume_write_gas init_set (s, i) v >>=? fun (c, bytes) ->
existing_size c >>=? fun prev_size -> existing_size c >>=? fun prev_size ->
init_set c N.name bytes >>=? fun c -> init_set c N.name bytes >>=? fun c ->
return (Raw_context.project c, MBytes.length bytes - prev_size) let size_diff = MBytes.length bytes - prev_size in
Lwt.return (Raw_context.record_bytes_stored c (Int64.of_int size_diff)) >>=? fun c ->
return (Raw_context.project c, size_diff)
let remove s i = let remove s i =
let remove c k = Raw_context.remove c k >>= return in let remove c k = Raw_context.remove c k >>= return in
consume_remove_gas remove (s, i) >>=? fun c -> consume_remove_gas remove (s, i) >>=? fun c ->
existing_size (s, i) >>=? fun prev_size -> existing_size (s, i) >>=? fun prev_size ->
remove c N.name >>=? fun c -> remove c N.name >>=? fun c ->
Lwt.return (Raw_context.record_bytes_stored c (Int64.of_int ~-prev_size)) >>=? fun c ->
return (Raw_context.project c, prev_size) return (Raw_context.project c, prev_size)
let delete s i = let delete s i =
consume_remove_gas Raw_context.delete (s, i) >>=? fun c -> consume_remove_gas Raw_context.delete (s, i) >>=? fun c ->
existing_size (s, i) >>=? fun prev_size -> existing_size (s, i) >>=? fun prev_size ->
Raw_context.delete c N.name >>=? fun c -> Raw_context.delete c N.name >>=? fun c ->
Lwt.return (Raw_context.record_bytes_stored c (Int64.of_int ~-prev_size)) >>=? fun c ->
return (Raw_context.project c, prev_size) return (Raw_context.project c, prev_size)
let set_option s i v = let set_option s i v =
match v with match v with
@ -856,6 +883,7 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX)
consume_remove_gas remove (s, i) >>=? fun (s, _) -> consume_remove_gas remove (s, i) >>=? fun (s, _) ->
existing_size (s, i) >>=? fun prev_size -> existing_size (s, i) >>=? fun prev_size ->
remove (s,i) N.name >>=? fun (s, _) -> remove (s,i) N.name >>=? fun (s, _) ->
Lwt.return (Raw_context.record_bytes_stored (s, i) (Int64.of_int ~-prev_size)) >>=? fun (s, _) ->
return (s, Z.add total (Z.of_int prev_size)) return (s, Z.add total (Z.of_int prev_size))
end >>=? fun (s, total) -> end >>=? fun (s, total) ->
return (C.project s, total) return (C.project s, total)

View File

@ -0,0 +1,51 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2016. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
type t =
| Unaccounted
| Limited of { remaining : Int64.t }
type error += Block_quota_exceeded (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
let () =
let open Data_encoding in
register_error_kind
`Temporary
~id:"storage_exhausted.operation"
~title: "Storage quota exceeded for the operation"
~description:
"A script or one of its callee wrote more \
bytes than the operation said it would"
empty
(function Operation_quota_exceeded -> Some () | _ -> None)
(fun () -> Operation_quota_exceeded) ;
register_error_kind
`Temporary
~id:"storage_exhausted.block"
~title: "Storage quota exceeded for the block"
~description:
"The sum of storage consumed by all the operations in the block \
exceeds the hard storage limit per block"
empty
(function Block_quota_exceeded -> Some () | _ -> None)
(fun () -> Block_quota_exceeded)
let consume block_storage operation_storage ~bytes = match operation_storage with
| Unaccounted -> ok (block_storage, Unaccounted)
| Limited { remaining } ->
let remaining =
Int64.sub remaining bytes in
let block_remaining =
Int64.sub block_storage bytes in
if Compare.Int64.(remaining < 0L)
then error Operation_quota_exceeded
else if Compare.Int64.(block_remaining < 0L)
then error Block_quota_exceeded
else ok (block_remaining, Limited { remaining })

View File

@ -0,0 +1,17 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2016. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
type t =
| Unaccounted
| Limited of { remaining : Int64.t }
type error += Block_quota_exceeded (* `Temporary *)
type error += Operation_quota_exceeded (* `Temporary *)
val consume : Int64.t -> t -> bytes:Int64.t -> (Int64.t * t) tzresult

View File

@ -26,6 +26,7 @@ let manager (src : Helpers_account.t) ?(fee = Tez.zero) operations context gas_l
counter ; counter ;
operations = (if revealed then operations else Reveal src.pub :: operations) ; operations = (if revealed then operations else Reveal src.pub :: operations) ;
gas_limit ; gas_limit ;
storage_limit = 30_000L ;
} }