-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
322 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Post Service | ||
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. | ||
|
||
## How to run | ||
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`). | ||
|
||
#### Example running on an un-encrypted channel, with the default configuration of _threads_ and _nonces_ | ||
```sh | ||
service --address=http://my-node-address.org --dir=./post-data | ||
``` | ||
|
||
#### Example running on an encrypted (mTLS) channel, with the custom _threads_ and _nonces_ | ||
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`: | ||
```sh | ||
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 | ||
``` | ||
|
||
A full usage/help can be viewed with | ||
```sh | ||
service --help | ||
``` | ||
|
||
## Operator API | ||
The operator API is a set of GRPC endpoints allowing control of the post service. | ||
|
||
The GRPC API supports reflection for easy use with tools like [grpcurl](https://github.com/fullstorydev/grpcurl). | ||
|
||
It is enabled by providing `--operator-address=<address>`, i.e. `--operator-address=127.0.0.1:50051` CLI argument. | ||
|
||
### Example usage | ||
#### Querying post service status | ||
```sh | ||
❯ grpcurl -plaintext localhost:50051 spacemesh.v1.PostServiceOperator/Status | ||
{ | ||
"status": "IDLE" | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,10 @@ | ||
use std::{env, path::PathBuf}; | ||
|
||
fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
tonic_build::configure().compile(&["api/spacemesh/v1/post.proto"], &["api"])?; | ||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||
tonic_build::configure() | ||
.file_descriptor_set_path(out_dir.join("post_descriptor.bin")) | ||
.compile(&["api/spacemesh/v1/post.proto"], &["api"])?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod client; | ||
pub mod operator; | ||
pub mod service; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
//! Operator service for controlling the post service. | ||
//! | ||
//! It exposes a GRPC API defined in `spacemesh.v1.post.proto`. | ||
//! Allows to query the status of the post service. | ||
use std::sync::Arc; | ||
|
||
use tokio::net::TcpListener; | ||
use tokio_stream::wrappers::TcpListenerStream; | ||
use tonic::{transport::Server, Request, Response, Status}; | ||
|
||
use spacemesh_v1::post_service_operator_server::{PostServiceOperator, PostServiceOperatorServer}; | ||
use spacemesh_v1::{PostServiceStatusRequest, PostServiceStatusResponse}; | ||
|
||
pub mod spacemesh_v1 { | ||
tonic::include_proto!("spacemesh.v1"); | ||
pub(crate) const FILE_DESCRIPTOR_SET: &[u8] = | ||
tonic::include_file_descriptor_set!("post_descriptor"); | ||
} | ||
|
||
pub enum ServiceState { | ||
Idle, | ||
Proving, | ||
} | ||
|
||
#[mockall::automock] | ||
/// The Service trait provides funcionality required by the OperatorService. | ||
pub trait Service { | ||
/// Returns the current state of the service. | ||
fn status(&self) -> ServiceState; | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct OperatorService<O: Service> { | ||
operator: Arc<O>, | ||
} | ||
|
||
#[tonic::async_trait] | ||
impl<O: Service + Sync + Send + 'static> PostServiceOperator for OperatorService<O> { | ||
async fn status( | ||
&self, | ||
request: Request<PostServiceStatusRequest>, | ||
) -> Result<Response<PostServiceStatusResponse>, Status> { | ||
log::debug!("got a request from {:?}", request.remote_addr()); | ||
|
||
let status = match self.operator.status() { | ||
ServiceState::Idle => spacemesh_v1::post_service_status_response::Status::Idle, | ||
ServiceState::Proving => spacemesh_v1::post_service_status_response::Status::Proving, | ||
}; | ||
|
||
Ok(Response::new(PostServiceStatusResponse { | ||
status: status as _, | ||
})) | ||
} | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct OperatorServer {} | ||
|
||
impl OperatorServer { | ||
pub async fn run<O>(listener: TcpListener, operator: Arc<O>) -> eyre::Result<()> | ||
where | ||
O: Service + Sync + Send + 'static, | ||
{ | ||
log::info!("running operator service on {}", listener.local_addr()?); | ||
|
||
let reflection_service = tonic_reflection::server::Builder::configure() | ||
.register_encoded_file_descriptor_set(spacemesh_v1::FILE_DESCRIPTOR_SET) | ||
.build()?; | ||
|
||
let operator_service = PostServiceOperatorServer::new(OperatorService { operator }); | ||
|
||
Server::builder() | ||
.add_service(reflection_service) | ||
.add_service(operator_service) | ||
.serve_with_incoming(TcpListenerStream::new(listener)) | ||
.await | ||
.map_err(|e| eyre::eyre!("failed to serve: {e}")) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::sync::Arc; | ||
|
||
use tokio::net::TcpListener; | ||
|
||
use super::spacemesh_v1::post_service_operator_client::PostServiceOperatorClient; | ||
use super::spacemesh_v1::post_service_status_response::Status; | ||
use super::spacemesh_v1::PostServiceStatusRequest; | ||
|
||
#[tokio::test] | ||
async fn test_status() { | ||
let mut svc_operator = super::MockService::new(); | ||
svc_operator | ||
.expect_status() | ||
.once() | ||
.returning(|| super::ServiceState::Idle); | ||
svc_operator | ||
.expect_status() | ||
.once() | ||
.returning(|| super::ServiceState::Proving); | ||
|
||
let listener = TcpListener::bind("localhost:0").await.unwrap(); | ||
let addr: std::net::SocketAddr = listener.local_addr().unwrap(); | ||
|
||
tokio::spawn(super::OperatorServer::run(listener, Arc::new(svc_operator))); | ||
|
||
let mut client = PostServiceOperatorClient::connect(format!("http://{addr}")) | ||
.await | ||
.unwrap(); | ||
|
||
let response = client.status(PostServiceStatusRequest {}).await.unwrap(); | ||
assert_eq!(response.into_inner().status(), Status::Idle); | ||
|
||
let response = client.status(PostServiceStatusRequest {}).await.unwrap(); | ||
assert_eq!(response.into_inner().status(), Status::Proving); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.