Skip to content

Commit

Permalink
Move KeyValueStore to the fuel-core-storage crate (#1566)
Browse files Browse the repository at this point in the history
Related work to the #1548.

The changes move `KeyValueStore` to the `fuel-core-storage` crate. It
requires updating the trait to use `StorageResult` instead of
`DatabaseResult`, causing according to changes in the downstream crates.

Also extracted `iter_all` functionality into a separate trait, because
it is not used by the state transition logic and more fancy stuff for
API.
  • Loading branch information
xgreenx authored Dec 20, 2023
1 parent 7e02c25 commit 2c0b93d
Show file tree
Hide file tree
Showing 19 changed files with 293 additions and 252 deletions.
7 changes: 0 additions & 7 deletions crates/database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use fuel_core_storage::Error as StorageError;
use fuel_core_types::services::executor::Error as ExecutorError;
use std::array::TryFromSliceError;

/// The error occurred during work with any of databases.
#[derive(Debug, derive_more::Display, derive_more::From)]
Expand Down Expand Up @@ -56,12 +55,6 @@ impl From<Error> for StorageError {
}
}

impl From<TryFromSliceError> for Error {
fn from(e: TryFromSliceError) -> Self {
Self::Other(anyhow::anyhow!(e))
}
}

impl From<Error> for ExecutorError {
fn from(e: Error) -> Self {
ExecutorError::StorageError(anyhow::anyhow!(StorageError::from(e)))
Expand Down
52 changes: 27 additions & 25 deletions crates/fuel-core/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::{
state::{
in_memory::memory_store::MemoryStore,
DataSource,
WriteOperation,
},
};
use fuel_core_chain_config::{
Expand All @@ -14,6 +13,11 @@ use fuel_core_chain_config::{
};
use fuel_core_storage::{
iter::IterDirection,
kv_store::{
StorageColumn,
Value,
WriteOperation,
},
transactional::{
StorageTransaction,
Transactional,
Expand Down Expand Up @@ -50,13 +54,11 @@ use strum::EnumCount;
pub use fuel_core_database::Error;
pub type Result<T> = core::result::Result<T, Error>;

type DatabaseError = Error;
type DatabaseResult<T> = Result<T>;

// TODO: Extract `Database` and all belongs into `fuel-core-database`.
#[cfg(feature = "rocksdb")]
use crate::state::rocks_db::RocksDb;
use crate::state::Value;
#[cfg(feature = "rocksdb")]
use std::path::Path;
#[cfg(feature = "rocksdb")]
Expand Down Expand Up @@ -160,7 +162,7 @@ impl Column {
}
}

impl crate::state::StorageColumn for Column {
impl StorageColumn for Column {
fn name(&self) -> &'static str {
self.into()
}
Expand Down Expand Up @@ -276,15 +278,15 @@ impl Database {
key: K,
column: Column,
value: &V,
) -> DatabaseResult<Option<R>> {
) -> StorageResult<Option<R>> {
let result = self.data.replace(
key.as_ref(),
column,
Arc::new(postcard::to_stdvec(value).map_err(|_| DatabaseError::Codec)?),
Arc::new(postcard::to_stdvec(value).map_err(|_| StorageError::Codec)?),
)?;
if let Some(previous) = result {
Ok(Some(
postcard::from_bytes(&previous).map_err(|_| DatabaseError::Codec)?,
postcard::from_bytes(&previous).map_err(|_| StorageError::Codec)?,
))
} else {
Ok(None)
Expand All @@ -296,7 +298,7 @@ impl Database {
key: K,
column: Column,
value: V,
) -> DatabaseResult<Option<Value>> {
) -> StorageResult<Option<Value>> {
self.data
.replace(key.as_ref(), column, Arc::new(value.as_ref().to_vec()))
}
Expand All @@ -305,22 +307,22 @@ impl Database {
&self,
column: Column,
set: S,
) -> DatabaseResult<()>
) -> StorageResult<()>
where
S: Iterator<Item = (K, V)>,
{
let set: Vec<_> = set
.map(|(key, value)| {
let value =
postcard::to_stdvec(&value).map_err(|_| DatabaseError::Codec)?;
postcard::to_stdvec(&value).map_err(|_| StorageError::Codec)?;

let tuple = (
key.as_ref().to_vec(),
column,
WriteOperation::Insert(Arc::new(value)),
);

Ok::<_, DatabaseError>(tuple)
Ok::<_, StorageError>(tuple)
})
.try_collect()?;

Expand All @@ -331,25 +333,25 @@ impl Database {
&self,
key: &[u8],
column: Column,
) -> DatabaseResult<Option<V>> {
) -> StorageResult<Option<V>> {
self.data
.take(key, column)?
.map(|val| postcard::from_bytes(&val).map_err(|_| DatabaseError::Codec))
.map(|val| postcard::from_bytes(&val).map_err(|_| StorageError::Codec))
.transpose()
}

fn take_raw(&self, key: &[u8], column: Column) -> DatabaseResult<Option<Value>> {
fn take_raw(&self, key: &[u8], column: Column) -> StorageResult<Option<Value>> {
self.data.take(key, column)
}
}

/// Read-only methods.
impl Database {
fn contains_key(&self, key: &[u8], column: Column) -> DatabaseResult<bool> {
fn contains_key(&self, key: &[u8], column: Column) -> StorageResult<bool> {
self.data.exists(key, column)
}

fn size_of_value(&self, key: &[u8], column: Column) -> DatabaseResult<Option<usize>> {
fn size_of_value(&self, key: &[u8], column: Column) -> StorageResult<Option<usize>> {
self.data.size_of_value(key, column)
}

Expand All @@ -358,11 +360,11 @@ impl Database {
key: &[u8],
column: Column,
buf: &mut [u8],
) -> DatabaseResult<Option<usize>> {
) -> StorageResult<Option<usize>> {
self.data.read(key, column, buf)
}

fn read_alloc(&self, key: &[u8], column: Column) -> DatabaseResult<Option<Vec<u8>>> {
fn read_alloc(&self, key: &[u8], column: Column) -> StorageResult<Option<Vec<u8>>> {
self.data
.get(key, column)
.map(|value| value.map(|value| value.deref().clone()))
Expand All @@ -372,18 +374,18 @@ impl Database {
&self,
key: &[u8],
column: Column,
) -> DatabaseResult<Option<V>> {
) -> StorageResult<Option<V>> {
self.data
.get(key, column)?
.map(|val| postcard::from_bytes(&val).map_err(|_| DatabaseError::Codec))
.map(|val| postcard::from_bytes(&val).map_err(|_| StorageError::Codec))
.transpose()
}

fn iter_all<K, V>(
&self,
column: Column,
direction: Option<IterDirection>,
) -> impl Iterator<Item = DatabaseResult<(K, V)>> + '_
) -> impl Iterator<Item = StorageResult<(K, V)>> + '_
where
K: From<Vec<u8>>,
V: DeserializeOwned,
Expand All @@ -395,7 +397,7 @@ impl Database {
&self,
column: Column,
prefix: Option<P>,
) -> impl Iterator<Item = DatabaseResult<(K, V)>> + '_
) -> impl Iterator<Item = StorageResult<(K, V)>> + '_
where
K: From<Vec<u8>>,
V: DeserializeOwned,
Expand All @@ -409,7 +411,7 @@ impl Database {
column: Column,
start: Option<S>,
direction: Option<IterDirection>,
) -> impl Iterator<Item = DatabaseResult<(K, V)>> + '_
) -> impl Iterator<Item = StorageResult<(K, V)>> + '_
where
K: From<Vec<u8>>,
V: DeserializeOwned,
Expand All @@ -424,7 +426,7 @@ impl Database {
prefix: Option<P>,
start: Option<S>,
direction: Option<IterDirection>,
) -> impl Iterator<Item = DatabaseResult<(K, V)>> + '_
) -> impl Iterator<Item = StorageResult<(K, V)>> + '_
where
K: From<Vec<u8>>,
V: DeserializeOwned,
Expand All @@ -442,7 +444,7 @@ impl Database {
val.and_then(|(key, value)| {
let key = K::from(key);
let value: V =
postcard::from_bytes(&value).map_err(|_| DatabaseError::Codec)?;
postcard::from_bytes(&value).map_err(|_| StorageError::Codec)?;
Ok((key, value))
})
})
Expand Down
7 changes: 3 additions & 4 deletions crates/fuel-core/src/database/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::database::{
Column,
Database,
Error as DatabaseError,
Result as DatabaseResult,
};
use fuel_core_storage::{
iter::IterDirection,
Expand Down Expand Up @@ -161,7 +160,7 @@ impl Database {
&self,
start: Option<BlockHeight>,
direction: IterDirection,
) -> impl Iterator<Item = DatabaseResult<(BlockHeight, BlockId)>> + '_ {
) -> impl Iterator<Item = StorageResult<(BlockHeight, BlockId)>> + '_ {
let start = start.map(|b| b.to_bytes());
self.iter_all_by_start::<Vec<u8>, BlockId, _>(
Column::FuelBlockSecondaryKeyBlockHeights,
Expand All @@ -178,7 +177,7 @@ impl Database {
})
}

pub fn ids_of_genesis_block(&self) -> DatabaseResult<(BlockHeight, BlockId)> {
pub fn ids_of_genesis_block(&self) -> StorageResult<(BlockHeight, BlockId)> {
self.iter_all(
Column::FuelBlockSecondaryKeyBlockHeights,
Some(IterDirection::Forward),
Expand All @@ -192,7 +191,7 @@ impl Database {
})
}

pub fn ids_of_latest_block(&self) -> DatabaseResult<Option<(BlockHeight, BlockId)>> {
pub fn ids_of_latest_block(&self) -> StorageResult<Option<(BlockHeight, BlockId)>> {
let ids = self
.iter_all::<Vec<u8>, BlockId>(
Column::FuelBlockSecondaryKeyBlockHeights,
Expand Down
13 changes: 5 additions & 8 deletions crates/fuel-core/src/database/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use crate::database::{
storage::DatabaseColumn,
Column,
Database,
Error as DatabaseError,
Result as DatabaseResult,
};
use fuel_core_chain_config::CoinConfig;
use fuel_core_storage::{
Expand Down Expand Up @@ -110,7 +108,7 @@ impl Database {
owner: &Address,
start_coin: Option<UtxoId>,
direction: Option<IterDirection>,
) -> impl Iterator<Item = DatabaseResult<UtxoId>> + '_ {
) -> impl Iterator<Item = StorageResult<UtxoId>> + '_ {
self.iter_all_filtered::<Vec<u8>, bool, _, _>(
Column::OwnedCoins,
Some(*owner),
Expand Down Expand Up @@ -138,14 +136,13 @@ impl Database {
Ok(coin)
}

pub fn get_coin_config(&self) -> DatabaseResult<Option<Vec<CoinConfig>>> {
pub fn get_coin_config(&self) -> StorageResult<Option<Vec<CoinConfig>>> {
let configs = self
.iter_all::<Vec<u8>, CompressedCoin>(Column::Coins, None)
.map(|raw_coin| -> DatabaseResult<CoinConfig> {
.map(|raw_coin| -> StorageResult<CoinConfig> {
let coin = raw_coin?;

let byte_id =
Bytes32::new(coin.0[..32].try_into().map_err(DatabaseError::from)?);
let byte_id = Bytes32::new(coin.0[..32].try_into()?);
let output_index = coin.0[32];

Ok(CoinConfig {
Expand All @@ -159,7 +156,7 @@ impl Database {
asset_id: coin.1.asset_id,
})
})
.collect::<DatabaseResult<Vec<CoinConfig>>>()?;
.collect::<StorageResult<Vec<CoinConfig>>>()?;

Ok(Some(configs))
}
Expand Down
25 changes: 9 additions & 16 deletions crates/fuel-core/src/database/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use crate::database::{
storage::DatabaseColumn,
Column,
Database,
Error as DatabaseError,
Result as DatabaseResult,
};
use fuel_core_chain_config::ContractConfig;
use fuel_core_storage::{
Expand Down Expand Up @@ -90,7 +88,7 @@ impl StorageMutate<ContractsRawCode> for Database {

impl StorageSize<ContractsRawCode> for Database {
fn size_of_value(&self, key: &ContractId) -> Result<Option<usize>, Self::Error> {
Ok(self.size_of_value(key.as_ref(), Column::ContractsRawCode)?)
self.size_of_value(key.as_ref(), Column::ContractsRawCode)
}
}

Expand All @@ -100,11 +98,11 @@ impl StorageRead<ContractsRawCode> for Database {
key: &ContractId,
buf: &mut [u8],
) -> Result<Option<usize>, Self::Error> {
Ok(self.read(key.as_ref(), Column::ContractsRawCode, buf)?)
self.read(key.as_ref(), Column::ContractsRawCode, buf)
}

fn read_alloc(&self, key: &ContractId) -> Result<Option<Vec<u8>>, Self::Error> {
Ok(self.read_alloc(key.as_ref(), Column::ContractsRawCode)?)
self.read_alloc(key.as_ref(), Column::ContractsRawCode)
}
}

Expand Down Expand Up @@ -142,7 +140,7 @@ impl Database {
Column::ContractsState,
Some(contract_id.as_ref()),
)
.map(|res| -> DatabaseResult<(Bytes32, Bytes32)> {
.map(|res| -> StorageResult<(Bytes32, Bytes32)> {
let safe_res = res?;

// We don't need to store ContractId which is the first 32 bytes of this
Expand All @@ -152,7 +150,7 @@ impl Database {
Ok((state_key, safe_res.1))
})
.filter(|val| val.is_ok())
.collect::<DatabaseResult<Vec<(Bytes32, Bytes32)>>>()?,
.collect::<StorageResult<Vec<(Bytes32, Bytes32)>>>()?,
);

let balances = Some(
Expand All @@ -163,9 +161,7 @@ impl Database {
.map(|res| {
let safe_res = res?;

let asset_id = AssetId::new(
safe_res.0[32..].try_into().map_err(DatabaseError::from)?,
);
let asset_id = AssetId::new(safe_res.0[32..].try_into()?);

Ok((asset_id, safe_res.1))
})
Expand All @@ -191,7 +187,7 @@ impl Database {
contract: ContractId,
start_asset: Option<AssetId>,
direction: Option<IterDirection>,
) -> impl Iterator<Item = DatabaseResult<(AssetId, Word)>> + '_ {
) -> impl Iterator<Item = StorageResult<(AssetId, Word)>> + '_ {
self.iter_all_filtered::<Vec<u8>, Word, _, _>(
Column::ContractsAssets,
Some(contract),
Expand All @@ -209,11 +205,8 @@ impl Database {
let configs = self
.iter_all::<Vec<u8>, Word>(Column::ContractsRawCode, None)
.map(|raw_contract_id| -> StorageResult<ContractConfig> {
let contract_id = ContractId::new(
raw_contract_id.unwrap().0[..32]
.try_into()
.map_err(DatabaseError::from)?,
);
let contract_id =
ContractId::new(raw_contract_id.unwrap().0[..32].try_into()?);
self.get_contract_config_by_id(contract_id)
})
.collect::<StorageResult<Vec<ContractConfig>>>()?;
Expand Down
Loading

0 comments on commit 2c0b93d

Please sign in to comment.