mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 01:38:32 +00:00
Merge branch 'main' into feat/add-validator-submitter-ci-job
This commit is contained in:
commit
6971df2ee1
24 changed files with 115 additions and 102 deletions
|
|
@ -35,7 +35,7 @@
|
|||
"randaoCommitExpiration": 24,
|
||||
"minNumRequiredSignatures": 2,
|
||||
"startBlock": 1,
|
||||
"rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"messageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"initialValidatorSetId": 0,
|
||||
"initialValidatorHashes": [
|
||||
"0xaeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7",
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@
|
|||
/// Initial BEEFY block number. Set to latest finalized block by update-beefy-checkpoint.
|
||||
/// The BeefyClient will only accept BEEFY commitments with block numbers > startBlock.
|
||||
"startBlock": 1,
|
||||
/// The origin linked to the Rewards Agent, the Agent contract who's allowed to submit
|
||||
/// new reward merkle roots to the RewardsRegistry contract.
|
||||
"rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
/// The origin linked to the Agent, the Agent contract who's allowed to submit
|
||||
/// new reward merkle roots or slashes.
|
||||
"messageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
/// The BEEFY validator set ID for the initial validators.
|
||||
/// This is fetched from Beefy.ValidatorSetId on the DataHaven chain.
|
||||
"initialValidatorSetId": 0,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
"randaoCommitExpiration": 24,
|
||||
"minNumRequiredSignatures": 16,
|
||||
"startBlock": 1,
|
||||
"rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"messageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"initialValidatorSetId": 0,
|
||||
"initialValidatorHashes": [],
|
||||
"nextValidatorSetId": 1,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
"randaoCommitExpiration": 24,
|
||||
"minNumRequiredSignatures": 3,
|
||||
"startBlock": 1303065,
|
||||
"rewardsMessageOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd",
|
||||
"messageOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd",
|
||||
"initialValidatorSetId": 2186,
|
||||
"initialValidatorHashes": [
|
||||
"0x07ce4f2cd558f4d4b529a3362b6ff7d616ca0893b53252dc62829b8218ea5c10",
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
"randaoCommitExpiration": 24,
|
||||
"minNumRequiredSignatures": 5,
|
||||
"startBlock": 1381173,
|
||||
"rewardsMessageOrigin": "0xd0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215",
|
||||
"messageOrigin": "0xd0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215",
|
||||
"initialValidatorSetId": 2303,
|
||||
"initialValidatorHashes": [
|
||||
"0x0ec3102f334aba804c18b843e45ec874005587122a1b49273b1b04d6fd98b1a2",
|
||||
|
|
|
|||
1
contracts/deployments/anvil-agent-info.json
Normal file
1
contracts/deployments/anvil-agent-info.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"Agent": "0xac06641381166cf085281c45292147f833C622d7","AgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
|
|
@ -1 +1 @@
|
|||
{"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7","RewardsAgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
{"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7","AgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
|
|
@ -1 +1 @@
|
|||
{"RewardsAgent": "0x2E039a88838241d1Ac738cf2e3C5763ba12571e7","RewardsAgentOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd"}
|
||||
{"RewardsAgent": "0x2E039a88838241d1Ac738cf2e3C5763ba12571e7","AgentOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd"}
|
||||
|
|
@ -12,7 +12,7 @@ contract Config {
|
|||
bytes32[] initialValidatorHashes;
|
||||
uint128 nextValidatorSetId;
|
||||
bytes32[] nextValidatorHashes;
|
||||
bytes32 rewardsMessageOrigin;
|
||||
bytes32 messageOrigin;
|
||||
}
|
||||
|
||||
// AVS parameters
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
BeefyClient beefyClient,
|
||||
AgentExecutor agentExecutor,
|
||||
IGatewayV2 gateway,
|
||||
address payable rewardsAgentAddress
|
||||
address payable agentAddress
|
||||
) = _deploySnowbridge(snowbridgeConfig);
|
||||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
|
@ -132,14 +132,14 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
(
|
||||
DataHavenServiceManager serviceManager,
|
||||
DataHavenServiceManager serviceManagerImplementation
|
||||
) = _deployDataHavenContracts(avsConfig, proxyAdmin, gateway);
|
||||
) = _deployDataHavenContracts(avsConfig, proxyAdmin, gateway, agentAddress);
|
||||
|
||||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
// Final configuration (same for both modes)
|
||||
Logging.logHeader("FINAL CONFIGURATION");
|
||||
Logging.logContractDeployed("Rewards Agent Address", rewardsAgentAddress);
|
||||
Logging.logContractDeployed("Agent Address", agentAddress);
|
||||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
|
|
@ -150,11 +150,11 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
gateway,
|
||||
serviceManager,
|
||||
serviceManagerImplementation,
|
||||
rewardsAgentAddress,
|
||||
agentAddress,
|
||||
proxyAdmin
|
||||
);
|
||||
|
||||
_outputRewardsAgentInfo(rewardsAgentAddress, snowbridgeConfig.rewardsMessageOrigin);
|
||||
_outputAgentInfo(agentAddress, snowbridgeConfig.messageOrigin);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,11 +201,11 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
// Create Agent
|
||||
Logging.logSection("Creating Snowbridge Agent");
|
||||
vm.broadcast(_deployerPrivateKey);
|
||||
gateway.v2_createAgent(config.rewardsMessageOrigin);
|
||||
address payable rewardsAgentAddress = payable(gateway.agentOf(config.rewardsMessageOrigin));
|
||||
Logging.logContractDeployed("Rewards Agent", rewardsAgentAddress);
|
||||
gateway.v2_createAgent(config.messageOrigin);
|
||||
address payable agentAddress = payable(gateway.agentOf(config.messageOrigin));
|
||||
Logging.logContractDeployed("Rewards Agent", agentAddress);
|
||||
|
||||
return (beefyClient, agentExecutor, gateway, rewardsAgentAddress);
|
||||
return (beefyClient, agentExecutor, gateway, agentAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,7 +240,8 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
function _deployDataHavenContracts(
|
||||
AVSConfig memory avsConfig,
|
||||
ProxyAdmin proxyAdmin,
|
||||
IGatewayV2 gateway
|
||||
IGatewayV2 gateway,
|
||||
address agentAddress
|
||||
) internal returns (DataHavenServiceManager, DataHavenServiceManager) {
|
||||
Logging.logHeader("DATAHAVEN CUSTOM CONTRACTS DEPLOYMENT");
|
||||
|
||||
|
|
@ -269,7 +270,7 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
// Create service manager initialisation parameters struct
|
||||
ServiceManagerInitParams memory initParams = ServiceManagerInitParams({
|
||||
avsOwner: avsConfig.avsOwner,
|
||||
rewardsInitiator: avsConfig.rewardsInitiator,
|
||||
rewardsInitiator: agentAddress,
|
||||
validatorsStrategiesAndMultipliers: strategiesAndMultipliers,
|
||||
gateway: address(gateway),
|
||||
validatorSetSubmitter: avsConfig.validatorSetSubmitter,
|
||||
|
|
@ -313,38 +314,38 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
IGatewayV2 gateway,
|
||||
DataHavenServiceManager serviceManager,
|
||||
DataHavenServiceManager serviceManagerImplementation,
|
||||
address rewardsAgent,
|
||||
address agent,
|
||||
ProxyAdmin proxyAdmin
|
||||
) internal virtual;
|
||||
|
||||
/**
|
||||
* @notice Output rewards agent info (shared across all deployment types)
|
||||
* @notice Output agent info (shared across all deployment types)
|
||||
*/
|
||||
function _outputRewardsAgentInfo(
|
||||
address rewardsAgent,
|
||||
bytes32 rewardsAgentOrigin
|
||||
function _outputAgentInfo(
|
||||
address agent,
|
||||
bytes32 agentOrigin
|
||||
) internal {
|
||||
Logging.logHeader("REWARDS AGENT INFO");
|
||||
Logging.logContractDeployed("RewardsAgent", rewardsAgent);
|
||||
Logging.logAgentOrigin("RewardsAgentOrigin", vm.toString(rewardsAgentOrigin));
|
||||
Logging.logHeader("AGENT INFO");
|
||||
Logging.logContractDeployed("Agent", agent);
|
||||
Logging.logAgentOrigin("AgentOrigin", vm.toString(agentOrigin));
|
||||
Logging.logFooter();
|
||||
|
||||
// Write to deployment file for future reference
|
||||
string memory network = _getNetworkName();
|
||||
string memory rewardsInfoPath =
|
||||
string.concat(vm.projectRoot(), "/deployments/", network, "-rewards-info.json");
|
||||
string memory agentInfoPath =
|
||||
string.concat(vm.projectRoot(), "/deployments/", network, "-agent-info.json");
|
||||
|
||||
// Create directory if it doesn't exist
|
||||
vm.createDir(string.concat(vm.projectRoot(), "/deployments"), true);
|
||||
|
||||
// Create JSON with rewards info
|
||||
string memory json = "{";
|
||||
json = string.concat(json, '"RewardsAgent": "', vm.toString(rewardsAgent), '",');
|
||||
json = string.concat(json, '"RewardsAgentOrigin": "', vm.toString(rewardsAgentOrigin), '"');
|
||||
json = string.concat(json, '"Agent": "', vm.toString(agent), '",');
|
||||
json = string.concat(json, '"AgentOrigin": "', vm.toString(agentOrigin), '"');
|
||||
json = string.concat(json, "}");
|
||||
|
||||
// Write to file
|
||||
vm.writeFile(rewardsInfoPath, json);
|
||||
Logging.logInfo(string.concat("Rewards info saved to: ", rewardsInfoPath));
|
||||
vm.writeFile(agentInfoPath, json);
|
||||
Logging.logInfo(string.concat("Agent info saved to: ", agentInfoPath));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ contract DeployParams is Script, Config {
|
|||
config.minNumRequiredSignatures =
|
||||
vm.parseJsonUint(configJson, ".snowbridge.minNumRequiredSignatures");
|
||||
config.startBlock = vm.parseJsonUint(configJson, ".snowbridge.startBlock").toUint64();
|
||||
config.rewardsMessageOrigin =
|
||||
vm.parseJsonBytes32(configJson, ".snowbridge.rewardsMessageOrigin");
|
||||
config.messageOrigin = vm.parseJsonBytes32(configJson, ".snowbridge.messageOrigin");
|
||||
|
||||
// Load validators from file or generate placeholder ones in dev mode
|
||||
bool isDevMode = keccak256(abi.encodePacked(vm.envOr("DEV_MODE", string("false"))))
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,7 @@ impl datahaven_runtime_common::rewards_adapter::RewardsSubmissionConfig for Main
|
|||
}
|
||||
|
||||
fn rewards_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
}
|
||||
|
||||
fn strategies_and_multipliers() -> Vec<(H160, u128)> {
|
||||
|
|
@ -1692,9 +1692,9 @@ impl datahaven_runtime_common::slashes_adapter::SlashesSubmissionConfig for Main
|
|||
runtime_params::dynamic_params::runtime_config::DatahavenServiceManagerAddress::get()
|
||||
}
|
||||
|
||||
// TODO: remove `slashes_` prefix and just call it `agent_origin`
|
||||
fn slashes_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
// TODO: Can we use the same as reward and just rename the config to `AgentOrigin` ?
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
}
|
||||
|
||||
fn strategies() -> Vec<Address> {
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ pub mod dynamic_params {
|
|||
|
||||
#[codec(index = 3)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The RewardsAgentOrigin is the hash of the string "external_validators_rewards"
|
||||
/// The AgentOrigin is the hash of the string "external_validators_rewards"
|
||||
/// TODO: Decide which agent origin we want to use. Currently for testing it's the zero hash
|
||||
pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
pub static AgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
"c505dfb2df107d106d08bd0f1a0acd10052ca9aa078629a4ccfd0c90c6e69b65"
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -1514,7 +1514,7 @@ impl datahaven_runtime_common::rewards_adapter::RewardsSubmissionConfig for Stag
|
|||
}
|
||||
|
||||
fn rewards_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
}
|
||||
|
||||
fn strategies_and_multipliers() -> Vec<(H160, u128)> {
|
||||
|
|
@ -1689,7 +1689,7 @@ impl datahaven_runtime_common::slashes_adapter::SlashesSubmissionConfig for Stag
|
|||
}
|
||||
|
||||
fn slashes_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
// TODO: Can we use the same as reward and just rename the config to `AgentOrigin` ?
|
||||
}
|
||||
|
||||
|
|
@ -1951,8 +1951,8 @@ mod tests {
|
|||
/// Test that the Rewards Agent ID (used for Snowbridge outbound messages from the rewards pallet)
|
||||
/// is correctly computed from the chain's genesis hash and the ExternalValidatorRewardsAccount.
|
||||
///
|
||||
/// This test verifies the value that should be set as `RewardsAgentOrigin` in runtime parameters
|
||||
/// and as `rewardsMessageOrigin` in the AVS contract configuration.
|
||||
/// This test verifies the value that should be set as `AgentOrigin` in runtime parameters
|
||||
/// and as `messageOrigin` in the AVS contract configuration.
|
||||
///
|
||||
/// The Agent ID is computed following Snowbridge's pattern for GlobalConsensus locations:
|
||||
/// blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), compact_len, "AccountKey20", account_key))
|
||||
|
|
@ -1992,8 +1992,8 @@ mod tests {
|
|||
// Hash with blake2_256
|
||||
let computed_agent_id = H256(blake2_256(&encoded));
|
||||
|
||||
// Expected Agent ID - this value must match RewardsAgentOrigin in runtime_params.rs
|
||||
// If this test fails, update RewardsAgentOrigin to match the computed value.
|
||||
// Expected Agent ID - this value must match AgentOrigin in runtime_params.rs
|
||||
// If this test fails, update AgentOrigin to match the computed value.
|
||||
let expected_agent_id = H256(hex_literal::hex!(
|
||||
"56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd"
|
||||
));
|
||||
|
|
@ -2003,8 +2003,8 @@ mod tests {
|
|||
expected_agent_id,
|
||||
"Computed Rewards Agent ID must match expected value.\n\
|
||||
This value should be set as:\n\
|
||||
- RewardsAgentOrigin in runtime_params.rs\n\
|
||||
- rewardsMessageOrigin in AVS contract config\n\
|
||||
- AgentOrigin in runtime_params.rs\n\
|
||||
- messageOrigin in AVS contract config\n\
|
||||
\n\
|
||||
Rewards account: 0x{}\n\
|
||||
Genesis hash: 0x{}\n\
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ pub mod dynamic_params {
|
|||
|
||||
#[codec(index = 3)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The RewardsAgentOrigin is the Agent ID for the rewards pallet's outbound Snowbridge messages.
|
||||
/// The AgentOrigin is the Agent ID for the rewards/slashes pallet's outbound Snowbridge messages.
|
||||
/// Computed as: blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), interior))
|
||||
/// where interior = SCALE_ENCODE("AccountKey20", ExternalValidatorRewardsAccount)
|
||||
///
|
||||
/// For stagenet with genesis hash 0x72d0856fd339e09cb21df7bac8ac3120bd871e327ec0e1658395df68acef9bee
|
||||
/// and rewards account 0x6d6f646c64682f65767265770000000000000000 (from PalletId "dh/evrew"):
|
||||
pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
pub static AgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
"56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd"
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,7 @@ impl datahaven_runtime_common::rewards_adapter::RewardsSubmissionConfig for Test
|
|||
}
|
||||
|
||||
fn rewards_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
}
|
||||
|
||||
fn strategies_and_multipliers() -> Vec<(H160, u128)> {
|
||||
|
|
@ -1693,8 +1693,7 @@ impl datahaven_runtime_common::slashes_adapter::SlashesSubmissionConfig for Test
|
|||
}
|
||||
|
||||
fn slashes_agent_origin() -> H256 {
|
||||
runtime_params::dynamic_params::runtime_config::RewardsAgentOrigin::get()
|
||||
// TODO: Can we use the same as reward and just rename the config to `AgentOrigin` ?
|
||||
runtime_params::dynamic_params::runtime_config::AgentOrigin::get()
|
||||
}
|
||||
|
||||
fn strategies() -> Vec<Address> {
|
||||
|
|
@ -1973,8 +1972,8 @@ mod tests {
|
|||
/// Test that the Rewards Agent ID (used for Snowbridge outbound messages from the rewards pallet)
|
||||
/// is correctly computed from the chain's genesis hash and the ExternalValidatorRewardsAccount.
|
||||
///
|
||||
/// This test verifies the value that should be set as `RewardsAgentOrigin` in runtime parameters
|
||||
/// and as `rewardsMessageOrigin` in the AVS contract configuration.
|
||||
/// This test verifies the value that should be set as `AgentOrigin` in runtime parameters
|
||||
/// and as `messageOrigin` in the AVS contract configuration.
|
||||
///
|
||||
/// The Agent ID is computed following Snowbridge's pattern for GlobalConsensus locations:
|
||||
/// blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), compact_len, "AccountKey20", account_key))
|
||||
|
|
@ -2014,8 +2013,8 @@ mod tests {
|
|||
// Hash with blake2_256
|
||||
let computed_agent_id = H256(blake2_256(&encoded));
|
||||
|
||||
// Expected Agent ID - this value must match RewardsAgentOrigin in runtime_params.rs
|
||||
// If this test fails, update RewardsAgentOrigin to match the computed value.
|
||||
// Expected Agent ID - this value must match AgentOrigin in runtime_params.rs
|
||||
// If this test fails, update AgentOrigin to match the computed value.
|
||||
let expected_agent_id = H256(hex_literal::hex!(
|
||||
"d0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215"
|
||||
));
|
||||
|
|
@ -2025,8 +2024,8 @@ mod tests {
|
|||
expected_agent_id,
|
||||
"Computed Rewards Agent ID must match expected value.\n\
|
||||
This value should be set as:\n\
|
||||
- RewardsAgentOrigin in runtime_params.rs\n\
|
||||
- rewardsMessageOrigin in AVS contract config\n\
|
||||
- AgentOrigin in runtime_params.rs\n\
|
||||
- messageOrigin in AVS contract config\n\
|
||||
\n\
|
||||
Rewards account: 0x{}\n\
|
||||
Genesis hash: 0x{}\n\
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ pub mod dynamic_params {
|
|||
|
||||
#[codec(index = 3)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
/// The RewardsAgentOrigin is the Agent ID for the rewards pallet's outbound Snowbridge messages.
|
||||
/// The AgentOrigin is the Agent ID for the rewards/slashes pallet's outbound Snowbridge messages.
|
||||
/// Computed as: blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), interior))
|
||||
/// where interior = SCALE_ENCODE("AccountKey20", ExternalValidatorRewardsAccount)
|
||||
///
|
||||
/// For testnet with genesis hash 0xdbf403d348916fb0694485bc7f9c0d8c53fdf86664ebac019af209c090c3df99
|
||||
/// and rewards account 0x6d6f646c64682f65767265770000000000000000 (from PalletId "dh/evrew"):
|
||||
pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
pub static AgentOrigin: H256 = H256::from_slice(&hex!(
|
||||
"d0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215"
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "0.1.0-autogenerated.18296316742446681711",
|
||||
"version": "0.1.0-autogenerated.15484599658830368838",
|
||||
"name": "@polkadot-api/descriptors",
|
||||
"files": [
|
||||
"dist"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -48,7 +48,7 @@ const palletIdToAccountId20 = (palletId: string): Hex => {
|
|||
* blake2_256(SCALE_ENCODE(("GlobalConsensus", ByGenesis(genesis_hash), ("AccountKey20", account_key))))
|
||||
*
|
||||
* NOTE: This computation follows Snowbridge's pattern but may need verification against
|
||||
* the actual on-chain Agent ID. The preferred approach is to set RewardsAgentOrigin on
|
||||
* the actual on-chain Agent ID. The preferred approach is to set AgentOrigin on
|
||||
* the chain and fetch it via this command.
|
||||
*
|
||||
* @param genesisHash - The chain's genesis hash (32 bytes, hex string with 0x prefix)
|
||||
|
|
@ -116,36 +116,36 @@ const computeAgentId = async (genesisHash: Hex, accountKey20: Hex): Promise<Hex>
|
|||
};
|
||||
|
||||
/**
|
||||
* Fetches the RewardsAgentOrigin from the runtime parameters.
|
||||
* Fetches the AgentOrigin from the runtime parameters.
|
||||
*
|
||||
* @param rpcUrl - WebSocket RPC endpoint of the DataHaven chain
|
||||
* @returns The RewardsAgentOrigin as a hex string, or null if not set or zero
|
||||
* @returns The AgentOrigin as a hex string, or null if not set or zero
|
||||
*/
|
||||
const fetchRewardsAgentOrigin = async (rpcUrl: string): Promise<Hex | null> => {
|
||||
const fetchAgentOrigin = async (rpcUrl: string): Promise<Hex | null> => {
|
||||
logger.info(`📡 Connecting to DataHaven chain at ${rpcUrl}...`);
|
||||
|
||||
const { client: papiClient, typedApi: dhApi } = createPapiConnectors(rpcUrl);
|
||||
|
||||
try {
|
||||
logger.info("🔍 Fetching RewardsAgentOrigin from runtime parameters...");
|
||||
logger.info("🔍 Fetching AgentOrigin from runtime parameters...");
|
||||
|
||||
// Query the Parameters pallet for RewardsAgentOrigin
|
||||
// Query the Parameters pallet for AgentOrigin
|
||||
const parameter = await dhApi.query.Parameters.Parameters.getValue(
|
||||
{
|
||||
type: "RuntimeConfig",
|
||||
value: { type: "RewardsAgentOrigin", value: undefined }
|
||||
value: { type: "AgentOrigin", value: undefined }
|
||||
},
|
||||
{ at: "best" }
|
||||
);
|
||||
|
||||
if (!parameter) {
|
||||
logger.info("ℹ️ RewardsAgentOrigin parameter not found (using default)");
|
||||
logger.info("ℹ️ AgentOrigin parameter not found (using default)");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract the value from the parameter result
|
||||
// The parameter is wrapped in the RuntimeConfig enum variant
|
||||
if (parameter.type === "RuntimeConfig" && parameter.value.type === "RewardsAgentOrigin") {
|
||||
if (parameter.type === "RuntimeConfig" && parameter.value.type === "AgentOrigin") {
|
||||
const origin = parameter.value.value;
|
||||
if (origin) {
|
||||
const originHex = origin.asHex();
|
||||
|
|
@ -153,15 +153,15 @@ const fetchRewardsAgentOrigin = async (rpcUrl: string): Promise<Hex | null> => {
|
|||
const zeroHash =
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000" as Hex;
|
||||
if (originHex === zeroHash) {
|
||||
logger.info("ℹ️ RewardsAgentOrigin is set to zero (placeholder)");
|
||||
logger.info("ℹ️ AgentOrigin is set to zero (placeholder)");
|
||||
return null;
|
||||
}
|
||||
logger.success(`Found RewardsAgentOrigin: ${originHex}`);
|
||||
logger.success(`Found AgentOrigin: ${originHex}`);
|
||||
return originHex as Hex;
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("ℹ️ RewardsAgentOrigin value not available");
|
||||
logger.info("ℹ️ AgentOrigin value not available");
|
||||
return null;
|
||||
} finally {
|
||||
papiClient.destroy();
|
||||
|
|
@ -193,9 +193,9 @@ const fetchGenesisHash = async (rpcUrl: string): Promise<Hex> => {
|
|||
* Updates the config file with the rewards message origin.
|
||||
*
|
||||
* @param networkId - The network identifier (e.g., "hoodi", "stagenet-hoodi")
|
||||
* @param rewardsMessageOrigin - The rewards message origin (Agent ID)
|
||||
* @param messageOrigin - The rewards message origin (Agent ID)
|
||||
*/
|
||||
const updateConfigFile = async (networkId: string, rewardsMessageOrigin: Hex): Promise<void> => {
|
||||
const updateConfigFile = async (networkId: string, messageOrigin: Hex): Promise<void> => {
|
||||
const configFilePath = `../contracts/config/${networkId}.json`;
|
||||
const configFile = Bun.file(configFilePath);
|
||||
|
||||
|
|
@ -211,21 +211,21 @@ const updateConfigFile = async (networkId: string, rewardsMessageOrigin: Hex): P
|
|||
configJson.snowbridge = {};
|
||||
}
|
||||
|
||||
const oldOrigin = configJson.snowbridge.rewardsMessageOrigin;
|
||||
configJson.snowbridge.rewardsMessageOrigin = rewardsMessageOrigin;
|
||||
const oldOrigin = configJson.snowbridge.messageOrigin;
|
||||
configJson.snowbridge.messageOrigin = messageOrigin;
|
||||
|
||||
await Bun.write(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`);
|
||||
|
||||
logger.success(`Config file updated: ${configFilePath}`);
|
||||
|
||||
if (oldOrigin !== rewardsMessageOrigin) {
|
||||
logger.info(` rewardsMessageOrigin: ${oldOrigin ?? "unset"} -> ${rewardsMessageOrigin}`);
|
||||
if (oldOrigin !== messageOrigin) {
|
||||
logger.info(` messageOrigin: ${oldOrigin ?? "unset"} -> ${messageOrigin}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Main handler for the update-rewards-origin command.
|
||||
* Fetches or computes the RewardsAgentOrigin and updates the config file.
|
||||
* Fetches or computes the AgentOrigin and updates the config file.
|
||||
*/
|
||||
export const updateRewardsOrigin = async (options: UpdateRewardsOriginOptions): Promise<void> => {
|
||||
const networkId = buildNetworkId(options.chain, options.environment);
|
||||
|
|
@ -246,17 +246,17 @@ export const updateRewardsOrigin = async (options: UpdateRewardsOriginOptions):
|
|||
printDivider();
|
||||
|
||||
try {
|
||||
// Step 1: Try to fetch RewardsAgentOrigin from the chain
|
||||
let rewardsMessageOrigin = await fetchRewardsAgentOrigin(options.rpcUrl);
|
||||
// Step 1: Try to fetch AgentOrigin from the chain
|
||||
let messageOrigin = await fetchAgentOrigin(options.rpcUrl);
|
||||
|
||||
printDivider();
|
||||
|
||||
if (rewardsMessageOrigin) {
|
||||
if (messageOrigin) {
|
||||
// Use the value from the chain
|
||||
logger.info("✅ Using RewardsAgentOrigin from chain runtime parameters");
|
||||
logger.info("✅ Using AgentOrigin from chain runtime parameters");
|
||||
} else {
|
||||
// Compute the Agent ID from genesis hash and pallet account
|
||||
logger.info("🔧 Computing RewardsAgentOrigin from genesis hash and pallet account...");
|
||||
logger.info("🔧 Computing AgentOrigin from genesis hash and pallet account...");
|
||||
|
||||
// Get genesis hash (from option or fetch from chain)
|
||||
const genesisHash = options.genesisHash
|
||||
|
|
@ -272,22 +272,22 @@ export const updateRewardsOrigin = async (options: UpdateRewardsOriginOptions):
|
|||
// Compute the Agent ID
|
||||
logger.info("🔐 Computing Agent ID...");
|
||||
logger.warn(
|
||||
"⚠️ Note: Computed Agent ID may need verification. Prefer setting RewardsAgentOrigin on-chain."
|
||||
"⚠️ Note: Computed Agent ID may need verification. Prefer setting AgentOrigin on-chain."
|
||||
);
|
||||
rewardsMessageOrigin = await computeAgentId(genesisHash, rewardsAccount);
|
||||
logger.info(` Agent ID: ${rewardsMessageOrigin}`);
|
||||
messageOrigin = await computeAgentId(genesisHash, rewardsAccount);
|
||||
logger.info(` Agent ID: ${messageOrigin}`);
|
||||
}
|
||||
|
||||
printDivider();
|
||||
|
||||
// Display the final value
|
||||
logger.info("📝 Rewards Message Origin:");
|
||||
logger.info(` ${rewardsMessageOrigin}`);
|
||||
logger.info(` ${messageOrigin}`);
|
||||
|
||||
printDivider();
|
||||
|
||||
// Update the config file
|
||||
await updateConfigFile(networkId, rewardsMessageOrigin);
|
||||
await updateConfigFile(networkId, messageOrigin);
|
||||
|
||||
printDivider();
|
||||
logger.success(`Rewards message origin updated successfully for ${networkId}`);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ const contractsCommand = program
|
|||
- upgrade: Upgrade contracts by deploying new implementations
|
||||
- verify: Verify deployed contracts on block explorer
|
||||
- update-beefy-checkpoint: Fetch BEEFY authorities from a live chain and update config
|
||||
- update-rewards-origin: Fetch or compute the RewardsAgentOrigin and update config
|
||||
- update-rewards-origin: Fetch or compute the AgentOrigin and update config
|
||||
- update-metadata: Update the metadata URI of an existing AVS contract
|
||||
|
||||
Common options:
|
||||
|
|
@ -385,17 +385,14 @@ contractsCommand
|
|||
contractsCommand
|
||||
.command("update-rewards-origin")
|
||||
.description(
|
||||
"Fetch or compute the RewardsAgentOrigin and update the config file with the rewards message origin"
|
||||
"Fetch or compute the AgentOrigin and update the config file with the rewards message origin"
|
||||
)
|
||||
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
||||
.option(
|
||||
"--environment <value>",
|
||||
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
||||
)
|
||||
.option(
|
||||
"--rpc-url <value>",
|
||||
"WebSocket RPC URL of the DataHaven chain to fetch RewardsAgentOrigin from"
|
||||
)
|
||||
.option("--rpc-url <value>", "WebSocket RPC URL of the DataHaven chain to fetch AgentOrigin from")
|
||||
.option(
|
||||
"--genesis-hash <value>",
|
||||
"Chain genesis hash (32 bytes hex). If not provided, will be fetched from the chain."
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"value": null
|
||||
},
|
||||
{
|
||||
"name": "RewardsAgentOrigin",
|
||||
"name": "AgentOrigin",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ import { $ } from "bun";
|
|||
import { Binary, FixedSizeBinary } from "polkadot-api";
|
||||
import { CROSS_CHAIN_TIMEOUTS, getPapiSigner, logger } from "utils";
|
||||
import type { Address } from "viem";
|
||||
import { gatewayAbi } from "../../contract-bindings";
|
||||
import { getContractInstance, parseDeploymentsFile } from "../../utils/contracts";
|
||||
import { waitForDataHavenEvent } from "../../utils/events";
|
||||
import { waitForDataHavenEvent, waitForEthereumEvent } from "../../utils/events";
|
||||
import { waitFor } from "../../utils/waits";
|
||||
import { BaseTestSuite } from "../framework";
|
||||
|
||||
|
|
@ -122,6 +123,8 @@ describe("Should slash an operator", () => {
|
|||
}, 40000);
|
||||
|
||||
it("use sudo to slash operator", async () => {
|
||||
const { publicClient } = suite.getTestConnectors();
|
||||
|
||||
// get era number
|
||||
const activeEra = await dhApi.query.ExternalValidators.ActiveEra.getValue();
|
||||
|
||||
|
|
@ -168,6 +171,19 @@ describe("Should slash an operator", () => {
|
|||
throw new Error("SlashesMessageSent event not found");
|
||||
}
|
||||
logger.info("Slashes message sent");
|
||||
|
||||
const fromBlock = await publicClient.getBlockNumber();
|
||||
const deployments = await parseDeploymentsFile();
|
||||
const _ethEvent = await waitForEthereumEvent({
|
||||
client: publicClient,
|
||||
address: deployments.Gateway,
|
||||
abi: gatewayAbi,
|
||||
eventName: "SlashingComplete",
|
||||
fromBlock: fromBlock > 0n ? fromBlock - 1n : fromBlock,
|
||||
timeout: CROSS_CHAIN_TIMEOUTS.DH_TO_ETH_MS
|
||||
});
|
||||
|
||||
logger.info("Got Ethereum event!");
|
||||
}, 560000);
|
||||
|
||||
it("should detect and slash an unresponsive validator (liveness)", async () => {
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ export const parseJsonToBeaconCheckpoint = (jsonInput: any): BeaconCheckpoint =>
|
|||
const DATAHAVEN_PARAM_NAMES = [
|
||||
"EthereumGatewayAddress",
|
||||
"RewardsUpdateSelector",
|
||||
"RewardsAgentOrigin",
|
||||
"AgentOrigin",
|
||||
"DatahavenServiceManagerAddress"
|
||||
] as const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue