mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Upgradable contracts using set_code function (#10690)
* poc logic * set_code_hash impl, tests, benchmark * Address @xgreenx's comments * Move func defs closer to set_storage * Check if code exists - increment/decrement codehash refcount * Document error for non-existing code hash * Revert unrelated change * Changes due to @athei's review * Fix error handling - comment errors: ReturnCodes - update mock ext implementation - return Error::CodeNotFound when no code for such hash * Emit ContractCodeUpdated when setting new code_hash * Address @athei's comments * Move related defs to the bottom * Minor comment update Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Improve docs * Improve docs * Update frame/contracts/src/wasm/runtime.rs Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Refactor set_code_hash test * Minor change to benchmark Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Minor change to benchmark Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Minor comment refactor Co-authored-by: Alexander Theißen <alex.theissen@me.com> * Address @HCastano's comments * Update seal_set_code_hash comment Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> * Move set_code_hash after delegate_call * Move function to the bottom * Moved and changed banchmark, added verify block * Bring back previous benchmark * Remove skip_meta for seal_set_code_hash * Bring back skip_meta for seal_set_storage_per_new_kb * Apply weights Co-authored-by: Alexander Theißen <alex.theissen@me.com> Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
83eed8018b
commit
e70ffbf44d
@@ -222,6 +222,9 @@ pub enum RuntimeCosts {
|
||||
/// Weight charged for calling into the runtime.
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
CallRuntime(Weight),
|
||||
/// Weight of calling `seal_set_code_hash`
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
SetCodeHash,
|
||||
}
|
||||
|
||||
impl RuntimeCosts {
|
||||
@@ -305,6 +308,8 @@ impl RuntimeCosts {
|
||||
CopyIn(len) => s.return_per_byte.saturating_mul(len.into()),
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
CallRuntime(weight) => weight,
|
||||
#[cfg(feature = "unstable-interface")]
|
||||
SetCodeHash => s.set_code_hash,
|
||||
};
|
||||
RuntimeToken {
|
||||
#[cfg(test)]
|
||||
@@ -1960,4 +1965,41 @@ define_env!(Env, <E: Ext>,
|
||||
Err(_) => Ok(ReturnCode::EcdsaRecoverFailed),
|
||||
}
|
||||
},
|
||||
|
||||
// Replace the contract code at the specified address with new code.
|
||||
//
|
||||
// # Note
|
||||
//
|
||||
// There are a couple of important considerations which must be taken into account when
|
||||
// using this API:
|
||||
//
|
||||
// 1. The storage at the code address will remain untouched. This means that contract developers
|
||||
// must ensure that the storage layout of the new code is compatible with that of the old code.
|
||||
//
|
||||
// 2. Contracts using this API can't be assumed as having deterministic addresses. Said another way,
|
||||
// when using this API you lose the guarantee that an address always identifies a specific code hash.
|
||||
//
|
||||
// 3. If a contract calls into itself after changing its code the new call would use
|
||||
// the new code. However, if the original caller panics after returning from the sub call it
|
||||
// would revert the changes made by `seal_set_code_hash` and the next caller would use
|
||||
// the old code.
|
||||
//
|
||||
// # Parameters
|
||||
//
|
||||
// - code_hash_ptr: A pointer to the buffer that contains the new code hash.
|
||||
//
|
||||
// # Errors
|
||||
//
|
||||
// `ReturnCode::CodeNotFound`
|
||||
[__unstable__] seal_set_code_hash(ctx, code_hash_ptr: u32) -> ReturnCode => {
|
||||
ctx.charge_gas(RuntimeCosts::SetCodeHash)?;
|
||||
let code_hash: CodeHash<<E as Ext>::T> = ctx.read_sandbox_memory_as(code_hash_ptr)?;
|
||||
match ctx.ext.set_code_hash(code_hash) {
|
||||
Err(err) => {
|
||||
let code = Runtime::<E>::err_into_return_code(err)?;
|
||||
Ok(code)
|
||||
},
|
||||
Ok(()) => Ok(ReturnCode::Success)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user