use std::fmt::Display;
use std::sync::Arc;
use borsh::{BorshDeserialize, BorshSerialize};
use hex;
use jmt::Version;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use sov_first_read_last_write_cache::{CacheKey, CacheValue};
use crate::codec::{EncodeKeyLike, StateValueCodec};
use crate::internal_cache::OrderedReadsAndWrites;
use crate::utils::AlignedVec;
use crate::witness::Witness;
use crate::Prefix;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize)]
pub struct StorageKey {
key: Arc<Vec<u8>>,
}
impl From<CacheKey> for StorageKey {
fn from(cache_key: CacheKey) -> Self {
Self { key: cache_key.key }
}
}
impl StorageKey {
pub fn key(&self) -> Arc<Vec<u8>> {
self.key.clone()
}
pub fn to_cache_key(&self) -> CacheKey {
CacheKey {
key: self.key.clone(),
}
}
pub fn into_cache_key(self) -> CacheKey {
CacheKey { key: self.key }
}
}
impl AsRef<Vec<u8>> for StorageKey {
fn as_ref(&self) -> &Vec<u8> {
&self.key
}
}
impl Display for StorageKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:x?}", hex::encode(self.key().as_ref()))
}
}
impl StorageKey {
pub fn new<K, Q, KC>(prefix: &Prefix, key: &Q, codec: &KC) -> Self
where
KC: EncodeKeyLike<Q, K>,
Q: ?Sized,
{
let encoded_key = codec.encode_key_like(key);
let encoded_key = AlignedVec::new(encoded_key);
let full_key = Vec::<u8>::with_capacity(prefix.len() + encoded_key.len());
let mut full_key = AlignedVec::new(full_key);
full_key.extend(prefix.as_aligned_vec());
full_key.extend(&encoded_key);
Self {
key: Arc::new(full_key.into_inner()),
}
}
pub fn singleton(prefix: &Prefix) -> Self {
Self {
key: Arc::new(prefix.as_aligned_vec().clone().into_inner()),
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize, Default,
)]
pub struct StorageValue {
value: Arc<Vec<u8>>,
}
impl From<CacheValue> for StorageValue {
fn from(cache_value: CacheValue) -> Self {
Self {
value: cache_value.value,
}
}
}
impl From<Vec<u8>> for StorageValue {
fn from(value: Vec<u8>) -> Self {
Self {
value: Arc::new(value),
}
}
}
impl StorageValue {
pub fn new<V, VC>(value: &V, codec: &VC) -> Self
where
VC: StateValueCodec<V>,
{
let encoded_value = codec.encode_value(value);
Self {
value: Arc::new(encoded_value),
}
}
pub fn value(&self) -> &[u8] {
&self.value
}
pub fn into_cache_value(self) -> CacheValue {
CacheValue { value: self.value }
}
}
#[derive(Debug, Clone, Serialize, Deserialize, BorshDeserialize, BorshSerialize)]
pub struct StorageProof<P> {
pub key: StorageKey,
pub value: Option<StorageValue>,
pub proof: P,
}
pub trait Storage: Clone {
type Witness: Witness + Send + Sync;
type RuntimeConfig;
type Proof: Serialize
+ DeserializeOwned
+ core::fmt::Debug
+ Clone
+ BorshSerialize
+ BorshDeserialize;
type Root: Serialize
+ DeserializeOwned
+ core::fmt::Debug
+ Clone
+ BorshSerialize
+ BorshDeserialize
+ Eq
+ AsRef<[u8]>
+ Into<[u8; 32]>;
type StateUpdate;
fn with_config(config: Self::RuntimeConfig) -> Result<Self, anyhow::Error>;
fn get(&self, key: &StorageKey, witness: &Self::Witness) -> Option<StorageValue>;
fn get_accessory(&self, _key: &StorageKey) -> Option<StorageValue> {
None
}
fn compute_state_update(
&self,
state_accesses: OrderedReadsAndWrites,
witness: &Self::Witness,
) -> Result<(Self::Root, Self::StateUpdate), anyhow::Error>;
fn commit(&self, node_batch: &Self::StateUpdate, accessory_update: &OrderedReadsAndWrites);
fn validate_and_commit(
&self,
state_accesses: OrderedReadsAndWrites,
witness: &Self::Witness,
) -> Result<Self::Root, anyhow::Error> {
Self::validate_and_commit_with_accessory_update(
self,
state_accesses,
witness,
&Default::default(),
)
}
fn validate_and_commit_with_accessory_update(
&self,
state_accesses: OrderedReadsAndWrites,
witness: &Self::Witness,
accessory_update: &OrderedReadsAndWrites,
) -> Result<Self::Root, anyhow::Error> {
let (root_hash, node_batch) = self.compute_state_update(state_accesses, witness)?;
self.commit(&node_batch, accessory_update);
Ok(root_hash)
}
fn open_proof(
state_root: Self::Root,
proof: StorageProof<Self::Proof>,
) -> Result<(StorageKey, Option<StorageValue>), anyhow::Error>;
fn is_empty(&self) -> bool;
}
impl From<&str> for StorageKey {
fn from(key: &str) -> Self {
Self {
key: Arc::new(key.as_bytes().to_vec()),
}
}
}
impl From<&str> for StorageValue {
fn from(value: &str) -> Self {
Self {
value: Arc::new(value.as_bytes().to_vec()),
}
}
}
pub trait NativeStorage: Storage {
fn get_with_proof(&self, key: StorageKey) -> StorageProof<Self::Proof>;
fn get_root_hash(&self, version: Version) -> Result<Self::Root, anyhow::Error>;
}