Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ext_dispatch_call #124

Merged
merged 72 commits into from Jul 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
cd77d1f
[core] Add AccountId to EnvTypes
ascjones Jun 18, 2019
3b755b1
[core] Add calls mod, plus WIP tests
ascjones Jun 18, 2019
5047ae6
[core] Balance transfer call roundtrip works
ascjones Jun 18, 2019
a1a154f
[core] Add ext_dispatch_call
ascjones Jun 18, 2019
0653897
[core] Implement ext_dispatch_call
ascjones Jun 18, 2019
675e4a7
[examples] Add example lang contract for ext_dispatch_call
ascjones Jun 18, 2019
5dfe4b4
[examples] WIP: implement example lang contract for ext_dispatch_call
ascjones Jun 18, 2019
6dba3b7
Merge branch 'master' into aj-dispatch-call
ascjones Jul 11, 2019
a44e1fc
[examples] complete basic implementation of dispatching Balances Call
ascjones Jun 19, 2019
1f16526
srml-contracts -> srml-contract
ascjones Jul 11, 2019
105ea46
[core] remove unsafe from dispatch_call api fn
ascjones Jul 12, 2019
02fe1d1
[core] Add docs to dispatch_call
ascjones Jul 12, 2019
385cc05
[core] Add missing trait bound to account index
ascjones Jul 12, 2019
f47fd92
[core] Some todos
ascjones Jul 12, 2019
48f17c8
[core] Rename dispatch_call to dispatch_raw_call on Env trait
ascjones Jul 12, 2019
e9e220b
[lang] Add AccountIndex type alias
ascjones Jul 12, 2019
0c8a7f6
[model] add strongly type dispatch call to EnvHandler
ascjones Jul 12, 2019
671a4c3
[*] specify latest parity-codec version, same as substrate
ascjones Jul 12, 2019
3d9f828
[core] fix call roundtrip tests
ascjones Jul 12, 2019
f2243d0
[lang] fix tests
ascjones Jul 12, 2019
b0ec13a
Merge branch 'master' into aj-dispatch-call
ascjones Jul 15, 2019
d2ed6b9
[core] fix wasm build
ascjones Jul 16, 2019
b8d30c9
[core] fix std build
ascjones Jul 16, 2019
bab809b
[core] move call type serialization tests
ascjones Jul 18, 2019
87996ad
[core] test Call serialization roundtrip
ascjones Jul 18, 2019
96d043f
[core] use node_runtime for Call serialization roundtrip
ascjones Jul 18, 2019
34fe330
[core] remove unused dependencies
ascjones Jul 18, 2019
a3d56c8
[core] remove unused substrate dependencies
ascjones Jul 18, 2019
958ca37
[core] change default Balance to u128, matching substrate
ascjones Jul 18, 2019
f282799
[core] introduce Address type for balance calls
ascjones Jul 22, 2019
72920f8
[core] fix Balances transfer serialization test
ascjones Jul 23, 2019
8fb6b74
[core] add Address serialization tests
ascjones Jul 23, 2019
13fe3e8
Merge branch 'master' into aj-dispatch-call
ascjones Jul 23, 2019
e5958aa
[ci] install wasm-gc for building substrate dev deps
ascjones Jul 23, 2019
c7d3f1e
[ci] move wasm-gc installation after wasm target added
ascjones Jul 23, 2019
69f615d
[examples] get the calls example compiling
ascjones Jul 23, 2019
1f58d06
[CI] add temporary check for debugging ci build
ascjones Jul 23, 2019
72f2cdb
[CI] restore wasm-gc to install section and remove temp version check
ascjones Jul 23, 2019
585bb12
[CI] temporarily depend on substrate branch to test build fix
ascjones Jul 23, 2019
d2a7e26
Merge branch 'master' into aj-dispatch-call
ascjones Jul 25, 2019
79abc7e
[CI] remove temp substrate branch, build issue fixed
ascjones Jul 25, 2019
7163068
[core] use std feature instead of test-env for EnvTypes
ascjones Jul 26, 2019
831cbc1
[core] remove Call types, moved to ink-types-node-runtime
ascjones Jul 26, 2019
8c6b852
[core] remove AccountIndex from EnvTypes
ascjones Jul 26, 2019
73323d7
[core] remove AccountIndex from lang codegen
ascjones Jul 29, 2019
7bb8d77
Merge branch 'master' into aj-dispatch-call
ascjones Jul 29, 2019
cdc1747
[core] fix unused for std
ascjones Jul 29, 2019
d58bad7
[CI] remove wasm-gc from travis build
ascjones Jul 29, 2019
de073bf
[CI] remove AccountIndex type alias from codegen
ascjones Jul 29, 2019
f21fadb
Merge branch 'master' into aj-dispatch-call
ascjones Jul 29, 2019
cabcfd0
parity-codec version 4.1.1 -> 4.1
ascjones Jul 29, 2019
c0c0cde
[core] ext_dispatch_call docs
ascjones Jul 29, 2019
415c42e
[core] describe in comment what will happen if decoding fails
ascjones Jul 29, 2019
a77a901
[model] implement suggestion of Into<Call>
ascjones Jul 29, 2019
49c4e19
Merge branch 'master' into aj-dispatch-call
ascjones Jul 29, 2019
82b0938
rustfmt
ascjones Jul 29, 2019
dd36c64
rustfmt again
ascjones Jul 29, 2019
76f052d
rustfmt again again
ascjones Jul 29, 2019
bcb11b1
[examples] deleted calls example - moved to ink_types_node_runtime
ascjones Jul 29, 2019
50c1f59
[core] use into in api::dispatch_call
ascjones Jul 29, 2019
821b257
[core] make Call empty enum and use test-env feature for EnvTypes
ascjones Jul 29, 2019
e0fed13
[core] remove unused Call enum
ascjones Jul 29, 2019
e9ab0e7
[core] add comments explaining rationale for test-env
ascjones Jul 29, 2019
4272988
[core] missing period
ascjones Jul 29, 2019
b5eb6ce
[core] add comments
ascjones Jul 29, 2019
e452d31
[core] add space in comment
ascjones Jul 30, 2019
c82ddf4
[core] add comment to Call decode impl
ascjones Jul 30, 2019
e21e3bd
Merge branch 'master' into aj-dispatch-call
ascjones Jul 30, 2019
f42f7a6
[core] make dispatched_calls a DoubleEndedIterator
ascjones Jul 30, 2019
219c851
[core] add missing doc comment
ascjones Jul 30, 2019
89d0e88
[core] add comment explaining Decode requirement
ascjones Jul 30, 2019
5d742f9
[core] doc comment and DoubleEndedIterator
ascjones Jul 30, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 19 additions & 2 deletions core/src/env/api.rs
Expand Up @@ -17,12 +17,16 @@
use super::ContractEnvStorage;
use crate::{
env::{
traits::Env,
traits::{
Env,
EnvTypes,
},
EnvStorage as _,
},
memory::vec::Vec,
storage::Key,
};
use parity_codec::Encode;

