Skip to content

Commit

Permalink
refactor: use only prism-serde for base64 + hex
Browse files Browse the repository at this point in the history
  • Loading branch information
jns-ps committed Dec 11, 2024
1 parent 9e8af18 commit b6c08ac
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 135 deletions.
6 changes: 0 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ prism-keys.workspace = true
# serde
prism-serde.workspace = true
serde.workspace = true
hex.workspace = true
bincode.workspace = true

# celestia
celestia-types.workspace = true
Expand Down
49 changes: 28 additions & 21 deletions crates/common/src/digest.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
use anyhow::{anyhow, Result};
use anyhow::Result;
use jmt::RootHash;
use serde::{Deserialize, Serialize};

use crate::hasher::Hasher;
use prism_serde::raw_or_hex_fixed;
use prism_serde::{
base64::FromBase64,
hex::{FromHex, ToHex},
raw_or_hex,
};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Copy)]
pub struct Digest(#[serde(with = "raw_or_hex_fixed")] pub [u8; 32]);
pub struct Digest(#[serde(with = "raw_or_hex")] pub [u8; 32]);

impl Digest {
pub const fn new(bytes: [u8; 32]) -> Self {
Digest(bytes)
}

pub fn hash(data: impl AsRef<[u8]>) -> Self {
let mut hasher = Hasher::new();
hasher.update(data.as_ref());
Expand All @@ -26,6 +34,10 @@ impl Digest {
pub const fn zero() -> Self {
Self([0u8; 32])
}

pub fn to_bytes(&self) -> [u8; 32] {
self.0
}
}

// serializer and deserializer for rocksdb
Expand Down Expand Up @@ -58,29 +70,24 @@ impl AsRef<[u8]> for Digest {
}
}

impl std::fmt::Display for Digest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_hex())
}
}
impl FromHex for Digest {
type Error = anyhow::Error;

impl Digest {
pub const fn new(bytes: [u8; 32]) -> Self {
Digest(bytes)
fn from_hex<T: AsRef<[u8]>>(hex: T) -> std::result::Result<Self, Self::Error> {
Ok(Self(<[u8; 32]>::from_hex(hex)?))
}
}

pub fn from_hex(hex_str: &str) -> Result<Self> {
let mut bytes = [0u8; 32];
hex::decode_to_slice(hex_str, &mut bytes)
.map_err(|e| anyhow!(format!("Invalid Format: {e}")))?;
Ok(Digest(bytes))
}
impl FromBase64 for Digest {
type Error = anyhow::Error;

pub fn to_hex(&self) -> String {
hex::encode(self.0)
fn from_base64<T: AsRef<[u8]>>(base64: T) -> Result<Self, Self::Error> {
Ok(Self(<[u8; 32]>::from_base64(base64)?))
}
}

pub fn to_bytes(&self) -> [u8; 32] {
self.0
impl std::fmt::Display for Digest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_hex())
}
}
2 changes: 0 additions & 2 deletions crates/da/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ async-trait = { workspace = true }
serde = { workspace = true }
ed25519-consensus = { workspace = true }
tokio = { workspace = true }
bincode = { workspace = true }
hex = { workspace = true }
log = { workspace = true }
celestia-rpc = { workspace = true }
celestia-types = { workspace = true }
Expand Down
7 changes: 5 additions & 2 deletions crates/da/src/celestia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use celestia_types::{nmt::Namespace, Blob, TxConfig};
use log::{debug, error, trace, warn};
use prism_common::transaction::Transaction;
use prism_errors::{DataAvailabilityError, GeneralError};
use prism_serde::binary::{FromBinary, ToBinary};
use prism_serde::{
binary::{FromBinary, ToBinary},
hex::FromHex,
};
use serde::{Deserialize, Serialize};
use std::{
self,
Expand Down Expand Up @@ -88,7 +91,7 @@ impl CelestiaConnection {
}

fn create_namespace(namespace_hex: &str) -> Result<Namespace> {
let decoded_hex = hex::decode(namespace_hex).context(format!(
let decoded_hex = Vec::<u8>::from_hex(namespace_hex).context(format!(
"Failed to decode namespace hex '{}'",
namespace_hex
))?;
Expand Down
6 changes: 3 additions & 3 deletions crates/da/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::Result;
use async_trait::async_trait;
use ed25519_consensus::{Signature, SigningKey, VerificationKey as VerifyingKey};
use prism_common::{digest::Digest, transaction::Transaction};
use prism_serde::binary::ToBinary;
use prism_serde::{binary::ToBinary, hex::ToHex};
use serde::{Deserialize, Serialize};
use sp1_sdk::SP1ProofWithPublicValues;
use tokio::sync::broadcast;
Expand All @@ -25,7 +25,7 @@ impl FinalizedEpoch {
pub fn insert_signature(&mut self, key: &SigningKey) {
let plaintext = self.encode_to_bytes().unwrap();
let signature = key.sign(&plaintext);
self.signature = Some(hex::encode(signature.to_bytes()));
self.signature = Some(signature.to_bytes().to_hex());
}

pub fn verify_signature(&self, vk: VerifyingKey) -> Result<()> {
Expand All @@ -44,7 +44,7 @@ impl FinalizedEpoch {
let signature =
self.signature.as_ref().ok_or_else(|| anyhow::anyhow!("No signature present"))?;

let signature_bytes = hex::decode(signature)
let signature_bytes = Vec::<u8>::from_hex(signature)

Check failure on line 47 in crates/da/src/lib.rs

View workflow job for this annotation

GitHub Actions / unused dependencies

no function or associated item named `from_hex` found for struct `Vec<u8>` in the current scope

Check failure on line 47 in crates/da/src/lib.rs

View workflow job for this annotation

GitHub Actions / unit-test

no function or associated item named `from_hex` found for struct `Vec<u8>` in the current scope

Check failure on line 47 in crates/da/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

no function or associated item named `from_hex` found for struct `std::vec::Vec<u8>` in the current scope

Check failure on line 47 in crates/da/src/lib.rs

View workflow job for this annotation

GitHub Actions / integration-test

no function or associated item named `from_hex` found for struct `Vec<u8>` in the current scope
.map_err(|e| anyhow::anyhow!("Failed to decode signature: {}", e))?;

if signature_bytes.len() != 64 {
Expand Down
8 changes: 4 additions & 4 deletions crates/keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub use verifying_keys::*;
#[cfg(test)]
mod tests {
use super::*;
use base64::{engine::general_purpose::STANDARD as engine, Engine as _};
use ed25519_consensus::SigningKey as Ed25519SigningKey;
use prism_serde::base64::ToBase64;
use rand::rngs::OsRng;
use secp256k1::SecretKey as Secp256k1SigningKey;

Expand Down Expand Up @@ -101,7 +101,7 @@ mod tests {
fn test_verifying_key_from_string_ed25519() {
let original_key: VerifyingKey =
SigningKey::Ed25519(Box::new(Ed25519SigningKey::new(OsRng))).into();
let encoded = engine.encode(original_key.to_bytes());
let encoded = original_key.to_bytes().to_base64();

let result = VerifyingKey::try_from(encoded);
assert!(result.is_ok());
Expand All @@ -114,7 +114,7 @@ mod tests {
fn test_verifying_key_from_string_secp256k1() {
let original_key: VerifyingKey =
SigningKey::Secp256k1(Secp256k1SigningKey::new(&mut OsRng)).into();
let encoded = engine.encode(original_key.to_bytes());
let encoded = original_key.to_bytes().to_base64();

let result = VerifyingKey::try_from(encoded);
assert!(result.is_ok());
Expand All @@ -126,7 +126,7 @@ mod tests {
#[test]
fn test_verifying_key_from_string_invalid_length() {
let invalid_bytes: [u8; 31] = [1; 31];
let encoded = engine.encode(invalid_bytes);
let encoded = invalid_bytes.to_base64();

let result = VerifyingKey::try_from(encoded);
assert!(result.is_err());
Expand Down
27 changes: 18 additions & 9 deletions crates/keys/src/verifying_keys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use anyhow::{anyhow, bail, Result};
use base64::{engine::general_purpose::STANDARD as engine, Engine as _};
use ed25519_consensus::{SigningKey as Ed25519SigningKey, VerificationKey as Ed25519VerifyingKey};
use p256::ecdsa::{
signature::DigestVerifier, SigningKey as Secp256r1SigningKey,
Expand All @@ -18,7 +17,10 @@ use std::{
};

use crate::{Signature, SigningKey};
use prism_serde::CryptoPayload;
use prism_serde::{
base64::{FromBase64, ToBase64},
CryptoPayload,
};

#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(try_from = "CryptoPayload", into = "CryptoPayload")]
Expand Down Expand Up @@ -162,7 +164,7 @@ impl From<Ed25519SigningKey> for VerifyingKey {

impl From<Secp256k1SigningKey> for VerifyingKey {
fn from(sk: Secp256k1SigningKey) -> Self {
sk.public_key(SECP256K1).into()
VerifyingKey::Secp256k1(sk.public_key(SECP256K1))
}
}

Expand All @@ -182,14 +184,14 @@ impl From<SigningKey> for VerifyingKey {
}
}

impl TryFrom<String> for VerifyingKey {
impl FromBase64 for VerifyingKey {
type Error = anyhow::Error;

/// Attempts to create a `VerifyingKey` from a base64-encoded string.
///
/// # Arguments
///
/// * `s` - The base64-encoded string representation of the public key.
/// * `base64` - The base64-encoded string representation of the public key.
///
/// Depending on the length of the input string, the function will attempt to
/// decode it and create a `VerifyingKey` instance. According to the specifications,
Expand All @@ -200,9 +202,8 @@ impl TryFrom<String> for VerifyingKey {
///
/// * `Ok(VerifyingKey)` if the conversion was successful.
/// * `Err` if the input is invalid or the conversion failed.
fn try_from(s: String) -> std::result::Result<Self, Self::Error> {
let bytes =
engine.decode(s).map_err(|e| anyhow!("Failed to decode base64 string: {}", e))?;
fn from_base64<T: AsRef<[u8]>>(base64: T) -> Result<Self, Self::Error> {
let bytes = Vec::<u8>::from_base64(base64)?;

match bytes.len() {
32 => {
Expand All @@ -220,9 +221,17 @@ impl TryFrom<String> for VerifyingKey {
}
}

impl TryFrom<String> for VerifyingKey {
type Error = anyhow::Error;

fn try_from(s: String) -> std::result::Result<Self, Self::Error> {
Self::from_base64(s)
}
}

impl std::fmt::Display for VerifyingKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let encoded = engine.encode(self.to_bytes());
let encoded = self.to_bytes().to_base64();
write!(f, "{}", encoded)
}
}
39 changes: 39 additions & 0 deletions crates/serde/src/base64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use anyhow::Result;
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};

pub trait ToBase64 {
fn to_base64(&self) -> String;
}

impl<T> ToBase64 for T
where
T: AsRef<[u8]>,
{
fn to_base64(&self) -> String {
BASE64.encode(self.as_ref())
}
}

pub trait FromBase64: Sized {
type Error;

fn from_base64<T: AsRef<[u8]>>(base64: T) -> Result<Self, Self::Error>;
}

impl FromBase64 for Vec<u8> {
type Error = anyhow::Error;

fn from_base64<T: AsRef<[u8]>>(base64: T) -> Result<Self> {
BASE64.decode(base64.as_ref()).map_err(|e| e.into())
}
}

impl FromBase64 for [u8; 32] {
type Error = anyhow::Error;

fn from_base64<T: AsRef<[u8]>>(base64: T) -> Result<Self> {
let mut output = [0u8; 32];
BASE64.decode_slice(base64, &mut output)?;
Ok(output)
}
}
33 changes: 33 additions & 0 deletions crates/serde/src/hex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use anyhow::Result;
use std::error::Error as StdError;

pub trait ToHex {
fn to_hex(&self) -> String;
}

impl<T> ToHex for T
where
T: hex::ToHex,
{
fn to_hex(&self) -> String {
self.encode_hex()
}
}

pub trait FromHex: Sized {
type Error;

fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error>;
}

impl<T> FromHex for T
where
T: hex::FromHex,
T::Error: StdError + Send + Into<anyhow::Error>,
{
type Error = anyhow::Error;

fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
T::from_hex(hex).map_err(|e| e.into())
}
}
Loading

0 comments on commit b6c08ac

Please sign in to comment.