Skip to content

Commit 4727823

Browse files
authored
Merge pull request #27 from lambdaclass/add-payload-module
Client v2: add payload module
2 parents 6c7806c + 5472ffb commit 4727823

File tree

7 files changed

+101
-0
lines changed

7 files changed

+101
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ tokio = {version = "1", features = ["fs"]}
1919
tokio-stream = "0.1.16"
2020
rust-kzg-bn254 = "0.2.1"
2121
ark-bn254 = "0.5.0"
22+
ark-poly = "0.5.0"
2223
ethereum-types = { version = "0.14.1", features = ["serialize"] }
2324
serde = { version = "1", features = ["derive"] }
2425
serde_json = "1"

crates/rust-eigenda-v2-client/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,7 @@ ethereum-types = { workspace = true }
3333
prost = { workspace = true }
3434
tonic = { workspace = true }
3535
tokio-stream = { workspace = true }
36+
ark-bn254 = {workspace = true }
37+
ark-poly = { workspace = true }
3638
rust-kzg-bn254-primitives = "0.1.0"
3739
rust-kzg-bn254-verifier = "0.1.0"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
1+
use ark_bn254::Fr;
12

3+
// Blob is data that is dispersed on eigenDA.
4+
//
5+
// A Blob is represented under the hood by an array of field elements, which represent a polynomial in coefficient form
6+
pub(crate) struct Blob {
7+
pub coeff_polynomial: Vec<Fr>,
8+
// blobLengthSymbols must be a power of 2, and should match the blobLength claimed in the BlobCommitment
9+
//
10+
// This value must be specified, rather than computed from the length of the coeffPolynomial, due to an edge case
11+
// illustrated by the following example: imagine a user disperses a very small blob, only 64 bytes, and the last 40
12+
// bytes are trailing zeros. When a different user fetches the blob from a relay, it's possible that the relay could
13+
// truncate the trailing zeros. If we were to say that blobLengthSymbols = nextPowerOf2(len(coeffPolynomial)), then the
14+
// user fetching and reconstructing this blob would determine that the blob length is 1 symbol, when it's actually 2.
15+
pub blob_length_symbols: u32,
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1+
use ark_bn254::Fr;
12

3+
use super::payload::Payload;
4+
5+
pub(crate) struct EncodedPayload {}
6+
7+
impl EncodedPayload {
8+
pub fn new(payload: &Payload) -> Self {
9+
EncodedPayload {}
10+
}
11+
12+
pub(crate) fn to_field_elements(&self) -> Vec<Fr> {
13+
todo!()
14+
}
15+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,58 @@
1+
use ark_bn254::Fr;
2+
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
13

4+
use crate::utils::eval_to_coeff_poly;
5+
6+
use super::{blob::Blob, encoded_payload::EncodedPayload};
7+
8+
// TODO: remove, this will be implemented somewhere else
9+
enum PayloadForm {
10+
Eval,
11+
Coeff,
12+
}
13+
14+
/// Payload represents arbitrary user data, without any processing.
15+
pub(crate) struct Payload {
16+
bytes: Vec<u8>,
17+
}
18+
19+
impl Payload {
20+
/// Wraps an arbitrary array of bytes into a Payload type.
21+
pub fn new(bytes: Vec<u8>) -> Self {
22+
Self { bytes }
23+
}
24+
25+
/// Converts the Payload bytes into a Blob
26+
///
27+
/// The payload_form indicates how payloads are interpreted. The form of a payload dictates what conversion, if any, must
28+
/// be performed when creating a blob from the payload.
29+
pub fn to_blob(&self, payload_form: PayloadForm) -> Result<Blob, String> {
30+
let encoded_payload = EncodedPayload::new(&self);
31+
let field_elements = encoded_payload.to_field_elements();
32+
33+
let blob_length_symbols = ((&field_elements).len() as u32).next_power_of_two();
34+
35+
let coeff_polynomial = match payload_form {
36+
PayloadForm::Coeff => {
37+
// the payload is already in coefficient form. no conversion needs to take place, since blobs are also in
38+
// coefficient form
39+
field_elements
40+
}
41+
PayloadForm::Eval => {
42+
// the payload is in evaluation form, so we need to convert it to coeff form, since blobs are in coefficient form
43+
let eval_poly = field_elements;
44+
eval_to_coeff_poly(eval_poly, blob_length_symbols)?
45+
}
46+
};
47+
48+
Ok(Blob {
49+
coeff_polynomial,
50+
blob_length_symbols,
51+
})
52+
}
53+
54+
/// Returns the bytes that underlie the payload, i.e. the unprocessed user data
55+
pub fn serialize(&self) -> Vec<u8> {
56+
self.bytes.clone()
57+
}
58+
}

crates/rust-eigenda-v2-client/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod utils;
12
pub mod core;
23
pub mod disperser_client;
34
pub mod retrieval_client;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use ark_bn254::Fr;
2+
use ark_poly::{GeneralEvaluationDomain, EvaluationDomain};
3+
4+
/// Converts an eval_poly to a coeff_poly, using the IFFT operation
5+
///
6+
/// blob_length_symbols is required, to be able to choose the correct parameters when performing FFT
7+
pub(crate) fn eval_to_coeff_poly(eval_poly: Vec<Fr>, blob_length_symbols: u32) -> Result<Vec<Fr>, String> {
8+
Ok(GeneralEvaluationDomain::<Fr>::new(blob_length_symbols as usize)
9+
.ok_or("Failed to create domain")?
10+
.fft(&eval_poly))
11+
}

0 commit comments

Comments
 (0)