Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove gas metering from fn put_code()
  • Loading branch information
athei committed Apr 22, 2020
commit 39ef81d3beb93eb41303a9faacfdaffbcb57449f
2 changes: 1 addition & 1 deletion bin/node/executor/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ fn deploying_wasm_contract_should_work() {
CheckedExtrinsic {
signed: Some((charlie(), signed_extra(0, 0))),
function: Call::Contracts(
pallet_contracts::Call::put_code::<Runtime>(500_000_000, transfer_code)
pallet_contracts::Call::put_code::<Runtime>(transfer_code)
),
},
CheckedExtrinsic {
Expand Down
14 changes: 8 additions & 6 deletions frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,23 +469,21 @@ decl_module! {
/// Stores the given binary Wasm code into the chain's storage and returns its `codehash`.
/// You can instantiate contracts only with stored code.
#[weight = FunctionOf(
|args: (&Weight, &Vec<u8>)| args.0 + MINIMUM_WEIGHT,
|args: (&Vec<u8>,)| Module::<T>::calc_code_put_costs(args.0) + MINIMUM_WEIGHT,
DispatchClass::Normal,
Pays::Yes
)]
pub fn put_code(
origin,
#[compact] gas_limit: Gas,
code: Vec<u8>
) -> DispatchResultWithPostInfo {
) -> DispatchResult {
ensure_signed(origin)?;
let mut gas_meter = GasMeter::new(gas_limit);
let schedule = <Module<T>>::current_schedule();
let result = wasm::save_code::<T>(code, &mut gas_meter, &schedule);
let result = wasm::save_code::<T>(code, &schedule);
if let Ok(code_hash) = result {
Self::deposit_event(RawEvent::CodeStored(code_hash));
}
gas_meter.into_dispatch_result(result)
result.map(|_| ()).map_err(Into::into)
}

/// Makes a call to an account, optionally transferring some balance.
Expand Down Expand Up @@ -631,6 +629,10 @@ impl<T: Trait> Module<T> {
}

impl<T: Trait> Module<T> {
fn calc_code_put_costs(code: &Vec<u8>) -> Gas {
<Module<T>>::current_schedule().put_code_per_byte_cost.saturating_mul(code.len() as Gas)
}

fn execute_wasm(
origin: T::AccountId,
gas_meter: &mut GasMeter<T>,
Expand Down
52 changes: 26 additions & 26 deletions frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ fn instantiate_and_call_and_deposit_event() {
ExtBuilder::default().existential_deposit(100).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);

assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Check at the end to get hash on error easily
let creation = Contracts::instantiate(
Expand Down Expand Up @@ -436,7 +436,7 @@ fn dispatch_call() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);

assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Let's keep this assert even though it's redundant. If you ever need to update the
// wasm source this test will fail and will show you the actual hash.
Expand Down Expand Up @@ -557,7 +557,7 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);

assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Let's keep this assert even though it's redundant. If you ever need to update the
// wasm source this test will fail and will show you the actual hash.
Expand Down Expand Up @@ -653,7 +653,7 @@ fn run_out_of_gas() {
.execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);

assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
Expand Down Expand Up @@ -699,7 +699,7 @@ fn test_set_rent_code_and_hash() {

ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// If you ever need to update the wasm source this test will fail
// and will show you the actual hash.
Expand Down Expand Up @@ -731,7 +731,7 @@ fn storage_size() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
30_000,
Expand Down Expand Up @@ -768,7 +768,7 @@ fn deduct_blocks() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
30_000,
Expand Down Expand Up @@ -862,7 +862,7 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool)
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
100,
Expand Down Expand Up @@ -895,7 +895,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm.clone()));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
100,
Expand Down Expand Up @@ -931,7 +931,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm.clone()));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
1_000,
Expand Down Expand Up @@ -966,7 +966,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm.clone()));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
50+Balances::minimum_balance(),
Expand Down Expand Up @@ -1010,7 +1010,7 @@ fn call_removed_contract() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm.clone()));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
100,
Expand Down Expand Up @@ -1054,7 +1054,7 @@ fn default_rent_allowance_on_instantiate() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
30_000,
Expand Down Expand Up @@ -1107,8 +1107,8 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:

ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, restoration_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, set_rent_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm));

