mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 06:41:02 +00:00
Add an RPC method for calling a contract. (#3563)
* Sketch * Some work on docs. * Doc improvements. * More docs. * Some more docs. * Yet another comment. * Bump impl_version. * Accept the block hash * Use NumberOrHex * Update node/rpc/src/contracts.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Move rpc/primitives
This commit is contained in:
@@ -75,11 +75,12 @@ pub type ExecResult = Result<ExecReturnValue, ExecError>;
|
||||
/// wrap the error string into an ExecutionError with the provided buffer and return from the
|
||||
/// enclosing function. This macro is used instead of .map_err(..)? in order to avoid taking
|
||||
/// ownership of buffer unless there is an error.
|
||||
#[macro_export]
|
||||
macro_rules! try_or_exec_error {
|
||||
($e:expr, $buffer:expr) => {
|
||||
match $e {
|
||||
Ok(val) => val,
|
||||
Err(reason) => return Err(ExecError { reason, buffer: $buffer }),
|
||||
Err(reason) => return Err($crate::exec::ExecError { reason, buffer: $buffer }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,15 +192,6 @@ pub trait Loader<T: Trait> {
|
||||
fn load_main(&self, code_hash: &CodeHash<T>) -> Result<Self::Executable, &'static str>;
|
||||
}
|
||||
|
||||
/// Struct that records a request to deposit an event with a list of topics.
|
||||
#[cfg_attr(any(feature = "std", test), derive(Debug, PartialEq, Eq))]
|
||||
pub struct IndexedEvent<T: Trait> {
|
||||
/// A list of topics this event will be deposited with.
|
||||
pub topics: Vec<T::Hash>,
|
||||
/// The event to deposit.
|
||||
pub event: Event<T>,
|
||||
}
|
||||
|
||||
/// A trait that represent a virtual machine.
|
||||
///
|
||||
/// You can view a virtual machine as something that takes code, an input data buffer,
|
||||
|
||||
@@ -98,11 +98,13 @@ mod rent;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::exec::{ExecutionContext, ExecResult};
|
||||
use crate::exec::ExecutionContext;
|
||||
use crate::account_db::{AccountDb, DirectAccountDb};
|
||||
pub use crate::gas::{Gas, GasMeter};
|
||||
use crate::wasm::{WasmLoader, WasmVm};
|
||||
|
||||
pub use crate::gas::{Gas, GasMeter};
|
||||
pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
use primitives::crypto::UncheckedFrom;
|
||||
@@ -573,9 +575,9 @@ decl_module! {
|
||||
let origin = ensure_signed(origin)?;
|
||||
let dest = T::Lookup::lookup(dest)?;
|
||||
|
||||
Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
|
||||
ctx.call(dest, value, gas_meter, data)
|
||||
})
|
||||
Self::bare_call(origin, dest, value, gas_limit, data)
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.reason)
|
||||
}
|
||||
|
||||
/// Creates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance.
|
||||
@@ -601,6 +603,8 @@ decl_module! {
|
||||
ctx.instantiate(endowment, gas_meter, &code_hash, data)
|
||||
.map(|(_address, output)| output)
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.reason)
|
||||
}
|
||||
|
||||
/// Allows block producers to claim a small reward for evicting a contract. If a block producer
|
||||
@@ -645,16 +649,37 @@ decl_module! {
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
/// Perform a call to a specified contract.
|
||||
///
|
||||
/// This function is similar to `Self::call`, but doesn't perform any lookups and better
|
||||
/// suitable for calling directly from Rust.
|
||||
pub fn bare_call(
|
||||
origin: T::AccountId,
|
||||
dest: T::AccountId,
|
||||
value: BalanceOf<T>,
|
||||
gas_limit: Gas,
|
||||
input_data: Vec<u8>,
|
||||
) -> ExecResult {
|
||||
Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| {
|
||||
ctx.call(dest, value, gas_meter, input_data)
|
||||
})
|
||||
}
|
||||
|
||||
fn execute_wasm(
|
||||
origin: T::AccountId,
|
||||
gas_limit: Gas,
|
||||
func: impl FnOnce(&mut ExecutionContext<T, WasmVm, WasmLoader>, &mut GasMeter<T>) -> ExecResult
|
||||
) -> Result {
|
||||
) -> ExecResult {
|
||||
// Pay for the gas upfront.
|
||||
//
|
||||
// NOTE: it is very important to avoid any state changes before
|
||||
// paying for the gas.
|
||||
let (mut gas_meter, imbalance) = gas::buy_gas::<T>(&origin, gas_limit)?;
|
||||
let (mut gas_meter, imbalance) =
|
||||
try_or_exec_error!(
|
||||
gas::buy_gas::<T>(&origin, gas_limit),
|
||||
// We don't have a spare buffer here in the first place, so create a new empty one.
|
||||
Vec::new()
|
||||
);
|
||||
|
||||
let cfg = Config::preload();
|
||||
let vm = WasmVm::new(&cfg.schedule);
|
||||
@@ -705,8 +730,6 @@ impl<T: Trait> Module<T> {
|
||||
});
|
||||
|
||||
result
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.reason)
|
||||
}
|
||||
|
||||
fn restore_to(
|
||||
|
||||
Reference in New Issue
Block a user