Skip to content

Commit

Permalink
Merge pull request #12 from alloy-rs/matt/add-network-crates
Browse files Browse the repository at this point in the history
feat: add OP network
  • Loading branch information
mattsse committed Jun 15, 2024
2 parents 641fcd6 + 9fe86af commit e2542c1
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 14 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
cache-on-failure: true
- name: cargo hack
run: |
cargo hack build --workspace --target wasm32-unknown-unknown
cargo hack build --workspace --target wasm32-unknown-unknown --exclude op-alloy-network --exclude op-alloy-rpc-types
wasm-wasi:
runs-on: ubuntu-latest
Expand All @@ -94,7 +94,7 @@ jobs:
cache-on-failure: true
- name: cargo hack
run: |
cargo hack build --workspace --target wasm32-wasi
cargo hack build --workspace --target wasm32-wasi --exclude op-alloy-network --exclude op-alloy-rpc-types
no-std:
runs-on: ubuntu-latest
Expand Down
24 changes: 18 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,32 @@ homepage = "https://github.com/alloy-rs/op-alloy"
repository = "https://github.com/alloy-rs/op-alloy"
exclude = ["benches/", "tests/"]

[workspace.lints]
rust.unused_must_use = "deny"
rust.rust_2018_idioms = "deny"
rustdoc.all = "warn"

[workspace.lints.clippy]
all = "warn"
missing_const_for_fn = "warn"
use_self = "warn"
option_if_let_else = "warn"

