Skip to content

Commit

Permalink
Surface module cache for reuse.
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Jan 10, 2025
1 parent 822727b commit 86ea7ea
Show file tree
Hide file tree
Showing 29 changed files with 652 additions and 320 deletions.
1 change: 1 addition & 0 deletions soroban-env-host/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,7 @@ impl Host {
CallParams::default_internal_call(),
);
if let Err(e) = &res {
use crate::ErrorHandler;
self.error(
e.error,
"check auth invocation for a custom account contract failed",
Expand Down
2 changes: 1 addition & 1 deletion soroban-env-host/src/builtin_contracts/account_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
self, AccountId, ContractIdPreimage, Hash, ScErrorCode, ScErrorType, ThresholdIndexes,
Uint256,
},
Env, EnvBase, HostError, Symbol, TryFromVal, TryIntoVal, Val,
Env, EnvBase, ErrorHandler, HostError, Symbol, TryFromVal, TryIntoVal, Val,
};
use core::cmp::Ordering;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
},
err,
host::{metered_clone::MeteredClone, Host},
Env, HostError, StorageType, TryIntoVal,
Env, ErrorHandler, HostError, StorageType, TryIntoVal,
};

use super::storage_types::AllowanceValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
LedgerEntry, LedgerEntryData, LedgerKey, ScAddress, TrustLineAsset, TrustLineEntry,
TrustLineEntryExt, TrustLineFlags,
},
Env, Host, HostError, StorageType, TryIntoVal,
Env, ErrorHandler, Host, HostError, StorageType, TryIntoVal,
};

use super::storage_types::{BalanceValue, BALANCE_EXTEND_AMOUNT, BALANCE_TTL_THRESHOLD};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
err,
host::{metered_clone::MeteredClone, Host},
xdr::Asset,
BytesObject, Compare, Env, EnvBase, HostError, TryFromVal, TryIntoVal,
BytesObject, Compare, Env, EnvBase, ErrorHandler, HostError, TryFromVal, TryIntoVal,
};

use soroban_builtin_sdk_macros::contractimpl;
Expand Down
10 changes: 6 additions & 4 deletions soroban-env-host/src/cost_runner/cost_types/vm_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use crate::{
xdr::{ContractCostType::VmInstantiation, Hash},
Vm,
};
use std::{hint::black_box, rc::Rc};
use std::{hint::black_box, rc::Rc, sync::Arc};

#[derive(Clone)]
pub struct VmInstantiationSample {
pub id: Option<Hash>,
pub wasm: Vec<u8>,
pub module: Rc<ParsedModule>,
pub module: Arc<ParsedModule>,
}

