Skip to content

Commit

Permalink
Refactore blob-hash logic and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mrLSD committed May 24, 2024
1 parent 74b6b16 commit 608c6cb
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 78 deletions.
3 changes: 2 additions & 1 deletion benches/loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ fn run_loop_contract() {
chain_id: U256::one(),
block_base_fee_per_gas: U256::zero(),
block_randomness: None,
blob_base_fee: None,
blob_gas_price: None,
blob_hashes: Vec::new(),
};

let mut state = BTreeMap::new();
Expand Down
20 changes: 19 additions & 1 deletion core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,32 @@ pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 {
/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers)
/// (`get_blob_gasprice`).
#[inline]
pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u128 {
pub fn calc_blob_gas_price(excess_blob_gas: u64) -> u128 {
fake_exponential(
MIN_BLOB_GASPRICE,
excess_blob_gas,
BLOB_GASPRICE_UPDATE_FRACTION,
)
}

/// Calculates the [EIP-4844] `data_fee` of the transaction.
///
/// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`].
///
/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
#[inline]
pub fn calc_data_fee(blob_gas_price: u128, blob_hashes_len: usize) -> U256 {
U256::from(blob_gas_price).saturating_mul(U256::from(get_total_blob_gas(blob_hashes_len)))
}

/// See [EIP-4844], [`calc_data_fee`]
///
/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
#[inline]
pub const fn get_total_blob_gas(blob_hashes_len: usize) -> u64 {
GAS_PER_BLOB * blob_hashes_len as u64
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Sign {
Plus,
Expand Down
60 changes: 49 additions & 11 deletions evm-tests/ethcore-builtin/src/kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use core::hash::{Hash, Hasher};
use derive_more::{AsMut, AsRef, Deref, DerefMut};
use hex_literal::hex;
use sha2::Digest;
use std::convert::TryFrom;
use std::rc::Rc;

pub const RETURN_VALUE: &[u8; 64] = &hex!(
Expand Down Expand Up @@ -162,15 +163,52 @@ pub fn kzg_to_versioned_hash(commitment: &[u8]) -> [u8; 32] {
hash
}

#[inline]
pub fn verify_kzg_proof(
commitment: &Bytes48,
z: &Bytes32,
y: &Bytes32,
proof: &Bytes48,
kzg_settings: &KzgSettings,
) -> bool {
KzgProof::verify_kzg_proof(commitment, z, y, proof, kzg_settings).unwrap_or(false)
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct KzgInput {
commitment: Bytes48,
z: Bytes32,
y: Bytes32,
proof: Bytes48,
}

impl KzgInput {
#[inline]
pub fn verify_kzg_proof(&self, kzg_settings: &KzgSettings) -> bool {
KzgProof::verify_kzg_proof(
&self.commitment,
&self.z,
&self.y,
&self.proof,
kzg_settings,
)
.unwrap_or(false)
}
}

impl TryFrom<&[u8]> for KzgInput {
type Error = &'static str;

fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
if input.len() != 192 {
return Err("BlobInvalidInputLength");
}
// Verify commitment matches versioned_hash
let versioned_hash = &input[..32];
let commitment = &input[96..144];
if kzg_to_versioned_hash(commitment) != versioned_hash {
return Err("BlobMismatchedVersion");
}
let commitment = *as_bytes48(commitment);
let z = *as_bytes32(&input[32..64]);
let y = *as_bytes32(&input[64..96]);
let proof = *as_bytes48(&input[144..192]);
Ok(Self {
commitment,
z,
y,
proof,
})
}
}

#[inline]
Expand All @@ -179,13 +217,13 @@ fn as_array<const N: usize>(bytes: &[u8]) -> &[u8; N] {
}

#[inline]
pub fn as_bytes32(bytes: &[u8]) -> &Bytes32 {
fn as_bytes32(bytes: &[u8]) -> &Bytes32 {
// SAFETY: `#[repr(C)] Bytes32([u8; 32])`
unsafe { &*as_array::<32>(bytes).as_ptr().cast() }
}

#[inline]
pub fn as_bytes48(bytes: &[u8]) -> &Bytes48 {
fn as_bytes48(bytes: &[u8]) -> &Bytes48 {
// SAFETY: `#[repr(C)] Bytes48([u8; 48])`
unsafe { &*as_array::<48>(bytes).as_ptr().cast() }
}
19 changes: 3 additions & 16 deletions evm-tests/ethcore-builtin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1340,26 +1340,13 @@ impl Implementation for Bls12MapFp2ToG2 {

impl Implementation for Kzg {
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
// Verify input length.
if input.len() != 192 {
return Err("BlobInvalidInputLength");
}
// Get and verify KZG input.
let kzg_input: kzg::KzgInput = input.try_into()?;
if output.is_empty() {
return Err("BlobInvalidOutputLength");
}
// Verify commitment matches versioned_hash
let versioned_hash = &input[..32];
let commitment = &input[96..144];
if kzg::kzg_to_versioned_hash(commitment) != versioned_hash {
return Err("BlobMismatchedVersion");
}
// Verify KZG proof with z and y in big endian format
let commitment = kzg::as_bytes48(commitment);
let z = kzg::as_bytes32(&input[32..64]);
let y = kzg::as_bytes32(&input[64..96]);
let proof = kzg::as_bytes48(&input[144..192]);
let kzg_settings = kzg::EnvKzgSettings::Default;
if !kzg::verify_kzg_proof(commitment, z, y, proof, &kzg_settings.get()) {
if !kzg_input.verify_kzg_proof(&kzg_settings.get()) {
return Err("BlobVerifyKzgProofFailed");
}
output.copy_from_slice(kzg::RETURN_VALUE.as_slice());
Expand Down
2 changes: 1 addition & 1 deletion evm-tests/ethjson/src/test_helpers/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub struct MultiTransaction {

/// EIP-4844
#[serde(default)]
pub blob_versioned_hashes: Vec<H256>,
pub blob_versioned_hashes: Vec<U256>,
/// EIP-4844
pub max_fee_per_blob_gas: Option<Uint>,
}
Expand Down
15 changes: 11 additions & 4 deletions evm-tests/ethjson/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub struct Transaction {

/// Environment.
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Env {
/// Address.
#[serde(rename = "currentCoinbase")]
Expand All @@ -125,9 +126,13 @@ pub struct Env {
#[serde(rename = "currentRandom")]
#[serde(default)]
pub random: Option<Uint>,
/// EIP-7516: Blob base fee
#[serde(default)]
pub blob_base_fee: Option<u128>,

/// EIP-4844
pub parent_blob_gas_used: Option<Uint>,
/// EIP-4844
pub parent_excess_blob_gas: Option<Uint>,
/// EIP-4844
pub current_excess_blob_gas: Option<Uint>,
}

#[cfg(test)]
Expand Down Expand Up @@ -202,7 +207,9 @@ mod tests {
timestamp: Uint(1.into()),
block_base_fee_per_gas: Uint(0.into()),
random: Some(Uint(1.into())),
blob_base_fee: None,
parent_excess_blob_gas: None,
parent_blob_gas_used: None,
current_excess_blob_gas: None
}
);
assert_eq!(
Expand Down
4 changes: 2 additions & 2 deletions evm-tests/jsontests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ const SKIPPED_CASES: &[&str] = &[
"vmPerformance/loopMul",
"stTimeConsuming/CALLBlake2f_MaxRounds",
// Skip python-specific tests
"eip4844_blobs",
// "eip4844_blobs",
// Cancun blob txs
"stEIP4844-blobtransactions",
// "stEIP4844-blobtransactions",
];

fn should_skip(path: &Path) -> bool {
Expand Down
Loading

0 comments on commit 608c6cb

Please sign in to comment.