Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3cd390a
ready for review
lobstergrindset Sep 18, 2024
ed325e8
fix comment
lobstergrindset Sep 18, 2024
5fbd0b7
respond to review
lobstergrindset Sep 23, 2024
de9b744
fix clippy errors
lobstergrindset Sep 23, 2024
b275612
address comments from @noot
lobstergrindset Sep 25, 2024
8162f9d
respond to all comments by @SuperFluffy except builder pattern
lobstergrindset Sep 25, 2024
a6f91a9
switch to combined builder for UnsignedTransaction and TransactionParams
lobstergrindset Sep 26, 2024
d3f0cf9
Merge branch 'main' into lilyjjo/transaction_categories_no_types
lobstergrindset Sep 26, 2024
3694ee6
add IbcSudo action pieces
lobstergrindset Sep 26, 2024
940cade
cleanup
lobstergrindset Sep 26, 2024
888b478
Merge branch 'main' into lilyjjo/transaction_categories_no_types
lobstergrindset Sep 26, 2024
50eda1e
update breaking test
lobstergrindset Sep 26, 2024
e41f6c7
Update crates/astria-sequencer/src/app/snapshots/astria_sequencer__ap…
lobstergrindset Sep 26, 2024
3e79a1c
respond to comments by @Fraser999
lobstergrindset Sep 28, 2024
613993f
respond to comment by @SuperFluffy
lobstergrindset Sep 30, 2024
aca96e9
Merge branch 'main' into lilyjjo/transaction_categories_no_types
lobstergrindset Sep 30, 2024
1809748
Merge branch 'main' into lilyjjo/transaction_categories_no_types
lobstergrindset Sep 30, 2024
052dbfd
respond to comments by @SuperFluffy
lobstergrindset Sep 30, 2024
503e2e0
clippy lint
lobstergrindset Sep 30, 2024
6a8a937
clippy lint
lobstergrindset Sep 30, 2024
38cd7a4
clippy
lobstergrindset Sep 30, 2024
33c9d44
clippy final fix pls
lobstergrindset Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use astria_core::{
},
protocol::transaction::v1alpha1::{
Action,
TransactionParams,
UnsignedTransaction,
},
};
Expand Down Expand Up @@ -154,13 +153,12 @@ impl Submitter {
.wrap_err("failed to get nonce from sequencer")?;
debug!(nonce, "fetched latest nonce");

let unsigned = UnsignedTransaction {
actions,
params: TransactionParams::builder()
.nonce(nonce)
.chain_id(sequencer_chain_id)
.build(),
};
let unsigned = UnsignedTransaction::builder()
.actions(actions)
.nonce(nonce)
.chain_id(sequencer_chain_id)
.try_build()
.wrap_err("failed to build unsigned transaction")?;

// sign transaction
let signed = unsigned.into_signed(signer.signing_key());
Expand Down
16 changes: 7 additions & 9 deletions crates/astria-cli/src/commands/bridge/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use astria_core::{
crypto::SigningKey,
protocol::transaction::v1alpha1::{
Action,
TransactionParams,
UnsignedTransaction,
},
};
Expand Down Expand Up @@ -129,14 +128,13 @@ async fn submit_transaction(
.await
.wrap_err("failed to get nonce")?;

let tx = UnsignedTransaction {
params: TransactionParams::builder()
.nonce(nonce_res.nonce)
.chain_id(chain_id)
.build(),
actions,
}
.into_signed(signing_key);
let tx = UnsignedTransaction::builder()
.actions(actions)
.nonce(nonce_res.nonce)
.chain_id(chain_id)
.try_build()
.wrap_err("failed to build transaction from actions")?
.into_signed(signing_key);
let res = client
.submit_transaction_sync(tx)
.await
Expand Down
16 changes: 7 additions & 9 deletions crates/astria-cli/src/commands/sequencer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use astria_core::{
TransferAction,
ValidatorUpdate,
},
TransactionParams,
UnsignedTransaction,
},
};
Expand Down Expand Up @@ -475,14 +474,13 @@ async fn submit_transaction(
.await
.wrap_err("failed to get nonce")?;

let tx = UnsignedTransaction {
params: TransactionParams::builder()
.nonce(nonce_res.nonce)
.chain_id(chain_id)
.build(),
actions: vec![action],
}
.into_signed(&sequencer_key);
let tx = UnsignedTransaction::builder()
.actions(vec![action])
.nonce(nonce_res.nonce)
.chain_id(chain_id)
.try_build()
.wrap_err("failed to build transaction from actions")?
.into_signed(&sequencer_key);
let res = sequencer_client
.submit_transaction_sync(tx)
.await
Expand Down
27 changes: 22 additions & 5 deletions crates/astria-composer/src/executor/bundle_factory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use astria_core::{
protocol::transaction::v1alpha1::{
action::SequenceAction,
Action,
UnsignedTransaction,
},
Protobuf as _,
};
Expand Down Expand Up @@ -74,6 +75,27 @@ impl SizedBundle {
}
}

