datahaven/test/scripts/setup-validators.ts

214 lines
8.1 KiB
TypeScript
Raw Permalink Normal View History

feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
import fs from "node:fs";
import path from "node:path";
import invariant from "tiny-invariant";
test: refactor e2e tests (#365) This PR significantly refactors and improves the end-to-end testing framework and infrastructure. The primary focus was on simplifying the test suites, improving reliability through better resource management, and hardening the relayer infrastructure. All E2E tests are now passing on the CI and demonstrate consistent reliability when run locally. ### Key Changes #### 1. E2E Test Suite Refactor & Cleanup * **Simplified Test Logic**: Heavily refactored the core test suites (`native-token-transfer.test.ts`, `rewards-message.test.ts`, and `validator-set-update.test.ts`). The new implementation is much cleaner, utilizing shared helpers to reduce boilerplate. * **Utility Consolidation**: Removed redundant utility files (`storage.ts`, `rewards-helpers.ts`) and simplified `events.ts`. Event waiting now uses `rxjs` for Substrate and native `viem` watchers for Ethereum, which is more robust and easier to maintain. * **Better Connector Management**: Unified the creation and cleanup of test clients in `ConnectorFactory`. It now handles the lifecycle of WebSocket connections more gracefully, including clearing the `socketClientCache` to prevent reconnection noise during teardown. #### 2. Infrastructure & Stability * **Relayer Relaunch Policy**: Added a restart policy for Snowbridge relayer containers. They are now configured with `--restart on-failure:5`, ensuring that relayers automatically relaunch if they crash during the sensitive initialization phase. * **WebSocket Integration**: * Updated the `ConnectorFactory` to prefer **WebSockets** for the Ethereum public client, which is essential for efficient, event-heavy E2E testing. * Enhanced `launchKurtosisNetwork` to correctly identify and register the Execution Layer's WebSocket endpoint from Kurtosis. * **Disabled Contract Injection**: This PR temporarily disables the automatic injection of contracts into the genesis state by default. * *Reason*: I encountered issues generating a valid `state-diff.json` for the latest contract versions. Even after applying several workarounds, the injected state remained unstable. As a result, I've reverted to manual contract deployment during the launch sequence for better reliability for now. #### 3. Documentation & Maintenance * Removed obsolete documentation (`event-utilities-guide.md`) that no longer reflects the simplified event-handling API. * Cleaned up `test/launcher/validators.ts` and moved logic into more appropriate helpers. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-12-24 12:31:40 +00:00
import { logger, runShellCommandWithLogger } from "../utils/index";
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
interface SetupValidatorsOptions {
rpcUrl: string;
validatorsConfig?: string; // Path to JSON config file with validator addresses
executeSignup?: boolean;
networkName?: string; // Network name for default deployment path
deploymentPath?: string; // Optional custom deployment path
}
/**
* JSON structure for validator configuration
*/
interface ValidatorConfig {
validators: {
publicKey: string;
privateKey: string;
test: Update validator set e2e test (#126) ## Add E2E validator-set update flow - feat: `test/utils/validators.ts` for on-demand validator orchestration. - feat: `test/suites/validator-set-update.test.ts` covering allowlist → register → update. - some minor launcher updates: avoid docker cache, add `--platform` when building datahaven image, avoid sending validator-set update on launch. - Helpers: ABI shortcut in `test/utils/contracts.ts`; config tweaks in `test/configs/validator-set.json`. - Minor cleanup/formatting across `test/launcher/*`, `test/scripts/setup-validators.ts`, and related tests. - added `keepAlive` flag to `BaseTestSuite`, in order to avoid tearing down the network while debugging. Defaults, obviously, to false. - added a `failOnTomeout` option on to waitForDataHavenEvents() so the test fails of the timeout is reached and no event was captured. ### Coverage - The test simulates an scenario in which we have two active authorities (alice and bob), which are running, and registered as operators, which is the normal state after the chain launches. Then: - It launches two more nodes (charlie and dave) - It add the nodes to allowlist and register them as operators - It sends the validator set update message - Checks that the validator update message was propagated through the gateway and arrived the external-validators pallet - Checks that the chain continues producing blocks ### Notes The last test case has a timeout of 10 minutes. This is to respect propagation times of the message through the relayers. We are testing that the external validators pallet actually updated the validator set. Locally, I could expect 5~6 minutes, I just wanted to be on the safe side. CI is passing showing that this was enough indeed. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-10-02 11:23:40 +00:00
solochainAddress?: string;
solochainPrivateKey?: string;
solochainAuthorityName: string;
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
}[];
notes?: string;
}
/**
* Registers validators in EigenLayer based on a configuration file.
* This function reads validator details (public/private keys, optional solochain addresses)
* from a JSON file. If `executeSignup` is true (or confirmed by user prompt),
* it iterates through the configured validators and runs the
* `script/transact/SignUpValidator.s.sol` forge script for each to register them.
* Environment variables `OPERATOR_PRIVATE_KEY`, `OPERATOR_SOLOCHAIN_ADDRESS`, and `NETWORK`
* are set for the forge script execution.
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
*
* @param options - Configuration options for the validator setup process.
* @param options.rpcUrl - The RPC URL for the Ethereum network to interact with.
* @param options.validatorsConfig - Optional path to the JSON file containing validator configurations.
* Defaults to `../configs/validator-set.json` relative to this script.
* @param options.executeSignup - Optional. If true, proceeds with registration. If false, skips.
* If undefined, the user is prompted to confirm registration.
* @param options.networkName - Optional network name used when executing underlying scripts (e.g., for setting the `NETWORK` environment variable).
* Defaults to "anvil".
* @returns A Promise resolving to `true` if the validator registration process was executed
* (for all configured validators), or `false` if the registration was skipped
* (either due to the `executeSignup` option or user declining the prompt).
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
*/
export const setupValidators = async (options: SetupValidatorsOptions): Promise<boolean> => {
const { rpcUrl, validatorsConfig, networkName = "anvil" } = options;
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
// Validate RPC URL
invariant(rpcUrl, "❌ RPC URL is required");
// Load validator configuration - use default path if not specified
const configPath = validatorsConfig || path.resolve(__dirname, "../configs/validator-set.json");
// Ensure the configuration file exists
if (!fs.existsSync(configPath)) {
logger.error(`Validator configuration file not found: ${configPath}`);
throw new Error("Validator configuration file is required");
}
// Load and validate the validator configuration
logger.debug(`Loading validator configuration from ${configPath}`);
let config: ValidatorConfig;
try {
const fileContent = fs.readFileSync(configPath, "utf8");
config = JSON.parse(fileContent);
} catch (error) {
logger.error(`Failed to parse validator config file: ${error}`);
throw new Error("Invalid JSON format in validator configuration file");
}
// Validate the validators array
if (!config.validators || !Array.isArray(config.validators) || config.validators.length === 0) {
logger.error("Invalid validator configuration: 'validators' array is missing or empty");
throw new Error("Validator configuration must contain a non-empty 'validators' array");
}
// Validate each validator entry
for (const [index, validator] of config.validators.entries()) {
if (!validator.publicKey) {
throw new Error(`Validator at index ${index} is missing 'publicKey'`);
}
if (!validator.privateKey) {
throw new Error(`Validator at index ${index} is missing 'privateKey'`);
}
if (!validator.publicKey.startsWith("0x")) {
throw new Error(`Validator publicKey at index ${index} must start with '0x'`);
}
if (!validator.privateKey.startsWith("0x")) {
throw new Error(`Validator privateKey at index ${index} must start with '0x'`);
}
}
test: refactor e2e tests (#365) This PR significantly refactors and improves the end-to-end testing framework and infrastructure. The primary focus was on simplifying the test suites, improving reliability through better resource management, and hardening the relayer infrastructure. All E2E tests are now passing on the CI and demonstrate consistent reliability when run locally. ### Key Changes #### 1. E2E Test Suite Refactor & Cleanup * **Simplified Test Logic**: Heavily refactored the core test suites (`native-token-transfer.test.ts`, `rewards-message.test.ts`, and `validator-set-update.test.ts`). The new implementation is much cleaner, utilizing shared helpers to reduce boilerplate. * **Utility Consolidation**: Removed redundant utility files (`storage.ts`, `rewards-helpers.ts`) and simplified `events.ts`. Event waiting now uses `rxjs` for Substrate and native `viem` watchers for Ethereum, which is more robust and easier to maintain. * **Better Connector Management**: Unified the creation and cleanup of test clients in `ConnectorFactory`. It now handles the lifecycle of WebSocket connections more gracefully, including clearing the `socketClientCache` to prevent reconnection noise during teardown. #### 2. Infrastructure & Stability * **Relayer Relaunch Policy**: Added a restart policy for Snowbridge relayer containers. They are now configured with `--restart on-failure:5`, ensuring that relayers automatically relaunch if they crash during the sensitive initialization phase. * **WebSocket Integration**: * Updated the `ConnectorFactory` to prefer **WebSockets** for the Ethereum public client, which is essential for efficient, event-heavy E2E testing. * Enhanced `launchKurtosisNetwork` to correctly identify and register the Execution Layer's WebSocket endpoint from Kurtosis. * **Disabled Contract Injection**: This PR temporarily disables the automatic injection of contracts into the genesis state by default. * *Reason*: I encountered issues generating a valid `state-diff.json` for the latest contract versions. Even after applying several workarounds, the injected state remained unstable. As a result, I've reverted to manual contract deployment during the launch sequence for better reliability for now. #### 3. Documentation & Maintenance * Removed obsolete documentation (`event-utilities-guide.md`) that no longer reflects the simplified event-handling API. * Cleaned up `test/launcher/validators.ts` and moved logic into more appropriate helpers. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-12-24 12:31:40 +00:00
// Filter to only alice and bob validators
const validatorsToRegister = config.validators.filter((v) =>
["alice", "bob"].includes((v.solochainAuthorityName || "").toLowerCase())
);
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
test: refactor e2e tests (#365) This PR significantly refactors and improves the end-to-end testing framework and infrastructure. The primary focus was on simplifying the test suites, improving reliability through better resource management, and hardening the relayer infrastructure. All E2E tests are now passing on the CI and demonstrate consistent reliability when run locally. ### Key Changes #### 1. E2E Test Suite Refactor & Cleanup * **Simplified Test Logic**: Heavily refactored the core test suites (`native-token-transfer.test.ts`, `rewards-message.test.ts`, and `validator-set-update.test.ts`). The new implementation is much cleaner, utilizing shared helpers to reduce boilerplate. * **Utility Consolidation**: Removed redundant utility files (`storage.ts`, `rewards-helpers.ts`) and simplified `events.ts`. Event waiting now uses `rxjs` for Substrate and native `viem` watchers for Ethereum, which is more robust and easier to maintain. * **Better Connector Management**: Unified the creation and cleanup of test clients in `ConnectorFactory`. It now handles the lifecycle of WebSocket connections more gracefully, including clearing the `socketClientCache` to prevent reconnection noise during teardown. #### 2. Infrastructure & Stability * **Relayer Relaunch Policy**: Added a restart policy for Snowbridge relayer containers. They are now configured with `--restart on-failure:5`, ensuring that relayers automatically relaunch if they crash during the sensitive initialization phase. * **WebSocket Integration**: * Updated the `ConnectorFactory` to prefer **WebSockets** for the Ethereum public client, which is essential for efficient, event-heavy E2E testing. * Enhanced `launchKurtosisNetwork` to correctly identify and register the Execution Layer's WebSocket endpoint from Kurtosis. * **Disabled Contract Injection**: This PR temporarily disables the automatic injection of contracts into the genesis state by default. * *Reason*: I encountered issues generating a valid `state-diff.json` for the latest contract versions. Even after applying several workarounds, the injected state remained unstable. As a result, I've reverted to manual contract deployment during the launch sequence for better reliability for now. #### 3. Documentation & Maintenance * Removed obsolete documentation (`event-utilities-guide.md`) that no longer reflects the simplified event-handling API. * Cleaned up `test/launcher/validators.ts` and moved logic into more appropriate helpers. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-12-24 12:31:40 +00:00
logger.info(`🔎 Registering ${validatorsToRegister.length} validators`);
test: Update validator set e2e test (#126) ## Add E2E validator-set update flow - feat: `test/utils/validators.ts` for on-demand validator orchestration. - feat: `test/suites/validator-set-update.test.ts` covering allowlist → register → update. - some minor launcher updates: avoid docker cache, add `--platform` when building datahaven image, avoid sending validator-set update on launch. - Helpers: ABI shortcut in `test/utils/contracts.ts`; config tweaks in `test/configs/validator-set.json`. - Minor cleanup/formatting across `test/launcher/*`, `test/scripts/setup-validators.ts`, and related tests. - added `keepAlive` flag to `BaseTestSuite`, in order to avoid tearing down the network while debugging. Defaults, obviously, to false. - added a `failOnTomeout` option on to waitForDataHavenEvents() so the test fails of the timeout is reached and no event was captured. ### Coverage - The test simulates an scenario in which we have two active authorities (alice and bob), which are running, and registered as operators, which is the normal state after the chain launches. Then: - It launches two more nodes (charlie and dave) - It add the nodes to allowlist and register them as operators - It sends the validator set update message - Checks that the validator update message was propagated through the gateway and arrived the external-validators pallet - Checks that the chain continues producing blocks ### Notes The last test case has a timeout of 10 minutes. This is to respect propagation times of the message through the relayers. We are testing that the external validators pallet actually updated the validator set. Locally, I could expect 5~6 minutes, I just wanted to be on the safe side. CI is passing showing that this was enough indeed. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-10-02 11:23:40 +00:00
// Iterate through validators to register them
test: refactor e2e tests (#365) This PR significantly refactors and improves the end-to-end testing framework and infrastructure. The primary focus was on simplifying the test suites, improving reliability through better resource management, and hardening the relayer infrastructure. All E2E tests are now passing on the CI and demonstrate consistent reliability when run locally. ### Key Changes #### 1. E2E Test Suite Refactor & Cleanup * **Simplified Test Logic**: Heavily refactored the core test suites (`native-token-transfer.test.ts`, `rewards-message.test.ts`, and `validator-set-update.test.ts`). The new implementation is much cleaner, utilizing shared helpers to reduce boilerplate. * **Utility Consolidation**: Removed redundant utility files (`storage.ts`, `rewards-helpers.ts`) and simplified `events.ts`. Event waiting now uses `rxjs` for Substrate and native `viem` watchers for Ethereum, which is more robust and easier to maintain. * **Better Connector Management**: Unified the creation and cleanup of test clients in `ConnectorFactory`. It now handles the lifecycle of WebSocket connections more gracefully, including clearing the `socketClientCache` to prevent reconnection noise during teardown. #### 2. Infrastructure & Stability * **Relayer Relaunch Policy**: Added a restart policy for Snowbridge relayer containers. They are now configured with `--restart on-failure:5`, ensuring that relayers automatically relaunch if they crash during the sensitive initialization phase. * **WebSocket Integration**: * Updated the `ConnectorFactory` to prefer **WebSockets** for the Ethereum public client, which is essential for efficient, event-heavy E2E testing. * Enhanced `launchKurtosisNetwork` to correctly identify and register the Execution Layer's WebSocket endpoint from Kurtosis. * **Disabled Contract Injection**: This PR temporarily disables the automatic injection of contracts into the genesis state by default. * *Reason*: I encountered issues generating a valid `state-diff.json` for the latest contract versions. Even after applying several workarounds, the injected state remained unstable. As a result, I've reverted to manual contract deployment during the launch sequence for better reliability for now. #### 3. Documentation & Maintenance * Removed obsolete documentation (`event-utilities-guide.md`) that no longer reflects the simplified event-handling API. * Cleaned up `test/launcher/validators.ts` and moved logic into more appropriate helpers. --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
2025-12-24 12:31:40 +00:00
for (const [i, validator] of validatorsToRegister.entries()) {
test: 🐳 Add Docker relay support to CLI (#74) ## Changes - Latest changes to have working relayer :tada: component - Changed spawning snowbridge relayers to docker containers - Small logging output changes - Refactoring to `LaunchedNetwork` class - new flag `--bd` `--build-datahaven` which will build a local docker container which is **much** quicker than the proper CI build (which uses a controlled build enviroment) - new bun script `start:e2e:local`, which is everything that `start:e2e:ci` has, but with building local docker container and log_level debug set --- <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Added support for launching and managing relayer and DataHaven services using Docker containers and networks. - Introduced a CLI option to specify the relayer Docker image tag instead of a binary path. - **Improvements** - Enhanced log messages with clearer text and expressive emojis for better user feedback. - Improved summary display by removing relayer services from the output. - Updated build scripts to consistently enable the "fast-runtime" feature for cross-platform builds. - Refined validation and error reporting for checkpoint data parsing. - **Bug Fixes** - Improved Docker container cleanup and network management during service launch and teardown. - **Chores** - Updated and refactored npm scripts for Docker operations and end-to-end test cleanup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-18 23:31:46 +00:00
logger.info(`🔧 Setting up validator ${i} (${validator.publicKey})`);
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
const env = {
...process.env,
NETWORK: networkName,
// OPERATOR_PRIVATE_KEY is what the script reads to set the operator
OPERATOR_PRIVATE_KEY: validator.privateKey,
// OPERATOR_SOLOCHAIN_ADDRESS is the validator's address on the substrate chain
OPERATOR_SOLOCHAIN_ADDRESS: validator.solochainAddress || ""
};
// Prepare command to register validator
test: ⚡️ CI Refactor (#59) Eventually our CI will be required to run two private blockchains locally plus associated relayers. This PR is to prepare for this fate by improving run times and refactoring our existing CIs so they are a bit easier to reason about. ### Refactors - **_We now run ALL CIs on every PR!_** This is so that we decomplexify the logic around conditional builds and fetching built binaries from another source. This reduces the surface area of code we have to maintain at the cost of execution time - This penalty is ameliorated by a layered caching system. At best, it will be less than a minute to complete a build since everything will be cached. On GH runners this is about 6 minutes sadly. - We will no longer be at risk of important CIs being skipped erroneously which hide true failures. - Caching is a low-risk approach because at worst it has to build from scratch. A bad cache hit will never imply the wrong thing gets build since cargo is smart enough to just throw away any inappropriate build artefacts. - `setup-rust` action created so we have a unified way of setting up runner and unifying our approach to caching - Use a unique caching key for different activities and it will fallback to shared cache if no matches - we are using `mainnet` kurtosis config so that it works with relayer assumptions ### Additions - We can specify the ethereum block time via a new cli arg `--slot-time <seconds>` - We can specify arbitrary network_param args which get passed into the generated yaml - e.g. giving `bun cli --kurtosis-network-args="pet=cat food=fish" will add: ```yml network_params: # existing params... pet: cat food: fish ``` - We now have the ability to programmatically modify the yaml - This means we are back down to a single `minimal.yml` kurtosis config so we dont have to maintain changes between them - Flow is: `add new cli arg` -> `add if() block which mutates yaml` -> `profit` --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-06 20:20:02 +00:00
const signupCommand = `forge script script/transact/SignUpValidator.s.sol --rpc-url ${rpcUrl} --broadcast --no-rpc-rate-limit --non-interactive`;
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
logger.debug(`Running command: ${signupCommand}`);
await runShellCommandWithLogger(signupCommand, { env, cwd: "../contracts", logLevel: "debug" });
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
logger.success(`Successfully registered validator ${validator.publicKey}`);
}
feat: implement weighted top-32 validator selection (#443) ## Overview Implements deterministic weighted-stake-based validator selection in `DataHavenServiceManager`, building on the era-targeting submitter model from PR #433. Previously, `buildNewValidatorSetMessage()` forwarded all registered operators in arbitrary membership order with no stake-based ranking, meaning high-stake operators could be displaced by lower-stake ones when downstream caps applied. This PR fixes that by computing a weighted stake score per operator and selecting the top-32 candidates before bridging the set to DataHaven. Spec: `specs/validator-set-selection/validator-set-selection.md` ## Contract Changes (`DataHavenServiceManager.sol`) **New state:** - `MAX_ACTIVE_VALIDATORS = 32` — cap on the outbound validator set - `mapping(IStrategy => uint96) public strategiesAndMultipliers` — per-strategy weight used in the selection formula **Updated `buildNewValidatorSetMessage()`:** 1. Fetches allocated stake for all operators × strategies from `AllocationManager` 2. Computes `weightedStake(op) = Σ(allocatedStake[op][j] × multiplier[j])` across all strategies 3. Filters operators with no solochain address mapping or zero weighted stake 4. Runs a partial selection sort to pick the top `min(candidateCount, 32)` by descending weighted stake; ties broken by lower operator address (deterministic) 5. Reverts with `EmptyValidatorSet()` if no eligible candidates remain **Admin API changes:** - `addStrategiesToValidatorsSupportedStrategies()` signature changed from `IStrategy[]` to `IRewardsCoordinatorTypes.StrategyAndMultiplier[]` — strategy and multiplier are stored atomically in one call, eliminating the risk of a strategy being registered without a multiplier - New `setStrategiesAndMultipliers(StrategyAndMultiplier[])` — updates multiplier weights for existing strategies without touching the EigenLayer strategy set - New `getStrategiesAndMultipliers()` — returns all strategies with their current multipliers - `removeStrategiesFromValidatorsSupportedStrategies()` now cleans up multiplier entries on removal **New error / event:** - `EmptyValidatorSet()` — reverts when no eligible candidates exist - `StrategiesAndMultipliersSet(StrategyAndMultiplier[])` — emitted on add or update of multipliers ## Tests (`ValidatorSetSelection.t.sol`) New 552-line Foundry test suite covering all cases from the spec: | Case | |------| | `addStrategies` stores multiplier atomically | | `removeStrategies` deletes multiplier | | `setStrategiesAndMultipliers` updates without touching the strategy set | | `getStrategiesAndMultipliers` returns correct pairs | | Weighted stake computed correctly across multiple strategies | | Operators with zero weighted stake are excluded | | Unset multiplier treated as 0 | | Top-32 selection when candidate count > 32 | | All candidates included when count < 32 | | Tie-breaking by lower operator address | | `EmptyValidatorSet` revert when no eligible operators | ## Deploy Scripts - **`DeployBase.s.sol`**: Sets a default multiplier of `1` for all configured validator strategies after AVS registration via `setStrategiesAndMultipliers` - **New `AllocateOperatorStake.s.sol`**: Forge script that allocates full magnitude (`1e18`) to the validator operator set for a given operator. Must be run at least one block after `SignUpValidator` to respect EigenLayer's allocation configuration delay. ## E2E Framework - **`validators.ts` — `registerOperator()`**: Extended to deposit tokens into each deployed strategy and allocate full magnitude to the DataHaven operator set after registration. Previously operators registered without staking, producing zero weighted stake and getting filtered out by the new selection logic. - **`setup-validators.ts`**: Added a stake allocation pass after the registration loop, invoking `AllocateOperatorStake.s.sol` per validator. - **`validator-set-update.test.ts`**: Added debug logging for transaction receipts and the `OutboundMessageAccepted` / `ExternalValidatorsSet` events. - **`generated.ts`**: Regenerated contract bindings to include new functions, events, and the `EmptyValidatorSet` error. ## ⚠️ Breaking Changes ⚠️ - `addStrategiesToValidatorsSupportedStrategies(IStrategy[])` → `addStrategiesToValidatorsSupportedStrategies(StrategyAndMultiplier[])`: callers must supply multipliers alongside strategies. - Operators with zero weighted stake are no longer included in the bridged validator set. ## Rollout Notes 1. PR #433 (era-targeting + submitter role) must be deployed first 2. Deploy this `ServiceManager` upgrade 3. Confirm `strategiesAndMultipliers` is set for all active strategies (default multiplier `1` applied automatically by `DeployBase`) 4. Deploy the runtime cap-enforcement changes (spec section 10.2) 5. Submitter daemon requires no changes — continues submitting `targetEra = ActiveEra + 1`
2026-02-24 08:23:57 +00:00
// Allocate stake for each validator (must run in a separate script because
// the allocation delay needs at least 1 block after registerAsOperator)
logger.info("📊 Allocating operator stake...");
for (const [i, validator] of validatorsToRegister.entries()) {
logger.info(`📊 Allocating stake for validator ${i} (${validator.publicKey})`);
const env = {
...process.env,
NETWORK: networkName,
OPERATOR_PRIVATE_KEY: validator.privateKey,
OPERATOR_SOLOCHAIN_ADDRESS: validator.solochainAddress || ""
};
const allocateCommand = `forge script script/transact/AllocateOperatorStake.s.sol --rpc-url ${rpcUrl} --broadcast --no-rpc-rate-limit --non-interactive`;
await runShellCommandWithLogger(allocateCommand, {
env,
cwd: "../contracts",
logLevel: "debug"
});
logger.success(`Successfully allocated stake for validator ${validator.publicKey}`);
}
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
return true;
};
// Allow script to be run directly with CLI arguments
if (import.meta.main) {
const args = process.argv.slice(2);
const options: {
rpcUrl?: string;
validatorsConfig?: string;
executeSignup?: boolean;
networkName?: string;
deploymentPath?: string;
} = {
executeSignup: args.includes("--no-signup") ? false : undefined,
networkName: "anvil" // Default network name
};
// Extract RPC URL
const rpcUrlIndex = args.indexOf("--rpc-url");
if (rpcUrlIndex !== -1 && rpcUrlIndex + 1 < args.length) {
options.rpcUrl = args[rpcUrlIndex + 1];
}
// Extract validators config path
const configIndex = args.indexOf("--config");
if (configIndex !== -1 && configIndex + 1 < args.length) {
options.validatorsConfig = args[configIndex + 1];
}
// Extract network name
const networkIndex = args.indexOf("--network");
if (networkIndex !== -1 && networkIndex + 1 < args.length) {
options.networkName = args[networkIndex + 1];
}
// Extract custom deployment path
const deploymentPathIndex = args.indexOf("--deployment-path");
if (deploymentPathIndex !== -1 && deploymentPathIndex + 1 < args.length) {
options.deploymentPath = args[deploymentPathIndex + 1];
}
// Parse signup flag
if (args.includes("--signup")) {
options.executeSignup = true;
}
// Check required parameters
if (!options.rpcUrl) {
console.error("Error: --rpc-url parameter is required");
process.exit(1);
}
// Run setup
setupValidators({
rpcUrl: options.rpcUrl,
validatorsConfig: options.validatorsConfig,
executeSignup: options.executeSignup,
networkName: options.networkName,
deploymentPath: options.deploymentPath
}).catch((error) => {
console.error("Validator setup failed:", error);
process.exit(1);
});
}