From 77d0c065d349940854b8a2bf87430cc88ce715f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= <tomusdrw@users.noreply.github.com> Date: Wed, 27 Nov 2019 19:23:55 +0100 Subject: [PATCH] Hard-cap the execution time of custom contract calls. (#4226) * Reject call requests that allocate too high gas limit. * Lower to 5x --- substrate/frame/contracts/rpc/src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/substrate/frame/contracts/rpc/src/lib.rs b/substrate/frame/contracts/rpc/src/lib.rs index e330e9efcc0..6f357f53b85 100644 --- a/substrate/frame/contracts/rpc/src/lib.rs +++ b/substrate/frame/contracts/rpc/src/lib.rs @@ -39,7 +39,16 @@ const RUNTIME_ERROR: i64 = 1; const CONTRACT_DOESNT_EXIST: i64 = 2; const CONTRACT_IS_A_TOMBSTONE: i64 = 3; -// A private newtype for converting `GetStorageError` into an RPC error. +/// A rough estimate of how much gas a decent hardware consumes per second, +/// using native execution. +/// This value is used to set the upper bound for maximal contract calls to +/// prevent blocking the RPC for too long. +/// +/// Based on W3F research spreadsheet: +/// https://docs.google.com/spreadsheets/d/1h0RqncdqiWI4KgxO0z9JIpZEJESXjX_ZCK6LFX6veDo/view +const GAS_PER_SECOND: u64 = 1_000_000_000; + +/// A private newtype for converting `GetStorageError` into an RPC error. struct GetStorageError(runtime_api::GetStorageError); impl From<GetStorageError> for Error { fn from(e: GetStorageError) -> Error { @@ -148,6 +157,19 @@ where data: None, })?; + let max_gas_limit = 5 * GAS_PER_SECOND; + if gas_limit > max_gas_limit { + return Err(Error { + code: ErrorCode::InvalidParams, + message: format!( + "Requested gas limit is greater than maximum allowed: {} > {}", + gas_limit, + max_gas_limit + ), + data: None, + }); + } + let exec_result = api .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) .map_err(|e| Error { -- GitLab