Dispatch Calls to other modules (#1473)

* WIP

* Use system::Origin::Signed as an origin

* Add a vm test for ext_dispatch_call

* Take fee for dispatching a Call

# Conflicts:
#	node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm

* Clean & Rebuild

# Conflicts:
#	node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm

* Dispatch call test.

* Rebuild the runtime.

* Fix the length of the buffer.

* Rebuild binaries.
This commit is contained in:
Sergei Pepyakin
2019-01-22 13:10:14 +01:00
committed by Gav Wood
parent 22b65c9cb0
commit 58cd6530be
11 changed files with 298 additions and 35 deletions
+31 -4
View File
@@ -21,11 +21,11 @@ use exec::{Ext, BalanceOf, VmExecResult, OutputBuf, EmptyOutputBuf, CallReceipt,
use rstd::prelude::*;
use rstd::mem;
use codec::{Decode, Encode};
use gas::{GasMeter, Token, GasMeterResult};
use gas::{GasMeter, Token, GasMeterResult, approx_gas_for_balance};
use runtime_primitives::traits::{As, CheckedMul, Bounded};
use sandbox;
use system;
use {Trait, CodeHash};
use {Trait, CodeHash, ComputeDispatchFee};
/// Enumerates all possible *special* trap conditions.
///
@@ -96,7 +96,7 @@ pub(crate) fn to_execution_result<E: Ext>(
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Copy, Clone)]
pub enum RuntimeToken {
pub enum RuntimeToken<Gas> {
/// Explicit call to the `gas` function. Charge the gas meter
/// with the value provided.
Explicit(u32),
@@ -107,9 +107,11 @@ 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),
/// Dispatch fee calculated by `T::ComputeDispatchFee`.
ComputedDispatchFee(Gas),
}
impl<T: Trait> Token<T> for RuntimeToken {
impl<T: Trait> Token<T> for RuntimeToken<T::Gas> {
type Metadata = Schedule<T::Gas>;
fn calculate_amount(&self, metadata: &Schedule<T::Gas>) -> T::Gas {
@@ -125,6 +127,7 @@ impl<T: Trait> Token<T> for RuntimeToken {
ReturnData(byte_count) => metadata
.return_data_per_byte_cost
.checked_mul(&<T::Gas as As<u32>>::sa(byte_count)),
ComputedDispatchFee(gas) => Some(gas),
};
value.unwrap_or_else(|| Bounded::max_value())
@@ -482,6 +485,30 @@ 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 = {
let call_buf = read_sandbox_memory(ctx, call_ptr, call_len)?;
<<<E as Ext>::T as Trait>::Call>::decode(&mut &call_buf[..])
.ok_or_else(|| sandbox::HostError)?
};
// Charge gas for dispatching this call.
let fee = {
let balance_fee = <<E as Ext>::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call);
approx_gas_for_balance::<<E as Ext>::T>(ctx.gas_meter.gas_price(), balance_fee)
};
charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::ComputedDispatchFee(fee))?;
ctx.ext.note_dispatch_call(call);
Ok(())
},
// Returns the size of the input buffer.
ext_input_size(ctx) -> u32 => {
Ok(ctx.input_data.len() as u32)