// Protocol 20 coarse and unified cost model
Expand Down Expand Up @@ -73,7 +73,7 @@ mod v21 {

type SampleType = VmInstantiationSample;

type RecycledType = (Option<Rc<ParsedModule>>, Vec<u8>);
type RecycledType = (Option<Arc<ParsedModule>>, Vec<u8>);

fn run_iter(
host: &crate::Host,
Expand All @@ -83,7 +83,9 @@ mod v21 {
let module = black_box(
ParsedModule::new(
host,
sample.module.module.engine(),
host.get_ledger_protocol_version()
.expect("protocol version"),
sample.module.wasmi_module.engine(),
&sample.wasm[..],
sample.module.cost_inputs.clone(),
)
Expand Down
4 changes: 2 additions & 2 deletions soroban-env-host/src/crypto/bls12_381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
budget::AsBudget,
host_object::HostVec,
xdr::{ContractCostType, ScBytes, ScErrorCode, ScErrorType},
Bool, BytesObject, ConversionError, Env, Host, HostError, TryFromVal, U256Object, U256Small,
U256Val, Val, VecObject, U256,
Bool, BytesObject, ConversionError, Env, ErrorHandler, Host, HostError, TryFromVal, U256Object,
U256Small, U256Val, Val, VecObject, U256,
};
use ark_bls12_381::{
g1::Config as G1Config, g2::Config as G2Config, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine,
Expand Down
43 changes: 42 additions & 1 deletion soroban-env-host/src/e2e_invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
/// host functions.
use std::{cmp::max, rc::Rc};

use crate::ledger_info::get_key_durability;
use crate::storage::EntryWithLiveUntil;
#[cfg(any(test, feature = "recording_mode"))]
use crate::{
Expand All @@ -31,6 +30,7 @@ use crate::{
},
DiagnosticLevel, Error, Host, HostError, LedgerInfo, MeteredOrdMap,
};
use crate::{ledger_info::get_key_durability, ModuleCache};
#[cfg(any(test, feature = "recording_mode"))]
use sha2::{Digest, Sha256};

Expand Down Expand Up @@ -336,6 +336,44 @@ pub fn invoke_host_function_with_trace_hook<T: AsRef<[u8]>, I: ExactSizeIterator
base_prng_seed: T,
diagnostic_events: &mut Vec<DiagnosticEvent>,
trace_hook: Option<TraceHook>,
) -> Result<InvokeHostFunctionResult, HostError> {
invoke_host_function_with_trace_hook_and_module_cache(
budget,
enable_diagnostics,
encoded_host_fn,
encoded_resources,
encoded_source_account,
encoded_auth_entries,
ledger_info,
encoded_ledger_entries,
encoded_ttl_entries,
base_prng_seed,
diagnostic_events,
trace_hook,
None,
)
}

/// Same as `invoke_host_function_with_trace_hook` but allows to pass a `ModuleCache`
/// which should be pre-loaded with all contracts in this invocation.
#[allow(clippy::too_many_arguments)]
pub fn invoke_host_function_with_trace_hook_and_module_cache<
T: AsRef<[u8]>,
I: ExactSizeIterator<Item = T>,
>(
budget: &Budget,
enable_diagnostics: bool,
encoded_host_fn: T,
encoded_resources: T,
encoded_source_account: T,
encoded_auth_entries: I,
ledger_info: LedgerInfo,
encoded_ledger_entries: I,
encoded_ttl_entries: I,
base_prng_seed: T,
diagnostic_events: &mut Vec<DiagnosticEvent>,
trace_hook: Option<TraceHook>,
module_cache: Option<ModuleCache>,
) -> Result<InvokeHostFunctionResult, HostError> {
let _span0 = tracy_span!("invoke_host_function");

Expand Down Expand Up @@ -376,6 +414,9 @@ pub fn invoke_host_function_with_trace_hook<T: AsRef<[u8]>, I: ExactSizeIterator
if enable_diagnostics {
host.set_diagnostic_level(DiagnosticLevel::Debug)?;
}
if let Some(module_cache) = module_cache {
host.set_module_cache(module_cache)?;
}
let result = {
let _span1 = tracy_span!("Host::invoke_function");
host.invoke_function(host_function)
Expand Down
46 changes: 34 additions & 12 deletions soroban-env-host/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub(crate) mod prng;
pub(crate) mod trace;
mod validity;

pub use error::HostError;
pub use error::{ErrorHandler, HostError};
use frame::CallParams;
pub use prng::{Seed, SEED_BYTES};
pub use trace::{TraceEvent, TraceHook, TraceRecord, TraceState};
Expand Down Expand Up @@ -92,7 +92,6 @@ pub(crate) const MIN_LEDGER_PROTOCOL_VERSION: u32 = 22;
#[derive(Clone, Default)]
struct HostImpl {
module_cache: RefCell<Option<ModuleCache>>,
shared_linker: RefCell<Option<wasmi::Linker<Host>>>,
source_account: RefCell<Option<AccountId>>,
ledger: RefCell<Option<LedgerInfo>>,
objects: RefCell<Vec<HostObject>>,
Expand Down Expand Up @@ -217,12 +216,6 @@ impl_checked_borrow_helpers!(
try_borrow_module_cache,
try_borrow_module_cache_mut
);
impl_checked_borrow_helpers!(
shared_linker,
Option<wasmi::Linker<Host>>,
try_borrow_linker,
try_borrow_linker_mut
);
impl_checked_borrow_helpers!(
source_account,
Option<AccountId>,
Expand Down Expand Up @@ -360,7 +353,6 @@ impl Host {
let _client = tracy_client::Client::start();
Self(Rc::new(HostImpl {
module_cache: RefCell::new(None),
shared_linker: RefCell::new(None),
source_account: RefCell::new(None),
ledger: RefCell::new(None),
objects: Default::default(),
Expand Down Expand Up @@ -398,13 +390,44 @@ impl Host {
pub fn build_module_cache_if_needed(&self) -> Result<(), HostError> {
if self.try_borrow_module_cache()?.is_none() {
let cache = ModuleCache::new(self)?;
let linker = cache.make_linker(self)?;
*self.try_borrow_module_cache_mut()? = Some(cache);
*self.try_borrow_linker_mut()? = Some(linker);
}
Ok(())
}

// Install a module cache from _outside_ the Host. Doing this is potentially
// delicate: the cache must contain all contracts that will be run by the
// host, and will not be further populated during execution. This is
// only allowed if the cache is of "reusable" type, i.e. it was created
// using `ModuleCache::new_reusable`.
pub fn set_module_cache(&self, cache: ModuleCache) -> Result<(), HostError> {
if !cache.is_reusable() {
return Err(self.err(
ScErrorType::Context,
ScErrorCode::InternalError,
"module cache not reusable",
&[],
));
}
*self.try_borrow_module_cache_mut()? = Some(cache);
Ok(())
}

// Remove and return the module cache, to allow reuse in another host. Should
// typically only be called during the "finish" sequence of a host's lifecycle,
// i.e. when [Self::can_finish] returns `true` and the host is about to be
// destroyed.
pub fn take_module_cache(&self) -> Result<ModuleCache, HostError> {
self.try_borrow_module_cache_mut()?.take().ok_or_else(|| {
self.err(
ScErrorType::Context,
ScErrorCode::InternalError,
"missing module cache",
&[],
)
})
}

#[cfg(any(test, feature = "recording_mode"))]
pub fn in_storage_recording_mode(&self) -> Result<bool, HostError> {
if let crate::storage::FootprintMode::Recording(_) = self.try_borrow_storage()?.mode {
Expand All @@ -417,7 +440,6 @@ impl Host {
#[cfg(any(test, feature = "recording_mode"))]
pub fn clear_module_cache(&self) -> Result<(), HostError> {
*self.try_borrow_module_cache_mut()? = None;
*self.try_borrow_linker_mut()? = None;
Ok(())
}

Expand Down
2 changes: 2 additions & 0 deletions soroban-env-host/src/host/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::{
SymbolObject, TryFromVal, TryIntoVal, U32Val, Val, VecObject,
};

use super::ErrorHandler;

impl Host {
// Notes on metering: free
pub(crate) fn usize_to_u32(&self, u: usize) -> Result<u32, HostError> {
Expand Down
2 changes: 1 addition & 1 deletion soroban-env-host/src/host/data_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
LedgerKeyTrustLine, PublicKey, ScAddress, ScContractInstance, ScErrorCode, ScErrorType,
ScMap, ScVal, Signer, SignerKey, ThresholdIndexes, TrustLineAsset, Uint256,
},
AddressObject, Env, Host, HostError, StorageType, U32Val, Val,
AddressObject, Env, ErrorHandler, Host, HostError, StorageType, U32Val, Val,
};

impl Host {
Expand Down
5 changes: 5 additions & 0 deletions soroban-env-host/src/host/declared_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ impl<T> DeclaredSizeForMetering for Rc<T> {
const DECLARED_SIZE: u64 = 16;
}

// Arc is the same.
impl<T> DeclaredSizeForMetering for std::sync::Arc<T> {
const DECLARED_SIZE: u64 = 16;
}

// RefCell is the underlying data plus an `isize` flag
impl<T: DeclaredSizeForMetering> DeclaredSizeForMetering for RefCell<T> {
const DECLARED_SIZE: u64 = T::DECLARED_SIZE + 8;
Expand Down
Loading

0 comments on commit 86ea7ea

Please sign in to comment.