1#![no_std]
2#![forbid(unsafe_code)]
3#[cfg(feature = "std")]
6extern crate std;
7
8use core::fmt;
9
10mod fork;
11mod header;
12mod state;
13mod transaction;
14
15pub use fork::{ChainSpec, ForkActivation, ForkError, ForkSpec, Hardfork, ValidationContext};
16pub use header::{
17 BlockHash, BlockHeaderDecodeError, BlockHeaderDecodeErrorCategory, BlockHeaderField,
18 CANCUN_HEADER_FIELD_COUNT, HeaderFieldSet, LEGACY_HEADER_FIELD_COUNT,
19 LONDON_HEADER_FIELD_COUNT, LogsBloom, PRAGUE_HEADER_FIELD_COUNT, SHANGHAI_HEADER_FIELD_COUNT,
20 UnvalidatedBlockHeader, decode_block_header,
21};
22pub use state::{
23 Canonical, CanonicalValidationProof, Decoded, ForkValidated, ForkValidationProof,
24 SenderRecovered, SenderRecoveryProof, StateTransitionError, Transaction,
25};
26pub use transaction::{
27 ACCESS_LIST_TRANSACTION_FIELD_COUNT, ACCESS_LIST_TRANSACTION_TYPE, AccessList,
28 AccessListEntries, AccessListEntry, AccessListStorageKeyItems, AccessListStorageKeys,
29 AccessListTransactionDecodeError, AccessListTransactionDecodeErrorCategory,
30 AccessListTransactionField, AccessListTransactionTo, BLOB_TRANSACTION_FIELD_COUNT,
31 BLOB_TRANSACTION_TYPE, BlobTransactionDecodeError, BlobTransactionDecodeErrorCategory,
32 BlobTransactionField, BlobVersionedHashItems, BlobVersionedHashes,
33 DYNAMIC_FEE_TRANSACTION_FIELD_COUNT, DYNAMIC_FEE_TRANSACTION_TYPE,
34 DynamicFeeTransactionDecodeError, DynamicFeeTransactionDecodeErrorCategory,
35 DynamicFeeTransactionField, DynamicFeeTransactionTo, EIP_2718_MAX_TYPED_PREFIX,
36 EIP_2718_RESERVED_PREFIX, EIP_2718_SCALAR_PREFIX_START, EIP_2718_TYPED_ZERO_PREFIX,
37 EIP_7702_DELEGATION_INDICATOR_PREFIX, InvalidSignatureYParity, LEGACY_TRANSACTION_FIELD_COUNT,
38 LEGACY_TRANSACTION_PREFIX_START, LegacyTransactionDecodeError,
39 LegacyTransactionDecodeErrorCategory, LegacyTransactionField, LegacyTransactionTo,
40 SET_CODE_AUTHORIZATION_FIELD_COUNT, SET_CODE_AUTHORIZATION_MAGIC,
41 SET_CODE_TRANSACTION_FIELD_COUNT, SET_CODE_TRANSACTION_TYPE, SetCodeAuthorityAccount,
42 SetCodeAuthorityCode, SetCodeAuthorityStateView, SetCodeAuthorization,
43 SetCodeAuthorizationAuthority, SetCodeAuthorizationAuthorityView, SetCodeAuthorizationChainId,
44 SetCodeAuthorizationField, SetCodeAuthorizationItems, SetCodeAuthorizationList,
45 SetCodeTransactionDecodeError, SetCodeTransactionDecodeErrorCategory, SetCodeTransactionField,
46 SetCodeTransactionValidationContext, SetCodeTransactionValidityError,
47 SetCodeTransactionValidityErrorCategory, SignatureYParity, TransactionEncodeError,
48 TransactionEncodeErrorCategory, TransactionEnvelope, TransactionEnvelopeError,
49 TransactionEnvelopeErrorCategory, TypedTransactionEnvelope, UnvalidatedAccessListTransaction,
50 UnvalidatedBlobTransaction, UnvalidatedDynamicFeeTransaction, UnvalidatedLegacyTransaction,
51 UnvalidatedSetCodeTransaction, UnvalidatedTransaction, ValidSetCodeTransaction,
52 decode_access_list_transaction, decode_blob_transaction, decode_dynamic_fee_transaction,
53 decode_legacy_transaction, decode_set_code_transaction, decode_transaction_envelope,
54 encode_access_list_signing_preimage, encode_access_list_transaction,
55 encode_blob_signing_preimage, encode_blob_transaction, encode_dynamic_fee_signing_preimage,
56 encode_dynamic_fee_transaction, encode_legacy_eip155_signing_preimage,
57 encode_legacy_transaction, encode_set_code_authorization_signing_preimage,
58 encode_set_code_signing_preimage, encode_set_code_transaction, encode_transaction,
59 encoded_access_list_signing_preimage_len, encoded_access_list_transaction_len,
60 encoded_blob_signing_preimage_len, encoded_blob_transaction_len,
61 encoded_dynamic_fee_signing_preimage_len, encoded_dynamic_fee_transaction_len,
62 encoded_legacy_eip155_signing_preimage_len, encoded_legacy_transaction_len,
63 encoded_set_code_authorization_signing_preimage_len, encoded_set_code_signing_preimage_len,
64 encoded_set_code_transaction_len, encoded_transaction_len,
65 validate_set_code_transaction_context,
66};
67
68#[non_exhaustive]
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
71pub enum ProtocolError {
72 Feature(FeatureError),
74 Fork(ForkError),
76 InvalidStateTransition,
78}
79
80impl ProtocolError {
81 #[must_use]
83 pub const fn code(self) -> &'static str {
84 match self {
85 Self::Feature(error) => error.code(),
86 Self::Fork(error) => error.code(),
87 Self::InvalidStateTransition => "ETH_PROTOCOL_INVALID_STATE_TRANSITION",
88 }
89 }
90
91 #[must_use]
93 pub const fn message(self) -> &'static str {
94 match self {
95 Self::Feature(error) => error.message(),
96 Self::Fork(error) => error.message(),
97 Self::InvalidStateTransition => {
98 "validation state transition is not allowed from the current state"
99 }
100 }
101 }
102
103 #[must_use]
105 pub const fn category(self) -> ProtocolErrorCategory {
106 match self {
107 Self::Feature(_) => ProtocolErrorCategory::Feature,
108 Self::Fork(_) => ProtocolErrorCategory::Fork,
109 Self::InvalidStateTransition => ProtocolErrorCategory::State,
110 }
111 }
112}
113
114impl fmt::Display for ProtocolError {
115 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
116 formatter.write_str(self.message())
117 }
118}
119
120#[cfg(feature = "std")]
121impl std::error::Error for ProtocolError {}
122
123#[non_exhaustive]
125#[derive(Clone, Copy, Debug, Eq, PartialEq)]
126pub enum ProtocolErrorCategory {
127 Feature,
129 Fork,
131 State,
133}
134
135#[non_exhaustive]
137#[derive(Clone, Copy, Debug, Eq, PartialEq)]
138pub enum FeatureError {
139 Disabled,
141 Unsupported,
143}
144
145impl FeatureError {
146 #[must_use]
148 pub const fn code(self) -> &'static str {
149 match self {
150 Self::Disabled => "ETH_FEATURE_DISABLED",
151 Self::Unsupported => "ETH_FEATURE_UNSUPPORTED",
152 }
153 }
154
155 #[must_use]
157 pub const fn message(self) -> &'static str {
158 match self {
159 Self::Disabled => "feature is disabled for this operation",
160 Self::Unsupported => "feature is not supported by this crate version",
161 }
162 }
163}
164
165impl fmt::Display for FeatureError {
166 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
167 formatter.write_str(self.message())
168 }
169}
170
171#[cfg(feature = "std")]
172impl std::error::Error for FeatureError {}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 extern crate std;
178 use std::string::ToString;
179
180 #[test]
181 fn protocol_errors_have_stable_codes_and_categories() {
182 let error = ProtocolError::Fork(ForkError::Inactive);
183
184 assert_eq!(error.code(), "ETH_FORK_INACTIVE");
185 assert_eq!(
186 error.message(),
187 "fork is not active for the validation context"
188 );
189 assert_eq!(error.category(), ProtocolErrorCategory::Fork);
190 assert_eq!(
191 error.to_string(),
192 "fork is not active for the validation context"
193 );
194 }
195
196 #[test]
197 fn feature_errors_format_without_payloads() {
198 let error = ProtocolError::Feature(FeatureError::Unsupported);
199
200 assert_eq!(error.code(), "ETH_FEATURE_UNSUPPORTED");
201 assert_eq!(
202 FeatureError::Unsupported.to_string(),
203 "feature is not supported by this crate version"
204 );
205 }
206}