From 7aa93088e4f49b40dcf8a39522fbdef5a67552e6 Mon Sep 17 00:00:00 2001 From: bagelface Date: Tue, 14 Jul 2026 13:34:03 +0100 Subject: [PATCH] refactor: rename orchestrator/contributor naming to router/operator --- .github/workflows/local-integration-test.yml | 2 +- config/orchestrator.json | 3 - ...c_orchestrator.json => public_router.json} | 0 ...uter_orchestrator.json => router_key.json} | 0 docker-compose.yml | 22 +++--- example.env | 8 --- examples/counter/node/src/app.rs | 51 +++++++------- examples/counter/router/src/app.rs | 12 ++-- node/README.md | 6 +- router/README.md | 6 +- router/src/submitter.rs | 10 +-- scripts/README.md | 67 +++++++++---------- 12 files changed, 87 insertions(+), 100 deletions(-) delete mode 100644 config/orchestrator.json rename config/{public_orchestrator.json => public_router.json} (100%) rename config/{router_orchestrator.json => router_key.json} (100%) diff --git a/.github/workflows/local-integration-test.yml b/.github/workflows/local-integration-test.yml index 975ad0f8..0e53b11d 100644 --- a/.github/workflows/local-integration-test.yml +++ b/.github/workflows/local-integration-test.yml @@ -132,7 +132,7 @@ jobs: echo "Starting router in background..." # Source environment and run router in background - nohup cargo run -p counter-router --release -- --key-file config/router_orchestrator.json --port 3000 > router.log 2>&1 & + nohup cargo run -p counter-router --release -- --key-file config/router_key.json --port 3000 > router.log 2>&1 & echo $! > router.pid # Wait for router to start diff --git a/config/orchestrator.json b/config/orchestrator.json deleted file mode 100644 index b24c5c77..00000000 --- a/config/orchestrator.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "privateKey": "21747297277459394737337554964532622739983285244437107194284923826011566394548" -} \ No newline at end of file diff --git a/config/public_orchestrator.json b/config/public_router.json similarity index 100% rename from config/public_orchestrator.json rename to config/public_router.json diff --git a/config/router_orchestrator.json b/config/router_key.json similarity index 100% rename from config/router_orchestrator.json rename to config/router_key.json diff --git a/docker-compose.yml b/docker-compose.yml index bf18a996..bba63ce7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -55,7 +55,7 @@ services: volumes: - ./config/.nodes/operator_keys/testacc1.private.bls.key.json:/app/key.json:ro - ./config/.nodes:/app/.nodes:ro - - ./config/public_orchestrator.json:/app/public_orchestrator.json:ro + - ./config/public_router.json:/app/public_router.json:ro - node-1-data:/app/data command: [ @@ -63,8 +63,8 @@ services: "/app/key.json", "--port", "3001", - "--orchestrator", - "/app/public_orchestrator.json", + "--router", + "/app/public_router.json", ] ports: - "3001:3001" @@ -91,7 +91,7 @@ services: volumes: - ./config/.nodes/operator_keys/testacc2.private.bls.key.json:/app/key.json:ro - ./config/.nodes:/app/.nodes:ro - - ./config/public_orchestrator.json:/app/public_orchestrator.json:ro + - ./config/public_router.json:/app/public_router.json:ro - node-2-data:/app/data command: [ @@ -99,8 +99,8 @@ services: "/app/key.json", "--port", "3002", - "--orchestrator", - "/app/public_orchestrator.json", + "--router", + "/app/public_router.json", ] ports: - "3002:3002" @@ -127,7 +127,7 @@ services: volumes: - ./config/.nodes/operator_keys/testacc3.private.bls.key.json:/app/key.json:ro - ./config/.nodes:/app/.nodes:ro - - ./config/public_orchestrator.json:/app/public_orchestrator.json:ro + - ./config/public_router.json:/app/public_router.json:ro - node-3-data:/app/data command: [ @@ -135,8 +135,8 @@ services: "/app/key.json", "--port", "3003", - "--orchestrator", - "/app/public_orchestrator.json", + "--router", + "/app/public_router.json", ] ports: - "3003:3003" @@ -167,9 +167,9 @@ services: - STORAGE_DIR=/app/data volumes: - ./config/.nodes:/app/.nodes:ro - - ./config/router_orchestrator.json:/app/router_orchestrator.json:ro + - ./config/router_key.json:/app/router_key.json:ro - router-data:/app/data - command: ["--key-file", "/app/router_orchestrator.json", "--port", "3000"] + command: ["--key-file", "/app/router_key.json", "--port", "3000"] ports: - "4000:3000" - "8080:8080" diff --git a/example.env b/example.env index 9165ee6e..f073f9f8 100644 --- a/example.env +++ b/example.env @@ -74,14 +74,6 @@ FUNDED_KEY= # Required for TESTNET mode, should have testnet ETH # ============================================================================= TEST_ACCOUNTS=3 -# ============================================================================= -# Contributor Key Files -# ============================================================================= -# These will be generated by the Docker setup -CONTRIBUTOR_1_KEYFILE="config/.nodes/operator_keys/testacc1.private.bls.key.json" -CONTRIBUTOR_2_KEYFILE="config/.nodes/operator_keys/testacc2.private.bls.key.json" -CONTRIBUTOR_3_KEYFILE="config/.nodes/operator_keys/testacc3.private.bls.key.json" - # ============================================================================= # Service Configuration # ============================================================================= diff --git a/examples/counter/node/src/app.rs b/examples/counter/node/src/app.rs index 29c9f280..70a31339 100644 --- a/examples/counter/node/src/app.rs +++ b/examples/counter/node/src/app.rs @@ -51,7 +51,7 @@ struct KeyConfig { } #[derive(Debug, Serialize, Deserialize)] #[allow(non_snake_case)] -struct OrchestratorConfig { +struct RouterConfig { g2_x1: String, g2_x2: String, g2_y1: String, @@ -77,10 +77,9 @@ fn load_key_from_file(path: &str) -> String { config.privateKey } -fn load_orchestrator_config(path: &str) -> OrchestratorConfig { +fn load_router_config(path: &str) -> RouterConfig { let contents = fs::read_to_string(path).expect("Could not read key file"); - let config: OrchestratorConfig = - serde_json::from_str(&contents).expect("Could not parse key file"); + let config: RouterConfig = serde_json::from_str(&contents).expect("Could not parse key file"); config } @@ -109,11 +108,11 @@ fn configure_identity(matches: &clap::ArgMatches) -> (Bn254, u16) { (signer, port) } -fn configure_orchestrator(matches: &clap::ArgMatches) -> OrchestratorConfig { - let orchestrator_file = matches - .get_one::("orchestrator") - .expect("No orchestrator addr"); - load_orchestrator_config(orchestrator_file) +fn configure_router(matches: &clap::ArgMatches) -> RouterConfig { + let router_file = matches + .get_one::("router") + .expect("No router connection file provided"); + load_router_config(router_file) } async fn get_operator_states() -> Result, Box> { @@ -153,22 +152,22 @@ pub fn main() { .help("Port to run the service on"), ) .arg( - Arg::new("orchestrator") - .long("orchestrator") + Arg::new("router") + .long("router") .required(false) - .help("Path to orchestrator key file"), + .help("Path to the router's public connection file"), ) .get_matches(); // Configure my identity let (signer, port) = configure_identity(&matches); - let orchestrator_config = configure_orchestrator(&matches); + let router_config = configure_router(&matches); // Start runtime runner.start(|context: tokio::Context| async move { let mut recipients: Vec<(PublicKey, Address)> = Vec::new(); // Scoped to avoid configuring two loggers - let orchestrator_pub_key; + let router_pub_key; let quorum_infos; { eigen_logging::init_logger(LogLevel::Debug); @@ -199,35 +198,35 @@ pub fn main() { recipients.push((verifier, Address::from(socket_addr))); } Err(_) => { - panic!("Contributor address not well-formed: {socket}"); + panic!("Operator address not well-formed: {socket}"); } } } } } } - orchestrator_pub_key = PublicKey::create_from_g2_coordinates( - &orchestrator_config.g2_x1, - &orchestrator_config.g2_x2, - &orchestrator_config.g2_y1, - &orchestrator_config.g2_y2, + router_pub_key = PublicKey::create_from_g2_coordinates( + &router_config.g2_x1, + &router_config.g2_x2, + &router_config.g2_y1, + &router_config.g2_y2, ) .unwrap(); - let orchestrator_addr = orchestrator_config + let router_addr = router_config .address .parse::() .unwrap_or(IpAddr::V4(Ipv4Addr::LOCALHOST)); let local_addr = SocketAddr::new( - orchestrator_addr, - orchestrator_config + router_addr, + router_config .port .parse::() .expect("Port not well-formed"), ); - recipients.push((orchestrator_pub_key.clone(), Address::from(local_addr))); + recipients.push((router_pub_key.clone(), Address::from(local_addr))); } tracing::info!(storage_dir = %storage_dir.display(), "engine journal storage directory"); @@ -260,7 +259,7 @@ pub fn main() { // both sides resolve a duplicate to the same G1 key. let operators = &quorum_infos[0].operators; if operators.is_empty() { - panic!("Please provide at least one contributor"); + panic!("Please provide at least one operator"); } let key_map: Map = Map::from_iter_dedup(operators.iter().map(|operator| { @@ -329,7 +328,7 @@ pub fn main() { // are authorized on the channel but must not assign heights). { let task_book_mailbox = task_book_mailbox.clone(); - let router_key = orchestrator_pub_key.clone(); + let router_key = router_pub_key.clone(); let engine_tip = Arc::clone(&engine_tip); let min_report_interval = rebroadcast_interval(); context.child("directives").spawn(move |_| async move { diff --git a/examples/counter/router/src/app.rs b/examples/counter/router/src/app.rs index 89b0d991..cdc09355 100644 --- a/examples/counter/router/src/app.rs +++ b/examples/counter/router/src/app.rs @@ -103,7 +103,7 @@ pub fn main() { let runner = tokio::Runner::new(runtime_cfg); // Parse arguments - let matches = Command::new("orchestrator") + let matches = Command::new("router") .about("generate and verify BN254 Multi-Signatures") .arg( Arg::new("bootstrappers") @@ -198,9 +198,9 @@ pub fn main() { } } // Authorize ourselves too (nodes dial the router from - // public_orchestrator.json; this entry is never dialed by us). - let orchestrator_verifier = signer.public_key(); - recipients.push((orchestrator_verifier, Address::from(my_addr))); + // public_router.json; this entry is never dialed by us). + let router_verifier = signer.public_key(); + recipients.push((router_verifier, Address::from(my_addr))); } let subscriber = tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) @@ -221,12 +221,12 @@ pub fn main() { // different G1 keys cannot misalign the two sides' participant indices. let operators = &quorum_infos[0].operators; if operators.is_empty() { - panic!("Please provide at least one contributor"); + panic!("Please provide at least one operator"); } let key_map: Map = Map::from_iter_dedup(operators.iter().map(|operator| { let keys = operator.pub_keys.as_ref().expect("operator has BLS keys"); - tracing::info!(key = ?keys.g2_pub_key, "registered contributor"); + tracing::info!(key = ?keys.g2_pub_key, "registered operator"); (keys.g2_pub_key.clone(), keys.g1_pub_key.clone()) })); let participants: Set = Set::from_iter_dedup(key_map.iter().cloned()); diff --git a/node/README.md b/node/README.md index 56d2f900..6eaa3b87 100644 --- a/node/README.md +++ b/node/README.md @@ -28,8 +28,8 @@ full task-flow and quorum model. ### Router Connection File -A node locates the router via a JSON file passed to `--orchestrator` carrying -the router's public identity and socket address: +A node locates the router via a JSON file passed to `--router` carrying the +router's public identity and socket address: ```json { @@ -61,7 +61,7 @@ the router's public identity and socket address: ### Running ```bash -cargo run --release -- --key-file operator1.bls.key.json --port 3001 --orchestrator public_orchestrator.json +cargo run --release -- --key-file operator1.bls.key.json --port 3001 --router public_router.json ``` Run one process per operator, each with its own `--key-file` and `--port`. diff --git a/router/README.md b/router/README.md index 97e8bb89..a1f1bf4b 100644 --- a/router/README.md +++ b/router/README.md @@ -65,15 +65,15 @@ Contract addresses are loaded from the deployment JSON file. ### Running ```bash -cargo run -p counter-router --release -- --key-file router_orchestrator.json --port 3000 +cargo run -p counter-router --release -- --key-file router_key.json --port 3000 ``` `--key-file` is the router's own BLS private key (`{"privateKey": "..."}`). `--bootstrappers` optionally takes a comma-separated list of additional peer addresses. Nodes locate the router via a separate file carrying its public identity and socket address (`{g2_x1, g2_x2, g2_y1, g2_y2, address, port}`, -conventionally named `public_orchestrator.json`), passed to each node's -`--orchestrator` flag. +conventionally named `public_router.json`), passed to each node's `--router` +flag. ### Docker diff --git a/router/src/submitter.rs b/router/src/submitter.rs index e45cb1ce..a98ebffc 100644 --- a/router/src/submitter.rs +++ b/router/src/submitter.rs @@ -298,16 +298,16 @@ where // precomputed pubkey hash. let mut operators: Vec> = Vec::with_capacity(participating.len()); let mut misses: Vec<(usize, PublicKey, FixedBytes<32>)> = Vec::new(); - for (index, (contributor, g1_pubkey)) in participating + for (index, (operator, g1_pubkey)) in participating .iter() .zip(participating_g1.iter()) .enumerate() { - match self.operator_cache.get(contributor) { + match self.operator_cache.get(operator) { Some(address) => operators.push(Some(*address)), None => { operators.push(None); - misses.push((index, contributor.clone(), pubkey_hash(g1_pubkey)?)); + misses.push((index, operator.clone(), pubkey_hash(g1_pubkey)?)); } } } @@ -332,11 +332,11 @@ where let resolved = futures::future::join_all(calls.iter().map(|call| call.call().into_future())).await; - for ((index, contributor, _), result) in misses.into_iter().zip(resolved) { + for ((index, operator, _), result) in misses.into_iter().zip(resolved) { let address = result.map_err(|e| { anyhow::anyhow!("Failed to get operator from pubkey hash: {}", e) })?; - self.operator_cache.insert(contributor, address); + self.operator_cache.insert(operator, address); operators[index] = Some(address); } } diff --git a/scripts/README.md b/scripts/README.md index 7e521e7f..8861f20c 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,20 +1,25 @@ # Local Test Scripts -This directory contains scripts for running local version of the BLS signature aggregation system. +This directory contains scripts for running a local end-to-end test of the AVS +stack. ## Overview The test validates the complete end-to-end flow: -1. **Local Blockchain Setup**: Starts a local Ethereum blockchain and deploys EigenLayer contracts -2. **BLS Signature Aggregation**: Runs the orchestrator and 3 contributors -3. **Verification**: Confirms that the counter contract was incremented at least twice through successful signature aggregation +1. **Local Blockchain Setup**: Starts a local Ethereum blockchain and deploys + EigenLayer contracts +2. **BLS Signature Aggregation**: Runs the router and 3 operator nodes +3. **Verification**: Confirms that the counter contract was incremented at + least twice through successful signature aggregation ## Files - `router_e2e_local.sh` - Main integration test script -- `verify_increments.rs` - Rust script that monitors and verifies counter increments -- `Cargo.toml` - Dependencies for the verification script +- `verify_increments.rs` - Rust script that monitors and verifies counter + increments +- `Cargo.toml` - Dependencies for the verification script (package + `commonware-avs-scripts`) ## Running the Test Locally @@ -22,7 +27,6 @@ The test validates the complete end-to-end flow: - Docker - Rust -- All submodules initialized (`git submodule update --init --recursive`) ### Run the Test @@ -32,69 +36,64 @@ The test validates the complete end-to-end flow: ``` The script will: -1. Build the router and node projects +1. Build the verification script 2. Set up environment files for local mode -3. Start Docker containers with local blockchain -4. Start 3 contributors and 1 orchestrator +3. Pull and start Docker Compose services (Ethereum, EigenLayer, signer, 3 + nodes, router) +4. Wait for EigenLayer setup and give the nodes time to initialize 5. Wait for signature aggregation cycles 6. Verify the counter was incremented at least twice -7. Clean up all processes and containers +7. Clean up all containers ### Expected Output ``` -✅ SUCCESS: Counter was incremented 2 times (target: 2) -Total time elapsed: 95.3 seconds ✅ Integration test PASSED! Counter was incremented successfully. ``` ## CI/CD Integration -The test is also automated through GitHub Actions in `.github/workflows/integration-test.yml`. The CI pipeline: - -- Triggers on pushes to `main` and `local-ci` branches -- Runs on Ubuntu with Docker support -- Has a 15-minute timeout -- Provides detailed logs on failure - +The same flow runs in GitHub Actions: +- `.github/workflows/integration-test.yml` — full Docker build, on push/PR to + `main`/`dev`/`staging` +- `.github/workflows/local-integration-test.yml` — pulls prebuilt node images + and runs the router via `cargo run` (no Docker build), on PRs to + `main`/`dev`/`staging` ## Troubleshooting ### Common Issues 1. **Docker containers fail to start** - - Check if ports 8545, 3333, 3334 are available + - Check if ports 8545, 3001-3003, 4000 are available - Ensure Docker daemon is running 2. **Contract deployment timeout** - - Increase timeout in the script + - Increase the timeout in the script - Check Docker logs: `docker compose logs` -3. **Contributors fail to connect** - - Verify keyfiles exist in `eigenlayer-bls-local/.nodes/operator_keys/` +3. **Nodes fail to connect** + - Verify keyfiles exist in `config/.nodes/operator_keys/` - Check network connectivity between processes + 4. **Not Using Funded Private Key** - - Ensure PRIVATE_KEY in .env has sufficient ETH for transactions + - Ensure `PRIVATE_KEY` in `.env` has sufficient ETH for transactions - Check balance: `cast balance $(cast --from-utf8 $(cast --private-key $PRIVATE_KEY))` - Fund if needed: `cast send --private-key $PRIVATE_KEY --value 1ether
` ### Debug Information -The script creates detailed logs in the `logs/` directory: -- `orchestrator.log` - Main orchestrator output -- `contributor1.log`, `contributor2.log`, `contributor3.log` - Individual contributor logs - -On test failure, recent log excerpts are displayed automatically. +On failure, the script prints `docker compose logs` output for the router, +each node, and EigenLayer. ### Manual Verification -You can also run the verification script separately: +You can also run the verification script separately once the stack is running: ```bash -# Start the system manually (follow README steps) -# Then run verification from the project root source .env -cargo run -p avs-scripts --bin verify_increments +export AVS_DEPLOYMENT_PATH="config/.nodes/avs_deploy.json" +cargo run -p commonware-avs-scripts --release --bin verify_increments ``` ## Configuration