Skip to content
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
3 changes: 2 additions & 1 deletion crates/revm/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ pub(crate) fn execute_rwasm_interruption<CTX: ContextTr>(
return_result!(MalformedBuiltinParams);
};
// input: slot + value
const INPUT_LEN: usize = size_of::<[u8; U256::BYTES]>() + U256::BYTES;
const INPUT_LEN: usize = U256::BYTES + U256::BYTES;
let syscall_params = &inputs.syscall_params;
assert_return!(
syscall_params.input.len() == INPUT_LEN && syscall_params.state == STATE_MAIN,
Expand All @@ -797,6 +797,7 @@ pub(crate) fn execute_rwasm_interruption<CTX: ContextTr>(
let slot_u256 = U256::from_le_bytes(slot);
let value_u256 = U256::from_le_bytes(value);
journal.sstore(account_owner_address, slot_u256, value_u256)?;
journal.touch_account(account_owner_address);

return_result!(Bytes::default(), Ok);
}
Expand Down
38 changes: 18 additions & 20 deletions crates/sdk/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ use crate::{
use alloc::vec;
use core::cell::RefCell;
use fluentbase_types::{
native_api::NativeAPI, Address, Bytes, ContextReader, ExitCode, IsAccountEmpty,
IsAccountOwnable, IsColdAccess, MetadataAPI, MetadataStorageAPI, SharedAPI,
SharedContextInputV1, StorageAPI, syscall::SyscallResult, B256, BN254_G1_POINT_COMPRESSED_SIZE,
BN254_G1_POINT_DECOMPRESSED_SIZE, BN254_G2_POINT_COMPRESSED_SIZE,
BN254_G2_POINT_DECOMPRESSED_SIZE, STATE_MAIN, syscall::SYSCALL_ID_BALANCE, syscall::SYSCALL_ID_BLOCK_HASH,
syscall::SYSCALL_ID_CALL, syscall::SYSCALL_ID_CALL_CODE, syscall::SYSCALL_ID_CODE_COPY, syscall::SYSCALL_ID_CODE_HASH,
syscall::SYSCALL_ID_CODE_SIZE, syscall::SYSCALL_ID_CREATE, syscall::SYSCALL_ID_CREATE2, syscall::SYSCALL_ID_DELEGATE_CALL,
syscall::SYSCALL_ID_DESTROY_ACCOUNT, syscall::SYSCALL_ID_EMIT_LOG, syscall::SYSCALL_ID_METADATA_COPY,
syscall::SYSCALL_ID_METADATA_CREATE, syscall::SYSCALL_ID_METADATA_SIZE, syscall::SYSCALL_ID_METADATA_STORAGE_READ,
syscall::SYSCALL_ID_METADATA_STORAGE_WRITE, syscall::SYSCALL_ID_METADATA_WRITE, syscall::SYSCALL_ID_SELF_BALANCE,
syscall::SYSCALL_ID_STATIC_CALL, syscall::SYSCALL_ID_STORAGE_READ, syscall::SYSCALL_ID_STORAGE_WRITE,
syscall::SYSCALL_ID_TRANSIENT_READ, syscall::SYSCALL_ID_TRANSIENT_WRITE, U256,
native_api::NativeAPI, syscall::SyscallResult, syscall::SYSCALL_ID_BALANCE,
syscall::SYSCALL_ID_BLOCK_HASH, syscall::SYSCALL_ID_CALL, syscall::SYSCALL_ID_CALL_CODE,
syscall::SYSCALL_ID_CODE_COPY, syscall::SYSCALL_ID_CODE_HASH, syscall::SYSCALL_ID_CODE_SIZE,
syscall::SYSCALL_ID_CREATE, syscall::SYSCALL_ID_CREATE2, syscall::SYSCALL_ID_DELEGATE_CALL,
syscall::SYSCALL_ID_DESTROY_ACCOUNT, syscall::SYSCALL_ID_EMIT_LOG,
syscall::SYSCALL_ID_METADATA_COPY, syscall::SYSCALL_ID_METADATA_CREATE,
syscall::SYSCALL_ID_METADATA_SIZE, syscall::SYSCALL_ID_METADATA_STORAGE_READ,
syscall::SYSCALL_ID_METADATA_STORAGE_WRITE, syscall::SYSCALL_ID_METADATA_WRITE,
syscall::SYSCALL_ID_SELF_BALANCE, syscall::SYSCALL_ID_STATIC_CALL,
syscall::SYSCALL_ID_STORAGE_READ, syscall::SYSCALL_ID_STORAGE_WRITE,
syscall::SYSCALL_ID_TRANSIENT_READ, syscall::SYSCALL_ID_TRANSIENT_WRITE, Address, Bytes,
ContextReader, ExitCode, IsAccountEmpty, IsAccountOwnable, IsColdAccess, MetadataAPI,
MetadataStorageAPI, SharedAPI, SharedContextInputV1, StorageAPI, B256,
BN254_G1_POINT_COMPRESSED_SIZE, BN254_G1_POINT_DECOMPRESSED_SIZE,
BN254_G2_POINT_COMPRESSED_SIZE, BN254_G2_POINT_DECOMPRESSED_SIZE, STATE_MAIN, U256,
};

pub struct SharedContextImpl<API: NativeAPI> {
Expand Down Expand Up @@ -170,16 +173,11 @@ impl<API: NativeAPI> MetadataStorageAPI for SharedContextImpl<API> {
None,
STATE_MAIN,
);
let value = self.native_sdk.return_data();
SyscallResult::new(
U256::from_le_slice(value.as_ref()),
fuel_consumed,
fuel_refunded,
exit_code,
)
let value = U256::from_le_slice(&self.native_sdk.return_data());
SyscallResult::new(value, fuel_consumed, fuel_refunded, exit_code)
}

fn metadata_storage_write(&self, slot: &U256, value: U256) -> SyscallResult<()> {
fn metadata_storage_write(&mut self, slot: &U256, value: U256) -> SyscallResult<()> {
let mut input = [0u8; U256::BYTES * 2];
input[..U256::BYTES].copy_from_slice(slot.as_le_slice());
input[U256::BYTES..].copy_from_slice(&value.to_le_bytes::<{ U256::BYTES }>());
Expand Down
4 changes: 2 additions & 2 deletions crates/svm/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use crate::{
helpers::is_zeroed,
solana_program::{loader_v4, sysvar::Sysvar},
system_instruction::{
MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION,
MAX_PERMITTED_DATA_LENGTH,
MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION, MAX_PERMITTED_DATA_LENGTH,
},
};
use alloc::{rc::Rc, sync::Arc, vec, vec::Vec};
Expand Down Expand Up @@ -292,6 +291,7 @@ impl Debug for AccountSharedData {
.field("owner", &self.owner)
.field("executable", &self.executable)
.field("rent_epoch", &self.rent_epoch)
.field("data.len", &self.data.len())
.finish()
}
}
Expand Down
85 changes: 84 additions & 1 deletion crates/svm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
use alloc::{sync::Arc, vec, vec::Vec};
use core::marker::PhantomData;
use fluentbase_sdk::{keccak256, Address, SharedAPI, U256};
use fluentbase_types::{ExitCode, MetadataStorageAPI};
use solana_bincode::limited_deserialize;
use solana_instruction::error::InstructionError;
use solana_pubkey::{Pubkey, PUBKEY_BYTES, SVM_ADDRESS_PREFIX};
Expand Down Expand Up @@ -429,13 +430,95 @@ pub fn evm_balance_from_lamports(value: u64) -> U256 {
U256::from_be_bytes(bytes) * U256::from(ONE_GWEI)
}

pub struct GlobalLamportsBalance<SDK: MetadataStorageAPI> {
_phantom_data: PhantomData<SDK>,
}

impl<API: MetadataStorageAPI> GlobalLamportsBalance<API> {
pub fn new() -> Self {
Self {
_phantom_data: Default::default(),
}
}
pub fn get_u256(sdk: &API, pk: &U256) -> U256 {
sdk.metadata_storage_read(&pk)
.expect("failed to read balance")
.data
}
pub fn get(sdk: &API, pk: &Pubkey) -> u64 {
lamports_from_evm_balance(Self::get_u256(sdk, &pubkey_to_u256(pk)))
}
pub fn set_u256(sdk: &mut API, pk: &U256, balance: U256) {
let balance_current = sdk
.metadata_storage_write(&pk, balance)
.expect("failed to write balance");
}
pub fn set(sdk: &mut API, pk: &Pubkey, lamports: u64) {
Self::set_u256(
sdk,
&pubkey_to_u256(pk),
evm_balance_from_lamports(lamports),
)
}
pub fn change<const ADD_OR_SUB: bool>(
sdk: &mut API,
pk: &Pubkey,
lamports_change: u64,
) -> Result<U256, SvmError> {
let pk_u256 = pubkey_to_u256(pk);
let balance_current = Self::get_u256(sdk, &pk_u256);
if lamports_change == 0 {
return Ok(balance_current);
}
let balance_change = evm_balance_from_lamports(lamports_change);

let balance_new = if ADD_OR_SUB {
balance_current.checked_add(balance_change)
} else {
balance_current.checked_sub(balance_change)
};
if let Some(balance_new) = balance_new {
Self::set_u256(sdk, &pk_u256, balance_new);
Ok(balance_new)
} else {
Err(ExitCode::IntegerOverflow.into())
}
}
pub fn transfer(
sdk: &mut API,
pk_from: &Pubkey,
pk_to: &Pubkey,
lamports_change: u64,
) -> Result<(U256, U256), SvmError> {
let pk_from_u256 = pubkey_to_u256(pk_from);
let pk_to_u256 = pubkey_to_u256(pk_to);
let balance_from_current = Self::get_u256(sdk, &pk_from_u256);
let balance_to_current = Self::get_u256(sdk, &pk_to_u256);
if lamports_change == 0 {
return Ok((balance_from_current, balance_to_current));
}
let balance_change = evm_balance_from_lamports(lamports_change);

let Some(balance_from_new) = balance_from_current.checked_sub(balance_change) else {
return Err(ExitCode::IntegerOverflow.into());
};
let Some(balance_to_new) = balance_to_current.checked_add(balance_change) else {
return Err(ExitCode::IntegerOverflow.into());
};
Self::set_u256(sdk, &pk_from_u256, balance_from_new);
Self::set_u256(sdk, &pk_to_u256, balance_to_new);

Ok((balance_from_new, balance_to_new))
}
}

#[cfg(test)]
mod tests {
use crate::common::{evm_balance_from_lamports, lamports_from_evm_balance, ONE_GWEI};
use fluentbase_sdk::U256;

#[test]
fn test_evm_balance_to_lamports_and_vice_versa() {
fn test_evm_balance_to_lamports_and_back() {
let evm_balance = U256::from(ONE_GWEI);
let lamports_balance = lamports_from_evm_balance(evm_balance);
assert_eq!(lamports_balance, 1);
Expand Down
5 changes: 3 additions & 2 deletions crates/svm/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use alloc::{boxed::Box, string::String, vec::Vec};
use core::{
fmt,
fmt::{Display, Formatter},
str::Utf8Error,
};
Expand Down Expand Up @@ -47,7 +46,7 @@ pub enum SyscallError {
}

impl Display for SyscallError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
SyscallError::InvalidString(_, _) => write!(f, "SyscallError::InvalidString"),
SyscallError::Abort => write!(f, "SyscallError::Abort"),
Expand Down Expand Up @@ -97,6 +96,7 @@ pub enum RuntimeError {
InvalidType,
InvalidPrefix,
InvalidConversion,
InvalidInputValue,
}

impl core::error::Error for RuntimeError {}
Expand All @@ -110,6 +110,7 @@ impl Display for RuntimeError {
RuntimeError::InvalidType => write!(f, "RuntimeError::InvalidType"),
RuntimeError::InvalidPrefix => write!(f, "RuntimeError::InvalidPrefix"),
RuntimeError::InvalidConversion => write!(f, "RuntimeError::InvalidConversion"),
RuntimeError::InvalidInputValue => write!(f, "RuntimeError::InvalidInputValue"),
}
}
}
Expand Down
18 changes: 11 additions & 7 deletions crates/svm/src/fluentbase/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
use alloc::{string::String, vec::Vec};
use core::marker::PhantomData;
use fluentbase_sdk::{debug_log_ext, MetadataAPI, SharedAPI, U256};
use fluentbase_types::{syscall::SyscallResult, ExitCode};
use fluentbase_types::{syscall::SyscallResult, ExitCode, MetadataStorageAPI};
use hashbrown::HashMap;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -67,7 +67,7 @@ lazy_static! {
};
}

pub(crate) fn extract_account_data_or_default<API: MetadataAPI>(
pub(crate) fn extract_account_data_or_default<API: MetadataAPI + MetadataStorageAPI>(
api: &API,
account_key: &Pubkey,
) -> Result<AccountSharedData, SvmError> {
Expand All @@ -76,17 +76,21 @@ pub(crate) fn extract_account_data_or_default<API: MetadataAPI>(
}

/// Stores provided accounts using specified storage api or alt api
/// Filters out system accounts
/// Filters out system accounts if set
/// Returns error if some accounts are not evm compatible
pub(crate) fn flush_not_system_accounts<SDK: SharedAPI, API: MetadataAPI>(
pub(crate) fn flush_accounts<
const SKIP_SYS_ACCS: bool,
SDK: SharedAPI,
API: MetadataAPI + MetadataStorageAPI,
>(
sdk: &mut SDK,
api: &mut Option<&mut API>,
alt_api: &mut Option<&mut API>,
accounts: &HashMap<Pubkey, AccountSharedData>,
) -> Result<u64, SvmError> {
let mut accounts_flushed = 0;
select_api!(api, sdk, |storage: &mut _| -> Result<(), SvmError> {
select_api!(alt_api, sdk, |storage: &mut _| -> Result<(), SvmError> {
for (pk, account_data) in accounts {
if SYSTEM_PROGRAMS_KEYS.contains(&pk) {
if SKIP_SYS_ACCS && SYSTEM_PROGRAMS_KEYS.contains(&pk) {
continue;
}
// if !is_evm_pubkey(&pk) {
Expand Down
41 changes: 14 additions & 27 deletions crates/svm/src/fluentbase/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,35 @@
use crate::{
account::{
is_executable_by_account,
Account,
AccountSharedData,
ReadableAccount,
WritableAccount,
is_executable_by_account, Account, AccountSharedData, ReadableAccount, WritableAccount,
PROGRAM_OWNERS,
},
builtins::register_builtins,
common::rbpf_config_default,
compute_budget::compute_budget::ComputeBudget,
context::{EnvironmentConfig, IndexOfAccount, InvokeContext, TransactionContext},
error::SvmError,
fluentbase::common::{
extract_account_data_or_default,
flush_not_system_accounts,
BatchMessage,
},
fluentbase::common::{extract_account_data_or_default, flush_accounts, BatchMessage},
helpers::storage_read_account_data,
loaded_programs::{ProgramCacheEntry, ProgramCacheForTxBatch, ProgramRuntimeEnvironments},
loaders::bpf_loader_v4,
message_processor::MessageProcessor,
native_loader,
saturating_add_assign,
select_api,
solana_program,
native_loader, saturating_add_assign, select_api, solana_program,
solana_program::{
feature_set::feature_set_default,
loader_v4,
message::{legacy, LegacyMessage, SanitizedMessage},
svm_message::SVMMessage,
sysvar::instructions::{
construct_instructions_data,
BorrowedAccountMeta,
BorrowedInstruction,
construct_instructions_data, BorrowedAccountMeta, BorrowedInstruction,
},
},
system_processor,
system_program,
system_processor, system_program,
sysvar_cache::SysvarCache,
types::BalanceHistorySnapshot,
};
use alloc::{sync::Arc, vec::Vec};
use fluentbase_sdk::{ContextReader, MetadataAPI, SharedAPI};
use fluentbase_types::MetadataStorageAPI;
use hashbrown::{hash_map::Entry, HashMap, HashSet};
use solana_bincode::deserialize;
use solana_clock::Clock;
Expand All @@ -62,7 +49,7 @@ pub fn init_config() -> Config {
rbpf_config_default(None)
}

pub fn exec_encoded_svm_batch_message<SDK: SharedAPI, API: MetadataAPI>(
pub fn exec_encoded_svm_batch_message<SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &mut SDK,
batch_message: &[u8],
flush_result_accounts: bool,
Expand All @@ -77,7 +64,7 @@ pub fn exec_encoded_svm_batch_message<SDK: SharedAPI, API: MetadataAPI>(
let batch_message = deserialize(batch_message)?;
exec_svm_batch_message(sdk, batch_message, flush_result_accounts, api)
}
pub fn exec_svm_batch_message<SDK: SharedAPI, API: MetadataAPI>(
pub fn exec_svm_batch_message<SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &mut SDK,
batch_message: BatchMessage,
do_flush: bool,
Expand Down Expand Up @@ -111,7 +98,7 @@ pub fn exec_svm_batch_message<SDK: SharedAPI, API: MetadataAPI>(
}
Ok((result_accounts, balance_changes))
}
pub fn exec_encoded_svm_message<SDK: SharedAPI, API: MetadataAPI>(
pub fn exec_encoded_svm_message<SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &mut SDK,
message: &[u8],
flush_result_accounts: bool,
Expand Down Expand Up @@ -181,7 +168,7 @@ fn account_shared_data_from_program(
}

#[allow(clippy::too_many_arguments)]
fn load_transaction_account<'a, SDK: SharedAPI, API: MetadataAPI>(
fn load_transaction_account<'a, SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
api: &API,
message: &impl SVMMessage,
account_key: &Pubkey,
Expand Down Expand Up @@ -248,7 +235,7 @@ fn load_transaction_account<'a, SDK: SharedAPI, API: MetadataAPI>(
Ok((loaded_account, account_found))
}

pub fn prepare_data_for_tx_ctx<SDK: SharedAPI, API: MetadataAPI>(
pub fn prepare_data_for_tx_ctx<SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &mut SDK,
message: &impl SVMMessage,
api: &mut Option<&mut API>,
Expand Down Expand Up @@ -357,7 +344,7 @@ pub fn prepare_data_for_tx_ctx<SDK: SharedAPI, API: MetadataAPI>(
Ok((accounts, program_indices))
}

fn filter_executable_program_accounts<'a, SDK: SharedAPI, API: MetadataAPI>(
fn filter_executable_program_accounts<'a, SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &SDK,
api: &mut Option<&mut API>,
txs: &[&impl SVMMessage],
Expand Down Expand Up @@ -389,7 +376,7 @@ fn filter_executable_program_accounts<'a, SDK: SharedAPI, API: MetadataAPI>(
result
}

pub fn exec_svm_message<SDK: SharedAPI, API: MetadataAPI>(
pub fn exec_svm_message<SDK: SharedAPI, API: MetadataAPI + MetadataStorageAPI>(
sdk: &mut SDK,
api: &mut Option<&mut API>,
message: legacy::Message,
Expand Down Expand Up @@ -509,7 +496,7 @@ pub fn exec_svm_message<SDK: SharedAPI, API: MetadataAPI>(
);
}
if flush_result_accounts {
flush_not_system_accounts(sdk, api, &result_accounts)?;
flush_accounts::<true, _, _>(sdk, api, &result_accounts)?;
}

Ok((result_accounts, balance_changes))
Expand Down
Loading