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
Show all changes
32 commits
Select commit Hold shift + click to select a range
a8214fd
Add logic, test, broken benchmark
yarikbratashchuk May 18, 2022
143c158
Merge branch 'master' into seal_reentrant_count
yarikbratashchuk May 20, 2022
219eb84
Merge branch 'master' into seal_reentrant_count
yarikbratashchuk May 22, 2022
fccd751
account_entrance_count
yarikbratashchuk May 23, 2022
0a70239
Addressing comments
yarikbratashchuk May 29, 2022
6f3655a
Address @agryaznov's comments
yarikbratashchuk Jun 1, 2022
f29884b
Add test for account_entrance_count, fix ci
yarikbratashchuk Jun 2, 2022
72c8f83
Cargo fmt
yarikbratashchuk Jun 2, 2022
0f6f894
Fix tests
yarikbratashchuk Jun 2, 2022
949c438
Fix tests
yarikbratashchuk Jun 5, 2022
f34b6da
Remove delegated call from test, address comments
yarikbratashchuk Jun 16, 2022
a036585
Minor fixes and indentation in wat files
yarikbratashchuk Jun 21, 2022
3be772e
Update test for account_entrance_count
yarikbratashchuk Jun 21, 2022
5fdc100
Update reentrant_count_call test
yarikbratashchuk Jun 21, 2022
b656c88
Delegate call test
yarikbratashchuk Jun 23, 2022
17bb81f
Cargo +nightly fmt
yarikbratashchuk Jun 24, 2022
2f7f405
Address comments
yarikbratashchuk Jun 24, 2022
5f01797
Update reentrant_count_works test
yarikbratashchuk Jun 24, 2022
013e3bf
Merge branch 'master' into master
yarikbratashchuk Jun 24, 2022
3948142
Apply weights diff
yarikbratashchuk Jul 3, 2022
9c0c06f
Add fixture descriptions
yarikbratashchuk Jul 3, 2022
9c5bb47
Update comments as suggested
yarikbratashchuk Jul 3, 2022
35c0349
Update reentrant_count_call test to use seal_address
yarikbratashchuk Jul 3, 2022
1efdd1a
Merge remote-tracking branch 'paritytech/master' into feature/seal_re…
Artemka374 Nov 11, 2022
028f2ca
add missing code
Artemka374 Nov 11, 2022
2e07c7b
cargo fmt
Artemka374 Nov 11, 2022
b6e5084
account_entrance_count -> account_reentrance_count
Artemka374 Nov 14, 2022
fa02149
fix tests
Artemka374 Nov 14, 2022
fa4eef6
fmt
Artemka374 Nov 14, 2022
229a3ce
normalize signatures
Artemka374 Nov 14, 2022
4ac3bb3
Merge remote-tracking branch 'paritytech/master' into feature/seal_re…
Artemka374 Nov 14, 2022
a620843
Merge remote-tracking branch 'paritytech/master' into feature/seal_re…
Artemka374 Nov 15, 2022
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
account_entrance_count
  • Loading branch information
yarikbratashchuk committed May 23, 2022
commit fccd751937684d53cdce9eff84fce1f37ef95e44
33 changes: 33 additions & 0 deletions frame/contracts/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,39 @@ benchmarks! {
let origin = RawOrigin::Signed(instance.caller.clone());
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])

seal_account_entrance_count {
let r in 0 .. API_BENCHMARK_BATCHES;
let dummy_code = WasmModule::<T>::dummy_with_bytes(0);
let accounts = (0..r * API_BENCHMARK_BATCH_SIZE)
.map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![]))
.collect::<Result<Vec<_>, _>>()?;
let account_id_len = accounts.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0);
let account_id_bytes = accounts.iter().flat_map(|x| x.account_id.encode()).collect();
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
name: "seal_account_entrance_count",
params: vec![ValueType::I32],
return_type: Some(ValueType::I32),
}],
data_segments: vec![
DataSegment {
offset: 0,
value: account_id_bytes,
},
],
call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![
Counter(0 as u32, account_id_len as u32), // account_ptr
Regular(Instruction::Call(0)),
Regular(Instruction::Drop),
])),
.. Default::default()
});
let instance = Contract::<T>::new(code, vec![])?;
let origin = RawOrigin::Signed(instance.caller.clone());
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])

// We make the assumption that pushing a constant and dropping a value takes roughly
// the same amount of time. We follow that `t.load` and `drop` both have the weight
// of this benchmark / 2. We need to make this assumption because there is no way
Expand Down
17 changes: 13 additions & 4 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,14 @@ pub trait Ext: sealing::Sealed {
/// Sets new code hash for existing contract.
fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> Result<(), DispatchError>;

/// Returns how often the currently executing contract exists on the call stack
/// in addition to the calling instance. So a value of 0 means no reentrancy.
/// Returns then number of times currently executing contract exists on the call stack in addition
/// to the calling instance. A value of 0 means no reentrancy.
fn reentrant_count(&mut self) -> u32;

/// Returns the number of times specified contract exists on the call stack. Delegated calls are not
/// calculated as separate entrance.
/// A value of 0 means it does not exist on the call stack.
fn account_entrance_count(&mut self, account_id: AccountIdOf<Self::T>) -> u32;
}

/// Describes the different functions that can be exported by an [`Executable`].
Expand Down Expand Up @@ -1233,8 +1238,12 @@ where
}

