Skip to content

feat: decode tx_input directly from RLP - #2653

Open
f3l1ph3s wants to merge 6 commits into
mainfrom
decode-rlp
Open

feat: decode tx_input directly from RLP#2653
f3l1ph3s wants to merge 6 commits into
mainfrom
decode-rlp

Conversation

@f3l1ph3s

@f3l1ph3s f3l1ph3s commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

PR Type

Enhancement, Tests


Description

  • Add signature_hash() method to TransactionInput

    • Supports Legacy and EIP-2930/1559/4844/7702 types
  • Refactor RLP decoding flow

    • Introduce build_transaction_input_from_envelope()
    • Replace try_from_alloy_transaction() logic
  • Remove redundant transaction conversion code

  • Add unit tests for signature_hash() correctness


Diagram Walkthrough

flowchart LR
  A["RLP bytes"] -- "Decodable.decode()" --> B["TxEnvelope"]
  B -- "build_transaction_input_from_envelope()" --> C["TransactionInput"]
  C -- "signature_hash()" --> D["B256 signature hash"]
Loading

File Walkthrough

Relevant files
Enhancement
transaction_input.rs
Add signature_hash and refactor decoding                                 

src/eth/types/transaction/transaction_input.rs

  • Introduce signature_hash() computing B256 from stored fields
  • Refactor RLP decoding into build_transaction_input_from_envelope()
  • Replace old try_from_alloy_transaction() conversion path
  • Add unit tests verifying signature hash matches envelope
+144/-26

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 6b243b5)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Incomplete signature hash

The new signature_hash() method defaults several important fields—access_list, blob‐related fields (blob_versioned_hashes, max_fee_per_blob_gas), and authorization_list—to empty or zero. It also uses the same gas_price for both max_fee_per_gas and max_priority_fee_per_gas. As a result, transactions that include a non‐empty access list, blob data, or distinct priority fees will produce an incorrect signing hash. This mismatch will only surface on real transactions with those fields populated.

fn signature_hash(&self) -> B256 {
    match self.transaction_info.tx_type.map(|t| t.as_u64()).unwrap_or(0) {
        // EIP-2930
        1 => TxEip2930 {
            chain_id: self.execution_info.chain_id.unwrap_or_default().into(),
            nonce: self.execution_info.nonce.into(),
            gas_price: self.execution_info.gas_price,
            gas_limit: self.execution_info.gas_limit.into(),
            to: TxKind::from(self.execution_info.to.map(Into::into)),
            value: self.execution_info.value.into(),
            input: self.execution_info.input.clone().into(),
            access_list: AccessList::default(),
        }
        .signature_hash(),

        // EIP-1559
        2 => TxEip1559 {
            chain_id: self.execution_info.chain_id.unwrap_or_default().into(),
            nonce: self.execution_info.nonce.into(),
            max_fee_per_gas: self.execution_info.gas_price,
            max_priority_fee_per_gas: self.execution_info.gas_price,
            gas_limit: self.execution_info.gas_limit.into(),
            to: TxKind::from(self.execution_info.to.map(Into::into)),
            value: self.execution_info.value.into(),
            input: self.execution_info.input.clone().into(),
            access_list: AccessList::default(),
        }
        .signature_hash(),

        // EIP-4844
        3 => TxEip4844 {
            chain_id: self.execution_info.chain_id.unwrap_or_default().into(),
            nonce: self.execution_info.nonce.into(),
            max_fee_per_gas: self.execution_info.gas_price,
            max_priority_fee_per_gas: self.execution_info.gas_price,
            gas_limit: self.execution_info.gas_limit.into(),
            to: self.execution_info.to.map(Into::into).unwrap_or_default(),
            value: self.execution_info.value.into(),
            input: self.execution_info.input.clone().into(),
            access_list: AccessList::default(),
            blob_versioned_hashes: Vec::default(),
            max_fee_per_blob_gas: 0,
        }
        .signature_hash(),

        // EIP-7702
        4 => TxEip7702 {
            chain_id: self.execution_info.chain_id.unwrap_or_default().into(),
            nonce: self.execution_info.nonce.into(),
            gas_limit: self.execution_info.gas_limit.into(),
            max_fee_per_gas: self.execution_info.gas_price,
            max_priority_fee_per_gas: self.execution_info.gas_price,
            to: self.execution_info.to.map(Into::into).unwrap_or_default(),
            value: self.execution_info.value.into(),
            input: self.execution_info.input.clone().into(),
            access_list: AccessList::default(),
            authorization_list: Vec::default(),
        }
        .signature_hash(),

        // Legacy (default)
        _ => TxLegacy {
            chain_id: self.execution_info.chain_id.map(Into::into),
            nonce: self.execution_info.nonce.into(),
            gas_price: self.execution_info.gas_price,
            gas_limit: self.execution_info.gas_limit.into(),
            to: TxKind::from(self.execution_info.to.map(Into::into)),
            value: self.execution_info.value.into(),
            input: self.execution_info.input.clone().into(),
        }
        .signature_hash(),
    }
}

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Latest suggestions up to 6b243b5
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Use TxKind for to field

