mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 22:11:06 +00:00
srml-contracts: Deferred actions (#3255)
* Switch to deferred actions * Make restore_to a deferred action. * Bump version. * Review fixes.
This commit is contained in:
committed by
Gavin Wood
parent
780942192e
commit
de02aee156
@@ -185,6 +185,13 @@ mod tests {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct DispatchEntry(Call);
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct RestoreEntry {
|
||||
dest: u64,
|
||||
code_hash: H256,
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
}
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct CreateEntry {
|
||||
code_hash: H256,
|
||||
endowment: u64,
|
||||
@@ -205,6 +212,7 @@ mod tests {
|
||||
creates: Vec<CreateEntry>,
|
||||
transfers: Vec<TransferEntry>,
|
||||
dispatches: Vec<DispatchEntry>,
|
||||
restores: Vec<RestoreEntry>,
|
||||
// (topics, data)
|
||||
events: Vec<(Vec<H256>, Vec<u8>)>,
|
||||
next_account_id: u64,
|
||||
@@ -262,6 +270,20 @@ mod tests {
|
||||
fn note_dispatch_call(&mut self, call: Call) {
|
||||
self.dispatches.push(DispatchEntry(call));
|
||||
}
|
||||
fn note_restore_to(
|
||||
&mut self,
|
||||
dest: u64,
|
||||
code_hash: H256,
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
) {
|
||||
self.restores.push(RestoreEntry {
|
||||
dest,
|
||||
code_hash,
|
||||
rent_allowance,
|
||||
delta,
|
||||
});
|
||||
}
|
||||
fn caller(&self) -> &u64 {
|
||||
&42
|
||||
}
|
||||
@@ -332,6 +354,20 @@ mod tests {
|
||||
fn note_dispatch_call(&mut self, call: Call) {
|
||||
(**self).note_dispatch_call(call)
|
||||
}
|
||||
fn note_restore_to(
|
||||
&mut self,
|
||||
dest: u64,
|
||||
code_hash: H256,
|
||||
rent_allowance: u64,
|
||||
delta: Vec<StorageKey>,
|
||||
) {
|
||||
(**self).note_restore_to(
|
||||
dest,
|
||||
code_hash,
|
||||
rent_allowance,
|
||||
delta,
|
||||
)
|
||||
}
|
||||
fn caller(&self) -> &u64 {
|
||||
(**self).caller()
|
||||
}
|
||||
|
||||
@@ -586,6 +586,87 @@ define_env!(Env, <E: Ext>,
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Record a request to restore the caller contract to the specified contract.
|
||||
//
|
||||
// At the finalization stage, i.e. when all changes from the extrinsic that invoked this
|
||||
// contract are commited, this function will compute a tombstone hash from the caller's
|
||||
// storage and the given code hash and if the hash matches the hash found in the tombstone at
|
||||
// the specified address - kill the caller contract and restore the destination contract and set
|
||||
// the specified `rent_allowance`. All caller's funds are transfered to the destination.
|
||||
//
|
||||
// This function doesn't perform restoration right away but defers it to the end of the
|
||||
// transaction. If there is no tombstone in the destination address or if the hashes don't match
|
||||
// then restoration is cancelled and no changes are made.
|
||||
//
|
||||
// `dest_ptr`, `dest_len` - the pointer and the length of a buffer that encodes `T::AccountId`
|
||||
// with the address of the to be restored contract.
|
||||
// `code_hash_ptr`, `code_hash_len` - the pointer and the length of a buffer that encodes
|
||||
// a code hash of the to be restored contract.
|
||||
// `rent_allowance_ptr`, `rent_allowance_len` - the pointer and the length of a buffer that
|
||||
// encodes the rent allowance that must be set in the case of successful restoration.
|
||||
// `delta_ptr` is the pointer to the start of a buffer that has `delta_count` storage keys
|
||||
// laid out sequentially.
|
||||
ext_restore_to(
|
||||
ctx,
|
||||
dest_ptr: u32,
|
||||
dest_len: u32,
|
||||
code_hash_ptr: u32,
|
||||
code_hash_len: u32,
|
||||
rent_allowance_ptr: u32,
|
||||
rent_allowance_len: u32,
|
||||
delta_ptr: u32,
|
||||
delta_count: u32
|
||||
) => {
|
||||
let dest = {
|
||||
let dest_buf = read_sandbox_memory(ctx, dest_ptr, dest_len)?;
|
||||
<<E as Ext>::T as system::Trait>::AccountId::decode(&mut &dest_buf[..])
|
||||
.ok_or_else(|| sandbox::HostError)?
|
||||
};
|
||||
let code_hash = {
|
||||
let code_hash_buf = read_sandbox_memory(ctx, code_hash_ptr, code_hash_len)?;
|
||||
<CodeHash<<E as Ext>::T>>::decode(&mut &code_hash_buf[..])
|
||||
.ok_or_else(|| sandbox::HostError)?
|
||||
};
|
||||
let rent_allowance = {
|
||||
let rent_allowance_buf = read_sandbox_memory(
|
||||
ctx,
|
||||
rent_allowance_ptr,
|
||||
rent_allowance_len
|
||||
)?;
|
||||
BalanceOf::<<E as Ext>::T>::decode(&mut &rent_allowance_buf[..])
|
||||
.ok_or_else(|| sandbox::HostError)?
|
||||
};
|
||||
let delta = {
|
||||
// We don't use `with_capacity` here to not eagerly allocate the user specified amount
|
||||
// of memory.
|
||||
let mut delta = Vec::new();
|
||||
let mut key_ptr = delta_ptr;
|
||||
|
||||
for _ in 0..delta_count {
|
||||
const KEY_SIZE: usize = 32;
|
||||
|
||||
// Read the delta into the provided buffer and collect it into the buffer.
|
||||
let mut delta_key: StorageKey = [0; KEY_SIZE];
|
||||
read_sandbox_memory_into_buf(ctx, key_ptr, &mut delta_key)?;
|
||||
delta.push(delta_key);
|
||||
|
||||
// Offset key_ptr to the next element.
|
||||
key_ptr = key_ptr.checked_add(KEY_SIZE as u32).ok_or_else(|| sandbox::HostError)?;
|
||||
}
|
||||
|
||||
delta
|
||||
};
|
||||
|
||||
ctx.ext.note_restore_to(
|
||||
dest,
|
||||
code_hash,
|
||||
rent_allowance,
|
||||
delta,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// Returns the size of the scratch buffer.
|
||||
//
|
||||
// For more details on the scratch buffer see `ext_scratch_copy`.
|
||||
|
||||
Reference in New Issue
Block a user