Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit d36a09f

Browse files
committed
Add StorageMeter
1 parent 042ea46 commit d36a09f

File tree

20 files changed

+2744
-1476
lines changed

20 files changed

+2744
-1476
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/node/executor/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ sc-executor = { version = "0.10.0-dev", path = "../../../client/executor" }
2020
sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
2121
sp-keystore = { version = "0.10.0-dev", path = "../../../primitives/keystore" }
2222
sp-state-machine = { version = "0.10.0-dev", path = "../../../primitives/state-machine" }
23+
sp-tracing = { version = "4.0.0-dev", path = "../../../primitives/tracing" }
2324
sp-trie = { version = "4.0.0-dev", path = "../../../primitives/trie" }
2425
frame-benchmarking = { version = "4.0.0-dev", path = "../../../frame/benchmarking" }
2526

bin/node/executor/tests/basic.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ fn deploying_wasm_contract_should_work() {
675675

676676
let addr = pallet_contracts::Pallet::<Runtime>::contract_address(&charlie(), &transfer_ch, &[]);
677677

678-
let subsistence = pallet_contracts::Pallet::<Runtime>::subsistence_threshold();
678+
let min_balance = <Runtime as pallet_contracts::Config>::Currency::minimum_balance();
679679

680680
let time = 42 * 1000;
681681
let b = construct_block(
@@ -691,8 +691,9 @@ fn deploying_wasm_contract_should_work() {
691691
signed: Some((charlie(), signed_extra(0, 0))),
692692
function: Call::Contracts(
693693
pallet_contracts::Call::instantiate_with_code::<Runtime> {
694-
endowment: 1000 * DOLLARS + subsistence,
694+
endowment: 1000 * DOLLARS + min_balance,
695695
gas_limit: 500_000_000,
696+
storage_limit: None,
696697
code: transfer_code,
697698
data: Vec::new(),
698699
salt: Vec::new(),
@@ -705,6 +706,7 @@ fn deploying_wasm_contract_should_work() {
705706
dest: sp_runtime::MultiAddress::Id(addr.clone()),
706707
value: 10,
707708
gas_limit: 500_000_000,
709+
storage_limit: None,
708710
data: vec![0x00, 0x01, 0x02, 0x03],
709711
}),
710712
},

bin/node/executor/tests/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub fn executor_call<
119119
hash: sp_core::blake2_256(&code).to_vec(),
120120
heap_pages: heap_pages.and_then(|hp| Decode::decode(&mut &hp[..]).ok()),
121121
};
122-
122+
sp_tracing::try_init_simple();
123123
executor().call::<R, NC>(&mut t, &runtime_code, method, data, use_native, native_call)
124124
}
125125

bin/node/runtime/src/lib.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -887,10 +887,8 @@ impl pallet_tips::Config for Runtime {
887887
}
888888

889889
parameter_types! {
890-
pub ContractDeposit: Balance = deposit(
891-
1,
892-
<pallet_contracts::Pallet<Runtime>>::contract_info_size(),
893-
);
890+
pub const DepositPerItem: Balance = deposit(1, 0);
891+
pub const DepositPerByte: Balance = deposit(0, 1);
894892
pub const MaxValueSize: u32 = 16 * 1024;
895893
// The lazy deletion runs inside on_initialize.
896894
pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
@@ -917,7 +915,8 @@ impl pallet_contracts::Config for Runtime {
917915
/// change because that would break already deployed contracts. The `Call` structure itself
918916
/// is not allowed to change the indices of existing pallets, too.
919917
type CallFilter = Nothing;
920-
type ContractDeposit = ContractDeposit;
918+
type DepositPerItem = DepositPerItem;
919+
type DepositPerByte = DepositPerByte;
921920
type CallStack = [pallet_contracts::Frame<Self>; 31];
922921
type WeightPrice = pallet_transaction_payment::Pallet<Self>;
923922
type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
@@ -1509,21 +1508,32 @@ impl_runtime_apis! {
15091508
dest: AccountId,
15101509
value: Balance,
15111510
gas_limit: u64,
1511+
storage_limit: Option<Balance>,
15121512
input_data: Vec<u8>,
1513-
) -> pallet_contracts_primitives::ContractExecResult {
1514-
Contracts::bare_call(origin, dest, value, gas_limit, input_data, true)
1513+
) -> pallet_contracts_primitives::ContractExecResult<Balance> {
1514+
Contracts::bare_call(origin, dest, value, gas_limit, storage_limit, input_data, true)
15151515
}
15161516

15171517
fn instantiate(
15181518
origin: AccountId,
15191519
endowment: Balance,
15201520
gas_limit: u64,
1521+
storage_limit: Option<Balance>,
15211522
code: pallet_contracts_primitives::Code<Hash>,
15221523
data: Vec<u8>,
15231524
salt: Vec<u8>,
1524-
) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId>
1525+
) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, Balance>
1526+
{
1527+
Contracts::bare_instantiate(origin, endowment, gas_limit, storage_limit, code, data, salt, true)
1528+
}
1529+
1530+
fn upload_code(
1531+
origin: AccountId,
1532+
code: Vec<u8>,
1533+
storage_limit: Option<Balance>,
1534+
) -> pallet_contracts_primitives::CodeUploadResult<Hash, Balance>
15251535
{
1526-
Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true)
1536+
Contracts::bare_upload_code(origin, code, storage_limit)
15271537
}
15281538

15291539
fn get_storage(

frame/contracts/common/src/lib.rs

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
use bitflags::bitflags;
2323
use codec::{Decode, Encode};
2424
use sp_core::Bytes;
25-
use sp_runtime::{DispatchError, RuntimeDebug};
25+
use sp_runtime::{traits::Zero, DispatchError, RuntimeDebug, traits::Saturating};
2626
use sp_std::prelude::*;
2727

2828
#[cfg(feature = "std")]
@@ -34,7 +34,7 @@ use serde::{Deserialize, Serialize};
3434
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
3535
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
3636
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
37-
pub struct ContractResult<T> {
37+
pub struct ContractResult<R, Balance> {
3838
/// How much gas was consumed during execution.
3939
pub gas_consumed: u64,
4040
/// How much gas is required as gas limit in order to execute this call.
@@ -45,7 +45,14 @@ pub struct ContractResult<T> {
4545
///
4646
/// This can only different from [`Self::gas_consumed`] when weight pre charging
4747
/// is used. Currently, only `seal_call_runtime` makes use of pre charging.
48+
/// Additionally, any `seal_call` or `seal_instantiate` makes use of pre-charging
49+
/// when a non-zero `gas_limit` argument is supplied.
4850
pub gas_required: u64,
51+
/// How much balance was deposited and reserved during execution in order to pay for storage.
52+
///
53+
/// The storage deposit is never actually charged from the caller in case of [`Self::result`]
54+
/// is `Err`. This is because on error all storage changes are rolled back.
55+
pub storage_deposit: StorageDeposit<Balance>,
4956
/// An optional debug message. This message is only filled when explicitly requested
5057
/// by the code that calls into the contract. Otherwise it is empty.
5158
///
@@ -63,15 +70,20 @@ pub struct ContractResult<T> {
6370
#[cfg_attr(feature = "std", serde(with = "as_string"))]
6471
pub debug_message: Vec<u8>,
6572
/// The execution result of the wasm code.
66-
pub result: T,
73+
pub result: R,
6774
}
6875

6976
/// Result type of a `bare_call` call.
70-
pub type ContractExecResult = ContractResult<Result<ExecReturnValue, DispatchError>>;
77+
pub type ContractExecResult<Balance> =
78+
ContractResult<Result<ExecReturnValue, DispatchError>, Balance>;
7179

7280
/// Result type of a `bare_instantiate` call.
73-
pub type ContractInstantiateResult<AccountId> =
74-
ContractResult<Result<InstantiateReturnValue<AccountId>, DispatchError>>;
81+
pub type ContractInstantiateResult<AccountId, Balance> =
82+
ContractResult<Result<InstantiateReturnValue<AccountId>, DispatchError>, Balance>;
83+
84+
/// Result type of a `bare_code_upload` call.
85+
pub type CodeUploadResult<CodeHash, Balance> =
86+
Result<CodeUploadReturnValue<CodeHash, Balance>, DispatchError>;
7587

7688
/// Result type of a `get_storage` call.
7789
pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
@@ -123,6 +135,17 @@ pub struct InstantiateReturnValue<AccountId> {
123135
pub account_id: AccountId,
124136
}
125137

138+
/// The result of succesfully uploading a contract.
139+
#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
140+
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
141+
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
142+
pub struct CodeUploadReturnValue<CodeHash, Balance> {
143+
/// The key under which the new code is stored.
144+
pub code_hash: CodeHash,
145+
/// The deposit that was reserved at the caller. Is zero when the code already existed.
146+
pub deposit: Balance,
147+
}
148+
126149
/// Reference to an existing code hash or a new wasm module.
127150
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
128151
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -134,6 +157,96 @@ pub enum Code<Hash> {
134157
Existing(Hash),
135158
}
136159

160+
/// The amount of balance that was either charged or refunded in order to pay for storage.
161+
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug, Clone)]
162+
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
163+
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
164+
pub enum StorageDeposit<Balance> {
165+
/// The transaction increased overall storage usage.
166+
///
167+
/// This means that the specified amount of balance was transferred from the call origin
168+
/// to the contracts involved.
169+
Charge(Balance),
170+
/// The transaction reduced storage consumption.
171+
///
172+
/// This means that the specified amount of balance was transferred from the involved
173+
/// contracts to the call origin.
174+
Refund(Balance),
175+
}
176+
177+
impl<Balance: Zero> Default for StorageDeposit<Balance> {
178+
fn default() -> Self {
179+
Self::Charge(Zero::zero())
180+
}
181+
}
182+
183+
impl<Balance: Zero> StorageDeposit<Balance> {
184+
/// Returns how much balance is charged or `0` in case of a refund.
185+
pub fn charge_or_zero(self) -> Balance {
186+
match self {
187+
Self::Charge(amount) => amount,
188+
Self::Refund(_) => Zero::zero(),
189+
}
190+
}
191+
}
192+
193+
impl<Balance> StorageDeposit<Balance>
194+
where
195+
Balance: Saturating + Ord + Copy
196+
{
197+
/// This is essentially a saturating signed add.
198+
pub fn saturating_add(&self, rhs: &Self) -> Self {
199+
use StorageDeposit::*;
200+
match (self, rhs) {
201+
(Charge(lhs), Charge(rhs)) => Charge(lhs.saturating_add(*rhs)),
202+
(Refund(lhs), Refund(rhs)) => Refund(lhs.saturating_add(*rhs)),
203+
(Charge(lhs), Refund(rhs)) => if lhs >= rhs {
204+
Charge(lhs.saturating_sub(*rhs))
205+
} else {
206+
Refund(rhs.saturating_sub(*lhs))
207+
},
208+
(Refund(lhs), Charge(rhs)) => if lhs > rhs {
209+
Refund(lhs.saturating_sub(*rhs))
210+
} else {
211+
Charge(rhs.saturating_sub(*lhs))
212+
},
213+
}
214+
}
215+
216+
/// This is essentially a saturating signed sub.
217+
pub fn saturating_sub(&self, rhs: &Self) -> Self {
218+
use StorageDeposit::*;
219+
match (self, rhs) {
220+
(Charge(lhs), Refund(rhs)) => Charge(lhs.saturating_add(*rhs)),
221+
(Refund(lhs), Charge(rhs)) => Refund(lhs.saturating_add(*rhs)),
222+
(Charge(lhs), Charge(rhs)) => if lhs >= rhs {
223+
Charge(lhs.saturating_sub(*rhs))
224+
} else {
225+
Refund(rhs.saturating_sub(*lhs))
226+
},
227+
(Refund(lhs), Refund(rhs)) => if lhs > rhs {
228+
Refund(lhs.saturating_sub(*rhs))
229+
} else {
230+
Charge(rhs.saturating_sub(*lhs))
231+
},
232+
}
233+
}
234+
235+
/// If the amount of deposit (this type) is constrained by a `limit` this calcuates how
236+
/// much balance (if any) is still available from this limit.
237+
///
238+
/// # Note
239+
///
240+
/// In case of a refund the return value can be larger than `limit`.
241+
pub fn available(&self, limit: &Balance) -> Balance {
242+
use StorageDeposit::*;
243+
match self {
244+
Charge(amount) => limit.saturating_sub(*amount),
245+
Refund(amount) => limit.saturating_add(*amount),
246+
}
247+
}
248+
}
249+
137250
#[cfg(feature = "std")]
138251
mod as_string {
139252
use super::*;

frame/contracts/rpc/runtime-api/src/lib.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
use codec::Codec;
2727
use pallet_contracts_primitives::{
28-
Code, ContractExecResult, ContractInstantiateResult, GetStorageResult,
28+
Code, CodeUploadResult, ContractExecResult, ContractInstantiateResult, GetStorageResult,
2929
};
3030
use sp_std::vec::Vec;
3131

@@ -45,8 +45,9 @@ sp_api::decl_runtime_apis! {
4545
dest: AccountId,
4646
value: Balance,
4747
gas_limit: u64,
48+
storage_limit: Option<Balance>,
4849
input_data: Vec<u8>,
49-
) -> ContractExecResult;
50+
) -> ContractExecResult<Balance>;
5051

5152
/// Instantiate a new contract.
5253
///
@@ -55,10 +56,21 @@ sp_api::decl_runtime_apis! {
5556
origin: AccountId,
5657
endowment: Balance,
5758
gas_limit: u64,
59+
storage_limit: Option<Balance>,
5860
code: Code<Hash>,
5961
data: Vec<u8>,
6062
salt: Vec<u8>,
61-
) -> ContractInstantiateResult<AccountId>;
63+
) -> ContractInstantiateResult<AccountId, Balance>;
64+
65+
66+
/// Upload new code without instantiating a contract from it.
67+
///
68+
/// See `pallet_contracts::Pallet::upload_code`.
69+
fn upload_code(
70+
origin: AccountId,
71+
code: Vec<u8>,
72+
storage_limit: Option<Balance>,
73+
) -> CodeUploadResult<Hash, Balance>;
6274

6375
/// Query a given storage key in a given contract.
6476
///

0 commit comments

Comments
 (0)