Skip to content

Commit

Permalink
Generate avail key pair if not configured.
Browse files Browse the repository at this point in the history
  • Loading branch information
aterentic-ethernal committed Nov 16, 2023
1 parent fdbbcf7 commit b2c2ea7
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 93 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
config*.yaml
avail_light_store
avail_path*
/identity.toml
1 change: 1 addition & 0 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 @@ -68,6 +68,7 @@ opentelemetry = "0.20.0"
opentelemetry-otlp = { version = "0.13.0", features = ["grpc-tonic", "metrics"] }
opentelemetry_api = { version = "0.20.0", features = ["metrics"] }
opentelemetry_sdk = { version = "0.20.0", features = ["metrics", "rt-tokio"] }
tiny-bip39 = "1.0.0"

[features]
network-analysis = []
Expand Down
3 changes: 3 additions & 0 deletions src/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! * `/v1/appdata/{block_number}` - returns decoded extrinsic data for configured app_id and given block number
use crate::api::v2;
use crate::types::IdentityConfig;
use crate::{
api::v1,
network::rpc::{self, Node},
Expand All @@ -27,6 +28,7 @@ use warp::{Filter, Reply};
pub struct Server {
pub db: Arc<DB>,
pub cfg: RuntimeConfig,
pub identity_cfg: IdentityConfig,
pub state: Arc<Mutex<State>>,
pub version: String,
pub network_version: String,
Expand Down Expand Up @@ -59,6 +61,7 @@ impl Server {
self.node,
self.state.clone(),
self.cfg,
self.identity_cfg,
self.node_client.clone(),
self.ws_clients.clone(),
crate::data::RocksDB(self.db.clone()),
Expand Down
4 changes: 0 additions & 4 deletions src/api/v2/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ pub async fn submit(
submitter: Arc<impl transactions::Submit>,
transaction: Transaction,
) -> Result<SubmitResponse, Error> {
if matches!(&transaction, Transaction::Data(_)) && !submitter.has_signer() {
return Err(Error::not_found());
};

submitter
.submit(transaction)
.await
Expand Down
51 changes: 18 additions & 33 deletions src/api/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use crate::{
api::v2::types::Topic,
data::{Database, RocksDB},
network::rpc::{Client, Node},
types::{RuntimeConfig, State},
types::{IdentityConfig, RuntimeConfig, State},
};
use avail_subxt::AvailConfig;
use sp_core::sr25519::Pair;
use std::{
convert::Infallible,
fmt::Display,
sync::{Arc, Mutex},
};
use subxt::tx::PairSigner;
use tokio::sync::broadcast;
use tracing::{debug, error, info};
use warp::{Filter, Rejection, Reply};
Expand Down Expand Up @@ -184,6 +187,7 @@ pub fn routes(
node: Node,
state: Arc<Mutex<State>>,
config: RuntimeConfig,
identity_config: IdentityConfig,
node_client: Client,
ws_clients: WsClients,
db: RocksDB,
Expand All @@ -194,7 +198,7 @@ pub fn routes(
};

let app_id = config.app_id.as_ref();
let pair_signer = config.avail_secret_key.clone().map(From::from);
let pair_signer = <PairSigner<AvailConfig, Pair>>::new(identity_config.avail_secret_key);

let submitter = app_id.map(|&app_id| {
Arc::new(transactions::Submitter {
Expand Down Expand Up @@ -612,9 +616,7 @@ mod tests {
}

#[derive(Clone)]
struct MockSubmitter {
pub has_signer: bool,
}
struct MockSubmitter {}

#[async_trait]
impl transactions::Submit for MockSubmitter {
Expand All @@ -625,10 +627,6 @@ mod tests {
index: 0,
})
}

fn has_signer(&self) -> bool {
self.has_signer
}
}

#[derive(Clone, Default)]
Expand Down Expand Up @@ -656,7 +654,7 @@ mod tests {
#[test_case(r#"{"data":"dHJhbnooNhY3Rpb24:"}"#, b"Request body deserialize error: Invalid byte" ; "Invalid base64 value")]
#[tokio::test]
async fn submit_route_bad_request(json: &str, message: &[u8]) {
let route = super::submit_route(Some(Arc::new(MockSubmitter { has_signer: true })));
let route = super::submit_route(Some(Arc::new(MockSubmitter {})));
let response = warp::test::request()
.method("POST")
.path("/v2/submit")
Expand All @@ -667,23 +665,11 @@ mod tests {
assert!(response.body().starts_with(message));
}

#[tokio::test]
async fn submit_route_no_signign_key() {
let route = super::submit_route(Some(Arc::new(MockSubmitter { has_signer: false })));
let response = warp::test::request()
.method("POST")
.path("/v2/submit")
.body(r#"{"data":"dHJhbnNhY3Rpb24K"}"#)
.reply(&route)
.await;
assert_eq!(response.status(), StatusCode::NOT_FOUND);
}

#[test_case(r#"{"data":"dHJhbnNhY3Rpb24K"}"# ; "No errors in case of submitted data")]
#[test_case(r#"{"extrinsic":"dHJhbnNhY3Rpb24K"}"# ; "No errors in case of submitted extrinsic")]
#[tokio::test]
async fn submit_route_extrinsic(body: &str) {
let route = super::submit_route(Some(Arc::new(MockSubmitter { has_signer: true })));
let route = super::submit_route(Some(Arc::new(MockSubmitter {})));
let response = warp::test::request()
.method("POST")
.path("/v2/submit")
Expand Down Expand Up @@ -821,20 +807,19 @@ mod tests {
Uuid::try_parse(uuid).unwrap()
}

#[test_case(r#"{"type":"submit","request_id":"16b24956-2e01-4ba8-bad5-456c561c87d7","message":{"data":""}}"#, None, Some("16b24956-2e01-4ba8-bad5-456c561c87d7"), "Submit is not configured" ; "No submitter")]
#[test_case(r#"{"type":"submit","request_id":"537a3c39-c029-4283-9612-17465bf7cfd1","message":{"data":"dHJhbnNhY3Rpb24K"}}"#, Some(false), Some("537a3c39-c029-4283-9612-17465bf7cfd1"), "Signer is not configured" ; "No signer")]
#[test_case(r#"{"type":"submit","request_id":"36bc1f28-e093-422f-964b-1cb1b3882baf","message":{"extrinsic":""}}"#, Some(false), Some("36bc1f28-e093-422f-964b-1cb1b3882baf"), "Transaction is empty" ; "Empty extrinsic")]
#[test_case(r#"{"type":"submit","request_id":"cc60b2f3-d9ff-4c73-9632-d21d07f7b620","message":{"data":""}}"#, Some(true), Some("cc60b2f3-d9ff-4c73-9632-d21d07f7b620"), "Transaction is empty" ; "Empty data")]
#[test_case(r#"{"type":"submit","request_id":"9181df86-22f0-42a1-a965-60adb9fc6bdc","message":{"extrinsic":"bad"}}"#, Some(false), None, "Failed to parse request" ; "Bad extrinsic")]
#[test_case(r#"{"type":"submit","request_id":"78cd7b7b-ba70-48e9-a1da-96b370db4d8f","message":{"data":"bad"}}"#, Some(true), None, "Failed to parse request" ; "Bad data")]
#[test_case(r#"{"type":"submit","request_id":"16b24956-2e01-4ba8-bad5-456c561c87d7","message":{"data":""}}"#, false, Some("16b24956-2e01-4ba8-bad5-456c561c87d7"), "Submit is not configured" ; "No submitter")]
#[test_case(r#"{"type":"submit","request_id":"36bc1f28-e093-422f-964b-1cb1b3882baf","message":{"extrinsic":""}}"#, true, Some("36bc1f28-e093-422f-964b-1cb1b3882baf"), "Transaction is empty" ; "Empty extrinsic")]
#[test_case(r#"{"type":"submit","request_id":"cc60b2f3-d9ff-4c73-9632-d21d07f7b620","message":{"data":""}}"#, true, Some("cc60b2f3-d9ff-4c73-9632-d21d07f7b620"), "Transaction is empty" ; "Empty data")]
#[test_case(r#"{"type":"submit","request_id":"9181df86-22f0-42a1-a965-60adb9fc6bdc","message":{"extrinsic":"bad"}}"#, true, None, "Failed to parse request" ; "Bad extrinsic")]
#[test_case(r#"{"type":"submit","request_id":"78cd7b7b-ba70-48e9-a1da-96b370db4d8f","message":{"data":"bad"}}"#, true, None, "Failed to parse request" ; "Bad data")]
#[tokio::test]
async fn ws_route_submit_bad_requests(
request: &str,
signer: Option<bool>,
submitter: bool,
expected_request_id: Option<&str>,
expected: &str,
) {
let submitter = signer.map(|has_signer| MockSubmitter { has_signer });
let submitter = submitter.then_some(MockSubmitter {});
let expected_request_id = expected_request_id.map(to_uuid);
let mut test = MockSetup::new(RuntimeConfig::default(), submitter).await;
let response = test.ws_send_text(request).await;
Expand All @@ -846,7 +831,7 @@ mod tests {

#[tokio::test]
async fn ws_route_submit_data() {
let submitter = Some(MockSubmitter { has_signer: true });
let submitter = Some(MockSubmitter {});
let mut test = MockSetup::new(RuntimeConfig::default(), submitter).await;

let request = r#"{"type":"submit","request_id":"fca2ff0c-7a26-42a2-a6f0-d0aeeaba8a9a","message":{"data":"dHJhbnNhY3Rpb24K"}}"#;
Expand All @@ -864,7 +849,7 @@ mod tests {

#[tokio::test]
async fn ws_route_submit_extrinsic() {
let submitter = Some(MockSubmitter { has_signer: true });
let submitter = Some(MockSubmitter {});
let mut test = MockSetup::new(RuntimeConfig::default(), submitter).await;

let request = r#"{"type":"submit","request_id":"fca2ff0c-7a26-42a2-a6f0-d0aeeaba8a9a","message":{"extrinsic":"dHJhbnNhY3Rpb24K"}}"#;
Expand Down
28 changes: 6 additions & 22 deletions src/api/v2/transactions.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,33 @@
use crate::{network::rpc, types::AvailSecretKey};
use crate::network::rpc;

use super::types::{SubmitResponse, Transaction};
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result};
use async_trait::async_trait;
use avail_subxt::{api, primitives::AvailExtrinsicParams, AvailConfig};
use subxt::{ext::sp_core::sr25519::Pair, tx::PairSigner};
use sp_core::sr25519::Pair;
use subxt::tx::PairSigner;

#[async_trait]
pub trait Submit {
async fn submit(&self, transaction: Transaction) -> Result<SubmitResponse>;
fn has_signer(&self) -> bool;
}

// TODO: Replace this with avail::PairSigner after implementing required traits in avail-subxt
pub type AvailSigner = PairSigner<AvailConfig, Pair>;

impl From<AvailSecretKey> for AvailSigner {
fn from(value: AvailSecretKey) -> Self {
AvailSigner::new(value.0)
}
}

#[derive(Clone)]
pub struct Submitter {
pub node_client: rpc::Client,
pub app_id: u32,
pub pair_signer: Option<AvailSigner>,
pub pair_signer: PairSigner<AvailConfig, Pair>,
}

#[async_trait]
impl Submit for Submitter {
async fn submit(&self, transaction: Transaction) -> Result<SubmitResponse> {
let tx_progress = match transaction {
Transaction::Data(data) => {
let Some(pair_signer) = self.pair_signer.as_ref() else {
return Err(anyhow!("Pair signer is not configured"));
};
let extrinsic = api::tx().data_availability().submit_data(data.into());
let params = AvailExtrinsicParams::new_with_app_id(self.app_id.into());
self.node_client
.submit_signed_and_watch(extrinsic, pair_signer.to_owned(), params)
.submit_signed_and_watch(extrinsic, self.pair_signer.clone(), params)
.await?
},
Transaction::Extrinsic(extrinsic) => {
Expand All @@ -58,8 +46,4 @@ impl Submit for Submitter {
})
.context("Cannot sign and submit transaction")
}

fn has_signer(&self) -> bool {
self.pair_signer.is_some()
}
}
7 changes: 1 addition & 6 deletions src/api/v2/ws.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use super::{
transactions,
types::{
Payload, Request, Response, Status, Transaction, Version, WsClients, WsError, WsResponse,
},
types::{Payload, Request, Response, Status, Version, WsClients, WsError, WsResponse},
};
use crate::{
api::v2::types::{Error, Sender},
Expand Down Expand Up @@ -111,9 +109,6 @@ async fn handle_request(
if transaction.is_empty() {
return Err(Error::bad_request(request_id, "Transaction is empty."));
}
if matches!(transaction, Transaction::Data(_)) && !submitter.has_signer() {
return Err(Error::bad_request(request_id, "Signer is not configured."));
};

submitter
.submit(transaction)
Expand Down
5 changes: 5 additions & 0 deletions src/bin/avail-light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use anyhow::{anyhow, Context, Result};
use avail_core::AppId;
use avail_light::types::IdentityConfig;
use avail_light::{api, data, network::rpc, telemetry};
use avail_light::{
consts::EXPECTED_NETWORK_VERSION,
Expand Down Expand Up @@ -84,6 +85,9 @@ async fn run(error_sender: Sender<anyhow::Error>) -> Result<()> {
tracing::subscriber::set_global_default(default_subscriber(log_level))
.expect("global default subscriber is set")
}

let identity_cfg = IdentityConfig::load_or_init("identity.toml", None)?;

let version = clap::crate_version!();
info!("Running Avail light client version: {version}");
info!("Using config: {cfg:?}");
Expand Down Expand Up @@ -215,6 +219,7 @@ async fn run(error_sender: Sender<anyhow::Error>) -> Result<()> {
let server = api::server::Server {
db: db.clone(),
cfg: cfg.clone(),
identity_cfg,
state: state.clone(),
version: format!("v{}", clap::crate_version!()),
network_version: EXPECTED_NETWORK_VERSION.to_string(),
Expand Down
Loading

0 comments on commit b2c2ea7

Please sign in to comment.