Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cdda4c7

Browse files
committedNov 19, 2024··
Merge branch 'ENG-1006/begin_and_end_block' of https://github.com/astriaorg/astria into ENG-1006/begin_and_end_block
2 parents f8f8f61 + e810996 commit cdda4c7

File tree

11 files changed

+275
-183
lines changed

11 files changed

+275
-183
lines changed
 

‎crates/astria-sequencer/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
## [Unreleased]
1111

12-
## Changed
12+
### Changed
1313

1414
- Index all event attributes [#1786](https://github.com/astriaorg/astria/pull/1786).
15+
- Ensure all deposit assets are trace prefixed [#1807](https://github.com/astriaorg/astria/pull/1807).
1516

1617
## [1.0.0] - 2024-10-25
1718

‎crates/astria-sequencer/src/accounts/component.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@ use astria_eyre::eyre::{
66
Result,
77
WrapErr as _,
88
};
9-
use tendermint::abci::request::{
10-
BeginBlock,
11-
EndBlock,
12-
};
139
use tracing::instrument;
1410

1511
use crate::{
1612
accounts,
1713
assets,
18-
component::Component,
14+
component::{
15+
Component,
16+
PrepareStateInfo,
17+
},
1918
};
2019

2120
#[derive(Default)]
@@ -48,18 +47,17 @@ impl Component for AccountsComponent {
4847
Ok(())
4948
}
5049

51-
#[instrument(name = "AccountsComponent::begin_block", skip_all)]
52-
async fn begin_block<S: accounts::StateWriteExt + 'static>(
50+
#[instrument(name = "AccountsComponent::prepare_state_for_tx_execution", skip_all)]
51+
async fn prepare_state_for_tx_execution<S: accounts::StateWriteExt + 'static>(
5352
_state: &mut Arc<S>,
54-
_begin_block: &BeginBlock,
53+
_prepare_state_for_tx_execution: &PrepareStateInfo,
5554
) -> Result<()> {
5655
Ok(())
5756
}
5857

59-
#[instrument(name = "AccountsComponent::end_block", skip_all)]
60-
async fn end_block<S: accounts::StateWriteExt + 'static>(
58+
#[instrument(name = "AccountsComponent::handle_post_tx_execution", skip_all)]
59+
async fn handle_post_tx_execution<S: accounts::StateWriteExt + 'static>(
6160
_state: &mut Arc<S>,
62-
_end_block: &EndBlock,
6361
) -> Result<()> {
6462
Ok(())
6563
}

‎crates/astria-sequencer/src/app/mod.rs

