Skip to content

Commit

Permalink
feat(grpc)!: enable celestia-grpc usage within wasm
Browse files Browse the repository at this point in the history
  • Loading branch information
zvolin committed Dec 10, 2024
1 parent 82c51f6 commit 82dc2cb
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 110 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ jobs:
- name: Run rpc wasm test
run: wasm-pack test --headless --chrome rpc --features=wasm-bindgen

- name: Run grpc wasm test
run: wasm-pack test --headless --chrome grpc

- name: Test node-wasm crate
# We're running node-wasm tests in release mode to get around a failing debug assertion
# https://github.com/libp2p/rust-libp2p/issues/5618
Expand Down
79 changes: 62 additions & 17 deletions Cargo.lock

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

10 changes: 10 additions & 0 deletions ci/Dockerfile.grpcwebproxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM docker.io/alpine:3.19.1

RUN apk update && apk add --no-cache wget unzip

RUN wget -O grpcwebproxy.zip https://github.com/improbable-eng/grpc-web/releases/download/v0.15.0/grpcwebproxy-v0.15.0-linux-x86_64.zip && \
unzip grpcwebproxy.zip && \
mv dist/grpcwebproxy* /usr/local/bin/grpcwebproxy && \
rm grpcwebproxy.zip

ENTRYPOINT ["/usr/local/bin/grpcwebproxy"]
5 changes: 3 additions & 2 deletions ci/credentials/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/*
!/.gitignore
*
!/bridge-0.*
/bridge-0.jwt
1 change: 1 addition & 0 deletions ci/credentials/bridge-0.addr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
celestia1t52q7uqgnjfzdh3wx5m5phvma3umrq8k6tq2p9
9 changes: 9 additions & 0 deletions ci/credentials/bridge-0.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN TENDERMINT PRIVATE KEY-----
type: secp256k1
kdf: bcrypt
salt: 2D070635EBDE45AD8845CE82FB6D5A89

PboW9MooV09RX733cy55wuciTKhveZdY2H5NhJ0DIhfHxfyR11viqxy4wJ917rkG
OfsQph8JPYp315ZRYq7vUIsbTreMgnlRSdqPmL0=
=SLpn
-----END TENDERMINT PRIVATE KEY-----
1 change: 1 addition & 0 deletions ci/credentials/bridge-0.plaintext-key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
393fdb5def075819de55756b45c9e2c8531a8c78dd6eede483d3440e9457d839
10 changes: 10 additions & 0 deletions ci/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ services:
- credentials:/credentials
- genesis:/genesis

grpcwebproxy:
image: grpcwebproxy
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile.grpcwebproxy
command: --backend_addr=validator:9090 --run_tls_server=false --allow_all_origins
ports:
- 18080:8080

bridge-0:
image: bridge
platform: "linux/amd64"
Expand Down
16 changes: 15 additions & 1 deletion grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ prost.workspace = true
tendermint-proto.workspace = true
tendermint.workspace = true

bytes = "1.8"
hex = "0.4.3"
http-body = "1"
k256 = "0.13.4"
serde = "1.0.215"
thiserror = "1.0.61"
Expand All @@ -35,7 +37,19 @@ tonic = { version = "0.12.3", default-features = false, features = [
]}

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tonic = { version = "0.12.3", default-features = false, features = [ "transport" ] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.15", features = ["js"] }
tonic-web-wasm-client = "0.6"

[dev-dependencies]
anyhow = "1.0.86"

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
dotenvy = "0.15.7"
tokio = { version = "1.38.0", features = ["rt", "macros"] }
tonic = { version = "0.12.3", optional = true, default-features = false, features = [ "transport" ] }

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
gloo-timers = { version = "0.3.0", features = ["futures"] }
wasm-bindgen-test = "0.3.42"
6 changes: 3 additions & 3 deletions grpc/grpc-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ impl GrpcMethod {
let method = quote! {
#doc_hash #doc_group
pub #signature {
let mut client = #grpc_client_struct :: with_interceptor(
self.grpc_channel.clone(),
self.auth_interceptor.clone(),
let mut client = #grpc_client_struct :: new(
self.transport.clone(),
);

let request = ::tonic::Request::new(( #( #params ),* ).into_parameter());
let response = client. #grpc_method_name (request).await;
response?.into_inner().try_from_response()
Expand Down
54 changes: 37 additions & 17 deletions grpc/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use prost::Message;
use tonic::service::Interceptor;
use tonic::transport::Channel;

use bytes::Bytes;
use celestia_grpc_macros::grpc_method;
use celestia_proto::celestia::blob::v1::query_client::QueryClient as BlobQueryClient;
use celestia_proto::cosmos::auth::v1beta1::query_client::QueryClient as AuthQueryClient;
Expand All @@ -13,6 +10,10 @@ use celestia_types::blob::{Blob, BlobParams, RawBlobTx};
use celestia_types::block::Block;
use celestia_types::state::auth::AuthParams;
use celestia_types::state::{Address, TxResponse};
use http_body::Body;
use prost::Message;
use tonic::body::BoxBody;
use tonic::client::GrpcService;

use crate::types::auth::Account;
use crate::types::tx::GetTxResponse;
Expand All @@ -21,25 +22,23 @@ use crate::Error;

pub use celestia_proto::cosmos::tx::v1beta1::BroadcastMode;

type StdError = Box<dyn std::error::Error + Send + Sync + 'static>;

/// Struct wrapping all the tonic types and doing type conversion behind the scenes.
pub struct GrpcClient<I>
where
I: Interceptor,
{
grpc_channel: Channel,
auth_interceptor: I,
pub struct GrpcClient<T> {
transport: T,
}

impl<I> GrpcClient<I>
impl<T> GrpcClient<T>
where
I: Interceptor + Clone,
T: GrpcService<BoxBody> + Clone,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
{
/// Create a new client out of channel and optional auth
pub fn new(grpc_channel: Channel, auth_interceptor: I) -> Self {
Self {
grpc_channel,
auth_interceptor,
}
pub fn new(transport: T) -> Self {
Self { transport }
}

/// Get Minimum Gas price
Expand Down Expand Up @@ -107,3 +106,24 @@ where
#[grpc_method(TxServiceClient::get_tx)]
async fn get_tx(&mut self, hash: String) -> Result<GetTxResponse, Error>;
}

#[cfg(not(target_arch = "wasm32"))]
impl GrpcClient<tonic::transport::Channel> {
/// Create a new client connected to the given `url` with default
/// settings of [`tonic::transport::Channel`].
pub fn with_url(url: impl Into<String>) -> Result<Self, tonic::transport::Error> {
let channel = tonic::transport::Endpoint::from_shared(url.into())?.connect_lazy();
Ok(Self { transport: channel })
}
}

#[cfg(target_arch = "wasm32")]
impl GrpcClient<tonic_web_wasm_client::Client> {
/// Create a new client connected to the given `url` with default
/// settings of [`tonic_web_wasm_client::Client`].
pub fn with_grpcweb_url(url: impl Into<String>) -> Self {
Self {
transport: tonic_web_wasm_client::Client::new(url.into()),
}
}
}
1 change: 0 additions & 1 deletion grpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![doc = include_str!("../README.md")]
#![cfg(not(target_arch = "wasm32"))]

mod client;
mod error;
Expand Down
Loading

0 comments on commit 82dc2cb

Please sign in to comment.