Skip to content

Commit

Permalink
Merge branch 'main' into operator-fee
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell authored Oct 1, 2024
2 parents d9896ec + ddc36fe commit 76db74d
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 291 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.2](https://github.com/alloy-rs/op-alloy
/releases/tag/v0.3.2) - 2024-09-30

### Features

- [consensus] Bincode compatibility ([#131](https://github.com/alloy-rs/op-alloy/issues/131))

### Miscellaneous Tasks

- [genesis] Small README Update ([#128](https://github.com/alloy-rs/op-alloy/issues/128))

## [0.3.1](https://github.com/alloy-rs/op-alloy
/releases/tag/v0.3.1) - 2024-09-30

### Bug Fixes

- HashMap default

### Miscellaneous Tasks

- Release 0.3.1

## [0.3.0](https://github.com/alloy-rs/op-alloy
/releases/tag/v0.3.0) - 2024-09-30

Expand Down
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"

[workspace.package]
version = "0.3.1"
version = "0.3.2"
edition = "2021"
rust-version = "1.81"
authors = ["Alloy Contributors"]
Expand Down Expand Up @@ -36,12 +36,12 @@ rustdoc-args = ["--cfg", "docsrs"]

[workspace.dependencies]
# Alloy
op-alloy-rpc-jsonrpsee = { version = "0.3.1", path = "crates/rpc-jsonrpsee" }
op-alloy-rpc-types = { version = "0.3.1", path = "crates/rpc-types" }
op-alloy-rpc-types-engine = { version = "0.3.1", path = "crates/rpc-types-engine" }
op-alloy-consensus = { version = "0.3.1", path = "crates/consensus", default-features = false }
op-alloy-genesis = { version = "0.3.1", path = "crates/genesis", default-features = false }
op-alloy-protocol = { version = "0.3.1", path = "crates/protocol", default-features = false }
op-alloy-rpc-jsonrpsee = { version = "0.3.2", path = "crates/rpc-jsonrpsee" }
op-alloy-rpc-types = { version = "0.3.2", path = "crates/rpc-types" }
op-alloy-rpc-types-engine = { version = "0.3.2", path = "crates/rpc-types-engine" }
op-alloy-consensus = { version = "0.3.2", path = "crates/consensus", default-features = false }
op-alloy-genesis = { version = "0.3.2", path = "crates/genesis", default-features = false }
op-alloy-protocol = { version = "0.3.2", path = "crates/protocol", default-features = false }

alloy-rlp = { version = "0.3", default-features = false }
alloy-primitives = { version = "0.8", default-features = false }
Expand Down
6 changes: 5 additions & 1 deletion crates/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ arbitrary = { workspace = true, features = ["derive"], optional = true }
# serde
alloy-serde = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
serde_with = { version = "3.9", optional = true }

# misc
spin.workspace = true
Expand All @@ -35,8 +36,10 @@ derive_more = { workspace = true, features = ["display"] }
alloy-primitives = { workspace = true, features = ["rand"] }
alloy-signer.workspace = true
arbitrary = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["macros"] }
bincode = "1.3"
rand.workspace = true
serde_json.workspace = true
tokio = { workspace = true, features = ["macros"] }

[features]
default = ["std"]
Expand All @@ -45,3 +48,4 @@ k256 = ["alloy-primitives/k256", "alloy-consensus/k256"]
kzg = ["alloy-eips/kzg", "alloy-consensus/kzg", "std"]
arbitrary = ["std", "dep:arbitrary", "alloy-consensus/arbitrary", "alloy-eips/arbitrary", "alloy-primitives/rand"]
serde = ["dep:serde", "dep:alloy-serde", "alloy-primitives/serde", "alloy-consensus/serde", "alloy-eips/serde"]
serde-bincode-compat = ["serde_with"]
12 changes: 12 additions & 0 deletions crates/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,15 @@ pub use hardforks::Hardforks;

mod block;
pub use block::OpBlock;

/// Bincode-compatible serde implementations for consensus types.
///
/// `bincode` crate doesn't work well with optionally serializable serde fields, but some of the
/// consensus types require optional serialization for RPC compatibility. This module makes so that
/// all fields are serialized.
///
/// Read more: <https://github.com/bincode-org/bincode/issues/326>
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub mod serde_bincode_compat {
pub use super::transaction::serde_bincode_compat::TxDeposit;
}
117 changes: 117 additions & 0 deletions crates/consensus/src/transaction/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,120 @@ mod tests {
assert!(total_len > len_without_header);
}
}

