Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/66/polka storage provider print start time of the provider #86

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f5f7c24
feat: provider rpc client wip
cernicc Jun 18, 2024
2cca531
fix: rename constant
cernicc Jun 18, 2024
52a6de8
feat: add method specific params
cernicc Jun 19, 2024
a20e65d
fix: remove unused dep
cernicc Jun 19, 2024
7b768c4
Merge branch 'develop' into feat/66/polka-storage-provider-print-star…
cernicc Jun 19, 2024
1005568
fix: taplo
cernicc Jun 20, 2024
e0c2196
feat: remove uptimeme
cernicc Jun 20, 2024
dcebcc6
fix: use url from params
cernicc Jun 20, 2024
6a3990f
fix: add logging
cernicc Jun 20, 2024
cc34cf5
fix: small changes
cernicc Jun 20, 2024
221d885
chore: add comment
cernicc Jun 20, 2024
92d5756
fix: remove unused import
cernicc Jun 20, 2024
1ac85ee
fix: pr suggestions
cernicc Jun 21, 2024
cf46461
Merge branch 'develop' into feat/66/polka-storage-provider-print-star…
cernicc Jun 26, 2024
92d7ce0
fix: pr suggestions
cernicc Jun 26, 2024
ba82300
Merge remote-tracking branch 'origin/develop' into feat/66/polka-stor…
cernicc Jun 26, 2024
cdfa193
fix: change request params to generic
cernicc Jun 26, 2024
7188abc
feat: refactor
cernicc Jun 27, 2024
c349014
Merge remote-tracking branch 'origin/develop' into feat/66/polka-stor…
cernicc Jun 27, 2024
b3e1c9f
fix: after merge
cernicc Jun 27, 2024
3bccbff
feat: add custom rpc client error
cernicc Jun 27, 2024
ab60f49
chore: some comments
cernicc Jun 27, 2024
e1494bf
fix: remove unused bounds
cernicc Jun 27, 2024
98f6872
fix: some pr suggestions
cernicc Jun 27, 2024
4a07a9b
fix: pr related
cernicc Jun 27, 2024
a689022
fix: V0 enum
cernicc Jun 27, 2024
5fedadb
Merge branch 'develop' into feat/66/polka-storage-provider-print-star…
cernicc Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", t

async-channel = "2.3.1"
async-stream = "0.3.5"
async-trait = "0.1.80"
base64 = "0.22.1"
bitflags = "2.5.0"
blake2b_simd = { version = "1.0.2" }
Expand Down Expand Up @@ -67,6 +68,7 @@ quote = { version = "1.0.33" }
rand = "0.8.5"
rocksdb = { version = "0.21" }
scale-info = { version = "2.11.1", default-features = false }
sealed = "0.5"
serde = { version = "1.0.197", default-features = false }
serde-big-array = { version = "0.3.2" }
serde_derive = { version = "1.0.117" }
Expand Down
5 changes: 4 additions & 1 deletion cli/polka-storage-provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ repository.workspace = true
version = "0.1.0"

[dependencies]
async-trait = { workspace = true }
chrono = { workspace = true, features = ["serde"] }
clap = { workspace = true, features = ["derive"] }
jsonrpsee = { workspace = true, features = ["server"] }
jsonrpsee = { workspace = true, features = ["http-client", "server", "ws-client"] }
sc-cli = { workspace = true }
sealed = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
subxt = { workspace = true }
Expand All @@ -21,6 +23,7 @@ tokio = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
url = { workspace = true }
uuid = { workspace = true }

[lints]
workspace = true
33 changes: 32 additions & 1 deletion cli/polka-storage-provider/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use clap::Parser;
use thiserror::Error;
use url::Url;

use crate::commands::{InfoCommand, InitCommand, RunCommand, WalletCommand};
use crate::{
commands::{InfoCommand, InitCommand, RunCommand, WalletCommand},
rpc::{server::RPC_SERVER_DEFAULT_BIND_ADDR, ClientError},
};

/// A CLI application that facilitates management operations over a running full
/// node and other components.
Expand All @@ -9,6 +14,10 @@ use crate::commands::{InfoCommand, InitCommand, RunCommand, WalletCommand};
pub(crate) struct Cli {
#[command(subcommand)]
pub subcommand: SubCommand,

/// URL of the providers RPC server.
#[arg(long, default_value_t = Url::parse(&format!("http://{RPC_SERVER_DEFAULT_BIND_ADDR}")).unwrap())]
pub rpc_server_url: Url,
}

