mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 12:51:05 +00:00
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:
@@ -578,6 +578,12 @@ mod tests {
|
||||
fn ecdsa_to_eth_address(&self, _pk: &[u8; 33]) -> Result<[u8; 20], ()> {
|
||||
Ok([2u8; 20])
|
||||
}
|
||||
fn reentrant_count(&self) -> u32 {
|
||||
12
|
||||
}
|
||||
fn account_reentrance_count(&self, _account_id: &AccountIdOf<Self::T>) -> u32 {
|
||||
12
|
||||
}
|
||||
}
|
||||
|
||||
fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, mut ext: E) -> ExecResult {
|
||||
@@ -2850,4 +2856,70 @@ mod tests {
|
||||
|
||||
assert_eq!(mock_ext.code_hashes.pop().unwrap(), H256::from_slice(&[17u8; 32]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
fn reentrant_count_works() {
|
||||
const CODE: &str = r#"
|
||||
(module
|
||||
(import "__unstable__" "reentrant_count" (func $reentrant_count (result i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(func $assert (param i32)
|
||||
(block $ok
|
||||
(br_if $ok
|
||||
(get_local 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(func (export "call")
|
||||
(local $return_val i32)
|
||||
(set_local $return_val
|
||||
(call $reentrant_count)
|
||||
)
|
||||
(call $assert
|
||||
(i32.eq (get_local $return_val) (i32.const 12))
|
||||
)
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
|
||||
let mut mock_ext = MockExt::default();
|
||||
execute(CODE, vec![], &mut mock_ext).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
fn account_reentrance_count_works() {
|
||||
const CODE: &str = r#"
|
||||
(module
|
||||
(import "__unstable__" "account_reentrance_count" (func $account_reentrance_count (param i32) (result i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(func $assert (param i32)
|
||||
(block $ok
|
||||
(br_if $ok
|
||||
(get_local 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(func (export "call")
|
||||
(local $return_val i32)
|
||||
(set_local $return_val
|
||||
(call $account_reentrance_count (i32.const 0))
|
||||
)
|
||||
(call $assert
|
||||
(i32.eq (get_local $return_val) (i32.const 12))
|
||||
)
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
|
||||
let mut mock_ext = MockExt::default();
|
||||
execute(CODE, vec![], &mut mock_ext).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user