Skip to content

Commit adc644e

Browse files
authored
feat(tron): validator announce (#7832)
1 parent 94c6499 commit adc644e

4 files changed

Lines changed: 132 additions & 5 deletions

File tree

rust/main/chains/hyperlane-tron/src/contracts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub use {interchain_gas::*, mailbox::*, merkle_tree_hook::*};
1+
pub use {interchain_gas::*, mailbox::*, merkle_tree_hook::*, validator_announce::*};
22

33
use std::sync::Arc;
44

@@ -13,6 +13,7 @@ use hyperlane_core::{ChainResult, LogMeta, H512};
1313
mod interchain_gas;
1414
mod mailbox;
1515
mod merkle_tree_hook;
16+
mod validator_announce;
1617

1718
pub(crate) async fn fetch_raw_logs_and_meta<T: EthEvent, M>(
1819
tx_hash: H512,
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#![allow(clippy::enum_variant_names)]
2+
#![allow(missing_docs)]
3+
4+
use std::sync::Arc;
5+
6+
use async_trait::async_trait;
7+
use ethers::providers::Middleware;
8+
use ethers_contract::builders::ContractCall;
9+
use hyperlane_core::{
10+
Announcement, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain,
11+
HyperlaneProvider, SignedType, TxOutcome, ValidatorAnnounce, H160, H256, U256,
12+
};
13+
use tracing::{instrument, trace};
14+
15+
use crate::{
16+
interfaces::i_validator_announce::IValidatorAnnounce as TronValidatorAnnounceInternal,
17+
TronProvider,
18+
};
19+
20+
/// A reference to a ValidatorAnnounce contract on some Tron chain
21+
#[derive(Debug)]
22+
pub struct TronValidatorAnnounce {
23+
contract: Arc<TronValidatorAnnounceInternal<TronProvider>>,
24+
domain: HyperlaneDomain,
25+
provider: Arc<TronProvider>,
26+
}
27+
28+
impl TronValidatorAnnounce {
29+
/// Create a reference to a ValidatoAnnounce contract at a specific Tron
30+
/// address on some chain
31+
pub fn new(provider: TronProvider, locator: &ContractLocator) -> Self {
32+
let provider = Arc::new(provider);
33+
Self {
34+
contract: Arc::new(TronValidatorAnnounceInternal::new(
35+
locator.address,
36+
provider.clone(),
37+
)),
38+
domain: locator.domain.clone(),
39+
provider,
40+
}
41+
}
42+
43+
/// Returns a ContractCall that processes the provided message.
44+
/// If the provided tx_gas_limit is None, gas estimation occurs.
45+
async fn announce_contract_call(
46+
&self,
47+
announcement: SignedType<Announcement>,
48+
) -> ChainResult<ContractCall<TronProvider, bool>> {
49+
let serialized_signature: [u8; 65] = announcement.signature.into();
50+
let tx = self.contract.announce(
51+
announcement.value.validator.into(),
52+
announcement.value.storage_location,
53+
serialized_signature.into(),
54+
);
55+
Ok(tx)
56+
}
57+
}
58+
59+
impl HyperlaneChain for TronValidatorAnnounce {
60+
fn domain(&self) -> &HyperlaneDomain {
61+
&self.domain
62+
}
63+
64+
fn provider(&self) -> Box<dyn HyperlaneProvider> {
65+
Box::new(self.provider.clone())
66+
}
67+
}
68+
69+
impl HyperlaneContract for TronValidatorAnnounce {
70+
fn address(&self) -> H256 {
71+
self.contract.address().into()
72+
}
73+
}
74+
75+
#[async_trait]
76+
impl ValidatorAnnounce for TronValidatorAnnounce {
77+
async fn get_announced_storage_locations(
78+
&self,
79+
validators: &[H256],
80+
) -> ChainResult<Vec<Vec<String>>> {
81+
let storage_locations = self
82+
.contract
83+
.get_announced_storage_locations(
84+
validators.iter().map(|v| H160::from(*v).into()).collect(),
85+
)
86+
.call()
87+
.await?;
88+
Ok(storage_locations)
89+
}
90+
91+
#[instrument(ret, skip(self))]
92+
async fn announce_tokens_needed(
93+
&self,
94+
announcement: SignedType<Announcement>,
95+
chain_signer: H256,
96+
) -> Option<U256> {
97+
let Ok(contract_call) = self.announce_contract_call(announcement).await else {
98+
trace!("Unable to get announce contract call");
99+
return None;
100+
};
101+
102+
let chain_signer_h160 = ethers::types::H160::from(chain_signer);
103+
let Ok(balance) = Middleware::get_balance(&self.provider, chain_signer_h160, None).await
104+
else {
105+
trace!("Unable to query balance");
106+
return None;
107+
};
108+
109+
let Some(max_cost) = contract_call.tx.max_cost() else {
110+
trace!("Unable to get announce max cost");
111+
return None;
112+
};
113+
Some(max_cost.saturating_sub(balance).into())
114+
}
115+
116+
#[instrument(err, ret, skip(self))]
117+
async fn announce(&self, announcement: SignedType<Announcement>) -> ChainResult<TxOutcome> {
118+
let contract_call = self.announce_contract_call(announcement).await?;
119+
self.provider.send_and_wait(&contract_call).await
120+
}
121+
}

rust/main/chains/hyperlane-tron/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use ethers_signers::LocalWallet;
99

1010
pub use {
1111
config::ConnectionConf, contracts::TronInterchainGasPaymaster, contracts::TronMailbox,
12-
contracts::TronMailboxIndexer, contracts::TronMerkleTreeHookIndexer, ism::TronAggregationIsm,
13-
ism::TronInterchainSecurityModule, ism::TronMultisigIsm, ism::TronRoutingIsm,
14-
provider::TronProvider,
12+
contracts::TronMailboxIndexer, contracts::TronMerkleTreeHookIndexer,
13+
contracts::TronValidatorAnnounce, ism::TronAggregationIsm, ism::TronInterchainSecurityModule,
14+
ism::TronMultisigIsm, ism::TronRoutingIsm, provider::TronProvider,
1515
};
1616

1717
mod config;

rust/main/hyperlane-base/src/settings/chains.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,12 @@ impl ChainConf {
985985
h_radix::RadixValidatorAnnounce::new(provider, &locator, conf)?;
986986
Ok(Box::new(validator_announce) as Box<dyn ValidatorAnnounce>)
987987
}
988-
ChainConnectionConf::Tron(_) => todo!(),
988+
ChainConnectionConf::Tron(conf) => {
989+
let signer = self.tron_signer().await.context(ctx)?;
990+
let provider = build_tron_provider(self, conf, metrics, &locator, signer)?;
991+
let validator_announce = h_tron::TronValidatorAnnounce::new(provider, &locator);
992+
Ok(Box::new(validator_announce) as Box<dyn ValidatorAnnounce>)
993+
}
989994
#[cfg(feature = "aleo")]
990995
ChainConnectionConf::Aleo(conf) => {
991996
let signer = self.aleo_signer().await?;

0 commit comments

Comments
 (0)