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(voyager): split out voyager-core #2999

Merged
merged 1 commit into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ members = [
"lib/unionlabs",
"lib/zktrie-rs",
"lib/voyager-message",
"lib/voyager-core",

"lib/near/near-ibc",
"lib/near/near-light-client",
Expand Down Expand Up @@ -99,6 +100,7 @@ members = [
"lib/aptos-verifier",

"lib/reconnecting-jsonrpc-ws-client",
"lib/voyager-core",
]

[workspace.package]
Expand Down Expand Up @@ -156,6 +158,7 @@ tendermint-verifier = { path = "lib/tendermint-verifier", default-fea
token-factory-api = { path = "cosmwasm/token-factory-api", default-features = false }
ucs01-relay-api = { path = "cosmwasm/ucs01-relay-api", default-features = false }
unionlabs = { path = "lib/unionlabs", default-features = false }
voyager-core = { path = "lib/voyager-core", default-features = false }
voyager-message = { path = "lib/voyager-message", default-features = false }
zktrie = { path = "lib/zktrie-rs", default-features = false }

Expand Down
10 changes: 5 additions & 5 deletions generated/rust/aptos-move-ibc/Cargo.toml

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

2 changes: 1 addition & 1 deletion lib/ics-008-wasm-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ workspace = true
cosmwasm-std = { workspace = true }
dlmalloc = { workspace = true, features = ["global"] }
frame-support-procedural = { workspace = true }
macros.workspace = true
macros = { workspace = true }
prost = { workspace = true }
protos = { workspace = true, features = ["proto_full", "std"] }
serde = { workspace = true, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion lib/unionlabs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ typenum = { workspace = true, features = ["const-generics", "no
uint = "*"
wasmparser = { version = "0.113" }

base64.workspace = true
base64 = { workspace = true }
bcs = { workspace = true }
borsh = { workspace = true, features = ["borsh-derive"], optional = true }
bs58 = "0.4"
Expand Down
26 changes: 26 additions & 0 deletions lib/voyager-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
edition = { workspace = true }
license-file = { workspace = true }
name = "voyager-core"
repository = { workspace = true }
resolver = "2"
version = "0.1.0"

[lints]
workspace = true

[dependencies]
enumorph = { workspace = true }
hex = { workspace = true }
macros = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
unionlabs = { workspace = true }

[dev-dependencies]
hex-literal = { workspace = true }

[features]
default = []
272 changes: 272 additions & 0 deletions lib/voyager-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
#![warn(clippy::pedantic)]

use macros::{apply, model};
use serde_json::Value;
use unionlabs::{hash::H256, ibc::core::client::height::Height};

/// Represents the IBC interface of a chain.
///
/// Since multiple chains with different consensus mechanisms can have the same
/// execution environment, this value is used to describe how the IBC state is
/// stored on-chain and how the IBC stack is to be interacted with.
#[apply(str_newtype)]
pub struct IbcInterface;

/// Well-known IBC interfaces, defined as constants for reusability and to allow
/// for pattern matching.
impl IbcInterface<'static> {
/// Native light clients in ibc-go, through the client v1 router. This
/// entrypoint uses protobuf [`Any`] wrapping to route to the correct
/// module, such as "/ibc.lightclients.tendermint.v1.ClientState" for native
/// 07-tendermint clients.
///
/// [`Any`]: https://protobuf.dev/programming-guides/proto3/#any
pub const IBC_GO_V8_NATIVE: &'static str = "ibc-go-v8/native";

/// 08-wasm light clients in ibc-go, through the client v1 router. Similar
/// to the ibc-go-v8/native entrypoint, this module also uses [`Any`]
/// wrapping for client routing, however, there is another level of
/// indirection, since the `Any` routing only routes to the wasm module. All
/// state for wasm clients is [wrapped](wasm-protos), with the internal
/// state being opaque bytes to be interpreted by the light client.
///
/// [`Any`]: https://protobuf.dev/programming-guides/proto3/#any
/// [wasm-protos]: https://github.com/cosmos/ibc-go/blob/release/v8.4.x/proto/ibc/lightclients/wasm/v1/wasm.proto
pub const IBC_GO_V8_08_WASM: &'static str = "ibc-go-v8/08-wasm";

/// Solidity light clients, run via Union's IBC solidity stack. This stack
/// is fully virtualized in the EVM, and as such can be run on any chain
/// running the EVM as part of their execution layer (ethereum, ethereum
/// L2s, berachain, etc).
pub const IBC_SOLIDITY: &'static str = "ibc-solidity";

pub const IBC_MOVE_APTOS: &'static str = "ibc-move/aptos";

// lots more to come - near, fuel - stay tuned
}

/// Newtype for client types. Clients of the same type have the same client
/// state, consensus state, and header (client update) types.
#[apply(str_newtype)]
pub struct ClientType;

/// Well-known client types, defined as constants for reusability and to allow
/// for pattern matching.
impl ClientType<'static> {
/// A client tracking [CometBLS] consensus.
///
/// [CometBLS]: https://github.com/unionlabs/cometbls
pub const COMETBLS: &'static str = "cometbls";

/// A client tracking vanilla [CometBFT] (Tendermint) consensus.
///
/// [CometBFT]: https://github.com/cometbft/cometbft
pub const TENDERMINT: &'static str = "tendermint";

/// A client tracking the Ethereum beacon chain consensus, with the mainnet
/// configuration.
pub const ETHEREUM_MAINNET: &'static str = "ethereum-mainnet";

/// A client tracking the Ethereum beacon chain consensus, with the minimal
/// configuration.
pub const ETHEREUM_MINIMAL: &'static str = "ethereum-minimal";

/// A client tracking the state of the [Scroll] zkevm L2, settling on
/// Ethereum.
///
/// [Scroll]: https://github.com/scroll-tech/scroll
pub const SCROLL: &'static str = "scroll";

/// A client tracking the state of the [Arbitrum] optimistic L2, settling on
/// Ethereum.
///
/// [Arbitrum]: https://github.com/OffchainLabs/nitro-contracts
pub const ARBITRUM: &'static str = "arbitrum";

/// A client tracking the state of a [BeaconKit] chain.
///
/// [BeaconKit]: https://github.com/berachain/beacon-kit
pub const BEACON_KIT: &'static str = "beacon-kit";

/// A client tracking the state of a [Movement] chain.
///
/// [Movement]: https://github.com/movementlabsxyz/movement
pub const MOVEMENT: &'static str = "movement";

// lots more to come - near, linea, polygon - stay tuned
}

/// Identifier used to uniquely identify a chain, as provided by the chain
/// itself.
///
/// # Examples
///
/// | chain id | chain |
/// | --------------- | ------------------------ |
/// | 1 | ethereum mainnet |
/// | 11155111 | ethereum sepolia testnet |
/// | union-testnet-8 | union testnet |
/// | stargaze-1 | stargaze mainnet |
#[apply(str_newtype)]
pub struct ChainId;

/// The type of a light client on a chain, along with the IBC interface it's on
/// (and any associated metadata).
///
/// # Examples
///
/// - 08-wasm client on union, tracking ethereum mainnet: `(ibc-go-v8/08-wasm,
/// ethereum_mainnet, {"checksum": "0x..."})`
/// - 07-tendermint client on stargaze, tracking osmosis: `(ibc-go-v8/native,
/// tendermint)`
/// - 08-wasm client on babylon, tracking union: `(ibc-go-v8/08-wasm, cometbls,
/// {"checksum": "0x..."}))`
/// - cometbls client on scroll, tracking union: `(ibc-solidity, cometbls)`
#[model]
pub struct ClientInfo {
pub client_type: ClientType<'static>,
pub ibc_interface: IbcInterface<'static>,
/// Additional metadata about this client.
///
/// This is currently only used for threading the checksum for ibc-go
/// 08-wasm clients, and can likely be removed when support for that IBC
/// interface is dropped.
#[serde(default)]
pub metadata: Value,
}

#[model]
pub struct ClientStateMeta {
/// The counterparty height this client has been updated to. A consensus
/// state will exist at this height.
pub height: Height,

/// The chain id of the counterparty chain this client tracks.
pub chain_id: ChainId<'static>,
}

#[model]
pub struct ConsensusStateMeta {
/// The timestamp of the counterparty at the height represented by this
/// consensus state.
pub timestamp_nanos: u64,
}

#[model]
pub struct IbcGo08WasmClientMetadata {
pub checksum: H256,
}

#[macro_export]
macro_rules! str_newtype {
(
$(#[doc = $doc:literal])+
$vis:vis struct $Struct:ident;
) => {
$(#[doc = $doc])+
#[derive(macros::Debug, Clone, PartialEq, Eq, Hash, ::serde::Serialize, ::serde::Deserialize)]
// I tested this and apparently it's not required (newtype is automatically transparent?) but
// keeping it here for clarity
#[serde(transparent)]
#[debug("{}({:?})", stringify!($Struct), self.0)]
$vis struct $Struct<'a>(#[doc(hidden)] ::std::borrow::Cow<'a, str>);

impl<'a> ::core::fmt::Display for $Struct<'a> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Display::fmt(&self.0, f)
}
}

#[allow(unused)]
impl<'a> $Struct<'a> {
/// Construct a new [`
#[doc = stringify!($Struct)]
/// `].
///
/// This will capture the lifetime of the passed in value:
/// ```
#[doc = concat!(
"let _: ",
stringify!($Struct),
"<'static> = ",
stringify!($Struct),
"::new(\"static string\");"
)]
/// let owned_string: String = "owned string".into();
///
/// // not static
#[doc = concat!(
"let _: ",
stringify!($Struct),
"<'_> = ",
stringify!($Struct),
"::new(&owned_string);"
)]
#[doc = concat!(
"let _: ",
stringify!($Struct),
"<'static> = ",
stringify!($Struct),
"::new(owned_string);"
)]
pub fn new(s: impl Into<::std::borrow::Cow<'a, str>>) -> Self {
Self(s.into())
}

