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 read only storage access sketch #153

Draft
wants to merge 4 commits into
base: nightly
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions module-system/sov-modules-core/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::common::{AlignedVec, Prefix, Version, Witness};

mod cache;
mod codec;
mod read_access;
mod scratchpad;

pub use cache::*;
Expand Down
39 changes: 39 additions & 0 deletions module-system/sov-modules-core/src/storage/read_access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::{Storage, StorageKey, StorageValue};

pub trait StateReader {
/// Get a value from the storage.
fn get(&self, key: &StorageKey) -> Option<StorageValue>;
}

pub trait AsReadonly {
/// Readonly version of the access.
type Readonly;

/// Performs the conversion.
fn as_readonly(&self, level: Option<IsolationLevel>) -> Self::Readonly;
}

pub enum IsolationLevel {
/// Read isolation level.
ReadCommitted,
/// Write isolation level.
DirtyRead,
}

pub struct StateSnapshot<S: Storage> {
inner: S,
}

impl<S: Storage> StateSnapshot<S> {
pub fn new(inner: S) -> Self {
Self { inner }
}
}

impl<S: Storage> StateReader for StateSnapshot<S> {
fn get(&self, key: &StorageKey) -> Option<StorageValue> {
// TODO propagate witness?
let witness: S::Witness = Default::default();
self.inner.get(key, None, &witness)
}
}
18 changes: 18 additions & 0 deletions module-system/sov-modules-core/src/storage/scratchpad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use sov_rollup_interface::stf::Event;
use crate::archival_state::{ArchivalAccessoryWorkingSet, ArchivalJmtWorkingSet};
use crate::common::{GasMeter, Prefix};
use crate::module::{Context, Spec};
use crate::storage::read_access::{AsReadonly, IsolationLevel, StateSnapshot};
use crate::storage::{
CacheKey, CacheValue, EncodeKeyLike, NativeStorage, OrderedReadsAndWrites, StateCodec,
StateValueCodec, Storage, StorageInternalCache, StorageKey, StorageProof, StorageValue,
Expand Down Expand Up @@ -335,6 +336,23 @@ impl<C: Context> StateCheckpoint<C> {
}
}

impl<C: Context> AsReadonly for StateCheckpoint<C> {
type Readonly = StateSnapshot<<C as Spec>::Storage>;

fn as_readonly(&self, level: Option<IsolationLevel>) -> Self::Readonly {
// TODO think about uncommitted changes and how to handle them. There are three options
// 1. Return a snapshot of the current state, ignoring uncommitted changes
// 2. Return a snapshot of the current state, but also include uncommitted changes
// 3. Return an error

let level = level.unwrap_or_else(|| IsolationLevel::ReadCommitted);
match level {
IsolationLevel::ReadCommitted => StateSnapshot::new(self.delta.inner.clone()),
IsolationLevel::DirtyRead => StateSnapshot::new(self.delta.inner.clone()), // TODO clone cache?
}
}
}

/// This structure contains the read-write set and the events collected during the execution of a transaction.
/// There are two ways to convert it into a StateCheckpoint:
/// 1. By using the checkpoint() method, where all the changes are added to the underlying StateCheckpoint.
Expand Down
Loading