Skip to content
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

feat(sequencer)!: transaction categories on UnsignedTransaction #1512

Merged
merged 22 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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 @@ -154,13 +154,14 @@ impl Submitter {
.wrap_err("failed to get nonce from sequencer")?;
debug!(nonce, "fetched latest nonce");

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

// sign transaction
let signed = unsigned.into_signed(signer.signing_key());
Expand Down
9 changes: 5 additions & 4 deletions crates/astria-cli/src/commands/bridge/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,14 @@ async fn submit_transaction(
.await
.wrap_err("failed to get nonce")?;

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

let tx = UnsignedTransaction {
params: TransactionParams::builder()
let tx = UnsignedTransaction::new(
vec![action],
TransactionParams::builder()
.nonce(nonce_res.nonce)
.chain_id(chain_id)
.build(),
actions: vec![action],
}
)
.wrap_err("failed to build transaction from actions")?
.into_signed(&sequencer_key);
let res = sequencer_client
.submit_transaction_sync(tx)
Expand Down
9 changes: 9 additions & 0 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,8 @@ use astria_core::{
protocol::transaction::v1alpha1::{
action::SequenceAction,
Action,
TransactionParams,
UnsignedTransaction,
},
Protobuf as _,
};
Expand Down Expand Up @@ -74,6 +76,12 @@ impl SizedBundle {
}
}

#[allow(clippy::panic)] // method is expected to never panic as an invariant of the type
/// Constructs an [`UnsignedTransaction`] from the actions contained in the bundle and `params`.
pub(super) fn to_unsigned_transaction(&self, params: TransactionParams) -> UnsignedTransaction {
UnsignedTransaction::new(self.buffer.clone(), params).unwrap()
}

/// Buffer `seq_action` into the bundle.
/// # Errors
/// - `seq_action` is beyond the max size allowed for the entire bundle
Expand Down Expand Up @@ -112,6 +120,7 @@ impl SizedBundle {
}

/// Consume self and return the underlying buffer of actions.
#[cfg(test)]
pub(super) fn into_actions(self) -> Vec<Action> {
self.buffer
}
Expand Down
25 changes: 25 additions & 0 deletions crates/astria-composer/src/executor/bundle_factory/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ mod sized_bundle {

#[cfg(test)]
mod bundle_factory {
use astria_core::protocol::transaction::v1alpha1::TransactionParams;

use super::*;
use crate::{
executor::bundle_factory::{
Expand Down Expand Up @@ -333,4 +335,27 @@ mod bundle_factory {
assert_eq!(bundle_factory.finished.len(), 0);
assert!(!bundle_factory.is_full());
}

#[test]
fn unsigned_transaction_construction() {
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();

let bundle = bundle_factory.pop_now();

let transaction_params = TransactionParams::builder()
.chain_id("astria-testnet-1".to_string())
.build();

// construction of multiple sequence actions should not panic
let unsigned_tx = bundle.to_unsigned_transaction(transaction_params);

assert_eq!(unsigned_tx.actions().len(), 2);
}
}
19 changes: 8 additions & 11 deletions crates/astria-composer/src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use astria_core::{
action::SequenceAction,
SignedTransaction,
TransactionParams,
UnsignedTransaction,
},
},
};
Expand Down Expand Up @@ -681,11 +680,10 @@ impl Future for SubmitFut {
.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(params)
.into_signed(this.signing_key);
info!(
nonce.actual = *this.nonce,
bundle = %telemetry::display::json(&SizedBundleReport(this.bundle)),
Expand Down Expand Up @@ -759,11 +757,10 @@ impl Future for SubmitFut {
.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(params)
.into_signed(this.signing_key);
info!(
nonce.resubmission = *this.nonce,
bundle = %telemetry::display::json(&SizedBundleReport(this.bundle)),
Expand Down
10 changes: 6 additions & 4 deletions crates/astria-core/src/protocol/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,18 @@ impl ConfigureSequencerBlock {
let txs = if actions.is_empty() {
vec![]
} else {
let unsigned_transaction = UnsignedTransaction {
let unsigned_transaction = UnsignedTransaction::new(
actions,
params: TransactionParams::builder()
TransactionParams::builder()
.nonce(1)
.chain_id(chain_id.clone())
.build(),
};
)
.expect(
"failed to build unsigned transaction, should be okay since only sequence actions",
);
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
32 changes: 32 additions & 0 deletions crates/astria-core/src/protocol/transaction/v1alpha1/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ impl Action {
};
Some(transfer_action)
}

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

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 @@ -252,6 +260,30 @@ impl TryFrom<raw::Action> for Action {
}
}

pub(super) trait ActionName {
Copy link
Member

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
Member

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::Ics20Withdrawal(_) => "Ics20Withdrawal",
Action::IbcRelayerChange(_) => "IbcRelayerChange",
Action::FeeAssetChange(_) => "FeeAssetChange",
Action::InitBridgeAccount(_) => "InitBridgeAccount",
Action::BridgeLock(_) => "BridgeLock",
Action::BridgeUnlock(_) => "BridgeUnlock",
Action::BridgeSudoChange(_) => "BridgeSudoChange",
Action::FeeChange(_) => "FeeChange",
}
}
}

#[allow(clippy::module_name_repetitions)]
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
Expand Down
Loading
Loading