diff --git a/Cargo.toml b/Cargo.toml index da6e95c2293..1d4b29a088d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,8 +87,8 @@ alloy-chains = { version = "0.2", default-features = false } # eips alloy-eip2124 = { version = "0.2.0", default-features = false } -alloy-eip2930 = { version = "0.2.0", default-features = false } -alloy-eip7702 = { version = "0.6.1", default-features = false } +alloy-eip2930 = { version = "0.2.3", default-features = false } +alloy-eip7702 = { version = "0.6.3", default-features = false } # hardforks alloy-hardforks = "0.2.0" @@ -153,6 +153,7 @@ bincode = "2.0" auto_impl = "1.2" base64 = "0.22" bimap = "0.6" +borsh = { version = "1.5", default-features = false } cfg-if = "1" derive_more = { version = "2", default-features = false } either = { version = "1.15", default-features = false } diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index 36a1f9a7e32..90dfd4eccb6 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -40,6 +40,9 @@ c-kzg = { workspace = true, features = ["serde"], optional = true } arbitrary = { workspace = true, features = ["derive"], optional = true } rand = { workspace = true, optional = true } +# borsh +borsh = { workspace = true, optional = true, features = ["derive"] } + # serde serde = { workspace = true, features = ["derive"], optional = true } serde_with = { workspace = true, optional = true } @@ -74,21 +77,22 @@ assert_matches.workspace = true [features] default = ["std"] std = [ - "alloy-eips/std", - "c-kzg?/std", - "alloy-serde?/std", - "alloy-primitives/std", - "alloy-rlp/std", - "alloy-trie/std", - "derive_more/std", - "k256?/std", - "serde?/std", - "serde_json?/std", - "serde_with?/std", - "thiserror/std", - "either/std", - "once_cell/std", - "secp256k1?/std" + "alloy-eips/std", + "c-kzg?/std", + "alloy-serde?/std", + "alloy-primitives/std", + "alloy-rlp/std", + "alloy-trie/std", + "derive_more/std", + "k256?/std", + "serde?/std", + "serde_json?/std", + "serde_with?/std", + "thiserror/std", + "either/std", + "once_cell/std", + "secp256k1?/std", + "borsh?/std" ] k256 = ["dep:k256", "alloy-primitives/k256", "alloy-eips/k256"] secp256k1 = ["dep:secp256k1"] @@ -120,3 +124,8 @@ serde = [ "alloy-tx-macros/serde" ] serde-bincode-compat = ["alloy-eips/serde-bincode-compat", "serde_with"] +borsh = [ + "dep:borsh", + "alloy-primitives/borsh", + "alloy-eips/borsh", +] diff --git a/crates/consensus/src/block/header.rs b/crates/consensus/src/block/header.rs index 48ca2c6666a..62a0927c62c 100644 --- a/crates/consensus/src/block/header.rs +++ b/crates/consensus/src/block/header.rs @@ -21,6 +21,7 @@ use core::mem; #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct Header { /// The Keccak 256-bit hash of the parent /// block’s header, in its entirety; formally Hp. diff --git a/crates/consensus/src/block/mod.rs b/crates/consensus/src/block/mod.rs index 92525a955f6..0a99e59d1f1 100644 --- a/crates/consensus/src/block/mod.rs +++ b/crates/consensus/src/block/mod.rs @@ -27,6 +27,7 @@ use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable}; /// See p2p block encoding reference: #[derive(Debug, Clone, PartialEq, Eq, derive_more::Deref)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct Block { /// Block header. #[deref] @@ -212,6 +213,7 @@ where /// Withdrawals can be optionally included at the end of the RLP encoded message. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[rlp(trailing)] pub struct BlockBody { /// Transactions in this block. diff --git a/crates/consensus/src/receipt/envelope.rs b/crates/consensus/src/receipt/envelope.rs index b2ba2dd9c82..d4a99fa17ed 100644 --- a/crates/consensus/src/receipt/envelope.rs +++ b/crates/consensus/src/receipt/envelope.rs @@ -24,6 +24,7 @@ use core::fmt; #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(tag = "type"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "TransactionReceiptEnvelope", alias = "TxReceiptEnvelope")] pub enum ReceiptEnvelope { /// Receipt envelope with no type flag. diff --git a/crates/consensus/src/receipt/receipts.rs b/crates/consensus/src/receipt/receipts.rs index 759e138991c..24adcdf8232 100644 --- a/crates/consensus/src/receipt/receipts.rs +++ b/crates/consensus/src/receipt/receipts.rs @@ -12,6 +12,7 @@ use core::fmt; #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "TransactionReceipt", alias = "TxReceipt")] pub struct Receipt { /// If transaction is executed successfully. @@ -254,6 +255,7 @@ impl Default for Receipts { #[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "TransactionReceiptWithBloom", alias = "TxReceiptWithBloom")] pub struct ReceiptWithBloom> { #[cfg_attr(feature = "serde", serde(flatten))] diff --git a/crates/consensus/src/receipt/status.rs b/crates/consensus/src/receipt/status.rs index 3580bef13b8..ea44fed5fc0 100644 --- a/crates/consensus/src/receipt/status.rs +++ b/crates/consensus/src/receipt/status.rs @@ -4,6 +4,7 @@ use alloy_rlp::{Buf, BufMut, Decodable, Encodable, Error, Header}; /// Captures the result of a transaction execution. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub enum Eip658Value { /// A boolean `statusCode` introduced by [EIP-658]. /// diff --git a/crates/consensus/src/transaction/eip1559.rs b/crates/consensus/src/transaction/eip1559.rs index 7cf881924d4..524d272468f 100644 --- a/crates/consensus/src/transaction/eip1559.rs +++ b/crates/consensus/src/transaction/eip1559.rs @@ -13,6 +13,7 @@ use super::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx}; #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "Eip1559Transaction", alias = "TransactionEip1559", alias = "Eip1559Tx")] pub struct TxEip1559 { /// EIP-155: Simple replay attack protection @@ -56,6 +57,8 @@ pub struct TxEip1559 { /// The 160-bit address of the message call’s recipient or, for a contract creation /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. #[cfg_attr(feature = "serde", serde(default))] + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for TxKind in alloy_primitives pub to: TxKind, /// A scalar value equal to the number of Wei to /// be transferred to the message call’s recipient or, @@ -72,6 +75,8 @@ pub struct TxEip1559 { // sometimes returning `null` instead of an empty array `[]`. // More details in . #[cfg_attr(feature = "serde", serde(deserialize_with = "alloy_serde::null_as_default"))] + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for AccessList in alloy_eip2930 pub access_list: AccessList, /// Input has two uses depending if `to` field is Create or Call. /// pub init: An unlimited size byte array specifying the diff --git a/crates/consensus/src/transaction/eip2930.rs b/crates/consensus/src/transaction/eip2930.rs index 18525f72326..b76d85cb582 100644 --- a/crates/consensus/src/transaction/eip2930.rs +++ b/crates/consensus/src/transaction/eip2930.rs @@ -13,6 +13,7 @@ use super::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx}; #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "Eip2930Transaction", alias = "TransactionEip2930", alias = "Eip2930Tx")] pub struct TxEip2930 { /// Added as EIP-pub 155: Simple replay attack protection @@ -43,6 +44,8 @@ pub struct TxEip2930 { /// The 160-bit address of the message call’s recipient or, for a contract creation /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. #[cfg_attr(feature = "serde", serde(default))] + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for TxKind in alloy_primitives pub to: TxKind, /// A scalar value equal to the number of Wei to /// be transferred to the message call’s recipient or, @@ -56,6 +59,8 @@ pub struct TxEip2930 { /// and `accessed_storage_keys` global sets (introduced in EIP-2929). /// A gas cost is charged, though at a discount relative to the cost of /// accessing outside the list. + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for AccessList in alloy_eip2930 pub access_list: AccessList, /// Input has two uses depending if `to` field is Create or Call. /// pub init: An unlimited size byte array specifying the diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index ce3da2adbe3..8c14b570e97 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -27,6 +27,7 @@ use alloy_eips::eip7594::{BlobTransactionSidecarEip7594, BlobTransactionSidecarV #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[cfg_attr(feature = "serde", serde(untagged))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "Eip4844TransactionVariant")] pub enum TxEip4844Variant { /// A standalone transaction with blob hashes and max blob fee. @@ -514,6 +515,7 @@ where #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "Eip4844Transaction", alias = "TransactionEip4844", alias = "Eip4844Tx")] pub struct TxEip4844 { /// Added as EIP-pub 155: Simple replay attack protection @@ -566,6 +568,8 @@ pub struct TxEip4844 { /// and `accessed_storage_keys` global sets (introduced in EIP-2929). /// A gas cost is charged, though at a discount relative to the cost of /// accessing outside the list. + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for AccessList in alloy_eip2930 pub access_list: AccessList, /// It contains a vector of fixed size hash(32 bytes) @@ -834,6 +838,7 @@ impl From> for TxEip4844 { #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "Eip4844TransactionWithSidecar", alias = "Eip4844TxWithSidecar")] pub struct TxEip4844WithSidecar { /// The actual transaction. diff --git a/crates/consensus/src/transaction/eip7702.rs b/crates/consensus/src/transaction/eip7702.rs index 6b5a352d0cb..9b1fdbe44d2 100644 --- a/crates/consensus/src/transaction/eip7702.rs +++ b/crates/consensus/src/transaction/eip7702.rs @@ -16,6 +16,7 @@ use super::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx}; #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] #[doc(alias = "Eip7702Transaction", alias = "TransactionEip7702", alias = "Eip7702Tx")] pub struct TxEip7702 { @@ -69,10 +70,14 @@ pub struct TxEip7702 { /// and `accessed_storage_keys` global sets (introduced in EIP-2929). /// A gas cost is charged, though at a discount relative to the cost of /// accessing outside the list. + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for AccessList in alloy_eip2930 pub access_list: AccessList, /// Authorizations are used to temporarily set the code of its signer to /// the code referenced by `address`. These also include a `chain_id` (which /// can be set to zero and not evaluated) as well as an optional `nonce`. + #[cfg_attr(feature = "borsh", borsh(skip))] + // TODO: Implement Borsh for SignedAuthorization in alloy_eip7702 pub authorization_list: Vec, /// An unlimited size byte array specifying the /// input data of the message call, formally Td. diff --git a/crates/consensus/src/transaction/legacy.rs b/crates/consensus/src/transaction/legacy.rs index f30bd89cf77..fd601f0084a 100644 --- a/crates/consensus/src/transaction/legacy.rs +++ b/crates/consensus/src/transaction/legacy.rs @@ -15,6 +15,7 @@ use core::mem; #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "LegacyTransaction", alias = "TransactionLegacy", alias = "LegacyTx")] pub struct TxLegacy { /// Added as EIP-155: Simple replay attack protection diff --git a/crates/eips/Cargo.toml b/crates/eips/Cargo.toml index 2a2d1f7798a..59e170c7cb4 100644 --- a/crates/eips/Cargo.toml +++ b/crates/eips/Cargo.toml @@ -58,6 +58,9 @@ ethereum_ssz = { workspace = true, optional = true } # arbitrary arbitrary = { workspace = true, features = ["derive"], optional = true } +# borsh +borsh = { workspace = true, optional = true, features = ["derive"] } + # misc auto_impl.workspace = true @@ -86,7 +89,8 @@ std = [ "sha2?/std", "either/std", "serde_with?/std", - "thiserror/std" + "thiserror/std", + "borsh?/std" ] serde = [ "dep:alloy-serde", @@ -118,3 +122,7 @@ arbitrary = [ "alloy-eip7702/k256", "c-kzg?/arbitrary" ] +borsh = [ + "dep:borsh", + "alloy-primitives/borsh", +] diff --git a/crates/eips/src/eip1559/basefee.rs b/crates/eips/src/eip1559/basefee.rs index 70968923c2d..2ee1aca8e2b 100644 --- a/crates/eips/src/eip1559/basefee.rs +++ b/crates/eips/src/eip1559/basefee.rs @@ -16,6 +16,7 @@ use crate::{ #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct BaseFeeParams { /// The base_fee_max_change_denominator from EIP-1559 #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] diff --git a/crates/eips/src/eip4844/sidecar.rs b/crates/eips/src/eip4844/sidecar.rs index 60dda87d618..5997a8c2874 100644 --- a/crates/eips/src/eip4844/sidecar.rs +++ b/crates/eips/src/eip4844/sidecar.rs @@ -34,6 +34,7 @@ pub struct IndexedBlobHash { #[derive(Clone, Default, PartialEq, Eq, Hash)] #[repr(C)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] #[doc(alias = "BlobTxSidecar")] pub struct BlobTransactionSidecar { /// The blob data. diff --git a/crates/eips/src/eip4895.rs b/crates/eips/src/eip4895.rs index 25bff187730..a6a51a1d42a 100644 --- a/crates/eips/src/eip4895.rs +++ b/crates/eips/src/eip4895.rs @@ -15,6 +15,7 @@ pub const GWEI_TO_WEI: u64 = 1_000_000_000; #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "ssz", derive(ssz_derive::Encode, ssz_derive::Decode))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct Withdrawal { /// Monotonically increasing identifier issued by consensus layer. #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] @@ -57,6 +58,7 @@ impl Withdrawal { )] #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct Withdrawals(pub Vec); impl Withdrawals { diff --git a/crates/eips/src/eip7840.rs b/crates/eips/src/eip7840.rs index e2439080a65..1a187d63663 100644 --- a/crates/eips/src/eip7840.rs +++ b/crates/eips/src/eip7840.rs @@ -18,6 +18,7 @@ pub const BLOB_BASE_COST: u64 = 2_u64.pow(13); feature = "serde", serde(from = "serde_impl::SerdeHelper", into = "serde_impl::SerdeHelper") )] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct BlobParams { /// Target blob count for the block. pub target_blob_count: u64, diff --git a/crates/genesis/Cargo.toml b/crates/genesis/Cargo.toml index 615a42fff76..e3b34e87854 100644 --- a/crates/genesis/Cargo.toml +++ b/crates/genesis/Cargo.toml @@ -32,6 +32,9 @@ alloy-trie = { workspace = true, features = ["ethereum"] } serde.workspace = true serde_with = { workspace = true, optional = true } +# borsh +borsh = { workspace = true, optional = true, features = ["derive"] } + [dev-dependencies] bincode = { workspace = true, features = ["serde"] } serde_json.workspace = true @@ -46,5 +49,11 @@ std = [ "alloy-eips/std", "serde_json/std", "serde_with?/std", + "borsh?/std" ] serde-bincode-compat = ["dep:serde_with", "alloy-eips/serde-bincode-compat"] +borsh = [ + "dep:borsh", + "alloy-primitives/borsh", + "alloy-eips/borsh", +] diff --git a/crates/genesis/src/lib.rs b/crates/genesis/src/lib.rs index b5c923ca01f..e12bdde5356 100644 --- a/crates/genesis/src/lib.rs +++ b/crates/genesis/src/lib.rs @@ -26,6 +26,7 @@ use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; /// The genesis block specification. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", default)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct Genesis { /// The fork configuration for this network. #[serde(default)] @@ -199,6 +200,7 @@ impl Genesis { /// An account in the state of the genesis block. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct GenesisAccount { /// The nonce of the account at genesis. #[serde(skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt", default)] @@ -300,6 +302,7 @@ impl From for TrieAccount { /// for the source of each field. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct ChainConfig { /// The network's chain ID. pub chain_id: u64, @@ -425,6 +428,7 @@ pub struct ChainConfig { /// Additional fields specific to each chain. #[serde(flatten, default)] + #[cfg_attr(feature = "borsh", borsh(skip))] pub extra_fields: OtherFields, /// The deposit contract address @@ -1072,10 +1076,12 @@ impl Default for ChainConfig { /// Empty consensus configuration for proof-of-work networks. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct EthashConfig {} /// Consensus configuration for Clique. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct CliqueConfig { /// Number of seconds between blocks to enforce. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1092,6 +1098,7 @@ pub struct CliqueConfig { /// For the general introduction: /// For the specification: #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] pub struct ParliaConfig { /// Number of seconds between blocks to enforce. #[serde(default, skip_serializing_if = "Option::is_none")]