/// Bincode-compatible [`TxDeposit`] serde implementation.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
use alloc::borrow::Cow;
use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};

/// Bincode-compatible [`super::TxDeposit`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use op_alloy_consensus::{serde_bincode_compat, TxDeposit};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::TxDeposit")]
/// transaction: TxDeposit,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct TxDeposit<'a> {
source_hash: B256,
from: Address,
#[serde(default)]
to: TxKind,
#[serde(default)]
mint: Option<u128>,
value: U256,
gas_limit: u64,
is_system_transaction: bool,
input: Cow<'a, Bytes>,
}

impl<'a> From<&'a super::TxDeposit> for TxDeposit<'a> {
fn from(value: &'a super::TxDeposit) -> Self {
Self {
source_hash: value.source_hash,
from: value.from,
to: value.to,
mint: value.mint,
value: value.value,
gas_limit: value.gas_limit,
is_system_transaction: value.is_system_transaction,
input: Cow::Borrowed(&value.input),
}
}
}

impl<'a> From<TxDeposit<'a>> for super::TxDeposit {
fn from(value: TxDeposit<'a>) -> Self {
Self {
source_hash: value.source_hash,
from: value.from,
to: value.to,
mint: value.mint,
value: value.value,
gas_limit: value.gas_limit,
is_system_transaction: value.is_system_transaction,
input: value.input.into_owned(),
}
}
}

impl<'a> SerializeAs<super::TxDeposit> for TxDeposit<'a> {
fn serialize_as<S>(source: &super::TxDeposit, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
TxDeposit::from(source).serialize(serializer)
}
}

impl<'de> DeserializeAs<'de, super::TxDeposit> for TxDeposit<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::TxDeposit, D::Error>
where
D: Deserializer<'de>,
{
TxDeposit::deserialize(deserializer).map(Into::into)
}
}

#[cfg(test)]
mod tests {
use arbitrary::Arbitrary;
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;

use super::super::{serde_bincode_compat, TxDeposit};

#[test]
fn test_tx_deposit_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::TxDeposit")]
transaction: TxDeposit,
}

let mut bytes = [0u8; 1024];
rand::thread_rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: TxDeposit::arbitrary(&mut arbitrary::Unstructured::new(&bytes))
.unwrap(),
};

let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}
6 changes: 6 additions & 0 deletions crates/consensus/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ pub use source::{
DepositSourceDomain, DepositSourceDomainIdentifier, L1InfoDepositSource, UpgradeDepositSource,
UserDepositSource,
};

/// Bincode-compatible serde implementations for transaction types.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
pub use super::deposit::serde_bincode_compat::TxDeposit;
}
2 changes: 1 addition & 1 deletion crates/protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub use frame::{
};

mod utils;
pub use utils::starts_with_2718_deposit;
pub use utils::{starts_with_2718_deposit, to_system_config, OpBlockConversionError};

mod channel;
pub use channel::{
Expand Down
104 changes: 104 additions & 0 deletions crates/protocol/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
//! Utility methods used by protocol types.
use crate::{
block_info::DecodeError, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoHolocene,
L1BlockInfoTx,
};
use alloy_primitives::B256;
use op_alloy_consensus::{OpBlock, OpTxEnvelope};
use op_alloy_genesis::{RollupConfig, SystemConfig};

/// Returns if the given `value` is a deposit transaction.
pub fn starts_with_2718_deposit<B>(value: &B) -> bool
where
Expand All @@ -8,6 +16,102 @@ where
value.as_ref().first() == Some(&0x7E)
}