Use a TxKind conversion for the to field in EIP-4844 and EIP-7702 arms to match how
other types are handled and ensure the signature hash aligns with to_tx_envelope.

src/eth/types/transaction/transaction_input.rs [187-203]

 // EIP-4844
 3 => TxEip4844 {
     ...
-    to: self.execution_info.to.map(Into::into).unwrap_or_default(),
+    to: TxKind::from(self.execution_info.to.map(Into::into)),
     ...
 }
 
 // EIP-7702
 4 => TxEip7702 {
     ...
-    to: self.execution_info.to.map(Into::into).unwrap_or_default(),
+    to: TxKind::from(self.execution_info.to.map(Into::into)),
     ...
 }
Suggestion importance[1-10]: 8

__

Why: Converting to with TxKind aligns EIP-4844 and EIP-7702 arms with other transaction types, ensuring consistent signature hash logic and preventing subtle bugs.

Medium
General
Qualify AccessList path

Qualify AccessList with its full path to avoid missing import errors and ensure the
code compiles without adding a new import. This makes it explicit where AccessList
is coming from.

src/eth/types/transaction/transaction_input.rs [162]

-access_list: AccessList::default(),
+access_list: alloy_consensus::AccessList::default(),
Suggestion importance[1-10]: 6

__

Why: Qualifying AccessList ensures the code compiles without adding a new import and prevents ambiguity, improving reliability with minimal change.

Low

Previous suggestions

Suggestions up to commit 7db6dee
CategorySuggestion                                                                                                                                    Impact
Possible issue
Separate EIP-1559 fee fields

Collapsing both fee fields into gas_price loses the original max and priority fee
distinction and will break EIP-1559 signature hashes when they differ. Split
ExecutionInfo.gas_price into max_fee_per_gas and max_priority_fee_per_gas, and use
them here.

src/eth/types/transaction/transaction_input.rs [170-171]

-// Inside the EIP-1559 arm of signature_hash:
-max_fee_per_gas: self.execution_info.gas_price,
-max_priority_fee_per_gas: self.execution_info.gas_price,
+max_fee_per_gas: self.execution_info.max_fee_per_gas,
+max_priority_fee_per_gas: self.execution_info.max_priority_fee_per_gas,
Suggestion importance[1-10]: 8

__

Why: Using the same gas_price for both EIP-1559 fee fields will produce incorrect signature hashes when original max_fee_per_gasmax_priority_fee_per_gas, so this is an important correctness fix.

Medium

@f3l1ph3s f3l1ph3s self-assigned this Aug 28, 2026
@f3l1ph3s
f3l1ph3s marked this pull request as ready for review August 28, 2026 19:10
@f3l1ph3s
f3l1ph3s requested a review from a team as a code owner August 28, 2026 19:10

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Nice refactor overall: decoding now builds TransactionInput directly from TxEnvelope, and the new signature_hash() path is covered by a focused consistency test against to_tx_envelope().signature_hash() across tx types 0–4.

I reviewed for correctness around signer recovery and hash derivation, and the implementation stays behaviorally aligned with the previous envelope-based hash flow for the fields currently persisted in TransactionInput.

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 6b243b5

@carneiro-cw carneiro-cw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong idea. The idea is to decode transaction input directly from the received rlp. This means that we never even create the alloy types in the first place, the rlp gets decoded directly to TransactionInput, this means we don't ever even decode to TxEnvelope.

Before doing this however, a better issue to solve first is #2548 . Since then when receiving an eth_sendRawTransaction we wouldn't have to do any conversions with alloy at all.

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the refactor — moving decode toward TransactionInput directly is a good direction. I found one blocking correctness issue in signer recovery:

Blocking: signature_hash() now reconstructs typed txs with fields that are not persisted in TransactionInput (access list, 1559 priority fee, 4844 blob fields, 7702 authorization list) using defaults. For any real tx where those fields are non-default, recovered prehash will differ from the original signed prehash, so signer recovery can fail or recover the wrong address.

Concretely in this diff:

  • type 1/2: access_list: AccessList::default()
  • type 2/3/4: max_priority_fee_per_gas = gas_price
  • type 3: blob_versioned_hashes = [], max_fee_per_blob_gas = 0
  • type 4: authorization_list = []

Because build_transaction_input_from_envelope() now calls recover_signer_address() (which uses this new hash path), this can break immediately on decode of valid raw txs carrying those fields.

