Skip to content
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: add TON blockchain support #4985

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

Keshoid
Copy link

@Keshoid Keshoid commented Dec 11, 2024

Description

This PR adds a TON blockchain support to hyperlane project.

  • add hyperlane-ton crate to workspace;
  • update relayer & validator to support TON chains;
  • add hyperlane smart contracts for TON blockchain;
  • add ton::test under run-locally utility with e2e test (ton<->ton).

Drive-by changes

Related issues

Backward compatibility

Yes

Testing

E2E test:

cargo test  --package run-locally --features ton test-utils -- ton::test --nocapture 

Lapo4kaKek and others added 2 commits December 11, 2024 16:09
* init commit

* Initial setup for TonProvider implementation

* Initial implementation of HyperlaneProvider methods (get_block_by_hash, get_txn_by_hash, is_contract, get_balance, get_chain_metrics)

* Refactor: Renamed folder, updated field name, and cleaned up unused imports

* implemented get_messages method for TonApiCenter

* Refactor: Added ConnectionConf and updated TON provider requests

* feat(ton-provider): Added get_account_state to provider and updated methods for improved logging and response handling

* feat(provider): add run_get_method for querying smart contract state

* added send_message request in ton-api-trait

* feat: add get_wallet_states method to Ton provider

* feat(ton-mailbox): scaffold structure and stub methods for Mailbox traits

* implemented default_ism and count methods

* implemented delivered method in mailbox

* resolve lifetimes problems in TonMailbox implementation

* added implementation SequenceAwareIndexer trait and recipient_ism method in Mailbox Ton

* resolve conflicts in main.rs

* added get_transaction_by_message in provider

* implemented process method in mailbox and some updates in recipient_ism

* added import utils

* feat: Implemented TOnMailboxIndexer and get_blocks to Ton provider

* feat: create TonInterchainSecurityModule and raw implemented InterchainSecurityModule trait

* feat: added init implementation multisig ism

* feat: initial implementation of Interchain Gas Paymaster

* refactor(mailbox): rework build_message method

* refactor(provider): move wait_for_transaction to provider

* refactor(ISM): refactor dry_run_verify and module_type methods

* refactor(multisig): rework validators_and_threshold getter

* refactor: update cargo.toml and mod.rs

* feat: integrate base64_to_H512 conversion in TonProvider and added utility tests

* refactor(fetch_logs_in_range): switch to masterchain seqno for time extraction

* refactor(get_finalized_block_number): switch to workchain -1

* feat: init implementation TonSigner

* feat: init implementation validator_announce

* feat: implemented get_announced_storage_locations in validatorAnnounce

* updates error in signers.rs

* Refactor error handling, added max attempts and delay to TonConnectionConfig

* refactor error handling for get_blocks in TonProvider

* feature: add conversion utilities and unit tests for address linking and parsing

* feature: new implementation get_announced_storage_locations in validator_announce

* feature: add conversion utils with new conversion methods and updateimports tonlib -> tonlib_core

* refactor(tonlib-core): migrate from tonlib to tonlib_core with updated methods

* feature:(TonSigner): added create_signed_message and constructor from_mnemonic in TonSigner

* refactor(contracts): replace TonWallet with TonSigner in off-chain components

* Refactor hyperlane-ton under hyperlane-core

* feature: integrate initial support for TON blockchain in hyperlane-base and hyperlane-core

* feat(utils): add method for converting H256 to TonAddress

* added using conversionUtils for parsing H256 address

* refactor(chains/hyperlane-ton and hyperlane-base/settings): migrated from tonlib to tonlib_core and resolved warnings

* feat: init commit e2e tests for chain hyperlane-ton

* feat(contracts): add TON contracts with empty implementations (merkle_tree_hook, aggregation_ism, routing_ism) and other micro updates

* feat(ton-signer): implement Debug trait for DebugWalletVersion

* feat(hyperlane-base and hyperlane-core): update data creation and parsing for Ton offchain components

* feat(run_locally): add initial draft for e2e tests in TON

* feature(ton-provider): add handler H256 to TON address conversion in get_wallet_states

* fix(cosmos_provider): update path to fix compilation with main repository

* fix(lib.rs): delete mod mailbox_test

* feat(run_locally ton):some updates

* feat(hyperlane-base/chains): init implementation for create TonMailboxIndexer

* feat(TonMailbox): init impelmentation Indexer<H256> for TonMailbox

* feat(ton provider): some updates in TonProvider

* feat(ton mailbox and igp): some updates

* Fix compile & runtime errors

* Fix

* Extract http_client requests to separate fn

* fix(cargo in ton): added features for tokio crate

* refactor(ton-provider): updated seqno and mc_seqno types to u32 for compatibility

* feat(relayer and base/contract-sync):Added additional logging for message sync and index metrics

* feat(chains/hyperlane-ton):added logging

* feat(run-locally/ton): some updates in config

* FIx env vars

* feat(run_locally/ton): some updates in generate config

* Refactor

* address update

* updated address

* FIx

* updated address

* fix(TonMailbox): fix problems with get_recipient_ism

* feat(TonMailbox): updated the delivered method and error handling

* Refactor h256 to ton_address + add ::new() fn

* fix(ton-igp): added handling of the case when the interval starts or ends at 0

* feat(run-get-method): stack in run_get_method update

* Fix min block index

* feat(multisig): update parser in multisig ton

* Fix

* Always ret 1 from get_merkle_leaf_id_by_message_id

* fix: update address() method

* fix: updated address() method

* fix: update address() method

* feat(ton-validator_announce): added default implementation for announce_tokens_needed

* Fix ton signer

* added a stub for process_estimate_costs and updated the validator_announce address in run-locally ton

* update parsing dictionary in validator announce, added a plug for the merkle tree

* feat(ton-provider): added default implementation for RunGetMethodResponse

* feat(merkle-tree-hok): init implementation merkle_tree_hook

* refactor(ton-igp): updates error handling and made the parsing of events into a separate function

* refactor(hyperlane-ton): Error handlers have been updated and a small decomposition has been done

* refactor(hyperlane-ton/multisig_ism): a little refactoring

* refactor(chains/hyperlane-ton): removed expect and a small refactoring

* refactor: removed Result<> in the ton_address_to_h256 function

* Refactoring

* refactor(ton/run_locally): some refactoring

* resolve conflicts in ton merkle-hook

* feat(ton/run_locally): update run locally for Ton

* Remove unused code

* FIx warnings & compile errors

* Rename local ton chains

* Uncomment original code

* refactor(ton/types): got rid of the wrapper over the hyperlane message

* refactor(TonSigner): migrate from DebugWalletVersion to native WalletVersion and update tonlib_core version

* feat(ton-provider): init implemented get_block_by_height

* Add ton contracts

* Remove package-lock

* Uncomment cosmos code

* Fix grpc.rs

* refactor(ton-mailbox): streamline flow and improve error handling

* refactor(ton-mailbox): refactor Mailbox flow

* refactor(ton-mailbox): TonMailbox refactor flow

---------

Co-authored-by: NikitaM <[email protected]>
Copy link

changeset-bot bot commented Dec 11, 2024

⚠️ No Changeset found

Latest commit: a39cb06

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@Keshoid Keshoid changed the title Add TON blockchain support feat: add TON blockchain support Dec 11, 2024
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I build the project from this branch, file Cargo.lock gets updated. I wonder if the latest version of Cargo.lock was committed with this change?


### Build

`npx blueprint build` or `yarn blueprint build`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested yarn blueprint build from altvm_contracts/ton dir. I have got the following error:

Usage Error: The nearest package directory (<path_to_repo>/hyperlane-monorepo/altvm_contracts/ton) doesn't seem to be part of the project declared in <path_to_repo>/hyperlane-monorepo.

- If <path_to_repo>/hyperlane-monorepo isn't intended to be a project, remove any yarn.lock and/or package.json file there.
- If <path_to_repo>/hyperlane-monorepo is intended to be a project, it might be that you forgot to list altvm_contracts/ton in its workspace configuration.
- Finally, if <path_to_repo>/hyperlane-monorepo is fine and you intend altvm_contracts/ton to be treated as a completely separate project (not even a workspace), create an empty yarn.lock file in it.