/// Convert this [`
#[doc = concat!(stringify!($Struct))]
/// `] into an owned version of itself.
///
/// This will allocate if the contained value is not already on the heap even if `'a == 'static`.
#[must_use = concat!("converting to an owned version of ", stringify!($Struct), " has no effect other than possibly allocating, if the returned value is not needed then the call to this method can be removed altogether and the value dropped directly")]
pub fn into_owned(self) -> $Struct<'static> {
use std::borrow::Cow;

$Struct(match self.0 {
Cow::Borrowed(x) => Cow::Owned(x.to_owned()),
Cow::Owned(x) => Cow::Owned(x),
})
}

/// Extracts a string slice containing the entire contained value.
#[must_use = "getting a reference to the contained string slice has no effect"]
pub fn as_str(&self) -> &str {
self.0.as_ref()
}


/// Borrow this [`
#[doc = stringify!($Struct)]
/// `], returning a new owned value pointing to the same data.
///
/// ```
#[doc = concat!("let t = ", stringify!($Struct), "::new_static(\"static\");")]
///
/// takes_ownership(t.borrow());
/// takes_ownership(t);
///
#[doc = concat!("fn takes_ownership<'a>(c: ", stringify!($Struct), "<'a>) {}")]
/// ```
#[must_use = "borrowing the inner value has no effect"]
pub fn borrow<'b>(&'a self) -> $Struct<'b>
where
'a: 'b,
{
use std::borrow::Cow;

match self.0 {
Cow::Borrowed(s) => Self(Cow::Borrowed(s)),
Cow::Owned(ref s) => Self(Cow::Borrowed(s.as_str())),
}
}
}

impl $Struct<'static> {
/// `const`-friendly version of [`Self::new`].
#[must_use = concat!("constructing a ", stringify!($Struct), " has no effect")]
pub const fn new_static(ibc_interface: &'static str) -> Self {
Self(::std::borrow::Cow::Borrowed(ibc_interface))
}
}
};
}
1 change: 1 addition & 0 deletions lib/voyager-message/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["json"] }
typenum = { workspace = true }
unionlabs = { workspace = true, features = ["ethabi"] }
voyager-core = { workspace = true }

[dev-dependencies]
hex-literal = { workspace = true }
Expand Down
Loading