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

2192 ics08 near light client #2254

Draft
wants to merge 38 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0e6627b
chore(unionlabs): move near lc types to correct location
aeryz Jun 20, 2024
ce36066
chore(near): generate proto
aeryz Jun 20, 2024
2811c48
chore(unionlabs): impl near light client protos
aeryz Jun 20, 2024
847c042
chore(unionlabs): add `model` to near proto types
aeryz Jun 24, 2024
76da3bf
feat(near-verifier): introduce the module
aeryz Jun 24, 2024
756db2e
feat(near-verifier): verify_state impl
aeryz Jun 24, 2024
fb3883c
chore(ics08-near): integrate `near-verifier`
aeryz Jun 24, 2024
a7211ef
chore(ics08-near): fix warnings
aeryz Jun 24, 2024
e3adb64
chore(near-lc): near lc on near compiles
aeryz Jun 29, 2024
577612a
fix(near): integration tests
aeryz Jul 2, 2024
7a3d897
chore(cometbls-ics08): split cometbls lc's by tech
aeryz Jul 2, 2024
58620c2
feat(cometbls-near): introduce cometbls near lc
aeryz Jul 2, 2024
5137d0a
chore(cometbls-near): use proto for states
aeryz Jul 3, 2024
59df1dd
chore(near): setup devnet
aeryz Jul 3, 2024
e6f95c0
wip: add near to voyager
benluelo Jul 3, 2024
1abc81f
chore(unionlabs): add `chain_id` to near `ClientState`
aeryz Jul 3, 2024
3317838
feat(chain-utils): near implementation compiles
aeryz Jul 4, 2024
83dce38
feat(voyager): near support
aeryz Jul 4, 2024
45c20fa
chore(near): devnet working
aeryz Jul 9, 2024
d03d51f
chore(near-verifier): convert asserts to errors
aeryz Jul 22, 2024
98ee630
chore(near): change balance proto from u64 to bytes
aeryz Jul 22, 2024
37b1351
chore(near-devnet): deploy ibc contract
aeryz Jul 22, 2024
a926d37
chore(ics08-near): add integration tests
aeryz Jul 22, 2024
4b4c8ee
chore(unionlabs): remove near feature gating
aeryz Jul 23, 2024
22b01c1
chore(near-verifier): remove `near-sdk` dep and use `near-account-id`
aeryz Jul 23, 2024
11cca6a
chore: implement poc-relayer
aeryz Jul 23, 2024
f3e51c4
chore(devnet-near): deploy contracts to named accounts
aeryz Jul 23, 2024
acbf537
chore: naming
aeryz Jul 23, 2024
9c74406
a lot of pain and failed verifications
aeryz Jul 23, 2024
80ab0dc
chore(near-verifier): add details to errors
aeryz Jul 24, 2024
40e374f
fix(ics08-near): membership verification
aeryz Jul 24, 2024
33d959d
chore(cometbls-near): disable non-native zk verification
aeryz Jul 24, 2024
ca8bce9
chore: update cometbls-near works
aeryz Jul 24, 2024
26526ab
chore: god near connopen works!!
aeryz Jul 24, 2024
4345af4
feat(cometbls-near): groth16 verifier with host functions
aeryz Jul 25, 2024
dbbcc0e
fix(near-ibc): make light clients capable of handling multiple clients
aeryz Jul 25, 2024
bc4a8d9
chore: fmt
aeryz Jul 26, 2024
fbd13ca
chore(ibc-vm): return error in VerifyClientMessage
aeryz Jul 27, 2024
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
Prev Previous commit
Next Next commit
wip: add near to voyager
benluelo authored and aeryz committed Jul 26, 2024
commit e6f95c08cead8a775cf56fd8852eafb1707146da
348 changes: 336 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion lib/chain-utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ beacon-api = { workspace = true }
contracts = { workspace = true, features = ["providers"] }
protos = { workspace = true, features = ["default", "client"] }
serde-utils = { workspace = true }
unionlabs = { workspace = true, features = ["default"] }
unionlabs = { workspace = true, features = ["default", "near"] }

arbitrary = { workspace = true, optional = true, features = ["derive"] }
bip32 = { workspace = true, features = ["secp256k1"] }
@@ -41,6 +41,9 @@ thiserror = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
typenum = { workspace = true, features = ["const-generics", "no_std"] }
near-jsonrpc-client = "0.10.1"
near-primitives = "0.23.0"
near-primitives-core = "0.23.0"

[features]
arbitrary = ["dep:arbitrary"]
1 change: 1 addition & 0 deletions lib/chain-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ pub mod arbitrum;
pub mod berachain;
pub mod cosmos;
pub mod ethereum;
pub mod near;
pub mod scroll;
pub mod union;

190 changes: 190 additions & 0 deletions lib/chain-utils/src/near.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use near_jsonrpc_client::methods::{self, status};
use near_primitives::types::{AccountId, BlockId, BlockReference, Finality};
use unionlabs::{
encoding::Borsh,
ibc::{core::client::height::Height, lightclients::near},
id::ClientId,
traits::{Chain, ChainIdOf},
};

pub struct Near {
// ???
rpc: near_jsonrpc_client::JsonRpcClient,
chain_id: String,
ibc_account_id: AccountId,
}

pub struct Config {
rpc_url: String,
ibc_account_id: AccountId,
}

impl Near {
pub fn new(config: Config) -> Self {
let rpc = near_jsonrpc_client::JsonRpcClient::connect(config.rpc_url);
Self {
rpc,
chain_id: rpc.call(status::RpcStatusRequest).await.unwrap().chain_id,
ibc_account_id: config.ibc_account_id,
}
}
}

impl Chain for Near {
type ChainType;

type SelfClientState = near::client_state::ClientState;
type SelfConsensusState = near::consensus_state::ConsensusState;
type Header = near::header::Header;

type StoredClientState<Tr: Chain> = Tr::SelfClientState;
type StoredConsensusState<Tr: Chain> = Tr::SelfConsensusState;

type Height = Height;
type ClientId = ClientId;
type IbcStateEncoding = Borsh;
type StateProof = RawStateProof;
type ClientType;

type Error = Box<dyn std::error::Error>;

fn chain_id(&self) -> ChainIdOf<Self> {
self.chain_id.clone()
}

async fn query_latest_height(&self) -> Result<Self::Height, Self::Error> {
self.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
})
.await
.map(|x| Height {
revision_number: NEAR_REVISION_NUMBER,
revision_height: x.header.height,
})
.map_err(|x| Box::new(x) as _)
}

async fn query_latest_height_as_destination(&self) -> Result<Self::Height, Self::Error> {
self.query_latest_height().await
}

async fn query_latest_timestamp(&self) -> Result<i64, Self::Error> {
self.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
})
.await
.map(|x| x.header.timestamp_nanosec.try_into().expect("idk bro"))
.map_err(|x| Box::new(x) as _)
}

async fn self_client_state(&self, height: Self::Height) -> Self::SelfClientState {
let block = self
.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
})
.await
.map_err(|x| Box::new(x))?;

let lc_block = self
.rpc
.call(
methods::next_light_client_block::RpcLightClientNextBlockRequest {
last_block_hash: block.header.last_final_block,
},
)
.await
.map_err(|x| Box::new(x) as _)?
.expect("needs a light client block");

Ok(near::client_state::ClientState {
latest_height: lc_block.inner_lite.height - 1,
ibc_account_id: self.ibc_account_id.clone(),
initial_block_producers: lc_block.next_bps.map(convert_block_producers),
frozen_height: 0,
})
}

async fn self_consensus_state(&self, height: Self::Height) -> Self::SelfConsensusState {
let block = self
.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
})
.await
.map_err(|x| Box::new(x))?;

let lc_block = self
.rpc
.call(
methods::next_light_client_block::RpcLightClientNextBlockRequest {
last_block_hash: block.header.last_final_block,
},
)
.await
.map_err(|x| Box::new(x) as _)?
.expect("needs a light client block");

let prev_state_root = self
.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::BlockId(BlockId::Height(
lc_block.inner_lite.height,
)),
})
.await
.map(|x| x.chunks[0].prev_state_root)
.map_err(|x| Box::new(x) as _)?;

