-
Notifications
You must be signed in to change notification settings - Fork 407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: posting ECDSARegistry signature to s3 bucket for validators #3674
Changes from all commits
c5ac704
8873f20
2158670
1ee6b10
42ae9a6
325031e
0488bc5
f737489
0eaffff
ef35202
5c1c827
a95a8c5
e348bdc
5680d72
98704f5
b8afaae
59c7019
c176526
d7c2032
01b1940
317d814
38e3ac5
bf3e8df
421353e
ff781c3
05d7979
df4a172
f045045
3abf566
2ef337c
b50e0b2
828f4e9
7112431
4cf5b02
7f3540b
b159fdf
23aa155
e11ed99
2f67212
0e29c58
e62daa4
2cd2d6a
ed089e3
25f4a0d
e8a199b
3800b6d
85ab916
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
typescript/sdk/src/cw-types/*.types.ts linguist-generated=true | ||
rust/chains/hyperlane-ethereum/abis/*.abi.json linguist-generated=true | ||
solidity/contracts/interfaces/avs/*.sol linguist-vendored=true | ||
solidity/contracts/avs/ECDSA*.sol linguist-vendored=true |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,14 +12,15 @@ use tracing::{error, info, info_span, instrument::Instrumented, warn, Instrument | |
use hyperlane_base::{ | ||
db::{HyperlaneRocksDB, DB}, | ||
metrics::AgentMetrics, | ||
settings::ChainConf, | ||
settings::{staking_config::StakingConf, ChainConf}, | ||
BaseAgent, ChainMetrics, CheckpointSyncer, ContractSyncMetrics, ContractSyncer, CoreMetrics, | ||
HyperlaneAgentCore, MetricsUpdater, SequencedDataContractSync, | ||
}; | ||
|
||
use hyperlane_core::{ | ||
Announcement, ChainResult, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSigner, | ||
HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, TxOutcome, ValidatorAnnounce, | ||
utils::operator_registration_signature_expiry, Announcement, ChainResult, HyperlaneChain, | ||
HyperlaneContract, HyperlaneDomain, HyperlaneSigner, HyperlaneSignerExt, Mailbox, | ||
MerkleTreeHook, MerkleTreeInsertion, OperatorRegistrationBuilder, TxOutcome, ValidatorAnnounce, | ||
H256, U256, | ||
}; | ||
use hyperlane_ethereum::{SingletonSigner, SingletonSignerHandle}; | ||
|
@@ -44,12 +45,16 @@ pub struct Validator { | |
signer: SingletonSignerHandle, | ||
// temporary holder until `run` is called | ||
signer_instance: Option<Box<SingletonSigner>>, | ||
avs_domain: Option<u32>, | ||
avs_signer: Option<SingletonSignerHandle>, | ||
avs_signer_instance: Option<Box<SingletonSigner>>, | ||
reorg_period: u64, | ||
interval: Duration, | ||
checkpoint_syncer: Arc<dyn CheckpointSyncer>, | ||
core_metrics: Arc<CoreMetrics>, | ||
agent_metrics: AgentMetrics, | ||
chain_metrics: ChainMetrics, | ||
staking_config: StakingConf, | ||
} | ||
|
||
#[async_trait] | ||
|
@@ -73,6 +78,16 @@ impl BaseAgent for Validator { | |
// Intentionally using hyperlane_ethereum for the validator's signer | ||
let (signer_instance, signer) = SingletonSigner::new(settings.validator.build().await?); | ||
|
||
// If the AVS operator is provided, create a signer for it to write the announcement | ||
let (avs_signer_instance, avs_signer) = match &settings.avs_operator { | ||
Some(avs_operator) => { | ||
let (avs_signer_instance, avs_signer) = | ||
SingletonSigner::new(avs_operator.build().await?); | ||
(Some(avs_signer_instance), Some(avs_signer)) | ||
} | ||
None => (None, None), | ||
}; | ||
|
||
let core = settings.build_hyperlane_core(metrics.clone()); | ||
let checkpoint_syncer = settings.checkpoint_syncer.build(None).await?.into(); | ||
|
||
|
@@ -116,12 +131,16 @@ impl BaseAgent for Validator { | |
validator_announce: validator_announce.into(), | ||
signer, | ||
signer_instance: Some(Box::new(signer_instance)), | ||
avs_domain: settings.avs_domain, | ||
avs_signer, | ||
avs_signer_instance: avs_signer_instance.map(Box::new), | ||
reorg_period: settings.reorg_period, | ||
interval: settings.interval, | ||
checkpoint_syncer, | ||
agent_metrics, | ||
chain_metrics, | ||
core_metrics: metrics, | ||
staking_config: settings.staking_config, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo instead of storing a config in the Validator that you can then lookup
it'd be nicer to just do that lookup in here when building the Validator once, and then store the |
||
}) | ||
} | ||
|
||
|
@@ -152,6 +171,15 @@ impl BaseAgent for Validator { | |
); | ||
} | ||
|
||
if let Some(avs_signer_instance) = self.avs_signer_instance.take() { | ||
tasks.push( | ||
tokio::spawn(async move { | ||
avs_signer_instance.run().await; | ||
}) | ||
.instrument(info_span!("AvsSingletonSigner")), | ||
); | ||
} | ||
|
||
let metrics_updater = MetricsUpdater::new( | ||
&self.origin_chain_conf, | ||
self.core_metrics.clone(), | ||
|
@@ -171,6 +199,10 @@ impl BaseAgent for Validator { | |
// announce the validator after spawning the signer task | ||
self.announce().await.expect("Failed to announce validator"); | ||
|
||
self.write_operator_registration() | ||
.await | ||
.expect("Failed to announce to AVS"); | ||
|
||
let reorg_period = NonZeroU64::new(self.reorg_period); | ||
|
||
// Ensure that the merkle tree hook has count > 0 before we begin indexing | ||
|
@@ -286,6 +318,45 @@ impl Validator { | |
} | ||
} | ||
|
||
async fn write_operator_registration(&self) -> Result<()> { | ||
if let Some(ref avs_signer) = &self.avs_signer { | ||
let address = avs_signer.eth_address(); | ||
let registration_location = self.checkpoint_syncer.announcement_location(); | ||
|
||
println!( | ||
"Announcing to AVS, location: {:?} for validator: {:?}", | ||
registration_location, address | ||
); | ||
|
||
let avs_domain = self.avs_domain.unwrap(); | ||
|
||
let service_manager = match self.staking_config.service_managers.get(&avs_domain) { | ||
Some(service_manager) => service_manager, | ||
None => { | ||
info!("No service manager found for AVS domain {}", avs_domain); | ||
return Ok(()); | ||
} | ||
}; | ||
|
||
let registration = OperatorRegistrationBuilder::default() | ||
.domain(avs_domain) | ||
.operator(address) | ||
.service_manager_address(*service_manager) // Dereference the service_manager variable | ||
.salt(H256::zero()) // TODO: is this ok? | ||
.expiry(operator_registration_signature_expiry()) | ||
.build() | ||
.unwrap(); | ||
|
||
let signed_registration = avs_signer.sign(registration.clone()).await?; | ||
self.checkpoint_syncer | ||
.write_operator_registration(&signed_registration) | ||
.await?; | ||
} else { | ||
info!("No AVS signer configured, skipping AVS announcement"); | ||
} | ||
Ok(()) | ||
} | ||
|
||
async fn announce(&self) -> Result<()> { | ||
let address = self.signer.eth_address(); | ||
let announcement_location = self.checkpoint_syncer.announcement_location(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use hyperlane_core::H160; | ||
use std::{collections::HashMap, str::FromStr}; | ||
|
||
#[derive(Clone, Debug, Default)] | ||
pub struct StakingConf { | ||
/// Address of the HyperlaneServiceManager contract | ||
pub service_managers: HashMap<u32, H160>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will there be stuff in here other than the service_managers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I imagine we'll have more config once we have native staking which will also have some form of registration announcement in a json form. |
||
} | ||
|
||
impl StakingConf { | ||
pub fn default_staking_config() -> StakingConf { | ||
let mut service_managers = HashMap::new(); | ||
service_managers.insert( | ||
1, | ||
H160::from_str("0xa3aC2db78AC678D9609637e23020dc210110DAE4").unwrap(), | ||
); | ||
service_managers.insert( | ||
17000, | ||
H160::from_str("0x055733000064333CaDDbC92763c58BF0192fFeBf").unwrap(), | ||
); // holesky | ||
|
||
StakingConf { service_managers } | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you expect to ever have this be set via settings?
if we won't ever have a different config other than the
default_staking_config
, imo you could just not even have this in ValidatorSettings, and just create it inimpl BaseAgent for Validator {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the above comment, I was anticipating we may need to set it via settings as you mentioned