Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Some trivial externalities added #1450

Merged
merged 2 commits into from
Jan 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions srml/contract/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ pub trait Ext {

/// Returns a reference to the account id of the current contract.
fn address(&self) -> &AccountIdOf<Self::T>;

/// Returns the balance of the current contract.
///
/// The `value_transferred` is already added.
fn balance(&self) -> BalanceOf<Self::T>;

/// Returns the value transfered along with this call or as endowment.
fn value_transferred(&self) -> BalanceOf<Self::T>;
}

/// Loader is a companion of the `Vm` trait. It loads an appropriate abstract
Expand Down Expand Up @@ -292,6 +300,7 @@ where
&mut CallContext {
ctx: &mut nested,
caller: self.self_account.clone(),
value_transferred: value,
},
input_data,
empty_output_buf,
Expand Down Expand Up @@ -361,6 +370,7 @@ where
&mut CallContext {
ctx: &mut nested,
caller: self.self_account.clone(),
value_transferred: endowment,
},
input_data,
EmptyOutputBuf::new(),
Expand Down Expand Up @@ -509,6 +519,7 @@ fn transfer<'a, T: Trait, V: Vm<T>, L: Loader<T>>(
struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm<T> + 'b, L: Loader<T>> {
ctx: &'a mut ExecutionContext<'b, T, V, L>,
caller: T::AccountId,
value_transferred: T::Balance,
}

impl<'a, 'b: 'a, T, E, V, L> Ext for CallContext<'a, 'b, T, V, L>
Expand Down Expand Up @@ -558,6 +569,14 @@ where
fn caller(&self) -> &T::AccountId {
&self.caller
}

fn balance(&self) -> T::Balance {
self.ctx.overlay.get_balance(&self.ctx.self_account)
}

fn value_transferred(&self) -> T::Balance {
self.value_transferred
}
}

/// These tests exercise the executive layer.
Expand Down
258 changes: 258 additions & 0 deletions srml/contract/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ mod tests {
fn address(&self) -> &u64 {
&69
}
fn balance(&self) -> u64 {
228
}
fn value_transferred(&self) -> u64 {
1337
}
}

fn execute<E: Ext>(
Expand Down Expand Up @@ -686,6 +692,257 @@ mod tests {
.unwrap();
}

const CODE_BALANCE: &str = r#"
(module
(import "env" "ext_balance" (func $ext_balance))
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))

(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)

(func (export "call")
;; This stores the balance in the scratch buffer
(call $ext_balance)

;; assert $ext_scratch_size == 8
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.const 8)
)
)

;; copy contents of the scratch buffer into the contract's memory.
(call $ext_scratch_copy
(i32.const 8) ;; Pointer in memory to the place where to copy.
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 8) ;; Count of bytes to copy.
)

;; assert that contents of the buffer is equal to the i64 value of 228.
(call $assert
(i64.eq
(i64.load
(i32.const 8)
)
(i64.const 228)
)
)
)
(func (export "deploy"))
)
"#;

#[test]
fn balance() {
let mut mock_ext = MockExt::default();
let mut gas_meter = GasMeter::with_limit(50_000, 1);
execute(
CODE_BALANCE,
&[],
&mut Vec::new(),
&mut mock_ext,
&mut gas_meter,
)
.unwrap();
}

const CODE_GAS_PRICE: &str = r#"
(module
(import "env" "ext_gas_price" (func $ext_gas_price))
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))

(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)

(func (export "call")
;; This stores the gas price in the scratch buffer
(call $ext_gas_price)

;; assert $ext_scratch_size == 8
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.const 8)
)
)

;; copy contents of the scratch buffer into the contract's memory.
(call $ext_scratch_copy
(i32.const 8) ;; Pointer in memory to the place where to copy.
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 8) ;; Count of bytes to copy.
)

;; assert that contents of the buffer is equal to the i64 value of 1312.
(call $assert
(i64.eq
(i64.load
(i32.const 8)
)
(i64.const 1312)
)
)
)
(func (export "deploy"))
)
"#;

