Skip to content

Commit

Permalink
Update serialisation traits (Sovereign-Labs#10)
Browse files Browse the repository at this point in the history
* renaming: Serialize=> Encode, Deser => Decode

* Error handling in the Decode trait

* comments in serialization.rs

* missing trait bounds

* missing trait bounds
  • Loading branch information
bkolad authored Jan 31, 2023
1 parent 93aec34 commit 5a1c096
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 63 deletions.
7 changes: 4 additions & 3 deletions specs/interfaces/zkvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ when proof verification fails.

Expressed in Rust, zkVM would be a `trait` that looked something like the following:


```rust
pub trait ZkVM {
type CodeCommitment: PartialEq + Clone;
type Proof: Serialize + Deserialize;
type Proof: Encode + Decode<Error = DeserializationError>;
type Error;

fn log<T: Serialize>(item: T);
fn verify<T: Deserialize>(
fn log<T: Encode>(item: T);
fn verify<T: Decode>(
proof: Self::Proof,
code_commitment: &Self::CodeCommitment,
) -> Result<T, Self::Error>;
Expand Down
6 changes: 3 additions & 3 deletions src/node/db/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::Result;
use super::{errors::CodecError, ColumnFamilyName, KeyCodec, Schema, ValueCodec};
use std::fmt::Debug;

use crate::{serial::Deser, services::da::SlotData};
use crate::{serial::Decode, services::da::SlotData};

pub const SLOT_CF_NAME: ColumnFamilyName = "slot";
pub type SlotNumber = u64;
Expand Down Expand Up @@ -42,10 +42,10 @@ where
T: SlotData,
{
fn encode_value(&self) -> Result<Vec<u8>> {
Ok(self.serialize_to_vec())
Ok(self.encode_to_vec())
}

fn decode_value(mut data: &[u8]) -> Result<Self> {
Ok(<T as Deser>::deser(&mut data)?)
Ok(<T as Decode>::decode(&mut data)?)
}
}
10 changes: 5 additions & 5 deletions src/node/db/slot_by_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{ColumnFamilyName, KeyCodec, Schema, ValueCodec};
use std::fmt::Debug;

use crate::da::BlockHashTrait;
use crate::{serial::Deser, services::da::SlotData};
use crate::{serial::Decode, services::da::SlotData};

pub const SLOT_BY_HASH_CF_NAME: ColumnFamilyName = "slot_by_hash";

Expand All @@ -27,11 +27,11 @@ where
V: Debug + Send + Sync + 'static + SlotData,
{
fn encode_key(&self) -> Result<Vec<u8>> {
Ok(self.serialize_to_vec())
Ok(self.encode_to_vec())
}

fn decode_key(mut data: &[u8]) -> Result<Self> {
Ok(K::deser(&mut data)?)
Ok(K::decode(&mut data)?)
}
}

Expand All @@ -41,10 +41,10 @@ where
V: Debug + Send + Sync + 'static + SlotData,
{
fn encode_value(&self) -> Result<Vec<u8>> {
Ok(self.serialize_to_vec())
Ok(self.encode_to_vec())
}

fn decode_value(mut data: &[u8]) -> Result<Self> {
Ok(<V as Deser>::deser(&mut data)?)
Ok(<V as Decode>::decode(&mut data)?)
}
}
4 changes: 2 additions & 2 deletions src/node/services/da.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::future::Future;

use crate::serial::{Deser, Serialize};
use crate::serial::{Decode, DeserializationError, Encode};

// TODO: Rename to clarify distinction with DaApp
/// A DaService is the local side of an RPC connection talking to node of the DA layer
Expand All @@ -27,4 +27,4 @@ pub trait DaService {
// TODO: Consider adding the send_transaction method
// fn send_transaction(tx: Self::Transaction, sender: Self::Address)
}
pub trait SlotData: Serialize + Deser + PartialEq {}
pub trait SlotData: Encode + Decode<Error = DeserializationError> + PartialEq {}
6 changes: 3 additions & 3 deletions src/state_machine/core/run.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
core::traits::{BatchTrait, BlockheaderTrait, CanonicalHash},
core::traits::{BlockheaderTrait, CanonicalHash},
da::{BlobTransactionTrait, DaLayerTrait},
serial::Deser,
serial::Decode,
state_machine::env,
stf::{ConsensusMessage, StateTransitionFunction},
zk::traits::{ProofTrait, RecursiveProofInput, ZkVM},
Expand Down Expand Up @@ -103,7 +103,7 @@ impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> Rollup<DaLayer, App> {

let mut state_tracker = self.app.begin_slot();
for tx in relevant_txs {
match ConsensusMessage::deser(&mut tx.data().as_ref()).unwrap() {
match ConsensusMessage::decode(&mut tx.data().as_ref()).unwrap() {
ConsensusMessage::Batch(batch) => {
if current_sequencers.allows(tx.sender()) {
match self.app.apply_batch(
Expand Down
10 changes: 7 additions & 3 deletions src/state_machine/core/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::fmt::Debug;

use crate::serial::{Deser, Serialize};
use crate::serial::{Decode, DeserializationError, Encode};

// NOTE: When naming traits, we use the naming convention below:
// *Trait IFF there's an associated type that would otherwise have the same name
Expand All @@ -15,7 +15,7 @@ pub trait CanonicalHash {
fn hash(&self) -> Self::Output;
}

pub trait BatchTrait: PartialEq + Debug + Serialize + Deser {
pub trait BatchTrait: PartialEq + Debug + Encode + Decode<Error = DeserializationError> {
type Header: BlockheaderTrait;
type Transaction: TransactionTrait;
fn header(&self) -> &Self::Header;
Expand All @@ -24,7 +24,11 @@ pub trait BatchTrait: PartialEq + Debug + Serialize + Deser {
}

pub trait TransactionTrait:
PartialEq + Debug + CanonicalHash<Output = Self::Hash> + Serialize + Deser
PartialEq
+ Debug
+ CanonicalHash<Output = Self::Hash>
+ Encode
+ Decode<Error = DeserializationError>
{
type Hash: AsRef<[u8]>;
}
Expand Down
11 changes: 6 additions & 5 deletions src/state_machine/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bytes::Bytes;

use crate::{
da::DaLayerTrait,
serial::{Deser, Serialize},
serial::{Decode, DeserializationError, Encode},
stf::{ConsensusSetUpdate, StateTransitionFunction},
};

Expand Down Expand Up @@ -36,13 +36,14 @@ impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> RollupHeader<DaLayer,
}
}

impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> Serialize for RollupHeader<DaLayer, App> {
fn serialize(&self, target: &mut impl std::io::Write) {
impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> Encode for RollupHeader<DaLayer, App> {
fn encode(&self, _target: &mut impl std::io::Write) {
todo!()
}
}
impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> Deser for RollupHeader<DaLayer, App> {
fn deser(target: &mut &[u8]) -> Result<Self, crate::serial::DeserializationError> {
impl<DaLayer: DaLayerTrait, App: StateTransitionFunction> Decode for RollupHeader<DaLayer, App> {
type Error = DeserializationError;
fn decode(_target: &mut &[u8]) -> Result<Self, Self::Error> {
todo!()
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/state_machine/da.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use bytes::Buf;

use crate::{
core::traits::{self, AddressTrait, BlockheaderTrait},
serial::{Deser, Serialize},
};
use crate::core::traits::{AddressTrait, BlockheaderTrait};
use crate::serial::{Decode, DeserializationError, Encode};
use core::fmt::Debug;

/// A DaLayer implements the logic required to create a zk proof that some data
Expand Down Expand Up @@ -57,4 +53,7 @@ pub trait BlobTransactionTrait<Addr> {
fn data(&self) -> Self::Data;
}

pub trait BlockHashTrait: Serialize + Deser + PartialEq + Debug {}
pub trait BlockHashTrait:
Encode + Decode<Error = DeserializationError> + PartialEq + Debug
{
}
23 changes: 12 additions & 11 deletions src/state_machine/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ pub enum DeserializationError {
// The objective is to not introduce a forcible serde dependency and potentially
// allow implementers to use rykv or another zero-copy framework. But we
// need to design that. This will work for now
pub trait Serialize {
fn serialize(&self, target: &mut impl std::io::Write);
fn serialize_to_vec(&self) -> Vec<u8> {

/// Trait used to express encoding relationships.
pub trait Encode {
fn encode(&self, target: &mut impl std::io::Write);

fn encode_to_vec(&self) -> Vec<u8> {
let mut target = Vec::new();
self.serialize(&mut target);
self.encode(&mut target);
target
}
}

// impl<T: Serialize> Serialize for &T {
// fn serialize(&self, target: &mut Vec<u8>) {
// (*self).serialize(target);
// }
// }
pub trait Deser: Sized {
fn deser(target: &mut &[u8]) -> Result<Self, DeserializationError>;
/// Trait used to express decoding relationships.
pub trait Decode: Sized {
type Error;

fn decode(target: &mut &[u8]) -> Result<Self, Self::Error>;
}
21 changes: 11 additions & 10 deletions src/state_machine/stf.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::collections::HashMap;

use bytes::{Buf, Bytes};
use bytes::Bytes;

use crate::{
core::traits::{AddressTrait, BatchTrait, BlockheaderTrait, TransactionTrait},
serial::{Deser, DeserializationError},
core::traits::{BatchTrait, TransactionTrait},
serial::{Decode, DeserializationError},
};

/// An address on the DA layer. Opaque to the StateTransitionFunction
Expand All @@ -18,7 +16,7 @@ pub trait StateTransitionFunction {
/// A batch of transactions. Also known as a "block" in most systems: we use
/// the term batch in this context to avoid ambiguity with DA layer blocks
type Batch: BatchTrait<Transaction = Self::Transaction>;
type Proof: Deser;
type Proof: Decode<Error = DeserializationError>;

/// A proof that the sequencer has misbehaved. For example, this could be a merkle proof of a transaction
/// with an invalid signature
Expand Down Expand Up @@ -81,8 +79,11 @@ pub enum ConsensusMessage<B, P> {
Proof(P),
}

impl<P: Deser, B: Deser> Deser for ConsensusMessage<B, P> {
fn deser(target: &mut &[u8]) -> Result<Self, crate::serial::DeserializationError> {
impl<P: Decode<Error = DeserializationError>, B: Decode<Error = DeserializationError>> Decode
for ConsensusMessage<B, P>
{
type Error = DeserializationError;
fn decode(target: &mut &[u8]) -> Result<Self, Self::Error> {
Ok(
match *target
.iter()
Expand All @@ -91,8 +92,8 @@ impl<P: Deser, B: Deser> Deser for ConsensusMessage<B, P> {
expected: 1,
got: 0,
})? {
0 => Self::Batch(B::deser(&mut &target[1..])?),
1 => Self::Proof(P::deser(&mut &target[1..])?),
0 => Self::Batch(B::decode(&mut &target[1..])?),
1 => Self::Proof(P::decode(&mut &target[1..])?),
_ => Err(DeserializationError::InvalidTag {
max_allowed: 1,
got: target[0],
Expand Down
21 changes: 10 additions & 11 deletions src/state_machine/zk/traits.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use core::fmt::Debug;

use crate::serial::{Deser, DeserializationError, Serialize};
use crate::serial::{Decode, DeserializationError, Encode};

/// A proof that a program was executed in a zkVM.
pub trait ZkVM {
type CodeCommitment: Matches<Self::CodeCommitment> + Clone;
type Proof: ProofTrait<Self>;
type Error: Debug;

fn log<T: Serialize>(item: T);
fn log<T: Encode>(item: T);
fn verify(
proof: Self::Proof,
code_commitment: &Self::CodeCommitment,
) -> Result<<<Self as ZkVM>::Proof as ProofTrait<Self>>::Output, Self::Error>;
}

pub trait ProofTrait<VM: ZkVM + ?Sized> {
type Output: Serialize + Deser;
type Output: Encode + Decode<Error = DeserializationError>;
/// Verify the proof, deserializing the result if successful.
fn verify(self, code_commitment: &VM::CodeCommitment) -> Result<Self::Output, VM::Error>;
}
Expand All @@ -34,16 +34,15 @@ pub struct RecursiveProofOutput<Vm: ZkVM, T> {
pub claimed_method_id: Vm::CodeCommitment,
pub output: T,
}
impl<Vm: ZkVM<CodeCommitment = C>, C: Serialize, T: Serialize> Serialize
for RecursiveProofOutput<Vm, T>
{
fn serialize(&self, target: &mut impl std::io::Write) {
self.claimed_method_id.serialize(target);
self.output.serialize(target);
impl<Vm: ZkVM<CodeCommitment = C>, C: Encode, T: Encode> Encode for RecursiveProofOutput<Vm, T> {
fn encode(&self, target: &mut impl std::io::Write) {
self.claimed_method_id.encode(target);
self.output.encode(target);
}
}
impl<Vm: ZkVM, T> Deser for RecursiveProofOutput<Vm, T> {
fn deser(target: &mut &[u8]) -> Result<Self, DeserializationError> {
impl<Vm: ZkVM, T> Decode for RecursiveProofOutput<Vm, T> {
type Error = DeserializationError;
fn decode(_target: &mut &[u8]) -> Result<Self, DeserializationError> {
todo!()
}
}
Expand Down

0 comments on commit 5a1c096

Please sign in to comment.