123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)letscaling_factor=1000letdecimals=3moduleArith=Fixed_point_repr.Make(structletdecimals=decimalsend)typet=Unaccounted|Limitedof{remaining:Arith.fp}typecost=Z.tletencoding=letopenData_encodinginunion[case(Tag0)~title:"Limited"Arith.z_fp_encoding(functionLimited{remaining}->Someremaining|_->None)(funremaining->Limited{remaining});case(Tag1)~title:"Unaccounted"(constant"unaccounted")(functionUnaccounted->Some()|_->None)(fun()->Unaccounted)]letppppf=function|Unaccounted->Format.fprintfppf"unaccounted"|Limited{remaining}->Format.fprintfppf"%a units remaining"Arith.ppremainingletcost_encoding=Data_encoding.zletpp_costfmtz=Format.fprintffmt"%s"(Z.to_stringz)typeerror+=Block_quota_exceeded(* `Temporary *)typeerror+=Operation_quota_exceeded(* `Temporary *)letallocation_weight=Z.of_int(scaling_factor*2)letstep_weight=Z.of_intscaling_factorletread_base_weight=Z.of_int(scaling_factor*100)letwrite_base_weight=Z.of_int(scaling_factor*160)letbyte_read_weight=Z.of_int(scaling_factor*10)letbyte_written_weight=Z.of_int(scaling_factor*15)letcost_to_milligas(cost:cost):Arith.fp=Arith.unsafe_fpcostletraw_consumeblock_gasoperation_gascost=matchoperation_gaswith|Unaccounted->ok(block_gas,Unaccounted)|Limited{remaining}->letgas=cost_to_milligascostinifArith.(gas>zero)thenletremaining=Arith.subremaininggasinletblock_remaining=Arith.subblock_gasgasinifArith.(remaining<zero)thenerrorOperation_quota_exceededelseifArith.(block_remaining<zero)thenerrorBlock_quota_exceededelseok(block_remaining,Limited{remaining})elseok(block_gas,operation_gas)letraw_check_enoughblock_gasoperation_gascost=raw_consumeblock_gasoperation_gascost>|?fun(_block_remaining,_remaining)->()letalloc_costn=Z.mulallocation_weight(Z.succn)letalloc_bytes_costn=alloc_cost(Z.of_int((n+7)/8))letatomic_step_costn=nletstep_costn=Z.mulstep_weightnletfree=Z.zeroletread_bytes_costn=Z.addread_base_weight(Z.mulbyte_read_weightn)letwrite_bytes_costn=Z.addwrite_base_weight(Z.mulbyte_written_weightn)let(+@)xy=Z.addxylet(*@)xy=Z.mulxyletalloc_mbytes_costn=alloc_cost(Z.of_int12)+@alloc_bytes_costnlet()=letopenData_encodinginregister_error_kind`Temporary~id:"gas_exhausted.operation"~title:"Gas quota exceeded for the operation"~description:"A script or one of its callee took more time than the operation said \
it would"empty(functionOperation_quota_exceeded->Some()|_->None)(fun()->Operation_quota_exceeded);register_error_kind`Temporary~id:"gas_exhausted.block"~title:"Gas quota exceeded for the block"~description:"The sum of gas consumed by all the operations in the block exceeds the \
hard gas limit per block"empty(functionBlock_quota_exceeded->Some()|_->None)(fun()->Block_quota_exceeded)