/// Constructs an [`UnsignedTransaction`] from the actions contained in the bundle and `params`.
/// # 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.
pub(super) fn to_unsigned_transaction(
&self,
nonce: u32,
chain_id: &str,
) -> UnsignedTransaction {
UnsignedTransaction::builder()
.actions(self.buffer.clone())
.chain_id(chain_id)
.nonce(nonce)
.try_build()
.expect(
"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",
)
}

/// Buffer `seq_action` into the bundle.
/// # Errors
/// - `seq_action` is beyond the max size allowed for the entire bundle
Expand Down Expand Up @@ -111,11 +133,6 @@ impl SizedBundle {
self.curr_size
}

/// Consume self and return the underlying buffer of actions.
pub(super) fn into_actions(self) -> Vec<Action> {
self.buffer
}

/// Returns the number of sequence actions in the bundle.
pub(super) fn actions_count(&self) -> usize {
self.buffer.len()
Expand Down
34 changes: 28 additions & 6 deletions crates/astria-composer/src/executor/bundle_factory/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ mod sized_bundle {
assert!(bundle.buffer.is_empty());

// assert that the flushed bundle has just the sequence action pushed earlier
let actions = flushed_bundle.into_actions();
let actions = flushed_bundle.buffer;
assert_eq!(actions.len(), 1);
let actual_seq_action = actions[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action.rollup_id);
Expand Down Expand Up @@ -137,7 +137,7 @@ mod bundle_factory {
assert_eq!(bundle_factory.finished.len(), 1);
// assert `pop_finished()` will return `seq_action0`
let next_actions = bundle_factory.next_finished();
let actions = next_actions.unwrap().pop().into_actions();
let actions = next_actions.unwrap().pop().buffer;
let actual_seq_action = actions[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action0.rollup_id);
assert_eq!(actual_seq_action.data, seq_action0.data);
Expand Down Expand Up @@ -240,7 +240,7 @@ mod bundle_factory {
// assert that the finished queue is empty (curr wasn't flushed)
assert_eq!(bundle_factory.finished.len(), 0);
// assert `pop_now()` returns `seq_action`
let actions = bundle_factory.pop_now().into_actions();
let actions = bundle_factory.pop_now().buffer;
let actual_seq_action = actions[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action.rollup_id);
assert_eq!(actual_seq_action.data, seq_action.data);
Expand All @@ -265,7 +265,7 @@ mod bundle_factory {
// assert that the bundle factory has one bundle in the finished queue
assert_eq!(bundle_factory.finished.len(), 1);
// assert `pop_now()` will return `seq_action0`
let actions = bundle_factory.pop_now().into_actions();
let actions = bundle_factory.pop_now().buffer;
let actual_seq_action = actions[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action0.rollup_id);
assert_eq!(actual_seq_action.data, seq_action0.data);
Expand Down Expand Up @@ -300,7 +300,7 @@ mod bundle_factory {
assert_eq!(bundle_factory.finished.len(), 1);

// assert `pop_now()` will return `seq_action0` on the first call
let actions_finished = bundle_factory.pop_now().into_actions();
let actions_finished = bundle_factory.pop_now().buffer;
assert_eq!(actions_finished.len(), 1);
let actual_seq_action = actions_finished[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action0.rollup_id);
Expand All @@ -310,7 +310,7 @@ mod bundle_factory {
assert_eq!(bundle_factory.finished.len(), 0);

// assert `pop_now()` will return `seq_action1` on the second call (i.e. from curr)
let actions_curr = bundle_factory.pop_now().into_actions();
let actions_curr = bundle_factory.pop_now().buffer;
assert_eq!(actions_curr.len(), 1);
let actual_seq_action = actions_curr[0].as_sequence().unwrap();
assert_eq!(actual_seq_action.rollup_id, seq_action1.rollup_id);
Expand All @@ -337,4 +337,26 @@ mod bundle_factory {
assert_eq!(bundle_factory.finished.len(), 0);
assert!(!bundle_factory.is_full());
}

#[test]
fn transaction_construction_does_not_panic() {
let mut bundle_factory = BundleFactory::new(1000, 10);

bundle_factory
.try_push(sequence_action_with_n_bytes(50))
.unwrap();
bundle_factory
.try_push(sequence_action_with_n_bytes(50))
.unwrap();
bundle_factory
.try_push(sequence_action_with_n_bytes(50))
.unwrap();

let bundle = bundle_factory.pop_now();

// construction of multiple sequence actions should not panic
let unsigned_tx = bundle.to_unsigned_transaction(0, "astria-testnet-1");

assert_eq!(unsigned_tx.actions().len(), 3);
}
}
29 changes: 8 additions & 21 deletions crates/astria-composer/src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ use astria_core::{
transaction::v1alpha1::{
action::SequenceAction,
SignedTransaction,
TransactionParams,
UnsignedTransaction,
},
},
};
Expand Down Expand Up @@ -670,23 +668,17 @@ impl Future for SubmitFut {
type Output = eyre::Result<u32>;

// FIXME (https://github.com/astriaorg/astria/issues/1572): This function is too long and should be refactored.
#[expect(clippy::too_many_lines, reason = "this may warrant a refactor")]
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
const INVALID_NONCE: Code = Code::Err(AbciErrorCode::INVALID_NONCE.value());
loop {
let this = self.as_mut().project();

let new_state = match this.state.project() {
SubmitStateProj::NotStarted => {
let params = TransactionParams::builder()
.nonce(*this.nonce)
.chain_id(&*this.chain_id)
.build();
let tx = UnsignedTransaction {
actions: this.bundle.clone().into_actions(),
params,
}
.into_signed(this.signing_key);
let tx = this
.bundle
.to_unsigned_transaction(*this.nonce, &*this.chain_id)
.into_signed(this.signing_key);
info!(
nonce.actual = *this.nonce,
bundle = %telemetry::display::json(&SizedBundleReport(this.bundle)),
Expand Down Expand Up @@ -756,15 +748,10 @@ impl Future for SubmitFut {
} => match ready!(fut.poll(cx)) {
Ok(nonce) => {
*this.nonce = nonce;
let params = TransactionParams::builder()
.nonce(*this.nonce)
.chain_id(&*this.chain_id)
.build();
let tx = UnsignedTransaction {
actions: this.bundle.clone().into_actions(),
params,
}
.into_signed(this.signing_key);
let tx = this
.bundle
.to_unsigned_transaction(*this.nonce, &*this.chain_id)
.into_signed(this.signing_key);
info!(
nonce.resubmission = *this.nonce,
bundle = %telemetry::display::json(&SizedBundleReport(this.bundle)),
Expand Down
24 changes: 11 additions & 13 deletions crates/astria-core/src/protocol/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@ use prost::Message as _;

use super::{
group_sequence_actions_in_signed_transaction_transactions_by_rollup_id,
transaction::v1alpha1::{
action::SequenceAction,
TransactionParams,
UnsignedTransaction,
},
transaction::v1alpha1::action::SequenceAction,
};
use crate::{
crypto::SigningKey,
primitive::v1::{
derive_merkle_tree_from_rollup_txs,
RollupId,
},
protocol::transaction::v1alpha1::UnsignedTransaction,
sequencerblock::v1alpha1::{
block::Deposit,
SequencerBlock,
Expand Down Expand Up @@ -107,16 +104,17 @@ impl ConfigureSequencerBlock {
let txs = if actions.is_empty() {
vec![]
} else {
let unsigned_transaction = UnsignedTransaction {
actions,
params: TransactionParams::builder()
.nonce(1)
.chain_id(chain_id.clone())
.build(),
};
let unsigned_transaction = UnsignedTransaction::builder()
.actions(actions)
.chain_id(chain_id.clone())
.nonce(1)
.try_build()
.expect(
"should be able to build unsigned transaction since only sequence actions are \
contained",
);
vec![unsigned_transaction.into_signed(&signing_key)]
};

let mut deposits_map: HashMap<RollupId, Vec<Deposit>> = HashMap::new();
for deposit in deposits {
if let Some(entry) = deposits_map.get_mut(&deposit.rollup_id) {
Expand Down
36 changes: 36 additions & 0 deletions crates/astria-core/src/protocol/transaction/v1alpha1/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl Protobuf for Action {
}
}

// TODO: add unit tests for these methods (https://github.com/astriaorg/astria/issues/1593)
impl Action {
#[must_use]
pub fn as_sequence(&self) -> Option<&SequenceAction> {
Expand All @@ -169,6 +170,14 @@ impl Action {
};
Some(transfer_action)
}

pub fn is_fee_asset_change(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's make a tracking issue to add unit tests for these.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

created and commented in code: #1593

matches!(self, Self::FeeAssetChange(_))
}

pub fn is_fee_change(&self) -> bool {
matches!(self, Self::FeeChange(_))
}
}

impl From<SequenceAction> for Action {
Expand Down Expand Up @@ -263,6 +272,33 @@ impl TryFrom<raw::Action> for Action {
}
}

// TODO: replace this trait with a Protobuf:FullName implementation.
// Issue tracked in #1567
pub(super) trait ActionName {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this. All of these should be done via the Protobuf trait implemented at the root of the crate - I intend to rename it to DomainType.

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed offline: this should flow through Protobuf::full_name but is out of scope for this PR. @Lilyjjo will create a PR to follow up on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tracked in a note in the code and here: #1567

fn name(&self) -> &'static str;
}

impl ActionName for Action {
fn name(&self) -> &'static str {
match self {
Action::Sequence(_) => "Sequence",
Action::Transfer(_) => "Transfer",
Action::ValidatorUpdate(_) => "ValidatorUpdate",
Action::SudoAddressChange(_) => "SudoAddressChange",
Action::Ibc(_) => "Ibc",
Action::IbcSudoChange(_) => "IbcSudoChange",
Action::Ics20Withdrawal(_) => "Ics20Withdrawal",
Action::IbcRelayerChange(_) => "IbcRelayerChange",
Action::FeeAssetChange(_) => "FeeAssetChange",
Action::InitBridgeAccount(_) => "InitBridgeAccount",
Action::BridgeLock(_) => "BridgeLock",
Action::BridgeUnlock(_) => "BridgeUnlock",
Action::BridgeSudoChange(_) => "BridgeSudoChange",
Action::FeeChange(_) => "FeeChange",
}
}
}

#[expect(
clippy::module_name_repetitions,
reason = "for parity with the Protobuf spec"
Expand Down
Loading