Skip to content

Commit

Permalink
dev-faucet (#2061)
Browse files Browse the repository at this point in the history
* WIP dev-faucet

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Eran Rundstein <[email protected]>

* fixup previous

* fixups

* fix clippy

* make the faucet have a background thread that splits tx outs (#2063)

* make the faucet have a background thread that splits tx outs

this enables it to support multiple faucet requests concurrently

* fix clippies, clean up some things, add tracking for queue depth

* bug fix and logging

* fix lints

* fix responses

* fix documentation and examples

* use async routes for compat with rocket 0.5

* Make more parameters configurable

* re-order worker thread checks

* skip serializing empty things

* add readme to cargo toml

* fix missing async

* fix after rebase

* eran comments

* fix enclave build

* fix an eran comment about fees

* dont implement rocket responder, feedback from core-team discussion

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* Update mobilecoind-dev-faucet/README.md

Co-authored-by: Mike Turner <[email protected]>

* review comments

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* remoun review comments (grpcio config)

* move more code into the library for testability

* move worker thread functionality to its own function

* Update mobilecoind-json/Cargo.toml

Co-authored-by: Remoun Metyas <[email protected]>

* fix code comments

* add a code comment

* Update mobilecoind-dev-faucet/src/bin/main.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/data_types.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/lib.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update util/serial/src/lib.rs

Co-authored-by: Remoun Metyas <[email protected]>

* Update mobilecoind-dev-faucet/src/worker.rs

Co-authored-by: Remoun Metyas <[email protected]>

* review comments

* make the faucet retry during initialization

* clippy

* add jsonu64 tests

* eran comments about Option<JsonU64> vs. #[serde(default)]

* Update mobilecoind-dev-faucet/src/lib.rs

Co-authored-by: Remoun Metyas <[email protected]>

* remove unused import

* fix build

Co-authored-by: Eran Rundstein <[email protected]>
Co-authored-by: Mike Turner <[email protected]>
Co-authored-by: Remoun Metyas <[email protected]>
  • Loading branch information
4 people authored Jun 9, 2022
1 parent bcad5f6 commit 8320c72
Show file tree
Hide file tree
Showing 12 changed files with 1,419 additions and 92 deletions.
84 changes: 26 additions & 58 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ members = [
"mint-auditor",
"mint-auditor/api",
"mobilecoind",
"mobilecoind-dev-faucet",
"mobilecoind-json",
"mobilecoind/api",
"peers",
Expand Down
29 changes: 29 additions & 0 deletions mobilecoind-dev-faucet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "mc-mobilecoind-dev-faucet"
version = "1.3.0-pre0"
authors = ["MobileCoin"]
edition = "2021"
readme = "README.md"

[[bin]]
name = "mobilecoind-dev-faucet"
path = "src/bin/main.rs"

[dependencies]
mc-account-keys = { path = "../account-keys" }
mc-api = { path = "../api" }
mc-common = { path = "../common", features = ["loggers"] }
mc-mobilecoind-api = { path = "../mobilecoind/api" }
mc-transaction-core = { path = "../transaction/core" }
mc-util-grpc = { path = "../util/grpc" }
mc-util-keyfile = { path = "../util/keyfile" }
mc-util-serial = { path = "../util/serial", features = ["std"] }

clap = { version = "3.1", features = ["derive", "env"] }
grpcio = "0.10.2"
hex = "0.4"
rocket = { version = "0.5.0-rc.2", features = ["json"] }
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tokio = "1"
81 changes: 81 additions & 0 deletions mobilecoind-dev-faucet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## mobilecoind-dev-faucet

This is a standalone http server which provides faucet functionality.
* Backed by [mobilecoind](../mobilecoind) -- similar to [mobilecoind-json](../mobilecoind-json), it relays requests to a separate mobilecoind instance, and is itself stateless
* No captcha or rate limiting. This is appropriate for developers running automated tests in a dev cluster.
* Any token id can be requested for testing
* TODO: HTTP Authorization headers may be added in the future

### Routes

You may POST to `/`, attaching a json object as the HTTP body:

```
{
b58_address: <string>,
token_id: <optional string>
}
```

Any tokenid can be requested and the faucet will attempt to send a nominal amount of
that token to the address specified, or return errors if it cannot. The nominal amount is
by default twenty times the minimum fee for that token. The response will contain a
JSON object, `success` will be `true` if it managed to submit a payment, and there will
be mobilecoind "Receiver Tx receipt" for the submitted transaction. If `success` is `false`
then `err_str` will describe the problem.

GET requests to `/status`, will respond with a json object with the
following information:

```
{
// The balances of the faucet
balances: { <token_id (string)>:<u64 balance (string)> }
// The amounts the faucet pays per token id
faucet_amounts: { <token_id (string)>:<u64 balance (string)> }
// The current number of "queued" UTXOs. Each can be used to fill a concurrent request.
// If a queue is empty then it may take a few seconds for the faucet to refill the queue.
queue_depths: { <token_id (string)>:<u64 length (string)> }
// This address can be paid to replenish the faucet
b58_address: <string>,
}
```

### Launching

The faucet should be started using a keyfile, which is a json formatted file containing a
mnemonic string or a root entropy for a MobileCoin account.

Required options are:

- `--keyfile` - path to the keyfile with the account mnemonic or entropy. This account holds the faucet funds.

Other options are:
- `--amount-factor` - An integer `X`. The amount we send when people hit the faucet is `minimum_fee * X`. Default is `X = 20`.
- `--listen-host` - hostname for webserver, default `127.0.0.1`
- `--listen-port` - port for webserver, default `9090`
- `--mobilecoind-uri` - URI for connecting to mobilecoind gRPC, default `insecure-mobilecoind://127.0.0.1:4444/`
- `--target-queue-depth` - The number of pre-split transactions the faucet attempts to maintain in its queue. Default is 20.
- `--worker-poll-period-ms` - A lower bound on how often the worker thread wakes up to check in with `mobilecoind`. Default is `100` milliseconds.

### Usage with cURL

Here is some example usage:

Requesting payment:

```
$ curl -s localhost:9090/ -d '{"b58_address": "c7f04fcd40d093ca6578b13d790df0790c96e94a77815e5052993af1b9d12923"}' -X POST -H 'Content-type: application/json'
{"success":true,"receiver_tx_receipt_list":[{"recipient":{"view_public_key":"86280244d51afed4217ee3dc6288650c27cacc6e4bfb558159f0f8caa38ae542","spend_public_key":"803958b71de5fa7a58d257a0411506e59f77eaff33ee7b7905ac4f9ef68e3c2a","fog_report_url":"","fog_authority_sig":"","fog_report_id":""},"tx_public_key":"880d56bc36411507131098dd404878fb083b6dd5b805c37f736dcfa94d31027d","tx_out_hash":"0fbe90326c255e08b3ee6cbdf626d244ac29bbdab8810163d09513fa1919664f","tombstone":56,"confirmation_number":"027c506b81ad5bd8142382c75f6148f6e5627ad45d2a09110ee9e4ff5a789398"}]}```

```
$ curl -s localhost:9090/ -d '{"b58_address": "c7f04fcd40d093ca6578b13d790df0790c96e94a77815e5052993af1b9d12923", "token_id": "1"}' -X POST -H 'Content-type: application/json'
{"success":false,"err_str":"faucet is depleted"}
```

Getting status:

```
$ curl -s localhost:9090/status
{"b58_address":"5KBMnd8cs5zPsytGgZrjmQ8z9VJYThuh1B39pKzDERTfzm3sVGQxnZPC8JEWP69togpSPRz3e6pBsLzwnMjrXTbDqoRTQ8VF98sQu7LqjL5","faucet_payout_amounts":{"2":"20480","1":"20480","0":"8000000000"},"balances":{"2":"0","1":"0","0":"12499999997600000000"},"queue_depths":{"1":"0","0":"26","2":"0"}}
```
58 changes: 58 additions & 0 deletions mobilecoind-dev-faucet/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2018-2022 The MobileCoin Foundation

//! HTTP faucet service backed by mobilecoind

#![deny(missing_docs)]
#![feature(proc_macro_hygiene, decl_macro)]

use clap::Parser;
use mc_common::logger::{create_app_logger, log, o};
use mc_mobilecoind_dev_faucet::{data_types::*, Config, State};
use rocket::{get, post, routes, serde::json::Json};

/// Request payment from the faucet, and map the rust result onto json for
/// rocket appropriately
#[post("/", format = "json", data = "<req>")]
async fn post(
state: &rocket::State<State>,
req: Json<JsonFaucetRequest>,
) -> Json<JsonSubmitTxResponse> {
Json(state.handle_post(&req).await.into())
}

/// Request status of the faucet, and map the rust result onto json for rocket
/// apporpriately
#[get("/status")]
async fn status(state: &rocket::State<State>) -> Json<JsonFaucetStatus> {
Json(state.handle_status().await.into())
}

#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
mc_common::setup_panic_handler();
let _sentry_guard = mc_common::sentry::init();

let config = Config::parse();

let (logger, _global_logger_guard) = create_app_logger(o!());
log::info!(
logger,
"Starting mobilecoind-dev-faucet HTTP on {}:{}, connecting to {}",
config.listen_host,
config.listen_port,
config.mobilecoind_uri,
);

let figment = rocket::Config::figment()
.merge(("port", config.listen_port))
.merge(("address", config.listen_host.clone()));

let state = State::new(&config, &logger);

let _rocket = rocket::custom(figment)
.mount("/", routes![post, status])
.manage(state)
.launch()
.await?;
Ok(())
}
Loading

0 comments on commit 8320c72

Please sign in to comment.