Skip to content

Commit

Permalink
Move trait definitions from fuel-data (#1)
Browse files Browse the repository at this point in the history
Include `Storage` and `MerkleStorage` to be used by `fuel-vm` and
`fuel-merkle`.

This split is done to not mix the VM types with the merkle tree
definitions.
  • Loading branch information
vlopes11 authored and xgreenx committed Dec 20, 2022
1 parent 6df0e98 commit 7d3051e
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 1 deletion.
49 changes: 49 additions & 0 deletions fuel-storage/.github/workflows/cargo_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Compile and Test

on:
push:
branches:
- master
tags:
- v*
pull_request:

env:
CARGO_TERM_COLOR: always
CARGO_NET_GIT_FETCH_WITH_CLI: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Install rustfmt
run: rustup component add rustfmt

- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all --verbose -- --check

- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --verbose

- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
9 changes: 9 additions & 0 deletions fuel-storage/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "fuel-storage"
version = "0.1.0"
authors = ["Victor Lopez <victor.lopez@fuel.sh>"]
edition = "2018"
repository = "https://github.com/FuelLabs/fuel-storage"
description = "Storage traits for Fuel storage-backed data structures."

[dependencies]
3 changes: 2 additions & 1 deletion fuel-storage/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# fuel-storage
# Fuel Storage

Storage traits for Fuel storage-backed data structures.
129 changes: 129 additions & 0 deletions fuel-storage/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use std::borrow::Cow;
use std::error::Error;
use std::ops::{Deref, DerefMut};

/// Merkle root alias type
pub type MerkleRoot = [u8; 32];

/// Base map trait for Fuel infrastructure
///
/// Generics:
///
/// - K: Key that maps to a value
/// - V: Stored value
pub trait Storage<K, V>
where
V: Clone,
{
/// Error implementation of the storage functions
type Error: Error;

/// Append `K->V` mapping to the storage.
///
/// If `K` was already mappped to a value, return the replaced value as `Ok(Some(V))`. Return
/// `Ok(None)` otherwise.
fn insert(&mut self, key: &K, value: &V) -> Result<Option<V>, Self::Error>;

/// Remove `K->V` mapping from the storage.
///
/// Return `Ok(Some(V))` if the value was present. If the key wasn't found, return
/// `Ok(None)`.
fn remove(&mut self, key: &K) -> Result<Option<V>, Self::Error>;

/// Retrieve `Cow<V>` such as `K->V`.
fn get<'a>(&'a self, key: &K) -> Result<Option<Cow<'a, V>>, Self::Error>;

/// Return `true` if there is a `K` mapping to a value in the storage.
fn contains_key(&self, key: &K) -> Result<bool, Self::Error>;
}

impl<K, V, S> Storage<K, V> for &mut S
where
V: Clone,
S: Storage<K, V>,
{
type Error = S::Error;

fn insert(&mut self, key: &K, value: &V) -> Result<Option<V>, S::Error> {
<S as Storage<K, V>>::insert(self.deref_mut(), key, value)
}

fn remove(&mut self, key: &K) -> Result<Option<V>, S::Error> {
<S as Storage<K, V>>::remove(self.deref_mut(), key)
}

fn get(&self, key: &K) -> Result<Option<Cow<'_, V>>, S::Error> {
<S as Storage<K, V>>::get(self.deref(), key)
}

fn contains_key(&self, key: &K) -> Result<bool, S::Error> {
<S as Storage<K, V>>::contains_key(self.deref(), key)
}
}

/// Base trait for Fuel Merkle storage
///
/// Generics:
///
/// - P: Domain of the merkle tree
/// - K: Key that maps to a value
/// - V: Stored value
pub trait MerkleStorage<P, K, V>
where
V: Clone,
{
/// Error implementation of the merkle storage functions
type Error: Error;

/// Append `P->K->V` mapping to the storage.
///
/// If `K` was already mappped to a value, return the replaced value as `Ok(Some(V))`. Return
/// `Ok(None)` otherwise.
fn insert(&mut self, parent: &P, key: &K, value: &V) -> Result<Option<V>, Self::Error>;

/// Remove `P->K->V` mapping from the storage.
///
/// Return `Ok(Some(V))` if the value was present. If the key wasn't found, return
/// `Ok(None)`.
fn remove(&mut self, parent: &P, key: &K) -> Result<Option<V>, Self::Error>;

/// Retrieve `Cow<V>` such as `P->K->V`.
fn get<'a>(&'a self, parent: &P, key: &K) -> Result<Option<Cow<'a, V>>, Self::Error>;

/// Return `true` if there is a `P->K` mapping to a value in the storage.
fn contains_key(&self, parent: &P, key: &K) -> Result<bool, Self::Error>;

/// Return the merkle root of the domain of `P`.
///
/// The cryptographic primitive is an arbitrary choice of the implementor and this trait won't
/// impose any restrictions to that.
fn root(&mut self, parent: &P) -> Result<MerkleRoot, Self::Error>;
}

impl<P, K, V, S> MerkleStorage<P, K, V> for &mut S
where
V: Clone,
S: MerkleStorage<P, K, V>,
{
type Error = S::Error;

fn insert(&mut self, parent: &P, key: &K, value: &V) -> Result<Option<V>, S::Error> {
<S as MerkleStorage<P, K, V>>::insert(self.deref_mut(), parent, key, value)
}

fn remove(&mut self, parent: &P, key: &K) -> Result<Option<V>, S::Error> {
<S as MerkleStorage<P, K, V>>::remove(self.deref_mut(), parent, key)
}

fn get(&self, parent: &P, key: &K) -> Result<Option<Cow<'_, V>>, S::Error> {
<S as MerkleStorage<P, K, V>>::get(self.deref(), parent, key)
}

fn contains_key(&self, parent: &P, key: &K) -> Result<bool, S::Error> {
<S as MerkleStorage<P, K, V>>::contains_key(self.deref(), parent, key)
}

fn root(&mut self, parent: &P) -> Result<MerkleRoot, S::Error> {
<S as MerkleStorage<P, K, V>>::root(self.deref_mut(), parent)
}
}

0 comments on commit 7d3051e

Please sign in to comment.