Ok(near::consensus_state::ConsensusState {
state: convert_block_header_inner(lc_block.inner_lite),
chunk_prev_state_root: prev_state_root,
timestamp: self
.rpc
.call(methods::block::RpcBlockRequest {
block_reference: BlockReference::Finality(Finality::Final),
})
.await
.map(|x| x.header.timestamp_nanosec.try_into().expect("idk bro"))
.map_err(|x| Box::new(x))?,
})
}
}

pub fn convert_block_producers(
bps: Vec<near_primitives::views::validator_stake_view::ValidatorStakeView>,
) -> Vec<near::validator_stake_view::ValidatorStakeView> {
bps.into_iter()
.map(|stake| {
let near_primitives::views::validator_stake_view::ValidatorStakeView::V1(stake) = stake;
let stake = near::validator_stake_view::ValidatorStakeView::V1(
near::validator_stake_view::ValidatorStakeViewV1 {
account_id: stake.account_id,
public_key: ::near::types::PublicKey::Ed25519(
stake.public_key.key_data().try_into().unwrap(),
),
stake: stake.stake,
},
);
stake
})
.collect()
}

pub fn convert_block_header_inner(
block_view: near_primitives::views::BlockHeaderInnerLiteView,
) -> near::block_header_inner::BlockHeaderInnerLiteView {
near::block_header_inner::BlockHeaderInnerLiteView {
height: block_view.height,
epoch_id: near_primitives_core::CryptoHash(block_view.epoch_id.0),
next_epoch_id: near_primitives_core::CryptoHash(block_view.next_epoch_id.0),
prev_state_root: near_primitives_core::CryptoHash(block_view.prev_state_root.0),
outcome_root: near_primitives_core::CryptoHash(block_view.outcome_root.0),
timestamp: block_view.timestamp,
timestamp_nanosec: block_view.timestamp_nanosec,
next_bp_hash: block_view.next_bp_hash.0.into(),
block_merkle_root: near_primitives_core::CryptoHash(block_view.block_merkle_root.0),
}
}
2 changes: 1 addition & 1 deletion lib/near-verifier/src/lib.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ use unionlabs::{
approval::ApprovalInner,
block_header_inner::{BlockHeaderInnerLite, BlockHeaderInnerLiteView},
light_client_block::LightClientBlockView,
validator_stake::ValidatorStakeView,
validator_stake_view::ValidatorStakeView,
},
near::types::{Direction, MerklePath, PublicKey, Signature},
};
5 changes: 0 additions & 5 deletions lib/near-verifier/src/state_proof.rs
Original file line number Diff line number Diff line change
@@ -5,11 +5,6 @@ use near_primitives_core::{hash::CryptoHash, types::AccountId};

use crate::nibble_slice::NibbleSlice;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RawStateProof {
pub state_proof: Vec<Vec<u8>>,
}