Suggested fix options:

  1. Keep using envelope-native signing hash for recovery when decoding from raw tx (envelope.signature_hash()), and only use field-derived hash where you can guarantee complete persisted fields; or
  2. Extend TransactionInput/ExecutionInfo to store all signing-relevant fields per tx type, then compute hash from fully faithful data.

Also, current test only checks signature_hash() vs to_tx_envelope() built from the same reduced fields, so it can’t catch this class of mismatch. Please add a test with a real typed tx (e.g. 1559 with non-empty access list / different priority fee, and/or 4844 with blob hashes) and assert recovered signer matches the signer from the original envelope/raw tx.

@f3l1ph3s f3l1ph3s changed the title feat: decode rlp directly from tx_input feat: decode tx_input directly from RLP Aug 31, 2026

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Thanks for pushing this forward — decoding TransactionInput directly from raw tx bytes is a good direction and the new decode tests are valuable. I found one blocking correctness issue in signer recovery/hash derivation for typed transactions.

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Thanks for the refactor toward direct raw-transaction decoding; the structure is clearer and the decode-path tests are useful. I found one blocking correctness issue that can break signer recovery for valid typed transactions.

Blocking: signature_hash() is reconstructed from a reduced field set and injects defaults/placeholders for typed-tx fields that are actually signed. For tx types 1/2/3/4 this can change the signing preimage (e.g., non-empty access list, differing 1559 tip vs max fee, 4844 blob fields, 7702 authorization list), so recover_signer_address() may recover the wrong address or fail.

Current tests don’t catch this because they only exercise default/degenerate values (empty lists and equal fee fields), where reconstructed and original preimages happen to match.

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Thanks for the refactor — decoding from raw bytes and removing the rlp crate dependency is a good direction. However, there is still one blocking correctness issue in signer recovery for typed transactions.

Blocking

TransactionInput::signature_hash() reconstructs typed preimages with placeholder/default values for signed fields that are not preserved in TransactionInput (e.g. access list, 1559 priority fee, 4844 blob fields, 7702 authorization list). Because recover_signer_address() now depends on this reconstructed hash, valid transactions with non-default values can recover the wrong signer or fail recovery.

Current tests only cover degenerate/default cases (empty lists and equal tip/max-fee), so they do not exercise this failure mode.

@cloudwalk-review-agent cloudwalk-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Thanks for the refactor toward direct raw-byte decoding and for adding decode/signature-hash tests. I still found one blocking correctness issue in signer recovery for typed transactions.

Blocking

TransactionInput::signature_hash() reconstructs typed signing payloads using placeholder/default values for signed fields that are not persisted in TransactionInput (e.g. access list, 1559 priority fee, 4844 blob fields, 7702 authorization list). Because recover_signer_address() now uses this reconstructed hash, valid transactions with non-default values in those fields can recover the wrong signer or fail recovery.

Current new tests only validate degenerate/default cases (empty lists and equal tip/max-fee), so this failure mode is not covered.

@f3l1ph3s
f3l1ph3s requested a review from carneiro-cw September 2, 2026 15:56
Comment thread src/eth/types/transaction/transaction_input.rs
Comment thread src/eth/types/transaction/transaction_input.rs
Comment thread src/eth/types/transaction/transaction_input.rs
Comment on lines +190 to +200
let encoded = Self::encode_rlp_list(&[
&chain_id,
&nonce,
&gas_price,
&gas_limit,
&to.as_slice(),
&value,
&input.as_slice(),
&AccessList::default(),
]);
let mut out = Vec::with_capacity(1 + encoded.len());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

u're repeating this snippet at every match, the only thing that it's changing it's the hex value that u're passing to out.push

maybe it's worth extracting this snippet out of the match statement and only apply the out.push at the match

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noticed that u're also adding new fields to the array passed into encode_rlp_list depending of the EIP, my suggestion stands

Comment on lines +507 to +559
let max_priority_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxPriorityFeePerGas"))?;
let max_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxFeePerGas"))?;
gas_price = max_fee_per_gas;
let _ = max_priority_fee_per_gas;
gas_limit = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasLimit"))?;
let to_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing to"))?;
to = Self::decode_to(&to_bytes)?;
value = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing value"))?;
let input_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing input"))?;
input = input_bytes.to_vec();
let _: AccessList = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing accessList"))?;
v = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing v"))?;
r = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing r"))?;
s = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing s"))?;
}

