Skip to content

Add opt-in revert protection #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
May 23, 2025
Merged

Conversation

ferranbt
Copy link
Collaborator

πŸ“ Summary

Missing tests

πŸ’‘ Motivation and Context


βœ… I have completed the following steps:

  • Run make lint
  • Run make test
  • Added tests (if applicable)

@ferranbt ferranbt requested review from SozinM and avalonche as code owners May 21, 2025 10:11
}

// Test 2: Bundle reverts. It is not included in the block
{}
Copy link
Contributor

Choose a reason for hiding this comment

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

is this a TODO?

Copy link
Collaborator Author

@ferranbt ferranbt May 21, 2025

Choose a reason for hiding this comment

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

Yes, tests are not finished yet, but feel free to review the rest.

pub trait FBPoolTransaction:
EthPoolTransaction + MaybeInteropTransaction + MaybeConditionalTransaction + DataAvailabilitySized
{
fn set_exclude_reverting_txs(&mut self, exclude: bool);
Copy link
Contributor

Choose a reason for hiding this comment

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

naming is a bit confusing, can it be called revert_protected_txs?

@@ -85,8 +75,8 @@ pub struct ExecutedPayload<N: NodePrimitives> {
#[non_exhaustive]
pub struct CustomOpPayloadBuilder {
builder_signer: Option<Signer>,
#[allow(dead_code)]
Copy link
Contributor

Choose a reason for hiding this comment

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

why is there dead code?

pub trait FBPoolTransaction:
EthPoolTransaction + MaybeInteropTransaction + MaybeConditionalTransaction + DataAvailabilitySized
{
fn set_exclude_reverting_txs(&mut self, exclude: bool);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fn set_exclude_reverting_txs(&mut self, exclude: bool);
fn set_reverting(&mut self, reverting: bool);

EthPoolTransaction + MaybeInteropTransaction + MaybeConditionalTransaction + DataAvailabilitySized
{
fn set_exclude_reverting_txs(&mut self, exclude: bool);
fn exclude_reverting_txs(&self) -> bool;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fn exclude_reverting_txs(&self) -> bool;
fn reverting(&self) -> bool;

@ferranbt ferranbt changed the title [Draft] Add revert protection endpoint Add opt-in revert protection May 21, 2025
@SozinM
Copy link
Collaborator

SozinM commented May 21, 2025

Looks almost perfect!

@ferranbt ferranbt requested a review from karim-agha May 22, 2025 11:33
rollup_args.supervisor_safety_level,
),
)
.payload(CustomOpPayloadBuilder::new(
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: maybe we can make CustomOpPayloadBuilder accept BuilderArgs as a constructor parameter to avoid passing too many individual arguments and changing this code as the list of arguments grows over time.

@@ -137,10 +128,10 @@ where
Primitives = OpPrimitives,
>,
>,
Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
Pool: TransactionPool<Transaction: FBPoolTransaction<Consensus = OpTransactionSigned>>
Copy link
Contributor

Choose a reason for hiding this comment

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

as part of my change in eliminating the need to have conditional builds I have used this pattern:

pub trait NodeBounds:
    FullNodeTypes<
    Types: NodeTypes<Payload = OpEngineTypes, ChainSpec = OpChainSpec, Primitives = OpPrimitives>,
>
{
}

impl<T> NodeBounds for T where
    T: FullNodeTypes<
        Types: NodeTypes<
            Payload = OpEngineTypes,
            ChainSpec = OpChainSpec,
            Primitives = OpPrimitives,
        >,
    >
{
}

pub trait PoolBounds<Node>: TransactionPool<Transaction: OpPooledTx> + Unpin + 'static
where
    Node: FullNodeTypes<
        Types: NodeTypes<
            Payload = OpEngineTypes,
            ChainSpec = OpChainSpec,
            Primitives = OpPrimitives,
        >,
    >,
{
}

impl<Node, T> PoolBounds<Node> for T
where
    T: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
        + Unpin
        + 'static,
    Node: FullNodeTypes<
        Types: NodeTypes<
            Payload = OpEngineTypes,
            ChainSpec = OpChainSpec,
            Primitives = OpPrimitives,
        >,
    >,
    <Self as TransactionPool>::Transaction: OpPooledTx,
{
}

Then every time you need to implement a type that needs those bounds you can just say:

impl<Node, Pool> reth_payload::PayloadBuilder for StandardBuilder<Node, Pool>
where
    Node: NodeBounds,
    Pool: PoolBounds<Node>,
{
  // ...
}

This should make the code significantly more readable and impls less chaotic.

},
)
self.build_payload(args, |attrs| {
#[allow(clippy::unit_arg)]
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this linter exception needed?

Comment on lines 36 to 46
impl Bundle {
fn conditional(&self) -> TransactionConditional {
TransactionConditional {
block_number_min: None,
block_number_max: self.block_number_max,
known_accounts: Default::default(),
timestamp_max: None,
timestamp_min: None,
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we could keep it close to the structure declaration in bundle.rs?

// 'Transaction event received target="monitoring" tx_hash="<tx_hash>" kind="discarded"'
let builder_logs = std::fs::read_to_string(&self.builder_log_path)?;
let txn_log = format!(
"Transaction event received target=\"monitoring\" tx_hash=\"{}\" kind=\"discarded\"",
Copy link
Contributor

Choose a reason for hiding this comment

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

Def not within the scope of this PR, but in the future I think that we should make this more type safe and insert a #[cfg(test)] debug_probe: DebugProbe somewhere in the builder to verify those types of things more reliably. Checking logs texts can be very fragile in the long run.


let tx_hash = provider
.client()
.request("eth_sendBundle", (bundle,))
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to make this more explicit and make the TransactionBuilder build a Bundle type or have BundleBuilder type altogether? Not entirely sure if this preserves separation of concerns.

@SozinM SozinM merged commit 3bc0aff into main May 23, 2025
3 checks passed
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.

4 participants