$ yarn run [--inspect] [--inspect-brk] [-T,--top-level] [-B,--binaries-only] [--require #0] <scriptName> ...

Comment on lines +1 to +2
const int error::unknown_op = 0xffff;
const int error::wrong_mailbox_version = 100;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why one error constant is in hex while others are in dec. Is it a convention?

@ameten
Copy link
Contributor

ameten commented Dec 12, 2024

Could you please run the following command and fix the issues it reports?

cargo clippy -- -D warnings

Comment on lines 332 to +339
pub async fn get_merkle_leaf_id_by_message_id(&self, message_id: H256) -> Result<Option<u32>> {
let merkle_leaf = self
// FIXME It's a stub for hyperlane-ton e2e test debugging.
// Remove when debugging is finished.
let _merkle_leaf = self
.db
.retrieve_merkle_leaf_index_by_message_id(&message_id)?;
Ok(merkle_leaf)
Ok(Some(1))
//Ok(merkle_leaf)
Copy link
Contributor

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 intentionally committed?

@ameten
Copy link
Contributor

ameten commented Dec 12, 2024

I see quite a lot of logging added for debug purposes, but with info log level. I wonder if the plan is not remove them?

Comment on lines +19 to +23
url = { workspace = true }
pretty_env_logger = {workspace = true}
base64 = {workspace = true}
tracing = {workspace = true}
num-bigint = {workspace = true}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we please use .workspace = true format if we don't need to mention features?

tokio = {workspace = true, features = ["full"]}

hyperlane-core = { path = "../../hyperlane-core", features = ["async", "agent"] }
tonlib-core = "0.22.2"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can specify the version in workspace and use .workspace = true here.

Comment on lines +1 to +5
runtime_test.rs
main.rs
mailbox_test.rs
ism_test.rs
announce_test.rs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how these files are generated and why we would like to avoid committing them into source control?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we need this empty file?

Comment on lines +1 to +30
use async_trait::async_trait;
use derive_new::new;
use log::{debug, info, warn};
use std::error::Error;
use std::str::FromStr;

use hyperlane_core::{
h512_to_bytes, BlockInfo, ChainCommunicationError, ChainInfo, ChainResult, FixedPointNumber,
HyperlaneChain, HyperlaneCustomErrorWrapper, HyperlaneDomain, HyperlaneProvider, TxOutcome,
TxnInfo, TxnReceiptInfo, H256, H512, U256,
};
use reqwest::{Client, Response};
use serde_json::{json, Value};
use tokio::time::sleep;

use crate::client::error::CustomHyperlaneError;
use crate::run_get_method::StackItem;
use crate::{
trait_builder::TonConnectionConf,
traits::ton_api_center::TonApiCenter,
types::{
account_state::AccountStateResponse, block_response::BlockResponse,
message::MessageResponse, message::SendMessageResponse,
run_get_method::RunGetMethodResponse, transaction::TransactionResponse,
wallet_state::WalletStatesResponse,
},
utils::conversion::ConversionUtils,
};
use tonlib_core::TonAddress;
use url::Url;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we please adopt the following format for imports?

  1. imports from std sorted alphabetically followed by an empty line
  2. imports from external crates sorted alphabetically (async_trait, reqwest, tokio, url, tonlib_core) followed by an empty line
  3. imports from hyperlane crates sorted alphabetically (hyperlane_core) followed by an empty line
  4. imports from local crate (crate::) followed by an empty line
  5. imports from parent crate (super::) followed by an empty line

Could we please adopt it in all source code files?

Comment on lines +117 to +120
let block = response.blocks.first().ok_or_else(|| {
tracing::warn!("No blocks found in the response: {:?}", response);
ChainCommunicationError::CustomError("No blocks found in the response".to_string())
})?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have quite a generic pattern on how define chain-specific errors and convert it into ChainCommunicationError. Could you please use it throughout the source code?

See example here: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/chains/hyperlane-sealevel/src/error.rs

.get_blocks(
-1, // Masterchain
None,
Some(_height),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since parameter _height is used, it should not have leading underscore in its name.

})?;

Ok(BlockInfo {
hash: H256::zero(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why this field is not populated?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why we need this empty file?

@@ -0,0 +1,279 @@
#![allow(dead_code)] // TODO: `rustc` 1.80.1 clippy issue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it is a new change, could you please remove this instruction and make sure this file does not contribute into clippy errors and warnings?

@@ -60,6 +62,7 @@ impl Indexable for MerkleTreeInsertion {
HyperlaneDomainProtocol::Fuel => todo!(),
HyperlaneDomainProtocol::Sealevel => CursorType::SequenceAware,
HyperlaneDomainProtocol::Cosmos => CursorType::SequenceAware,
HyperlaneDomainProtocol::Ton => CursorType::SequenceAware, // need check
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merkle tree insertion should be SequenceAware as it is. So, comment need check can be removed.

Comment on lines +26 to +27
}
pub fn from_mnemonic(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new line before next method definition:

Suggested change
}
pub fn from_mnemonic(
}
pub fn from_mnemonic(

Comment on lines +35 to +47
#[derive(Debug, Deserialize)]
pub struct MessageState {
pub body: String,
pub decoded: Option<DecodedMessage>,
pub hash: String,
}

#[derive(Debug, Deserialize)]
pub struct MessageContent {
pub body: String,
pub decoded: Option<DecodedMessage>,
pub hash: String,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what the difference is between these two struct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be great to cover all the conversions with tests.

"symbol": "TON",
"decimals": 9
},
"chainId": 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we need to choose chainId and domainId for TON.

use tracing::instrument;

use super::aws_credentials::AwsChainCredentialsProvider;
use crate::types::utils;

/// Signer types
#[derive(Default, Debug, Clone)]
#[derive(Default, Debug, Clone)] /////
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why we need the comment in the end of the line?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we need this commented out source code.

Comment on lines +386 to +408
self.mailbox
.provider
.get_blocks(
-1, // masterchain (workchain = -1)
None, // shard
None, // Block block seqno
Some(block), // Masterchain block seqno
None,
None,
None,
None,
None,
None,
None,
)
.await
.map_err(|e| {
ChainCommunicationError::CustomError(format!(
"Failed to fetch block info for block {}: {:?}",
block, e
))
})?
.blocks
Copy link
Contributor

@ameten ameten Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that it will be useful to extract this call into a separate method and use it here as well as in the implementation of Indexer traits for other events like interchain gas payments.

self.mailbox
.provider
.get_blocks(
-1, // masterchain (workchain = -1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be great to move this literal to a constant which can be used everywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Review
Development

Successfully merging this pull request may close these issues.

3 participants