#[test]
fn gas_price() {
let mut mock_ext = MockExt::default();
let mut gas_meter = GasMeter::with_limit(50_000, 1312);
execute(
CODE_GAS_PRICE,
&[],
&mut Vec::new(),
&mut mock_ext,
&mut gas_meter,
)
.unwrap();
}

const CODE_GAS_LEFT: &str = r#"
(module
(import "env" "ext_gas_left" (func $ext_gas_left))
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32)))
(import "env" "ext_return" (func $ext_return (param i32 i32)))
(import "env" "memory" (memory 1 1))

(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)

(func (export "call")
;; This stores the gas left in the scratch buffer
(call $ext_gas_left)

;; assert $ext_scratch_size == 8
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.const 8)
)
)

;; copy contents of the scratch buffer into the contract's memory.
(call $ext_scratch_copy
(i32.const 8) ;; Pointer in memory to the place where to copy.
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 8) ;; Count of bytes to copy.
)

(call $ext_return
(i32.const 8)
(i32.const 8)
)

(unreachable)
)
(func (export "deploy"))
)
"#;

#[test]
fn gas_left() {
let mut mock_ext = MockExt::default();
let mut gas_meter = GasMeter::with_limit(50_000, 1312);
execute(
CODE_GAS_LEFT,
&[],
&mut Vec::new(),
&mut mock_ext,
&mut gas_meter,
)
.unwrap();
}

const CODE_VALUE_TRANSFERRED: &str = r#"
(module
(import "env" "ext_value_transferred" (func $ext_value_transferred))
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))

(func $assert (param i32)
(block $ok
(br_if $ok
(get_local 0)
)
(unreachable)
)
)

(func (export "call")
;; This stores the value transferred in the scratch buffer
(call $ext_value_transferred)

;; assert $ext_scratch_size == 8
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.const 8)
)
)

;; copy contents of the scratch buffer into the contract's memory.
(call $ext_scratch_copy
(i32.const 8) ;; Pointer in memory to the place where to copy.
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 8) ;; Count of bytes to copy.
)

;; assert that contents of the buffer is equal to the i64 value of 1337.
(call $assert
(i64.eq
(i64.load
(i32.const 8)
)
(i64.const 1337)
)
)
)
(func (export "deploy"))
)
"#;

#[test]
fn value_transferred() {
let mut mock_ext = MockExt::default();
let mut gas_meter = GasMeter::with_limit(50_000, 1);
execute(
CODE_VALUE_TRANSFERRED,
&[],
&mut Vec::new(),
&mut mock_ext,
&mut gas_meter,
)
.unwrap();
}


const CODE_RETURN_FROM_START_FN: &str = r#"
(module
(import "env" "ext_return" (func $ext_return (param i32 i32)))
Expand All @@ -709,6 +966,7 @@ mod tests {
)
"#;


#[test]
fn return_from_start_fn() {
let mut mock_ext = MockExt::default();
Expand Down
32 changes: 32 additions & 0 deletions srml/contract/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,38 @@ define_env!(Env, <E: Ext>,
Ok(())
},

// Stores the gas price for the current transaction into the scratch buffer.
//
// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
ext_gas_price(ctx) => {
ctx.scratch_buf = ctx.gas_meter.gas_price().encode();
Ok(())
},

// Stores the amount of gas left into the scratch buffer.
//
// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
ext_gas_left(ctx) => {
ctx.scratch_buf = ctx.gas_meter.gas_left().encode();
Ok(())
},

// Stores the balance of the current account into the scratch buffer.
//
// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
ext_balance(ctx) => {
ctx.scratch_buf = ctx.ext.balance().encode();
Ok(())
},

// Stores the value transferred along with this call or as endowment into the scratch buffer.
//
// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
ext_value_transferred(ctx) => {
ctx.scratch_buf = ctx.ext.value_transferred().encode();
Ok(())
},

// Returns the size of the input buffer.
ext_input_size(ctx) -> u32 => {
Ok(ctx.input_data.len() as u32)
Expand Down