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

Convert small int VM hooks #1713

Draft
wants to merge 2 commits into
base: rc/v0.55
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"arguments": [
"23,000000000"
],
"gasLimit": "9,000,000",
"gasLimit": "50,000,000",
"gasPrice": "0"
},
"expect": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"expect": {
"out": [],
"status": "*",
"message": "str:storage decode error (key: i64): argument out of range",
"message": "str:storage decode error (key: i64): value too long",
"logs": "*",
"gas": "*",
"refund": "*"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"expect": {
"out": [],
"status": "4",
"message": "str:storage decode error (key: u64): input too long",
"message": "str:storage decode error (key: u64): value too long",
"logs": "*",
"gas": "*",
"refund": "*"
Expand Down
8 changes: 8 additions & 0 deletions framework/base/src/api/managed_types/managed_type_api_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ pub trait ManagedTypeApiImpl:
dest: Self::ManagedBufferHandle,
);

fn mb_to_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle) -> i64;

fn mb_to_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle) -> i64;

fn mb_from_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle, value: i64);

fn mb_from_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle, value: i64);

fn mb_to_big_float(&self, buffer_handle: Self::ManagedBufferHandle, dest: Self::BigFloatHandle);

fn mb_from_big_float(
Expand Down
16 changes: 16 additions & 0 deletions framework/base/src/api/uncallable/managed_type_api_uncallable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ impl ManagedTypeApiImpl for UncallableApi {
unreachable!()
}

fn mb_to_small_int_unsigned(&self, _buffer_handle: Self::ManagedBufferHandle) -> i64 {
unreachable!()
}

fn mb_to_small_int_signed(&self, _buffer_handle: Self::ManagedBufferHandle) -> i64 {
unreachable!()
}

fn mb_from_small_int_unsigned(&self, _buffer_handle: Self::ManagedBufferHandle, _value: i64) {
unreachable!()
}

fn mb_from_small_int_signed(&self, _buffer_handle: Self::ManagedBufferHandle, _value: i64) {
unreachable!()
}

fn mb_to_big_float(
&self,
_buffer_handle: Self::ManagedBufferHandle,
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/err_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub const ARG_ASYNC_RETURN_WRONG_NUMBER: &str = "wrong number of arguments retur
pub const ARG_CALLBACK_TOO_FEW: &str = "too few callback arguments provided";
pub const ARG_CALLBACK_TOO_MANY: &str = "too many callback arguments provided";

pub const VALUE_TOO_LONG: &str = "value too long";
pub const ARG_OUT_OF_RANGE: &str = "argument out of range";
pub const ARG_BAD_LENGTH: &str = "argument has wrong length";
pub const ARG_BAD_LENGTH_32: &str = "argument has wrong length: 32 bytes expected";
Expand Down
8 changes: 7 additions & 1 deletion framework/base/src/storage/storage_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,20 @@ where
.into_max_size_buffer_align_right(buffer, h)
}

#[inline]
fn into_i64<H>(self, h: H) -> Result<i64, H::HandledErr>
where
H: DecodeErrorHandler,
{
self.to_managed_buffer().into_i64(h)
}

fn into_u64<H>(self, h: H) -> Result<u64, H::HandledErr>
where
H: DecodeErrorHandler,
{
self.to_managed_buffer().into_u64(h)
}

#[inline]
fn supports_specialized_type<T: TryStaticCast>() -> bool {
T::type_eq::<ManagedBuffer<A>>() || T::type_eq::<BigUint<A>>() || T::type_eq::<BigInt<A>>()
Expand Down
16 changes: 15 additions & 1 deletion framework/base/src/storage/storage_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use unwrap_infallible::UnwrapInfallible;
use crate::{
api::{
const_handles, use_raw_handle, ErrorApi, ManagedBufferApiImpl, ManagedTypeApi,
StorageWriteApi, StorageWriteApiImpl,
ManagedTypeApiImpl, StorageWriteApi, StorageWriteApiImpl,
},
codec::*,
contract_base::ExitCodecErrorHandler,
Expand Down Expand Up @@ -47,6 +47,20 @@ where
self.set_managed_buffer(&bytes.into())
}

fn set_u64(self, value: u64) {
let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1);
A::managed_type_impl().mb_from_small_int_unsigned(handle.clone(), value as i64);
let managed_buffer = ManagedBuffer::from_handle(handle);
self.set_managed_buffer(&managed_buffer);
}

fn set_i64(self, value: i64) {
let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1);
A::managed_type_impl().mb_from_small_int_signed(handle.clone(), value);
let managed_buffer = ManagedBuffer::from_handle(handle);
self.set_managed_buffer(&managed_buffer);
}

