mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 05:51:02 +00:00
contracts: Improve contract address derivation (#12883)
* Add prefix to address derivation * Extend benchmark * Fix node test * ".git/.scripts/bench-bot.sh" pallet dev pallet_contracts * Adapt to new benchmark * Update dispatchable benchmarks * ".git/.scripts/bench-bot.sh" pallet dev pallet_contracts * Use benchmark results * Apply suggestions from code review Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * Don't use T::AdressGenerator directly * Rename constructor_args to input_data Co-authored-by: command-bot <> Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
committed by
GitHub
parent
af15848be0
commit
4083b5358a
@@ -105,7 +105,7 @@ use crate::{
|
||||
wasm::{OwnerInfo, PrefabWasmModule, TryInstantiate},
|
||||
weights::WeightInfo,
|
||||
};
|
||||
use codec::{Codec, Encode, HasCompact};
|
||||
use codec::{Codec, Decode, Encode, HasCompact};
|
||||
use frame_support::{
|
||||
dispatch::{Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo},
|
||||
ensure,
|
||||
@@ -123,8 +123,7 @@ use pallet_contracts_primitives::{
|
||||
StorageDeposit,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup};
|
||||
use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup, TrailingZeroInput};
|
||||
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
|
||||
|
||||
pub use crate::{
|
||||
@@ -155,7 +154,7 @@ const SENTINEL: u32 = u32::MAX;
|
||||
/// Provides the contract address generation method.
|
||||
///
|
||||
/// See [`DefaultAddressGenerator`] for the default implementation.
|
||||
pub trait AddressGenerator<T: frame_system::Config> {
|
||||
pub trait AddressGenerator<T: Config> {
|
||||
/// Generate the address of a contract based on the given instantiate parameters.
|
||||
///
|
||||
/// # Note for implementors
|
||||
@@ -166,6 +165,7 @@ pub trait AddressGenerator<T: frame_system::Config> {
|
||||
fn generate_address(
|
||||
deploying_address: &T::AccountId,
|
||||
code_hash: &CodeHash<T>,
|
||||
input_data: &[u8],
|
||||
salt: &[u8],
|
||||
) -> T::AccountId;
|
||||
}
|
||||
@@ -176,28 +176,21 @@ pub trait AddressGenerator<T: frame_system::Config> {
|
||||
/// is only dependant on its inputs. It can therefore be used to reliably predict the
|
||||
/// address of a contract. This is akin to the formula of eth's CREATE2 opcode. There
|
||||
/// is no CREATE equivalent because CREATE2 is strictly more powerful.
|
||||
///
|
||||
/// Formula: `hash(deploying_address ++ code_hash ++ salt)`
|
||||
/// Formula:
|
||||
/// `hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)`
|
||||
pub struct DefaultAddressGenerator;
|
||||
|
||||
impl<T> AddressGenerator<T> for DefaultAddressGenerator
|
||||
where
|
||||
T: frame_system::Config,
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
impl<T: Config> AddressGenerator<T> for DefaultAddressGenerator {
|
||||
fn generate_address(
|
||||
deploying_address: &T::AccountId,
|
||||
code_hash: &CodeHash<T>,
|
||||
input_data: &[u8],
|
||||
salt: &[u8],
|
||||
) -> T::AccountId {
|
||||
let buf: Vec<_> = deploying_address
|
||||
.as_ref()
|
||||
.iter()
|
||||
.chain(code_hash.as_ref())
|
||||
.chain(salt)
|
||||
.cloned()
|
||||
.collect();
|
||||
UncheckedFrom::unchecked_from(T::Hashing::hash(&buf))
|
||||
let entropy = (b"contract_addr_v1", deploying_address, code_hash, input_data, salt)
|
||||
.using_encoded(T::Hashing::hash);
|
||||
Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
|
||||
.expect("infinite length input; no invalid inputs for type; qed")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,11 +345,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T>
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash>,
|
||||
T::AccountId: AsRef<[u8]>,
|
||||
{
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight {
|
||||
Storage::<T>::process_deletion_queue_batch(remaining_weight)
|
||||
.saturating_add(T::WeightInfo::on_process_deletion_queue_batch())
|
||||
@@ -385,8 +374,6 @@ pub mod pallet {
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T>
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash>,
|
||||
T::AccountId: AsRef<[u8]>,
|
||||
<BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
|
||||
{
|
||||
/// Deprecated version if [`Self::call`] for use in an in-storage `Call`.
|
||||
@@ -415,7 +402,7 @@ pub mod pallet {
|
||||
/// Deprecated version if [`Self::instantiate_with_code`] for use in an in-storage `Call`.
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate_with_code(code.len() as u32, salt.len() as u32)
|
||||
T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
|
||||
.saturating_add(<Pallet<T>>::compat_weight(*gas_limit))
|
||||
)]
|
||||
#[allow(deprecated)]
|
||||
@@ -445,7 +432,7 @@ pub mod pallet {
|
||||
/// Deprecated version if [`Self::instantiate`] for use in an in-storage `Call`.
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate(salt.len() as u32).saturating_add(<Pallet<T>>::compat_weight(*gas_limit))
|
||||
T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(<Pallet<T>>::compat_weight(*gas_limit))
|
||||
)]
|
||||
#[allow(deprecated)]
|
||||
#[deprecated(note = "1D weight is used in this extrinsic, please migrate to `instantiate`")]
|
||||
@@ -633,7 +620,7 @@ pub mod pallet {
|
||||
/// - The `deploy` function is executed in the context of the newly-created account.
|
||||
#[pallet::call_index(7)]
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate_with_code(code.len() as u32, salt.len() as u32)
|
||||
T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
|
||||
.saturating_add(*gas_limit)
|
||||
)]
|
||||
pub fn instantiate_with_code(
|
||||
@@ -647,6 +634,7 @@ pub mod pallet {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let code_len = code.len() as u32;
|
||||
let data_len = data.len() as u32;
|
||||
let salt_len = salt.len() as u32;
|
||||
let mut output = Self::internal_instantiate(
|
||||
origin,
|
||||
@@ -665,7 +653,7 @@ pub mod pallet {
|
||||
}
|
||||
output.gas_meter.into_dispatch_result(
|
||||
output.result.map(|(_address, result)| result),
|
||||
T::WeightInfo::instantiate_with_code(code_len, salt_len),
|
||||
T::WeightInfo::instantiate_with_code(code_len, data_len, salt_len),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -676,7 +664,7 @@ pub mod pallet {
|
||||
/// must be supplied.
|
||||
#[pallet::call_index(8)]
|
||||
#[pallet::weight(
|
||||
T::WeightInfo::instantiate(salt.len() as u32).saturating_add(*gas_limit)
|
||||
T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(*gas_limit)
|
||||
)]
|
||||
pub fn instantiate(
|
||||
origin: OriginFor<T>,
|
||||
@@ -688,6 +676,7 @@ pub mod pallet {
|
||||
salt: Vec<u8>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let data_len = data.len() as u32;
|
||||
let salt_len = salt.len() as u32;
|
||||
let mut output = Self::internal_instantiate(
|
||||
origin,
|
||||
@@ -706,7 +695,7 @@ pub mod pallet {
|
||||
}
|
||||
output.gas_meter.into_dispatch_result(
|
||||
output.result.map(|(_address, output)| output),
|
||||
T::WeightInfo::instantiate(salt_len),
|
||||
T::WeightInfo::instantiate(data_len, salt_len),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -943,10 +932,7 @@ struct InternalOutput<T: Config, O> {
|
||||
result: Result<O, ExecError>,
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T>
|
||||
where
|
||||
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
|
||||
{
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Perform a call to a specified contract.
|
||||
///
|
||||
/// This function is similar to [`Self::call`], but doesn't perform any address lookups
|
||||
@@ -1081,9 +1067,10 @@ where
|
||||
pub fn contract_address(
|
||||
deploying_address: &T::AccountId,
|
||||
code_hash: &CodeHash<T>,
|
||||
input_data: &[u8],
|
||||
salt: &[u8],
|
||||
) -> T::AccountId {
|
||||
T::AddressGenerator::generate_address(deploying_address, code_hash, salt)
|
||||
T::AddressGenerator::generate_address(deploying_address, code_hash, input_data, salt)
|
||||
}
|
||||
|
||||
/// Returns the code hash of the contract specified by `account` ID.
|
||||
|
||||
Reference in New Issue
Block a user