Skip to content

feat(sequencer)!: enforce block ordering by transaction group #1618

Merged
lobstergrindset merged 16 commits intomainfrom
lilyjjo/order_blocks_by_tx_category
Oct 11, 2024
Merged

feat(sequencer)!: enforce block ordering by transaction group #1618
lobstergrindset merged 16 commits intomainfrom
lilyjjo/order_blocks_by_tx_category

Conversation

@lobstergrindset
Copy link
Contributor

Summary

We want to order blocks by the transaction categories introduced in #1512 to finish the goals of #1412.

Background

Certain transactions have the ability to cause other transactions to become invalid. For example, FeeChangeActions can cause transactions that were valid to become invalid. For the sake of UX we want to order the potentially-invalidating actions after others so we don't needlessly execute transactions that were just invalidated. More background can be found in #1412.

Changes

  • The mempool now orders the transactions it feeds to prepare_proposal by ActionGroup.
  • prepare_proposal will now skip any transactions in it's block construction process that are out of group order.
  • process_proposal will now reject any blocks that contain out-of-order transactions.

Note: the mempool does not check for out of order actions inside of the pending queue. This was decided because the amount of times that actions besides BundleableGeneral are expected to be ran is low. Instead we let prepare_proposal gracefully ignore out-of-order actions in a way that allows them to be included in future blocks.

For example, let's say an account sends these two transactions into the mempool:

  • tx_0: {nonce: 0, action_group: UnbundleableGeneral}
  • tx_1: {nonce: 1, action_group: BundleableGeneral}

The mempool will feed these transaction in the order of {tx_1, tx_0} to prepare_proposal, which is correct on a group ordering level but incorrect on a nonce ordering level. prepare_proposal will handle this by skipping tx_1 and only including tx_0 in the block. The mempool will re-feed tx_1 on the next round to prepare_proposal to be included.

Testing

Unit tests and ran locally.

Breaking Changelist

Block that would've passed before with incorrect transaction ordering will now fail.

Related Issues

closes #1412 #1417

@lobstergrindset lobstergrindset marked this pull request as ready for review October 3, 2024 13:20
@lobstergrindset lobstergrindset requested a review from a team as a code owner October 3, 2024 13:20
@github-actions github-actions bot added the sequencer pertaining to the astria-sequencer crate label Oct 3, 2024
@lobstergrindset lobstergrindset marked this pull request as draft October 3, 2024 13:21
@lobstergrindset
Copy link
Contributor Author

Oops, hit the wrong button. This isn't ready for review.

@lobstergrindset lobstergrindset marked this pull request as ready for review October 3, 2024 16:38
BundleableGeneral,
UnbundleableGeneral,
BundleableSudo,
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is public now, might be nice to add a little rustdoc comments to the enum and its variants.

Comment on lines 85 to 88
UnbundleableSudo,
BundleableSudo,
UnbundleableGeneral,
BundleableGeneral,
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the ordering here is very load-bearing. It might be worth adding explicit values to each variant to make this more obvious (maybe also a non-rustdoc "// NOTE: ..." comment on the enum)?

Suggested change
UnbundleableSudo,
BundleableSudo,
UnbundleableGeneral,
BundleableGeneral,
UnbundleableSudo = 1,
BundleableSudo = 2,
UnbundleableGeneral = 3,
BundleableGeneral = 4,

Also probably worth adding a unit test to try and avoid an accidental change here, e.g.

#[test]
fn should_be_in_correct_order() {
    assert_eq!(ActionGroup::UnbundleableSudo < ActionGroup::BundleableSudo);
    assert_eq!(ActionGroup::BundleableSudo < ActionGroup::UnbundleableGeneral);
    assert_eq!(ActionGroup::UnbundleableGeneral < ActionGroup::BundleableGeneral);
}

);
excluded_tx_count = excluded_tx_count.saturating_add(1);
continue;
return Err(eyre!("max block sequenced data limit passed"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return Err(eyre!("max block sequenced data limit passed"));
bail!("max block sequenced data limit passed");

Copy link
Contributor

Choose a reason for hiding this comment

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

Also would be nice to have a unit test for this change, asserting we return here rather than relying on the final tx count causing the proposal to fail. Could be a follow-up PR though, since there are maybe a bunch of similar tests which could be added?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the unit tests checking for the other error cases!

"transaction error: failed to execute transaction"
);
excluded_tx_count = excluded_tx_count.saturating_add(1);
return Err(eyre!("transaction failed to execute"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return Err(eyre!("transaction failed to execute"));
bail!("transaction failed to execute");


assert!(bundleable_sudo >= bundleable_sudo);
assert!(bundleable_sudo >= unbundleable_sudo);

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
assert!(unbundleable_sudo >= unbundleable_sudo);

@github-actions github-actions bot added the composer pertaining to composer label Oct 9, 2024
Copy link
Contributor

@SuperFluffy SuperFluffy left a comment

Choose a reason for hiding this comment

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

Looks fine to me, going to follow @Fraser999's approval.

I just left some minor comments.

/// # Panics
/// Method is expected to never panic because only `SequenceActions` are added to the bundle,
/// which should produce a valid variant of the `ActionGroup` type.
/// which should produce a valid variant of the `Action::Group` type.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// which should produce a valid variant of the `Action::Group` type.
/// which should produce a valid variant of the [`action::Group`] type.

"method is expected to never panic because only `SequenceActions` are added to \
the bundle, which should produce a valid variant of the `ActionGroup` type; this \
is checked by `tests::transaction_construction_should_not_panic",
the bundle, which should produce a valid variant of the `Action::Group` type; \
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
the bundle, which should produce a valid variant of the `Action::Group` type; \
the bundle, which should produce a valid variant of the `action::Group` type; \

///
/// # Errors
/// Returns an error if the actions do not make a valid `ActionGroup`.
/// Returns an error if the actions do not make a valid `Action::Group`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Returns an error if the actions do not make a valid `Action::Group`.
/// Returns an error if the actions do not make a valid [`action::Group`].

group: Group,
}

impl PartialEq for TransactionPriority {
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this the same as deriving PartialEq?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you say more about what you mean by this? I'm a little confused

Copy link
Contributor

@SuperFluffy SuperFluffy Oct 11, 2024

Choose a reason for hiding this comment

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

I meant that your manual implementation looks the same as deriving PartialEq. Maybe at some point the type contained some field that you wanted to exclude from the comparison, but then you removed it at some point?

I'd derive PartialEq now instead of doing it manually.

@lobstergrindset lobstergrindset added this pull request to the merge queue Oct 11, 2024
Merged via the queue into main with commit 412eebe Oct 11, 2024
@lobstergrindset lobstergrindset deleted the lilyjjo/order_blocks_by_tx_category branch October 11, 2024 11:31
steezeburger added a commit that referenced this pull request Oct 11, 2024
* main:
  feat(sequencer)!: enforce block ordering by transaction group  (#1618)
  fix(cli): ensure checkTx passes before waiting for inclusion (#1636)
  chore(sequencer)!: update storage keys locations and values (ENG-898) (#1616)
  chore: cargo audit warning (#1644)
  chore(proto, core)!: remove action suffix from all action types (#1630)
  feat(sequencer)!: add limit to total amount of transactions in parked  (#1638)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

composer pertaining to composer sequencer pertaining to the astria-sequencer crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

block ordering and tx inclusion action rules

3 participants