Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale down gas consumption #877

Merged
merged 12 commits into from
Aug 14, 2020
  •  
  •  
  •  
19 changes: 13 additions & 6 deletions src/base/Checker.ml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ open EventInfo
open TypeInfo
open Cashflow
open Accept
open Stdint
module Parser = ScillaParser.Make (ParserSyntax)
module PSRep = ParserRep
module PERep = ParserRep
Expand Down Expand Up @@ -202,7 +203,7 @@ let wrap_error_with_gas gas res =

let check_lmodule cli =
let r =
let initial_gas = cli.gas_limit in
let initial_gas = Uint64.mul Gas.scale_factor cli.gas_limit in
let%bind (lmod : ParserSyntax.lmodule) =
wrap_error_with_gas initial_gas
@@ check_parsing cli.input_file Parser.Incremental.lmodule
Expand All @@ -228,10 +229,13 @@ let check_lmodule cli =
let type_info =
if cli.p_type_info then TI.type_info_lmod typed_lmod else []
in
pure ((typed_lmod, typed_rlibs, typed_elibs), type_info, remaining_gas)
let remaining_gas' =
Gas.finalize_remaining_gas cli.gas_limit remaining_gas
in
pure ((typed_lmod, typed_rlibs, typed_elibs), type_info, remaining_gas')
in
match r with
| Error (s, g) -> fatal_error_gas s g
| Error (s, g) -> fatal_error_gas_scale Gas.scale_factor s g
| Ok (_, type_info, g) ->
let json_output =
if cli.p_type_info then
Expand All @@ -255,7 +259,7 @@ let check_lmodule cli =
(* Check a contract module. *)
let check_cmodule cli =
let r =
let initial_gas = cli.gas_limit in
let initial_gas = Uint64.mul Gas.scale_factor cli.gas_limit in
let%bind (cmod : ParserSyntax.cmodule) =
wrap_error_with_gas initial_gas
@@ check_parsing cli.input_file Parser.Incremental.cmodule
Expand Down Expand Up @@ -296,10 +300,13 @@ let check_cmodule cli =
if cli.cf_flag then Some (check_cashflow typed_cmod cli.cf_token_fields)
else None
in
pure @@ (cmod, tenv, event_info, type_info, cf_info_opt, remaining_gas)
let remaining_gas' =
Gas.finalize_remaining_gas cli.gas_limit remaining_gas
in
pure @@ (cmod, tenv, event_info, type_info, cf_info_opt, remaining_gas')
in
match r with
| Error (s, g) -> fatal_error_gas s g
| Error (s, g) -> fatal_error_gas_scale Gas.scale_factor s g
| Ok (cmod, _, event_info, type_info, cf_info_opt, g) ->
check_version cmod.smver;
let output =
Expand Down
11 changes: 11 additions & 0 deletions src/base/Gas.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ open Scilla_crypto.Schnorr
open PrettyPrinters
open Datatypes.SnarkTypes

let scale_factor = Stdint.Uint64.of_int 8

(* Scale down the remaining gas to original metrics *)
let finalize_remaining_gas initial_gas_limit remaining_gas =
let open Stdint in
let remain = Uint64.div remaining_gas scale_factor in
(* Ensure that at least one unit of gas is consumed. *)
if Uint64.compare remain initial_gas_limit = 0 then
Uint64.sub remain Uint64.one
else remain

(* Arbitrarily picked, the largest prime less than 100. *)
let version_mismatch_penalty = 97

Expand Down
6 changes: 6 additions & 0 deletions src/base/PrettyPrinters.ml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@ let fatal_error_gas err gas_remaining =
let msg = scilla_error_gas_string gas_remaining err in
raise (FatalError msg)

let fatal_error_gas_scale scaling_factor err gas_remaining =
let msg =
scilla_error_gas_string (Uint64.div gas_remaining scaling_factor) err
in
raise (FatalError msg)

let fatal_error_noformat msg = raise (FatalError msg)

(*****************************************************)
Expand Down
56 changes: 33 additions & 23 deletions src/eval/Runner.ml
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ let check_libs clibs elibs name gas_limit =
(String.concat ~sep:", " (List.rev_map res ~f:fst))
name);
gas_remaining
| Error (err, gas_remaining) -> fatal_error_gas err gas_remaining
| Error (err, gas_remaining) ->
fatal_error_gas_scale Gas.scale_factor err gas_remaining

(****************************************************)
(* Checking initialized contract state *)
(****************************************************)
let check_extract_cstate name res gas_limit =
match res Eval.init_gas_kont gas_limit with
| Error (err, remaining_gas) -> fatal_error_gas err remaining_gas
| Error (err, remaining_gas) ->
fatal_error_gas_scale Gas.scale_factor err remaining_gas
| Ok ((_, cstate, field_vals), remaining_gas) ->
plog (sprintf "[Initializing %s's fields]\nSuccess!\n" name);
(cstate, remaining_gas, field_vals)
Expand All @@ -67,7 +69,8 @@ let check_extract_cstate name res gas_limit =

let check_after_step res gas_limit =
match res Eval.init_gas_kont gas_limit with
| Error (err, remaining_gas) -> fatal_error_gas err remaining_gas
| Error (err, remaining_gas) ->
fatal_error_gas_scale Gas.scale_factor err remaining_gas
| Ok ((cstate, outs, events, accepted_b), remaining_gas) ->
plog
( sprintf "Success! Here's what we got:\n"
Expand Down Expand Up @@ -107,7 +110,7 @@ let output_message_json gas_remaining mlist =
(List.map mlist ~f:(function
| Msg m -> JSON.Message.message_to_json m
| _ ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
(mk_error0 "Attempt to send non-message construct.")
gas_remaining))

Expand All @@ -122,7 +125,7 @@ let validate_get_init_json init_file gas_remaining source_ver =
let initargs =
try JSON.ContractState.get_json_data init_file
with Invalid_json s ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
(s @ mk_error0 (sprintf "Failed to parse json %s:\n" init_file))
gas_remaining
in
Expand All @@ -140,8 +143,9 @@ let validate_get_init_json init_file gas_remaining source_ver =
| Some (UintLit (Uint32L v)) ->
let mver, _, _ = scilla_version in
let v' = Uint32.to_int v in
if v' <> mver || mver <> source_ver then fatal_error_gas emsg rgas
| _ -> fatal_error_gas emsg rgas
if v' <> mver || mver <> source_ver then
fatal_error_gas_scale Gas.scale_factor emsg rgas
| _ -> fatal_error_gas_scale Gas.scale_factor emsg rgas
in
initargs

Expand All @@ -150,7 +154,7 @@ let deploy_library args gas_remaining =
| Error e ->
(* Error is printed by the parser. *)
plog (sprintf "%s\n" "Failed to parse input library file.");
fatal_error_gas e gas_remaining
fatal_error_gas_scale Gas.scale_factor e gas_remaining
| Ok lmod ->
plog
(sprintf "\n[Parsing]:\nLibrary module [%s] is successfully parsed.\n"
Expand All @@ -167,7 +171,10 @@ let deploy_library args gas_remaining =
let _ =
validate_get_init_json args.input_init gas_remaining' lmod.smver
in
`Assoc [ ("gas_remaining", `String (Uint64.to_string gas_remaining')) ]
let gas_remaining'' =
Gas.finalize_remaining_gas args.gas_limit gas_remaining'
in
`Assoc [ ("gas_remaining", `String (Uint64.to_string gas_remaining'')) ]

let run_with_args args =
let is_deployment = String.is_empty args.input_message in
Expand All @@ -176,33 +183,34 @@ let run_with_args args =
FilePath.check_extension args.input
GlobalConfig.StdlibTracker.file_extn_library
in
let initial_gas_limit = Uint64.mul args.gas_limit Gas.scale_factor in
let gas_remaining =
(* Subtract gas based on (contract+init) size / message size. *)
if is_deployment then
let cost' =
UnixLabels.((stat args.input).st_size + (stat args.input_init).st_size)
in
let cost = Uint64.of_int cost' in
if Uint64.compare args.gas_limit cost < 0 then
fatal_error_gas
if Uint64.compare initial_gas_limit cost < 0 then
fatal_error_gas_scale Gas.scale_factor
(mk_error0
(sprintf "Ran out of gas when parsing contract/init files.\n"))
Uint64.zero
else Uint64.sub args.gas_limit cost
else Uint64.sub initial_gas_limit cost
else
let cost = Uint64.of_int (UnixLabels.stat args.input_message).st_size in
(* libraries can only be deployed, not "run". *)
if is_library then
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
(mk_error0
(sprintf
"Cannot run a library contract. They can only be deployed\n"))
Uint64.zero
else if Uint64.compare args.gas_limit cost < 0 then
fatal_error_gas
else if Uint64.compare initial_gas_limit cost < 0 then
fatal_error_gas_scale Gas.scale_factor
(mk_error0 (sprintf "Ran out of gas when parsing message.\n"))
Uint64.zero
else Uint64.sub args.gas_limit cost
else Uint64.sub initial_gas_limit cost
in

if is_library then deploy_library args gas_remaining
Expand All @@ -211,7 +219,7 @@ let run_with_args args =
| Error e ->
(* Error is printed by the parser. *)
plog (sprintf "%s\n" "Failed to parse input file.");
fatal_error_gas e gas_remaining
fatal_error_gas_scale Gas.scale_factor e gas_remaining
| Ok cmod ->
plog
(sprintf
Expand All @@ -235,7 +243,7 @@ let run_with_args args =
let bstate =
try JSON.BlockChainState.get_json_data args.input_blockchain
with Invalid_json s ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
( s
@ mk_error0
(sprintf "Failed to parse json %s:\n" args.input_blockchain)
Expand Down Expand Up @@ -282,7 +290,8 @@ let run_with_args args =
in
finalize ()
with
| Error s -> fatal_error_gas s remaining_gas'
| Error s ->
fatal_error_gas_scale Gas.scale_factor s remaining_gas'
| Ok _ -> () );

(* In IPC mode, we don't need to output an initial state as it will be updated directly. *)
Expand All @@ -299,7 +308,7 @@ let run_with_args args =
let mmsg =
try JSON.Message.get_json_data args.input_message
with Invalid_json s ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
( s
@ mk_error0
(sprintf "Failed to parse json %s:\n" args.input_message)
Expand Down Expand Up @@ -333,7 +342,7 @@ let run_with_args args =
let curargs, cur_bal =
try input_state_json args.input_state
with Invalid_json s ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
( s
@ mk_error0
(sprintf "Failed to parse json %s:\n"
Expand Down Expand Up @@ -386,15 +395,16 @@ let run_with_args args =
with
| Ok fv, Ok () -> fv
| _ ->
fatal_error_gas
fatal_error_gas_scale Gas.scale_factor
(mk_error0 "Error finalizing state from StateService")
gas
in

let osj = output_state_json cstate'.balance field_vals in
let omj = output_message_json gas mlist in
let oej = `List (output_event_json elist) in
((omj, osj, oej, accepted_b), gas)
let gas' = Gas.finalize_remaining_gas args.gas_limit gas in
((omj, osj, oej, accepted_b), gas')
in
`Assoc
[
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/blowup.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "2",
"gas_remaining": "0",
"errors": [
{
"error_message": "Ran out of gas",
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/inplace-map.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "7309",
"gas_remaining": "7913",
"errors": [
{
"error_message": "Type mismatch: Int32 expected, but String provided.",
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/libdup1.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "6678",
"gas_remaining": "7834",
"errors": [
{
"error_message":
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/libdup2.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "6678",
"gas_remaining": "7834",
"errors": [
{
"error_message":
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/libindirect.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "7339",
"gas_remaining": "7917",
"errors": [
{
"error_message": "Couldn't resolve the identifier \"list_sort\".\n",
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/mappair.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "7278",
"gas_remaining": "7909",
"errors": [
{
"error_message": "Type mismatch: Int32 expected, but Int64 provided.",
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/mappair2.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "7274",
"gas_remaining": "7909",
"errors": [
{
"error_message": "Identifier malMessage1 used more than once\n",
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/bad/gold/namespace1.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"gas_remaining": "7339",
"gas_remaining": "7917",
"errors": [
{
"error_message":
Expand Down
2 changes: 1 addition & 1 deletion tests/checker/good/gold/InstantiatedListUtils.scillib.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "7339" }
{ "warnings": [], "gas_remaining": "7917" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/TestLibNS1.scillib.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "8000" }
{ "warnings": [], "gas_remaining": "7999" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/TestLibNS2.scillib.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "8000" }
{ "warnings": [], "gas_remaining": "7999" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/TestLibNS3.scillib.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "8000" }
{ "warnings": [], "gas_remaining": "7999" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/TestLibNS4.scillib.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "8000" }
{ "warnings": [], "gas_remaining": "7999" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/adt_test.scilla.gold
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@
"warning_id": 1
}
],
"gas_remaining": "8000"
"gas_remaining": "7999"
}

2 changes: 1 addition & 1 deletion tests/checker/good/gold/auction.scilla.gold
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,6 @@
"warning_id": 1
}
],
"gas_remaining": "8000"
"gas_remaining": "7999"
}

2 changes: 1 addition & 1 deletion tests/checker/good/gold/auction.scilla.typeinfo.gold
Original file line number Diff line number Diff line change
Expand Up @@ -2699,6 +2699,6 @@
"warning_id": 1
}
],
"gas_remaining": "8000"
"gas_remaining": "7999"
}

Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@
"warning_id": 1
}
],
"gas_remaining": "8000"
"gas_remaining": "7999"
}

2 changes: 1 addition & 1 deletion tests/checker/good/gold/blockchain_import.scilla.gold
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{ "warnings": [], "gas_remaining": "8000" }
{ "warnings": [], "gas_remaining": "7999" }

2 changes: 1 addition & 1 deletion tests/checker/good/gold/bookstore.scilla.gold
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,6 @@
"warning_id": 1
}
],
"gas_remaining": "8000"
"gas_remaining": "7999"
}

Loading