forked from Sovereign-Labs/sovereign-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ZkStorage
implementation (Sovereign-Labs#51)
- Loading branch information
Showing
10 changed files
with
317 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use crate::storage::{StorageKey, StorageValue}; | ||
use first_read_last_write_cache::{ | ||
cache::{self, CacheLog}, | ||
CacheValue, | ||
}; | ||
use std::{cell::RefCell, rc::Rc}; | ||
|
||
/// `ValueReader` Reads a value from an external data source. | ||
pub trait ValueReader { | ||
fn read_value(&self, key: StorageKey) -> Option<StorageValue>; | ||
} | ||
|
||
/// Caches reads and writes for a (key, value) pair. On the first read the value is fetched | ||
/// from an external source represented by the `ValueReader` trait. On following reads, | ||
/// the cache checks if the value we read was inserted before. | ||
#[derive(Default, Clone)] | ||
pub(crate) struct StorageInternalCache { | ||
pub(crate) cache: Rc<RefCell<CacheLog>>, | ||
} | ||
|
||
impl StorageInternalCache { | ||
/// Gets a value from the cache or reads it from the provided `ValueReader`. | ||
pub(crate) fn get_or_fetch<VR: ValueReader>( | ||
&self, | ||
key: StorageKey, | ||
value_reader: &VR, | ||
) -> Option<StorageValue> { | ||
let cache_key = key.clone().as_cache_key(); | ||
let cache_value = self.cache.borrow().get_value(&cache_key); | ||
|
||
match cache_value { | ||
cache::ValueExists::Yes(cache_value_exists) => { | ||
self.cache | ||
.borrow_mut() | ||
.add_read(cache_key, cache_value_exists.clone()) | ||
// It is ok to panic here, we must guarantee that the cache is consistent. | ||
.unwrap_or_else(|e| panic!("Inconsistent read from the cache: {e:?}")); | ||
|
||
cache_value_exists.value.map(|value| StorageValue { value }) | ||
} | ||
// If the value does not exist in the cache, then fetch it from an external source. | ||
cache::ValueExists::No => value_reader.read_value(key), | ||
} | ||
} | ||
|
||
pub(crate) fn set(&mut self, key: StorageKey, value: StorageValue) { | ||
let cache_key = key.as_cache_key(); | ||
let cache_value = value.as_cache_value(); | ||
self.cache.borrow_mut().add_write(cache_key, cache_value); | ||
} | ||
|
||
pub(crate) fn delete(&mut self, key: StorageKey) { | ||
let cache_key = key.as_cache_key(); | ||
self.cache | ||
.borrow_mut() | ||
.add_write(cache_key, CacheValue::empty()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,36 @@ | ||
use std::{cell::RefCell, rc::Rc}; | ||
|
||
use crate::storage::{Storage, StorageKey, StorageValue}; | ||
use first_read_last_write_cache::{ | ||
cache::{self, CacheLog}, | ||
CacheValue, | ||
use crate::{ | ||
internal_cache::{StorageInternalCache, ValueReader}, | ||
storage::{GenericStorage, StorageKey, StorageValue}, | ||
}; | ||
use first_read_last_write_cache::cache::{CacheLog, FirstReads}; | ||
use jellyfish_merkle_generic::Version; | ||
|
||
// Storage backed by JMT. | ||
#[derive(Default, Clone)] | ||
pub struct JmtStorage { | ||
// Caches first read and last write for a particular key. | ||
cache: Rc<RefCell<CacheLog>>, | ||
pub struct JmtDb { | ||
_version: Version, | ||
} | ||
|
||
impl Storage for JmtStorage { | ||
fn get(&self, key: StorageKey) -> Option<StorageValue> { | ||
let cache_key = key.as_cache_key(); | ||
let cache_value = self.cache.borrow().get_value(&cache_key); | ||
impl ValueReader for JmtDb { | ||
fn read_value(&self, _key: StorageKey) -> Option<StorageValue> { | ||
todo!() | ||
} | ||
} | ||
|
||
match cache_value { | ||
cache::ExistsInCache::Yes(cache_value_exists) => { | ||
self.cache | ||
.borrow_mut() | ||
.add_read(cache_key, cache_value_exists.clone()) | ||
// It is ok to panic here, we must guarantee that the cache is consistent. | ||
.unwrap_or_else(|e| panic!("Inconsistent read from the cache: {e:?}")); | ||
/// Storage backed by JmtDb. | ||
pub type JmtStorage = GenericStorage<JmtDb>; | ||
|
||
cache_value_exists.value.map(|value| StorageValue { value }) | ||
} | ||
// TODO If the value does not exist in the cache, then fetch it from the JMT. | ||
cache::ExistsInCache::No => todo!(), | ||
impl JmtStorage { | ||
/// Creates a new JmtStorage. | ||
pub fn new(jmt: JmtDb) -> Self { | ||
Self { | ||
internal_cache: StorageInternalCache::default(), | ||
value_reader: jmt, | ||
} | ||
} | ||
|
||
fn set(&mut self, key: StorageKey, value: StorageValue) { | ||
let cache_key = key.as_cache_key(); | ||
let cache_value = value.as_cache_value(); | ||
self.cache.borrow_mut().add_write(cache_key, cache_value); | ||
} | ||
|
||
fn delete(&mut self, key: StorageKey) { | ||
let cache_key = key.as_cache_key(); | ||
self.cache | ||
.borrow_mut() | ||
.add_write(cache_key, CacheValue::empty()); | ||
/// Gets the first reads from the JmtStorage. | ||
pub fn get_first_reads(&self) -> FirstReads { | ||
let cache: &CacheLog = &self.internal_cache.cache.borrow(); | ||
cache.get_first_reads() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.