Skip to content

Commit

Permalink
Switch to wasmi native fuel metering (#815)
Browse files Browse the repository at this point in the history
* Pick up new wasmi version, make it compile

* Switch to wasmi native fuel metering

Add wasmi memory fuel metering; all tests pass

* Address review comments

---------

Co-authored-by: Graydon Hoare <graydon@pobox.com>
  • Loading branch information
jayz22 and graydon committed Jun 3, 2023
1 parent d7ceb0a commit 3a3d763
Show file tree
Hide file tree
Showing 24 changed files with 543 additions and 237 deletions.
42 changes: 27 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,15 @@ default-features = false

[workspace.dependencies.wasmi]
package = "soroban-wasmi"
version = "0.16.0-soroban2"
version = "0.30.0-soroban"
git = "https://github.com/stellar/wasmi"
rev = "862b32f5"
rev = "1a2bc7f"

# [patch."https://github.com/stellar/rs-stellar-xdr"]
# stellar-xdr = { path = "../rs-stellar-xdr/" }

# [patch."https://github.com/stellar/wasmi"]
# soroban-wasmi = { path = "../wasmi/wasmi_v1/" }
# soroban-wasmi_core = { path = "../wasmi/core/" }
# soroban-wasmi = { path = "../wasmi/crates/wasmi/" }
# soroban-wasmi_core = { path = "../wasmi/crates/core/" }

[profile.release]
codegen-units = 1
Expand Down
53 changes: 28 additions & 25 deletions soroban-env-common/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,35 +134,38 @@ impl From<stellar_xdr::Error> for Error {
}
}

#[cfg(feature = "wasmi")]
impl From<wasmi::core::TrapCode> for Error {
fn from(code: wasmi::core::TrapCode) -> Self {
let ec = match code {
wasmi::core::TrapCode::UnreachableCodeReached => ScErrorCode::InternalError,

wasmi::core::TrapCode::MemoryOutOfBounds | wasmi::core::TrapCode::TableOutOfBounds => {
ScErrorCode::IndexBounds
}

wasmi::core::TrapCode::IndirectCallToNull => ScErrorCode::MissingValue,

wasmi::core::TrapCode::IntegerDivisionByZero
| wasmi::core::TrapCode::IntegerOverflow
| wasmi::core::TrapCode::BadConversionToInteger => ScErrorCode::ArithDomain,

wasmi::core::TrapCode::BadSignature => ScErrorCode::UnexpectedType,

wasmi::core::TrapCode::StackOverflow | wasmi::core::TrapCode::OutOfFuel => {
return Error::from_type_and_code(ScErrorType::Budget, ScErrorCode::ExceededLimit)
}
};
return Error::from_type_and_code(ScErrorType::WasmVm, ec);
}
}

