seal_reentrant_count returns contract reentrant count (#12695)

* Add logic, test, broken benchmark

* account_entrance_count

* Addressing comments

* Address @agryaznov's comments

* Add test for account_entrance_count, fix ci

* Cargo fmt

* Fix tests

* Fix tests

* Remove delegated call from test, address comments

* Minor fixes and indentation in wat files

* Update test for account_entrance_count

* Update reentrant_count_call test

* Delegate call test

* Cargo +nightly fmt

* Address comments

* Update reentrant_count_works test

* Apply weights diff

* Add fixture descriptions

* Update comments as suggested

* Update reentrant_count_call test to use seal_address

* add missing code

* cargo fmt

* account_entrance_count -> account_reentrance_count

* fix tests

* fmt

* normalize signatures

Co-authored-by: yarikbratashchuk <yarik.bratashchuk@gmail.com>
This commit is contained in:
Artemka374
2022-11-15 15:12:08 +02:00
committed by GitHub
parent 679d2dcd25
commit 103ea38f95
10 changed files with 569 additions and 1 deletions
@@ -251,6 +251,12 @@ pub enum RuntimeCosts {
SetCodeHash,
/// Weight of calling `ecdsa_to_eth_address`
EcdsaToEthAddress,
/// Weight of calling `seal_reentrant_count`
#[cfg(feature = "unstable-interface")]
ReentrantCount,
/// Weight of calling `seal_account_reentrance_count`
#[cfg(feature = "unstable-interface")]
AccountEntranceCount,
}
impl RuntimeCosts {
@@ -330,6 +336,10 @@ impl RuntimeCosts {
CallRuntime(weight) => weight.ref_time(),
SetCodeHash => s.set_code_hash,
EcdsaToEthAddress => s.ecdsa_to_eth_address,
#[cfg(feature = "unstable-interface")]
ReentrantCount => s.reentrant_count,
#[cfg(feature = "unstable-interface")]
AccountEntranceCount => s.account_reentrance_count,
};
RuntimeToken {
#[cfg(test)]
@@ -1188,6 +1198,7 @@ pub mod env {
Ok(ReturnCode::KeyNotFound)
}
}
/// Transfer some value to another account.
///
/// # Parameters
@@ -1354,6 +1365,7 @@ pub mod env {
output_len_ptr,
)
}
/// Instantiate a contract with the specified code hash.
///
/// # Deprecation
@@ -2444,4 +2456,34 @@ pub mod env {
Err(_) => Ok(ReturnCode::EcdsaRecoverFailed),
}
}
/// Returns the number of times the currently executing contract exists on the call stack in
/// addition to the calling instance.
///
/// # Return Value
///
/// Returns 0 when there is no reentrancy.
#[unstable]
fn reentrant_count(ctx: Runtime<E>) -> Result<u32, TrapReason> {
ctx.charge_gas(RuntimeCosts::ReentrantCount)?;
Ok(ctx.ext.reentrant_count())
}
/// Returns the number of times specified contract exists on the call stack. Delegated calls are
/// not counted as separate calls.
///
/// # Parameters
///
/// - `account_ptr`: a pointer to the contract address.
///
/// # Return Value
///
/// Returns 0 when the contract does not exist on the call stack.
#[unstable]
fn account_reentrance_count(ctx: Runtime<E>, account_ptr: u32) -> Result<u32, TrapReason> {
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_reentrance_count(&account_id))
}
}