// If you ever need to update the wasm source this test will fail
// and will show you the actual hash.
Expand Down Expand Up @@ -1323,7 +1323,7 @@ fn storage_max_value_limit() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
30_000,
Expand Down Expand Up @@ -1369,8 +1369,8 @@ fn deploy_and_call_other_contract() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, callee_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, caller_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));

assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
Expand All @@ -1397,7 +1397,7 @@ fn cannot_self_destruct_through_draning() {
let (wasm, code_hash) = compile_module::<Test>(&load_wasm("drain.wat")).unwrap();
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Instantiate the BOB contract.
assert_ok!(Contracts::instantiate(
Expand Down Expand Up @@ -1435,7 +1435,7 @@ fn cannot_self_destruct_while_live() {
.unwrap();
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Instantiate the BOB contract.
assert_ok!(Contracts::instantiate(
Expand Down Expand Up @@ -1479,7 +1479,7 @@ fn self_destruct_works() {
.unwrap();
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Instantiate the BOB contract.
assert_ok!(Contracts::instantiate(
Expand Down Expand Up @@ -1528,8 +1528,8 @@ fn destroy_contract_and_transfer_funds() {
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
// Create
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, callee_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, caller_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));

// This deploys the BOB contract, which in turn deploys the CHARLIE contract during
// construction.
Expand Down Expand Up @@ -1567,7 +1567,7 @@ fn cannot_self_destruct_in_constructor() {
compile_module::<Test>(&load_wasm("self_destructing_constructor.wat")).unwrap();
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Fail to instantiate the BOB because the call that is issued in the deploy
// function exhausts all balances which puts it below the existential deposit.
Expand Down Expand Up @@ -1595,7 +1595,7 @@ fn get_runtime_storage() {
0x14144020u32.to_le_bytes().to_vec().as_ref()
);

assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
100,
Expand All @@ -1619,7 +1619,7 @@ fn crypto_hashes() {

ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), GAS_LIMIT, wasm));
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));

// Instantiate the CRYPTO_HASHES contract.
assert_ok!(Contracts::instantiate(
Expand Down
31 changes: 1 addition & 30 deletions frame/contracts/src/wasm/code_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,49 +26,20 @@
//! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one.
//! Thus, before executing a contract it should be reinstrument with new schedule.

use crate::gas::{Gas, GasMeter, Token};
use crate::wasm::{prepare, runtime::Env, PrefabWasmModule};
use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait};
use sp_std::prelude::*;
use sp_runtime::traits::{Hash, Bounded};
use sp_runtime::traits::Hash;
use frame_support::StorageMap;

/// Gas metering token that used for charging storing code into the code storage.
///
/// Specifies the code length in bytes.
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Copy, Clone)]
pub struct PutCodeToken(u32);

impl<T: Trait> Token<T> for PutCodeToken {
type Metadata = Schedule;

fn calculate_amount(&self, metadata: &Schedule) -> Gas {
metadata
.put_code_per_byte_cost
.checked_mul(self.0.into())
.unwrap_or_else(|| Bounded::max_value())
}
}

/// Put code in the storage. The hash of code is used as a key and is returned
/// as a result of this function.
///
/// This function instruments the given code and caches it in the storage.
pub fn save<T: Trait>(
original_code: Vec<u8>,
gas_meter: &mut GasMeter<T>,
schedule: &Schedule,
) -> Result<CodeHash<T>, &'static str> {
// The first time instrumentation is on the user. However, consequent reinstrumentation
// due to the schedule changes is on governance system.
if gas_meter
.charge(schedule, PutCodeToken(original_code.len() as u32))
.is_out_of_gas()
{
return Err("there is not enough gas for storing the code");
}

let prefab_module = prepare::prepare_contract::<Env>(&original_code, schedule)?;
let code_hash = T::Hashing::hash(&original_code);

Expand Down