/// Stores the given value under the specified key in the contract storage.
///
Expand Down Expand Up @@ -64,8 +68,21 @@ pub unsafe fn load(key: Key) -> Option<Vec<u8>> {
/// own to always encode the expected type.
pub unsafe fn r#return<T, E>(value: T) -> !
where
T: parity_codec::Encode,
T: Encode,
E: Env,
{
E::r#return(&value.encode()[..])
}

/// Dispatches a Call into the runtime, for invoking other substrate
/// modules. Dispatched only after successful contract execution.
///
/// The encoded Call MUST be decodable by the target substrate runtime.
Robbepop marked this conversation as resolved.
Show resolved Hide resolved
/// If decoding fails, then the smart contract execution will fail.
pub fn dispatch_call<T, C>(call: C)
where
T: Env,
C: Into<<T as EnvTypes>::Call>,
{
T::dispatch_raw_call(&call.into().encode()[..])
}
5 changes: 5 additions & 0 deletions core/src/env/srml/srml_only/impls.rs
Expand Up @@ -86,6 +86,7 @@ where
type Hash = <T as EnvTypes>::Hash;
type Moment = <T as EnvTypes>::Moment;
type BlockNumber = <T as EnvTypes>::BlockNumber;
type Call = <T as EnvTypes>::Call;
}

macro_rules! impl_getters_for_srml_env {
Expand Down Expand Up @@ -151,4 +152,8 @@ where
)
}
}

fn dispatch_raw_call(data: &[u8]) {
unsafe { sys::ext_dispatch_call(data.as_ptr() as u32, data.len() as u32) }
}
}
6 changes: 6 additions & 0 deletions core/src/env/srml/srml_only/sys.rs
Expand Up @@ -72,6 +72,12 @@ extern "C" {
value_len: u32,
);

/// Dispatches a Call into the runtime, for invocation of substrate modules
///
/// Call data is written to the scratch buffer, and it MUST be decodable into the host chain
/// runtime `Call` type.
pub fn ext_dispatch_call(call_ptr: u32, call_len: u32);

/// Tells the execution environment to load the contents
/// stored at the given key into the scratch buffer.
pub fn ext_get_storage(key_ptr: u32) -> u32;
Expand Down
26 changes: 25 additions & 1 deletion core/src/env/srml/types.rs
Expand Up @@ -31,14 +31,38 @@ use parity_codec::{

/// The SRML fundamental types.
#[allow(unused)]
#[cfg_attr(feature = "test-env", derive(Debug, Clone, PartialEq, Eq))]
ascjones marked this conversation as resolved.
Show resolved Hide resolved
pub enum DefaultSrmlTypes {}

/// Empty enum for default Call type, so it cannot be constructed.
/// For calling into the runtime, a user defined Call type required.
/// See https://github.com/paritytech/ink-types-node-runtime.
///
/// # Note
ascjones marked this conversation as resolved.
Show resolved Hide resolved
///
/// Some traits are only implemented to satisfy the constraints of the test
/// environment, in order to keep the code size small.
#[cfg_attr(feature = "test-env", derive(Debug, Clone, PartialEq, Eq))]
pub enum Call {}
impl parity_codec::Encode for Call {}

/// This implementation is only to satisfy the Decode constraint in the
/// test environment. Since Call cannot be constructed then just return
/// None, but this should never be called.
#[cfg(feature = "test-env")]
impl parity_codec::Decode for Call {
fn decode<I: parity_codec::Input>(_value: &mut I) -> Option<Self> {
None
}
}

impl EnvTypes for DefaultSrmlTypes {
type AccountId = AccountId;
type Balance = Balance;
type Hash = Hash;
type Moment = Moment;
type BlockNumber = BlockNumber;
type Call = Call;
}

/// The default SRML address type.
Expand All @@ -61,7 +85,7 @@ impl<'a> TryFrom<&'a [u8]> for AccountId {
}

/// The default SRML balance type.
pub type Balance = u64;
pub type Balance = u128;
Robbepop marked this conversation as resolved.
Show resolved Hide resolved

/// The default SRML hash type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
Expand Down
35 changes: 35 additions & 0 deletions core/src/env/test_env.rs
Expand Up @@ -171,6 +171,8 @@ pub struct TestEnvData {
total_writes: u64,
/// Deposited events of the contract invocation.
events: Vec<EventData>,
/// Calls dispatched to the runtime
dispatched_calls: Vec<Vec<u8>>,
/// The current gas price.
gas_price: Vec<u8>,
/// The remaining gas.
Expand All @@ -197,6 +199,7 @@ impl Default for TestEnvData {
gas_price: Vec::new(),
gas_left: Vec::new(),
value_transferred: Vec::new(),
dispatched_calls: Vec::new(),
}
}
}
Expand All @@ -216,6 +219,7 @@ impl TestEnvData {
self.total_reads.set(0);
self.total_writes = 0;
self.events.clear();
self.dispatched_calls.clear();
}

/// Increments the total number of reads from the storage.
Expand Down Expand Up @@ -282,6 +286,11 @@ impl TestEnvData {
self.events.push(new_event);
}

/// Appends a dispatched call to the runtime
pub fn add_dispatched_call(&mut self, call: &[u8]) {
self.dispatched_calls.push(call.to_vec());
}

/// Sets the random seed for the next contract invocation.
pub fn set_random_seed(&mut self, random_seed_hash: Vec<u8>) {
self.random_seed = random_seed_hash.to_vec();
Expand All @@ -303,6 +312,11 @@ impl TestEnvData {
.iter()
.map(|event_data| event_data.data_as_bytes())
}

ascjones marked this conversation as resolved.
Show resolved Hide resolved
/// Returns an iterator over all dispatched calls
pub fn dispatched_calls(&self) -> impl DoubleEndedIterator<Item = &[u8]> {
self.dispatched_calls.iter().map(Vec::as_slice)
}
}

impl TestEnvData {
Expand Down Expand Up @@ -399,6 +413,10 @@ impl TestEnvData {
pub fn deposit_raw_event(&mut self, topics: &[Vec<u8>], data: &[u8]) {
self.add_event(topics, data);
}

pub fn dispatch_call(&mut self, call: &[u8]) {
self.add_dispatched_call(call);
}
}

thread_local! {
Expand Down Expand Up @@ -477,6 +495,18 @@ where
.into_iter()
})
}

ascjones marked this conversation as resolved.
Show resolved Hide resolved
/// Returns an iterator over all dispatched calls.
pub fn dispatched_calls() -> impl DoubleEndedIterator<Item = T::Call> {
TEST_ENV_DATA.with(|test_env| {
test_env
.borrow()
.dispatched_calls()
.map(|call| Decode::decode(&mut &call[..]).expect("Valid encoded Call"))
.collect::<Vec<_>>()
.into_iter()
})
}
}

