Skip to content

Commit

Permalink
docs(unionlabs): add README to unionlabs (#1193)
Browse files Browse the repository at this point in the history
Also configured crane to include any files in the package.include array
in workspace members.
  • Loading branch information
benluelo authored Jan 27, 2024
2 parents a810677 + 2328a53 commit 92401e5
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 56 deletions.
13 changes: 9 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
# NOTE: All paths must be listed out (i.e. no globs) since ifd is still broken in nix (still can't import the output of `cargo metadata` :( ). See crane.nix for where this is used.
members = [
"lib/beacon-api",
"lib/chain-utils",
Expand All @@ -9,16 +10,20 @@ members = [
"lib/serde-utils",
"lib/unionlabs",
"lib/ics23",
"lib/*/fuzz",
"lib/unionlabs/fuzz",
"tools/generate-rust-sol-bindings",
"light-clients/*",
"e2e/*",
"light-clients/cometbls-light-client",
"light-clients/ethereum-light-client",
"e2e/ensure-blocks",
"generated/rust",
"generated/contracts",
"ucli",
"unionvisor",
"voyager",
"cosmwasm/*",
"cosmwasm/token-factory-api",
"cosmwasm/ucs00-pingpong",
"cosmwasm/ucs01-relay-api",
"cosmwasm/ucs01-relay",
"hubble",
"tools/parse-wasm-client-type",
"zerg",
Expand Down
6 changes: 2 additions & 4 deletions dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ roadmap
rollups
rpath
rsplit
ruint
runtimeservices
rustc
rustfilt
Expand Down Expand Up @@ -775,7 +776,7 @@ unbonded
unbonding
undelegate
undelegations
undelrine
unergonomic
unescrow
uninit
unionbuild
Expand Down Expand Up @@ -808,8 +809,6 @@ urql
ursi
utilised
utilising
uunionx
uuno
valbz
valcons
valconspub
Expand Down Expand Up @@ -853,7 +852,6 @@ xprv
xqxp
ypyp
yqyp
zedxv
zellij
zerg
zerolog
Expand Down
1 change: 1 addition & 0 deletions lib/unionlabs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
edition = "2021"
include = ["README.md"]
name = "unionlabs"
version = "0.1.0"

Expand Down
25 changes: 25 additions & 0 deletions lib/unionlabs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# `unionlabs`

This crate contains types and traits used throughout our stack.

## Wrappers around generated code

Due to how prost generates protobuf bindings, working with the raw generated code is quite unergonomic and error-prone. This library provides a unified interface for all encodings (protobuf, ethabi, etc), allowing for both more type safety and ease of use for downstream users.

The general pattern is as follows, using `Channel` as an example:

- prost generated code: `protos::ibc::core::channel::v1::Channel`
- ethers generated code: `contracts::ibc_handler::IbcCoreChannelV1ChannelData`
- unionlabs type: `unionlabs::ibc::core::channel::Channel`

Note that the `unionlabs` type doesn't include the version - we currently only support the latest version of each module.

## Hash and UInt

The most commonly used crate for hash and uint types is parity's [primitive-types](https://docs.rs/primitive-types/latest/primitive_types/), which is quite old and has quite a lot of issues ([hidden panics](https://github.com/paritytech/parity-common/issues/764), [strange Display impl](https://github.com/paritytech/parity-common/issues/656), [parsing inconsistencies](https://github.com/paritytech/parity-common/issues/643), etc). There are alternatives, such as [ruint](https://github.com/recmo/uint), which is used in [alloy](https://github.com/alloy-rs/core), but for simplicity we currently define our own hash and uint types (note that our uint is just a wrapper around `primitive-types::U256` that provides sane string parsing and Display defaults). We will likely migrate to `ruint` in the future, once we migrate to `alloy` from `ethers`.

## Encoding and Decoding

This library exposes generic Encoding and Decoding traits, to allow for abstracting over the encoding used for a type (essentially a poor man's HKTs). See the Voyager source code for examples of how this can be used.

Note: The `{TryFrom,From,Into}{Proto,EthAbi}` traits are a previous (less powerful) iteration of this concept, and are only public while the rest of the codebase is still migrating to the new `Encode<_>`/`Decode<_>` API.
5 changes: 2 additions & 3 deletions lib/unionlabs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![doc = include_str!("../README.md")]
#![deny(clippy::pedantic)]
#![allow(clippy::missing_errors_doc, clippy::module_name_repetitions)]

Expand Down Expand Up @@ -121,9 +122,6 @@ pub mod errors {
}
}

// TODO: Move these traits into `ibc`

// Into<Self::Proto>
pub trait Proto {
// all prost generated code implements Default
type Proto: Message + Default;
Expand Down Expand Up @@ -380,6 +378,7 @@ pub enum WasmClientTypeParseError {
UnknownType(String),
}

// TODO: Move this and the above type into tools/parse-wasm-client-type, and make it into a library with an optional `parse` feature (so as to not bring in the very heavy wasmparser stack where it's not needed)
pub fn parse_wasm_client_type(
bz: impl AsRef<[u8]>,
) -> Result<Option<WasmClientType>, WasmClientTypeParseError> {
Expand Down
2 changes: 1 addition & 1 deletion lib/unionlabs/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub mod from_str_exact {
/// Represents a chain. One [`Chain`] may have many related [`LightClient`]s for connecting to
/// various other [`Chain`]s, all sharing a common config.
pub trait Chain: Sized + Send + Sync + 'static {
/// Expected to be unique across all implementations. Note that Wasm<_> implements this by passing through to the host chain, as Wasm<A> <-> Wasm<B> and A <-> B simultaneously is not currently supported.
/// Expected to be unique across all implementations. Note that Wasm<_> implements this by passing through to the host chain, as `Wasm<A> <-> Wasm<B>` and `A <-> B` simultaneously is not currently supported.
type ChainType: FromStrExact;
type SelfClientState: Debug
+ Clone
Expand Down
2 changes: 1 addition & 1 deletion site/src/components/Socials.astro
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ let socialLinks = [
class='h-10'
/>
<div class='mt-4'>
<span class='mt-16 border-b-[1px] uppercase border-white text-semibold undelrine'>
<span class='mt-16 border-b-[1px] uppercase border-white text-semibold'>
{socialLink.cta} -&gt;
</span>
</div>
Expand Down
136 changes: 93 additions & 43 deletions tools/rust/crane.nix
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# cspell:ignore tomls
{ inputs, ... }: {
perSystem = { self', pkgs, rust, system, lib, dbg, inputs', ... }:
let
Expand Down Expand Up @@ -65,6 +66,7 @@
};

workspaceCargoToml = lib.trivial.importTOML (root + "/Cargo.toml");

workspaceCargoLockPath = root + "/Cargo.lock";

buildWorkspaceMember =
Expand Down Expand Up @@ -154,38 +156,64 @@
"expected crateDirFromRoot to be a string, but it was a ${builtins.typeOf crateDirFromRoot}: ${crateDirFromRoot}"
crateDirFromRoot);

crateSrc = mkCleanSrc {
name = cratePname;
srcFilter = path': type: ((additionalSrcFilter path' type)
# TODO: only include this filter for tests; maybe by adding to preConfigureHooks?
|| (additionalTestSrcFilter path' type))
&& (
path' == "Cargo.toml"
|| path' == "Cargo.lock"
|| (
builtins.any
(depPath: ensureDirectoryIncluded {
inherit path';
pathToInclude = depPath;
})
workspaceDepsForCrate
)
# Yes, this does need to be filtered twice - once in the original filter so it's included
# in the cargo sources, and once again so it's included when filtering down to workspace
# dependencies
|| (additionalSrcFilter path' type)
# TODO: Only include this filter for tests; maybe by adding to preConfigureHooks?
# apparently nix doesn't cache calls to builtins.readFile (which importTOML calls internally), so we cache the cargo tomls here
# this saves ~2-3 minutes in evaluation time
workspaceDepsForCrateCargoTomls = builtins.listToAttrs (map (dep: lib.attrsets.nameValuePair dep (lib.trivial.importTOML "${root}/${dep}/Cargo.toml")) workspaceDepsForCrate);

crateSrc =
let
isIncluded = path': builtins.elem path'
(
lib.unique
(lib.flatten
(map
(dep: map
(includedPath: "${dep}/${includedPath}")
(pkgs.lib.attrsets.attrByPath
[ "package" "include" ]
[ ]
(workspaceDepsForCrateCargoTomls.${dep})
)
)
workspaceDepsForCrate)
)
);
in
mkCleanSrc {
name = cratePname;
srcFilter = path': type: ((additionalSrcFilter path' type)
# TODO: only include this filter for tests; maybe by adding to preConfigureHooks?
|| (additionalTestSrcFilter path' type)
);
};
|| (isIncluded path')
)
&& (
path' == "Cargo.toml"
|| path' == "Cargo.lock"
|| (
builtins.any
(depPath: ensureDirectoryIncluded {
inherit path';
pathToInclude = depPath;
})
workspaceDepsForCrate
)
# Yes, this does need to be filtered twice - once in the original filter so it's included
# in the cargo sources, and once again so it's included when filtering down to workspace
# dependencies
|| (additionalSrcFilter path' type)
# TODO: Only include this filter for tests; maybe by adding to preConfigureHooks?
|| (additionalTestSrcFilter path' type)
|| (isIncluded path')
);
};

# patch the workspace Cargo.toml to only contain the local dependencies required to build this crate.
patchedWorkspaceToml =
let
patchedCargoToml = (pkgs.formats.toml { }).generate
"Cargo.toml"
(lib.recursiveUpdate workspaceCargoToml {
workspace. members = workspaceDepsForCrate;
workspace.members = workspaceDepsForCrate;
});
in
# REVIEW: This can maybe be a runCommand?
Expand Down Expand Up @@ -300,26 +328,48 @@
};
};

allCargoTomls = builtins.listToAttrs (map (dep: lib.attrsets.nameValuePair dep (lib.trivial.importTOML "${root}/${dep}/Cargo.toml")) workspaceCargoToml.workspace.members);

cargoWorkspaceSrc = mkCleanSrc {
name = "cargo-workspace-src";
srcFilter =
path: _type: (pkgs.lib.hasPrefix "hubble/src/graphql/" path || pkgs.lib.hasPrefix ".sqlx" path) ||
(pkgs.lib.hasPrefix "unionvisor/src/testdata/" path) ||
(pkgs.lib.hasPrefix ".sqlx" path) ||
((pkgs.lib.hasPrefix "lib/pg-queue/.sqlx" path)) ||
(pkgs.lib.hasPrefix "hubble/src/graphql" path) ||
((lib.hasPrefix "lib/ethereum-verifier/src/test" path)
&& (lib.strings.hasSuffix ".json" path)) ||
(ensureDirectoryIncluded {
path' = path;
pathToInclude = "light-clients/ethereum-light-client/src/test";
}) ||
(ensureDirectoryIncluded {
path' = path;
pathToInclude = "light-clients/cometbls-light-client/src/test";
});
};
cargoWorkspaceSrc =
let
allIncludes = lib.unique
(lib.flatten
(map
(dep: map
(includedPath: "${dep}/${includedPath}")
(pkgs.lib.attrsets.attrByPath
[ "package" "include" ]
[ ]
(allCargoTomls.${dep})
)
)
workspaceCargoToml.workspace.members)
);
isIncluded = path': builtins.elem path'
(
allIncludes
);
in
mkCleanSrc {
name = "cargo-workspace-src";
srcFilter =
path: _type: (pkgs.lib.hasPrefix "hubble/src/graphql/" path || pkgs.lib.hasPrefix ".sqlx" path) ||
(pkgs.lib.hasPrefix "unionvisor/src/testdata/" path) ||
(pkgs.lib.hasPrefix ".sqlx" path) ||
(pkgs.lib.hasPrefix "lib/pg-queue/.sqlx" path) ||
(pkgs.lib.hasPrefix "hubble/src/graphql" path) ||
((lib.hasPrefix "lib/ethereum-verifier/src/test" path)
&& (lib.strings.hasSuffix ".json" path)) ||
(ensureDirectoryIncluded {
path' = path;
pathToInclude = "light-clients/ethereum-light-client/src/test";
}) ||
(isIncluded path) ||
(ensureDirectoryIncluded {
path' = path;
pathToInclude = "light-clients/cometbls-light-client/src/test";
});
};
in
{
_module.args = {
Expand Down

0 comments on commit 92401e5

Please sign in to comment.