-
Notifications
You must be signed in to change notification settings - Fork 446
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: Cosmos SDK Module #5370
base: main
Are you sure you want to change the base?
feat: Cosmos SDK Module #5370
Conversation
|
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.
Only spent about 20 mins the other day poking around some of the first files, hopefully will have time to leave more feedback but posting for now
The biggest thing that stands out to me is just how much duplication there is with hyperlane-cosmos
. I could see there being some arguments for keeping this separate but I feel like consolidating as much as possible is probably the better move. Curious what @daniel-savu @ameten think
let tip = self.get_finalized_block_number().await?; | ||
let sequence = self | ||
.provider | ||
.rest() |
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.
When is rest vs grpc vs rpc appropriate? Given we have rpc and grpc for the CW implementation, I have a slight preference to just keep needing just those 2 - is that possible?
Rationale being that we have some work in progress rn to add some metrics for our Cosmos gRPC & RPC interactions, would be nice to not need to extend that work to cover rest too
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.
In Cosmos, gRPC, REST, and RPC all communicate with the chain through ABCI. They serve as wrappers around raw ABCI queries, meaning the main differences is in convenience and probably some performance overhead.
We chose to remove gRPC since it is not fully supported on our public KYVE endpoints, but this shouldn't matter for the agents implementation. We used REST as the query client implementation, because of its simplicity and human readability.
If we want to stick with gRPC and RPC, we would need to manually implement the gRPC Query Client for the Cosmos module. This includes handling protobuf serialization for each struct, i think it would make sense to move this into a separate repository (similar to the CW queries) and add that to the monorepo.
let value = attribute | ||
.value_str() | ||
.map_err(HyperlaneCosmosError::from)? | ||
.replace("\"", ""); |
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.
why's this necessary? curious what a raw EventAttribute here would look like
|
||
async fn get_ism(&self) -> ChainResult<Option<ISM>> { | ||
let isms = self.provider.rest().isms(ReorgPeriod::None).await?; | ||
for ism in isms { |
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.
should be able to do .into_iter()
to not need to clone
/// metadata offchain fetching and onchain formatting standard. | ||
async fn module_type(&self) -> ChainResult<ModuleType> { | ||
let isms = self.provider.rest().isms(ReorgPeriod::None).await?; | ||
for ism in isms { |
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.
ditto
/// This error can then be converted into the broader error type | ||
/// in hyperlane-core using the `From` trait impl | ||
#[derive(Debug, thiserror::Error)] | ||
pub enum HyperlaneCosmosError { |
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.
thoughts on reusing this with hyperlane-cosmos
?
|
||
#[derive(Debug, Eq, PartialEq)] | ||
/// An event parsed from the RPC response. | ||
pub struct ParsedEvent<T: PartialEq> { |
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.
lots of opportunity for reuse with hyperlane-cosmos
tracing = { workspace = true } | ||
tracing-futures = { workspace = true } | ||
url = { workspace = true } | ||
prost = "0.13.4" |
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.
I wonder if we can reference it in workspace?
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.
Good point, will look into it
hex = { workspace = true } | ||
http = { workspace = true } | ||
hyperlane-core = { path = "../../hyperlane-core", features = ["async"] } | ||
hyperlane-cosmwasm-interface.workspace = true |
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.
hyperlane-cosmwasm-interface.workspace = true | |
hyperlane-cosmwasm-interface = { workspace = true } |
rust/main/Cargo.toml
Outdated
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.
I wonder why some dependencies are remove. We don't use them anymore?
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.
Not too sure. I only used the cli for managing dependencies. Can re-add them if we want to be sure.
@@ -110,7 +110,7 @@ impl<T: Debug + Clone + Sync + Send + Indexable + 'static> ForwardSequenceAwareS | |||
/// If there are no logs to index, returns `None`. | |||
/// If there are logs to index, returns the range of logs, either by sequence or block number | |||
/// depending on the mode. | |||
#[instrument(ret)] | |||
// #[instrument(ret)] |
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.
I wonder why this annotation was removed?
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.
Sorry, just forgot to remove the comment again.
// limit this to 1 | ||
if start < 1 { | ||
return 1..=current_indexing_snapshot.at_block; | ||
} |
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.
I wonder if it will work for all chains. Presumably, Ethereum genesis block has height 0.
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.
Yes, good point, that was just annoying when testing with a local chain.
This will probably never be the case in a real world deployment, however i think it would make sense to add an optional additional property like genesis_height
or deployment_height
in IndexSettings
that defines on what height the mailbox has been deployed and this should be the lower bound of each indexer, as there can't be any events prior to that height.
The default value of that property can then be set by the protocol type.
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.
Just for visibility: RoutingISM and AggregationISM are not implemented
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.
Correct, they are not supported by the Cosmos Module implementation yet. Will add a comment for clarity 👍
// always write the 0th index | ||
if index > curr || index == 0 { |
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.
I wonder what is the issue which requires this change?
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.
Can't seem to replicate the issue anymore, nor did i fully understand it at that time.
When i first started the implementation, the syncer wouldn't write the 0th index. That was probably due to a faulty implementation of latest_checkpoint
in our merkle_tree_hook
. A lot has changed since then, i would just remove it again.
rust/main/config/testnet_config.json
Outdated
@@ -1515,7 +1515,7 @@ | |||
"protocol": "ethereum", | |||
"rpcUrls": [ | |||
{ | |||
"http": "http://127.0.0.1:8545" | |||
"http": "http://0.0.0.0:8545" |
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.
I wonder if this change was intentional?
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.
Nope, not intentional, will remove. Thanks 👍
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.
I wonder if it will make sense to have the functionality shared by CosmosWasm and CosmosNative implementations to be extracted into separate module and re-used?
Example: sender_and_nonce
method in CosmosProvider
and CosmosNativeProvider
. There can be more examples like this.
use std::{io::Cursor, ops::Deref}; | ||
|
||
use cosmrs::{ | ||
crypto::PublicKey, | ||
proto::{ | ||
cosmos::{ | ||
auth::v1beta1::QueryAccountRequest, | ||
bank::v1beta1::{QueryBalanceRequest, QueryBalanceResponse}, | ||
base::abci::v1beta1::TxResponse, | ||
}, | ||
tendermint::types::Block, | ||
}, | ||
tx::{SequenceNumber, SignerInfo, SignerPublicKey}, | ||
AccountId, Any, Coin, Tx, | ||
}; | ||
use derive_new::new; | ||
|
||
use super::{rest::RestProvider, RpcProvider}; | ||
use crate::{ | ||
ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, | ||
}; | ||
use hyperlane_core::{ | ||
h512_to_bytes, | ||
rpc_clients::{BlockNumberGetter, FallbackProvider}, | ||
utils::{self, to_atto}, | ||
AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, | ||
ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, | ||
HyperlaneProviderError, LogMeta, ModuleType, RawHyperlaneMessage, TxnInfo, TxnReceiptInfo, | ||
H256, H512, U256, | ||
}; | ||
use itertools::Itertools; | ||
use prost::Message; | ||
use reqwest::Error; | ||
use serde::{de::DeserializeOwned, Deserialize}; | ||
use tendermint::{hash::Algorithm, Hash}; | ||
use tendermint_rpc::{ | ||
client::CompatMode, | ||
endpoint::{block, block_results, tx}, | ||
Client, HttpClient, | ||
}; | ||
use time::OffsetDateTime; | ||
use tonic::async_trait; | ||
use tracing::{debug, trace, warn}; |
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.
It is worth to do everywhere.
It will be great to format imports as follows.
- std (and empty line)
- external crates (and empty line)
- internal crates (like
hyperlane_core
) (and empty line) crate::
imports (and empty line)super::
imports (and empty line)
use std::{io::Cursor, ops::Deref}; | |
use cosmrs::{ | |
crypto::PublicKey, | |
proto::{ | |
cosmos::{ | |
auth::v1beta1::QueryAccountRequest, | |
bank::v1beta1::{QueryBalanceRequest, QueryBalanceResponse}, | |
base::abci::v1beta1::TxResponse, | |
}, | |
tendermint::types::Block, | |
}, | |
tx::{SequenceNumber, SignerInfo, SignerPublicKey}, | |
AccountId, Any, Coin, Tx, | |
}; | |
use derive_new::new; | |
use super::{rest::RestProvider, RpcProvider}; | |
use crate::{ | |
ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, | |
}; | |
use hyperlane_core::{ | |
h512_to_bytes, | |
rpc_clients::{BlockNumberGetter, FallbackProvider}, | |
utils::{self, to_atto}, | |
AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, | |
ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, | |
HyperlaneProviderError, LogMeta, ModuleType, RawHyperlaneMessage, TxnInfo, TxnReceiptInfo, | |
H256, H512, U256, | |
}; | |
use itertools::Itertools; | |
use prost::Message; | |
use reqwest::Error; | |
use serde::{de::DeserializeOwned, Deserialize}; | |
use tendermint::{hash::Algorithm, Hash}; | |
use tendermint_rpc::{ | |
client::CompatMode, | |
endpoint::{block, block_results, tx}, | |
Client, HttpClient, | |
}; | |
use time::OffsetDateTime; | |
use tonic::async_trait; | |
use tracing::{debug, trace, warn}; | |
use std::{io::Cursor, ops::Deref}; | |
use cosmrs::{ | |
crypto::PublicKey, | |
proto::{ | |
cosmos::{ | |
auth::v1beta1::QueryAccountRequest, | |
bank::v1beta1::{QueryBalanceRequest, QueryBalanceResponse}, | |
base::abci::v1beta1::TxResponse, | |
}, | |
tendermint::types::Block, | |
}, | |
tx::{SequenceNumber, SignerInfo, SignerPublicKey}, | |
AccountId, Any, Coin, Tx, | |
}; | |
use derive_new::new; | |
use itertools::Itertools; | |
use prost::Message; | |
use reqwest::Error; | |
use serde::{de::DeserializeOwned, Deserialize}; | |
use tendermint::{hash::Algorithm, Hash}; | |
use tendermint_rpc::{ | |
client::CompatMode, | |
endpoint::{block, block_results, tx}, | |
Client, HttpClient, | |
}; | |
use time::OffsetDateTime; | |
use tonic::async_trait; | |
use tracing::{debug, trace, warn}; | |
use hyperlane_core::{ | |
h512_to_bytes, | |
rpc_clients::{BlockNumberGetter, FallbackProvider}, | |
utils::{self, to_atto}, | |
AccountAddressType, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, | |
ContractLocator, HyperlaneChain, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, | |
HyperlaneProviderError, LogMeta, ModuleType, RawHyperlaneMessage, TxnInfo, TxnReceiptInfo, | |
H256, H512, U256, | |
}; | |
use crate::{ | |
ConnectionConf, CosmosAccountId, CosmosAddress, CosmosAmount, HyperlaneCosmosError, Signer, | |
}; | |
use super::{rest::RestProvider, RpcProvider}; |
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.
Good to know, will adapt this convention 👍
I would agree with @tkporter in this comment that reducing the duplication of the code will be great since it will make the review of the change much easier. It will be ideal to have the refactoring of the re-used parts as a separate PR and, if it too hard, at least as a separate commit so that it can be reviewed without other CosmosNative changes. |
Description
This PR adds Agent support for the upcoming Hyperlane Cosmos SDK Module, called CosmosNative, to differentiate it from the existing CosmWasm (CW) implementation.
Drive-by Fixes
None
Related Issues
Backward Compatibility
Testing
The CosmosNative implementation has been tested through:
E2E Testing Details
To run the tests locally, use:
cargo test -r -p run-locally --features cosmosnative -- cosmosnative::test --nocapture