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
+53 -11
View File
@@ -104,26 +104,41 @@ use rstd::prelude::*;
use rstd::marker::PhantomData;
use codec::{Codec, HasCompact};
use runtime_primitives::traits::{Hash, As, SimpleArithmetic,Bounded, StaticLookup};
use runtime_support::dispatch::Result;
use runtime_support::dispatch::{Result, Dispatchable};
use runtime_support::{Parameter, StorageMap, StorageValue, StorageDoubleMap};
use system::ensure_signed;
use system::{ensure_signed, RawOrigin};
use runtime_io::{blake2_256, twox_128};
pub type CodeHash<T> = <T as system::Trait>::Hash;
/// A function that generates an `AccountId` for a contract upon instantiation.
pub trait ContractAddressFor<CodeHash, AccountId: Sized> {
fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId;
}
/// A function that returns the fee for dispatching a `Call`.
pub trait ComputeDispatchFee<Call, Balance> {
fn compute_dispatch_fee(call: &Call) -> Balance;
}
pub trait Trait: balances::Trait {
/// Function type to get the contract address given the creator.
type DetermineContractAddress: ContractAddressFor<CodeHash<Self>, Self::AccountId>;
/// The outer call dispatch type.
type Call: Parameter + Dispatchable<Origin=<Self as system::Trait>::Origin>;
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
// As<u32> is needed for wasm-utils
type Gas: Parameter + Default + Codec + SimpleArithmetic + Bounded + Copy + As<Self::Balance> + As<u64> + As<u32>;
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
/// A function type to get the contract address given the creator.
type DetermineContractAddress: ContractAddressFor<CodeHash<Self>, Self::AccountId>;
pub trait ContractAddressFor<CodeHash, AccountId: Sized> {
fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId;
/// A function type that computes the fee for dispatching the given `Call`.
///
/// It is recommended (though not required) for this function to return a fee that would be taken
/// by executive module for regular dispatch.
type ComputeDispatchFee: ComputeDispatchFee<Self::Call, <Self as balances::Trait>::Balance>;
}
/// Simple contract address determintator.
@@ -133,7 +148,6 @@ pub trait ContractAddressFor<CodeHash, AccountId: Sized> {
///
/// Formula: `blake2_256(blake2_256(code) + blake2_256(data) + origin)`
pub struct SimpleAddressDeterminator<T: Trait>(PhantomData<T>);
impl<T: Trait> ContractAddressFor<CodeHash<T>, T::AccountId> for SimpleAddressDeterminator<T>
where
T::AccountId: From<T::Hash> + AsRef<[u8]>
@@ -150,9 +164,21 @@ where
}
}
/// The default dispatch fee computor computes the fee in the same way that
/// implementation of `MakePayment` for balances module does.
pub struct DefaultDispatchFeeComputor<T: Trait>(PhantomData<T>);
impl<T: Trait> ComputeDispatchFee<T::Call, T::Balance> for DefaultDispatchFeeComputor<T> {
fn compute_dispatch_fee(call: &T::Call) -> T::Balance {
let encoded_len = codec::Encode::encode(&call).len();
let base_fee = <balances::Module<T>>::transaction_base_fee();
let byte_fee = <balances::Module<T>>::transaction_byte_fee();
base_fee + byte_fee * <T::Balance as As<u64>>::sa(encoded_len as u64)
}
}
decl_module! {
/// Contracts module.
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
fn deposit_event<T>() = default;
/// Updates the schedule for metering contracts.
@@ -231,6 +257,12 @@ decl_module! {
// can alter the balance of the caller.
gas::refund_unused_gas::<T>(&origin, gas_meter);
// Dispatch every recorded call with an appropriate origin.
ctx.calls.into_iter().for_each(|(who, call)| {
let result = call.dispatch(RawOrigin::Signed(who.clone()).into());
Self::deposit_event(RawEvent::Dispatched(who, result.is_ok()));
});
result.map(|_| ())
}
@@ -280,6 +312,12 @@ decl_module! {
// can alter the balance of the caller.
gas::refund_unused_gas::<T>(&origin, gas_meter);
// Dispatch every recorded call with an appropriate origin.
ctx.calls.into_iter().for_each(|(who, call)| {
let result = call.dispatch(RawOrigin::Signed(who.clone()).into());
Self::deposit_event(RawEvent::Dispatched(who, result.is_ok()));
});
result.map(|_| ())
}
@@ -307,6 +345,10 @@ decl_event! {
/// Triggered when the current schedule is updated.
ScheduleUpdated(u32),
/// A call was dispatched from the given account. The bool signals whether it was
/// successful execution or not.
Dispatched(AccountId, bool),
}
}