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

CCIP Read ISM #2398

Merged
merged 49 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c1ccd21
feat: initial ccip read contract verifying message body via a multi sig
AlexBHarley Jun 16, 2023
dad7b7d
refactor: abstract ccip read contract
AlexBHarley Jun 16, 2023
d7b3e34
refactor: clean up
AlexBHarley Jun 16, 2023
7999aa7
refactor: clean up
AlexBHarley Jun 16, 2023
27506d9
refactor: clean up
AlexBHarley Jun 16, 2023
26c1822
test: mock
AlexBHarley Jun 16, 2023
144e910
refactor: better function names
AlexBHarley Jun 16, 2023
72dcef5
doc: missing doc
AlexBHarley Jun 16, 2023
6a69e54
doc: missing doc
AlexBHarley Jun 16, 2023
c0e9eea
feat: initial cl aggregator
AlexBHarley Jun 17, 2023
ecd5382
chore: compiling
AlexBHarley Jun 17, 2023
6abcafe
feat: working chainlink aggregator
AlexBHarley Jun 17, 2023
638ba9c
refactor: bring more in line with Chainlink setup
AlexBHarley Jun 20, 2023
fe1b5e6
refactor: bring more in line with Chainlink setup
AlexBHarley Jun 20, 2023
f74364f
refactor: bring more in line with Chainlink setup
AlexBHarley Jun 20, 2023
0ab74b0
feat: little bit of cleanup and testing chainlink messages
AlexBHarley Jun 22, 2023
9cb7eaa
feat: initial ccip read ism relayer
AlexBHarley Jun 22, 2023
c85ff91
test: cleanup
AlexBHarley Jun 22, 2023
26021f2
feat: relayer working
AlexBHarley Jun 22, 2023
f73c6e7
fix: metadata decoding is hex
AlexBHarley Jun 23, 2023
6462fb4
Merge branch 'main' into alexbharley/ccip-read-ism
AlexBHarley Jun 23, 2023
48f820d
test: fix
AlexBHarley Jun 23, 2023
e138a3c
cargo fmt
AlexBHarley Jun 23, 2023
9d71a23
cargo clippy
AlexBHarley Jun 23, 2023
cdfeb41
refactor: simplify and move logic to different repo
AlexBHarley Jun 24, 2023
74a9182
refactor: simplify and move logic to different repo
AlexBHarley Jun 24, 2023
7579e4b
refactor: simplify and move logic to different repo
AlexBHarley Jun 24, 2023
4358fbd
refactor: simplify and move logic to different repo
AlexBHarley Jun 24, 2023
ce82b54
chore: bump msg size limit
AlexBHarley Jun 24, 2023
a7ab2ab
doc
AlexBHarley Jun 24, 2023
9f0ac76
chore: update abi
AlexBHarley Jun 24, 2023
32ff55c
refactor: clean up agent a little
AlexBHarley Jun 24, 2023
995f76c
fix: wrong if condition for POST CCIP Reads
AlexBHarley Jun 24, 2023
925582e
feat: successful relay
AlexBHarley Jun 25, 2023
9ce259c
doc: better wording
AlexBHarley Jun 26, 2023
1802faf
chore: remove old _offchainCalldata variable
AlexBHarley Jun 26, 2023
ff6b59d
fix
AlexBHarley Jun 26, 2023
1c1d442
docs & removing more logic from AbstractCcipReadIsm
AlexBHarley Jun 28, 2023
173e350
fixes
AlexBHarley Jun 28, 2023
b57fd4d
doc
AlexBHarley Jun 28, 2023
fc73c2b
fix: message, not message.body
AlexBHarley Jun 28, 2023
b6d1eec
revert: no need for huge messages when metadata can store info
AlexBHarley Jun 28, 2023
94ec4c5
Merge branch 'main' into alexbharley/ccip-read-ism
AlexBHarley Jul 3, 2023
8275a07
chore: undo comment
AlexBHarley Jul 3, 2023
56d6906
refactor: address review comments
AlexBHarley Jul 6, 2023
24cc2be
refactor: address review comments
AlexBHarley Jul 6, 2023
0b37cae
refactor: address review comments
AlexBHarley Jul 6, 2023
387576f
Merge branch 'main' into alexbharley/ccip-read-ism
AlexBHarley Jul 13, 2023
c4447fe
Merge branch 'main' into alexbharley/ccip-read-ism
nambrot Jul 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/agents/relayer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tokio = { workspace = true, features = ["rt", "macros", "parking_lot"] }
tracing-futures.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
regex = "1.5"

hyperlane-core = { path = "../../hyperlane-core" }
hyperlane-base = { path = "../../hyperlane-base" }
Expand Down
12 changes: 10 additions & 2 deletions rust/agents/relayer/src/msg/metadata/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ use hyperlane_base::{
};
use hyperlane_core::accumulator::merkle::Proof;
use hyperlane_core::{
Checkpoint, HyperlaneDomain, HyperlaneMessage, ModuleType, MultisigIsm, RoutingIsm,
ValidatorAnnounce, H160, H256,
CcipReadIsm, Checkpoint, HyperlaneDomain, HyperlaneMessage, ModuleType, MultisigIsm,
RoutingIsm, ValidatorAnnounce, H160, H256,
};

