Skip to content

Commit

Permalink
Sketch of cheaper instantiation change
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Feb 29, 2024
1 parent abd977d commit c09eb57
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 47 deletions.
5 changes: 0 additions & 5 deletions Cargo.lock

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

10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ soroban-builtin-sdk-macros = { version = "=20.2.2", path = "soroban-builtin-sdk-
# NB: When updating, also update the version in rs-soroban-env dev-dependencies
[workspace.dependencies.stellar-xdr]
version = "=20.1.0"
path = "/src/rs-stellar-xdr/"
# git = "https://github.com/stellar/rs-stellar-xdr"
# rev = "8b9d623ef40423a8462442b86997155f2c04d3a1"
default-features = false

[workspace.dependencies.wasmi]
package = "soroban-wasmi"
version = "=0.31.1-soroban.20.0.1"
git = "https://github.com/stellar/wasmi"
rev = "0ed3f3dee30dc41ebe21972399e0a73a41944aa0"
path = "/src/wasmi/crates/wasmi/"
#git = "https://github.com/stellar/wasmi"
#rev = "0ed3f3dee30dc41ebe21972399e0a73a41944aa0"

# [patch."https://github.com/stellar/rs-stellar-xdr"]
# stellar-xdr = { path = "../rs-stellar-xdr/" }
#[patch."https://github.com/stellar/rs-stellar-xdr"]
# stellar-xdr = { path = "/src/rs-stellar-xdr/" }
# [patch."https://github.com/stellar/wasmi"]
# soroban-wasmi = { path = "../wasmi/crates/wasmi/" }
# soroban-wasmi_core = { path = "../wasmi/crates/core/" }
Expand Down
1 change: 1 addition & 0 deletions soroban-env-host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ rustversion = "1.0"

[dev-dependencies.stellar-xdr]
version = "=20.1.0"
path = "/src/rs-stellar-xdr"
# git = "https://github.com/stellar/rs-stellar-xdr"
# rev = "8b9d623ef40423a8462442b86997155f2c04d3a1"
default-features = false
Expand Down
96 changes: 93 additions & 3 deletions soroban-env-host/src/budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{

use dimension::{BudgetDimension, IsCpu, IsShadowMode};

#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct CostTracker {
pub iterations: u64,
pub inputs: Option<u64>,
Expand All @@ -46,11 +46,11 @@ struct BudgetTracker {
impl Default for BudgetTracker {
fn default() -> Self {
let mut mt = Self {
cost_tracker: Default::default(),
cost_tracker: [CostTracker::default(); ContractCostType::variants().len()],
meter_count: Default::default(),
#[cfg(any(test, feature = "testutils", feature = "bench"))]
wasm_memory: Default::default(),
time_tracker: Default::default(),
time_tracker: [0_u64; ContractCostType::variants().len()],
};
for (ct, tracker) in ContractCostType::variants()
.iter()
Expand Down Expand Up @@ -92,6 +92,16 @@ impl Default for BudgetTracker {
ContractCostType::Int256Pow => (),
ContractCostType::Int256Shift => (),
ContractCostType::ChaCha20DrawBytes => init_input(), // number of random bytes to draw
ContractCostType::VmInstantiateUnknownBytes => init_input(),
ContractCostType::VmInstantiateInstructions => init_input(),
ContractCostType::VmInstantiateFunctions => init_input(),
ContractCostType::VmInstantiateGlobals => init_input(),
ContractCostType::VmInstantiateTableEntries => init_input(),
ContractCostType::VmInstantiateMemories => init_input(),
ContractCostType::VmInstantiateDataSegments => init_input(),
ContractCostType::VmInstantiateElemSegments => init_input(),
ContractCostType::VmInstantiateImports => init_input(),
ContractCostType::VmInstantiateExports => init_input(),
}
}
mt
Expand Down Expand Up @@ -368,6 +378,46 @@ impl Default for BudgetImpl {
cpu.const_term = 1058;
cpu.lin_term = ScaledU64(501);
}
ContractCostType::VmInstantiateUnknownBytes => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateInstructions => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateFunctions => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateGlobals => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateTableEntries => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateMemories => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateDataSegments => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateElemSegments => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateImports => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateExports => {
cpu.const_term = 0;
cpu.lin_term = ScaledU64(1);
}
}

// define the memory cost model parameters
Expand Down Expand Up @@ -471,6 +521,46 @@ impl Default for BudgetImpl {
mem.const_term = 0;
mem.lin_term = ScaledU64(0);
}
ContractCostType::VmInstantiateUnknownBytes => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateInstructions => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateFunctions => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateGlobals => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateTableEntries => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateMemories => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateDataSegments => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateElemSegments => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateImports => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
ContractCostType::VmInstantiateExports => {
mem.const_term = 0;
mem.lin_term = ScaledU64(1);
}
}
}

Expand Down
14 changes: 13 additions & 1 deletion soroban-env-host/src/budget/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::fmt::Debug;
pub(crate) struct IsCpu(pub(crate) bool);
pub(crate) struct IsShadowMode(pub(crate) bool);

#[derive(Clone, Default)]
#[derive(Clone)]
pub(crate) struct BudgetDimension {
/// A set of cost models that map input values (eg. event counts, object
/// sizes) from some CostType to whatever concrete resource type is being
Expand Down Expand Up @@ -36,6 +36,18 @@ pub(crate) struct BudgetDimension {
pub(crate) shadow_total_count: u64,
}

impl Default for BudgetDimension {
fn default() -> Self {
Self {
cost_models: [MeteredCostComponent::default(); ContractCostType::variants().len()],
limit: Default::default(),
total_count: Default::default(),
shadow_limit: Default::default(),
shadow_total_count: Default::default(),
}
}
}

impl Debug for BudgetDimension {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(
Expand Down
4 changes: 2 additions & 2 deletions soroban-env-host/src/budget/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub trait HostCostModel {
const COST_MODEL_LIN_TERM_SCALE_BITS: u32 = 7;

/// A helper type that wraps an u64 to signify the wrapped value have been scaled.
#[derive(Clone, Default, Debug)]
#[derive(Clone, Copy, Default, Debug)]
pub struct ScaledU64(pub(crate) u64);

impl ScaledU64 {
Expand Down Expand Up @@ -81,7 +81,7 @@ impl From<f64> for ScaledU64 {
}
}

#[derive(Clone, Debug, Default)]
#[derive(Clone, Copy, Debug, Default)]
pub struct MeteredCostComponent {
pub const_term: u64,
pub lin_term: ScaledU64,
Expand Down
27 changes: 19 additions & 8 deletions soroban-env-host/src/host/data_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use crate::{
host::metered_clone::{MeteredAlloc, MeteredClone},
storage::{InstanceStorageMap, Storage},
xdr::{
AccountEntry, AccountId, Asset, BytesM, ContractCodeEntry, ContractDataDurability,
ContractDataEntry, ContractExecutable, ContractIdPreimage, ExtensionPoint, Hash,
HashIdPreimage, HashIdPreimageContractId, LedgerEntry, LedgerEntryData, LedgerEntryExt,
LedgerKey, LedgerKeyAccount, LedgerKeyContractCode, LedgerKeyContractData,
LedgerKeyTrustLine, PublicKey, ScAddress, ScContractInstance, ScErrorCode, ScErrorType,
ScMap, ScVal, Signer, SignerKey, ThresholdIndexes, TrustLineAsset, Uint256,
AccountEntry, AccountId, Asset, BytesM, ContractCodeCostInputs, ContractCodeEntry,
ContractCodeEntryExt, ContractDataDurability, ContractDataEntry, ContractExecutable,
ContractIdPreimage, ExtensionPoint, Hash, HashIdPreimage, HashIdPreimageContractId,
LedgerEntry, LedgerEntryData, LedgerEntryExt, LedgerKey, LedgerKeyAccount,
LedgerKeyContractCode, LedgerKeyContractData, LedgerKeyTrustLine, PublicKey, ScAddress,
ScContractInstance, ScErrorCode, ScErrorType, ScMap, ScVal, Signer, SignerKey,
ThresholdIndexes, TrustLineAsset, Uint256,
},
AddressObject, Env, Host, HostError, StorageType, U32Val, Val,
};
Expand Down Expand Up @@ -122,15 +123,25 @@ impl Host {
)
}

pub(crate) fn retrieve_wasm_from_storage(&self, wasm_hash: &Hash) -> Result<BytesM, HostError> {
pub(crate) fn retrieve_wasm_from_storage(
&self,
wasm_hash: &Hash,
) -> Result<(BytesM, Option<ContractCodeCostInputs>), HostError> {
let key = self.contract_code_ledger_key(wasm_hash)?;
match &self
.try_borrow_storage_mut()?
.get(&key, self.as_budget())
.map_err(|e| self.decorate_contract_code_storage_error(e, wasm_hash))?
.data
{
LedgerEntryData::ContractCode(e) => e.code.metered_clone(self),
LedgerEntryData::ContractCode(e) => {
let code = e.code.metered_clone(self)?;
let costs = match &e.ext {
ContractCodeEntryExt::V0 => None,
ContractCodeEntryExt::V1(v1) => Some(v1.cost_inputs.clone()),
};
Ok((code, costs))
}
_ => Err(err!(
self,
(ScErrorType::Storage, ScErrorCode::InternalError),
Expand Down
4 changes: 2 additions & 2 deletions soroban-env-host/src/host/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,8 @@ impl Host {
let args_vec = args.to_vec();
match &instance.executable {
ContractExecutable::Wasm(wasm_hash) => {
let code_entry = self.retrieve_wasm_from_storage(&wasm_hash)?;
let vm = Vm::new(self, id.metered_clone(self)?, code_entry.as_slice())?;
let (code, costs) = self.retrieve_wasm_from_storage(&wasm_hash)?;
let vm = Vm::new(self, id.metered_clone(self)?, code.as_slice(), costs)?;
let relative_objects = Vec::new();
self.with_frame(
Frame::ContractVM {
Expand Down
24 changes: 21 additions & 3 deletions soroban-env-host/src/host/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::{
metered_write_xdr, ContractReentryMode, CreateContractArgs,
},
xdr::{
Asset, ContractCodeEntry, ContractDataDurability, ContractExecutable, ContractIdPreimage,
Asset, ContractCodeCostInputs, ContractCodeEntry, ContractCodeEntryExt,
ContractCodeEntryV1, ContractDataDurability, ContractExecutable, ContractIdPreimage,
ContractIdPreimageFromAddress, ExtensionPoint, Hash, LedgerKey, LedgerKeyContractCode,
ScAddress, ScErrorCode, ScErrorType,
},
Expand Down Expand Up @@ -164,6 +165,8 @@ impl Host {
)
})?;

let cost_inputs: ContractCodeCostInputs;

// Instantiate a temporary / throwaway VM using this wasm. This will do
// both quick checks like "does this wasm have the right protocol number
// to run on this network" and also a full parse-and-link pass to check
Expand All @@ -176,12 +179,24 @@ impl Host {
// Allow a zero-byte contract when testing, as this is used to make
// native test contracts behave like wasm. They will never be
// instantiated, this is just to exercise their storage logic.
cost_inputs = ContractCodeCostInputs {
n_functions: 0,
n_globals: 0,
n_table_entries: 0,
n_memories: 0,
n_data_segments: 0,
n_elem_segments: 0,
n_imports: 0,
n_exports: 0,
};
} else {
let _check_vm = Vm::new(
let check_vm = Vm::new(
self,
Hash(hash_bytes.metered_clone(self)?),
wasm_bytes_m.as_slice(),
None,
)?;
cost_inputs = check_vm.get_contract_code_cost_inputs()?;
}

let hash_obj = self.add_host_object(self.scbytes_from_slice(hash_bytes.as_slice())?)?;
Expand All @@ -199,7 +214,10 @@ impl Host {
self.with_mut_storage(|storage| {
let data = ContractCodeEntry {
hash: Hash(hash_bytes),
ext: ExtensionPoint::V0,
ext: ContractCodeEntryExt::V1(ContractCodeEntryV1 {
ext: ExtensionPoint::V0,
cost_inputs,
}),
code: wasm_bytes_m,
};
storage.put(
Expand Down
2 changes: 1 addition & 1 deletion soroban-env-host/src/test/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,6 @@ fn f32_does_not_work() -> Result<(), HostError> {
use soroban_env_common::xdr::Hash;
let host = observe_host!(Host::default());
let hash = Hash::from([0; 32]);
assert!(crate::vm::Vm::new(&host, hash, soroban_test_wasms::ADD_F32).is_err());
assert!(crate::vm::Vm::new(&host, hash, soroban_test_wasms::ADD_F32, None).is_err());
Ok(())
}
Loading

0 comments on commit c09eb57

Please sign in to comment.