/// Supported sub-commands.
Expand All @@ -24,3 +33,25 @@ pub enum SubCommand {
#[command(subcommand)]
Wallet(WalletCommand),
}

/// CLI components error handling implementor.
#[derive(Debug, Error)]
pub enum CliError {
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),

#[error("FromEnv error: {0}")]
EnvError(#[from] tracing_subscriber::filter::FromEnvError),

#[error("URL parse error: {0}")]
ParseUrl(#[from] url::ParseError),

#[error("Substrate error: {0}")]
Substrate(#[from] subxt::Error),

#[error(transparent)]
SubstrateCli(#[from] sc_cli::Error),

#[error("Rpc Client error: {0}")]
RpcClient(#[from] ClientError),
}
33 changes: 29 additions & 4 deletions cli/polka-storage-provider/src/commands/info.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
use std::fmt::{self, Display, Formatter};

use chrono::{DateTime, Utc};
use clap::Parser;

use crate::Error;
use crate::{
cli::CliError,
rpc::{methods::common::InfoRequest, version::V0, Client},
};

/// Command to display information about the storage provider.
#[derive(Debug, Clone, Parser)]
pub(crate) struct InfoCommand;

impl InfoCommand {
pub async fn run(&self) -> Result<(), Error> {
// TODO(#66,@cernicc,31/05/2024): Print start time of the provider
pub async fn run(&self, client: &Client<V0>) -> Result<(), CliError> {
// TODO(#67,@cernicc,07/06/2024): Print polkadot address used by the provider
unimplemented!()

// Get server info
let server_info = client.execute(InfoRequest).await?;

let node_status_info = NodeStatusInfo {
start_time: server_info.start_time,
};

println!("{}", node_status_info);

Ok(())
}
}

struct NodeStatusInfo {
start_time: DateTime<Utc>,
}

impl Display for NodeStatusInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "Started at: {}", self.start_time)
}
}
4 changes: 2 additions & 2 deletions cli/polka-storage-provider/src/commands/init.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use clap::Parser;
use tracing::info;

use crate::Error;
use crate::cli::CliError;

/// Command to initialize the storage provider.
#[derive(Debug, Clone, Parser)]
pub(crate) struct InitCommand;

impl InitCommand {
pub async fn run(&self) -> Result<(), Error> {
pub async fn run(&self) -> Result<(), CliError> {
info!("Initializing polka storage provider...");
// TODO(#64,@cernicc,31/05/2024): Init needed configurations.
// TODO(#65,@cernicc,31/05/2024): Check if full node is synced
Expand Down
20 changes: 10 additions & 10 deletions cli/polka-storage-provider/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ use tracing::info;
use url::Url;

use crate::{
rpc::{start_rpc, RpcServerState},
substrate, Error,
cli::CliError,
rpc::server::{start_rpc_server, RpcServerState, RPC_SERVER_DEFAULT_BIND_ADDR},
substrate,
};

const SERVER_DEFAULT_BIND_ADDR: &str = "127.0.0.1:8000";
const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:9944";

/// Command to start the storage provider.
#[derive(Debug, Clone, Parser)]
pub(crate) struct RunCommand {
/// RPC API endpoint used by the parachain node.
#[arg(short = 'n', long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)]
pub node_rpc_address: Url,
/// Address used for RPC. By default binds on localhost on port 8000.
#[arg(short = 'a', long, default_value = SERVER_DEFAULT_BIND_ADDR)]
#[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)]
pub rpc_address: Url,
/// Address and port used for RPC server.
#[arg(long, default_value = RPC_SERVER_DEFAULT_BIND_ADDR)]
pub listen_addr: SocketAddr,
}

impl RunCommand {
pub async fn run(&self) -> Result<(), Error> {
let substrate_client = substrate::init_client(self.node_rpc_address.as_str()).await?;
pub async fn run(&self) -> Result<(), CliError> {
let substrate_client = substrate::init_client(self.rpc_address.as_str()).await?;

let state = Arc::new(RpcServerState {
start_time: Utc::now(),
substrate_client,
});

// Start RPC server
let handle = start_rpc(state, self.listen_addr).await?;
let handle = start_rpc_server(state, self.listen_addr).await?;
info!("RPC server started at {}", self.listen_addr);

// Monitor shutdown
Expand Down
17 changes: 12 additions & 5 deletions cli/polka-storage-provider/src/commands/runner.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
use clap::Parser;

use super::WalletCommand;
use crate::{cli::SubCommand, Cli, Error};
use crate::{
cli::{CliError, SubCommand},
rpc::Client,
Cli,
};

/// Parses command line arguments into the service configuration and runs the specified
/// command with it.
pub(crate) async fn run() -> Result<(), Error> {
/// Parses command line arguments into the service configuration and runs the
/// specified command with it.
pub(crate) async fn run() -> Result<(), CliError> {
// CLI arguments parsed and mapped to the struct.
let cli_arguments: Cli = Cli::parse();

// RPC client used to interact with the full node
let rpc_client = Client::new(cli_arguments.rpc_server_url).await?;

match &cli_arguments.subcommand {
SubCommand::Init(cmd) => cmd.run().await,
SubCommand::Run(cmd) => cmd.run().await,
SubCommand::Info(cmd) => cmd.run().await,
SubCommand::Info(cmd) => cmd.run(&rpc_client).await,
SubCommand::Wallet(cmd) => match cmd {
WalletCommand::GenerateNodeKey(cmd) => Ok(cmd.run()?),
WalletCommand::Generate(cmd) => Ok(cmd.run()?),
Expand Down
17 changes: 0 additions & 17 deletions cli/polka-storage-provider/src/error.rs

This file was deleted.

5 changes: 2 additions & 3 deletions cli/polka-storage-provider/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@

mod cli;
pub(crate) mod commands;
mod error;
mod rpc;
mod substrate;

pub(crate) use cli::Cli;
use cli::CliError;
use commands::runner;
pub(crate) use error::Error;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

#[tokio::main]
async fn main() -> Result<(), Error> {
async fn main() -> Result<(), CliError> {
// Logger initialization.
tracing_subscriber::registry()
.with(fmt::layer())
Expand Down
73 changes: 4 additions & 69 deletions cli/polka-storage-provider/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,6 @@
use std::{future::Future, net::SocketAddr, sync::Arc};

use chrono::Utc;
use error::ServerError;
use jsonrpsee::{
server::{Server, ServerHandle},
types::Params,
RpcModule,
};
use methods::create_module;
use serde::{Deserialize, Serialize};

use crate::{substrate, Error};

pub mod error;
mod client;
pub mod methods;
pub mod server;
pub mod version;

/// A definition of an RPC method handler which can be registered with an [`RpcModule`].
pub trait RpcMethod {
/// Method name.
const NAME: &'static str;
/// See [`ApiVersion`].
const API_VERSION: ApiVersion;
/// Successful response type.
type Ok: Serialize;

/// Logic for this method.
fn handle(
ctx: Arc<RpcServerState>,
params: Params,
) -> impl Future<Output = Result<Self::Ok, ServerError>> + Send;

/// Register this method with an [`RpcModule`].
fn register_async(module: &mut RpcModule<RpcServerState>) -> &mut jsonrpsee::MethodCallback
where
Self::Ok: Clone + 'static,
{
module
.register_async_method(Self::NAME, move |params, ctx| async move {
let ok = Self::handle(ctx, params).await?;
Result::<_, jsonrpsee::types::ErrorObjectOwned>::Ok(ok)
})
.expect("method should be valid") // This is safe because we know the method registered is valid.
}
}

/// Available API versions.
///
/// These are significant because they are expressed in the URL path against
/// which RPC calls are made, e.g `rpc/v0` or `rpc/v1`.
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum ApiVersion {
V0,
}

pub struct RpcServerState {
pub start_time: chrono::DateTime<Utc>,
pub substrate_client: substrate::Client,
}

pub async fn start_rpc(
state: Arc<RpcServerState>,
listen_addr: SocketAddr,
) -> Result<ServerHandle, Error> {
let server = Server::builder().build(listen_addr).await?;

let module = create_module(state.clone());
let server_handle = server.start(module);

Ok(server_handle)
}
pub use client::{Client, ClientError};
Loading