Skip to main content

eth_valkyoth_protocol/
lib.rs

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