#[inline]
fn supports_specialized_type<T: TryStaticCast>() -> bool {
T::type_eq::<ManagedBuffer<A>>() || T::type_eq::<BigUint<A>>() || T::type_eq::<BigInt<A>>()
Expand Down
24 changes: 13 additions & 11 deletions framework/base/src/types/managed/basic/managed_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
abi::{TypeAbi, TypeAbiFrom, TypeName},
api::{
use_raw_handle, ErrorApiImpl, HandleConstraints, InvalidSliceError, ManagedBufferApiImpl,
ManagedTypeApi, StaticVarApiImpl,
ManagedTypeApi, ManagedTypeApiImpl, StaticVarApiImpl,
},
codec::{
DecodeErrorHandler, Empty, EncodeErrorHandler, NestedDecode, NestedDecodeInput,
Expand Down Expand Up @@ -313,23 +313,25 @@ impl<M: ManagedTypeApi> ManagedBuffer<M> {
}

/// Convenience method for quickly getting a top-decoded u64 from the managed buffer.
///
/// TODO: remove this method once TopDecodeInput is implemented for ManagedBuffer reference.
pub fn parse_as_u64(&self) -> Option<u64> {
const U64_NUM_BYTES: usize = 8;
let l = self.len();
if l > U64_NUM_BYTES {
return None;
}
let mut bytes = [0u8; U64_NUM_BYTES];
if M::managed_type_impl()
.mb_load_slice(self.handle.clone(), 0, &mut bytes[U64_NUM_BYTES - l..])
.is_err()
{
None
} else {
Some(u64::from_be_bytes(bytes))
let value = M::managed_type_impl().mb_to_small_int_unsigned(self.handle.clone());
Some(value as u64)
}

/// Convenience method for quickly getting a top-decoded i64 from the managed buffer.
pub fn parse_as_i64(&self) -> Option<i64> {
const I64_NUM_BYTES: usize = 8;
let l = self.len();
if l > I64_NUM_BYTES {
return None;
}
let value = M::managed_type_impl().mb_to_small_int_signed(self.handle.clone());
Some(value)
}

/// Produces a hex expression in another managed buffer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::{
api::{
const_handles, managed_types::BigIntApiImpl, use_raw_handle, ManagedTypeApi,
ManagedTypeApiImpl,
},
api::ManagedTypeApi,
codec::{
try_execute_then_cast, DecodeError, DecodeErrorHandler, TopDecodeInput, TryStaticCast,
},
Expand Down Expand Up @@ -67,12 +64,21 @@ where
where
H: DecodeErrorHandler,
{
let big_int_temp: M::BigIntHandle = use_raw_handle(const_handles::BIG_INT_TEMPORARY_1);
M::managed_type_impl().mb_to_big_int_signed(self.handle.clone(), big_int_temp.clone());
if let Some(value) = M::managed_type_impl().bi_to_i64(big_int_temp) {
if let Some(value) = self.parse_as_i64() {
Ok(value)
} else {
Err(h.handle_error(err_msg::VALUE_TOO_LONG.into()))
}
}

fn into_u64<H>(self, h: H) -> Result<u64, H::HandledErr>
where
H: DecodeErrorHandler,
{
if let Some(value) = self.parse_as_u64() {
Ok(value)
} else {
Err(h.handle_error(err_msg::ARG_OUT_OF_RANGE.into()))
Err(h.handle_error(err_msg::VALUE_TOO_LONG.into()))
}
}

Expand Down
3 changes: 2 additions & 1 deletion framework/scenario/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ path = "../../sdk/scenario-format"
[dependencies.multiversx-chain-vm-executor]
# version = "0.2.0"
git = "https://github.com/multiversx/mx-vm-executor-rs"
branch = "rc/v1.7.next1"
branch = "convert-small-int"
# path = "/Users/andreim/multiversx/vm/mx-vm-executor-rs/vm-executor"

[dependencies.multiversx-chain-vm]
version = "=0.9.0"
Expand Down
24 changes: 24 additions & 0 deletions framework/scenario/src/api/managed_type_api_vh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,30 @@ impl<VHB: VMHooksApiBackend> ManagedTypeApiImpl for VMHooksApi<VHB> {
});
}

fn mb_to_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle) -> i64 {
self.with_vm_hooks_ctx_1(&buffer_handle, |vh| {
vh.mbuffer_to_small_int_unsigned(buffer_handle.get_raw_handle_unchecked())
})
}

fn mb_to_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle) -> i64 {
self.with_vm_hooks_ctx_1(&buffer_handle, |vh| {
vh.mbuffer_to_small_int_signed(buffer_handle.get_raw_handle_unchecked())
})
}

fn mb_from_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle, value: i64) {
self.with_vm_hooks_ctx_1(&buffer_handle, |vh| {
vh.mbuffer_from_small_int_unsigned(buffer_handle.get_raw_handle_unchecked(), value)
})
}