#[cfg(feature = "wasmi")]
impl From<wasmi::Error> for Error {
fn from(e: wasmi::Error) -> Self {
if let wasmi::Error::Trap(trap) = e {
if let Some(code) = trap.as_code() {
let ec = match code {
wasmi::core::TrapCode::Unreachable => ScErrorCode::InternalError,

wasmi::core::TrapCode::MemoryAccessOutOfBounds
| wasmi::core::TrapCode::TableAccessOutOfBounds => ScErrorCode::IndexBounds,

wasmi::core::TrapCode::ElemUninitialized => ScErrorCode::MissingValue,

wasmi::core::TrapCode::DivisionByZero
| wasmi::core::TrapCode::IntegerOverflow
| wasmi::core::TrapCode::InvalidConversionToInt => ScErrorCode::ArithDomain,

wasmi::core::TrapCode::UnexpectedSignature => ScErrorCode::UnexpectedType,

wasmi::core::TrapCode::StackOverflow
| wasmi::core::TrapCode::MemLimitExceeded
| wasmi::core::TrapCode::CpuLimitExceeded => {
return Error::from_type_and_code(
ScErrorType::Budget,
ScErrorCode::ExceededLimit,
)
}
};
return Error::from_type_and_code(ScErrorType::WasmVm, ec);
if let Some(code) = trap.trap_code() {
return code.into();
}
}
Error::from_type_and_code(ScErrorType::WasmVm, ScErrorCode::InternalError)
Expand Down
2 changes: 2 additions & 0 deletions soroban-env-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub use num::{I256, U256};
pub use stellar_xdr as xdr;

// RawVal is the 64-bit transparent type.
#[cfg(feature = "wasmi")]
pub use raw_val::WasmiMarshal;
pub use raw_val::{
AddressObject, ContractExecutableObject, LedgerKeyNonceObject, MapObject, VecObject,
};
Expand Down
45 changes: 39 additions & 6 deletions soroban-env-common/src/raw_val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,20 +383,53 @@ impl_tryfroms_and_tryfromvals_delegating_to_rawvalconvertible!(i32);
impl_tryfroms_and_tryfromvals_delegating_to_rawvalconvertible!(Error);

#[cfg(feature = "wasmi")]
impl wasmi::core::FromValue for RawVal {
fn from_value(val: wasmi::core::Value) -> Option<Self> {
if let wasmi::core::Value::I64(i) = val {
pub trait WasmiMarshal: Sized {
fn try_marshal_from_value(v: wasmi::Value) -> Option<Self>;
fn marshal_from_self(self) -> wasmi::Value;
}

#[cfg(feature = "wasmi")]
impl WasmiMarshal for RawVal {
fn try_marshal_from_value(v: wasmi::Value) -> Option<Self> {
if let wasmi::Value::I64(i) = v {
Some(RawVal::from_payload(i as u64))
} else {
None
}
}

fn marshal_from_self(self) -> wasmi::Value {
wasmi::Value::I64(self.get_payload() as i64)
}
}

#[cfg(feature = "wasmi")]
impl From<RawVal> for wasmi::core::Value {
fn from(v: RawVal) -> Self {
wasmi::core::Value::I64(v.get_payload() as i64)
impl WasmiMarshal for u64 {
fn try_marshal_from_value(v: wasmi::Value) -> Option<Self> {
if let wasmi::Value::I64(i) = v {
Some(i as u64)
} else {
None
}
}

fn marshal_from_self(self) -> wasmi::Value {
wasmi::Value::I64(self as i64)
}
}

#[cfg(feature = "wasmi")]
impl WasmiMarshal for i64 {
fn try_marshal_from_value(v: wasmi::Value) -> Option<Self> {
if let wasmi::Value::I64(i) = v {
Some(i)
} else {
None
}
}

fn marshal_from_self(self) -> wasmi::Value {
wasmi::Value::I64(self)
}
}

Expand Down
31 changes: 12 additions & 19 deletions soroban-env-common/src/wrapper_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,28 +84,21 @@ macro_rules! impl_wrapper_wasmi_conversions {
($wrapper:ty) => {
// wasmi / VM argument support
#[cfg(feature = "wasmi")]
impl wasmi::core::FromValue for $wrapper {
fn from_value(val: wasmi::core::Value) -> Option<Self> {
let maybe: Option<u64> = <u64 as wasmi::core::FromValue>::from_value(val);
match maybe {
Some(u) => {
let raw = $crate::RawVal::from_payload(u);
if <Self as $crate::RawValConvertible>::is_val_type(raw) {
Some(unsafe {
<Self as $crate::RawValConvertible>::unchecked_from_val(raw)
})
} else {
None
}
impl $crate::WasmiMarshal for $wrapper {
fn try_marshal_from_value(v: wasmi::Value) -> Option<Self> {
if let wasmi::Value::I64(i) = v {
let raw = $crate::RawVal::from_payload(i as u64);
if <Self as $crate::RawValConvertible>::is_val_type(raw) {
return Some(unsafe {
<Self as $crate::RawValConvertible>::unchecked_from_val(raw)
});
}
None => None,
}
None
}
}
#[cfg(feature = "wasmi")]
impl From<$wrapper> for wasmi::core::Value {
fn from(v: $wrapper) -> Self {
wasmi::core::Value::I64(v.as_raw().get_payload() as i64)

fn marshal_from_self(self) -> wasmi::Value {
wasmi::Value::I64(self.as_raw().get_payload() as i64)
}
}
};
Expand Down
Loading

0 comments on commit 3a3d763

Please sign in to comment.