Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimism RPC Types #2

Merged
merged 25 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0582d5c
chore: add serde and alloy_primitives to the dependencies
EmperorOrokuSaki Apr 10, 2024
dbdcda9
feat: add transaction receipt type without tests + several dependencies.
EmperorOrokuSaki Apr 10, 2024
1ebd0e0
feat: add log
EmperorOrokuSaki Apr 10, 2024
15eb436
feat: add txtype, deposit nonce, and receipt version.
EmperorOrokuSaki Apr 10, 2024
599c9a2
feat: add block.
EmperorOrokuSaki Apr 10, 2024
2def3b0
feat: add txType as a separate file under transactions and update rec…
EmperorOrokuSaki Apr 10, 2024
6b0c42a
refactor: update optimism specific fields and their (de)serialization…
EmperorOrokuSaki Apr 10, 2024
87742c3
docs: remove outdated documentation.
EmperorOrokuSaki Apr 10, 2024
516eb59
feat: add transaction, and request types. Adjust block to use the cra…
EmperorOrokuSaki Apr 10, 2024
fafe2aa
feat: add op-consensus and receiptEnvelope
EmperorOrokuSaki Apr 11, 2024
2599060
feat: add call.rs and update visibility of transaction requests, type…
EmperorOrokuSaki Apr 11, 2024
d5c9b78
lint: cargo fmt.
EmperorOrokuSaki Apr 11, 2024
b9169e9
feat: add pubsub.rs
EmperorOrokuSaki Apr 12, 2024
f1675b9
feat: fix imports, add TODO comments, organize the code.
EmperorOrokuSaki Apr 12, 2024
d939344
lint: cargo fmt
EmperorOrokuSaki Apr 12, 2024
5dbd2f5
fix: receipt.rs imports are fixed.
EmperorOrokuSaki Apr 12, 2024
2304918
feat: add filters.rs
EmperorOrokuSaki Apr 12, 2024
2ad3438
feat: re-export all eth types.
EmperorOrokuSaki Apr 12, 2024
6a72e80
feat: review changes.
EmperorOrokuSaki Apr 15, 2024
93141f0
refactor: re-import instead of redefining.
EmperorOrokuSaki Apr 18, 2024
b5005c9
chore: bump alloy version.
EmperorOrokuSaki Apr 20, 2024
577749e
feat: use generics, remove unnecessary types.
EmperorOrokuSaki Apr 20, 2024
0744884
lint: fmt
EmperorOrokuSaki Apr 20, 2024
12195e1
refactor: use native types
EmperorOrokuSaki Apr 25, 2024
cf248d4
chore: bump alloy version
EmperorOrokuSaki Apr 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ homepage = "https://github.com/alloy-rs/op-alloy"
repository = "https://github.com/alloy-rs/op-alloy"
exclude = ["benches/", "tests/"]

[workspace.dependencies]
# Alloy
alloy-primitives = { version = "0.7.1", default-features = false }
alloy = { git = "https://github.com/alloy-rs/alloy", rev = "004aa98", features = [
"serde",
"rpc-types-eth",
"rpc-types","rlp","consensus"
] }
op-rpc-types = { version = "0.1.0", default-features = false, path = "crates/op-rpc-types" }

# Serde
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

## misc-testing
arbitrary = { version = "1.3", features = ["derive"] }
rand = "0.8"
proptest = "1.4"
proptest-derive = "0.4"

[workspace.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
32 changes: 32 additions & 0 deletions crates/op-rpc-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,35 @@ homepage.workspace = true
authors.workspace = true
repository.workspace = true
exclude.workspace = true

[dependencies]
# alloy-rlp = { workspace = true, features = ["arrayvec", "derive"] }
alloy-primitives = { workspace = true, features = ["rlp", "serde", "std"] }
# alloy-serde.workspace = true
# alloy-genesis.workspace = true

# alloy-consensus = { workspace = true, features = ["std", "serde"] }
# alloy-eips = { workspace = true, features = ["std", "serde"] }
EmperorOrokuSaki marked this conversation as resolved.
Show resolved Hide resolved

serde = { workspace = true, features = ["derive"] }
alloy = { workspace = true , features = ["serde", "rpc-types", "rpc-types-eth", "rlp", "consensus"]}
serde_json.workspace = true

# arbitrary
arbitrary = { version = "1.3", features = ["derive"], optional = true }
proptest = { version = "1.4", optional = true }
proptest-derive = { version = "0.4", optional = true }

[features]
arbitrary = [
"dep:arbitrary",
"dep:proptest-derive",
"dep:proptest",
"alloy-primitives/arbitrary",
]

[dev-dependencies]
arbitrary = { workspace = true, features = ["derive"] }
proptest.workspace = true
proptest-derive.workspace = true
rand.workspace = true
2 changes: 1 addition & 1 deletion crates/op-rpc-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@

mod op;
5 changes: 5 additions & 0 deletions crates/op-rpc-types/src/op/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod transaction;
use crate::op::transaction::Transaction;
use alloy::rpc::types::eth::FilterChanges as EthFilterChanges;

pub type FilterChanges = EthFilterChanges<Transaction>;
188 changes: 188 additions & 0 deletions crates/op-rpc-types/src/op/transaction/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
use alloy::{
consensus::{Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEnvelope, TxLegacy},
rpc::types::eth::{ConversionError, TransactionRequest},
};
use alloy_primitives::{B256, U128, U64};
use serde::{Deserialize, Serialize};

use self::tx_type::TxType;

pub mod receipt;
pub mod tx_type;

#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
EmperorOrokuSaki marked this conversation as resolved.
Show resolved Hide resolved
/// Ethereum Transaction Types
#[serde(flatten)]
pub inner: alloy::rpc::types::eth::Transaction,
/// The ETH value to mint on L2
#[serde(rename = "mint", skip_serializing_if = "Option::is_none")]
pub mint: Option<u128>,
/// Hash that uniquely identifies the source of the deposit.
#[serde(rename = "sourceHash", skip_serializing_if = "Option::is_none")]
pub source_hash: Option<B256>,
/// Field indicating whether the transaction is a system transaction, and therefore
/// exempt from the L2 gas limit.
#[serde(rename = "isSystemTx", skip_serializing_if = "Option::is_none")]
pub is_system_tx: Option<bool>,
/// Deposit receipt version for deposit transactions post-canyon
#[serde(skip_serializing_if = "Option::is_none")]
pub deposit_receipt_version: Option<u64>,
}

