mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 00:58:11 -05:00
docs: improve rlp transaction encoding docs (#5922)
This commit is contained in:
@@ -104,9 +104,9 @@ impl TryFrom<u8> for DisconnectReason {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`Encodable`] implementation for [`DisconnectReason`] encodes the disconnect reason in a
|
||||
/// single-element RLP list.
|
||||
impl Encodable for DisconnectReason {
|
||||
/// The [`Encodable`] implementation for [`DisconnectReason`] encodes the disconnect reason in
|
||||
/// a single-element RLP list.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
vec![*self as u8].encode(out);
|
||||
}
|
||||
@@ -115,9 +115,9 @@ impl Encodable for DisconnectReason {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`Decodable`] implementation for [`DisconnectReason`] supports either a disconnect reason
|
||||
/// encoded a single byte or a RLP list containing the disconnect reason.
|
||||
impl Decodable for DisconnectReason {
|
||||
/// The [`Decodable`] implementation for [`DisconnectReason`] supports either a disconnect
|
||||
/// reason encoded a single byte or a RLP list containing the disconnect reason.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
if buf.is_empty() {
|
||||
return Err(RlpError::InputTooShort)
|
||||
|
||||
@@ -643,11 +643,11 @@ impl P2PMessage {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`Encodable`] implementation for [`P2PMessage::Ping`] and [`P2PMessage::Pong`] encodes the
|
||||
/// message as RLP, and prepends a snappy header to the RLP bytes for all variants except the
|
||||
/// [`P2PMessage::Hello`] variant, because the hello message is never compressed in the `p2p`
|
||||
/// subprotocol.
|
||||
impl Encodable for P2PMessage {
|
||||
/// The [`Encodable`] implementation for [`P2PMessage::Ping`] and [`P2PMessage::Pong`] encodes
|
||||
/// the message as RLP, and prepends a snappy header to the RLP bytes for all variants except
|
||||
/// the [`P2PMessage::Hello`] variant, because the hello message is never compressed in the
|
||||
/// `p2p` subprotocol.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
(self.message_id() as u8).encode(out);
|
||||
match self {
|
||||
@@ -680,13 +680,13 @@ impl Encodable for P2PMessage {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`Decodable`] implementation for [`P2PMessage`] assumes that each of the message variants
|
||||
/// are snappy compressed, except for the [`P2PMessage::Hello`] variant since the hello message is
|
||||
/// never compressed in the `p2p` subprotocol.
|
||||
///
|
||||
/// The [`Decodable`] implementation for [`P2PMessage::Ping`] and [`P2PMessage::Pong`] expects a
|
||||
/// snappy encoded payload, see [`Encodable`] implementation.
|
||||
impl Decodable for P2PMessage {
|
||||
/// The [`Decodable`] implementation for [`P2PMessage`] assumes that each of the message
|
||||
/// variants are snappy compressed, except for the [`P2PMessage::Hello`] variant since the
|
||||
/// hello message is never compressed in the `p2p` subprotocol.
|
||||
///
|
||||
/// The [`Decodable`] implementation for [`P2PMessage::Ping`] and [`P2PMessage::Pong`] expects
|
||||
/// a snappy encoded payload, see [`Encodable`] implementation.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
/// Removes the snappy prefix from the Ping/Pong buffer
|
||||
fn advance_snappy_ping_pong_payload(buf: &mut &[u8]) -> alloy_rlp::Result<()> {
|
||||
|
||||
@@ -105,9 +105,9 @@ impl ProtocolMessage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes the protocol message into bytes.
|
||||
/// The message type is encoded as a single byte and prepended to the message.
|
||||
impl Encodable for ProtocolMessage {
|
||||
/// Encodes the protocol message into bytes. The message type is encoded as a single byte and
|
||||
/// prepended to the message.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
self.message_type.encode(out);
|
||||
self.message.encode(out);
|
||||
@@ -130,9 +130,9 @@ pub struct ProtocolBroadcastMessage {
|
||||
pub message: EthBroadcastMessage,
|
||||
}
|
||||
|
||||
/// Encodes the protocol message into bytes.
|
||||
/// The message type is encoded as a single byte and prepended to the message.
|
||||
impl Encodable for ProtocolBroadcastMessage {
|
||||
/// Encodes the protocol message into bytes. The message type is encoded as a single byte and
|
||||
/// prepended to the message.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
self.message_type.encode(out);
|
||||
self.message.encode(out);
|
||||
|
||||
@@ -138,6 +138,10 @@ impl TxEip1559 {
|
||||
|
||||
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
|
||||
/// hash that for eip2718 does not require rlp header
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit to, value, input,
|
||||
/// access_list, y_parity, r, s)`
|
||||
pub(crate) fn encode_with_signature(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
@@ -192,6 +196,12 @@ impl TxEip1559 {
|
||||
}
|
||||
|
||||
/// Encodes the legacy transaction in RLP for signing.
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `tx_type || rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to,
|
||||
/// value, input, access_list)`
|
||||
///
|
||||
/// Note that there is no rlp header before the transaction type byte.
|
||||
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
|
||||
out.put_u8(self.tx_type() as u8);
|
||||
Header { list: true, payload_length: self.fields_len() }.encode(out);
|
||||
|
||||
@@ -117,6 +117,9 @@ impl TxEip2930 {
|
||||
|
||||
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
|
||||
/// hash that for eip2718 does not require rlp header
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `rlp(nonce, gas_price, gas_limit, to, value, input, access_list, y_parity, r, s)`
|
||||
pub(crate) fn encode_with_signature(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
@@ -157,6 +160,11 @@ impl TxEip2930 {
|
||||
}
|
||||
|
||||
/// Encodes the legacy transaction in RLP for signing.
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `tx_type || rlp(chain_id, nonce, gas_price, gas_limit, to, value, input, access_list)`
|
||||
///
|
||||
/// Note that there is no rlp header before the transaction type byte.
|
||||
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
|
||||
out.put_u8(self.tx_type() as u8);
|
||||
Header { list: true, payload_length: self.fields_len() }.encode(out);
|
||||
|
||||
@@ -295,6 +295,12 @@ impl TxEip4844 {
|
||||
}
|
||||
|
||||
/// Encodes the legacy transaction in RLP for signing.
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `tx_type || rlp(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to,
|
||||
/// value, input, access_list, max_fee_per_blob_gas, blob_versioned_hashes)`
|
||||
///
|
||||
/// Note that there is no rlp header before the transaction type byte.
|
||||
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
|
||||
out.put_u8(self.tx_type() as u8);
|
||||
Header { list: true, payload_length: self.fields_len() }.encode(out);
|
||||
|
||||
@@ -81,6 +81,11 @@ impl TxLegacy {
|
||||
|
||||
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
|
||||
/// hash.
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `rlp(nonce, gas_price, gas_limit, to, value, input, v, r, s)`
|
||||
///
|
||||
/// The `v` value is encoded according to EIP-155 if the `chain_id` is not `None`.
|
||||
pub(crate) fn encode_with_signature(&self, signature: &Signature, out: &mut dyn bytes::BufMut) {
|
||||
let payload_length =
|
||||
self.fields_len() + signature.payload_len_with_eip155_chain_id(self.chain_id);
|
||||
@@ -105,6 +110,9 @@ impl TxLegacy {
|
||||
|
||||
/// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy
|
||||
/// transactions.
|
||||
///
|
||||
/// If a `chain_id` is `Some`, this encodes the `chain_id`, followed by two zeroes, as defined
|
||||
/// by [EIP-155](https://eips.ethereum.org/EIPS/eip-155).
|
||||
pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) {
|
||||
// if this is a legacy transaction without a chain ID, it must be pre-EIP-155
|
||||
// and does not need to encode the chain ID for the signature hash encoding
|
||||
@@ -131,6 +139,12 @@ impl TxLegacy {
|
||||
}
|
||||
|
||||
/// Encodes the legacy transaction in RLP for signing, including the EIP-155 fields if possible.
|
||||
///
|
||||
/// If a `chain_id` is `Some`, this encodes the transaction as:
|
||||
/// `rlp(nonce, gas_price, gas_limit, to, value, input, chain_id, 0, 0)`
|
||||
///
|
||||
/// Otherwise, this encodes the transaction as:
|
||||
/// `rlp(nonce, gas_price, gas_limit, to, value, input)`
|
||||
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
|
||||
Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() }
|
||||
.encode(out);
|
||||
|
||||
@@ -669,9 +669,9 @@ impl Default for Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
/// This encodes the transaction _without_ the signature, and is only suitable for creating a hash
|
||||
/// intended for signing.
|
||||
impl Encodable for Transaction {
|
||||
/// This encodes the transaction _without_ the signature, and is only suitable for creating a
|
||||
/// hash intended for signing.
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
match self {
|
||||
Transaction::Legacy(legacy_tx) => {
|
||||
@@ -771,12 +771,19 @@ impl Compact for TransactionKind {
|
||||
}
|
||||
|
||||
impl Encodable for TransactionKind {
|
||||
/// This encodes the `to` field of a transaction request.
|
||||
/// If the [TransactionKind] is a [TransactionKind::Call] it will encode the inner address:
|
||||
/// `rlp(address)`
|
||||
///
|
||||
/// If the [TransactionKind] is a [TransactionKind::Create] it will encode an empty list:
|
||||
/// `rlp([])`, which is also
|
||||
fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
|
||||
match self {
|
||||
TransactionKind::Call(to) => to.encode(out),
|
||||
TransactionKind::Create => out.put_u8(EMPTY_STRING_CODE),
|
||||
}
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
match self {
|
||||
TransactionKind::Call(to) => to.length(),
|
||||
@@ -1092,9 +1099,10 @@ impl TransactionSigned {
|
||||
/// Encodes the transaction into the "raw" format (e.g. `eth_sendRawTransaction`).
|
||||
/// This format is also referred to as "binary" encoding.
|
||||
///
|
||||
/// For legacy transactions, it encodes the RLP of the transaction into the buffer: `rlp(tx)`
|
||||
/// For legacy transactions, it encodes the RLP of the transaction into the buffer:
|
||||
/// `rlp(tx-data)`
|
||||
/// For EIP-2718 typed it encodes the type of the transaction followed by the rlp of the
|
||||
/// transaction: `type || rlp(tx)`
|
||||
/// transaction: `tx-type || rlp(tx-data)`
|
||||
pub fn encode_enveloped(&self, out: &mut dyn bytes::BufMut) {
|
||||
self.encode_inner(out, false)
|
||||
}
|
||||
@@ -1211,12 +1219,12 @@ impl TransactionSigned {
|
||||
///
|
||||
/// This should be used _only_ be used internally in general transaction decoding methods,
|
||||
/// which have already ensured that the input is a typed transaction with the following format:
|
||||
/// `tx_type || rlp(tx)`
|
||||
/// `tx-type || rlp(tx-data)`
|
||||
///
|
||||
/// Note that this format does not start with any RLP header, and instead starts with a single
|
||||
/// byte indicating the transaction type.
|
||||
///
|
||||
/// CAUTION: this expects that `data` is `tx_type || rlp(tx)`
|
||||
/// CAUTION: this expects that `data` is `tx-type || rlp(tx-data)`
|
||||
pub fn decode_enveloped_typed_transaction(
|
||||
data: &mut &[u8],
|
||||
) -> alloy_rlp::Result<TransactionSigned> {
|
||||
@@ -1276,13 +1284,13 @@ impl TransactionSigned {
|
||||
///
|
||||
/// A raw transaction is either a legacy transaction or EIP-2718 typed transaction.
|
||||
///
|
||||
/// For legacy transactions, the format is encoded as: `rlp(tx)`. This format will start with a
|
||||
/// RLP list header.
|
||||
/// For legacy transactions, the format is encoded as: `rlp(tx-data)`. This format will start
|
||||
/// with a RLP list header.
|
||||
///
|
||||
/// For EIP-2718 typed transactions, the format is encoded as the type of the transaction
|
||||
/// followed by the rlp of the transaction: `type || rlp(tx)`.
|
||||
/// followed by the rlp of the transaction: `type || rlp(tx-data)`.
|
||||
///
|
||||
/// To decode EIP-4844 transactions in `eth_sendRawTransaction`, use
|
||||
/// To decode EIP-4844 transactions from `eth_sendRawTransaction`, use
|
||||
/// [PooledTransactionsElement::decode_enveloped].
|
||||
pub fn decode_enveloped(data: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
if data.is_empty() {
|
||||
@@ -1325,6 +1333,14 @@ impl From<TransactionSignedEcRecovered> for TransactionSigned {
|
||||
}
|
||||
|
||||
impl Encodable for TransactionSigned {
|
||||
/// This encodes the transaction _with_ the signature, and an rlp header.
|
||||
///
|
||||
/// For legacy transactions, it encodes the transaction data:
|
||||
/// `rlp(tx-data)`
|
||||
///
|
||||
/// For EIP-2718 typed transactions, it encodes the transaction type followed by the rlp of the
|
||||
/// transaction:
|
||||
/// `rlp(tx-type || rlp(tx-data))`
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
self.encode_inner(out, true);
|
||||
}
|
||||
@@ -1334,29 +1350,37 @@ impl Encodable for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
/// This `Decodable` implementation only supports decoding rlp encoded transactions as it's used by
|
||||
/// p2p.
|
||||
///
|
||||
/// The p2p encoding format always includes an RLP header, although the type RLP header depends on
|
||||
/// whether or not the transaction is a legacy transaction.
|
||||
///
|
||||
/// If the transaction is a legacy transaction, it is just encoded as a RLP list: `rlp(tx)`.
|
||||
///
|
||||
/// If the transaction is a typed transaction, it is encoded as a RLP string:
|
||||
/// `rlp(type || rlp(tx))`
|
||||
///
|
||||
/// This cannot be used for decoding EIP-4844 transactions in p2p, since the EIP-4844 variant of
|
||||
/// [TransactionSigned] does not include the blob sidecar. For a general purpose decoding method
|
||||
/// suitable for decoding transactions from p2p, see [PooledTransactionsElement].
|
||||
///
|
||||
/// CAUTION: Due to a quirk in [Header::decode], this method will succeed even if a typed
|
||||
/// transaction is encoded in the RPC format, and does not start with a RLP header. This is because
|
||||
/// [Header::decode] does not advance the buffer, and returns a length-1 string header if the first
|
||||
/// byte is less than `0xf7`. This causes this decode implementation to pass unaltered buffer to
|
||||
/// [TransactionSigned::decode_enveloped_typed_transaction], which expects the RPC format. Despite
|
||||
/// this quirk, this should **not** be used for RPC methods that accept raw transactions.
|
||||
impl Decodable for TransactionSigned {
|
||||
/// This `Decodable` implementation only supports decoding rlp encoded transactions as it's used
|
||||
/// by p2p.
|
||||
///
|
||||
/// The p2p encoding format always includes an RLP header, although the type RLP header depends
|
||||
/// on whether or not the transaction is a legacy transaction.
|
||||
///
|
||||
/// If the transaction is a legacy transaction, it is just encoded as a RLP list:
|
||||
/// `rlp(tx-data)`.
|
||||
///
|
||||
/// If the transaction is a typed transaction, it is encoded as a RLP string:
|
||||
/// `rlp(tx-type || rlp(tx-data))`
|
||||
///
|
||||
/// This can be used for decoding all signed transactions in p2p `BlockBodies` responses.
|
||||
///
|
||||
/// This cannot be used for decoding EIP-4844 transactions in p2p `PooledTransactions`, since
|
||||
/// the EIP-4844 variant of [TransactionSigned] does not include the blob sidecar.
|
||||
///
|
||||
/// For a method suitable for decoding pooled transactions, see [PooledTransactionsElement].
|
||||
///
|
||||
/// CAUTION: Due to a quirk in [Header::decode], this method will succeed even if a typed
|
||||
/// transaction is encoded in this format, and does not start with a RLP header:
|
||||
/// `tx-type || rlp(tx-data)`.
|
||||
///
|
||||
/// This is because [Header::decode] does not advance the buffer, and returns a length-1 string
|
||||
/// header if the first byte is less than `0xf7`.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
if buf.is_empty() {
|
||||
return Err(RlpError::InputTooShort)
|
||||
}
|
||||
|
||||
// decode header
|
||||
let mut original_encoding = *buf;
|
||||
let header = Header::decode(buf)?;
|
||||
@@ -1480,6 +1504,9 @@ impl TransactionSignedEcRecovered {
|
||||
}
|
||||
|
||||
impl Encodable for TransactionSignedEcRecovered {
|
||||
/// This encodes the transaction _with_ the signature, and an rlp header.
|
||||
///
|
||||
/// Refer to docs for [TransactionSigned::encode] for details on the exact format.
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
self.signed_transaction.encode(out)
|
||||
}
|
||||
@@ -1569,6 +1596,19 @@ mod tests {
|
||||
assert_eq!(RlpError::InputTooShort, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_kind_encoding_sanity() {
|
||||
// check the 0x80 encoding for Create
|
||||
let mut buf = Vec::new();
|
||||
TransactionKind::Create.encode(&mut buf);
|
||||
assert_eq!(buf, vec![0x80]);
|
||||
|
||||
// check decoding
|
||||
let buf = [0x80];
|
||||
let decoded = TransactionKind::decode(&mut &buf[..]).unwrap();
|
||||
assert_eq!(decoded, TransactionKind::Create);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_create_goerli() {
|
||||
// test that an example create tx from goerli decodes properly
|
||||
|
||||
@@ -321,17 +321,27 @@ impl PooledTransactionsElement {
|
||||
|
||||
impl Encodable for PooledTransactionsElement {
|
||||
/// Encodes an enveloped post EIP-4844 [PooledTransactionsElement].
|
||||
///
|
||||
/// For legacy transactions, this encodes the transaction as `rlp(tx-data)`.
|
||||
///
|
||||
/// For EIP-2718 transactions, this encodes the transaction as `rlp(tx_type || rlp(tx-data)))`.
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
// The encoding of `tx-data` depends on the transaction type. Refer to these docs for more
|
||||
// information on the exact format:
|
||||
// - Legacy: TxLegacy::encode_with_signature
|
||||
// - EIP-2930: TxEip2930::encode_with_signature
|
||||
// - EIP-1559: TxEip1559::encode_with_signature
|
||||
// - EIP-4844: BlobTransaction::encode_with_type_inner
|
||||
match self {
|
||||
Self::Legacy { transaction, signature, .. } => {
|
||||
transaction.encode_with_signature(signature, out)
|
||||
}
|
||||
Self::Eip2930 { transaction, signature, .. } => {
|
||||
// encodes with header
|
||||
// encodes with string header
|
||||
transaction.encode_with_signature(signature, out, true)
|
||||
}
|
||||
Self::Eip1559 { transaction, signature, .. } => {
|
||||
// encodes with header
|
||||
// encodes with string header
|
||||
transaction.encode_with_signature(signature, out, true)
|
||||
}
|
||||
Self::BlobTransaction(blob_tx) => {
|
||||
@@ -377,7 +387,7 @@ impl Encodable for PooledTransactionsElement {
|
||||
impl Decodable for PooledTransactionsElement {
|
||||
/// Decodes an enveloped post EIP-4844 [PooledTransactionsElement].
|
||||
///
|
||||
/// CAUTION: this expects that `buf` is `[id, rlp(tx)]`
|
||||
/// CAUTION: this expects that `buf` is `rlp(tx_type || rlp(tx-data))`
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
// From the EIP-4844 spec:
|
||||
// Blob transactions have two network representations. During transaction gossip responses
|
||||
|
||||
@@ -646,8 +646,8 @@ impl From<U64> for BlockHashOrNumber {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows for RLP encoding of either a block hash or block number
|
||||
impl Encodable for BlockHashOrNumber {
|
||||
/// RLP encodes either the block hash or block number, depending on the variant.
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
match self {
|
||||
Self::Hash(block_hash) => block_hash.encode(out),
|
||||
@@ -662,8 +662,10 @@ impl Encodable for BlockHashOrNumber {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows for RLP decoding of a block hash or block number
|
||||
impl Decodable for BlockHashOrNumber {
|
||||
/// RLP decodes the data into a block hash or number.
|
||||
/// If the data is exactly 32 bytes and a RLP string, it will be decoded into a block hash.
|
||||
/// Otherwise, this will try to decode a `u64` from the data as a block number.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
let header: u8 = *buf.first().ok_or(RlpError::InputTooShort)?;
|
||||
// if the byte string is exactly 32 bytes, decode it into a Hash
|
||||
|
||||
@@ -107,6 +107,12 @@ impl TransactionKind {
|
||||
}
|
||||
|
||||
impl Encodable for TransactionKind {
|
||||
/// This encodes the `to` field of a transaction request.
|
||||
/// If the [TransactionKind] is a [TransactionKind::Call] it will encode the inner address:
|
||||
/// `rlp(address)`
|
||||
///
|
||||
/// If the [TransactionKind] is a [TransactionKind::Create] it will encode an empty list:
|
||||
/// `rlp([])`, which is also
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
match self {
|
||||
TransactionKind::Call(to) => to.encode(out),
|
||||
@@ -148,3 +154,21 @@ pub struct BlobTransactionSidecar {
|
||||
/// The blob proofs.
|
||||
pub proofs: Vec<Bytes48>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn raw_kind_encoding_sanity() {
|
||||
// check the 0x80 encoding for Create
|
||||
let mut buf = Vec::new();
|
||||
TransactionKind::Create.encode(&mut buf);
|
||||
assert_eq!(buf, vec![0x80]);
|
||||
|
||||
// check decoding
|
||||
let buf = [0x80];
|
||||
let decoded = TransactionKind::decode(&mut &buf[..]).unwrap();
|
||||
assert_eq!(decoded, TransactionKind::Create);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user