impl RawStateProof {
pub fn parse(self) -> StateProof {
let state_proof_nodes = self
2 changes: 2 additions & 0 deletions lib/relay-message/src/lib.rs
Original file line number Diff line number Diff line change
@@ -250,6 +250,8 @@ pub enum AnyLightClientIdentified<T: AnyLightClient> {

/// The 08-wasm client tracking the state of Cosmos.
CosmosOnCosmos(lc!(Cosmos => Cosmos)),
// NearOnUnion(lc!(Near => Wasm<Union>)),
// UnionOnNear(lc!(Wasm<Union> => Near)),
}

impl<T: AnyLightClient> AnyLightClientIdentified<T> {
4 changes: 4 additions & 0 deletions lib/unionlabs/src/encoding.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,10 @@ impl Encoding for Ssz {}
pub enum Json {}
impl Encoding for Json {}

// TODO: feature gate this
pub enum Borsh {}
impl Encoding for Borsh {}

impl<T> Encode<Json> for T
where
T: serde::Serialize,
12 changes: 9 additions & 3 deletions lib/unionlabs/src/ibc/core/client/height.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use macros::model;
use serde::{Deserialize, Serialize};
use ssz::Ssz;

#[derive(Ssz, Default, Copy, Ord, Eq)]
#[derive(Ssz, Default, Copy, Eq)]
#[model(borsh, proto(raw(protos::ibc::core::client::v1::Height), into, from))]
#[debug("Height({self})")]
#[cfg_attr(feature = "schemars", derive(::schemars::JsonSchema))]
@@ -89,11 +89,17 @@ impl From<Height> for protos::ibc::core::client::v1::Height {

impl PartialOrd for Height {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(match self.revision_number.cmp(&other.revision_number) {
Some(self.cmp(other))
}
}

impl Ord for Height {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
match self.revision_number.cmp(&other.revision_number) {
core::cmp::Ordering::Less => core::cmp::Ordering::Less,
core::cmp::Ordering::Equal => self.revision_height.cmp(&other.revision_height),
core::cmp::Ordering::Greater => core::cmp::Ordering::Greater,
})
}
}
}

2 changes: 1 addition & 1 deletion lib/unionlabs/src/ibc/lightclients/near.rs
Original file line number Diff line number Diff line change
@@ -4,4 +4,4 @@ pub mod client_state;
pub mod consensus_state;
pub mod header;
pub mod light_client_block;
pub mod validator_stake;
pub mod validator_stake_view;
3 changes: 3 additions & 0 deletions lib/unionlabs/src/ibc/lightclients/near/block_header_inner.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO: Use h256 here for all hash types?

use borsh::{BorshDeserialize, BorshSerialize};
use macros::model;
use near_primitives_core::{
@@ -21,6 +23,7 @@ pub struct BlockHeaderInnerLiteView {
pub outcome_root: CryptoHash,
// TODO(aeryz): put deprecated?
/// Legacy json number. Should not be used.
// #[deprecated]
pub timestamp: u64,
// TODO(aeryz): #[serde(with = "dec_format")]
pub timestamp_nanosec: u64,
5 changes: 4 additions & 1 deletion lib/unionlabs/src/ibc/lightclients/near/client_state.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use macros::model;
use near_primitives_core::account::id::ParseAccountError;
use near_sdk::AccountId;

use super::validator_stake::{TryFromValidatorStakeView, ValidatorStakeView};
use super::validator_stake_view::{TryFromValidatorStakeView, ValidatorStakeView};

#[model(proto(
raw(protos::union::ibc::lightclients::near::v1::ClientState),
@@ -12,9 +12,12 @@ use super::validator_stake::{TryFromValidatorStakeView, ValidatorStakeView};
))]
#[derive(BorshSerialize, BorshDeserialize)]
pub struct ClientState {
pub chain_id: String,
pub latest_height: u64,
pub ibc_account_id: AccountId,
// TODO: Remove this option
pub initial_block_producers: Option<Vec<ValidatorStakeView>>,
// TODO: Make option
pub frozen_height: u64,
}

Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use near_primitives_core::hash::CryptoHash;

use super::{
block_header_inner::{BlockHeaderInnerLiteView, TryFromBlockHeaderInnerLiteViewError},
validator_stake::{TryFromValidatorStakeView, ValidatorStakeView},
validator_stake_view::{TryFromValidatorStakeView, ValidatorStakeView},
};
use crate::{
errors::{required, MissingField},
Original file line number Diff line number Diff line change
@@ -74,6 +74,7 @@ impl TryFrom<protos::union::ibc::lightclients::near::v1::ValidatorStakeView>
.try_into()
.map_err(TryFromValidatorStakeView::PublicKey)?,
// TODO(aeryz): make this a u128
// this will need to be done through string (or two fields, low and high bits)
stake: value.balance.try_into().unwrap(),
}))
}
3 changes: 3 additions & 0 deletions lib/unionlabs/src/near/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub mod raw_state_proof;
pub mod types;

pub const NEAR_REVISION_NUMBER: u64 = 0;
6 changes: 6 additions & 0 deletions lib/unionlabs/src/near/raw_state_proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use macros::model;

#[model]
pub struct RawStateProof {
pub state_proof: Vec<Vec<u8>>,
}
Loading