mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-01-15 19:53:07 +00:00
188 lines
5.7 KiB
Markdown
188 lines
5.7 KiB
Markdown
|
|
# Quickstart
|
|||
|
|
|
|||
|
|
Get a working example running quickly.
|
|||
|
|
|
|||
|
|
## Prerequisites
|
|||
|
|
|
|||
|
|
- Rust toolchain (nightly)
|
|||
|
|
- Sibling `nomos-node` checkout built and available
|
|||
|
|
- This repository cloned
|
|||
|
|
- Unix-like system (tested on Linux and macOS)
|
|||
|
|
|
|||
|
|
## Your First Test
|
|||
|
|
|
|||
|
|
The framework ships with runnable example binaries in `examples/src/bin/`. Let's start with the local runner:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# From the nomos-testing directory
|
|||
|
|
POL_PROOF_DEV_MODE=true cargo run -p runner-examples --bin local_runner
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This runs a complete scenario with **defaults**: 1 validator + 1 executor, mixed transaction + DA workload (5 tx/block + 1 channel + 1 blob), 60s duration.
|
|||
|
|
|
|||
|
|
**Core API Pattern** (simplified example):
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
use testing_framework_core::scenario::{Deployer, ScenarioBuilder};
|
|||
|
|
use testing_framework_runner_local::LocalDeployer;
|
|||
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|||
|
|
use std::time::Duration;
|
|||
|
|
|
|||
|
|
// Define the scenario (1 validator + 1 executor, tx + DA workload)
|
|||
|
|
let mut plan = ScenarioBuilder::topology()
|
|||
|
|
.network_star()
|
|||
|
|
.validators(1)
|
|||
|
|
.executors(1)
|
|||
|
|
.apply()
|
|||
|
|
.wallets(64)
|
|||
|
|
.transactions()
|
|||
|
|
.rate(5) // 5 transactions per block
|
|||
|
|
.users(8)
|
|||
|
|
.apply()
|
|||
|
|
.da()
|
|||
|
|
.channel_rate(1) // 1 channel operation per block
|
|||
|
|
.blob_rate(1) // 1 blob dispersal per block
|
|||
|
|
.apply()
|
|||
|
|
.expect_consensus_liveness()
|
|||
|
|
.with_run_duration(Duration::from_secs(60))
|
|||
|
|
.build();
|
|||
|
|
|
|||
|
|
// Deploy and run
|
|||
|
|
let deployer = LocalDeployer::default();
|
|||
|
|
let runner = deployer.deploy(&plan).await?;
|
|||
|
|
let _handle = runner.run(&mut plan).await?;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Note:** The examples are binaries with `#[tokio::main]`, not test functions. If you want to write integration tests, wrap this pattern in `#[tokio::test]` functions in your own test suite.
|
|||
|
|
|
|||
|
|
**Important:** `POL_PROOF_DEV_MODE=true` disables expensive Groth16 zero-knowledge proof generation for leader election. Without it, proof generation is CPU-intensive and tests will timeout. **This is required for all runners** (local, compose, k8s) for practical testing. Never use in production.
|
|||
|
|
|
|||
|
|
**What you should see:**
|
|||
|
|
- Nodes spawn as local processes
|
|||
|
|
- Consensus starts producing blocks
|
|||
|
|
- Scenario runs for the configured duration
|
|||
|
|
- Node logs written to temporary directories in working directory (auto-cleaned up after test)
|
|||
|
|
- To persist logs: set `NOMOS_TESTS_TRACING=true` and `NOMOS_LOG_DIR=/path/to/logs` (files will have prefix like `nomos-node-0*`, may include timestamps)
|
|||
|
|
|
|||
|
|
## What Just Happened?
|
|||
|
|
|
|||
|
|
Let's unpack the code:
|
|||
|
|
|
|||
|
|
### 1. Topology Configuration
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
ScenarioBuilder::topology()
|
|||
|
|
.network_star() // Star topology: all nodes connect to seed
|
|||
|
|
.validators(1) // 1 validator node
|
|||
|
|
.executors(1) // 1 executor node (validator + DA dispersal)
|
|||
|
|
.apply()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This defines **what** your test network looks like.
|
|||
|
|
|
|||
|
|
### 2. Wallet Seeding
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
.wallets(64) // Seed 64 funded wallet accounts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Provides funded accounts for transaction submission.
|
|||
|
|
|
|||
|
|
### 3. Workloads
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
.transactions()
|
|||
|
|
.rate(5) // 5 transactions per block
|
|||
|
|
.users(8) // Use 8 of the 64 wallets
|
|||
|
|
.apply()
|
|||
|
|
.da()
|
|||
|
|
.channel_rate(1) // 1 channel operation per block
|
|||
|
|
.blob_rate(1) // 1 blob dispersal per block
|
|||
|
|
.apply()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Generates both transaction and DA traffic to stress both subsystems.
|
|||
|
|
|
|||
|
|
### 4. Expectation
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
.expect_consensus_liveness()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This says **what success means**: blocks must be produced continuously.
|
|||
|
|
|
|||
|
|
### 5. Run Duration
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
.with_run_duration(Duration::from_secs(60))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Run for 60 seconds (~27 blocks with default 2s slots, 0.9 coefficient). Framework ensures this is at least 2× the consensus slot duration.
|
|||
|
|
|
|||
|
|
### 6. Deploy and Execute
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
let deployer = LocalDeployer::default(); // Use local process deployer
|
|||
|
|
let runner = deployer.deploy(&plan).await?; // Provision infrastructure
|
|||
|
|
let _handle = runner.run(&mut plan).await?; // Execute workloads & expectations
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Deployer** provisions the infrastructure. **Runner** orchestrates execution.
|
|||
|
|
|
|||
|
|
## Adjust the Topology
|
|||
|
|
|
|||
|
|
The binary accepts environment variables to adjust defaults:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Scale up to 3 validators + 2 executors, run for 2 minutes
|
|||
|
|
LOCAL_DEMO_VALIDATORS=3 \
|
|||
|
|
LOCAL_DEMO_EXECUTORS=2 \
|
|||
|
|
LOCAL_DEMO_RUN_SECS=120 \
|
|||
|
|
POL_PROOF_DEV_MODE=true \
|
|||
|
|
cargo run -p runner-examples --bin local_runner
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Try Docker Compose
|
|||
|
|
|
|||
|
|
Use the same API with a different deployer for reproducible containerized environment:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Build the test image first (includes circuit assets)
|
|||
|
|
chmod +x scripts/setup-nomos-circuits.sh
|
|||
|
|
scripts/setup-nomos-circuits.sh v0.3.1 /tmp/nomos-circuits
|
|||
|
|
cp -r /tmp/nomos-circuits/* testing-framework/assets/stack/kzgrs_test_params/
|
|||
|
|
|
|||
|
|
chmod +x testing-framework/assets/stack/scripts/build_test_image.sh
|
|||
|
|
testing-framework/assets/stack/scripts/build_test_image.sh
|
|||
|
|
|
|||
|
|
# Run with Compose
|
|||
|
|
NOMOS_TESTNET_IMAGE=nomos-testnet:local \
|
|||
|
|
POL_PROOF_DEV_MODE=true \
|
|||
|
|
cargo run -p runner-examples --bin compose_runner
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Benefit:** Reproducible containerized environment with Prometheus at `http://localhost:9090`.
|
|||
|
|
|
|||
|
|
**In code:** Just swap the deployer:
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
use testing_framework_runner_compose::ComposeDeployer;
|
|||
|
|
|
|||
|
|
// ... same scenario definition ...
|
|||
|
|
|
|||
|
|
let deployer = ComposeDeployer::default(); // Use Docker Compose
|
|||
|
|
let runner = deployer.deploy(&plan).await?;
|
|||
|
|
let _handle = runner.run(&mut plan).await?;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Next Steps
|
|||
|
|
|
|||
|
|
Now that you have a working test:
|
|||
|
|
|
|||
|
|
- **Understand the philosophy**: [Testing Philosophy](testing-philosophy.md)
|
|||
|
|
- **Learn the architecture**: [Architecture Overview](architecture-overview.md)
|
|||
|
|
- **See more examples**: [Examples](examples.md)
|
|||
|
|
- **API reference**: [Builder API Quick Reference](dsl-cheat-sheet.md)
|
|||
|
|
- **Debug failures**: [Troubleshooting](troubleshooting.md)
|
|||
|
|
|