Skip to content

Commit

Permalink
Wire up module cache and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Mar 28, 2024
1 parent f03d0e4 commit bdbd053
Show file tree
Hide file tree
Showing 5 changed files with 378 additions and 38 deletions.
5 changes: 5 additions & 0 deletions soroban-env-host/src/e2e_invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ pub fn invoke_host_function_with_trace_hook<T: AsRef<[u8]>, I: ExactSizeIterator
let source_account: AccountId = host.metered_from_xdr(encoded_source_account.as_ref())?;
host.set_source_account(source_account)?;
host.set_ledger_info(ledger_info)?;
host.maybe_add_module_cache()?;
host.set_authorization_entries(auth_entries)?;
let seed32: [u8; 32] = base_prng_seed.as_ref().try_into().map_err(|_| {
host.err(
Expand Down Expand Up @@ -533,6 +534,10 @@ pub fn invoke_host_function_in_recording_mode(
let invoke_result = host.invoke_function(host_function);
let mut contract_events_and_return_value_size = 0_u32;
if let Ok(res) = &invoke_result {
// See explanation for this line in [crate::vm::Vm::parse_module] -- it exists
// to add-back module-parsing costs that were suppressed during the invocation.
host.maybe_add_module_cache()?;

let mut encoded_result_sc_val = vec![];
metered_write_xdr(&budget, res, &mut encoded_result_sc_val)?;
contract_events_and_return_value_size = contract_events_and_return_value_size
Expand Down
71 changes: 71 additions & 0 deletions soroban-env-host/src/test/e2e_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1737,3 +1737,74 @@ fn test_classic_account_auth_using_simulation() {
.unwrap();
assert!(res.invoke_result.is_ok());
}

#[cfg(feature = "next")]
mod cap_54_55_56 {

use super::*;
use more_asserts::assert_lt;
use pretty_assertions::assert_eq;

// Test that when running on a protocol that supports the ModuleCache, when
// doing work that would be significantly different under cached instantiation,
// we get a cost estimate from recording mode that still matches the cost of the
// actual execution.
#[test]
fn test_module_cache_recording_fidelity() {
let cd = CreateContractData::new([111; 32], ADD_I32);
let mut ledger_info = default_ledger_info();
ledger_info.protocol_version = crate::vm::ModuleCache::MIN_LEDGER_VERSION;
let host_fn = invoke_contract_host_fn(
&cd.contract_address,
"add",
vec![ScVal::I32(1), ScVal::I32(2)],
);
let ledger_entries_with_ttl = vec![
(
cd.wasm_entry.clone(),
Some(ledger_info.sequence_number + 100),
),
(
cd.contract_entry.clone(),
Some(ledger_info.sequence_number + 1000),
),
];
let res = invoke_host_function_recording_helper(
true,
&host_fn,
&cd.deployer,
None,
&ledger_info,
ledger_entries_with_ttl.clone(),
&prng_seed(),
None,
)
.unwrap();
assert_eq!(res.invoke_result.unwrap(), ScVal::I32(3));

let resources = res.resources;
let auth_entries = res.auth;

let res = invoke_host_function_helper(
true,
&host_fn,
&resources,
&cd.deployer,
auth_entries,
&ledger_info,
ledger_entries_with_ttl,
&prng_seed(),
)
.unwrap();
assert_eq!(res.invoke_result.unwrap(), ScVal::I32(3));

let insns_recording = resources.instructions as f64;
let insns_enforcing = res.budget.get_cpu_insns_consumed().unwrap() as f64;
let insns_delta = (insns_recording - insns_enforcing).abs();
let rel_delta_pct = 100.0 * (insns_delta / insns_enforcing);

// Check that the recording-mode module cache hack puts us within a
// half-percent of the right number.
assert_lt!(rel_delta_pct, 0.5);
}
}
Loading

0 comments on commit bdbd053

Please sign in to comment.