Skip to content

Commit

Permalink
update changelog, example config, test soft-first and firm-first scen…
Browse files Browse the repository at this point in the history
…arios separately
  • Loading branch information
ethanoroshiba authored and SuperFluffy committed Feb 4, 2025
1 parent add58bc commit c720931
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 21 deletions.
2 changes: 2 additions & 0 deletions crates/astria-conductor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Update `idna` dependency to resolve cargo audit warning [#1869](https://github.com/astriaorg/astria/pull/1869).
- Remove panic source on shutdown [#1919](https://github.com/astriaorg/astria/pull/1919).
- Add stop height logic, remove chain id env vars, accomodate new genesis info
shape [#1843](https://github.com/astriaorg/astria/pull/1843).

## [1.0.0] - 2024-10-25

Expand Down
6 changes: 0 additions & 6 deletions crates/astria-conductor/local.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ ASTRIA_CONDUCTOR_SEQUENCER_BLOCK_TIME_MS=2000
# CometBFT node.
ASTRIA_CONDUCTOR_SEQUENCER_REQUESTS_PER_SECOND=500

# The chain ID of the sequencer network the conductor should be communicating with.
ASTRIA_CONDUCTOR_EXPECTED_SEQUENCER_CHAIN_ID="test-sequencer-1000"

# The chain ID of the Celestia network the conductor should be communicating with.
ASTRIA_CONDUCTOR_EXPECTED_CELESTIA_CHAIN_ID="test-celestia-1000"

# Set to true to enable prometheus metrics.
ASTRIA_CONDUCTOR_NO_METRICS=true

Expand Down
263 changes: 248 additions & 15 deletions crates/astria-conductor/tests/blackbox/soft_and_firm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,19 +594,18 @@ async fn conductor_restarts_on_permission_denied() {
);
}

/// Tests if the conductor correctly stops and procedes to restart after reaching the sequencer stop
/// height (from genesis info provided by rollup). In `SoftAndFirm` mode executor should execute
/// both the soft and firm blocks at the stop height and then perform a restart.
/// Tests if the conductor correctly stops and procedes to restart after soft block height reaches
/// sequencer stop height (from genesis info provided by rollup). In `SoftAndFirm` mode executor
/// should execute both the soft and firm blocks at the stop height and then perform a restart.
///
/// This test consists of the following steps:
/// 1. Mount commitment state and genesis info with a sequencer stop height of 3, only responding up
/// to 1 time so that Conductor will not receive the same response after restart.
/// 2. Mount Celestia network head and sequencer genesis.
/// 3. Mount ABCI info and sequencer (soft blocks) for heights 3 and 4.
/// 4. Mount firm blocks at heights 3 and 4, with corresponding `update_commitment_state` mounts,
/// which should both be called. These are mounted with a slight delay to ensure that the soft
/// block arrives first after restart.
/// 5. Mount `execute_block` and `update_commitment_state` for both soft and firm blocks at height
/// 3. Mount ABCI info and sequencer blocks (soft blocks) for heights 3 and 4.
/// 4. Mount firm blocks at heights 3 and 4 with a slight delay to ensure that the soft blocks
/// arrive first.
/// 5. Mount `execute_block` and `update_commitment_state` for both soft and firm blocks at height 3
/// 6. Await satisfaction of the `execute_block` and `update_commitment_state` for the soft and firm
/// blocks at height 3 with a timeout of 1000ms. The test sleeps during this time, so that the
/// following mounts do not occur before the conductor restarts.
Expand All @@ -620,7 +619,7 @@ async fn conductor_restarts_on_permission_denied() {
reason = "All lines reasonably necessary for the thoroughness of this test"
)]
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn conductor_restarts_after_reaching_stop_height() {
async fn conductor_restarts_after_reaching_soft_stop_height_first() {
let test_conductor = spawn_conductor(CommitLevel::SoftAndFirm).await;

mount_get_genesis_info!(
Expand Down Expand Up @@ -695,6 +694,237 @@ async fn conductor_restarts_after_reaching_stop_height() {
expected_calls: 1, // This should not be called again after restart
);

let update_commitment_state_soft_1 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_soft_1",
firm: (
number: 1,
hash: [1; 64],
parent: [0; 64],
),
soft: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
base_celestia_height: 1,
expected_calls: 1,
);

let update_commitment_state_firm_1 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_firm_1",
firm: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
soft: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
base_celestia_height: 1,
expected_calls: 1, // Should not be called again after restart
);

timeout(
Duration::from_millis(1000),
join3(
execute_block_1.wait_until_satisfied(),
update_commitment_state_firm_1.wait_until_satisfied(),
update_commitment_state_soft_1.wait_until_satisfied(),
),
)
.await
.expect("conductor should have updated the firm commitment state within 1000ms");

// Wait until conductor is restarted before performing next set of mounts
sleep(Duration::from_millis(1000)).await;

mount_get_genesis_info!(
test_conductor,
sequencer_start_block_height: 2,
sequencer_stop_block_height: 10,
celestia_block_variance: 10,
rollup_start_block_height: 1,
);

mount_get_commitment_state!(
test_conductor,
firm: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
soft: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
base_celestia_height: 1,
);

let execute_block_2 = mount_executed_block!(
test_conductor,
mock_name: "execute_block_2",
number: 3,
hash: [3; 64],
parent: [2; 64],
expected_calls: 1,
);

// This condition should be satisfied, since there is a delay on the firm block response
let update_commitment_state_soft_2 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_soft_2",
firm: (
number: 2,
hash: [2; 64],
parent: [1; 64],
),
soft: (
number: 3,
hash: [3; 64],
parent: [2; 64],
),
base_celestia_height: 1,
expected_calls: 1,
);

let update_commitment_state_firm_2 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_firm_2",
firm: (
number: 3,
hash: [3; 64],
parent: [2; 64],
),
soft: (
number: 3,
hash: [3; 64],
parent: [2; 64],
),
base_celestia_height: 1,
expected_calls: 1,
);

timeout(
Duration::from_millis(1000),
join3(
execute_block_2.wait_until_satisfied(),
update_commitment_state_firm_2.wait_until_satisfied(),
update_commitment_state_soft_2.wait_until_satisfied(),
),
)
.await
.expect("conductor should have updated the firm commitment state within 1000ms");
}

/// Tests if the conductor correctly stops and procedes to restart after firm height reaches
/// sequencer stop height, *without* updating soft commitment state, since the firm was received
/// first.
///
/// This test consists of the following steps:
/// 1. Mount commitment state and genesis info with a sequencer stop height of 3, only responding up
/// to 1 time so that Conductor will not receive the same response after restart.
/// 2. Mount Celestia network head and sequencer genesis.
/// 3. Mount ABCI info and sequencer blocks (soft blocks) for heights 3 and 4 with a slight delay,
/// to ensure the firm blocks arrive first.
/// 4. Mount firm blocks at heights 3 and 4.
/// 5. Mount `update_commitment_state` for the soft block at height 3, expecting 0 calls since the
/// firm block will be received first.
/// 5. Mount `execute_block` and `update_commitment_state` for firm block at height 3.
/// 6. Await satisfaction of the `execute_block` and `update_commitment_state` for the firm block at
/// height 3 with a timeout of 1000ms. The test sleeps during this time, so that the following
/// mounts do not occur before the conductor restarts.
/// 7. Mount new genesis info with a sequencer stop height of 10 and a rollup start block height of
/// 2, along with corresponding commitment state, reflecting that block 1 has already been
/// executed and the commitment state updated.
/// 8. Mount `execute_block` and `update_commitment_state` for both soft and firm blocks at height 4
/// and await their satisfaction (the soft mount need not be satisfied in the case that the firm
/// block is received first; we are just looking to see that the conductor restarted properly).
#[expect(
clippy::too_many_lines,
reason = "All lines reasonably necessary for the thoroughness of this test"
)]
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn conductor_restarts_after_reaching_firm_stop_height_first() {
let test_conductor = spawn_conductor(CommitLevel::SoftAndFirm).await;

mount_get_genesis_info!(
test_conductor,
sequencer_start_block_height: 1,
sequencer_stop_block_height: 3,
celestia_block_variance: 10,
rollup_start_block_height: 0,
up_to_n_times: 1, // We only respond once since this needs to be updated after restart
);

mount_get_commitment_state!(
test_conductor,
firm: (
number: 1,
hash: [1; 64],
parent: [0; 64],
),
soft: (
number: 1,
hash: [1; 64],
parent: [0; 64],
),
base_celestia_height: 1,
up_to_n_times: 1, // We only respond once since this needs to be updated after restart
);

mount_sequencer_genesis!(test_conductor);
mount_celestia_header_network_head!(
test_conductor,
height: 1u32,
);
mount_abci_info!(
test_conductor,
latest_sequencer_height: 4,
);

// Mount soft blocks for heights 3 and 4
mount_get_filtered_sequencer_block!(
test_conductor,
sequencer_height: 3,
delay: Duration::from_millis(200),
);
mount_get_filtered_sequencer_block!(
test_conductor,
sequencer_height: 4,
);

// Mount firm blocks for heights 3 and 4
mount_celestia_blobs!(
test_conductor,
celestia_height: 1,
sequencer_heights: [3, 4],
);
mount_sequencer_commit!(
test_conductor,
height: 3u32,
);
mount_sequencer_commit!(
test_conductor,
height: 4u32,
);
mount_sequencer_validator_set!(test_conductor, height: 2u32);
mount_sequencer_validator_set!(test_conductor, height: 3u32);

let execute_block_1 = mount_executed_block!(
test_conductor,
mock_name: "execute_block_1",
number: 2,
hash: [2; 64],
parent: [1; 64],
expected_calls: 1, // This should not be called again after restart
);

// Should not be called since the firm block will be received first
let _update_commitment_state_soft_1 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_soft_1",
Expand All @@ -709,7 +939,7 @@ async fn conductor_restarts_after_reaching_stop_height() {
parent: [1; 64],
),
base_celestia_height: 1,
expected_calls: 0..=1,
expected_calls: 0,
);

let update_commitment_state_firm_1 = mount_update_commitment_state!(
Expand Down Expand Up @@ -774,7 +1004,7 @@ async fn conductor_restarts_after_reaching_stop_height() {
expected_calls: 1,
);

// This condition need not be satisfied, the firm commitment state might fire first.
// This condition does not need to be satisfied, since firm block may fire first after restart
let _update_commitment_state_soft_2 = mount_update_commitment_state!(
test_conductor,
mock_name: "update_commitment_state_soft_2",
Expand Down Expand Up @@ -827,11 +1057,14 @@ async fn conductor_restarts_after_reaching_stop_height() {
/// 1. Mount commitment state and genesis info with a sequencer stop height of 3, expecting only 1
/// response.
/// 2. Mount Celestia network head and sequencer genesis.
/// 3. Mount ABCI info and sequencer (soft blocks) for height 3.
/// 4. Mount firm blocks at height 3, with corresponding `update_commitment_state` mount.
/// 3. Mount ABCI info and sequencer blocks (soft blocks) for height 3.
/// 4. Mount firm blocks at height 3.
/// 5. Mount `execute_block` and `update_commitment_state` for soft and firm blocks at height 3.
/// 6. Await satisfaction of the `execute_block` and `update_commitment_state` for the soft and firm
/// block height 3 with a timeout of 1000ms.
/// 6. Await satisfaction of the `execute_block` and `update_commitment_state` for the firm block
/// height 3 with a timeout of 1000ms. The soft mount need not be satisfied in the case that the
/// firm block is received first. The test case of ensuring the soft commitment state is updated
/// correctly in the case of receiving a soft block first is covered in
/// `conductor_restarts_after_reaching_soft_stop_height_first`.
/// 7. Allow ample time for the conductor to potentially restart erroneously.
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn conductor_stops_at_stop_height() {
Expand Down

0 comments on commit c720931

Please sign in to comment.