mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 17:55:42 +00:00
Some trivial externalities added (#1450)
* Add gas_left, gas_price and balance externalities * Add a value_transferred externality
This commit is contained in:
committed by
Gav Wood
parent
1ccb590d18
commit
0ad2a5fb96
@@ -82,6 +82,14 @@ pub trait Ext {
|
|||||||
|
|
||||||
/// Returns a reference to the account id of the current contract.
|
/// Returns a reference to the account id of the current contract.
|
||||||
fn address(&self) -> &AccountIdOf<Self::T>;
|
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
|
/// Loader is a companion of the `Vm` trait. It loads an appropriate abstract
|
||||||
@@ -292,6 +300,7 @@ where
|
|||||||
&mut CallContext {
|
&mut CallContext {
|
||||||
ctx: &mut nested,
|
ctx: &mut nested,
|
||||||
caller: self.self_account.clone(),
|
caller: self.self_account.clone(),
|
||||||
|
value_transferred: value,
|
||||||
},
|
},
|
||||||
input_data,
|
input_data,
|
||||||
empty_output_buf,
|
empty_output_buf,
|
||||||
@@ -361,6 +370,7 @@ where
|
|||||||
&mut CallContext {
|
&mut CallContext {
|
||||||
ctx: &mut nested,
|
ctx: &mut nested,
|
||||||
caller: self.self_account.clone(),
|
caller: self.self_account.clone(),
|
||||||
|
value_transferred: endowment,
|
||||||
},
|
},
|
||||||
input_data,
|
input_data,
|
||||||
EmptyOutputBuf::new(),
|
EmptyOutputBuf::new(),
|
||||||
@@ -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>> {
|
struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm<T> + 'b, L: Loader<T>> {
|
||||||
ctx: &'a mut ExecutionContext<'b, T, V, L>,
|
ctx: &'a mut ExecutionContext<'b, T, V, L>,
|
||||||
caller: T::AccountId,
|
caller: T::AccountId,
|
||||||
|
value_transferred: T::Balance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a, T, E, V, L> Ext for CallContext<'a, 'b, T, V, L>
|
impl<'a, 'b: 'a, T, E, V, L> Ext for CallContext<'a, 'b, T, V, L>
|
||||||
@@ -558,6 +569,14 @@ where
|
|||||||
fn caller(&self) -> &T::AccountId {
|
fn caller(&self) -> &T::AccountId {
|
||||||
&self.caller
|
&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.
|
/// These tests exercise the executive layer.
|
||||||
|
|||||||
@@ -254,6 +254,12 @@ mod tests {
|
|||||||
fn address(&self) -> &u64 {
|
fn address(&self) -> &u64 {
|
||||||
&69
|
&69
|
||||||
}
|
}
|
||||||
|
fn balance(&self) -> u64 {
|
||||||
|
228
|
||||||
|
}
|
||||||
|
fn value_transferred(&self) -> u64 {
|
||||||
|
1337
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute<E: Ext>(
|
fn execute<E: Ext>(
|
||||||
@@ -686,6 +692,257 @@ mod tests {
|
|||||||
.unwrap();
|
.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#"
|
const CODE_RETURN_FROM_START_FN: &str = r#"
|
||||||
(module
|
(module
|
||||||
(import "env" "ext_return" (func $ext_return (param i32 i32)))
|
(import "env" "ext_return" (func $ext_return (param i32 i32)))
|
||||||
@@ -709,6 +966,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn return_from_start_fn() {
|
fn return_from_start_fn() {
|
||||||
let mut mock_ext = MockExt::default();
|
let mut mock_ext = MockExt::default();
|
||||||
|
|||||||
@@ -447,6 +447,38 @@ define_env!(Env, <E: Ext>,
|
|||||||
Ok(())
|
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.
|
// Returns the size of the input buffer.
|
||||||
ext_input_size(ctx) -> u32 => {
|
ext_input_size(ctx) -> u32 => {
|
||||||
Ok(ctx.input_data.len() as u32)
|
Ok(ctx.input_data.len() as u32)
|
||||||
|
|||||||
Reference in New Issue
Block a user