diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6fe5aeb..ee2734fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - [\#172](https://github.com/Manta-Network/manta-rs/pull/172) Add abstract Phase 2 for Groth16 trusted setup ### Changed +- [\#191](https://github.com/Manta-Network/manta-rs/pull/191) Move HTTP Utilities to `manta-util` ### Deprecated diff --git a/manta-parameters/Cargo.toml b/manta-parameters/Cargo.toml index ae14c1893..7d4ff6290 100644 --- a/manta-parameters/Cargo.toml +++ b/manta-parameters/Cargo.toml @@ -38,7 +38,7 @@ blake3 = { version = "1.3.1", default-features = false } workspace-hack = { version = "0.1.0", path = "../workspace-hack" } [dev-dependencies] -git2 = { version = "0.14.4", default-features = false } +git2 = { version = "0.15.0", default-features = false } hex = { version = "0.4.3", default-features = false, features = ["std"] } manta-parameters = { path = ".", default-features = false, features = ["download"] } tempfile = { version = "3.3.0", default-features = false } diff --git a/manta-pay/Cargo.toml b/manta-pay/Cargo.toml index 6f434d179..59fdfc704 100644 --- a/manta-pay/Cargo.toml +++ b/manta-pay/Cargo.toml @@ -56,7 +56,7 @@ download = ["manta-parameters/download", "std"] groth16 = ["ark-groth16", "ark-snark", "arkworks"] # Enable HTTP Signer Client -http = ["reqwest", "serde"] +http = ["manta-util/reqwest", "serde"] # SCALE Codec and Type Info scale = ["scale-codec", "scale-info"] @@ -128,7 +128,6 @@ manta-util = { path = "../manta-util", default-features = false } parking_lot = { version = "0.12.1", optional = true, default-features = false } rand_chacha = { version = "0.3.1", default-features = false } rayon = { version = "1.5.1", optional = true, default-features = false } -reqwest = { version = "0.11.9", optional = true, default-features = false, features = ["json"] } scale-codec = { package = "parity-scale-codec", version = "3.1.2", optional = true, default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.1.2", optional = true, default-features = false, features = ["derive"] } serde_json = { version = "1.0.82", optional = true, default-features = false, features = ["alloc"] } diff --git a/manta-pay/src/signer/client/http.rs b/manta-pay/src/signer/client/http.rs index 0c1fd3eb2..964f430d3 100644 --- a/manta-pay/src/signer/client/http.rs +++ b/manta-pay/src/signer/client/http.rs @@ -22,20 +22,22 @@ use crate::{ Checkpoint, ReceivingKeyRequest, SignError, SignRequest, SignResponse, SyncError, SyncRequest, SyncResponse, }, - util::http::{self, IntoUrl}, }; use alloc::{boxed::Box, vec::Vec}; use manta_accounting::wallet::{self, signer}; -use manta_util::future::LocalBoxFutureResult; +use manta_util::{ + future::LocalBoxFutureResult, + http::reqwest::{self, IntoUrl, KnownUrlClient}, +}; #[doc(inline)] -pub use http::Error; +pub use reqwest::Error; /// Wallet Associated to [`Client`] pub type Wallet = wallet::Wallet; /// HTTP Signer Client -pub struct Client(http::Client); +pub struct Client(KnownUrlClient); impl Client { /// Builds a new HTTP [`Client`] that connects to `server_url`. @@ -44,7 +46,7 @@ impl Client { where U: IntoUrl, { - Ok(Self(http::Client::new(server_url)?)) + Ok(Self(KnownUrlClient::new(server_url)?)) } } diff --git a/manta-pay/src/simulation/ledger/http/client.rs b/manta-pay/src/simulation/ledger/http/client.rs index 5edba77e3..1cb25ce53 100644 --- a/manta-pay/src/simulation/ledger/http/client.rs +++ b/manta-pay/src/simulation/ledger/http/client.rs @@ -19,7 +19,6 @@ use crate::{ config::{Config, TransferPost}, simulation::ledger::{http::Request, AccountId, Checkpoint}, - util::http::{self, Error, IntoUrl}, }; use manta_accounting::{ asset::AssetList, @@ -29,7 +28,10 @@ use manta_accounting::{ test::PublicBalanceOracle, }, }; -use manta_util::future::{LocalBoxFuture, LocalBoxFutureResult}; +use manta_util::{ + future::{LocalBoxFuture, LocalBoxFutureResult}, + http::reqwest::{Error, IntoUrl, KnownUrlClient}, +}; /// HTTP Ledger Client pub struct Client { @@ -37,7 +39,7 @@ pub struct Client { account: AccountId, /// Client Connection - client: http::Client, + client: KnownUrlClient, } impl Client { @@ -49,7 +51,7 @@ impl Client { { Ok(Self { account, - client: http::Client::new(server_url)?, + client: KnownUrlClient::new(server_url)?, }) } } diff --git a/manta-pay/src/util/mod.rs b/manta-pay/src/util/mod.rs index eb5bbb86a..fe69b8ddc 100644 --- a/manta-pay/src/util/mod.rs +++ b/manta-pay/src/util/mod.rs @@ -16,10 +16,6 @@ //! Manta Pay Utilities -#[cfg(feature = "http")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "http")))] -pub mod http; - #[cfg(feature = "scale")] #[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))] pub mod scale; diff --git a/manta-util/Cargo.toml b/manta-util/Cargo.toml index 058a6dd06..2e79d5c52 100644 --- a/manta-util/Cargo.toml +++ b/manta-util/Cargo.toml @@ -40,6 +40,8 @@ std = ["alloc"] [dependencies] crossbeam-channel = { version = "0.5.6", optional = true, default-features = false } rayon = { version = "1.5.3", optional = true, default-features = false } +reqwest = { version = "0.11.11", optional = true, default-features = false, features = ["json"] } serde = { version = "1.0.140", optional = true, default-features = false, features = ["derive"] } serde_with = { version = "1.14.0", optional = true, default-features = false, features = ["macros"] } +tide = { version = "0.16.0", optional = true, default-features = false } workspace-hack = { version = "0.1.0", path = "../workspace-hack" } diff --git a/manta-util/src/http/mod.rs b/manta-util/src/http/mod.rs new file mode 100644 index 000000000..785744374 --- /dev/null +++ b/manta-util/src/http/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! HTTP Utilities + +#[cfg(feature = "tide")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "tide")))] +pub mod tide; + +#[cfg(feature = "reqwest")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "reqwest")))] +pub mod reqwest; diff --git a/manta-pay/src/util/http.rs b/manta-util/src/http/reqwest.rs similarity index 81% rename from manta-pay/src/util/http.rs rename to manta-util/src/http/reqwest.rs index 4c741d800..e8c2241ea 100644 --- a/manta-pay/src/util/http.rs +++ b/manta-util/src/http/reqwest.rs @@ -14,44 +14,40 @@ // You should have received a copy of the GNU General Public License // along with manta-rs. If not, see . -//! HTTP Utilities +//! Reqwest HTTP Client Utilities -use manta_util::serde::{de::DeserializeOwned, Serialize}; +use crate::serde::{de::DeserializeOwned, Serialize}; -pub use reqwest::{Error, IntoUrl, Method, Response, Url}; +#[doc(inline)] +pub use reqwest::*; /// Asynchronous HTTP Client /// /// This client is a wrapper around [`reqwest::Client`] with a known server URL. -pub struct Client { +pub struct KnownUrlClient { /// Server URL pub server_url: Url, /// Base HTTP Client - pub client: reqwest::Client, + pub client: Client, } -impl Client { - /// Builds a new HTTP [`Client`] that connects to `server_url`. +impl KnownUrlClient { + /// Builds a new HTTP [`KnownUrlClient`] that connects to `server_url`. #[inline] - pub fn new(server_url: U) -> Result + pub fn new(server_url: U) -> Result where U: IntoUrl, { Ok(Self { - client: reqwest::Client::builder().build()?, + client: Client::builder().build()?, server_url: server_url.into_url()?, }) } /// Sends a new request asynchronously of type `command` with query string `request`. #[inline] - pub async fn request( - &self, - method: Method, - command: &str, - request: &T, - ) -> Result + pub async fn request(&self, method: Method, command: &str, request: &T) -> Result where T: Serialize, R: DeserializeOwned, @@ -85,7 +81,7 @@ impl Client { /// Sends a POST request of type `command` with query string `request`. #[inline] - pub async fn post(&self, command: &str, request: &T) -> Result + pub async fn post(&self, command: &str, request: &T) -> Result where T: Serialize, R: DeserializeOwned, diff --git a/manta-util/src/http/tide.rs b/manta-util/src/http/tide.rs new file mode 100644 index 000000000..7e2facb89 --- /dev/null +++ b/manta-util/src/http/tide.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Tide HTTP Server Utilities + +use crate::serde::{de::DeserializeOwned, Serialize}; +use core::future::Future; + +pub use tide::{Body, Error, Request, Response, Server, StatusCode}; + +/// Generates the JSON body for the output of `f`, returning an HTTP reponse. +#[inline] +pub async fn into_body(f: F) -> Result +where + R: Serialize, + E: Into, + F: FnOnce() -> Fut, + Fut: Future>, +{ + Ok(Body::from_json(&f().await.map_err(Into::into)?)?.into()) +} + +/// Executes `f` on the incoming `request`. +#[inline] +pub async fn execute(mut request: Request, f: F) -> Result +where + S: Clone, + T: DeserializeOwned, + R: Serialize, + E: Into, + F: FnOnce(S, T) -> Fut, + Fut: Future>, +{ + let args = request.body_json::().await?; + into_body(move || async move { f(request.state().clone(), args).await }).await +} + +/// Registers a `POST` command with the given `path` and execution `f`. +#[inline] +pub fn register_post(api: &mut Server, path: &'static str, f: F) +where + S: Clone + Send + Sync + 'static, + T: DeserializeOwned + Send + 'static, + R: Serialize + 'static, + E: Into + 'static, + F: Clone + Send + Sync + 'static + Fn(S, T) -> Fut, + Fut: Future> + Send + 'static, +{ + api.at(path).post(move |r| execute(r, f.clone())); +} diff --git a/manta-util/src/lib.rs b/manta-util/src/lib.rs index 66f2e9d41..4ddef5d11 100644 --- a/manta-util/src/lib.rs +++ b/manta-util/src/lib.rs @@ -32,6 +32,7 @@ mod sealed; pub mod codec; pub mod convert; pub mod future; +pub mod http; pub mod iter; pub mod num; pub mod ops; diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index ab0e4dd42..35e4e641e 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -44,7 +44,8 @@ serde_json = { version = "1.0.82", features = ["alloc", "std"] } sha2 = { version = "0.9.9", features = ["std"] } standback = { version = "0.2.17", default-features = false, features = ["std"] } subtle = { version = "2.4.1", default-features = false, features = ["i128"] } -tracing = { version = "0.1.35", default-features = false, features = ["attributes", "tracing-attributes"] } +tide = { version = "0.16.0", default-features = false, features = ["async-h1", "h1-server"] } +tracing = { version = "0.1.36", default-features = false, features = ["attributes", "tracing-attributes"] } url = { version = "2.2.2", default-features = false, features = ["serde"] } web-sys = { version = "0.3.59", default-features = false, features = ["BinaryType", "Blob", "CloseEvent", "DomException", "Event", "EventTarget", "MessageEvent", "WebSocket", "console"] } zeroize = { version = "1.5.7", default-features = false, features = ["alloc", "zeroize_derive"] }