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 e267d1c

Browse files
committedSep 26, 2024··
Merge branch 'main' into ENG-819/allow_to_expect
2 parents 4c47878 + 33dae42 commit e267d1c

20 files changed

+631
-860
lines changed
 

‎crates/astria-conductor/tests/blackbox/helpers/macros.rs

+60-16
Original file line numberDiff line numberDiff line change
@@ -115,20 +115,36 @@ macro_rules! mount_celestia_blobs {
115115
celestia_height: $celestia_height:expr,
116116
sequencer_heights: [ $($sequencer_height:expr),+ ]
117117
$(,)?
118+
) => {
119+
mount_celestia_blobs!(
120+
$test_env,
121+
celestia_height: $celestia_height,
122+
sequencer_heights: [ $($sequencer_height),+ ],
123+
delay: None,
124+
)
125+
};
126+
(
127+
$test_env:ident,
128+
celestia_height: $celestia_height:expr,
129+
sequencer_heights: [ $($sequencer_height:expr),+ ],
130+
delay: $delay:expr
131+
$(,)?
118132
) => {{
119133
let blobs = $crate::helpers::make_blobs(&[ $( $sequencer_height ),+ ]);
120134
$test_env
121135
.mount_celestia_blob_get_all(
122136
$celestia_height,
123137
$crate::sequencer_namespace(),
124138
vec![blobs.header],
139+
$delay,
125140
)
126141
.await;
127142
$test_env
128143
.mount_celestia_blob_get_all(
129144
$celestia_height,
130145
$crate::rollup_namespace(),
131146
vec![blobs.rollup],
147+
$delay,
132148
)
133149
.await
134150
}};
@@ -177,13 +193,47 @@ macro_rules! mount_get_commitment_state {
177193

178194
#[macro_export]
179195
macro_rules! mount_update_commitment_state {
196+
(
197+
$test_env:ident,
198+
firm: ( number: $firm_number:expr, hash: $firm_hash:expr, parent: $firm_parent:expr$(,)? ),
199+
soft: ( number: $soft_number:expr, hash: $soft_hash:expr, parent: $soft_parent:expr$(,)? ),
200+
base_celestia_height: $base_celestia_height:expr
201+
$(,)?
202+
) => {
203+
mount_update_commitment_state!(
204+
$test_env,
205+
mock_name: None,
206+
firm: ( number: $firm_number, hash: $firm_hash, parent: $firm_parent, ),
207+
soft: ( number: $soft_number, hash: $soft_hash, parent: $soft_parent, ),
208+
base_celestia_height: $base_celestia_height,
209+
expected_calls: 1,
210+
)
211+
};
180212
(
181213
$test_env:ident,
182214
mock_name: $mock_name:expr,
183215
firm: ( number: $firm_number:expr, hash: $firm_hash:expr, parent: $firm_parent:expr$(,)? ),
184216
soft: ( number: $soft_number:expr, hash: $soft_hash:expr, parent: $soft_parent:expr$(,)? ),
185217
base_celestia_height: $base_celestia_height:expr
186218
$(,)?
219+
) => {
220+
mount_update_commitment_state!(
221+
$test_env,
222+
mock_name: $mock_name,
223+
firm: ( number: $firm_number, hash: $firm_hash, parent: $firm_parent, ),
224+
soft: ( number: $soft_number, hash: $soft_hash, parent: $soft_parent, ),
225+
base_celestia_height: $base_celestia_height,
226+
expected_calls: 1,
227+
)
228+
};
229+
(
230+
$test_env:ident,
231+
mock_name: $mock_name:expr,
232+
firm: ( number: $firm_number:expr, hash: $firm_hash:expr, parent: $firm_parent:expr$(,)? ),
233+
soft: ( number: $soft_number:expr, hash: $soft_hash:expr, parent: $soft_parent:expr$(,)? ),
234+
base_celestia_height: $base_celestia_height:expr,
235+
expected_calls: $expected_calls:expr
236+
$(,)?
187237
) => {
188238
$test_env
189239
.mount_update_commitment_state(
@@ -201,24 +251,10 @@ macro_rules! mount_update_commitment_state {
201251
),
202252
base_celestia_height: $base_celestia_height,
203253
),
254+
$expected_calls,
204255
)
205256
.await
206257
};
207-
(
208-
$test_env:ident,
209-
firm: ( number: $firm_number:expr, hash: $firm_hash:expr, parent: $firm_parent:expr$(,)? ),
210-
soft: ( number: $soft_number:expr, hash: $soft_hash:expr, parent: $soft_parent:expr$(,)? ),
211-
base_celestia_height: $base_celestia_height:expr
212-
$(,)?
213-
) => {
214-
mount_update_commitment_state!(
215-
$test_env,
216-
mock_name: None,
217-
firm: ( number: $firm_number, hash: $firm_hash, parent: $firm_parent, ),
218-
soft: ( number: $soft_number, hash: $soft_hash, parent: $soft_parent, ),
219-
base_celestia_height: $base_celestia_height,
220-
)
221-
};
222258
}
223259

224260
#[macro_export]
@@ -270,17 +306,25 @@ macro_rules! mount_executed_block {
270306

271307
#[macro_export]
272308
macro_rules! mount_get_filtered_sequencer_block {
273-
($test_env:ident, sequencer_height: $height:expr $(,)?) => {
309+
($test_env:ident, sequencer_height: $height:expr, delay: $delay:expr $(,)?) => {
274310
$test_env
275311
.mount_get_filtered_sequencer_block(
276312
::astria_core::generated::sequencerblock::v1alpha1::GetFilteredSequencerBlockRequest {
277313
height: $height,
278314
rollup_ids: vec![$crate::ROLLUP_ID.to_raw()],
279315
},
280316
$crate::filtered_sequencer_block!(sequencer_height: $height),
317+
$delay,
281318
)
282319
.await;
283320
};
321+
($test_env:ident, sequencer_height: $height:expr$(,)?) => {
322+
mount_get_filtered_sequencer_block!(
323+
$test_env,
324+
sequencer_height: $height,
325+
delay: Duration::from_secs(0),
326+
)
327+
};
284328
}
285329

286330
#[macro_export]

‎crates/astria-conductor/tests/blackbox/helpers/mod.rs

+14-29
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ use astria_core::{
1919
},
2020
primitive::v1::RollupId,
2121
};
22-
use astria_grpc_mock::{
23-
response::ResponseResult,
24-
AnyMessage,
25-
Respond,
26-
};
22+
use astria_grpc_mock::response::error_response;
2723
use bytes::Bytes;
2824
use celestia_types::{
2925
nmt::Namespace,
@@ -198,6 +194,7 @@ impl TestConductor {
198194
celestia_height: u64,
199195
namespace: Namespace,
200196
blobs: Vec<Blob>,
197+
delay: Option<Duration>,
201198
) {
202199
use base64::prelude::*;
203200
use wiremock::{
@@ -209,6 +206,7 @@ impl TestConductor {
209206
Request,
210207
ResponseTemplate,
211208
};
209+
let delay = delay.unwrap_or(Duration::from_millis(0));
212210
let namespace_params = BASE64_STANDARD.encode(namespace.as_bytes());
213211
Mock::given(body_partial_json(json!({
214212
"jsonrpc": "2.0",
@@ -222,11 +220,13 @@ impl TestConductor {
222220
.respond_with(move |request: &Request| {
223221
let body: serde_json::Value = serde_json::from_slice(&request.body).unwrap();
224222
let id = body.get("id");
225-
ResponseTemplate::new(200).set_body_json(json!({
226-
"jsonrpc": "2.0",
227-
"id": id,
228-
"result": blobs,
229-
}))
223+
ResponseTemplate::new(200)
224+
.set_body_json(json!({
225+
"jsonrpc": "2.0",
226+
"id": id,
227+
"result": blobs,
228+
}))
229+
.set_delay(delay)
230230
})
231231
.expect(1..)
232232
.mount(&self.mock_http)
@@ -407,6 +407,7 @@ impl TestConductor {
407407
&self,
408408
expected_pbjson: S,
409409
response: FilteredSequencerBlock,
410+
delay: Duration,
410411
) {
411412
use astria_grpc_mock::{
412413
matcher::message_partial_pbjson,
@@ -417,7 +418,7 @@ impl TestConductor {
417418
"get_filtered_sequencer_block",
418419
message_partial_pbjson(&expected_pbjson),
419420
)
420-
.respond_with(constant_response(response))
421+
.respond_with(constant_response(response).set_delay(delay))
421422
.expect(1..)
422423
.mount(&self.mock_grpc.mock_server)
423424
.await;
@@ -427,6 +428,7 @@ impl TestConductor {
427428
&self,
428429
mock_name: Option<&str>,
429430
commitment_state: CommitmentState,
431+
expected_calls: u64,
430432
) -> astria_grpc_mock::MockGuard {
431433
use astria_core::generated::execution::v1alpha2::UpdateCommitmentStateRequest;
432434
use astria_grpc_mock::{
@@ -444,7 +446,7 @@ impl TestConductor {
444446
if let Some(name) = mock_name {
445447
mock = mock.with_name(name);
446448
}
447-
mock.expect(1)
449+
mock.expect(expected_calls)
448450
.mount_as_scoped(&self.mock_grpc.mock_server)
449451
.await
450452
}
@@ -697,20 +699,3 @@ pub fn rollup_namespace() -> Namespace {
697699
pub fn sequencer_namespace() -> Namespace {
698700
astria_core::celestia::namespace_v0_from_sha256_of_bytes(SEQUENCER_CHAIN_ID.as_bytes())
699701
}
700-
701-
pub struct ErrorResponse {
702-
status: tonic::Status,
703-
}
704-
705-
impl Respond for ErrorResponse {
706-
fn respond(&self, _req: &tonic::Request<AnyMessage>) -> ResponseResult {
707-
Err(self.status.clone())
708-
}
709-
}
710-
711-
#[must_use]
712-
pub fn error_response(code: tonic::Code) -> ErrorResponse {
713-
ErrorResponse {
714-
status: tonic::Status::new(code, "error"),
715-
}
716-
}

‎crates/astria-conductor/tests/blackbox/soft_and_firm.rs

+198-17
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,8 @@ use crate::{
3333
/// 4. block information for rollup number 1, sequencer height 2 is reconstructed from Celestia
3434
/// height 1
3535
/// 5. the rollup's firm commitment state is updated (but without executing the block)
36-
///
37-
/// NOTE: there is a potential race condition in this test in that the information could be first
38-
/// retrieved from Celestia before Sequencer and executed against the rollup. In that case step 3.
39-
/// would be skipped (no soft commitment update).
4036
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
41-
async fn simple() {
37+
async fn executes_soft_first_then_updates_firm() {
4238
let test_conductor = spawn_conductor(CommitLevel::SoftAndFirm).await;
4339

4440
mount_get_genesis_info!(
@@ -74,10 +70,51 @@ async fn simple() {
7470
height: 1u32,
7571
);
7672

73+
mount_get_filtered_sequencer_block!(
74+
test_conductor,
75+
sequencer_height: 3,
76+
);
77+
78+
let execute_block = mount_executed_block!(
79+
test_conductor,
80+
number: 2,
81+
hash: [2; 64],
82+
parent: [1; 64],
83+
);
84+
85+
let update_commitment_state_soft = mount_update_commitment_state!(
86+
test_conductor,
87+
firm: (
88+
number: 1,
89+
hash: [1; 64],
90+
parent: [0; 64],
91+
),
92+
soft: (
93+
number: 2,
94+
hash: [2; 64],
95+
parent: [1; 64],
96+
),
97+
base_celestia_height: 1,
98+
);
99+
100+
timeout(
101+
Duration::from_millis(500),
102+
join(
103+
execute_block.wait_until_satisfied(),
104+
update_commitment_state_soft.wait_until_satisfied(),
105+
),
106+
)
107+
.await
108+
.expect(
109+
"Conductor should have executed the block and updated the soft commitment state within \
110+
500ms",
111+
);
112+
77113
mount_celestia_blobs!(
78114
test_conductor,
79115
celestia_height: 1,
80116
sequencer_heights: [3],
117+
delay: Some(Duration::from_millis(500))
81118
);
82119

83120
mount_sequencer_commit!(
@@ -87,20 +124,144 @@ async fn simple() {
87124

88125
mount_sequencer_validator_set!(test_conductor, height: 2u32);
89126

90-
mount_get_filtered_sequencer_block!(
127+
let update_commitment_state_firm = mount_update_commitment_state!(
91128
test_conductor,
92-
sequencer_height: 3,
129+
firm: (
130+
number: 2,
131+
hash: [2; 64],
132+
parent: [1; 64],
133+
),
134+
soft: (
135+
number: 2,
136+
hash: [2; 64],
137+
parent: [1; 64],
138+
),
139+
base_celestia_height: 1,
140+
);
141+
142+
timeout(
143+
Duration::from_millis(1000),
144+
update_commitment_state_firm.wait_until_satisfied(),
145+
)
146+
.await
147+
.expect("conductor should have updated the firm commitment state within 1000ms");
148+
}
149+
150+
/// Tests if a single block is executed and the rollup's state updated after first receiving a firm
151+
/// block, ensuring that update commitment state is not called upon receiving a tardy soft block.
152+
/// Then, ensures the conductor updates the state for the soft block at the next height.
153+
///
154+
/// The following steps occur:
155+
/// 1. Firm and soft blocks at the current height are mounted, the soft block with a 500ms delay to
156+
/// allow for the firm block to be received first.
157+
/// 2. The soft block for the next height is mounted with a 1000ms delay, so that execution and
158+
/// state update of the current height happen before receipt of the next block.
159+
/// 3. Mounts are made for firm and soft update commitment state calls, with the soft mount
160+
/// expecting exactly 0 calls.
161+
/// 4. 1000ms is allotted for the conductor to execute the block and update the firm commitment
162+
/// state, noting that this allows time to test for an erroneously updated soft commitment state
163+
/// before the conductor receives the next block.
164+
/// 5. 2000ms is allotted for the conductor to execute the next block and update the soft commitment
165+
/// state at the next height.
166+
#[expect(
167+
clippy::too_many_lines,
168+
reason = "all mounts and test logic are necessary"
169+
)]
170+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
171+
async fn executes_firm_then_soft_at_next_height() {
172+
let test_conductor = spawn_conductor(CommitLevel::SoftAndFirm).await;
173+
174+
mount_get_genesis_info!(
175+
test_conductor,
176+
sequencer_genesis_block_height: 1,
177+
celestia_block_variance: 10,
178+
);
179+
180+
mount_get_commitment_state!(
181+
test_conductor,
182+
firm: (
183+
number: 1,
184+
hash: [1; 64],
185+
parent: [0; 64],
186+
),
187+
soft: (
188+
number: 1,
189+
hash: [1; 64],
190+
parent: [0; 64],
191+
),
192+
base_celestia_height: 1,
193+
);
194+
195+
mount_abci_info!(
196+
test_conductor,
197+
latest_sequencer_height: 4,
198+
);
199+
200+
mount_sequencer_genesis!(test_conductor);
201+
202+
mount_celestia_header_network_head!(
203+
test_conductor,
204+
height: 1u32,
93205
);
94206

207+
mount_celestia_blobs!(
208+
test_conductor,
209+
celestia_height: 1,
210+
sequencer_heights: [3],
211+
);
212+
213+
mount_sequencer_commit!(
214+
test_conductor,
215+
height: 3u32,
216+
);
217+
218+
mount_sequencer_validator_set!(test_conductor, height: 2u32);
219+
95220
let execute_block = mount_executed_block!(
96221
test_conductor,
97222
number: 2,
98223
hash: [2; 64],
99224
parent: [1; 64],
100225
);
101226

102-
let update_commitment_state_soft = mount_update_commitment_state!(
227+
// Mount soft block at current height with a slight delay
228+
mount_get_filtered_sequencer_block!(
229+
test_conductor,
230+
sequencer_height: 3,
231+
delay: Duration::from_millis(500),
232+
);
233+
234+
// Mount soft block at next height with substantial delay
235+
mount_get_filtered_sequencer_block!(
236+
test_conductor,
237+
sequencer_height: 4,
238+
delay: Duration::from_millis(1000),
239+
);
240+
241+
let update_commitment_state_firm = mount_update_commitment_state!(
103242
test_conductor,
243+
firm: (
244+
number: 2,
245+
hash: [2; 64],
246+
parent: [1; 64],
247+
),
248+
soft: (
249+
number: 2,
250+
hash: [2; 64],
251+
parent: [1; 64],
252+
),
253+
base_celestia_height: 1,
254+
);
255+
256+
// This guard's conditions will be checked when it is dropped, ensuring that there have been 0
257+
// calls to update the commitment state for the stale soft block. This is done instead of
258+
// waiting for the guard to be satisfied because if we call `wait_until_satisfied` on it, it
259+
// will succeed immediately and future erroneous calls will not be checked. It would be most
260+
// ideal to mount this logic directly to the server, but this workaround functions with the
261+
// current setup of the blackbox test helpers.
262+
let _stale_update_soft_commitment_state = mount_update_commitment_state!(
263+
test_conductor,
264+
mock_name: "should_be_ignored_update_commitment_state_soft",
104265
firm: (
105266
number: 1,
106267
hash: [1; 64],
@@ -112,35 +273,55 @@ async fn simple() {
112273
parent: [1; 64],
113274
),
114275
base_celestia_height: 1,
276+
expected_calls: 0,
115277
);
116278

117-
let update_commitment_state_firm = mount_update_commitment_state!(
279+
timeout(
280+
Duration::from_millis(1000),
281+
join(
282+
execute_block.wait_until_satisfied(),
283+
update_commitment_state_firm.wait_until_satisfied(),
284+
),
285+
)
286+
.await
287+
.expect(
288+
"Conductor should have executed the block and updated the firm commitment state within \
289+
1000ms",
290+
);
291+
292+
let execute_block = mount_executed_block!(
293+
test_conductor,
294+
number: 3,
295+
hash: [3; 64],
296+
parent: [2; 64],
297+
);
298+
299+
let update_commitment_state_soft = mount_update_commitment_state!(
118300
test_conductor,
119301
firm: (
120302
number: 2,
121303
hash: [2; 64],
122304
parent: [1; 64],
123305
),
124306
soft: (
125-
number: 2,
126-
hash: [2; 64],
127-
parent: [1; 64],
307+
number: 3,
308+
hash: [3; 64],
309+
parent: [2; 64],
128310
),
129311
base_celestia_height: 1,
130312
);
131313

132314
timeout(
133-
Duration::from_millis(1000),
134-
join3(
315+
Duration::from_millis(2000),
316+
join(
135317
execute_block.wait_until_satisfied(),
136318
update_commitment_state_soft.wait_until_satisfied(),
137-
update_commitment_state_firm.wait_until_satisfied(),
138319
),
139320
)
140321
.await
141322
.expect(
142-
"conductor should have executed the block and updated the soft and firm commitment states \
143-
within 1000ms",
323+
"conductor should have executed the block and updated the soft commitment state within \
324+
2000ms",
144325
);
145326
}
146327

‎crates/astria-grpc-mock/src/mock.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ use std::ops::{
88
RangeToInclusive,
99
};
1010

11-
use super::{
12-
response::Respond,
13-
AnyMessage,
14-
};
11+
use super::AnyMessage;
1512
use crate::{
1613
mock_server::MockGuard,
14+
response::ResponseTemplate,
1715
MockServer,
1816
};
1917

@@ -32,7 +30,7 @@ impl Match for Matcher {
3230
pub struct Mock {
3331
pub(crate) rpc: &'static str,
3432
pub(crate) matchers: Vec<Matcher>,
35-
pub(crate) response: Box<dyn Respond>,
33+
pub(crate) response: ResponseTemplate,
3634
pub(crate) max_n_matches: Option<u64>,
3735
pub(crate) expectation_range: Times,
3836
pub(crate) name: Option<String>,
@@ -86,15 +84,15 @@ impl MockBuilder {
8684
self
8785
}
8886

89-
pub fn respond_with(self, rsp: impl Respond + 'static) -> Mock {
87+
pub fn respond_with(self, rsp: ResponseTemplate) -> Mock {
9088
let Self {
9189
rpc,
9290
matchers,
9391
} = self;
9492
Mock {
9593
rpc,
9694
matchers,
97-
response: Box::new(rsp),
95+
response: rsp,
9896
max_n_matches: None,
9997
name: None,
10098
expectation_range: Times(TimesEnum::Unbounded(RangeFull)),

‎crates/astria-grpc-mock/src/mock_server.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ impl MockServer {
5454
rpc: &'static str,
5555
req: tonic::Request<T>,
5656
) -> tonic::Result<tonic::Response<U>> {
57-
self.state.write().await.handle_request(rpc, req)
57+
let (response, delay) = self.state.write().await.handle_request(rpc, req);
58+
if let Some(delay) = delay {
59+
tokio::time::sleep(delay).await;
60+
}
61+
response
5862
}
5963

6064
pub async fn register(&self, mock: Mock) {
@@ -176,7 +180,10 @@ impl MockServerState {
176180
&mut self,
177181
rpc: &'static str,
178182
req: tonic::Request<T>,
179-
) -> tonic::Result<tonic::Response<U>> {
183+
) -> (
184+
tonic::Result<tonic::Response<U>>,
185+
Option<std::time::Duration>,
186+
) {
180187
if let Some(received_requests) = &mut self.received_requests {
181188
received_requests.push((rpc, erase_request(clone_request(&req)).into()));
182189
}

‎crates/astria-grpc-mock/src/mock_set.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -55,29 +55,34 @@ impl MockSet {
5555
&mut self,
5656
rpc: &'static str,
5757
req: tonic::Request<T>,
58-
) -> tonic::Result<tonic::Response<U>> {
58+
) -> (
59+
tonic::Result<tonic::Response<U>>,
60+
Option<std::time::Duration>,
61+
) {
5962
debug!(rpc, "handling request.");
6063
// perform erasure here so that it's not done in every single `Mock::matches` call.
6164
let erased = erase_request(req);
6265
let mut mock_response: Option<tonic::Result<tonic::Response<U>>> = None;
66+
let mut delay = None;
6367
for (mock, mock_state) in &mut self.mocks {
6468
if let MountedMockState::OutOfScope = mock_state {
6569
continue;
6670
}
6771
match mock.match_and_respond::<U>(rpc, &erased) {
68-
MockResult::NoMatch => continue,
69-
MockResult::BadResponse(status) => {
72+
(MockResult::NoMatch, _) => continue,
73+
(MockResult::BadResponse(status), _) => {
7074
mock_response.replace(Err(status));
7175
break;
7276
}
73-
MockResult::Success(response) => {
77+
(MockResult::Success(response), response_delay) => {
7478
mock_response.replace(response);
79+
delay = response_delay;
7580
break;
7681
}
7782
}
7883
}
7984

80-
mock_response
85+
let result = mock_response
8186
.ok_or_else(|| {
8287
let mut msg = "got unexpected request: ".to_string();
8388
msg.push_str(
@@ -86,7 +91,8 @@ impl MockSet {
8691
);
8792
tonic::Status::not_found(msg)
8893
})
89-
.and_then(std::convert::identity)
94+
.and_then(std::convert::identity);
95+
(result, delay)
9096
}
9197

9298
pub(crate) fn register(&mut self, mock: Mock) -> (Arc<(Notify, AtomicBool)>, MockId) {

‎crates/astria-grpc-mock/src/mounted_mock.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl MountedMock {
111111
&mut self,
112112
rpc: &'static str,
113113
request: &Request<AnyMessage>,
114-
) -> MockResult<U> {
114+
) -> (MockResult<U>, Option<std::time::Duration>) {
115115
let n_matches =
116116
u64::try_from(self.successful_responses.len() + self.bad_responses.len()).ok();
117117
if self.inner.max_n_matches == n_matches
@@ -122,16 +122,18 @@ impl MountedMock {
122122
.iter()
123123
.all(|matcher| matcher.matches(request))
124124
{
125-
return MockResult::NoMatch;
125+
return (MockResult::NoMatch, None);
126126
}
127127

128+
let mut delay = None;
128129
let response = match self.inner.response.respond(request) {
129-
Err(status) => {
130+
(Err(status), _) => {
130131
self.successful_responses
131132
.push((clone_request(request), Err(status.clone())));
132133
Ok(Err(status))
133134
}
134-
Ok(mock_response) => {
135+
(Ok(mock_response), rsp_delay) => {
136+
delay = rsp_delay;
135137
let (metadata, erased_message, extensions) =
136138
clone_response(&mock_response.inner).into_parts();
137139
if let Ok(message) = erased_message.clone_box().into_any().downcast::<U>() {
@@ -173,8 +175,8 @@ impl MountedMock {
173175
self.notify.0.notify_waiters();
174176
}
175177
match response {
176-
Ok(ok) => MockResult::Success(ok),
177-
Err(err) => MockResult::BadResponse(err),
178+
Ok(ok) => (MockResult::Success(ok), delay),
179+
Err(err) => (MockResult::BadResponse(err), None),
178180
}
179181
}
180182

‎crates/astria-grpc-mock/src/response.rs

+69-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::marker::PhantomData;
1+
use std::{
2+
marker::PhantomData,
3+
time::Duration,
4+
};
25

36
use super::{
47
clone_response,
@@ -10,14 +13,17 @@ pub fn constant_response<
1013
T: erased_serde::Serialize + prost::Name + Clone + Default + Send + Sync + 'static,
1114
>(
1215
value: T,
13-
) -> ConstantResponse {
14-
ConstantResponse {
15-
type_name: std::any::type_name::<T>(),
16-
response: erase_response(tonic::Response::new(value)),
16+
) -> ResponseTemplate {
17+
ResponseTemplate {
18+
response: Box::new(ConstantResponse {
19+
type_name: std::any::type_name::<T>(),
20+
response: erase_response(tonic::Response::new(value)),
21+
}),
22+
delay: None,
1723
}
1824
}
1925

20-
pub struct ConstantResponse {
26+
struct ConstantResponse {
2127
type_name: &'static str,
2228
response: tonic::Response<AnyMessage>,
2329
}
@@ -34,37 +40,30 @@ impl Respond for ConstantResponse {
3440
#[must_use]
3541
pub fn default_response<
3642
T: erased_serde::Serialize + prost::Name + Clone + Default + Send + Sync + 'static,
37-
>() -> DefaultResponse {
43+
>() -> ResponseTemplate {
3844
let response = T::default();
39-
DefaultResponse {
40-
type_name: std::any::type_name::<T>(),
41-
response: erase_response(tonic::Response::new(response)),
42-
}
43-
}
44-
45-
pub struct DefaultResponse {
46-
type_name: &'static str,
47-
response: tonic::Response<AnyMessage>,
48-
}
49-
50-
impl Respond for DefaultResponse {
51-
fn respond(&self, _req: &tonic::Request<AnyMessage>) -> ResponseResult {
52-
Ok(MockResponse {
53-
type_name: self.type_name,
54-
inner: clone_response(&self.response),
55-
})
45+
ResponseTemplate {
46+
response: Box::new(ConstantResponse {
47+
type_name: std::any::type_name::<T>(),
48+
response: erase_response(tonic::Response::new(response)),
49+
}),
50+
delay: None,
5651
}
5752
}
5853

59-
pub fn dynamic_response<I, O, F>(responder: F) -> DynamicResponse<I, O, F>
54+
pub fn dynamic_response<I, O, F>(responder: F) -> ResponseTemplate
6055
where
6156
O: erased_serde::Serialize + prost::Name + Clone + 'static,
62-
F: Fn(&I) -> O,
57+
F: Send + Sync + 'static + Fn(&I) -> O,
58+
I: Send + Sync + 'static,
6359
{
64-
DynamicResponse {
65-
type_name: std::any::type_name::<O>(),
66-
responder: Box::new(responder),
67-
_phantom_data: PhantomData,
60+
ResponseTemplate {
61+
response: Box::new(DynamicResponse {
62+
type_name: std::any::type_name::<O>(),
63+
responder: Box::new(responder),
64+
_phantom_data: PhantomData,
65+
}),
66+
delay: None,
6867
}
6968
}
7069

@@ -74,6 +73,26 @@ pub struct DynamicResponse<I, O, F> {
7473
_phantom_data: PhantomData<(I, O)>,
7574
}
7675

76+
struct ErrorResponse {
77+
status: tonic::Status,
78+
}
79+
80+
impl Respond for ErrorResponse {
81+
fn respond(&self, _req: &tonic::Request<AnyMessage>) -> ResponseResult {
82+
Err(self.status.clone())
83+
}
84+
}
85+
86+
#[must_use]
87+
pub fn error_response(code: tonic::Code) -> ResponseTemplate {
88+
ResponseTemplate {
89+
response: Box::new(ErrorResponse {
90+
status: tonic::Status::new(code, "error"),
91+
}),
92+
delay: None,
93+
}
94+
}
95+
7796
impl<I, O, F> Respond for DynamicResponse<I, O, F>
7897
where
7998
I: Send + Sync + 'static,
@@ -119,6 +138,26 @@ impl Clone for MockResponse {
119138
}
120139
}
121140

141+
pub struct ResponseTemplate {
142+
response: Box<dyn Respond>,
143+
delay: Option<Duration>,
144+
}
145+
146+
impl ResponseTemplate {
147+
pub(crate) fn respond(
148+
&self,
149+
req: &tonic::Request<AnyMessage>,
150+
) -> (ResponseResult, Option<Duration>) {
151+
(self.response.respond(req), self.delay)
152+
}
153+
154+
#[must_use]
155+
pub fn set_delay(mut self, delay: Duration) -> Self {
156+
self.delay = Some(delay);
157+
self
158+
}
159+
}
160+
122161
pub trait Respond: Send + Sync {
123162
fn respond(&self, req: &tonic::Request<AnyMessage>) -> ResponseResult;
124163
}

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

+32-31
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,28 @@ use cnidarium::{
3434
use prost::Message;
3535
use tracing::instrument;
3636

37-
fn block_hash_by_height_key(height: u64) -> String {
38-
format!("blockhash/{height}")
37+
fn block_hash_by_height_key(height: u64) -> Vec<u8> {
38+
[b"blockhash/".as_slice(), &height.to_le_bytes()].concat()
3939
}
4040

41-
fn sequencer_block_header_by_hash_key(hash: &[u8]) -> String {
42-
format!("blockheader/{}", crate::utils::Hex(hash))
41+
fn sequencer_block_header_by_hash_key(hash: &[u8]) -> Vec<u8> {
42+
[b"blockheader/", hash].concat()
4343
}
4444

45-
fn rollup_data_by_hash_and_rollup_id_key(hash: &[u8], rollup_id: &RollupId) -> String {
46-
format!("rollupdata/{}/{}", crate::utils::Hex(hash), rollup_id)
45+
fn rollup_data_by_hash_and_rollup_id_key(hash: &[u8], rollup_id: &RollupId) -> Vec<u8> {
46+
[b"rollupdata/", hash, rollup_id.as_ref()].concat()
4747
}
4848

49-
fn rollup_ids_by_hash_key(hash: &[u8]) -> String {
50-
format!("rollupids/{}", crate::utils::Hex(hash))
49+
fn rollup_ids_by_hash_key(hash: &[u8]) -> Vec<u8> {
50+
[b"rollupids/", hash].concat()
5151
}
5252

53-
fn rollup_transactions_proof_by_hash_key(hash: &[u8]) -> String {
54-
format!("rolluptxsproof/{}", crate::utils::Hex(hash))
53+
fn rollup_transactions_proof_by_hash_key(hash: &[u8]) -> Vec<u8> {
54+
[b"rolluptxsproof/", hash].concat()
5555
}
5656

57-
fn rollup_ids_proof_by_hash_key(hash: &[u8]) -> String {
58-
format!("rollupidsproof/{}", crate::utils::Hex(hash))
57+
fn rollup_ids_proof_by_hash_key(hash: &[u8]) -> Vec<u8> {
58+
[b"rollupidsproof/", hash].concat()
5959
}
6060

6161
#[derive(BorshSerialize, BorshDeserialize)]
@@ -139,7 +139,7 @@ pub(crate) trait StateReadExt: StateRead {
139139
async fn get_block_hash_by_height(&self, height: u64) -> Result<[u8; 32]> {
140140
let key = block_hash_by_height_key(height);
141141
let Some(hash) = self
142-
.get_raw(&key)
142+
.nonverifiable_get_raw(&key)
143143
.await
144144
.map_err(anyhow_to_eyre)
145145
.wrap_err("failed to read block hash by height from state")?
@@ -160,7 +160,7 @@ pub(crate) trait StateReadExt: StateRead {
160160
) -> Result<SequencerBlockHeader> {
161161
let key = sequencer_block_header_by_hash_key(hash);
162162
let Some(header_bytes) = self
163-
.get_raw(&key)
163+
.nonverifiable_get_raw(&key)
164164
.await
165165
.map_err(anyhow_to_eyre)
166166
.wrap_err("failed to read raw sequencer block from state")?
@@ -179,7 +179,7 @@ pub(crate) trait StateReadExt: StateRead {
179179
async fn get_rollup_ids_by_block_hash(&self, hash: &[u8]) -> Result<Vec<RollupId>> {
180180
let key = rollup_ids_by_hash_key(hash);
181181
let Some(rollup_ids_bytes) = self
182-
.get_raw(&key)
182+
.nonverifiable_get_raw(&key)
183183
.await
184184
.map_err(anyhow_to_eyre)
185185
.wrap_err("failed to read rollup IDs by block hash from state")?
@@ -195,7 +195,7 @@ pub(crate) trait StateReadExt: StateRead {
195195
#[instrument(skip_all)]
196196
async fn get_sequencer_block_by_hash(&self, hash: &[u8]) -> Result<SequencerBlock> {
197197
let Some(header_bytes) = self
198-
.get_raw(&sequencer_block_header_by_hash_key(hash))
198+
.nonverifiable_get_raw(&sequencer_block_header_by_hash_key(hash))
199199
.await
200200
.map_err(anyhow_to_eyre)
201201
.wrap_err("failed to read raw sequencer block from state")?
@@ -214,10 +214,11 @@ pub(crate) trait StateReadExt: StateRead {
214214
let mut rollup_transactions = Vec::with_capacity(rollup_ids.len());
215215
for id in &rollup_ids {
216216
let key = rollup_data_by_hash_and_rollup_id_key(hash, id);
217-
let raw =
218-
self.get_raw(&key).await.map_err(anyhow_to_eyre).wrap_err(
219-
"failed to read rollup data by block hash and rollup ID from state",
220-
)?;
217+
let raw = self
218+
.nonverifiable_get_raw(&key)
219+
.await
220+
.map_err(anyhow_to_eyre)
221+
.context("failed to read rollup data by block hash and rollup ID from state")?;
221222
if let Some(raw) = raw {
222223
let raw = raw.as_slice();
223224
let rollup_data = raw::RollupTransactions::decode(raw)
@@ -227,7 +228,7 @@ pub(crate) trait StateReadExt: StateRead {
227228
}
228229

229230
let Some(rollup_transactions_proof) = self
230-
.get_raw(&rollup_transactions_proof_by_hash_key(hash))
231+
.nonverifiable_get_raw(&rollup_transactions_proof_by_hash_key(hash))
231232
.await
232233
.map_err(anyhow_to_eyre)
233234
.wrap_err("failed to read rollup transactions proof by block hash from state")?
@@ -240,7 +241,7 @@ pub(crate) trait StateReadExt: StateRead {
240241
.wrap_err("failed to decode rollup transactions proof from raw bytes")?;
241242

242243
let Some(rollup_ids_proof) = self
243-
.get_raw(&rollup_ids_proof_by_hash_key(hash))
244+
.nonverifiable_get_raw(&rollup_ids_proof_by_hash_key(hash))
244245
.await
245246
.map_err(anyhow_to_eyre)
246247
.wrap_err("failed to read rollup IDs proof by block hash from state")?
@@ -284,7 +285,7 @@ pub(crate) trait StateReadExt: StateRead {
284285
) -> Result<RollupTransactions> {
285286
let key = rollup_data_by_hash_and_rollup_id_key(hash, rollup_id);
286287
let Some(bytes) = self
287-
.get_raw(&key)
288+
.nonverifiable_get_raw(&key)
288289
.await
289290
.map_err(anyhow_to_eyre)
290291
.wrap_err("failed to read rollup data by block hash and rollup ID from state")?
@@ -306,7 +307,7 @@ pub(crate) trait StateReadExt: StateRead {
306307
hash: &[u8],
307308
) -> Result<(primitiveRaw::Proof, primitiveRaw::Proof)> {
308309
let Some(rollup_transactions_proof) = self
309-
.get_raw(&rollup_transactions_proof_by_hash_key(hash))
310+
.nonverifiable_get_raw(&rollup_transactions_proof_by_hash_key(hash))
310311
.await
311312
.map_err(anyhow_to_eyre)
312313
.wrap_err("failed to read rollup transactions proof by block hash from state")?
@@ -319,7 +320,7 @@ pub(crate) trait StateReadExt: StateRead {
319320
.wrap_err("failed to decode rollup transactions proof from raw bytes")?;
320321

321322
let Some(rollup_ids_proof) = self
322-
.get_raw(&rollup_ids_proof_by_hash_key(hash))
323+
.nonverifiable_get_raw(&rollup_ids_proof_by_hash_key(hash))
323324
.await
324325
.map_err(anyhow_to_eyre)
325326
.wrap_err("failed to read rollup IDs proof by block hash from state")?
@@ -348,7 +349,7 @@ pub(crate) trait StateWriteExt: StateWrite {
348349
// 6. block hash to rollup IDs proof
349350

350351
let key = block_hash_by_height_key(block.height().into());
351-
self.put_raw(key, block.block_hash().to_vec());
352+
self.nonverifiable_put_raw(key, block.block_hash().to_vec());
352353

353354
let rollup_ids = block
354355
.rollup_transactions()
@@ -359,7 +360,7 @@ pub(crate) trait StateWriteExt: StateWrite {
359360

360361
let key = rollup_ids_by_hash_key(&block.block_hash());
361362

362-
self.put_raw(
363+
self.nonverifiable_put_raw(
363364
key,
364365
borsh::to_vec(&RollupIdSeq(rollup_ids))
365366
.wrap_err("failed to serialize rollup IDs list")?,
@@ -374,18 +375,18 @@ pub(crate) trait StateWriteExt: StateWrite {
374375
rollup_ids_proof,
375376
} = block.into_parts();
376377
let header = header.into_raw();
377-
self.put_raw(key, header.encode_to_vec());
378+
self.nonverifiable_put_raw(key, header.encode_to_vec());
378379

379380
for (id, rollup_data) in rollup_transactions {
380381
let key = rollup_data_by_hash_and_rollup_id_key(&block_hash, &id);
381-
self.put_raw(key, rollup_data.into_raw().encode_to_vec());
382+
self.nonverifiable_put_raw(key, rollup_data.into_raw().encode_to_vec());
382383
}
383384

384385
let key = rollup_transactions_proof_by_hash_key(&block_hash);
385-
self.put_raw(key, rollup_transactions_proof.into_raw().encode_to_vec());
386+
self.nonverifiable_put_raw(key, rollup_transactions_proof.into_raw().encode_to_vec());
386387

387388
let key = rollup_ids_proof_by_hash_key(&block_hash);
388-
self.put_raw(key, rollup_ids_proof.into_raw().encode_to_vec());
389+
self.nonverifiable_put_raw(key, rollup_ids_proof.into_raw().encode_to_vec());
389390

390391
Ok(())
391392
}

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

+9-22
Original file line numberDiff line numberDiff line change
@@ -336,11 +336,7 @@ impl App {
336336
self.metrics
337337
.record_proposal_transactions(signed_txs_included.len());
338338

339-
let deposits = self
340-
.state
341-
.get_block_deposits()
342-
.await
343-
.wrap_err("failed to get block deposits in prepare_proposal")?;
339+
let deposits = self.state.get_cached_block_deposits();
344340
self.metrics.record_proposal_deposits(deposits.len());
345341

346342
// generate commitment to sequence::Actions and deposits and commitment to the rollup IDs
@@ -445,11 +441,7 @@ impl App {
445441
);
446442
self.metrics.record_proposal_transactions(signed_txs.len());
447443

448-
let deposits = self
449-
.state
450-
.get_block_deposits()
451-
.await
452-
.wrap_err("failed to get block deposits in process_proposal")?;
444+
let deposits = self.state.get_cached_block_deposits();
453445
self.metrics.record_proposal_deposits(deposits.len());
454446

455447
let GeneratedCommitments {
@@ -872,21 +864,16 @@ impl App {
872864

873865
let end_block = self.end_block(height.value(), sudo_address).await?;
874866

875-
// get and clear block deposits from state
867+
// get deposits for this block from state's ephemeral cache and put them to storage.
876868
let mut state_tx = StateDelta::new(self.state.clone());
877-
let deposits = self
878-
.state
879-
.get_block_deposits()
880-
.await
881-
.wrap_err("failed to get block deposits in end_block")?;
882-
state_tx
883-
.clear_block_deposits()
884-
.await
885-
.wrap_err("failed to clear block deposits")?;
869+
let deposits_in_this_block = self.state.get_cached_block_deposits();
886870
debug!(
887-
deposits = %telemetry::display::json(&deposits),
871+
deposits = %telemetry::display::json(&deposits_in_this_block),
888872
"got block deposits from state"
889873
);
874+
state_tx
875+
.put_deposits(&block_hash, deposits_in_this_block.clone())
876+
.wrap_err("failed to put deposits to state")?;
890877

891878
let sequencer_block = SequencerBlock::try_from_block_info_and_data(
892879
block_hash,
@@ -899,7 +886,7 @@ impl App {
899886
.into_iter()
900887
.map(std::convert::Into::into)
901888
.collect(),
902-
deposits,
889+
deposits_in_this_block,
903890
)
904891
.wrap_err("failed to convert block info and data to SequencerBlock")?;
905892
state_tx
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
11
---
22
source: crates/astria-sequencer/src/app/tests_breaking_changes.rs
3+
assertion_line: 308
34
expression: app.app_hash.as_bytes()
45
---
56
[
6-
237,
7+
67,
8+
124,
9+
63,
10+
240,
711
228,
8-
62,
9-
229,
10-
45,
12+
207,
13+
78,
14+
64,
15+
191,
16+
89,
17+
84,
18+
121,
19+
150,
20+
21,
21+
207,
22+
248,
23+
173,
24+
132,
1125
77,
12-
247,
26+
126,
27+
148,
28+
252,
1329
239,
14-
251,
15-
224,
16-
244,
17-
97,
18-
68,
19-
46,
20-
184,
21-
181,
22-
205,
23-
86,
24-
212,
25-
153,
26-
66,
27-
146,
28-
179,
29-
120,
30-
206,
31-
95,
32-
76,
33-
11,
34-
0,
35-
184,
36-
137,
37-
173
30+
104,
31+
130,
32+
55,
33+
201,
34+
32,
35+
57,
36+
167,
37+
215,
38+
228
3839
]
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
11
---
22
source: crates/astria-sequencer/src/app/tests_breaking_changes.rs
3+
assertion_line: 157
34
expression: app.app_hash.as_bytes()
45
---
56
[
6-
111,
7-
25,
8-
76,
9-
238,
10-
112,
11-
77,
12-
102,
13-
234,
14-
8,
15-
97,
16-
24,
17-
100,
18-
73,
19-
128,
20-
228,
21-
106,
22-
82,
23-
255,
24-
119,
25-
93,
26-
248,
7+
7,
278
224,
28-
51,
29-
239,
309
115,
31-
58,
32-
9,
33-
149,
34-
86,
35-
23,
10+
113,
11+
195,
12+
128,
13+
219,
3614
248,
37-
114
15+
198,
16+
108,
17+
251,
18+
204,
19+
202,
20+
182,
21+
150,
22+
203,
23+
69,
24+
213,
25+
169,
26+
101,
27+
228,
28+
90,
29+
61,
30+
94,
31+
59,
32+
180,
33+
251,
34+
59,
35+
119,
36+
37,
37+
42,
38+
216
3839
]

‎crates/astria-sequencer/src/app/snapshots/astria_sequencer__app__tests_breaking_changes__app_genesis_snapshot.snap

+31-31
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@ source: crates/astria-sequencer/src/app/tests_breaking_changes.rs
33
expression: app.app_hash.as_bytes()
44
---
55
[
6-
230,
7-
203,
8-
68,
9-
175,
10-
166,
11-
230,
12-
219,
13-
247,
14-
217,
15-
191,
16-
121,
17-
236,
18-
155,
19-
53,
20-
148,
21-
22,
22-
12,
23-
121,
24-
60,
25-
22,
26-
214,
27-
93,
6+
7,
7+
34,
8+
84,
9+
104,
10+
180,
11+
74,
12+
207,
13+
31,
14+
198,
15+
255,
16+
107,
17+
249,
18+
25,
19+
37,
20+
103,
21+
202,
22+
199,
23+
132,
24+
141,
25+
201,
26+
64,
27+
172,
2828
26,
29-
177,
30-
216,
31-
135,
32-
217,
33-
212,
34-
93,
35-
40,
36-
173,
37-
94
29+
24,
30+
80,
31+
182,
32+
114,
33+
182,
34+
189,
35+
220,
36+
109,
37+
211
3838
]

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

+19-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use astria_core::{
66
primitive::v1::{
77
asset::TracePrefixed,
88
RollupId,
9+
TransactionId,
910
},
1011
protocol::{
1112
genesis::v1alpha1::Account,
@@ -54,10 +55,7 @@ use crate::{
5455
StateWriteExt as _,
5556
ValidatorSet,
5657
},
57-
bridge::{
58-
StateReadExt as _,
59-
StateWriteExt as _,
60-
},
58+
bridge::StateWriteExt as _,
6159
proposal::commitment::generate_rollup_datas_commitment,
6260
state_ext::StateReadExt as _,
6361
test_utils::{
@@ -304,6 +302,23 @@ async fn app_create_sequencer_block_with_sequenced_data_and_deposits() {
304302
state_tx
305303
.put_bridge_account_ibc_asset(bridge_address, nria())
306304
.unwrap();
305+
// Put a deposit from a previous block to ensure it is not mixed in with deposits for this
306+
// block (it has a different amount and tx ID to the later deposit).
307+
let old_deposit = Deposit {
308+
bridge_address,
309+
rollup_id,
310+
amount: 99,
311+
asset: nria().into(),
312+
destination_chain_address: "nootwashere".to_string(),
313+
source_transaction_id: TransactionId::new([99; 32]),
314+
source_action_index: starting_index_of_action,
315+
};
316+
state_tx
317+
.put_deposits(
318+
&[32u8; 32],
319+
HashMap::from_iter([(rollup_id, vec![old_deposit])]),
320+
)
321+
.unwrap();
307322
app.apply(state_tx);
308323
app.prepare_commit(storage.clone()).await.unwrap();
309324
app.commit(storage.clone()).await;
@@ -361,10 +376,6 @@ async fn app_create_sequencer_block_with_sequenced_data_and_deposits() {
361376
.unwrap();
362377
app.commit(storage).await;
363378

364-
// ensure deposits are cleared at the end of the block
365-
let deposit_events = app.state.get_deposit_events(&rollup_id).await.unwrap();
366-
assert_eq!(deposit_events.len(), 0);
367-
368379
let block = app.state.get_sequencer_block_by_height(1).await.unwrap();
369380
let mut deposits = vec![];
370381
for (_, rollup_data) in block.rollup_transactions() {

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,8 @@ async fn app_execute_transaction_bridge_lock_action_ok() {
773773
bridge_before_balance + amount
774774
);
775775

776-
let deposits = app.state.get_deposit_events(&rollup_id).await.unwrap();
776+
let all_deposits = app.state.get_cached_block_deposits();
777+
let deposits = all_deposits.get(&rollup_id).unwrap();
777778
assert_eq!(deposits.len(), 1);
778779
assert_eq!(deposits[0], expected_deposit);
779780
}
@@ -1116,7 +1117,8 @@ async fn app_execute_transaction_action_index_correctly_increments() {
11161117
app.execute_transaction(signed_tx.clone()).await.unwrap();
11171118
assert_eq!(app.state.get_account_nonce(alice_address).await.unwrap(), 1);
11181119

1119-
let deposits = app.state.get_deposit_events(&rollup_id).await.unwrap();
1120+
let all_deposits = app.state.get_cached_block_deposits();
1121+
let deposits = all_deposits.get(&rollup_id).unwrap();
11201122
assert_eq!(deposits.len(), 2);
11211123
assert_eq!(deposits[0].source_action_index, starting_index_of_action);
11221124
assert_eq!(

‎crates/astria-sequencer/src/assets/state_ext.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct DenominationTrace(String);
3030

3131
const BLOCK_FEES_PREFIX: &str = "block_fees/";
3232
const FEE_ASSET_PREFIX: &str = "fee_asset/";
33-
const NATIVE_ASSET_KEY: &[u8] = b"nativeasset";
33+
const NATIVE_ASSET_KEY: &str = "nativeasset";
3434

3535
fn asset_storage_key<TAsset: Into<asset::IbcPrefixed>>(asset: TAsset) -> String {
3636
format!("asset/{}", crate::storage_keys::hunks::Asset::from(asset))
@@ -71,7 +71,7 @@ pub(crate) trait StateReadExt: StateRead {
7171
#[instrument(skip_all)]
7272
async fn get_native_asset(&self) -> Result<asset::TracePrefixed> {
7373
let Some(bytes) = self
74-
.nonverifiable_get_raw(NATIVE_ASSET_KEY)
74+
.get_raw(NATIVE_ASSET_KEY)
7575
.await
7676
.map_err(anyhow_to_eyre)
7777
.wrap_err("failed to read raw native asset from state")?
@@ -191,7 +191,7 @@ impl<T: ?Sized + StateRead> StateReadExt for T {}
191191
pub(crate) trait StateWriteExt: StateWrite {
192192
#[instrument(skip_all)]
193193
fn put_native_asset(&mut self, asset: &asset::TracePrefixed) {
194-
self.nonverifiable_put_raw(NATIVE_ASSET_KEY.to_vec(), asset.to_string().into_bytes());
194+
self.put_raw(NATIVE_ASSET_KEY.to_string(), asset.to_string().into_bytes());
195195
}
196196

197197
#[instrument(skip_all)]

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

+1-4
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,7 @@ impl ActionHandler for BridgeLockAction {
142142
.wrap_err("failed to deduct fee from account balance")?;
143143

144144
state.record(deposit_abci_event);
145-
state
146-
.put_deposit_event(deposit)
147-
.await
148-
.wrap_err("failed to put deposit event into state")?;
145+
state.cache_deposit_event(deposit);
149146
Ok(())
150147
}
151148
}

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

+91-553
Large diffs are not rendered by default.

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

+6-24
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,7 @@ async fn emit_deposit<S: StateWrite>(
733733
};
734734
let deposit_abci_event = create_deposit_event(&deposit);
735735
state.record(deposit_abci_event);
736-
state
737-
.put_deposit_event(deposit)
738-
.await
739-
.wrap_err("failed to put deposit event into state")?;
736+
state.cache_deposit_event(deposit);
740737
Ok(())
741738
}
742739

@@ -962,10 +959,7 @@ mod tests {
962959
);
963960
assert_eq!(balance, 100);
964961

965-
let deposits = state_tx
966-
.get_block_deposits()
967-
.await
968-
.expect("a deposit should exist as a result of the transfer to a bridge account");
962+
let deposits = state_tx.get_cached_block_deposits();
969963
assert_eq!(deposits.len(), 1);
970964

971965
let expected_deposit = Deposit {
@@ -1043,10 +1037,7 @@ mod tests {
10431037
.expect("receipt of funds to a rollup should have updated funds in the bridge account");
10441038
assert_eq!(balance, amount);
10451039

1046-
let deposits = state_tx
1047-
.get_block_deposits()
1048-
.await
1049-
.expect("a deposit should exist as a result of the transfer to a bridge account");
1040+
let deposits = state_tx.get_cached_block_deposits();
10501041
assert_eq!(deposits.len(), 1);
10511042

10521043
let expected_deposit = Deposit {
@@ -1284,10 +1275,7 @@ mod tests {
12841275
.expect("rollup withdrawal refund should have updated funds in the bridge address");
12851276
assert_eq!(balance, amount);
12861277

1287-
let deposit = state_tx
1288-
.get_block_deposits()
1289-
.await
1290-
.expect("a deposit should exist as a result of the rollup withdrawal refund");
1278+
let deposit = state_tx.get_cached_block_deposits();
12911279

12921280
let expected_deposit = Deposit {
12931281
bridge_address,
@@ -1360,10 +1348,7 @@ mod tests {
13601348
.expect("refunds of rollup withdrawals should be credited to the bridge account");
13611349
assert_eq!(balance, amount);
13621350

1363-
let deposits = state_tx
1364-
.get_block_deposits()
1365-
.await
1366-
.expect("a deposit should exist as a result of the rollup withdrawal refund");
1351+
let deposits = state_tx.get_cached_block_deposits();
13671352

13681353
let deposit = deposits
13691354
.get(&rollup_id)
@@ -1444,10 +1429,7 @@ mod tests {
14441429
.expect("refunding a rollup should add the tokens to its bridge address");
14451430
assert_eq!(balance, amount);
14461431

1447-
let deposits = state_tx
1448-
.get_block_deposits()
1449-
.await
1450-
.expect("a deposit should exist as a result of the rollup withdrawal refund");
1432+
let deposits = state_tx.get_cached_block_deposits();
14511433
assert_eq!(deposits.len(), 1);
14521434

14531435
let deposit = deposits.get(&rollup_id).unwrap().first().unwrap();

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

-11
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,6 @@ use tendermint::abci::{
1313
EventAttributeIndexExt as _,
1414
};
1515

16-
pub(crate) struct Hex<'a>(pub(crate) &'a [u8]);
17-
18-
impl<'a> std::fmt::Display for Hex<'a> {
19-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20-
for byte in self.0 {
21-
f.write_fmt(format_args!("{byte:02x}"))?;
22-
}
23-
Ok(())
24-
}
25-
}
26-
2716
pub(crate) fn cometbft_to_sequencer_validator(
2817
value: tendermint::validator::Update,
2918
) -> Result<ValidatorUpdate> {

0 commit comments

Comments
 (0)
Please sign in to comment.