[workspace.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[workspace.dependencies]
# Alloy
op-alloy-rpc-types = { path = "crates/rpc-types" }
op-alloy-consensus = { path = "crates/rpc-types" }
op-alloy-rpc-types = { version = "0.1.0", path = "crates/rpc-types" }
op-alloy-consensus = { version = "0.1.0", path = "crates/op-consensus" }

alloy-rlp = { version = "0.3", default-features = false }
alloy-primitives = { version = "0.7.1", default-features = false }

alloy = { git = "https://github.com/alloy-rs/alloy" }
alloy-consensus = { git = "https://github.com/alloy-rs/alloy", default-features = false}
alloy-network = { git = "https://github.com/alloy-rs/alloy", default-features = false }
alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy" }
alloy-rpc-types-eth = { git = "https://github.com/alloy-rs/alloy" }
alloy-eips = { git = "https://github.com/alloy-rs/alloy", default-features = false }
Expand All @@ -43,7 +59,3 @@ tokio = "1"
## crypto
c-kzg = { version = "1.0", default-features = false }
k256 = { version = "0.13", default-features = false, features = ["ecdsa"] }

[workspace.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
26 changes: 26 additions & 0 deletions crates/network/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "op-alloy-network"
description = "Optimism blockchain RPC behavior abstraction"

version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
exclude.workspace = true

[lints]
workspace = true

[dependencies]
op-alloy-consensus = { workspace = true, features = ["serde"] }
op-alloy-rpc-types.workspace = true

alloy-consensus.workspace = true
alloy-network.workspace = true
alloy-primitives.workspace = true
alloy-rpc-types-eth.workspace = true


8 changes: 8 additions & 0 deletions crates/network/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# op-alloy-network

Optimism blockchain RPC behavior abstraction.

This crate contains a simple abstraction of the RPC behavior of an
Op-stack blockchain. It is intended to be used by the Alloy client to
provide a consistent interface to the rest of the library, regardless of
changes the underlying blockchain makes to the RPC interface.
191 changes: 191 additions & 0 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg",
html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

use alloy_consensus::{BlobTransactionSidecar, TxType};
pub use alloy_network::*;
use alloy_primitives::{Address, Bytes, ChainId, TxKind, U256};
use alloy_rpc_types_eth::AccessList;

/// Types for an Op-stack network.
#[derive(Clone, Copy, Debug)]
pub struct Optimism {
_private: (),
}

impl Network for Optimism {
type TxType = TxType;

type TxEnvelope = alloy_consensus::TxEnvelope;

type UnsignedTx = alloy_consensus::TypedTransaction;

type ReceiptEnvelope = op_alloy_consensus::OpReceiptEnvelope;

type Header = alloy_consensus::Header;

type TransactionRequest = alloy_rpc_types_eth::transaction::TransactionRequest;

type TransactionResponse = alloy_rpc_types_eth::Transaction;

type ReceiptResponse = op_alloy_rpc_types::OpTransactionReceipt;

type HeaderResponse = alloy_rpc_types_eth::Header;
}

impl TransactionBuilder<Optimism> for alloy_rpc_types_eth::transaction::TransactionRequest {
fn chain_id(&self) -> Option<ChainId> {
self.chain_id
}

fn set_chain_id(&mut self, chain_id: ChainId) {
self.chain_id = Some(chain_id);
}

fn nonce(&self) -> Option<u64> {
self.nonce
}

fn set_nonce(&mut self, nonce: u64) {
self.nonce = Some(nonce);
}

fn input(&self) -> Option<&Bytes> {
self.input.input()
}

fn set_input<T: Into<Bytes>>(&mut self, input: T) {
self.input.input = Some(input.into());
}

fn from(&self) -> Option<Address> {
self.from
}

fn set_from(&mut self, from: Address) {
self.from = Some(from);
}

fn kind(&self) -> Option<TxKind> {
self.to
}

fn clear_kind(&mut self) {
self.to = None;
}

fn set_kind(&mut self, kind: TxKind) {
self.to = Some(kind);
}

fn value(&self) -> Option<U256> {
self.value
}

fn set_value(&mut self, value: U256) {
self.value = Some(value)
}

fn gas_price(&self) -> Option<u128> {
self.gas_price
}

fn set_gas_price(&mut self, gas_price: u128) {
self.gas_price = Some(gas_price);
}

fn max_fee_per_gas(&self) -> Option<u128> {
self.max_fee_per_gas
}

fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128) {
self.max_fee_per_gas = Some(max_fee_per_gas);
}

fn max_priority_fee_per_gas(&self) -> Option<u128> {
self.max_priority_fee_per_gas
}

fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128) {
self.max_priority_fee_per_gas = Some(max_priority_fee_per_gas);
}

fn max_fee_per_blob_gas(&self) -> Option<u128> {
self.max_fee_per_blob_gas
}

fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
self.max_fee_per_blob_gas = Some(max_fee_per_blob_gas)
}

fn gas_limit(&self) -> Option<u128> {
self.gas
}

fn set_gas_limit(&mut self, gas_limit: u128) {
self.gas = Some(gas_limit);
}

fn access_list(&self) -> Option<&AccessList> {
self.access_list.as_ref()
}

fn set_access_list(&mut self, access_list: AccessList) {
self.access_list = Some(access_list);
}

fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> {
self.sidecar.as_ref()
}

fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
TransactionBuilder::<Ethereum>::set_blob_sidecar(self, sidecar)
}

fn complete_type(&self, ty: TxType) -> Result<(), Vec<&'static str>> {
TransactionBuilder::<Ethereum>::complete_type(self, ty)
}

fn can_submit(&self) -> bool {
TransactionBuilder::<Ethereum>::can_submit(self)
}

fn can_build(&self) -> bool {
TransactionBuilder::<Ethereum>::can_build(self)
}

#[doc(alias = "output_transaction_type")]
fn output_tx_type(&self) -> TxType {
self.preferred_type()
}

#[doc(alias = "output_transaction_type_checked")]
fn output_tx_type_checked(&self) -> Option<TxType> {
self.buildable_type()
}

fn prep_for_submission(&mut self) {
self.transaction_type = Some(self.preferred_type() as u8);
self.trim_conflicting_keys();
self.populate_blob_hashes();
}

