Skip to content

Commit

Permalink
storage: refactor and rocksdb implementation (#123)
Browse files Browse the repository at this point in the history
* refactor: move storage & redis into its own crates

* fix: import errors with redis

* feat: create skeleton for rocksdb

* feat: seperate out config into its own crate

* feat: seperate out da into its own crate

* fix: errors with moving crates around

* merge: diff patch

co-authored by: Ryan Ford <ryan@deltadevs.xyz>

* feat: replace todos with stuff in database

* fix: remove anyhow macro

* feat: refactor Digest and add basic tests

* fix: cargo clippy error

* fix: Digest hash refactor

* fix: remove packages

* fix: remove n

* fix: remove remove n

* fix: the only good thing the bot recommended

* fix: ci failings
  • Loading branch information
hhamud authored Sep 25, 2024
1 parent f7617c1 commit 797cb09
Show file tree
Hide file tree
Showing 26 changed files with 805 additions and 550 deletions.
616 changes: 200 additions & 416 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,22 @@ keywords = ["crypto", "key-transparency"]
readme = "README.md"

[workspace]
default-members = [
"crates/prism",
"crates/common",
"crates/errors",
"crates/storage",
"crates/da",
]

members = [
"crates/prism",
"crates/common",
"crates/nova",
"crates/groth16",
"crates/errors",
"crates/sp1",
"crates/storage",
"crates/da",
]
default-members = ["crates/prism", "crates/common", "crates/errors"]
resolver = "2"

[workspace.dependencies]
Expand Down Expand Up @@ -72,10 +79,14 @@ secp256k1 = "0.29.0"
sp1-zkvm = { version = "1.2.0" }
sp1-sdk = { version = "1.2.0" }
prism-common = { path = "crates/common" }
prism-storage = { path = "crates/storage" }
prism-nova = { path = "crates/nova" }
prism-da = { path = "crates/da" }
prism-errors = { path = "crates/errors" }
prism-main = { path = "crates/prism" }
prism-groth16 = { path = "crates/groth16" }
rocksdb = { version = "0.21.0", features = ["multi-threaded-cf"] }


[patch.crates-io]
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-sha2-v0.10.8" }
Expand Down
1 change: 0 additions & 1 deletion crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ repository.workspace = true
prism-errors.workspace = true
anyhow.workspace = true
bls12_381.workspace = true
borsh.workspace = true
jmt.workspace = true
serde.workspace = true
hex.workspace = true
Expand Down
13 changes: 6 additions & 7 deletions crates/common/src/hashchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{

use crate::{
operation::{CreateAccountArgs, Operation, PublicKey, ServiceChallengeInput},
tree::{hash, Digest, Hasher},
tree::{Digest, Hasher},
};

#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
Expand Down Expand Up @@ -280,12 +280,11 @@ pub struct HashchainEntry {

impl HashchainEntry {
pub fn new(operation: Operation, previous_hash: Digest) -> Self {
let hash = {
let mut data = Vec::new();
data.extend_from_slice(operation.to_string().as_bytes());
data.extend_from_slice(previous_hash.as_ref());
hash(&data)
};
let mut data = Vec::new();
data.extend_from_slice(operation.to_string().as_bytes());
data.extend_from_slice(previous_hash.as_ref());
let hash = Digest::hash(data);

Self {
hash,
previous_hash,
Expand Down
32 changes: 21 additions & 11 deletions crates/common/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use jmt::{
};
use prism_errors::DatabaseError;
use serde::{ser::SerializeTupleStruct, Deserialize, Serialize};
use std::convert::{From, Into};
use std::sync::Arc;

use crate::{
Expand Down Expand Up @@ -70,21 +71,30 @@ impl SimpleHasher for Hasher {
}
}

pub fn hash(data: &[u8]) -> Digest {
let mut hasher = Hasher::new();
hasher.update(data);
Digest(hasher.finalize())
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Copy)]
pub struct Digest([u8; 32]);
pub struct Digest(pub [u8; 32]);

impl Digest {
pub fn to_bytes(&self) -> [u8; 32] {
self.0
pub fn hash(data: impl AsRef<[u8]>) -> Self {
let mut hasher = Hasher::new();
hasher.update(data.as_ref());
Self(hasher.finalize())
}
}

// serializer and deserializer for rocksdb
// converts from bytearrays into digests
// padds it with zero if it is too small
impl <const N: usize> From<[u8; N]> for Digest {
fn from(value: [u8; N]) -> Self {
assert!(N <= 32, "Input array must not exceed 32 bytes");
let mut digest = [0u8; 32];
digest[..N].copy_from_slice(&value);
Self(digest)
}
}


// implementing it for now to get things to compile, curve choice will be made later
impl TryFrom<Digest> for Scalar {
type Error = anyhow::Error;
Expand Down Expand Up @@ -330,7 +340,7 @@ where
match operation {
Operation::AddKey(KeyOperationArgs { id, .. })
| Operation::RevokeKey(KeyOperationArgs { id, .. }) => {
let hashed_id = hash(id.as_bytes());
let hashed_id = Digest::hash(id);
let key_hash = KeyHash::with::<Hasher>(hashed_id);

let mut current_chain = self
Expand All @@ -351,7 +361,7 @@ where
service_id,
challenge,
}) => {
let hashed_id = hash(id.as_bytes());
let hashed_id = Digest::hash(id);
let key_hash = KeyHash::with::<Hasher>(hashed_id);

match &challenge {
Expand Down
26 changes: 26 additions & 0 deletions crates/da/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "prism-da"
version.workspace = true
authors.workspace = true
edition.workspace = true
description.workspace = true
homepage.workspace = true
repository.workspace = true
license.workspace = true
keywords.workspace = true
readme.workspace = true

[dependencies]
async-trait = { workspace = true }
serde = { workspace = true }
ed25519-dalek = { workspace = true }
tokio = { workspace = true }
bincode = { workspace = true }
hex = { workspace = true }
log = { workspace = true }
celestia-rpc = { workspace = true }
celestia-types = { workspace = true }
anyhow = { workspace = true }
prism-common = { workspace = true }
prism-errors = { workspace = true }
sp1-sdk = { workspace = true }
26 changes: 22 additions & 4 deletions crates/prism/src/da/celestia.rs → crates/da/src/celestia.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use crate::{
cfg::CelestiaConfig,
da::{DataAvailabilityLayer, FinalizedEpoch},
};
use crate::{DataAvailabilityLayer, FinalizedEpoch};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use celestia_rpc::{BlobClient, Client, HeaderClient};
use celestia_types::{nmt::Namespace, Blob, TxConfig};
use prism_common::operation::Operation;
use prism_errors::{DataAvailabilityError, GeneralError};
use serde::{Deserialize, Serialize};
use std::{
self,
sync::{
Expand All @@ -16,6 +14,7 @@ use std::{
},
};
use tokio::{sync::broadcast, task::spawn};
use log::{trace, debug, warn, error};

use bincode;

Expand All @@ -29,6 +28,25 @@ impl TryFrom<&Blob> for FinalizedEpoch {
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CelestiaConfig {
pub connection_string: String,
pub start_height: u64,
pub snark_namespace_id: String,
pub operation_namespace_id: Option<String>,
}

impl Default for CelestiaConfig {
fn default() -> Self {
CelestiaConfig {
connection_string: "ws://localhost:26658".to_string(),
start_height: 0,
snark_namespace_id: "00000000000000de1008".to_string(),
operation_namespace_id: Some("00000000000000de1009".to_string()),
}
}
}

pub struct CelestiaConnection {
pub client: celestia_rpc::Client,
pub snark_namespace: Namespace,
Expand Down
File renamed without changes.
75 changes: 75 additions & 0 deletions crates/da/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use anyhow::Result;
use async_trait::async_trait;
use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
use prism_common::{operation::Operation, tree::Digest};
use serde::{Deserialize, Serialize};
use sp1_sdk::SP1ProofWithPublicValues;
use tokio::sync::broadcast;

pub mod celestia;
pub mod consts;
pub mod memory;

// FinalizedEpoch is the data structure that represents the finalized epoch data, and is posted to the DA layer.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FinalizedEpoch {
pub height: u64,
pub prev_commitment: Digest,
pub current_commitment: Digest,
pub proof: SP1ProofWithPublicValues,
pub signature: Option<String>,
}

impl FinalizedEpoch {
pub fn insert_signature(&mut self, key: &SigningKey) {
let plaintext = bincode::serialize(&self).unwrap();
let signature = key.sign(&plaintext);
self.signature = Some(hex::encode(signature.to_bytes()));
}

pub fn verify_signature(&self, vk: VerifyingKey) -> Result<()> {
let epoch_without_signature = FinalizedEpoch {
height: self.height,
prev_commitment: self.prev_commitment,
current_commitment: self.current_commitment,
proof: self.proof.clone(),
signature: None,
};

let message = bincode::serialize(&epoch_without_signature)
.map_err(|e| anyhow::anyhow!("Failed to serialize epoch: {}", e))?;

let signature = self
.signature
.as_ref()
.ok_or_else(|| anyhow::anyhow!("No signature present"))?;

let signature_bytes = hex::decode(signature)
.map_err(|e| anyhow::anyhow!("Failed to decode signature: {}", e))?;

if signature_bytes.len() != 64 {
return Err(anyhow::anyhow!("Invalid signature length"));
}

let signature: Signature = signature_bytes
.as_slice()
.try_into()
.map_err(|_| anyhow::anyhow!("Invalid signature length"))?;

vk.verify_strict(&message, &signature)
.map_err(|e| anyhow::anyhow!("Signature verification failed: {}", e))?;
Ok(())
}
}

#[async_trait]
pub trait DataAvailabilityLayer: Send + Sync {
async fn get_latest_height(&self) -> Result<u64>;
async fn initialize_sync_target(&self) -> Result<u64>;
async fn get_finalized_epoch(&self, height: u64) -> Result<Option<FinalizedEpoch>>;
async fn submit_finalized_epoch(&self, epoch: FinalizedEpoch) -> Result<u64>;
async fn get_operations(&self, height: u64) -> Result<Vec<Operation>>;
async fn submit_operations(&self, operations: Vec<Operation>) -> Result<u64>;
async fn start(&self) -> Result<()>;
fn subscribe_to_heights(&self) -> broadcast::Receiver<u64>;
}
3 changes: 2 additions & 1 deletion crates/prism/src/da/memory.rs → crates/da/src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::da::{DataAvailabilityLayer, FinalizedEpoch};
use crate::{DataAvailabilityLayer, FinalizedEpoch};
use anyhow::Result;
use async_trait::async_trait;
use log::debug;
use prism_common::operation::Operation;
use std::{collections::VecDeque, sync::Arc};
use tokio::{
Expand Down
8 changes: 0 additions & 8 deletions crates/groth16/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ homepage.workspace = true
repository.workspace = true

[dependencies]
borsh = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
ed25519-dalek = { workspace = true }
bellman = { workspace = true }
bls12_381 = { workspace = true }
rand = { workspace = true }
hex = { workspace = true }
ff = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
indexed-merkle-tree = { workspace = true }
celestia-types = { workspace = true }
anyhow = { workspace = true }
jmt = { workspace = true }
sha2 = { workspace = true }
prism-common = { workspace = true }
prism-errors = { workspace = true }
9 changes: 0 additions & 9 deletions crates/nova/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@ homepage.workspace = true
repository.workspace = true

[dependencies]
borsh = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
base64 = { workspace = true }
num = { workspace = true }
bls12_381 = { workspace = true }
rand = { workspace = true }
hex = { workspace = true }
ff = { workspace = true }
thiserror = { workspace = true }
celestia-types = { workspace = true }
Expand All @@ -24,7 +18,4 @@ bellpepper-core = { workspace = true }
bellpepper = { workspace = true }
arecibo = { workspace = true }
itertools = { workspace = true }
sha2 = { workspace = true }
bincode = { workspace = true }
prism-common = { workspace = true, features = ["test_utils"] }
ed25519-dalek = { workspace = true }
10 changes: 3 additions & 7 deletions crates/prism/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ mock_prover = []

[dependencies]
axum = { workspace = true }
borsh = { workspace = true }
tower-http = { workspace = true }
utoipa = { workspace = true }
utoipa-swagger-ui = { workspace = true }
Expand All @@ -29,29 +28,26 @@ tokio = { workspace = true }
bellman = { workspace = true }
bincode = { workspace = true }
bls12_381 = { workspace = true }
rand = { workspace = true }
hex = { workspace = true }
ff = { workspace = true }
log = { workspace = true }
pretty_env_logger = { workspace = true }
clap = { workspace = true }
config = { workspace = true }
thiserror = { workspace = true }
indexed-merkle-tree = { workspace = true }
dotenvy = { workspace = true }
celestia-rpc = { workspace = true }
celestia-types = { workspace = true }
mockall = { workspace = true }
keystore-rs = { workspace = true }
toml = { workspace = true }
dirs = { workspace = true }
anyhow = { workspace = true }
jmt = { workspace = true }
sha2 = { workspace = true }
auto_impl = { workspace = true }
prism-common = { workspace = true, features = ["test_utils"] }
prism-storage = { workspace = true }
prism-errors = { workspace = true }
prism-da = { workspace = true }
sp1-sdk = { workspace = true }
rand = { workspace = true }

[dev-dependencies]
serial_test = "3.1.1"
Expand Down
Loading

0 comments on commit 797cb09

Please sign in to comment.