macro_rules! impl_env_getters_for_test_env {
Expand All @@ -499,6 +529,7 @@ where
type Hash = <T as EnvTypes>::Hash;
type Moment = <T as EnvTypes>::Moment;
type BlockNumber = <T as EnvTypes>::BlockNumber;
type Call = <T as EnvTypes>::Call;
}

impl<T> Env for TestEnv<T>
Expand Down Expand Up @@ -532,6 +563,10 @@ where
test_env.borrow_mut().deposit_raw_event(&topics, data)
})
}

fn dispatch_raw_call(data: &[u8]) {
TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().dispatch_call(data))
}
}

pub enum TestEnvStorage {}
Expand Down
9 changes: 9 additions & 0 deletions core/src/env/traits.rs
Expand Up @@ -33,10 +33,13 @@ pub trait EnvTypes {
type Moment: Codec + Clone + PartialEq + Eq;
/// The type of block number.
type BlockNumber: Codec + Clone + PartialEq + Eq;
/// The type of a call into the runtime
type Call: parity_codec::Encode;
}

#[cfg(feature = "test-env")]
/// The environmental types usable by contracts defined with ink!.
/// For the test environment extra trait bounds are required for using the types in unit tests.
pub trait EnvTypes {
/// The type of an address.
type AccountId: Codec + Clone + PartialEq + Eq + core::fmt::Debug;
Expand All @@ -48,6 +51,9 @@ pub trait EnvTypes {
type Moment: Codec + Clone + PartialEq + Eq + core::fmt::Debug;
/// The type of block number.
type BlockNumber: Codec + Clone + PartialEq + Eq + core::fmt::Debug;
/// The type of a call into the runtime.
/// Requires Decode for inspecting raw dispatched calls in the test environment.
type Call: Codec + Clone + PartialEq + Eq + core::fmt::Debug;
ascjones marked this conversation as resolved.
Show resolved Hide resolved
}

/// Types implementing this can act as contract storage.
Expand Down Expand Up @@ -127,4 +133,7 @@ pub trait Env: EnvTypes {

/// Deposits raw event data through Contracts module.
fn deposit_raw_event(topics: &[<Self as EnvTypes>::Hash], data: &[u8]);

/// Dispatches a call into the Runtime.
fn dispatch_raw_call(data: &[u8]);
}
2 changes: 1 addition & 1 deletion examples/lang/events/Cargo.toml
Expand Up @@ -28,4 +28,4 @@ generate-api-description = [
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
opt-level = "z"
2 changes: 1 addition & 1 deletion examples/lang/flipper/Cargo.toml
Expand Up @@ -28,4 +28,4 @@ generate-api-description = [
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
opt-level = "z"
4 changes: 2 additions & 2 deletions examples/lang/incrementer/Cargo.toml
Expand Up @@ -8,7 +8,7 @@ edition = "2018"
ink_core = { path = "../../../core" }
ink_model = { path = "../../../model" }
ink_lang = { path = "../../../lang" }
parity-codec = { version = "3.2", default-features = false, features = ["derive"] }
parity-codec = { version = "4.1", default-features = false, features = ["derive"] }

[lib]
name = "incrementer"
Expand All @@ -28,4 +28,4 @@ generate-api-description = [
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
opt-level = "z"
4 changes: 2 additions & 2 deletions examples/lang/shared_vec/Cargo.toml
Expand Up @@ -8,7 +8,7 @@ edition = "2018"
ink_core = { path = "../../../core" }
ink_model = { path = "../../../model" }
ink_lang = { path = "../../../lang" }
parity-codec = { version = "3.2", default-features = false, features = ["derive"] }
parity-codec = { version = "4.1", default-features = false, features = ["derive"] }

[lib]
name = "shared_vec"
Expand All @@ -28,4 +28,4 @@ generate-api-description = [
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
opt-level = "z"
10 changes: 10 additions & 0 deletions model/src/exec_env.rs
Expand Up @@ -28,6 +28,7 @@ use ink_core::{
Initialize,
},
};
use parity_codec::Encode as _;

/// Provides a safe interface to an environment given a contract state.
pub struct ExecutionEnv<State, Env> {
Expand Down Expand Up @@ -177,7 +178,16 @@ impl<T: Env> EnvHandler<T> {
T::now()
}

/// Returns the latest block number.
pub fn block_number(&self) -> T::BlockNumber {
T::block_number()
}

ascjones marked this conversation as resolved.
Show resolved Hide resolved
/// Dispatches a call into the runtime.
pub fn dispatch_call<C>(&self, call: C)
where
C: Into<T::Call>,
{
T::dispatch_raw_call(call.into().encode().as_slice())
}
}