Skip to content

Commit

Permalink
review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
MujkicA committed Jul 5, 2024
1 parent 9856540 commit 01709f2
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 23 deletions.
1 change: 1 addition & 0 deletions committer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ async fn main() -> Result<()> {
storage.clone(),
&metrics_registry,
cancel_token.clone(),
&config,
);

launch_api_server(
Expand Down
6 changes: 4 additions & 2 deletions committer/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,13 @@ pub fn state_importer(
storage: impl Storage + 'static,
_registry: &Registry,
cancel_token: CancellationToken,
config: &config::Config,
) -> tokio::task::JoinHandle<()> {
let state_importer = services::StateImporter::new(storage, fuel);
let validator = BlockValidator::new(config.fuel.block_producer_public_key);
let state_importer = services::StateImporter::new(storage, fuel, validator);

schedule_polling(
Duration::from_secs(10),
config.app.block_check_interval,
state_importer,
"State Importer",
cancel_token,
Expand Down
10 changes: 9 additions & 1 deletion packages/eth/src/eip_4844/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ impl BlobSidecar {
self.blobs.iter().map(|blob| blob.versioned_hash).collect()
}

// When preparing a blob transaction, we compute the KZG commitment and proof for the blob data.
// To be able to apply the KZG commitment scheme, the data is treated as a polynomial with the field elements as coefficients.
// We split it into 31-byte chunks (field elements) padded with a zero byte.
fn partition_data(data: Vec<u8>) -> Vec<[u8; 32]> {
let capacity = data.len().div_ceil(31);
let mut field_elements = Vec::with_capacity(capacity);
Expand All @@ -80,11 +83,13 @@ impl BlobSidecar {
field_elements
}

// Generate the right amount of blobs to carry all the field elements.
fn field_elements_to_blobs(field_elements: Vec<[u8; 32]>) -> Vec<c_kzg::Blob> {
let mut blobs = Vec::new();
let mut current_blob = [0u8; c_kzg::BYTES_PER_BLOB];
let mut offset = 0;

// Each field element is 32 bytes long. A blob can hold 4096 field elements.
for fe in field_elements {
if offset + 32 > c_kzg::BYTES_PER_BLOB {
blobs.push(current_blob.into());
Expand Down Expand Up @@ -127,7 +132,7 @@ impl BlobSidecar {

fn kzg_proof(blob: &c_kzg::Blob, commitment: &c_kzg::KzgCommitment) -> c_kzg::KzgProof {
c_kzg::KzgProof::compute_blob_kzg_proof(blob, &commitment.to_bytes(), &KZG_SETTINGS)
.unwrap()
.expect("KZG proof computation failed")
}
}

Expand Down Expand Up @@ -164,6 +169,7 @@ impl BlobTransactionEncoder {
let blobs_count = self.sidecar.num_blobs();

let mut stream = RlpStream::new();
// 4 fields: tx type, blobs, commitments, proofs
stream.begin_list(4);

// skip the tx type byte
Expand Down Expand Up @@ -215,6 +221,7 @@ impl BlobTransactionEncoder {

fn rlp(&self) -> Vec<u8> {
let mut stream = RlpStream::new();
// 11 fields: common tx fields, unused fields, blob tx fields
stream.begin_list(11);

self.append_common_tx_fields(&mut stream);
Expand All @@ -226,6 +233,7 @@ impl BlobTransactionEncoder {

fn rlp_signed(&self, signature: Signature) -> Vec<u8> {
let mut stream = RlpStream::new();
// 14 fields: common tx fields, unused fields, blob tx fields, signature
stream.begin_list(14);

self.append_common_tx_fields(&mut stream);
Expand Down
2 changes: 2 additions & 0 deletions packages/eth/src/eip_4844/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const BLOB_BASE_FEE_UPDATE_FRACTION: u64 = 3338477;
const GAS_PER_BLOB: u64 = 131_072;
const MIN_BASE_FEE_PER_BLOB_GAS: u64 = 1;

// Calculate blob fee based on the EIP-4844 specs
// https://eips.ethereum.org/EIPS/eip-4844
pub fn calculate_blob_fee(excess_blob_gas: U256, num_blobs: u64) -> U256 {
get_total_blob_gas(num_blobs) * get_base_fee_per_blob_gas(excess_blob_gas)
}
Expand Down
13 changes: 3 additions & 10 deletions packages/eth/src/websocket/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::{
error::{Error, Result},
};

const STANDARD_GAS_LIMIT: u64 = 21000;

abigen!(
FUEL_STATE_CONTRACT,
r#"[
Expand Down Expand Up @@ -163,16 +165,7 @@ impl WsConnection {
let (max_fee_per_gas, max_priority_fee_per_gas) =
self.provider.estimate_eip1559_fees(None).await?;

// Gas limit should be 21000, otherwise we'll have to estimate it
let gas_limit = U256::from(21000);
// let estimate_tx = TypedTransaction::Eip1559(Eip1559TransactionRequest {
// from: address.into(),
// to: Some(address.into()),
// max_priority_fee_per_gas: Some(max_priority_fee_per_gas),
// max_fee_per_gas: Some(max_fee_per_gas),
// ..Default::default()
// });
// let gas_limit = self.provider.estimate_gas(&estimate_tx, None).await?;
let gas_limit = U256::from(STANDARD_GAS_LIMIT);

let max_fee_per_blob_gas = self.calculate_blob_fee(blob_versioned_hashes.len()).await?;

Expand Down
39 changes: 29 additions & 10 deletions packages/services/src/state_importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,38 @@ use ports::{
storage::Storage,
types::{StateFragment, StateSubmission},
};
use validator::Validator;

use crate::{Result, Runner};

pub struct StateImporter<Db, A> {
pub struct StateImporter<Db, A, BlockValidator> {
storage: Db,
fuel_adapter: A,
block_validator: BlockValidator,
}

impl<Db, A> StateImporter<Db, A> {
pub fn new(storage: Db, fuel_adapter: A) -> Self {
impl<Db, A, BlockValidator> StateImporter<Db, A, BlockValidator> {
pub fn new(storage: Db, fuel_adapter: A, block_validator: BlockValidator) -> Self {
Self {
storage,
fuel_adapter,
block_validator,
}
}
}

impl<Db, A> StateImporter<Db, A>
impl<Db, A, BlockValidator> StateImporter<Db, A, BlockValidator>
where
Db: Storage,
A: ports::fuel::Api,
BlockValidator: Validator,
{
async fn fetch_latest_block(&self) -> Result<FuelBlock> {
let latest_block = self.fuel_adapter.latest_block().await?;
// validate if needed

// validate block but don't return the validated block
// so we can use the original block for state submission
self.block_validator.validate(&latest_block)?;

Ok(latest_block)
}
Expand Down Expand Up @@ -90,10 +97,11 @@ where
}

#[async_trait]
impl<Db, Fuel> Runner for StateImporter<Db, Fuel>
impl<Db, Fuel, BlockValidator> Runner for StateImporter<Db, Fuel, BlockValidator>
where
Db: Storage,
Fuel: ports::fuel::Api,
BlockValidator: Validator,
{
async fn run(&mut self) -> Result<()> {
let block = self.fetch_latest_block().await?;
Expand All @@ -114,13 +122,22 @@ where

#[cfg(test)]
mod tests {
use fuel_crypto::SecretKey;
use ports::fuel::FuelBytes32;
use rand::{rngs::StdRng, SeedableRng};
use storage::PostgresProcess;
use tai64::Tai64;
use validator::BlockValidator;

use super::*;

fn given_block() -> FuelBlock {
fn given_secret_key() -> SecretKey {
let mut rng = StdRng::seed_from_u64(42);

SecretKey::random(&mut rng)
}

fn given_block(secret: SecretKey) -> FuelBlock {
let id = FuelBytes32::from([1u8; 32]);
let header = ports::fuel::FuelHeader {
id,
Expand All @@ -142,7 +159,7 @@ mod tests {
header,
transactions: vec![[2u8; 32].into()],
consensus: ports::fuel::FuelConsensus::Unknown,
block_producer: Default::default(),
block_producer: Some(secret.public_key()),
};

block
Expand All @@ -160,13 +177,15 @@ mod tests {

#[tokio::test]
async fn test_import_state() -> Result<()> {
let block = given_block();
let secret_key = given_secret_key();
let block = given_block(secret_key);
let block_id = *block.id;
let fuel_mock = given_fetcher(block);
let block_validator = BlockValidator::new(secret_key.public_key());

let process = PostgresProcess::shared().await.unwrap();
let db = process.create_random_db().await?;
let mut importer = StateImporter::new(db.clone(), fuel_mock);
let mut importer = StateImporter::new(db.clone(), fuel_mock, block_validator);

importer.run().await.unwrap();

Expand Down

0 comments on commit 01709f2

Please sign in to comment.