use core::fmt;
use eth_valkyoth_codec::{DecodeError, DecodeErrorCategory};
use super::SetCodeTransactionField;
use crate::transaction::{TransactionEnvelopeError, TransactionEnvelopeErrorCategory};
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SetCodeAuthorizationField {
ChainId,
Address,
Nonce,
YParity,
R,
S,
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SetCodeTransactionDecodeError {
Envelope(TransactionEnvelopeError),
WrongTransactionType {
type_byte: u8,
},
WrongFieldCount {
expected: usize,
found: usize,
},
FieldDecode {
field: SetCodeTransactionField,
source: DecodeError,
},
AuthorizationFieldDecode {
field: SetCodeAuthorizationField,
source: DecodeError,
},
InvalidToLength {
found: usize,
},
InvalidYParity {
value: u64,
},
InvalidAccessListEntryFieldCount {
found: usize,
},
InvalidAccessListAddressLength {
found: usize,
},
InvalidStorageKeyLength {
found: usize,
},
InvalidAuthorizationFieldCount {
found: usize,
},
InvalidAuthorizationAddressLength {
found: usize,
},
InvalidAuthorizationYParity {
value: u64,
},
}
impl SetCodeTransactionDecodeError {
#[must_use]
pub const fn code(self) -> &'static str {
match self {
Self::Envelope(error) => error.code(),
Self::WrongTransactionType { .. } => "ETH_SET_CODE_TX_WRONG_TYPE",
Self::WrongFieldCount { .. } => "ETH_SET_CODE_TX_WRONG_FIELD_COUNT",
Self::FieldDecode { source, .. } => source.code(),
Self::AuthorizationFieldDecode { source, .. } => source.code(),
Self::InvalidToLength { .. } => "ETH_SET_CODE_TX_INVALID_TO_LENGTH",
Self::InvalidYParity { .. } => "ETH_SET_CODE_TX_INVALID_Y_PARITY",
Self::InvalidAccessListEntryFieldCount { .. } => {
"ETH_SET_CODE_TX_INVALID_ENTRY_FIELD_COUNT"
}
Self::InvalidAccessListAddressLength { .. } => {
"ETH_SET_CODE_TX_INVALID_ACCESS_ADDRESS_LENGTH"
}
Self::InvalidStorageKeyLength { .. } => "ETH_SET_CODE_TX_INVALID_STORAGE_KEY_LENGTH",
Self::InvalidAuthorizationFieldCount { .. } => {
"ETH_SET_CODE_TX_INVALID_AUTH_FIELD_COUNT"
}
Self::InvalidAuthorizationAddressLength { .. } => {
"ETH_SET_CODE_TX_INVALID_AUTH_ADDRESS_LENGTH"
}
Self::InvalidAuthorizationYParity { .. } => "ETH_SET_CODE_TX_INVALID_AUTH_Y_PARITY",
}
}
#[must_use]
pub const fn message(self) -> &'static str {
match self {
Self::Envelope(error) => error.message(),
Self::WrongTransactionType { .. } => {
"set-code transaction decoder received a different envelope type"
}
Self::WrongFieldCount { .. } => {
"set-code transaction must contain exactly thirteen RLP fields"
}
Self::FieldDecode { .. } => "set-code transaction field failed bounded decoding",
Self::AuthorizationFieldDecode { .. } => {
"set-code authorization tuple field failed bounded decoding"
}
Self::InvalidToLength { .. } => {
"set-code transaction destination field must be a 20-byte address"
}
Self::InvalidYParity { .. } => "set-code transaction y parity must be 0 or 1",
Self::InvalidAccessListEntryFieldCount { .. } => {
"set-code transaction access-list entry must contain exactly address and storage-key list"
}
Self::InvalidAccessListAddressLength { .. } => {
"set-code transaction access-list address must be a 20-byte scalar"
}
Self::InvalidStorageKeyLength { .. } => {
"set-code transaction access-list storage key must be a 32-byte scalar"
}
Self::InvalidAuthorizationFieldCount { .. } => {
"set-code authorization tuple must contain exactly chain id, address, nonce, y parity, r, and s"
}
Self::InvalidAuthorizationAddressLength { .. } => {
"set-code authorization address must be a 20-byte scalar"
}
Self::InvalidAuthorizationYParity { .. } => {
"set-code authorization y parity must be 0 or 1"
}
}
}
#[must_use]
pub const fn category(self) -> SetCodeTransactionDecodeErrorCategory {
match self {
Self::Envelope(error) => match error.category() {
TransactionEnvelopeErrorCategory::ResourceExhaustion => {
SetCodeTransactionDecodeErrorCategory::ResourceExhaustion
}
TransactionEnvelopeErrorCategory::Unsupported => {
SetCodeTransactionDecodeErrorCategory::WrongType
}
_ => SetCodeTransactionDecodeErrorCategory::MalformedInput,
},
Self::WrongTransactionType { .. } => SetCodeTransactionDecodeErrorCategory::WrongType,
Self::FieldDecode { source, .. } | Self::AuthorizationFieldDecode { source, .. } => {
match source.category() {
DecodeErrorCategory::ResourceExhaustion => {
SetCodeTransactionDecodeErrorCategory::ResourceExhaustion
}
_ => SetCodeTransactionDecodeErrorCategory::MalformedInput,
}
}
Self::WrongFieldCount { .. }
| Self::InvalidToLength { .. }
| Self::InvalidYParity { .. }
| Self::InvalidAccessListEntryFieldCount { .. }
| Self::InvalidAccessListAddressLength { .. }
| Self::InvalidStorageKeyLength { .. }
| Self::InvalidAuthorizationFieldCount { .. }
| Self::InvalidAuthorizationAddressLength { .. }
| Self::InvalidAuthorizationYParity { .. } => {
SetCodeTransactionDecodeErrorCategory::MalformedInput
}
}
}
}
impl fmt::Display for SetCodeTransactionDecodeError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.message())
}
}
#[cfg(feature = "std")]
impl std::error::Error for SetCodeTransactionDecodeError {}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SetCodeTransactionDecodeErrorCategory {
MalformedInput,
WrongType,
ResourceExhaustion,
}