Skip to content

Commit

Permalink
Merge pull request #231 from hackaugusto/hacka-stark-proof-serializab…
Browse files Browse the repository at this point in the history
…le-deserializable

Stark proof serializable deserializable
  • Loading branch information
irakliyk authored Dec 1, 2023
2 parents 73d0b7e + addca1f commit a671515
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 43 deletions.
8 changes: 8 additions & 0 deletions air/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,19 @@ impl FieldExtension {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for FieldExtension {
/// Serializes `self` and writes the resulting bytes into the `target`.
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u8(*self as u8);
}

/// Returns an estimate of how many bytes are needed to represent self.
fn get_size_hint(&self) -> usize {
1
}
}

impl Deserializable for FieldExtension {
Expand Down
8 changes: 8 additions & 0 deletions air/src/proof/commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,21 @@ impl Commitments {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for Commitments {
/// Serializes `self` and writes the resulting bytes into the `target`.
fn write_into<W: ByteWriter>(&self, target: &mut W) {
assert!(self.0.len() < u16::MAX as usize);
target.write_u16(self.0.len() as u16);
target.write_bytes(&self.0);
}

/// Returns an estimate of how many bytes are needed to represent self.
fn get_size_hint(&self) -> usize {
self.0.len() + 2
}
}

impl Deserializable for Commitments {
Expand Down
3 changes: 3 additions & 0 deletions air/src/proof/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ impl<E: StarkField> ToElements<E> for Context {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for Context {
/// Serializes `self` and writes the resulting bytes into the `target`.
fn write_into<W: ByteWriter>(&self, target: &mut W) {
Expand Down
89 changes: 46 additions & 43 deletions air/src/proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,56 +129,15 @@ impl StarkProof {

/// Serializes this proof into a vector of bytes.
pub fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::new();
self.context.write_into(&mut result);
result.push(self.num_unique_queries);
self.commitments.write_into(&mut result);
self.trace_queries.write_into(&mut result);
self.constraint_queries.write_into(&mut result);
self.ood_frame.write_into(&mut result);
self.fri_proof.write_into(&mut result);
result.extend_from_slice(&self.pow_nonce.to_le_bytes());
result
Serializable::to_bytes(self)
}

/// Returns a STARK proof read from the specified `source`.
///
/// # Errors
/// Returns an error of a valid STARK proof could not be read from the specified `source`.
pub fn from_bytes(source: &[u8]) -> Result<Self, DeserializationError> {
let mut source = SliceReader::new(source);

// parse the context
let context = Context::read_from(&mut source)?;

// parse the number of unique queries made by the verifier
let num_unique_queries = source.read_u8()?;

// parse the commitments
let commitments = Commitments::read_from(&mut source)?;

// parse trace queries
let num_trace_segments = context.trace_layout().num_segments();
let mut trace_queries = Vec::with_capacity(num_trace_segments);
for _ in 0..num_trace_segments {
trace_queries.push(Queries::read_from(&mut source)?);
}

// parse the rest of the proof
let proof = StarkProof {
context,
num_unique_queries,
commitments,
trace_queries,
constraint_queries: Queries::read_from(&mut source)?,
ood_frame: OodFrame::read_from(&mut source)?,
fri_proof: FriProof::read_from(&mut source)?,
pow_nonce: source.read_u64()?,
};
if source.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
Ok(proof)
Deserializable::read_from_bytes(source)
}

/// Creates a dummy `StarkProof` for use in tests.
Expand Down Expand Up @@ -211,6 +170,50 @@ impl StarkProof {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for StarkProof {
fn write_into<W: utils::ByteWriter>(&self, target: &mut W) {
self.context.write_into(target);
target.write_u8(self.num_unique_queries);
self.commitments.write_into(target);
self.trace_queries.write_into(target);
self.constraint_queries.write_into(target);
self.ood_frame.write_into(target);
self.fri_proof.write_into(target);
self.pow_nonce.write_into(target)
}
}

impl Deserializable for StarkProof {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let context = Context::read_from(source)?;
let num_unique_queries = source.read_u8()?;
let commitments = Commitments::read_from(source)?;
let num_trace_segments = context.trace_layout().num_segments();
let mut trace_queries = Vec::with_capacity(num_trace_segments);
for _ in 0..num_trace_segments {
trace_queries.push(Queries::read_from(source)?);
}

let proof = StarkProof {
context,
num_unique_queries,
commitments,
trace_queries,
constraint_queries: Queries::read_from(source)?,
ood_frame: OodFrame::read_from(source)?,
fri_proof: FriProof::read_from(source)?,
pow_nonce: source.read_u64()?,
};
if source.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
Ok(proof)
}
}

// HELPER FUNCTIONS
// ================================================================================================

Expand Down
8 changes: 8 additions & 0 deletions air/src/proof/ood_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ impl OodFrame {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for OodFrame {
/// Serializes `self` and writes the resulting bytes into the `target`.
fn write_into<W: ByteWriter>(&self, target: &mut W) {
Expand All @@ -130,6 +133,11 @@ impl Serializable for OodFrame {
target.write_u16(self.evaluations.len() as u16);
target.write_bytes(&self.evaluations)
}

/// Returns an estimate of how many bytes are needed to represent self.
fn get_size_hint(&self) -> usize {
self.trace_states.len() + self.evaluations.len() + 4
}
}

impl Deserializable for OodFrame {
Expand Down
8 changes: 8 additions & 0 deletions air/src/proof/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ impl Queries {
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for Queries {
/// Serializes `self` and writes the resulting bytes into the `target`.
fn write_into<W: ByteWriter>(&self, target: &mut W) {
Expand All @@ -139,6 +142,11 @@ impl Serializable for Queries {
target.write_u32(self.paths.len() as u32);
target.write_bytes(&self.paths);
}

/// Returns an estimate of how many bytes are needed to represent self.
fn get_size_hint(&self) -> usize {
self.paths.len() + self.values.len() + 8
}
}

impl Deserializable for Queries {
Expand Down
48 changes: 48 additions & 0 deletions utils/core/src/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,54 @@ impl Serializable for () {
fn write_into<W: ByteWriter>(&self, _target: &mut W) {}
}

impl Serializable for u8 {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u8(*self);
}
}

impl Serializable for u16 {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u16(*self);
}
}

impl Serializable for u32 {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u32(*self);
}
}

impl Serializable for u64 {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u64(*self);
}
}

impl<T: Serializable> Serializable for Option<T> {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
match self {
Some(v) => {
target.write_bool(true);
v.write_into(target);
}
None => target.write_bool(false),
}
}
}

impl<T: Serializable> Serializable for &Option<T> {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
match self {
Some(v) => {
target.write_bool(true);
v.write_into(target);
}
None => target.write_bool(false),
}
}
}

impl<T: Serializable> Serializable for Vec<T> {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
T::write_batch_into(self, target);
Expand Down

0 comments on commit a671515

Please sign in to comment.