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

Add instance storage wrapper #1017

Merged
merged 11 commits into from
Jun 24, 2023
12 changes: 6 additions & 6 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ soroban-token-sdk = { version = "0.8.4", path = "soroban-token-sdk" }
[workspace.dependencies.soroban-env-common]
version = "0.0.16"
git = "https://github.com/stellar/rs-soroban-env"
rev = "bf09e81fe1b00d674a6cb1ce3f31034c0b1d5d8b"
rev = "a9dbd06aaa22c67a96b5eef81c80326e50a89086"

[workspace.dependencies.soroban-env-guest]
version = "0.0.16"
git = "https://github.com/stellar/rs-soroban-env"
rev = "bf09e81fe1b00d674a6cb1ce3f31034c0b1d5d8b"
rev = "a9dbd06aaa22c67a96b5eef81c80326e50a89086"

[workspace.dependencies.soroban-env-host]
version = "0.0.16"
git = "https://github.com/stellar/rs-soroban-env"
rev = "bf09e81fe1b00d674a6cb1ce3f31034c0b1d5d8b"
rev = "a9dbd06aaa22c67a96b5eef81c80326e50a89086"

[workspace.dependencies.stellar-strkey]
version = "0.0.7"
Expand All @@ -60,7 +60,7 @@ rev = "e6ba45c60c16de28c7522586b80ed0150157df73"
[workspace.dependencies.stellar-xdr]
version = "0.0.16"
git = "https://github.com/stellar/rs-stellar-xdr"
rev = "518171b12025283cac1233c7de8e4c20088d95b5"
rev = "6750a11325a7c4eed1e79372d136106e5bfecaff"
default-features = false

#[patch."https://github.com/stellar/rs-soroban-env"]
Expand Down
97 changes: 97 additions & 0 deletions soroban-sdk/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,69 @@ impl Storage {
Storage { env: env.clone() }
}

/// Storage for data that can stay in the ledger forever until deleted.
///
/// Persistent entries might expire and be removed from the ledger if they run out
/// of the rent balance. However, expired entries can be restored and
/// they cannot be recreated. This means these entries
/// behave 'as if' they were stored in the ledger forever.
///
/// This should be used for data that requires persistency, such as token
/// balances, user properties etc.
pub fn persistent(&self) -> Persistent {
Persistent {
storage: self.clone(),
}
}

/// Storage for data that may stay in ledger only for a limited amount of
/// time.
///
/// Temporary storage is cheaper than Persistent storage.
///
/// Temporary entries will be removed from the ledger after their lifetime
/// ends. Removed entries can be created again, potentially with different
/// values.
///
/// This should be used for data that needs to only exist for a limited
/// period of time, such as oracle data, claimable balances, offer, etc.
pub fn temporary(&self) -> Temporary {
Temporary {
storage: self.clone(),
}
}

/// Storage for a **small amount** of persistent data associated with
/// the current contract's instance.
///
/// Storing a small amount of frequently used data in instance storage is
/// likely cheaper than storing it separately in Persistent storage.
///
/// Instance storage is tightly coupled with the contract instance: it will
/// be loaded from the ledger every time the contract instance itself is
/// loaded. It also won't appear in the ledger footprint. *All*
/// the data stored in the instance storage is read from ledger every time
/// the contract is used and it doesn't matter whether contract uses the
/// storage or not.
///
/// This has the same lifetime properties as Persistent storage, i.e.
/// the data semantically stays in the ledger forever and can be
/// expired/restored.
///
/// The amount of data that can be stored in the instance storage is limited
/// by the ledger entry size (a network-defined parameter). It is
/// in the order of 100 KB serialized.
///
/// This should be used for small data directly associated with the current
/// contract, such as its admin, configuration settings, tokens the contract
/// operates on etc. Do not use this with any data that can scale in
/// unbounded fashion (such as user balances).
pub fn instance(&self) -> Instance {
Instance {
storage: self.clone(),
}
}

/// Returns if there is a value stored for the given key in the currently
/// executing contracts storage.
#[inline(always)]
Expand Down Expand Up @@ -274,3 +325,49 @@ impl Temporary {
self.storage.remove(key, StorageType::Temporary)
}
}

pub struct Instance {
storage: Storage,
}

impl Instance {
pub fn has<K>(&self, key: &K) -> bool
where
K: IntoVal<Env, Val>,
{
self.storage.has(key, StorageType::Instance)
}

pub fn get<K, V>(&self, key: &K) -> Option<V>
where
V::Error: Debug,
K: IntoVal<Env, Val>,
V: TryFromVal<Env, Val>,
{
self.storage.get(key, StorageType::Instance)
}

pub fn set<K, V>(&self, key: &K, val: &V, flags: Option<u32>)
where
K: IntoVal<Env, Val>,
V: IntoVal<Env, Val>,
{
self.storage.set(key, val, StorageType::Instance, flags)
}

#[inline(always)]
pub fn remove<K>(&self, key: &K)
where
K: IntoVal<Env, Val>,
{
self.storage.remove(key, StorageType::Instance)
}

pub fn bump(&self, min_ledgers_to_live: u32) {
internal::Env::bump_current_contract_instance_and_code(
&self.storage.env,
min_ledgers_to_live.into(),
)
.unwrap_infallible();
}
}
6 changes: 1 addition & 5 deletions soroban-sdk/src/tests/budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ fn test_budget() {
let b = client.add();
e.budget().print();

// Here the cost of 5 for `MapEntry` is broken down into
// 2 - charge for adding the two elements
// 1 - charge for binary search of map with len == 0
// 2 - charge for binary search of map with len == 1
assert_eq!(e.budget().tracker(ContractCostType::MapEntry), (8, None));
assert_eq!(e.budget().tracker(ContractCostType::MapEntry), (13, None));
assert_eq!(b, map![&e, (1, 10), (2, 20)]);
}