fn build_unsigned(self) -> BuildResult<alloy_consensus::TypedTransaction, Optimism> {
if let Err((tx_type, missing)) = self.missing_keys() {
return Err(TransactionBuilderError::InvalidTransactionRequest(tx_type, missing)
.into_unbuilt(self));
}
Ok(self.build_typed_tx().expect("checked by missing_keys"))
}

async fn build<W: NetworkWallet<Optimism>>(
self,
wallet: &W,
) -> Result<<Optimism as Network>::TxEnvelope, TransactionBuilderError<Optimism>> {
Ok(wallet.sign_request(self).await?)
}
}
1 change: 1 addition & 0 deletions crates/op-consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ arbitrary = { workspace = true, features = ["derive"], optional = true }
serde = { workspace = true, features = ["derive"], optional = true }

[dev-dependencies]
alloy-primitives = { workspace = true, features = ["rand"] }
alloy-signer.workspace = true
arbitrary = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["macros"] }
Expand Down
31 changes: 30 additions & 1 deletion crates/op-consensus/src/receipt/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{OpDepositReceipt, OpDepositReceiptWithBloom, OpTxType};
use alloy_consensus::{Receipt, ReceiptWithBloom};
use alloy_consensus::{Eip658Value, Receipt, ReceiptWithBloom, TxReceipt};
use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718};
use alloy_primitives::{Bloom, Log};
use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable};
Expand Down Expand Up @@ -147,6 +147,35 @@ impl OpReceiptEnvelope {
}
}

impl<T> TxReceipt<T> for OpReceiptEnvelope<T> {
fn status_or_post_state(&self) -> &Eip658Value {
&self.as_receipt().unwrap().status
}

fn status(&self) -> bool {
self.as_receipt().unwrap().status.coerce_status()
}

/// Return the receipt's bloom.
fn bloom(&self) -> Bloom {
*self.logs_bloom()
}

fn bloom_cheap(&self) -> Option<Bloom> {
Some(self.bloom())
}

/// Returns the cumulative gas used at this receipt.
fn cumulative_gas_used(&self) -> u128 {
self.as_receipt().unwrap().cumulative_gas_used
}

/// Return the receipt logs.
fn logs(&self) -> &[T] {
&self.as_receipt().unwrap().logs
}
}

impl Encodable for OpReceiptEnvelope {
fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
self.network_encode(out)
Expand Down
14 changes: 9 additions & 5 deletions crates/op-consensus/src/receipt/receipts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable};

#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::borrow::Borrow;

/// Receipt containing result of transaction execution.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
Expand Down Expand Up @@ -46,7 +47,10 @@ impl<T> AsRef<Receipt<T>> for OpDepositReceipt<T> {
}
}

impl TxReceipt for OpDepositReceipt {
impl<T> TxReceipt<T> for OpDepositReceipt<T>
where
T: Borrow<Log>,
{
fn status_or_post_state(&self) -> &Eip658Value {
self.inner.status_or_post_state()
}
Expand All @@ -56,15 +60,15 @@ impl TxReceipt for OpDepositReceipt {
}

fn bloom(&self) -> Bloom {
self.bloom_slow()
self.inner.bloom_slow()
}

fn cumulative_gas_used(&self) -> u128 {
self.inner.cumulative_gas_used
self.inner.cumulative_gas_used()
}

fn logs(&self) -> &[Log] {
&self.inner.logs
fn logs(&self) -> &[T] {
self.inner.logs()
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/rpc-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ repository.workspace = true
exclude.workspace = true

[dependencies]
op-alloy-consensus = { workspace = true, features = ["serde"] }

alloy-primitives = { workspace = true, features = ["rlp", "serde", "std"] }
alloy-rpc-types-eth.workspace = true
alloy-network.workspace = true

serde = { workspace = true, features = ["derive"] }

Expand Down
Loading

0 comments on commit e2542c1

Please sign in to comment.