// EIP-4844
3 => {
let max_priority_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxPriorityFeePerGas"))?;
let max_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxFeePerGas"))?;
gas_price = max_fee_per_gas;
let _ = max_priority_fee_per_gas;
gas_limit = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasLimit"))?;
let to_addr: AlloyAddress = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing to"))?;
to = Some(Address::from(to_addr.0));
value = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing value"))?;
let input_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing input"))?;
input = input_bytes.to_vec();
let _: AccessList = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing accessList"))?;
let _: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxFeePerBlobGas"))?;
let _: Vec<B256> = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing blobVersionedHashes"))?;
v = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing v"))?;
r = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing r"))?;
s = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing s"))?;
}

// EIP-7702
4 => {
let max_priority_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxPriorityFeePerGas"))?;
let max_fee_per_gas: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing maxFeePerGas"))?;
gas_price = max_fee_per_gas;
let _ = max_priority_fee_per_gas;
gas_limit = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasLimit"))?;
let to_addr: AlloyAddress = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing to"))?;
to = Some(Address::from(to_addr.0));
value = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing value"))?;
let input_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing input"))?;
input = input_bytes.to_vec();
let _: AccessList = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing accessList"))?;
let _: Vec<SignedAuthorization> = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing authorizationList"))?;
v = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing v"))?;
r = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing r"))?;
s = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing s"))?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three are very similar, maybe there's a way to u abstract/generalize this snippet of code

Comment on lines +453 to +461
let nonce: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing nonce"))?;
let gas_price: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasPrice"))?;
let gas_limit: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasLimit"))?;
let to_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing to"))?;
let value: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing value"))?;
let input: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing input"))?;
let v: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing v"))?;
let r: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing r"))?;
let s: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing s"))?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe u can implement from or try_from to do this in a more self-contained way

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to do it u would probably need to create a dto with those fields

at stratus we usually don't do that if the dto will be barely used, so take ur time and think about it

If u can define a good, small dto and it will be well reused at the module, it's ok

@carneiro-cw carneiro-cw Sep 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The right approach would be to implement Decodable for each of the the types in TransactionInput. Most, if not all should be pretty straightforward as we'd only need to delegate to the newtype's inner Decodable implementation.

It might be possible to make a trait Primitive that has a type parameter type inner: Decodable and then impl<T: StratusDecodable> Decodable for T where the decode function returns Self(inner::decode(buf)). Or if that doesn't work, a derive macro in stratus_macros.

Or maybe just use the RlpDecodable/RlpEnecodable derive macros from alloy_rlp. I think it does that in a more generalized manner.

}

/// Decodes a legacy transaction from raw RLP bytes.
fn decode_legacy(raw_bytes: &[u8]) -> alloy_rlp::Result<Self> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use stratus error types (src/eth/rpc/types/error.rs), either return StratusError or some of the more specific enums. If you think it makes sense you can create a new error enum for RLP parsing and add that as a variant in StratusError OR in RpcError (Maybe changing RpcError::ParameterDecodeError but idk maybe some new variant)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also use anyhow::Result

Comment on lines +453 to +461
let nonce: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing nonce"))?;
let gas_price: u128 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasPrice"))?;
let gas_limit: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing gasLimit"))?;
let to_bytes: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing to"))?;
let value: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing value"))?;
let input: AlloyBytes = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing input"))?;
let v: u64 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing v"))?;
let r: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing r"))?;
let s: U256 = rlp.get_next()?.ok_or(alloy_rlp::Error::Custom("missing s"))?;

@carneiro-cw carneiro-cw Sep 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The right approach would be to implement Decodable for each of the the types in TransactionInput. Most, if not all should be pretty straightforward as we'd only need to delegate to the newtype's inner Decodable implementation.

It might be possible to make a trait Primitive that has a type parameter type inner: Decodable and then impl<T: StratusDecodable> Decodable for T where the decode function returns Self(inner::decode(buf)). Or if that doesn't work, a derive macro in stratus_macros.

Or maybe just use the RlpDecodable/RlpEnecodable derive macros from alloy_rlp. I think it does that in a more generalized manner.

}
}

impl TryFrom<AlloyTransaction> for TransactionInput {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dead code now :) you can remove it

}

fn try_from_alloy_transaction(value: alloy_rpc_types_eth::Transaction) -> anyhow::Result<TransactionInput> {
fn build_transaction_input_from_envelope(envelope: &TxEnvelope) -> anyhow::Result<TransactionInput> {

@carneiro-cw carneiro-cw Sep 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still needed for now because of the importer .

I think today one easy win would be updating stratus_get_block_and_receipts to serialize stratus::eth::types::Block directly instead of converting to the alloy type. Then updating the importers. We can leave this to another PR but should be straightforward. We probably should add an optional parameter to the request for selecting what type of response it expects to maintain backwards compatibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after adding that this and try_from_alloy_transaction can be removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants