|
| 1 | +# L1 Multi-Mode Testing Documentation |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This document describes the test suite for Issue #420: Testing multi-mode L1 event consumption, reorg handling, and node restart scenarios. |
| 6 | + |
| 7 | +**Related Issue**: https://github.com/scroll-tech/rollup-node/issues/420 |
| 8 | + |
| 9 | +## Test Coverage |
| 10 | + |
| 11 | +### 1. Event Consumption in Different Sync States |
| 12 | + |
| 13 | +The test suite covers the following scenarios as specified in the issue: |
| 14 | + |
| 15 | +| Event | Sync State | Test Function | Expected Outcome | |
| 16 | +| ---------------- | ---------- | ------------- | ---------------- | |
| 17 | +| BatchCommit | Syncing | `test_batch_commit_while_syncing` | No change (events only processed when finalized) | |
| 18 | +| BatchCommit | Synced | `test_batch_commit_while_synced` | Updates safe head immediately | |
| 19 | +| BatchFinalized | Syncing | `test_batch_finalized_while_syncing` | Triggers unprocessed BatchCommit events, updates safe and finalized heads | |
| 20 | +| BatchFinalized | Synced | `test_batch_finalized_while_synced` | Updates finalized head only | |
| 21 | +| BatchRevert | Syncing | `test_batch_revert_while_syncing` | No effect | |
| 22 | +| BatchRevert | Synced | `test_batch_revert_while_synced` | Updates safe head to last block of previous batch | |
| 23 | + |
| 24 | +### 2. L1 Reorg Handling |
| 25 | + |
| 26 | +Tests for handling L1 reorgs of various events: |
| 27 | + |
| 28 | +| Reorged Event | Test Function | Expected Outcome | |
| 29 | +| ------------------ | ------------- | ---------------- | |
| 30 | +| BatchCommit | `test_l1_reorg_batch_commit` | Updates safe head to last block of previous BatchCommit | |
| 31 | +| BatchFinalized | `test_l1_reorg_batch_finalized_has_no_effect` | No change (finalized events can't be reorged) | |
| 32 | + |
| 33 | +### 3. Node Shutdown and Restart |
| 34 | + |
| 35 | +- `test_node_restart_after_l1_reorg`: Tests node restart after L1 reorg (requires implementation) |
| 36 | + |
| 37 | +### 4. Anvil Integration |
| 38 | + |
| 39 | +- `test_with_anvil_l1_events`: Demonstrates using real Anvil instance for L1 interactions |
| 40 | + |
| 41 | +## Current Status |
| 42 | + |
| 43 | +### ✅ Completed |
| 44 | + |
| 45 | +1. **Test structure created** - All test functions are defined with proper documentation |
| 46 | +2. **Anvil integration** - TestFixture now supports Anvil with configurable state files |
| 47 | +3. **Test data prepared**: |
| 48 | + - `tests/anvil_state.json` - Anvil initial state with deployed L1 contracts |
| 49 | + - `crates/node/tests/testdata/test_transactions.json` - Raw transaction data |
| 50 | + - `crates/node/tests/testdata/batch_0_calldata.bin` - Real batch calldata |
| 51 | + - `crates/node/tests/testdata/batch_1_calldata.bin` - Real batch calldata |
| 52 | + |
| 53 | +### 🚧 Needs Implementation |
| 54 | + |
| 55 | +1. **Node restart testing infrastructure**: |
| 56 | + - Persistent database across test runs |
| 57 | + - Ability to stop and restart ChainOrchestrator |
| 58 | + - Reorg detection on startup |
| 59 | + |
| 60 | +2. **Anvil state file loading**: |
| 61 | + - The current `spawn_anvil` implementation logs a warning about state loading |
| 62 | + - Need to implement proper state loading from `tests/anvil_state.json` |
| 63 | + - See `crates/node/src/test_utils/fixture.rs:582-587` |
| 64 | + |
| 65 | +3. **Enhanced L1 event helpers**: |
| 66 | + - Consider adding `BatchRangeReverted` event helper |
| 67 | + - Add more granular reorg testing utilities |
| 68 | + |
| 69 | +4. **Real L1 contract interactions**: |
| 70 | + - Send transactions to Anvil L1 contracts (ScrollChain, MessageQueue) |
| 71 | + - Parse real contract events |
| 72 | + - Test end-to-end flow from contract call to rollup node event processing |
| 73 | + |
| 74 | +## Running the Tests |
| 75 | + |
| 76 | +### Run all L1 multi-mode tests: |
| 77 | + |
| 78 | +```bash |
| 79 | +cargo test --test l1_multi_mode |
| 80 | +``` |
| 81 | + |
| 82 | +### Run a specific test: |
| 83 | + |
| 84 | +```bash |
| 85 | +cargo test --test l1_multi_mode test_batch_commit_while_syncing |
| 86 | +``` |
| 87 | + |
| 88 | +### Run tests with logging: |
| 89 | + |
| 90 | +```bash |
| 91 | +RUST_LOG=debug cargo test --test l1_multi_mode -- --nocapture |
| 92 | +``` |
| 93 | + |
| 94 | +### Run Anvil integration tests: |
| 95 | + |
| 96 | +```bash |
| 97 | +# These tests are ignored by default |
| 98 | +cargo test --test l1_multi_mode test_with_anvil_l1_events -- --ignored |
| 99 | +``` |
| 100 | + |
| 101 | +## Next Steps |
| 102 | + |
| 103 | +### Phase 1: Fix Compilation Issues |
| 104 | + |
| 105 | +Some tests may have compilation errors due to: |
| 106 | +- Rust toolchain version mismatch (proc macro ABI issues) |
| 107 | +- Missing trait imports |
| 108 | + |
| 109 | +**Action**: Run `cargo clean` and rebuild with the correct toolchain version. |
| 110 | + |
| 111 | +### Phase 2: Implement Anvil State Loading |
| 112 | + |
| 113 | +Update `TestFixtureBuilder::spawn_anvil` to properly load state from JSON: |
| 114 | + |
| 115 | +```rust |
| 116 | +async fn spawn_anvil( |
| 117 | + state_path: Option<&std::path::Path>, |
| 118 | + chain_id: Option<u64>, |
| 119 | + block_time: Option<u64>, |
| 120 | +) -> eyre::Result<anvil::NodeHandle> { |
| 121 | + let mut config = anvil::NodeConfig::default(); |
| 122 | + |
| 123 | + if let Some(id) = chain_id { |
| 124 | + config.chain_id = Some(id); |
| 125 | + } |
| 126 | + |
| 127 | + if let Some(time) = block_time { |
| 128 | + config.block_time = Some(std::time::Duration::from_secs(time)); |
| 129 | + } |
| 130 | + |
| 131 | + // TODO: Implement state loading |
| 132 | + // Research the correct Anvil API for loading state from file |
| 133 | + |
| 134 | + let (_api, handle) = anvil::spawn(config).await; |
| 135 | + Ok(handle) |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +### Phase 3: Enhance Test Infrastructure |
| 140 | + |
| 141 | +1. **Add persistent database support**: |
| 142 | + ```rust |
| 143 | + pub fn with_persistent_db(mut self, path: impl Into<PathBuf>) -> Self { |
| 144 | + // Implementation needed |
| 145 | + } |
| 146 | + ``` |
| 147 | + |
| 148 | +2. **Add node restart capability**: |
| 149 | + ```rust |
| 150 | + pub async fn restart_node(&mut self, index: usize) -> eyre::Result<()> { |
| 151 | + // Implementation needed |
| 152 | + } |
| 153 | + ``` |
| 154 | + |
| 155 | +3. **Add more event assertions**: |
| 156 | + ```rust |
| 157 | + impl EventAssertions { |
| 158 | + pub async fn batch_reverted(self) -> eyre::Result<()> { |
| 159 | + // Implementation needed |
| 160 | + } |
| 161 | + |
| 162 | + pub async fn l1_reorg(self) -> eyre::Result<()> { |
| 163 | + // Implementation needed |
| 164 | + } |
| 165 | + } |
| 166 | + ``` |
| 167 | + |
| 168 | +### Phase 4: Real L1 Contract Testing |
| 169 | + |
| 170 | +Use the `test_transactions.json` data to: |
| 171 | + |
| 172 | +1. Send real transactions to Anvil contracts |
| 173 | +2. Trigger actual BatchCommit/BatchFinalized events |
| 174 | +3. Verify the rollup node processes them correctly |
| 175 | + |
| 176 | +Example structure: |
| 177 | + |
| 178 | +```rust |
| 179 | +#[tokio::test] |
| 180 | +async fn test_real_l1_batch_commit() -> eyre::Result<()> { |
| 181 | + let mut fixture = TestFixture::builder() |
| 182 | + .sequencer() |
| 183 | + .with_anvil_default_state() |
| 184 | + .with_anvil_chain_id(1337) |
| 185 | + .build() |
| 186 | + .await?; |
| 187 | + |
| 188 | + // Get provider for Anvil |
| 189 | + let anvil = fixture.anvil.as_ref().unwrap(); |
| 190 | + let provider = ProviderBuilder::new() |
| 191 | + .with_recommended_fillers() |
| 192 | + .on_http(anvil.endpoint().parse()?); |
| 193 | + |
| 194 | + // Load and send transaction from test_transactions.json |
| 195 | + let tx_data = load_test_transaction("batch_commit_tx_0")?; |
| 196 | + let tx_hash = provider.send_raw_transaction(&tx_data).await?.tx_hash(); |
| 197 | + |
| 198 | + // Wait for rollup node to process the event |
| 199 | + fixture.expect_event().batch_consolidated().await?; |
| 200 | + |
| 201 | + Ok(()) |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +## Environment Setup |
| 206 | + |
| 207 | +### Required Files |
| 208 | + |
| 209 | +1. `tests/anvil_state.json` - ✅ Already created |
| 210 | +2. `tests/anvil.env` - ✅ Already created |
| 211 | +3. `crates/node/tests/testdata/test_transactions.json` - ✅ Already created |
| 212 | +4. `crates/node/tests/testdata/batch_0_calldata.bin` - ✅ Already exists |
| 213 | +5. `crates/node/tests/testdata/batch_1_calldata.bin` - ✅ Already exists |
| 214 | + |
| 215 | +### Contract Addresses (from anvil.env) |
| 216 | + |
| 217 | +Key L1 contract addresses deployed in Anvil: |
| 218 | + |
| 219 | +- **L1_SCROLL_CHAIN_PROXY**: `0x5FC8d32690cc91D4c39d9d3abcBD16989F875707` |
| 220 | +- **L1_MESSAGE_QUEUE_V2_PROXY**: `0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9` |
| 221 | +- **L1_SYSTEM_CONFIG_PROXY**: `0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0` |
| 222 | + |
| 223 | +## Testing Matrix |
| 224 | + |
| 225 | +Use this matrix to track test implementation progress: |
| 226 | + |
| 227 | +| Category | Test | Status | Notes | |
| 228 | +|----------|------|--------|-------| |
| 229 | +| **Sync State** | BatchCommit - Syncing | ✅ | Implemented | |
| 230 | +| | BatchCommit - Synced | ✅ | Implemented | |
| 231 | +| | BatchFinalized - Syncing | ✅ | Implemented | |
| 232 | +| | BatchFinalized - Synced | ✅ | Implemented | |
| 233 | +| | BatchRevert - Syncing | ✅ | Implemented | |
| 234 | +| | BatchRevert - Synced | ✅ | Implemented | |
| 235 | +| **L1 Reorg** | BatchCommit Reorg | ✅ | Implemented | |
| 236 | +| | BatchFinalized Reorg | ✅ | Implemented | |
| 237 | +| | BatchRevert Reorg | ⬜ | TODO | |
| 238 | +| | BatchRangeRevert Reorg | ⬜ | TODO | |
| 239 | +| **Node Restart** | Restart after reorg | 🚧 | Needs infrastructure | |
| 240 | +| | Restart with unfinalized events | ⬜ | TODO | |
| 241 | +| **Anvil Integration** | Real contract events | 🚧 | Partial implementation | |
| 242 | + |
| 243 | +## Troubleshooting |
| 244 | + |
| 245 | +### Proc Macro ABI Mismatch |
| 246 | + |
| 247 | +If you see errors like: |
| 248 | +``` |
| 249 | +proc macro server error: mismatched ABI |
| 250 | +``` |
| 251 | + |
| 252 | +**Solution**: |
| 253 | +```bash |
| 254 | +cargo clean |
| 255 | +cargo build --tests |
| 256 | +``` |
| 257 | + |
| 258 | +### Missing Batch Calldata Files |
| 259 | + |
| 260 | +If tests fail with "No such file or directory" for batch calldata: |
| 261 | + |
| 262 | +**Solution**: Ensure you're running tests from the project root: |
| 263 | +```bash |
| 264 | +cd /Users/yiweichi/Scroll/rollup-node |
| 265 | +cargo test --test l1_multi_mode |
| 266 | +``` |
| 267 | + |
| 268 | +### Anvil Connection Issues |
| 269 | + |
| 270 | +If Anvil tests time out: |
| 271 | + |
| 272 | +**Solution**: Check that the Anvil instance is starting correctly and listening on the expected port. |
| 273 | + |
| 274 | +## Contributing |
| 275 | + |
| 276 | +When adding new tests: |
| 277 | + |
| 278 | +1. Follow the existing test structure and naming conventions |
| 279 | +2. Add comprehensive documentation comments |
| 280 | +3. Update this README with new test coverage |
| 281 | +4. Ensure tests are idempotent and don't depend on execution order |
| 282 | +5. Use the builder pattern for complex test setup |
| 283 | + |
| 284 | +## References |
| 285 | + |
| 286 | +- [Issue #420](https://github.com/scroll-tech/rollup-node/issues/420) - Original issue |
| 287 | +- [TestFixture Documentation](crates/node/src/test_utils/fixture.rs) |
| 288 | +- [L1 Helper Functions](crates/node/src/test_utils/l1_helpers.rs) |
| 289 | +- [Event Assertions](crates/node/src/test_utils/event_utils.rs) |
| 290 | + |
| 291 | + |
0 commit comments