contracts: Add instantiation_nonce API (#12800)

* Add `instantiation_nonce` API

* Fixes for tests

* Update frame/contracts/src/schedule.rs

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* ".git/.scripts/bench-bot.sh" pallet dev pallet_contracts

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
Co-authored-by: command-bot <>
This commit is contained in:
Alexander Theißen
2022-12-06 12:01:58 +01:00
committed by GitHub
parent c336eae64a
commit 770afb9ee3
7 changed files with 169 additions and 19 deletions
+35 -6
View File
@@ -625,6 +625,9 @@ mod tests {
fn account_reentrance_count(&self, _account_id: &AccountIdOf<Self::T>) -> u32 {
12
}
fn nonce(&mut self) -> u64 {
995
}
}
fn execute_internal<E: BorrowMut<MockExt>>(
@@ -649,16 +652,16 @@ mod tests {
}
fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, ext: E) -> ExecResult {
execute_internal(wat, input_data, ext, false)
execute_internal(wat, input_data, ext, true)
}
#[cfg(not(feature = "runtime-benchmarks"))]
fn execute_with_unstable<E: BorrowMut<MockExt>>(
fn execute_no_unstable<E: BorrowMut<MockExt>>(
wat: &str,
input_data: Vec<u8>,
ext: E,
) -> ExecResult {
execute_internal(wat, input_data, ext, true)
execute_internal(wat, input_data, ext, false)
}
const CODE_TRANSFER: &str = r#"
@@ -2971,13 +2974,39 @@ mod tests {
execute(CODE, vec![], &mut mock_ext).unwrap();
}
#[test]
fn instantiation_nonce_works() {
const CODE: &str = r#"
(module
(import "seal0" "instantiation_nonce" (func $nonce (result i64)))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func (export "call")
(call $assert
(i64.eq (call $nonce) (i64.const 995))
)
)
(func (export "deploy"))
)
"#;
let mut mock_ext = MockExt::default();
execute(CODE, vec![], &mut mock_ext).unwrap();
}
/// This test check that an unstable interface cannot be deployed. In case of runtime
/// benchmarks we always allow unstable interfaces. This is why this test does not
/// work when this feature is enabled.
#[cfg(not(feature = "runtime-benchmarks"))]
#[test]
fn cannot_deploy_unstable() {
const CANNT_DEPLOY_UNSTABLE: &str = r#"
const CANNOT_DEPLOY_UNSTABLE: &str = r#"
(module
(import "seal0" "reentrance_count" (func $reentrance_count (result i32)))
(func (export "call"))
@@ -2985,9 +3014,9 @@ mod tests {
)
"#;
assert_err!(
execute(CANNT_DEPLOY_UNSTABLE, vec![], MockExt::default()),
execute_no_unstable(CANNOT_DEPLOY_UNSTABLE, vec![], MockExt::default()),
<Error<Test>>::CodeRejected,
);
assert_ok!(execute_with_unstable(CANNT_DEPLOY_UNSTABLE, vec![], MockExt::default()));
assert_ok!(execute(CANNOT_DEPLOY_UNSTABLE, vec![], MockExt::default()));
}
}
@@ -265,6 +265,8 @@ pub enum RuntimeCosts {
ReentrantCount,
/// Weight of calling `account_reentrance_count`
AccountEntranceCount,
/// Weight of calling `instantiation_nonce`
InstantationNonce,
}
impl RuntimeCosts {
@@ -344,6 +346,7 @@ impl RuntimeCosts {
EcdsaToEthAddress => s.ecdsa_to_eth_address,
ReentrantCount => s.reentrance_count,
AccountEntranceCount => s.account_reentrance_count,
InstantationNonce => s.instantiation_nonce,
};
RuntimeToken {
#[cfg(test)]
@@ -2614,4 +2617,14 @@ pub mod env {
ctx.read_sandbox_memory_as(memory, account_ptr)?;
Ok(ctx.ext.account_reentrance_count(&account_id))
}
/// Returns a nonce that is unique per contract instantiation.
///
/// The nonce is incremented for each succesful contract instantiation. This is a
/// sensible default salt for contract instantiations.
#[unstable]
fn instantiation_nonce(ctx: _, _memory: _) -> Result<u64, TrapReason> {
ctx.charge_gas(RuntimeCosts::InstantationNonce)?;
Ok(ctx.ext.nonce())
}
}