Skip to content

Commit 5ee9822

Browse files
authored
Merge pull request #140 from spacemeshos/139-basic-service-operator-api
Basic operator API
2 parents 75f2917 + 49faffc commit 5ee9822

15 files changed

+572
-112
lines changed

Cargo.lock

+51-25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ Includes:
1818
### Randomx-rs
1919
[RandomX](https://github.com/tevador/randomx), that [randomx-rs](https://github.com/spacemeshos/randomx-rs) depends on, requires **cmake**. Follow [these instructions](https://github.com/spacemeshos/randomx-rs#build-dependencies) to install it.
2020

21+
## Post Service
22+
Please refer to [service README](service/README.md) for instructions.

benches/verifying.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use post::{
66
initialize::{CpuInitializer, Initialize},
77
metadata::ProofMetadata,
88
pow::randomx::{PoW, RandomXFlag},
9-
prove::generate_proof,
9+
prove::{generate_proof, NoopProgressReporter},
1010
verification::{Mode, Verifier},
1111
};
1212
#[cfg(not(windows))]
@@ -44,7 +44,17 @@ fn verifying(c: &mut Criterion) {
4444
let pow_flags = RandomXFlag::get_recommended_flags();
4545
// Generate a proof
4646
let stop = AtomicBool::new(false);
47-
let proof = generate_proof(datadir.path(), challenge, cfg, 32, 1, pow_flags, stop).unwrap();
47+
let proof = generate_proof(
48+
datadir.path(),
49+
challenge,
50+
cfg,
51+
32,
52+
1,
53+
pow_flags,
54+
stop,
55+
NoopProgressReporter {},
56+
)
57+
.unwrap();
4858
let metadata = ProofMetadata::new(metadata, *challenge);
4959

5060
// Bench verifying the proof

certifier/tests/test_certify.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use post::{
77
initialize::{CpuInitializer, Initialize},
88
metadata::ProofMetadata,
99
pow::randomx::RandomXFlag,
10-
prove::generate_proof,
10+
prove::{self, generate_proof},
1111
};
1212
use reqwest::StatusCode;
1313
use tokio::net::TcpListener;
@@ -45,7 +45,17 @@ async fn test_certificate_post_proof() {
4545
// Generate a proof
4646
let pow_flags = RandomXFlag::get_recommended_flags();
4747
let stop = AtomicBool::new(false);
48-
let proof = generate_proof(datadir.path(), challenge, cfg, 32, 1, pow_flags, stop).unwrap();
48+
let proof = generate_proof(
49+
datadir.path(),
50+
challenge,
51+
cfg,
52+
32,
53+
1,
54+
pow_flags,
55+
stop,
56+
prove::NoopProgressReporter {},
57+
)
58+
.unwrap();
4959
let metadata = ProofMetadata::new(metadata, *challenge);
5060

5161
// Spawn the certifier service

ffi/src/post_impl.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,16 @@ fn _generate_proof(
103103
let challenge = challenge.try_into()?;
104104

105105
let stop = AtomicBool::new(false);
106-
let proof = prove::generate_proof(datadir, challenge, cfg, nonces, threads, pow_flags, stop)?;
106+
let proof = prove::generate_proof(
107+
datadir,
108+
challenge,
109+
cfg,
110+
nonces,
111+
threads,
112+
pow_flags,
113+
stop,
114+
prove::NoopProgressReporter {},
115+
)?;
107116
Ok(Box::new(Proof::from(proof)))
108117
}
109118

service/Cargo.toml

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ path = "src/lib.rs"
1010
[dependencies]
1111
post-rs = { path = "../" }
1212
prost = "0.12.1"
13-
tonic = { version = "0.10.0", features = ["tls"] }
13+
tonic = { version = "0.11.0", features = ["tls"] }
1414
tokio = { version = "1.0", features = [
1515
"rt-multi-thread",
1616
"macros",
@@ -26,11 +26,15 @@ clap = { version = "4.4.4", features = ["derive"] }
2626
hex = "0.4.3"
2727
mockall = "0.11.4"
2828
sysinfo = "0.29.10"
29+
axum = "0.7.4"
30+
serde = "1.0.196"
31+
range-set = "0.0.11"
2932

3033
[build-dependencies]
31-
tonic-build = "0.10.0"
34+
tonic-build = "0.11.0"
3235

3336
[dev-dependencies]
3437
rcgen = "0.11.3"
38+
reqwest = { version = "0.11.24", features = ["json"] }
3539
rstest = "0.18.2"
3640
tempfile = "3.8.0"

service/README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Post Service
2+
Post service allows to separate expensive PoST proving from a node by allowing to generate a proof on a different machine. It connects to the node via GRPC (on an address pointed by `--address`) and awaits commands from the node.
3+
4+
## How to run
5+
First of all, the service currently doesn't support initializing PoST data. The data must be initialized separately (presumably using [postcli](https://github.com/spacemeshos/post/tree/develop/cmd/postcli) and placed in a directory pointed to by `--dir`).
6+
7+
#### Example running on an un-encrypted channel, with the default configuration of _threads_ and _nonces_
8+
```sh
9+
service --address=http://my-node-address.org --dir=./post-data
10+
```
11+
12+
#### Example running on an encrypted (mTLS) channel, with the custom _threads_ and _nonces_
13+
For mTLS, you need to pass the certificate and private key of the post-service with `--cert` and `-key`, as well as the CA of the server with `--ca-cert`:
14+
```sh
15+
service --address=https://my-node-address.org --cert=client.pem --key=client-key.pem --ca-cert=server-rootCA.pem --dir=./post-data --threads=8 --nonces=288
16+
```
17+
18+
A full usage/help can be viewed with
19+
```sh
20+
service --help
21+
```
22+
23+
## Operator API
24+
The operator API is a set of HTTP endpoints allowing control of the post service.
25+
26+
It is enabled by providing `--operator-address=<address>`, i.e. `--operator-address=127.0.0.1:50051` CLI argument.
27+
28+
### Example usage
29+
#### Querying post service status
30+
```sh
31+
# Not doing anything
32+
❯ curl http://localhost:50051/status
33+
"Idle"
34+
35+
# Proving
36+
❯ curl http://localhost:50051/status
37+
{"Proving":{"nonces":{"start":0,"end":128},"position":0}}
38+
39+
# Proving, read some data already
40+
❯ curl http://localhost:50051/status
41+
{"Proving":{"nonces":{"start":0,"end":128},"position":10000}}
42+
43+
# Started second pass
44+
❯ curl http://localhost:50051/status
45+
{"Proving":{"nonces":{"start":128,"end":256},"position":10000}}
46+
47+
# Finished proving, but the node has not fetched the proof yet
48+
❯ curl http://localhost:50051/status
49+
"DoneProving"
50+
51+
# Finished proving and the node has fetched the proof
52+
❯ curl http://localhost:50051/status
53+
"Idle"
54+
```

service/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod client;
2+
pub mod operator;
23
pub mod service;

service/src/main.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
use std::{fs::read_to_string, path::PathBuf, time::Duration};
1+
use std::{fs::read_to_string, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration};
22

33
use clap::{Args, Parser, ValueEnum};
44
use eyre::Context;
55
use sysinfo::{Pid, ProcessExt, ProcessStatus, System, SystemExt};
6+
use tokio::net::TcpListener;
67
use tokio::sync::oneshot::{self, error::TryRecvError, Receiver};
78
use tonic::transport::{Certificate, Identity};
89

910
use post::pow::randomx::RandomXFlag;
10-
use post_service::client;
11+
use post_service::{client, operator};
1112

1213
/// Post Service
1314
#[derive(Parser, Debug)]
@@ -39,6 +40,11 @@ struct Cli {
3940
/// watch PID and exit if it dies
4041
#[arg(long)]
4142
watch_pid: Option<sysinfo::Pid>,
43+
44+
/// address to listen on for operator service
45+
/// the operator service is disabled if not specified
46+
#[arg(long)]
47+
operator_address: Option<SocketAddr>,
4248
}
4349

4450
#[derive(Args, Debug)]
@@ -220,6 +226,13 @@ async fn main() -> eyre::Result<()> {
220226
None
221227
};
222228

229+
let service = Arc::new(service);
230+
231+
if let Some(address) = args.operator_address {
232+
let listener = TcpListener::bind(address).await?;
233+
tokio::spawn(operator::run(listener, service.clone()));
234+
}
235+
223236
let client = client::ServiceClient::new(args.address, tls, service)?;
224237
let client_handle = tokio::spawn(client.run(args.max_retries, args.reconnect_interval_s));
225238

0 commit comments

Comments
 (0)