+54-82
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ use tendermint::{
7373
Event,
7474
},
7575
account,
76-
block::Header,
7776
AppHash,
7877
Hash,
7978
};
@@ -109,7 +108,10 @@ use crate::{
109108
StateReadExt as _,
110109
StateWriteExt as _,
111110
},
112-
component::Component as _,
111+
component::{
112+
Component as _,
113+
PrepareStateInfo,
114+
},
113115
fees::{
114116
component::FeesComponent,
115117
StateReadExt as _,
@@ -207,8 +209,8 @@ pub(crate) struct App {
207209

208210
// This is set to the executed hash of the proposal during `process_proposal`
209211
//
210-
// If it does not match the hash given during `begin_block`, then we clear and
211-
// reset the execution results cache + state delta. Transactions are re-executed.
212+
// If it does not match the hash given during `prepare_state_for_tx_execution`, then we clear
213+
// and reset the execution results cache + state delta. Transactions are re-executed.
212214
// If it does match, we utilize cached results to reduce computation.
213215
//
214216
// Resets to default hash at the beginning of `prepare_proposal`, and `process_proposal` if
@@ -682,7 +684,8 @@ impl App {
682684
}
683685

684686
/// sets up the state for execution of the block's transactions.
685-
/// set the current height and timestamp, and calls `begin_block` on all components.
687+
/// set the current height and timestamp, and calls `prepare_state_for_tx_execution` on all
688+
/// components.
686689
///
687690
/// this *must* be called anytime before a block's txs are executed, whether it's
688691
/// during the proposal phase, or finalize_block phase.
@@ -697,42 +700,19 @@ impl App {
697700
// reset recost flag
698701
self.recost_mempool = false;
699702

700-
// call begin_block on all components
701-
// NOTE: the fields marked `unused` are not used by any of the components;
702-
// however, we need to still construct a `BeginBlock` type for now as
703-
// the penumbra IBC implementation still requires it as a parameter.
704-
let begin_block: abci::request::BeginBlock = abci::request::BeginBlock {
705-
hash: Hash::default(), // unused
706-
byzantine_validators: block_data.misbehavior.clone(),
707-
header: Header {
708-
app_hash: self.app_hash.clone(),
709-
chain_id: chain_id.clone(),
710-
consensus_hash: Hash::default(), // unused
711-
data_hash: Some(Hash::default()), // unused
712-
evidence_hash: Some(Hash::default()), // unused
713-
height: block_data.height,
714-
last_block_id: None, // unused
715-
last_commit_hash: Some(Hash::default()), // unused
716-
last_results_hash: Some(Hash::default()), // unused
717-
next_validators_hash: block_data.next_validators_hash,
718-
proposer_address: block_data.proposer_address,
719-
time: block_data.time,
720-
validators_hash: Hash::default(), // unused
721-
version: tendermint::block::header::Version {
722-
// unused
723-
app: 0,
724-
block: 0,
725-
},
726-
},
727-
last_commit_info: tendermint::abci::types::CommitInfo {
728-
round: 0u16.into(), // unused
729-
votes: vec![],
730-
}, // unused
703+
let prepare_state_info = PrepareStateInfo {
704+
app_hash: self.app_hash.clone(),
705+
byzantine_validators: block_data.misbehavior,
706+
chain_id,
707+
height: block_data.height,
708+
next_validators_hash: block_data.next_validators_hash,
709+
proposer_address: block_data.proposer_address,
710+
time: block_data.time,
731711
};
732712

733-
self.begin_block(&begin_block)
713+
self.start_block(&prepare_state_info)
734714
.await
735-
.wrap_err("begin_block failed")?;
715+
.wrap_err("prepare_state_for_tx_execution failed")?;
736716

737717
Ok(())
738718
}
@@ -766,7 +746,9 @@ impl App {
766746
.await
767747
.wrap_err("failed to get sudo address from state")?;
768748

769-
let end_block = self.end_block(height.value(), &sudo_address).await?;
749+
let (validator_updates, events) = self
750+
.component_post_execution_state_updates(&sudo_address)
751+
.await?;
770752

771753
// get deposits for this block from state's ephemeral cache and put them to storage.
772754
let mut state_tx = StateDelta::new(self.state.clone());
@@ -804,15 +786,14 @@ impl App {
804786
.wrap_err("failed to write sequencer block to state")?;
805787

806788
let result = PostTransactionExecutionResult {
807-
events: end_block.events,
808-
validator_updates: end_block.validator_updates,
809-
consensus_param_updates: end_block.consensus_param_updates,
789+
events,
790+
validator_updates,
810791
tx_results: finalize_block_tx_results,
811792
};
812793

813794
state_tx.object_put(POST_TRANSACTION_EXECUTION_RESULT_KEY, result);
814795

815-
// events that occur after end_block are ignored here;
796+
// events that occur after handle_post_tx_execution are ignored here;
816797
// there should be none anyways.
817798
let _ = self.apply(state_tx);
818799

@@ -931,7 +912,7 @@ impl App {
931912
let finalize_block = abci::response::FinalizeBlock {
932913
events: post_transaction_execution_result.events,
933914
validator_updates: post_transaction_execution_result.validator_updates,
934-
consensus_param_updates: post_transaction_execution_result.consensus_param_updates,
915+
consensus_param_updates: None,
935916
app_hash,
936917
tx_results: post_transaction_execution_result.tx_results,
937918
};
@@ -976,34 +957,34 @@ impl App {
976957
Ok(app_hash)
977958
}
978959

979-
#[instrument(name = "App::begin_block", skip_all)]
980-
async fn begin_block(
960+
#[instrument(name = "App::start_block", skip_all)]
961+
async fn start_block(
981962
&mut self,
982-
begin_block: &abci::request::BeginBlock,
963+
prepare_state_info: &PrepareStateInfo,
983964
) -> Result<Vec<abci::Event>> {
984965
let mut state_tx = StateDelta::new(self.state.clone());
985966

986967
state_tx
987-
.put_block_height(begin_block.header.height.into())
968+
.put_block_height(prepare_state_info.height.into())
988969
.wrap_err("failed to put block height")?;
989970
state_tx
990-
.put_block_timestamp(begin_block.header.time)
971+
.put_block_timestamp(prepare_state_info.time)
991972
.wrap_err("failed to put block timestamp")?;
992973

993-
// call begin_block on all components
974+
// call prepare_state_for_tx_execution on all components
994975
let mut arc_state_tx = Arc::new(state_tx);
995-
AccountsComponent::begin_block(&mut arc_state_tx, begin_block)
976+
AccountsComponent::prepare_state_for_tx_execution(&mut arc_state_tx, prepare_state_info)
996977
.await
997-
.wrap_err("begin_block failed on AccountsComponent")?;
998-
AuthorityComponent::begin_block(&mut arc_state_tx, begin_block)
978+
.wrap_err("prepare_state_for_tx_execution failed on AccountsComponent")?;
979+
AuthorityComponent::prepare_state_for_tx_execution(&mut arc_state_tx, prepare_state_info)
999980
.await
1000-
.wrap_err("begin_block failed on AuthorityComponent")?;
1001-
IbcComponent::begin_block(&mut arc_state_tx, begin_block)
981+
.wrap_err("prepare_state_for_tx_execution failed on AuthorityComponent")?;
982+
IbcComponent::prepare_state_for_tx_execution(&mut arc_state_tx, prepare_state_info)
1002983
.await
1003-
.wrap_err("begin_block failed on IbcComponent")?;
1004-
FeesComponent::begin_block(&mut arc_state_tx, begin_block)
984+
.wrap_err("prepare_state_for_tx_execution failed on IbcComponent")?;
985+
FeesComponent::prepare_state_for_tx_execution(&mut arc_state_tx, prepare_state_info)
1005986
.await
1006-
.wrap_err("begin_block failed on FeesComponent")?;
987+
.wrap_err("prepare_state_for_tx_execution failed on FeesComponent")?;
1007988

1008989
let state_tx = Arc::try_unwrap(arc_state_tx)
1009990
.expect("components should not retain copies of shared state");
@@ -1049,34 +1030,27 @@ impl App {
10491030
Ok(events)
10501031
}
10511032

1052-
#[instrument(name = "App::end_block", skip_all)]
1053-
async fn end_block(
1033+
#[instrument(name = "App::component_post_execution_state_updates", skip_all)]
1034+
async fn component_post_execution_state_updates(
10541035
&mut self,
1055-
height: u64,
10561036
fee_recipient: &[u8; 20],
1057-
) -> Result<abci::response::EndBlock> {
1037+
) -> Result<(Vec<tendermint::validator::Update>, Vec<Event>)> {
10581038
let state_tx = StateDelta::new(self.state.clone());
10591039
let mut arc_state_tx = Arc::new(state_tx);
10601040

1061-
let end_block = abci::request::EndBlock {
1062-
height: height
1063-
.try_into()
1064-
.expect("a block height should be able to fit in an i64"),
1065-
};
1066-
1067-
// call end_block on all components
1068-
AccountsComponent::end_block(&mut arc_state_tx, &end_block)
1041+
// call handle_post_tx_execution on all components
1042+
AccountsComponent::handle_post_tx_execution(&mut arc_state_tx)
10691043
.await
1070-
.wrap_err("end_block failed on AccountsComponent")?;
1071-
AuthorityComponent::end_block(&mut arc_state_tx, &end_block)
1044+
.wrap_err("handle_post_tx_execution failed on AccountsComponent")?;
1045+
AuthorityComponent::handle_post_tx_execution(&mut arc_state_tx)
10721046
.await
1073-
.wrap_err("end_block failed on AuthorityComponent")?;
1074-
FeesComponent::end_block(&mut arc_state_tx, &end_block)
1047+
.wrap_err("handle_post_tx_execution failed on AuthorityComponent")?;
1048+
FeesComponent::handle_post_tx_execution(&mut arc_state_tx)
10751049
.await
1076-
.wrap_err("end_block failed on FeesComponent")?;
1077-
IbcComponent::end_block(&mut arc_state_tx, &end_block)
1050+
.wrap_err("handle_post_tx_execution failed on FeesComponent")?;
1051+
IbcComponent::handle_post_tx_execution(&mut arc_state_tx)
10781052
.await
1079-
.wrap_err("end_block failed on IbcComponent")?;
1053+
.wrap_err("handle_post_tx_execution failed on IbcComponent")?;
10801054

10811055
let mut state_tx = Arc::try_unwrap(arc_state_tx)
10821056
.expect("components should not retain copies of shared state");
@@ -1102,13 +1076,12 @@ impl App {
11021076
}
11031077

11041078
let events = self.apply(state_tx);
1105-
Ok(abci::response::EndBlock {
1106-
validator_updates: validator_updates
1079+
Ok((
1080+
validator_updates
11071081
.try_into_cometbft()
11081082
.wrap_err("failed converting astria validators to cometbft compatible type")?,
11091083
events,
1110-
..Default::default()
1111-
})
1084+
))
11121085
}
11131086

11141087
#[instrument(name = "App::commit", skip_all)]
@@ -1194,7 +1167,6 @@ struct PostTransactionExecutionResult {
11941167
events: Vec<Event>,
11951168
tx_results: Vec<ExecTxResult>,
11961169
validator_updates: Vec<tendermint::validator::Update>,
1197-
consensus_param_updates: Option<tendermint::consensus::Params>,
11981170
}
11991171

12001172
#[derive(PartialEq)]

‎crates/astria-sequencer/src/app/tests_app/mod.rs

+15-37
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ use tendermint::{
4646
},
4747
account,
4848
block::{
49-
header::Version,
50-
Header,
5149
Height,
5250
Round,
5351
},
@@ -77,28 +75,6 @@ use crate::{
7775
proposal::commitment::generate_rollup_datas_commitment,
7876
};
7977

80-
fn default_tendermint_header() -> Header {
81-
Header {
82-
app_hash: AppHash::try_from(vec![]).unwrap(),
83-
chain_id: "test".to_string().try_into().unwrap(),
84-
consensus_hash: Hash::default(),
85-
data_hash: Some(Hash::try_from([0u8; 32].to_vec()).unwrap()),
86-
evidence_hash: Some(Hash::default()),
87-
height: Height::default(),
88-
last_block_id: None,
89-
last_commit_hash: Some(Hash::default()),
90-
last_results_hash: Some(Hash::default()),
91-
next_validators_hash: Hash::default(),
92-
proposer_address: account::Id::try_from([0u8; 20].to_vec()).unwrap(),
93-
time: Time::now(),
94-
validators_hash: Hash::default(),
95-
version: Version {
96-
app: 0,
97-
block: 0,
98-
},
99-
}
100-
}
101-
10278
#[tokio::test]
10379
async fn app_genesis_and_init_chain() {
10480
let app = initialize_app(None, vec![]).await;
@@ -147,7 +123,7 @@ async fn app_pre_execute_transactions() {
147123
}
148124

149125
#[tokio::test]
150-
async fn app_begin_block_remove_byzantine_validators() {
126+
async fn app_prepare_state_for_tx_execution_remove_byzantine_validators() {
151127
use tendermint::abci::types;
152128

153129
let initial_validator_set = vec![
@@ -174,18 +150,17 @@ async fn app_begin_block_remove_byzantine_validators() {
174150
total_voting_power: 101u32.into(),
175151
};
176152

177-
let mut begin_block = abci::request::BeginBlock {
178-
header: default_tendermint_header(),
179-
hash: Hash::default(),
180-
last_commit_info: CommitInfo {
181-
votes: vec![],
182-
round: Round::default(),
183-
},
153+
let prepare_state_info = PrepareStateInfo {
154+
app_hash: AppHash::try_from(vec![]).unwrap(),
184155
byzantine_validators: vec![misbehavior],
156+
chain_id: "test".to_string().try_into().unwrap(),
157+
height: 1u8.into(),
158+
next_validators_hash: Hash::default(),
159+
proposer_address: account::Id::try_from([0u8; 20].to_vec()).unwrap(),
160+
time: Time::now(),
185161
};
186-
begin_block.header.height = 1u8.into();
187162

188-
app.begin_block(&begin_block).await.unwrap();
163+
app.start_block(&prepare_state_info).await.unwrap();
189164

190165
// assert that validator with pubkey_a is removed
191166
let validator_set = app.state.get_validator_set().await.unwrap();
@@ -876,7 +851,7 @@ async fn app_process_proposal_transaction_fails_to_execute_fails() {
876851
}
877852

878853
#[tokio::test]
879-
async fn app_end_block_validator_updates() {
854+
async fn app_handle_post_tx_execution_validator_updates() {
880855
let initial_validator_set = vec![
881856
ValidatorUpdate {
882857
power: 100,
@@ -912,10 +887,13 @@ async fn app_end_block_validator_updates() {
912887
.unwrap();
913888
app.apply(state_tx);
914889

915-
let resp = app.end_block(1, &proposer_address).await.unwrap();
890+
let (validator_updates, _) = app
891+
.component_post_execution_state_updates(&proposer_address)
892+
.await
893+
.unwrap();
916894
// we only assert length here as the ordering of the updates is not guaranteed
917895
// and validator::Update does not implement Ord
918-
assert_eq!(resp.validator_updates.len(), validator_updates.len());
896+
assert_eq!(validator_updates.len(), validator_updates.len());
919897

920898
// validator with pubkey_a should be removed (power set to 0)
921899
// validator with pubkey_b should be updated

‎crates/astria-sequencer/src/app/tests_breaking_changes.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ async fn app_execute_transaction_with_every_action_snapshot() {
346346
app.execute_transaction(signed_tx).await.unwrap();
347347

348348
let sudo_address = app.state.get_sudo_address().await.unwrap();
349-
app.end_block(1, &sudo_address).await.unwrap();
349+
app.component_post_execution_state_updates(&sudo_address)
350+
.await
351+
.unwrap();
350352

351353
app.prepare_commit(storage.clone()).await.unwrap();
352354
app.commit(storage.clone()).await;

‎crates/astria-sequencer/src/authority/action.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl ActionHandler for ValidatorUpdate {
5858
ensure!(validator_set.len() != 1, "cannot remove the last validator");
5959
}
6060

61-
// add validator update in non-consensus state to be used in end_block
61+
// add validator update in non-consensus state to be used in handle_post_tx_execution
6262
let mut validator_updates = state
6363
.get_validator_updates()
6464
.await

‎crates/astria-sequencer/src/authority/component.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@ use astria_eyre::eyre::{
99
Result,
1010
WrapErr as _,
1111
};
12-
use tendermint::abci::request::{
13-
BeginBlock,
14-
EndBlock,
15-
};
1612
use tracing::instrument;
1713

1814
use super::{
1915
StateReadExt,
2016
StateWriteExt,
2117
ValidatorSet,
2218
};
23-
use crate::component::Component;
19+
use crate::component::{
20+
Component,
21+
PrepareStateInfo,
22+
};
2423

2524
#[derive(Default)]
2625
pub(crate) struct AuthorityComponent;
@@ -48,17 +47,17 @@ impl Component for AuthorityComponent {
4847
Ok(())
4948
}
5049

51-
#[instrument(name = "AuthorityComponent::begin_block", skip_all)]
52-
async fn begin_block<S: StateWriteExt + 'static>(
50+
#[instrument(name = "AuthorityComponent::prepare_state_for_tx_execution", skip_all)]
51+
async fn prepare_state_for_tx_execution<S: StateWriteExt + 'static>(
5352
state: &mut Arc<S>,
54-
begin_block: &BeginBlock,
53+
prepare_state_for_tx_execution: &PrepareStateInfo,
5554
) -> Result<()> {
5655
let mut current_set = state
5756
.get_validator_set()
5857
.await
5958
.wrap_err("failed getting validator set")?;
6059

61-
for misbehaviour in &begin_block.byzantine_validators {
60+
for misbehaviour in &prepare_state_for_tx_execution.byzantine_validators {
6261
current_set.remove(&misbehaviour.validator.address);
6362
}
6463

@@ -70,10 +69,9 @@ impl Component for AuthorityComponent {
7069
Ok(())
7170
}
7271

73-
#[instrument(name = "AuthorityComponent::end_block", skip_all)]
74-
async fn end_block<S: StateWriteExt + StateReadExt + 'static>(
72+
#[instrument(name = "AuthorityComponent::handle_post_tx_execution", skip_all)]
73+
async fn handle_post_tx_execution<S: StateWriteExt + StateReadExt + 'static>(
7574
state: &mut Arc<S>,
76-
_end_block: &EndBlock,
7775
) -> Result<()> {
7876
// update validator set
7977
let validator_updates = state

‎crates/astria-sequencer/src/bridge/bridge_lock_action.rs

+101-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
},
2121
address::StateReadExt as _,
2222
app::ActionHandler,
23+
assets::StateReadExt as _,
2324
bridge::{
2425
StateReadExt as _,
2526
StateWriteExt as _,
@@ -68,11 +69,21 @@ impl ActionHandler for BridgeLock {
6869
.expect("current source should be set before executing action")
6970
.source_action_index;
7071

72+
// map asset to trace prefixed asset for deposit, if it is not already
73+
let deposit_asset = match self.asset.as_trace_prefixed() {
74+
Some(asset) => asset.clone(),
75+
None => state
76+
.map_ibc_to_trace_prefixed_asset(&allowed_asset)
77+
.await
78+
.wrap_err("failed to map IBC asset to trace prefixed asset")?
79+
.ok_or_eyre("mapping from IBC prefixed bridge asset to trace prefixed not found")?,
80+
};
81+
7182
let deposit = Deposit {
7283
bridge_address: self.to,
7384
rollup_id,
7485
amount: self.amount,
75-
asset: self.asset.clone(),
86+
asset: deposit_asset.into(),
7687
destination_chain_address: self.destination_chain_address.clone(),
7788
source_transaction_id,
7889
source_action_index,
@@ -94,3 +105,92 @@ impl ActionHandler for BridgeLock {
94105
Ok(())
95106
}
96107
}
108+
109+
#[cfg(test)]
110+
mod tests {
111+
use astria_core::{
112+
primitive::v1::{
113+
asset,
114+
TransactionId,
115+
},
116+
protocol::transaction::v1::action::BridgeLock,
117+
};
118+
use cnidarium::StateDelta;
119+
120+
use crate::{
121+
accounts::{
122+
AddressBytes,
123+
StateWriteExt as _,
124+
},
125+
address::StateWriteExt as _,
126+
app::ActionHandler as _,
127+
assets::StateWriteExt as _,
128+
benchmark_and_test_utils::{
129+
astria_address,
130+
nria,
131+
ASTRIA_PREFIX,
132+
},
133+
bridge::{
134+
StateReadExt,
135+
StateWriteExt as _,
136+
},
137+
transaction::{
138+
StateWriteExt as _,
139+
TransactionContext,
140+
},
141+
};
142+
143+
#[tokio::test]
144+
async fn bridge_lock_maps_ibc_to_trace_prefixed_for_deposit() {
145+
let storage = cnidarium::TempStorage::new().await.unwrap();
146+
let snapshot = storage.latest_snapshot();
147+
let mut state = StateDelta::new(snapshot);
148+
149+
let trace_asset = "trace_asset"
150+
.parse::<asset::denom::TracePrefixed>()
151+
.unwrap();
152+
let ibc_asset = trace_asset.to_ibc_prefixed();
153+
let transfer_amount = 100;
154+
let bridge_address = astria_address(&[3; 20]);
155+
let from_address = astria_address(&[1; 20]);
156+
157+
state.put_transaction_context(TransactionContext {
158+
address_bytes: *from_address.address_bytes(),
159+
transaction_id: TransactionId::new([0; 32]),
160+
source_action_index: 0,
161+
});
162+
state.put_base_prefix(ASTRIA_PREFIX.to_string()).unwrap();
163+
state
164+
.put_bridge_account_rollup_id(&bridge_address, [0; 32].into())
165+
.unwrap();
166+
state
167+
.put_bridge_account_ibc_asset(&bridge_address, ibc_asset)
168+
.unwrap();
169+
state.put_ibc_asset(trace_asset.clone()).unwrap();
170+
state
171+
.put_account_balance(&from_address, &trace_asset, transfer_amount)
172+
.unwrap();
173+
174+
let bridge_lock_action = BridgeLock {
175+
to: bridge_address,
176+
amount: transfer_amount,
177+
asset: ibc_asset.into(),
178+
fee_asset: nria().into(),
179+
destination_chain_address: "ethan_was_here".to_string(),
180+
};
181+
182+
bridge_lock_action
183+
.check_and_execute(&mut state)
184+
.await
185+
.unwrap();
186+
187+
let deposits = state
188+
.get_cached_block_deposits()
189+
.values()
190+
.next()
191+
.unwrap()
192+
.clone();
193+
assert_eq!(deposits.len(), 1);
194+
assert!(deposits[0].asset.as_trace_prefixed().is_some());
195+
}
196+
}

‎crates/astria-sequencer/src/component.rs

+26-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,25 @@ use std::sync::Arc;
33
use astria_eyre::eyre::Result;
44
use async_trait::async_trait;
55
use cnidarium::StateWrite;
6-
use tendermint::abci;
6+
use tendermint::{
7+
abci::types,
8+
account,
9+
block,
10+
chain,
11+
AppHash,
12+
Hash,
13+
Time,
14+
};
15+
16+
pub(crate) struct PrepareStateInfo {
17+
pub(crate) app_hash: AppHash,
18+
pub(crate) byzantine_validators: Vec<types::Misbehavior>,
19+
pub(crate) chain_id: chain::Id,
20+
pub(crate) height: block::Height,
21+
pub(crate) next_validators_hash: Hash,
22+
pub(crate) proposer_address: account::Id,
23+
pub(crate) time: Time,
24+
}
725

826
/// A component of the Sequencer application.
927
/// Based off Penumbra's [`Component`], but with modifications.
@@ -20,8 +38,7 @@ pub(crate) trait Component {
2038
/// be empty.
2139
async fn init_chain<S: StateWrite>(state: S, app_state: &Self::AppState) -> Result<()>;
2240

23-
/// Begins a new block, optionally inspecting the ABCI
24-
/// [`BeginBlock`](abci::request::BeginBlock) request.
41+
/// Makes necessary state changes for the given component at the start of the block.
2542
///
2643
/// # Invariants
2744
///
@@ -30,27 +47,23 @@ pub(crate) trait Component {
3047
/// called, `state.get_mut().is_some()`, i.e., the `Arc` is not shared. The
3148
/// implementor MUST ensure that any clones of the `Arc` are dropped before
3249
/// it returns, so that `state.get_mut().is_some()` on completion.
33-
async fn begin_block<S: StateWrite + 'static>(
50+
async fn prepare_state_for_tx_execution<S: StateWrite + 'static>(
3451
state: &mut Arc<S>,
35-
begin_block: &abci::request::BeginBlock,
52+
prepare_state_for_tx_execution: &PrepareStateInfo,
3653
) -> Result<()>;
3754

38-
/// Ends the block, optionally inspecting the ABCI
39-
/// [`EndBlock`](abci::request::EndBlock) request, and performing any batch
40-
/// processing.
55+
/// Handles necessary state changes for the given component after transaction execution, ending
56+
/// the block.
4157
///
4258
/// # Invariants
4359
///
44-
/// This method should only be called after [`Component::begin_block`].
60+
/// This method should only be called after [`Component::prepare_state_for_tx_execution`].
4561
/// No methods should be called following this method.
4662
///
4763
/// The `&mut Arc<S>` allows the implementor to optionally share state with
4864
/// its subtasks. The implementor SHOULD assume that when the method is
4965
/// called, `state.get_mut().is_some()`, i.e., the `Arc` is not shared. The
5066
/// implementor MUST ensure that any clones of the `Arc` are dropped before
5167
/// it returns, so that `state.get_mut().is_some()` on completion.
52-
async fn end_block<S: StateWrite + 'static>(
53-
state: &mut Arc<S>,
54-
end_block: &abci::request::EndBlock,
55-
) -> Result<()>;
68+
async fn handle_post_tx_execution<S: StateWrite + 'static>(state: &mut Arc<S>) -> Result<()>;
5669
}

‎crates/astria-sequencer/src/fees/component.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@ use astria_eyre::eyre::{
55
Result,
66
WrapErr as _,
77
};
8-
use tendermint::abci::request::{
9-
BeginBlock,
10-
EndBlock,
11-
};
128
use tracing::instrument;
139

1410
use crate::{
15-
component::Component,
11+
component::{
12+
Component,
13+
PrepareStateInfo,
14+
},
1615
fees,
1716
};
1817

@@ -133,18 +132,17 @@ impl Component for FeesComponent {
133132
Ok(())
134133
}
135134

136-
#[instrument(name = "FeesComponent::begin_block", skip_all)]
137-
async fn begin_block<S: fees::StateWriteExt + 'static>(
135+
#[instrument(name = "FeesComponent::prepare_state_for_tx_execution", skip_all)]
136+
async fn prepare_state_for_tx_execution<S: fees::StateWriteExt + 'static>(
138137
_state: &mut Arc<S>,
139-
_begin_block: &BeginBlock,
138+
_prepare_state_for_tx_execution: &PrepareStateInfo,
140139
) -> Result<()> {
141140
Ok(())
142141
}
143142

144-
#[instrument(name = "FeesComponent::end_block", skip_all)]
145-
async fn end_block<S: fees::StateWriteExt + 'static>(
143+
#[instrument(name = "FeesComponent::handle_post_tx_execution", skip_all)]
144+
async fn handle_post_tx_execution<S: fees::StateWriteExt + 'static>(
146145
_state: &mut Arc<S>,
147-
_end_block: &EndBlock,
148146
) -> Result<()> {
149147
Ok(())
150148
}

‎crates/astria-sequencer/src/ibc/component.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,20 @@ use penumbra_ibc::{
99
component::Ibc,
1010
genesis::Content,
1111
};
12-
use tendermint::abci::request::{
13-
BeginBlock,
14-
EndBlock,
12+
use tendermint::{
13+
abci::{
14+
self,
15+
},
16+
block::Header,
17+
Hash,
1518
};
1619
use tracing::instrument;
1720

1821
use crate::{
19-
component::Component,
22+
component::{
23+
Component,
24+
PrepareStateInfo,
25+
},
2026
ibc::{
2127
host_interface::AstriaHost,
2228
state_ext::StateWriteExt,
@@ -53,21 +59,47 @@ impl Component for IbcComponent {
5359
Ok(())
5460
}
5561

56-
#[instrument(name = "IbcComponent::begin_block", skip_all)]
57-
async fn begin_block<S: StateWriteExt + 'static>(
62+
#[instrument(name = "IbcComponent::prepare_state_for_tx_execution", skip_all)]
63+
async fn prepare_state_for_tx_execution<S: StateWriteExt + 'static>(
5864
state: &mut Arc<S>,
59-
begin_block: &BeginBlock,
65+
prepare_state_info: &PrepareStateInfo,
6066
) -> Result<()> {
61-
Ibc::begin_block::<AstriaHost, S>(state, begin_block).await;
67+
let begin_block: abci::request::BeginBlock = abci::request::BeginBlock {
68+
hash: Hash::default(),
69+
byzantine_validators: prepare_state_info.byzantine_validators.clone(),
70+
header: Header {
71+
app_hash: prepare_state_info.app_hash.clone(),
72+
chain_id: prepare_state_info.chain_id.clone(),
73+
consensus_hash: Hash::default(),
74+
data_hash: Some(Hash::default()),
75+
evidence_hash: Some(Hash::default()),
76+
height: prepare_state_info.height,
77+
last_block_id: None,
78+
last_commit_hash: Some(Hash::default()),
79+
last_results_hash: Some(Hash::default()),
80+
next_validators_hash: prepare_state_info.next_validators_hash,
81+
proposer_address: prepare_state_info.proposer_address,
82+
time: prepare_state_info.time,
83+
validators_hash: Hash::default(),
84+
version: tendermint::block::header::Version {
85+
app: 0,
86+
block: 0,
87+
},
88+
},
89+
last_commit_info: tendermint::abci::types::CommitInfo {
90+
round: 0u16.into(),
91+
votes: vec![],
92+
},
93+
};
94+
Ibc::begin_block::<AstriaHost, S>(state, &begin_block).await;
6295
Ok(())
6396
}
6497

65-
#[instrument(name = "IbcComponent::end_block", skip_all)]
66-
async fn end_block<S: StateWriteExt + 'static>(
67-
state: &mut Arc<S>,
68-
end_block: &EndBlock,
98+
#[instrument(name = "IbcComponent::handle_post_tx_execution", skip_all)]
99+
async fn handle_post_tx_execution<S: StateWriteExt + 'static>(
100+
_state: &mut Arc<S>,
69101
) -> Result<()> {
70-
Ibc::end_block(state, end_block).await;
102+
// There is no need to call `Ibc::end_block`. It is a no-op.
71103
Ok(())
72104
}
73105
}

0 commit comments

Comments
 (0)
Please sign in to comment.