fn reentrant_count(&mut self) -> u32 {
let id: &AccountIdOf<Self::T> = &self.top_frame().account_id;
(self.frames().filter_map(|f| Some(f.delegate_caller.is_none() && &f.account_id == id)).count() - 1).try_into().unwrap()
let id: AccountIdOf<Self::T> = self.top_frame().account_id.clone();
self.account_entrance_count(id) - 1u32
}

fn account_entrance_count(&mut self, account_id: AccountIdOf<Self::T>) -> u32 {
self.frames().filter_map(|f| Some(f.delegate_caller.is_none() && &f.account_id == &account_id)).count() as u32
}
}

Expand Down
4 changes: 4 additions & 0 deletions frame/contracts/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ pub struct HostFnWeights<T: Config> {
/// Weight of calling `seal_reentrant_count`.
pub reentrant_count: Weight,

/// Weight of calling `seal_account_entrance_count`.
pub account_entrance_count: Weight,

/// The type parameter is used in the default implementation.
#[codec(skip)]
pub _phantom: PhantomData<T>,
Expand Down Expand Up @@ -655,6 +658,7 @@ impl<T: Config> Default for HostFnWeights<T> {
ecdsa_recover: cost_batched!(seal_ecdsa_recover),
ecdsa_to_eth_address: cost_batched!(seal_ecdsa_to_eth_address),
reentrant_count: cost_batched!(seal_reentrant_count),
account_entrance_count: cost_batched!(seal_account_entrance_count),
_phantom: PhantomData,
}
}
Expand Down
1 change: 1 addition & 0 deletions frame/contracts/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ mod tests {
self.reentrant_count.push(12u8);
12
}
fn account_entrance_count(&mut self, _account_id: AccountIdOf<Self::T>) -> u32 { unimplemented!() }
}

fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, mut ext: E) -> ExecResult {
Expand Down
16 changes: 15 additions & 1 deletion frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ pub enum RuntimeCosts {
/// Weight of calling `seal_reentrant_count`
#[cfg(feature = "unstable-interface")]
ReentrantCount,
/// Weight of calling `seal_account_entrance_count`
#[cfg(feature = "unstable-interface")]
AccountEntranceCount,
}

impl RuntimeCosts {
Expand Down Expand Up @@ -307,6 +310,8 @@ impl RuntimeCosts {
EcdsaToEthAddress => s.ecdsa_to_eth_address,
#[cfg(feature = "unstable-interface")]
ReentrantCount => s.reentrant_count,
#[cfg(feature = "unstable-interface")]
AccountEntranceCount => s.account_entrance_count,
};
RuntimeToken {
#[cfg(test)]
Expand Down Expand Up @@ -2082,10 +2087,19 @@ define_env!(Env, <E: Ext>,
}
},

// Returns how often the currently executing contract exists on the call stack in addition
// Returns then number of times currently executing contract exists on the call stack in addition
// to the calling instance. A value of 0 means no reentrancy.
[__unstable__] seal_reentrant_count(ctx) -> u32 => {
ctx.charge_gas(RuntimeCosts::ReentrantCount)?;
Ok(ctx.ext.reentrant_count() as u32)
},

// Returns the number of times specified contract exists on the call stack. Delegated calls are
// not calculated as separate calls.
// A value of 0 means it does not exist on the stack.
[__unstable__] seal_account_entrance_count(ctx, account_ptr: u32) -> u32 => {
ctx.charge_gas(RuntimeCosts::AccountEntranceCount)?;
let account_id: <<E as Ext>::T as frame_system::Config>::AccountId = ctx.read_sandbox_memory_as(account_ptr)?;
Ok(ctx.ext.account_entrance_count(account_id) as u32)
},
);
23 changes: 23 additions & 0 deletions frame/contracts/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub trait WeightInfo {
fn seal_ecdsa_to_eth_address(r: u32, ) -> Weight;
fn seal_set_code_hash(r: u32, ) -> Weight;
fn seal_reentrant_count(r: u32, ) -> Weight;
fn seal_account_entrance_count(r: u32, ) -> Weight;
fn instr_i64const(r: u32, ) -> Weight;
fn instr_i64load(r: u32, ) -> Weight;
fn instr_i64store(r: u32, ) -> Weight;
Expand Down Expand Up @@ -849,6 +850,17 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
// Storage: System Account (r:1 w:0)
// Storage: Contracts ContractInfoOf (r:1 w:1)
// Storage: Contracts CodeStorage (r:1 w:0)
// Storage: Timestamp Now (r:1 w:0)
fn seal_account_entrance_count(r: u32, ) -> Weight {
(179_313_000 as Weight)
// Standard Error: 610_000
.saturating_add((63_085_000 as Weight).saturating_mul(r as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn instr_i64const(r: u32, ) -> Weight {
(74_627_000 as Weight)
// Standard Error: 1_000
Expand Down Expand Up @@ -1793,6 +1805,17 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
// Storage: System Account (r:1 w:0)
// Storage: Contracts ContractInfoOf (r:1 w:1)
// Storage: Contracts CodeStorage (r:1 w:0)
// Storage: Timestamp Now (r:1 w:0)
fn seal_account_entrance_count(r: u32, ) -> Weight {
(179_313_000 as Weight)
// Standard Error: 610_000
.saturating_add((63_085_000 as Weight).saturating_mul(r as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn instr_i64const(r: u32, ) -> Weight {
(74_627_000 as Weight)
// Standard Error: 1_000
Expand Down