keyforkd: split into enum based request
This commit is contained in:
parent
48e4d7096c
commit
ada6cf150b
|
@ -1103,6 +1103,7 @@ dependencies = [
|
|||
"keyfork-frame",
|
||||
"keyfork-mnemonic-util",
|
||||
"keyfork-slip10-test-data",
|
||||
"keyforkd-models",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
@ -1121,11 +1122,21 @@ dependencies = [
|
|||
"keyfork-frame",
|
||||
"keyfork-slip10-test-data",
|
||||
"keyforkd",
|
||||
"keyforkd-models",
|
||||
"tempdir",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keyforkd-models"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"keyfork-derive-util",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.20.0"
|
||||
|
@ -1944,18 +1955,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -15,5 +15,6 @@ members = [
|
|||
"keyfork-slip10-test-data",
|
||||
"keyforkd",
|
||||
"keyforkd-client",
|
||||
"keyforkd-models",
|
||||
"smex",
|
||||
]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{env, process::ExitCode, str::FromStr};
|
||||
|
||||
use keyfork_derive_util::{
|
||||
request::{DerivationAlgorithm, DerivationError, DerivationRequest},
|
||||
request::{DerivationAlgorithm, DerivationError, DerivationRequest, DerivationResponse},
|
||||
DerivationPath,
|
||||
};
|
||||
use keyforkd_client::Client;
|
||||
|
@ -38,8 +38,8 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
let mut client = Client::discover_socket()?;
|
||||
let request = DerivationRequest::new(algo, &path);
|
||||
let response = client.request(&request)?;
|
||||
println!("{}", smex::encode(&response.data));
|
||||
let response = client.request(&request.into())?;
|
||||
println!("{}", smex::encode(&DerivationResponse::try_from(response)?.data));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{env, process::ExitCode, str::FromStr};
|
||||
|
||||
use keyfork_derive_util::{
|
||||
request::{DerivationAlgorithm, DerivationRequest},
|
||||
request::{DerivationAlgorithm, DerivationRequest, DerivationResponse},
|
||||
DerivationIndex, DerivationPath,
|
||||
};
|
||||
use keyforkd_client::Client;
|
||||
|
@ -107,7 +107,9 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||
};
|
||||
|
||||
let request = DerivationRequest::new(DerivationAlgorithm::Ed25519, &path);
|
||||
let derived_data = Client::discover_socket()?.request(&request)?;
|
||||
let derived_data: DerivationResponse = Client::discover_socket()?
|
||||
.request(&request.into())?
|
||||
.try_into()?;
|
||||
let subkeys = subkey_format
|
||||
.iter()
|
||||
.map(|kt| kt.inner().clone())
|
||||
|
|
|
@ -14,6 +14,7 @@ secp256k1 = ["keyfork-derive-util/secp256k1"]
|
|||
bincode = "1.3.3"
|
||||
keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util", default-features = false }
|
||||
keyfork-frame = { version = "0.1.0", path = "../keyfork-frame" }
|
||||
keyforkd-models = { version = "0.1.0", path = "../keyforkd-models" }
|
||||
thiserror = "1.0.49"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{collections::HashMap, os::unix::net::UnixStream, path::PathBuf};
|
||||
|
||||
use keyfork_derive_util::request::{DerivationRequest, DerivationResponse};
|
||||
use keyfork_frame::{try_decode_from, try_encode_to, DecodeError, EncodeError};
|
||||
use keyforkd_models::{Request, Response /* Error as KeyforkdError */};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -65,7 +65,7 @@ impl Client {
|
|||
get_socket().map(|socket| Self { socket })
|
||||
}
|
||||
|
||||
pub fn request(&mut self, req: &DerivationRequest) -> Result<DerivationResponse> {
|
||||
pub fn request(&mut self, req: &Request) -> Result<Response> {
|
||||
try_encode_to(&bincode::serialize(&req)?, &mut self.socket)?;
|
||||
let resp = try_decode_from(&mut self.socket)?;
|
||||
bincode::deserialize(&resp).map_err(From::from)
|
||||
|
|
|
@ -46,7 +46,8 @@ fn secp256k1() {
|
|||
DerivationAlgorithm::Secp256k1,
|
||||
&DerivationPath::from_str(test.chain).unwrap(),
|
||||
);
|
||||
let response = client.request(&req).unwrap();
|
||||
let response =
|
||||
DerivationResponse::try_from(client.request(&req.into()).unwrap()).unwrap();
|
||||
assert_eq!(response.data, test.private_key);
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,8 @@ fn ed25519() {
|
|||
DerivationAlgorithm::Ed25519,
|
||||
&DerivationPath::from_str(test.chain).unwrap(),
|
||||
);
|
||||
let response = client.request(&req).unwrap();
|
||||
let response =
|
||||
DerivationResponse::try_from(client.request(&req.into()).unwrap()).unwrap();
|
||||
assert_eq!(response.data, test.private_key);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "keyforkd-models"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util", default-features = false }
|
||||
serde = { version = "1.0.190", features = ["derive"] }
|
||||
thiserror = "1.0.50"
|
|
@ -0,0 +1,84 @@
|
|||
//! All values that can be sent to and returned from Keyforkd.
|
||||
//!
|
||||
//! All Error values are stored as enum unit values.
|
||||
|
||||
use keyfork_derive_util::request::{DerivationRequest, DerivationResponse};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A request made to Keyforkd.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum Request {
|
||||
/// A derivation request.
|
||||
Derivation(DerivationRequest),
|
||||
|
||||
/// A derivation request, with a TTY provided for pinentry if necessary.
|
||||
DerivationWithTTY(DerivationRequest, String),
|
||||
}
|
||||
|
||||
impl From<DerivationRequest> for Request {
|
||||
fn from(value: DerivationRequest) -> Self {
|
||||
Self::Derivation(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(DerivationRequest, String)> for Request {
|
||||
fn from((request, tty): (DerivationRequest, String)) -> Self {
|
||||
Self::DerivationWithTTY(request, tty)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum DerivationError {
|
||||
#[error("The provided TTY was not valid")]
|
||||
InvalidTTY,
|
||||
|
||||
#[error("A TTY was required by the pinentry program but was not provided")]
|
||||
NoTTY,
|
||||
|
||||
#[error("Invalid derivation length: Expected 2, actual: {0}")]
|
||||
InvalidDerivationLength(usize),
|
||||
|
||||
#[error("Derivation error: {0}")]
|
||||
Derivation(String),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Derivation(#[from] DerivationError),
|
||||
}
|
||||
|
||||
/// Any response from a Keyforkd request.
|
||||
///
|
||||
/// Responses can be converted to their inner values without matching the Response type by
|
||||
/// using a type annotation and [`TryInto::try_into`].
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Response {
|
||||
/// A derivation response.
|
||||
///
|
||||
/// From:
|
||||
/// * [`Request::Derivation`]
|
||||
/// * [`Request::DerivationWithTTY`]
|
||||
Derivation(DerivationResponse),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error("Unable to downcast to {0}")]
|
||||
pub struct Downcast(&'static str);
|
||||
|
||||
use std::any::type_name;
|
||||
|
||||
impl TryFrom<Response> for DerivationResponse {
|
||||
type Error = Downcast;
|
||||
|
||||
fn try_from(value: Response) -> Result<Self, Self::Error> {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let Response::Derivation(response) = value {
|
||||
Ok(response)
|
||||
} else {
|
||||
Err(Downcast(type_name::<Self>()))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ tower = { version = "0.4.13", features = ["tokio", "util"] }
|
|||
thiserror = "1.0.47"
|
||||
serde = { version = "1.0.186", features = ["derive"] }
|
||||
keyfork-derive-path-data = { version = "0.1.0", path = "../keyfork-derive-path-data" }
|
||||
keyforkd-models = { version = "0.1.0", path = "../keyforkd-models" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.4.1"
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
use std::{future::Future, pin::Pin, sync::Arc, task::Poll};
|
||||
|
||||
use keyfork_derive_path_data::guess_target;
|
||||
use keyfork_derive_util::request::{DerivationError, DerivationRequest, DerivationResponse};
|
||||
// use keyfork_derive_util::request::{DerivationError, DerivationRequest, DerivationResponse};
|
||||
use keyforkd_models::{DerivationError, Error, Request, Response};
|
||||
use tower::Service;
|
||||
use tracing::info;
|
||||
|
||||
// NOTE: All values implemented in Keyforkd must implement Clone with low overhead, either by
|
||||
// using an Arc or by having a small signature. This is because Service<T> takes &mut self.
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum KeyforkdRequestError {
|
||||
#[error("Invalid derivation length: Expected: 2, actual: {0}")]
|
||||
InvalidDerivationLength(usize),
|
||||
|
||||
#[error("Derivation error: {0}")]
|
||||
Derivation(#[from] DerivationError),
|
||||
}
|
||||
|
||||
//
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Keyforkd {
|
||||
seed: Arc<Vec<u8>>,
|
||||
|
@ -30,10 +22,11 @@ impl Keyforkd {
|
|||
}
|
||||
}
|
||||
|
||||
impl Service<DerivationRequest> for Keyforkd {
|
||||
type Response = DerivationResponse;
|
||||
impl Service<Request> for Keyforkd {
|
||||
type Response = Response;
|
||||
|
||||
type Error = KeyforkdRequestError;
|
||||
// TODO: indicate serialize in BincodeLayer
|
||||
type Error = Error;
|
||||
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
|
@ -45,12 +38,13 @@ impl Service<DerivationRequest> for Keyforkd {
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))]
|
||||
fn call(&mut self, req: DerivationRequest) -> Self::Future {
|
||||
fn call(&mut self, req: Request) -> Self::Future {
|
||||
let seed = self.seed.clone();
|
||||
Box::pin(async move {
|
||||
match req {
|
||||
Request::Derivation(req) => Box::pin(async move {
|
||||
let len = req.path().len();
|
||||
if len < 2 {
|
||||
return Err(KeyforkdRequestError::InvalidDerivationLength(len));
|
||||
return Err(DerivationError::InvalidDerivationLength(len).into());
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
|
@ -61,8 +55,11 @@ impl Service<DerivationRequest> for Keyforkd {
|
|||
}
|
||||
|
||||
req.derive_with_master_seed((*seed).clone())
|
||||
.map_err(KeyforkdRequestError::from)
|
||||
})
|
||||
.map(Response::Derivation)
|
||||
.map_err(|e| DerivationError::Derivation(e.to_string()).into())
|
||||
}),
|
||||
Request::DerivationWithTTY(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +89,15 @@ mod tests {
|
|||
continue;
|
||||
}
|
||||
let req = DerivationRequest::new(DerivationAlgorithm::Secp256k1, &chain);
|
||||
let response = keyforkd.ready().await.unwrap().call(req).await.unwrap();
|
||||
let response: DerivationResponse = keyforkd
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(Request::Derivation(req))
|
||||
.await
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
assert_eq!(response.data, test.private_key);
|
||||
assert_eq!(response.chain_code.as_slice(), test.chain_code);
|
||||
}
|
||||
|
@ -114,7 +119,15 @@ mod tests {
|
|||
continue;
|
||||
}
|
||||
let req = DerivationRequest::new(DerivationAlgorithm::Ed25519, &chain);
|
||||
let response = keyforkd.ready().await.unwrap().call(req).await.unwrap();
|
||||
let response: DerivationResponse = keyforkd
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(Request::Derivation(req))
|
||||
.await
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
assert_eq!(response.data, test.private_key);
|
||||
assert_eq!(response.chain_code.as_slice(), test.chain_code);
|
||||
}
|
||||
|
@ -134,7 +147,15 @@ mod tests {
|
|||
for (seed, path, _, private_key, _) in tests {
|
||||
let req = DerivationRequest::new(DerivationAlgorithm::Ed25519, &path);
|
||||
let mut keyforkd = Keyforkd::new(seed.to_vec());
|
||||
let response = keyforkd.ready().await.unwrap().call(req).await.unwrap();
|
||||
let response: DerivationResponse = keyforkd
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(Request::Derivation(req))
|
||||
.await
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
assert_eq!(response.data, private_key)
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +173,15 @@ mod tests {
|
|||
for (seed, path, _, private_key, _) in tests {
|
||||
let req = DerivationRequest::new(DerivationAlgorithm::Ed25519, &path);
|
||||
let mut keyforkd = Keyforkd::new(seed.to_vec());
|
||||
let response = keyforkd.ready().await.unwrap().call(req).await.unwrap();
|
||||
let response: DerivationResponse = keyforkd
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(Request::Derivation(req))
|
||||
.await
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
assert_eq!(response.data, private_key)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue