seal: Remove ext_dispatch_call and ext_get_runtime_storage (#6464)

Those are way too hard to audit and make only sense with specific
chains. They shouldn't be in the core API.
This commit is contained in:
Alexander Theißen
2020-06-24 13:53:40 +02:00
committed by GitHub
parent a3a42f599a
commit b14b472edf
11 changed files with 28 additions and 649 deletions
-144
View File
@@ -206,7 +206,6 @@ mod tests {
instantiates: Vec<InstantiateEntry>,
terminations: Vec<TerminationEntry>,
transfers: Vec<TransferEntry>,
dispatches: Vec<DispatchEntry>,
restores: Vec<RestoreEntry>,
// (topics, data)
events: Vec<(Vec<H256>, Vec<u8>)>,
@@ -299,9 +298,6 @@ mod tests {
});
Ok(())
}
fn note_dispatch_call(&mut self, call: Call) {
self.dispatches.push(DispatchEntry(call));
}
fn restore_to(
&mut self,
dest: u64,
@@ -421,9 +417,6 @@ mod tests {
) -> ExecResult {
(**self).call(to, value, gas_meter, input_data)
}
fn note_dispatch_call(&mut self, call: Call) {
(**self).note_dispatch_call(call)
}
fn restore_to(
&mut self,
dest: u64,
@@ -1238,44 +1231,6 @@ mod tests {
).unwrap();
}
const CODE_DISPATCH_CALL: &str = r#"
(module
(import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "call")
(call $ext_dispatch_call
(i32.const 8) ;; Pointer to the start of encoded call buffer
(i32.const 13) ;; Length of the buffer
)
)
(func (export "deploy"))
(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
)
"#;
#[test]
fn dispatch_call() {
// This test can fail due to the encoding changes. In case it becomes too annoying
// let's rewrite so as we use this module controlled call or we serialize it in runtime.
let mut mock_ext = MockExt::default();
let _ = execute(
CODE_DISPATCH_CALL,
vec![],
&mut mock_ext,
&mut GasMeter::new(GAS_LIMIT),
).unwrap();
assert_eq!(
&mock_ext.dispatches,
&[DispatchEntry(
Call::Balances(pallet_balances::Call::set_balance(42, 1337, 0)),
)]
);
}
const CODE_RETURN_FROM_START_FN: &str = r#"
(module
(import "env" "ext_return" (func $ext_return (param i32 i32)))
@@ -1883,103 +1838,4 @@ mod tests {
assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() });
assert!(!output.is_success());
}
const CODE_GET_RUNTIME_STORAGE: &str = r#"
(module
(import "env" "ext_get_runtime_storage"
(func $ext_get_runtime_storage (param i32 i32) (result i32))
)
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
(import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "deploy"))
(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)
(func $call (export "call")
;; Load runtime storage for the first key and assert that it exists.
(call $assert
(i32.eq
(call $ext_get_runtime_storage
(i32.const 16)
(i32.const 4)
)
(i32.const 0)
)
)
;; assert $ext_scratch_size == 4
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.const 4)
)
)
;; copy contents of the scratch buffer into the contract's memory.
(call $ext_scratch_read
(i32.const 4) ;; Pointer in memory to the place where to copy.
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 4) ;; Count of bytes to copy.
)
;; assert that contents of the buffer is equal to the i32 value of 0x14144020.
(call $assert
(i32.eq
(i32.load
(i32.const 4)
)
(i32.const 0x14144020)
)
)
;; Load the second key and assert that it doesn't exist.
(call $assert
(i32.eq
(call $ext_get_runtime_storage
(i32.const 20)
(i32.const 4)
)
(i32.const 1)
)
)
)
;; The first key, 4 bytes long.
(data (i32.const 16) "\01\02\03\04")
;; The second key, 4 bytes long.
(data (i32.const 20) "\02\03\04\05")
)
"#;
#[test]
fn get_runtime_storage() {
let mut gas_meter = GasMeter::new(GAS_LIMIT);
let mock_ext = MockExt::default();
// "\01\02\03\04" - Some(0x14144020)
// "\02\03\04\05" - None
*mock_ext.runtime_storage_keys.borrow_mut() = [
([1, 2, 3, 4].to_vec(), Some(0x14144020u32.to_le_bytes().to_vec())),
([2, 3, 4, 5].to_vec().to_vec(), None),
]
.iter()
.cloned()
.collect();
let _ = execute(
CODE_GET_RUNTIME_STORAGE,
vec![],
mock_ext,
&mut gas_meter,
).unwrap();
}
}
@@ -32,7 +32,6 @@ use sp_io::hashing::{
blake2_128,
sha2_256,
};
use frame_support::weights::GetDispatchInfo;
/// The value returned from ext_call and ext_instantiate contract external functions if the call or
/// instantiation traps. This value is chosen as if the execution does not trap, the return value
@@ -162,8 +161,6 @@ pub enum RuntimeToken {
/// The given number of bytes is read from the sandbox memory and
/// is returned as the return data buffer of the call.
ReturnData(u32),
/// Dispatched a call with the given weight.
DispatchWithWeight(Gas),
/// (topic_count, data_bytes): A buffer of the given size is posted as an event indexed with the
/// given number of topics.
DepositEvent(u32, u32),
@@ -204,7 +201,6 @@ impl<T: Trait> Token<T> for RuntimeToken {
data_and_topics_cost.checked_add(metadata.event_base_cost)
)
},
DispatchWithWeight(gas) => gas.checked_add(metadata.dispatch_base_cost),
};
value.unwrap_or_else(|| Bounded::max_value())
@@ -785,30 +781,6 @@ define_env!(Env, <E: Ext>,
Ok(())
},
// Decodes the given buffer as a `T::Call` and adds it to the list
// of to-be-dispatched calls.
//
// All calls made it to the top-level context will be dispatched before
// finishing the execution of the calling extrinsic.
ext_dispatch_call(ctx, call_ptr: u32, call_len: u32) => {
let call: <<E as Ext>::T as Trait>::Call =
read_sandbox_memory_as(ctx, call_ptr, call_len)?;
// We already deducted the len costs when reading from the sandbox.
// Bill on the actual weight of the dispatched call.
let info = call.get_dispatch_info();
charge_gas(
&mut ctx.gas_meter,
ctx.schedule,
&mut ctx.special_trap,
RuntimeToken::DispatchWithWeight(info.weight)
)?;
ctx.ext.note_dispatch_call(call);
Ok(())
},
// Try to restore the given destination contract sacrificing the caller.
//
// This function will compute a tombstone hash from the caller's storage and the given code hash
@@ -1005,32 +977,6 @@ define_env!(Env, <E: Ext>,
Ok(())
},
// Retrieve the value under the given key from the **runtime** storage and return 0.
// If there is no entry under the given key then this function will return 1 and
// clear the scratch buffer.
//
// - key_ptr: the pointer into the linear memory where the requested value is placed.
// - key_len: the length of the key in bytes.
ext_get_runtime_storage(ctx, key_ptr: u32, key_len: u32) -> u32 => {
// Steal the scratch buffer so that we hopefully save an allocation for the `key_buf`.
read_sandbox_memory_into_scratch(ctx, key_ptr, key_len)?;
let key_buf = mem::replace(&mut ctx.scratch_buf, Vec::new());
match ctx.ext.get_runtime_storage(&key_buf) {
Some(value_buf) => {
// The given value exists.
ctx.scratch_buf = value_buf;
Ok(0)
}
None => {
// Put back the `key_buf` and allow its allocation to be reused.
ctx.scratch_buf = key_buf;
ctx.scratch_buf.clear();
Ok(1)
}
}
},
// Computes the SHA2 256-bit hash on the given input buffer.
//
// Returns the result directly into the given output buffer.