use crate::merkle_tree_builder::MerkleTreeBuilder;
use crate::msg::metadata::multisig::{
LegacyMultisigMetadataBuilder, MerkleRootMultisigMetadataBuilder,
MessageIdMultisigMetadataBuilder,
};
use crate::msg::metadata::CcipReadIsmMetadataBuilder;
use crate::msg::metadata::RoutingIsmMetadataBuilder;

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -87,6 +88,7 @@ impl MetadataBuilder for BaseMetadataBuilder {
}
ModuleType::MessageIdMultisig => Box::new(MessageIdMultisigMetadataBuilder::new(base)),
ModuleType::Routing => Box::new(RoutingIsmMetadataBuilder::new(base)),
ModuleType::CcipRead => Box::new(CcipReadIsmMetadataBuilder::new(base)),
_ => return Err(MetadataBuilderError::UnsupportedModuleType(module_type).into()),
};
metadata_builder
Expand Down Expand Up @@ -150,6 +152,12 @@ impl BaseMetadataBuilder {
.await
}

pub async fn build_ccip_read_ism(&self, address: H256) -> Result<Box<dyn CcipReadIsm>> {
self.destination_chain_setup
.build_ccip_read_ism(address, &self.metrics)
.await
}

pub async fn build_checkpoint_syncer(
&self,
validators: &[H256],
Expand Down
105 changes: 105 additions & 0 deletions rust/agents/relayer/src/msg/metadata/ccip_read.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use async_trait::async_trait;
use hyperlane_ethereum::OffchainLookup;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::ops::Deref;

use derive_new::new;
use eyre::Context;
use tracing::instrument;

use super::{BaseMetadataBuilder, MetadataBuilder};
use ethers::abi::AbiDecode;
use ethers::core::utils::hex::decode as hex_decode;
use hyperlane_core::{ChainCommunicationError, HyperlaneMessage, H256};
use regex::Regex;

#[derive(Serialize, Deserialize)]
struct OffchainResponse {
metadata: String,
message: String,
}

#[derive(Clone, Debug, new)]
pub struct CcipReadIsmMetadataBuilder {
base: BaseMetadataBuilder,
}

impl Deref for CcipReadIsmMetadataBuilder {
type Target = BaseMetadataBuilder;

fn deref(&self) -> &Self::Target {
&self.base
}
}

#[async_trait]
impl MetadataBuilder for CcipReadIsmMetadataBuilder {
#[instrument(err, skip(self))]
async fn build(
&self,
ism_address: H256,
message: &HyperlaneMessage,
) -> eyre::Result<Option<Vec<u8>>> {
const CTX: &str = "When fetching CcipRead metadata";
let ism = self.build_ccip_read_ism(ism_address).await.context(CTX)?;
let info_result = ism.get_offchain_verify_info(message).await.context(CTX);

let info: OffchainLookup = match info_result {
Ok(_) => panic!("Shouldn't get here"),
Err(e) => match e.downcast_ref::<ChainCommunicationError>() {
Some(err) => {
println!("err {:?}", err);
let regex = Regex::new(r"0x[[:xdigit:]]+").unwrap();

if let Some(capture) = regex.captures(&err.to_string()) {
let extracted = &capture[0];

let data = hex_decode(extracted.replace("0x", "")).unwrap();
OffchainLookup::decode(data).unwrap()
} else {
panic!("Shouldn't get here");
// Err(hyperlane_core::ChainCommunicationError::TransactionTimeout())
}
}
None => panic!("Shouldn't get here"),
},
};

for url in info.urls.iter() {
let request_url = url
.replace("{sender}", &info.sender.to_string())
.replace("{data}", &info.call_data.to_string());
let res = if url.contains("{data}") {
let body = json!({
"data": info.call_data.to_string(),
"sender": info.sender.to_string(),
});
Client::new()
.post(request_url)
.header("Content-Type", "application/json")
.json(&body)
.send()
.await?
} else {
reqwest::get(request_url).await?
};

let json: Result<OffchainResponse, reqwest::Error> = res.json().await;

match json {
Ok(result) => {
// remove leading 0x which hex_decode doesn't like
let metadata = hex_decode(&result.metadata[2..]).unwrap();
return Ok(Some(metadata));
}
Err(_err) => {
// let the next URL
}
}
}

Ok(None)
}
}
2 changes: 2 additions & 0 deletions rust/agents/relayer/src/msg/metadata/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod base;
mod ccip_read;
mod multisig;
mod routing;

pub(crate) use base::BaseMetadataBuilder;
pub(crate) use base::MetadataBuilder;
use ccip_read::CcipReadIsmMetadataBuilder;
use routing::RoutingIsmMetadataBuilder;
221 changes: 221 additions & 0 deletions rust/chains/hyperlane-ethereum/abis/ICcipReadIsm.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "string[]",
"name": "urls",
"type": "string[]"
},
{
"internalType": "bytes",
"name": "callData",
"type": "bytes"
},
{
"internalType": "bytes4",
"name": "callbackFunction",
"type": "bytes4"
},
{
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
}
],
"name": "OffchainLookup",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "callData",
"type": "bytes"
}
],
"name": "OffchainCallDataUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "extraData",
"type": "bytes"
}
],
"name": "OffchainExtraDataUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string[]",
"name": "urls",
"type": "string[]"
}
],
"name": "OffchainUrlsUpdated",
"type": "event"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "getOffchainVerifyInfo",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "moduleType",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "offchainCallData",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "offchainExtraData",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "offchainUrls",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_message",
"type": "bytes"
}
],
"name": "validatorsAndThreshold",
"outputs": [
{
"internalType": "address[]",
"name": "",
"type": "address[]"
},
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_metadata",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "_message",
"type": "bytes"
}
],
"name": "verify",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "response",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "verifyWithProof",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
Loading