impl Transaction {
/// Converts [Transaction] into [TransactionRequest].
///
/// During this conversion data for [TransactionRequest::sidecar] is not populated as it is not
/// part of [Transaction].
pub fn into_request(self) -> TransactionRequest {
let gas_price = match (self.gas_price, self.max_fee_per_gas) {
(Some(gas_price), None) => Some(gas_price),
// EIP-1559 transactions include deprecated `gasPrice` field displaying gas used by
// transaction.
// Setting this field for resulted tx request will result in it being invalid
(_, Some(_)) => None,
// unreachable
(None, None) => None,
};
TransactionRequest {
from: Some(self.from),
to: self.to,
gas: Some(self.gas),
gas_price,
value: Some(self.value),
input: self.input.into(),
nonce: Some(self.nonce),
chain_id: self.chain_id,
access_list: self.access_list,
transaction_type: self.transaction_type,
max_fee_per_gas: self.max_fee_per_gas,
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
max_fee_per_blob_gas: self.max_fee_per_blob_gas,
blob_versioned_hashes: self.blob_versioned_hashes,
sidecar: self.sidecar,
transaction_type: self.transaction_type,
}
}
}

impl TryFrom<Transaction> for Signed<TxLegacy> {
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
let signature = tx.signature.ok_or(ConversionError::MissingSignature)?.try_into()?;

let tx = TxLegacy {
chain_id: tx.chain_id,
nonce: tx.nonce,
gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?,
gas_limit: tx.gas,
to: tx.to.into(),
value: tx.value,
input: tx.input,
};
Ok(tx.into_signed(signature))
}
}

impl TryFrom<Transaction> for Signed<TxEip1559> {
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
let signature = tx.signature.ok_or(ConversionError::MissingSignature)?.try_into()?;

let tx = TxEip1559 {
chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?,
nonce: tx.nonce,
max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?,
max_priority_fee_per_gas: tx
.max_priority_fee_per_gas
.ok_or(ConversionError::MissingMaxPriorityFeePerGas)?,
gas_limit: tx.gas,
to: tx.to.into(),
value: tx.value,
input: tx.input,
access_list: tx.access_list.unwrap_or_default(),
};
Ok(tx.into_signed(signature))
}
}

impl TryFrom<Transaction> for Signed<TxEip2930> {
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
let signature = tx.signature.ok_or(ConversionError::MissingSignature)?.try_into()?;

let tx = TxEip2930 {
chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?,
nonce: tx.nonce,
gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?,
gas_limit: tx.gas,
to: tx.to.into(),
value: tx.value,
input: tx.input,
access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?,
};
Ok(tx.into_signed(signature))
}
}

impl TryFrom<Transaction> for Signed<TxEip4844> {
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
let signature = tx.signature.ok_or(ConversionError::MissingSignature)?.try_into()?;
let tx = TxEip4844 {
chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?,
nonce: tx.nonce,
max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?,
max_priority_fee_per_gas: tx
.max_priority_fee_per_gas
.ok_or(ConversionError::MissingMaxPriorityFeePerGas)?,
gas_limit: tx.gas,
to: tx.to.ok_or(ConversionError::MissingTo)?,
value: tx.value,
input: tx.input,
access_list: tx.access_list.unwrap_or_default(),
blob_versioned_hashes: tx.blob_versioned_hashes.unwrap_or_default(),
max_fee_per_blob_gas: tx
.max_fee_per_blob_gas
.ok_or(ConversionError::MissingMaxFeePerBlobGas)?,
};
Ok(tx.into_signed(signature))
}
}

impl TryFrom<Transaction> for Signed<TxEip4844Variant> {
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
let tx: Signed<TxEip4844> = tx.try_into()?;
let (inner, signature, _) = tx.into_parts();
let tx = TxEip4844Variant::TxEip4844(inner);

Ok(tx.into_signed(signature))
}
}

// TODO: Implement a impl TryFrom<Transaction> for Signed<Deposit> when the consensus types are
// ready

impl TryFrom<Transaction> for TxEnvelope {
// TODO: When the TxEnvelope is implemented for op-consensus, import it from there. This
// envelope doesn't handle DEPOSIT
type Error = ConversionError;

fn try_from(tx: Transaction) -> Result<Self, Self::Error> {
match tx.transaction_type.unwrap_or_default().try_into()? {
TxType::Legacy => Ok(Self::Legacy(tx.try_into()?)),
TxType::Eip1559 => Ok(Self::Eip1559(tx.try_into()?)),
TxType::Eip2930 => Ok(Self::Eip2930(tx.try_into()?)),
TxType::Eip4844 => Ok(Self::Eip4844(tx.try_into()?)),
TxType::Deposit => Ok(Self::Deposit(tx.try_into()?)),
}
}
}
Loading