Contracts Add deposit for dependencies (#14079)

* wip

* fixes

* rm comment

* join fns

* clippy

* Fix limits

* reduce diff

* fix

* fix

* fix typo

* refactor store to  use self

* refactor run to take self by value

* pass tests

* rm comment

* fixes

* fix typo

* rm

* fix fmt

* clippy

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* Update frame/contracts/src/lib.rs

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

* Update frame/contracts/src/wasm/mod.rs

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

* Update frame/contracts/src/wasm/mod.rs

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

* PR review, rm duplicate increment_refcount

* PR review

* Update frame/contracts/src/wasm/prepare.rs

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

* Add test for failing storage_deposit

* fix lint

* wip

* Delegate update take 2

* update

* fix migration

* fix migration

* doc

* fix lint

* update migration

* fix warning

* reformat comment

* regenerate weightInfo trait

* fix merge

* PR review

https://github.com/paritytech/substrate/pull/14079#discussion_r1255904563

* PR review

https://github.com/paritytech/substrate/pull/14079/files#r1257521373

* PR review remove optimisation

https://github.com/paritytech/substrate/pull/14079/files#r1263312237

* PR review fix return type

https://github.com/paritytech/substrate/pull/14079/files#r1263315804

* Apply suggestions from code review

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* PR review pass CodeInfo and update docstring

https://github.com/paritytech/substrate/pull/14079/files#r1257522327

* PR review add code_info to the executable

https://github.com/paritytech/substrate/pull/14079/files#r1263309049

* rename info -> contract_info

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/fixtures/add_remove_delegate_dependency.wat

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/src/migration/v13.rs

* fix tests

* Fmt & fix tests

* Test Result<(), _> return type

* Update frame/contracts/src/migration.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Revert "Test Result<(), _> return type"

This reverts commit a876168f2054edf84d720c666387583ccbe78dcd.

* add / update doc comments

* fix backticks

* Revert "Revert "Test Result<(), _> return type""

This reverts commit 3cbb6161d1abd9520cd9f8519b4dfbf4f29a2998.

* fix bench

* fix bench

* fix

* Update frame/contracts/src/storage/meter.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* rm stale comments

* Apply suggestions from code review

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

* PR suggestion

* Add missing doc

* fx lint

* ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_contracts

* Update frame/contracts/src/lib.rs

Co-authored-by: Juan <juangirini@gmail.com>

---------

Co-authored-by: command-bot <>
Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: Juan <juangirini@gmail.com>
This commit is contained in:
PG Herveou
2023-07-26 14:09:02 +02:00
committed by GitHub
parent 47bb475d6d
commit 5a5b1df69b
14 changed files with 3956 additions and 2798 deletions
+82 -5
View File
@@ -22,7 +22,7 @@ pub mod meter;
use crate::{
exec::{AccountIdOf, Key},
weights::WeightInfo,
AddressGenerator, BalanceOf, CodeHash, Config, ContractInfoOf, DeletionQueue,
AddressGenerator, BalanceOf, CodeHash, CodeInfo, Config, ContractInfoOf, DeletionQueue,
DeletionQueueCounter, Error, Pallet, TrieId, SENTINEL,
};
use codec::{Decode, Encode, MaxEncodedLen};
@@ -30,19 +30,22 @@ use frame_support::{
dispatch::DispatchError,
storage::child::{self, ChildInfo},
weights::Weight,
DefaultNoBound, RuntimeDebugNoBound,
CloneNoBound, DefaultNoBound, RuntimeDebugNoBound,
};
use scale_info::TypeInfo;
use sp_core::Get;
use sp_io::KillStorageResult;
use sp_runtime::{
traits::{Hash, Saturating, Zero},
RuntimeDebug,
BoundedBTreeMap, DispatchResult, RuntimeDebug,
};
use sp_std::{marker::PhantomData, ops::Deref, prelude::*};
use self::meter::Diff;
/// Information for managing an account and its sub trie abstraction.
/// This is the required info to cache for an account.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct ContractInfo<T: Config> {
/// Unique ID for the subtree encoded as a bytes vector.
@@ -66,6 +69,12 @@ pub struct ContractInfo<T: Config> {
/// We need to store this information separately so it is not used when calculating any refunds
/// since the base deposit can only ever be refunded on contract termination.
storage_base_deposit: BalanceOf<T>,
/// Map of code hashes and deposit balances.
///
/// Tracks the code hash and deposit held for adding delegate dependencies. Dependencies added
/// to the map can not be removed from the chain state and can be safely used for delegate
/// calls.
delegate_dependencies: BoundedBTreeMap<CodeHash<T>, BalanceOf<T>, T::MaxDelegateDependencies>,
}
impl<T: Config> ContractInfo<T> {
@@ -101,6 +110,7 @@ impl<T: Config> ContractInfo<T> {
storage_byte_deposit: Zero::zero(),
storage_item_deposit: Zero::zero(),
storage_base_deposit: Zero::zero(),
delegate_dependencies: Default::default(),
};
Ok(contract)
@@ -123,11 +133,16 @@ impl<T: Config> ContractInfo<T> {
.saturating_sub(Pallet::<T>::min_balance())
}
/// Return the account that storage deposits should be deposited into.
/// Returns the account that storage deposits should be deposited into.
pub fn deposit_account(&self) -> &DepositAccount<T> {
&self.deposit_account
}
/// Returns the storage base deposit of the contract.
pub fn storage_base_deposit(&self) -> BalanceOf<T> {
self.storage_base_deposit
}
/// Reads a storage kv pair of a contract.
///
/// The read is performed from the `trie_id` only. The `address` is not necessary. If the
@@ -201,6 +216,68 @@ impl<T: Config> ContractInfo<T> {
})
}
/// Sets and returns the contract base deposit.
///
/// The base deposit is updated when the `code_hash` of the contract changes, as it depends on
/// the deposit paid to upload the contract's code.
pub fn update_base_deposit(&mut self, code_info: &CodeInfo<T>) -> BalanceOf<T> {
let ed = Pallet::<T>::min_balance();
let info_deposit =
Diff { bytes_added: self.encoded_size() as u32, items_added: 1, ..Default::default() }
.update_contract::<T>(None)
.charge_or_zero();
// Instantiating the contract prevents its code to be deleted, therefore the base deposit
// includes a fraction (`T::CodeHashLockupDepositPercent`) of the original storage deposit
// to prevent abuse.
let upload_deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit());
// Instantiate needs to transfer at least the minimum balance in order to pull the
// deposit account into existence.
// We also add another `ed` here which goes to the contract's own account into existence.
let deposit = info_deposit.saturating_add(upload_deposit).max(ed).saturating_add(ed);
self.storage_base_deposit = deposit;
deposit
}
/// Adds a new delegate dependency to the contract.
/// The `amount` is the amount of funds that will be reserved for the dependency.
///
/// Returns an error if the maximum number of delegate_dependencies is reached or if
/// the delegate dependency already exists.
pub fn add_delegate_dependency(
&mut self,
code_hash: CodeHash<T>,
amount: BalanceOf<T>,
) -> DispatchResult {
self.delegate_dependencies
.try_insert(code_hash, amount)
.map_err(|_| Error::<T>::MaxDelegateDependenciesReached)?
.map_or(Ok(()), |_| Err(Error::<T>::DelegateDependencyAlreadyExists))
.map_err(Into::into)
}
/// Removes the delegate dependency from the contract and returns the deposit held for this
/// dependency.
///
/// Returns an error if the entry doesn't exist.
pub fn remove_delegate_dependency(
&mut self,
code_hash: &CodeHash<T>,
) -> Result<BalanceOf<T>, DispatchError> {
self.delegate_dependencies
.remove(code_hash)
.ok_or(Error::<T>::DelegateDependencyNotFound.into())
}
/// Returns the delegate_dependencies of the contract.
pub fn delegate_dependencies(
&self,
) -> &BoundedBTreeMap<CodeHash<T>, BalanceOf<T>, T::MaxDelegateDependencies> {
&self.delegate_dependencies
}
/// Push a contract's trie to the deletion queue for lazy removal.
///
/// You must make sure that the contract is also removed when queuing the trie for deletion.