fn mb_from_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle, value: i64) {
self.with_vm_hooks_ctx_1(&buffer_handle, |vh| {
vh.mbuffer_from_small_int_signed(buffer_handle.get_raw_handle_unchecked(), value)
})
}

fn mb_to_big_float(
&self,
buffer_handle: Self::ManagedBufferHandle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ extern "C" {
fn mBufferToBigIntSigned(mBufferHandle: i32, bigIntHandle: i32) -> i32;
fn mBufferFromBigIntUnsigned(mBufferHandle: i32, bigIntHandle: i32) -> i32;
fn mBufferFromBigIntSigned(mBufferHandle: i32, bigIntHandle: i32) -> i32;

fn mBufferToSmallIntUnsigned(mBufferHandle: i32) -> i64;
fn mBufferToSmallIntSigned(mBufferHandle: i32) -> i64;
fn mBufferFromSmallIntUnsigned(mBufferHandle: i32, value: i64);
fn mBufferFromSmallIntSigned(mBufferHandle: i32, value: i64);

fn mBufferToBigFloat(mBufferHandle: i32, bigFloatHandle: i32) -> i32;
fn mBufferFromBigFloat(mBufferHandle: i32, bigFloatHandle: i32) -> i32;

Expand Down Expand Up @@ -65,6 +71,26 @@ impl ManagedTypeApiImpl for VmApiImpl {
}
}

fn mb_to_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle) -> i64 {
unsafe { mBufferToSmallIntUnsigned(buffer_handle) }
}

fn mb_to_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle) -> i64 {
unsafe { mBufferToSmallIntSigned(buffer_handle) }
}

fn mb_from_small_int_unsigned(&self, buffer_handle: Self::ManagedBufferHandle, value: i64) {
unsafe {
mBufferFromSmallIntUnsigned(buffer_handle, value);
}
}

fn mb_from_small_int_signed(&self, buffer_handle: Self::ManagedBufferHandle, value: i64) {
unsafe {
mBufferFromSmallIntSigned(buffer_handle, value);
}
}

#[inline]
fn mb_to_big_float(
&self,
Expand Down
2 changes: 1 addition & 1 deletion vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ ed25519-dalek = { version = "1.0.1" , optional = true }
[dependencies.multiversx-chain-vm-executor]
# version = "0.2.0"
git = "https://github.com/multiversx/mx-vm-executor-rs"
branch = "rc/v1.7.next1"
branch = "convert-small-int"
4 changes: 3 additions & 1 deletion vm/src/tx_mock/tx_managed_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ mod tx_managed_map;

pub use handle_map::HandleMap;
use num_bigint::BigInt;
pub use tx_big_int::big_int_to_i64;
pub use tx_big_int::{
big_int_signed_bytes, big_int_to_i64, big_uint_to_u64, big_uint_unsigned_bytes,
};

use std::collections::HashMap;

Expand Down
31 changes: 26 additions & 5 deletions vm/src/tx_mock/tx_managed_types/tx_big_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ impl TxManagedTypes {

pub fn bi_get_signed_bytes(&self, handle: RawHandle) -> Vec<u8> {
let bi = self.bi_get(handle);
if bi.is_zero() {
Vec::new()
} else {
bi.to_signed_bytes_be()
}
big_int_signed_bytes(&bi)
}

pub fn bi_set_signed_bytes(&mut self, destination: RawHandle, bytes: &[u8]) {
Expand Down Expand Up @@ -90,3 +86,28 @@ pub fn big_int_to_i64(bi: &num_bigint::BigInt) -> Option<i64> {
},
}
}

pub fn big_uint_to_u64(bu: &num_bigint::BigUint) -> Option<u64> {
let digits = bu.to_u64_digits();
match digits.len() {
0 => Some(0),
1 => Some(digits[0]),
_ => None,
}
}

pub fn big_uint_unsigned_bytes(bu: &num_bigint::BigUint) -> Vec<u8> {
if bu.is_zero() {
Vec::new()
} else {
bu.to_bytes_be()
}
}

pub fn big_int_signed_bytes(bi: &num_bigint::BigInt) -> Vec<u8> {
if bi.is_zero() {
Vec::new()
} else {
bi.to_signed_bytes_be()
}
}
3 changes: 3 additions & 0 deletions vm/src/vm_err_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ pub const ERROR_SIGNALLED_BY_SMARTCONTRACT: &str = "error signalled by smartcont

pub const ERROR_NO_CALLBACK_CLOSURE: &str =
"no callback for closure, cannot call callback directly";

pub const ERROR_BYTES_EXCEED_INT64: &str = "bytes cannot be parsed as int64";
pub const ERROR_BYTES_EXCEED_UINT64: &str = "bytes cannot be parsed as uint64";
Loading
Loading