/// An error encountered during [OpBlock] conversion.
#[derive(Debug, derive_more::Display)]
pub enum OpBlockConversionError {
/// Invalid genesis hash.
#[display("Invalid genesis hash. Expected {_0}, got {_1}")]
InvalidGenesisHash(B256, B256),
/// Invalid transaction type.
#[display("First payload transaction has unexpected type: {_0}")]
InvalidTxType(u8),
/// L1 Info error
#[display("Failed to decode L1 info: {_0}")]
L1InfoError(DecodeError),
/// Missing system config in genesis block.
#[display("Missing system config in genesis block")]
MissingSystemConfigGenesis,
/// Empty transactions.
#[display("Empty transactions in payload. Block hash: {_0}")]
EmptyTransactions(B256),
}

impl core::error::Error for OpBlockConversionError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::L1InfoError(err) => Some(err),
_ => None,
}
}
}

impl From<DecodeError> for OpBlockConversionError {
fn from(e: DecodeError) -> Self {
Self::L1InfoError(e)
}
}

/// Converts the [OpBlock] to a partial [SystemConfig].
pub fn to_system_config(
block: &OpBlock,
rollup_config: &RollupConfig,
) -> Result<SystemConfig, OpBlockConversionError> {
if block.header.number == rollup_config.genesis.l2.number {
if block.header.hash_slow() != rollup_config.genesis.l2.hash {
return Err(OpBlockConversionError::InvalidGenesisHash(
rollup_config.genesis.l2.hash,
block.header.hash_slow(),
));
}
return rollup_config
.genesis
.system_config
.ok_or(OpBlockConversionError::MissingSystemConfigGenesis);
}

if block.body.transactions.is_empty() {
return Err(OpBlockConversionError::EmptyTransactions(block.header.hash_slow()));
}
let OpTxEnvelope::Deposit(ref tx) = block.body.transactions[0] else {
return Err(OpBlockConversionError::InvalidTxType(
block.body.transactions[0].tx_type() as u8
));
};

let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?;
let l1_fee_scalar = match l1_info {
L1BlockInfoTx::Bedrock(L1BlockInfoBedrock { l1_fee_scalar, .. }) => l1_fee_scalar,
L1BlockInfoTx::Ecotone(L1BlockInfoEcotone {
base_fee_scalar,
blob_base_fee_scalar,
..
})
| L1BlockInfoTx::Holocene(L1BlockInfoHolocene {
base_fee_scalar,
blob_base_fee_scalar,
..
}) => {
// Translate Ecotone values back into encoded scalar if needed.
// We do not know if it was derived from a v0 or v1 scalar,
// but v1 is fine, a 0 blob base fee has the same effect.
let mut buf = B256::ZERO;
buf[0] = 0x01;
buf[24..28].copy_from_slice(blob_base_fee_scalar.to_be_bytes().as_ref());
buf[28..32].copy_from_slice(base_fee_scalar.to_be_bytes().as_ref());
buf.into()
}
};

Ok(SystemConfig {
batcher_address: l1_info.batcher_address(),
overhead: l1_info.l1_fee_overhead(),
scalar: l1_fee_scalar,
gas_limit: block.header.gas_limit,
base_fee_scalar: None,
blob_base_fee_scalar: None,
})
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 0 additions & 7 deletions crates/rpc-types-engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@ exclude.workspace = true
workspace = true

[dependencies]
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rpc-types-engine.workspace = true
op-alloy-protocol.workspace = true
op-alloy-genesis.workspace = true
op-alloy-consensus.workspace = true

derive_more = { workspace = true, features = ["display"] }

Expand All @@ -37,14 +34,10 @@ std = [
"alloy-primitives/std",
"alloy-rpc-types-engine/std",
"op-alloy-protocol/std",
"op-alloy-genesis/std",
"op-alloy-consensus/std",
]
serde = [
"dep:serde",
"dep:alloy-serde",
"op-alloy-genesis/serde",
"op-alloy-protocol/serde",
"alloy-rpc-types-engine/serde",
"op-alloy-consensus/serde",
]
Loading

0 comments on commit 76db74d

Please sign in to comment.