Skip to content

Commit

Permalink
feat: blob decoding wip
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Feb 3, 2024
1 parent 90d038a commit 8354827
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 70 deletions.
12 changes: 6 additions & 6 deletions src/derive/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::{mpsc, Arc, RwLock};

use bytes::Bytes;
use eyre::Result;

use crate::{config::Config, engine::PayloadAttributes};
Expand Down Expand Up @@ -53,7 +54,7 @@ impl Pipeline {
})
}

pub fn push_batcher_transactions(&self, txs: Vec<Vec<u8>>, l1_origin: u64) -> Result<()> {
pub fn push_batcher_transactions(&self, txs: Vec<Bytes>, l1_origin: u64) -> Result<()> {
self.batcher_transaction_sender
.send(BatcherTransactionMessage { txs, l1_origin })?;
Ok(())
Expand Down Expand Up @@ -142,12 +143,11 @@ mod tests {
_ => panic!("wrong update type"),
};

// let calldata = l1_info.batcher_transactions.into();
// TODO: get calldata from blob
let calldata = vec![];

pipeline
.push_batcher_transactions(calldata, l1_info.block_info.number)
.push_batcher_transactions(
l1_info.batcher_transactions.clone(),
l1_info.block_info.number,
)
.unwrap();

state.write().unwrap().update_l1_info(l1_info);
Expand Down
4 changes: 2 additions & 2 deletions src/derive/stages/batcher_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::collections::VecDeque;
use crate::derive::PurgeableIterator;

pub struct BatcherTransactionMessage {
pub txs: Vec<Vec<u8>>,
pub txs: Vec<bytes::Bytes>,
pub l1_origin: u64,
}

Expand Down Expand Up @@ -156,7 +156,7 @@ mod tests {

#[test]
fn test_push_tx() {
let data = hex::decode(TX_DATA).unwrap();
let data = bytes::Bytes::from(hex::decode(TX_DATA).unwrap());
let txs = vec![data];

let (tx, rx) = mpsc::channel();
Expand Down
10 changes: 5 additions & 5 deletions src/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ impl<E: Engine> Driver<E> {
self.unsafe_block_signer_sender
.send(l1_info.system_config.unsafe_block_signer)?;

// let calldata = l1_info.batcher_transactions.into();
// TODO: decode valid data from blob
let calldata = vec![];

self.pipeline.push_batcher_transactions(calldata, num)?;
self.pipeline.push_batcher_transactions(
// cloning `bytes::Bytes` is cheap
l1_info.batcher_transactions.clone(),
num,
)?;

self.state
.write()
Expand Down
95 changes: 95 additions & 0 deletions src/l1/blob_encoding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use bytes::Bytes;
use eyre::Result;

const MAX_BLOB_DATA_SIZE: usize = (4 * 31 + 3) * 1024 - 4;
const ENCODING_VERSION: u8 = 0;
const VERSION_OFFSET: usize = 0;
const ROUNDS: usize = 1024;

pub fn decode_blob_data(blob: &Bytes) -> Result<Bytes> {
let mut output = vec![0; MAX_BLOB_DATA_SIZE];

if blob[VERSION_OFFSET] != ENCODING_VERSION {
eyre::bail!("Invalid encoding version");
}

// decode the 3-byte big-endian length value into a 4-byte integer
let output_len = u32::from_be_bytes([0, blob[2], blob[3], blob[4]]) as usize;
if output_len > MAX_BLOB_DATA_SIZE {
eyre::bail!("Invalid length");
}

output[0..27].copy_from_slice(&blob[5..32]);

let mut output_pos = 28;
let mut input_pos = 32;

// buffer for the 4 6-bit chunks
let mut encoded_byte = [0; 4];

encoded_byte[0] = blob[0];
for byte in encoded_byte.iter_mut().skip(1) {
*byte = decode_field_element(&mut output_pos, &mut input_pos, blob, &mut output)?;
}
reassemble_bytes(&mut output_pos, encoded_byte, &mut output);

for _ in 1..ROUNDS {
if output_pos >= output_len {
break;
}

for byte in encoded_byte.iter_mut() {
*byte = decode_field_element(&mut output_pos, &mut input_pos, blob, &mut output)?;
}
reassemble_bytes(&mut output_pos, encoded_byte, &mut output);
}

for output_byte in output.iter().take(MAX_BLOB_DATA_SIZE).skip(output_len) {
if output_byte != &0 {
eyre::bail!("Extraneous data in field element {}", output_pos / 32);
}
}

output.truncate(output_len);

for byte in blob.iter().skip(input_pos) {
if byte != &0 {
eyre::bail!("Extraneous data in input position {}", input_pos);
}
}

Ok(output.into())
}

fn decode_field_element(
output_pos: &mut usize,
input_pos: &mut usize,
blob: &Bytes,
output: &mut [u8],
) -> Result<u8> {
let result = blob[*input_pos];

// two highest order bits of the first byte of each field element should always be 0
if result & 0b1100_0000 != 0 {
eyre::bail!("Invalid field element");
}

output[*output_pos..*output_pos + 31].copy_from_slice(&blob[*input_pos + 1..*input_pos + 32]);

*output_pos += 32;
*input_pos += 32;

Ok(result)
}

fn reassemble_bytes(output_pos: &mut usize, encoded_byte: [u8; 4], output: &mut [u8]) {
*output_pos -= 1;

let x = (encoded_byte[0] & 0b0011_1111) | ((encoded_byte[1] & 0b0011_0000) << 2);
let y = (encoded_byte[1] & 0b0000_1111) | ((encoded_byte[3] & 0b0000_1111) << 4);
let z = (encoded_byte[2] & 0b0011_1111) | ((encoded_byte[3] & 0b0011_0000) << 2);

output[*output_pos - 32] = z;
output[*output_pos - (32 * 2)] = y;
output[*output_pos - (32 * 3)] = x;
}
Loading

0 comments on commit 8354827

Please sign in to comment.