keyforkd-client: extract from keyfork-derive-key

This commit is contained in:
Ryan Heywood 2023-09-27 21:30:56 -05:00
parent c4882f2d21
commit 1b6241f92b
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
11 changed files with 122 additions and 85 deletions

23
Cargo.lock generated
View File

@ -533,6 +533,7 @@ dependencies = [
"keyfork-frame", "keyfork-frame",
"keyfork-slip10-test-data", "keyfork-slip10-test-data",
"keyforkd", "keyforkd",
"keyforkd-client",
"tempdir", "tempdir",
"thiserror", "thiserror",
"tokio", "tokio",
@ -617,6 +618,20 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
] ]
[[package]]
name = "keyforkd-client"
version = "0.1.0"
dependencies = [
"bincode",
"keyfork-derive-util",
"keyfork-frame",
"keyfork-slip10-test-data",
"keyforkd",
"tempdir",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -1072,18 +1087,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -11,5 +11,6 @@ members = [
"keyfork-mnemonic-util", "keyfork-mnemonic-util",
"keyfork-slip10-test-data", "keyfork-slip10-test-data",
"keyforkd", "keyforkd",
"keyforkd-client",
"smex", "smex",
] ]

View File

@ -10,6 +10,7 @@ bincode = { version = "1.3.3", default-features = false }
clap = { version = "4.4.2", default-features = false, features = ["std", "usage", "help", "derive"] } clap = { version = "4.4.2", default-features = false, features = ["std", "usage", "help", "derive"] }
keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util" } keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util" }
keyfork-frame = { version = "0.1.0", path = "../keyfork-frame", default-features = false } keyfork-frame = { version = "0.1.0", path = "../keyfork-frame", default-features = false }
keyforkd-client = { version = "0.1.0", path = "../keyforkd-client" }
thiserror = "1.0.48" thiserror = "1.0.48"
[dev-dependencies] [dev-dependencies]

View File

@ -1,6 +1,9 @@
use crate::client::Client;
use clap::Parser; use clap::Parser;
use keyfork_derive_util::{request::{DerivationAlgorithm, DerivationRequest, DerivationResponse}, DerivationPath}; use keyfork_derive_util::{
request::{DerivationAlgorithm, DerivationRequest, DerivationResponse},
DerivationPath,
};
use keyforkd_client::{Client, Result};
#[derive(Parser, Clone, Debug)] #[derive(Parser, Clone, Debug)]
pub struct Command { pub struct Command {
@ -12,7 +15,7 @@ pub struct Command {
} }
impl Command { impl Command {
pub fn handle(&self) -> super::Result<DerivationResponse> { pub fn handle(&self) -> Result<DerivationResponse> {
let mut client = Client::discover_socket()?; let mut client = Client::discover_socket()?;
let request = DerivationRequest::new(self.algorithm.clone(), &self.path); let request = DerivationRequest::new(self.algorithm.clone(), &self.path);
client.request(&request) client.request(&request)

View File

@ -1,25 +0,0 @@
use crate::Result;
use keyfork_derive_util::request::{DerivationRequest, DerivationResponse};
use keyfork_frame::{try_decode_from, try_encode_to};
use std::os::unix::net::UnixStream;
#[derive(Debug)]
pub struct Client {
socket: UnixStream,
}
impl Client {
pub fn new(socket: UnixStream) -> Self {
Self { socket }
}
pub fn discover_socket() -> Result<Self> {
super::socket::get_socket().map(|socket| Self { socket })
}
pub fn request(&mut self, req: &DerivationRequest) -> Result<DerivationResponse> {
try_encode_to(&bincode::serialize(&req)?, &mut self.socket)?;
let resp = try_decode_from(&mut self.socket)?;
bincode::deserialize(&resp).map_err(From::from)
}
}

View File

@ -1,11 +1,4 @@
use keyfork_frame::{DecodeError, EncodeError};
use std::path::PathBuf;
pub mod cli; pub mod cli;
pub mod client;
pub mod socket;
pub use client::Client;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
@ -15,23 +8,8 @@ pub enum Error {
#[error("The given path was incorrectly formatted: {0}")] #[error("The given path was incorrectly formatted: {0}")]
ArgsFormat(#[from] keyfork_derive_util::path::Error), ArgsFormat(#[from] keyfork_derive_util::path::Error),
#[error("Neither KEYFORK_SOCKET_PATH nor XDG_RUNTIME_DIR were set")] #[error("Unable to perform key derivation request: {0}")]
EnvVarsNotFound, KeyforkdClient(#[from] keyforkd_client::Error),
#[error("Socket was unable to connect to {1}: {0}")]
Connect(std::io::Error, PathBuf),
#[error("Could not write to or from the socket: {0}")]
Io(#[from] std::io::Error),
#[error("Could not perform bincode transformation: {0}")]
Bincode(#[from] Box<bincode::ErrorKind>),
#[error("Could not perform frame transformation: {0}")]
FrameEnc(#[from] EncodeError),
#[error("Could not perform frame transformation: {0}")]
FrameDec(#[from] DecodeError),
} }
pub type Result<T, E = Error> = std::result::Result<T, E>; pub type Result<T, E = Error> = std::result::Result<T, E>;

View File

@ -1,8 +1,5 @@
use clap::Parser; use clap::Parser;
#[cfg(test)]
mod tests;
#[allow(clippy::wildcard_imports)] #[allow(clippy::wildcard_imports)]
use keyfork_derive_key::*; use keyfork_derive_key::*;

View File

@ -1,25 +0,0 @@
use super::Error;
use std::{collections::HashMap, os::unix::net::UnixStream, path::PathBuf};
#[allow(clippy::module_name_repetitions)]
pub fn get_socket() -> Result<UnixStream, Error> {
let socket_vars = std::env::vars()
.filter(|(key, _)| ["XDG_RUNTIME_DIR", "KEYFORKD_SOCKET_PATH"].contains(&key.as_str()))
.collect::<HashMap<String, String>>();
let mut socket_path: PathBuf;
#[allow(clippy::single_match_else)]
match socket_vars.get("KEYFORKD_SOCKET_PATH") {
Some(occupied) => {
socket_path = PathBuf::from(occupied);
}
None => {
socket_path = PathBuf::from(
socket_vars
.get("XDG_RUNTIME_DIR")
.ok_or(Error::EnvVarsNotFound)?,
);
socket_path.extend(["keyforkd", "keyforkd.sock"]);
}
}
UnixStream::connect(&socket_path).map_err(|e| Error::Connect(e, socket_path))
}

View File

@ -0,0 +1,18 @@
[package]
name = "keyforkd-client"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3.3"
keyfork-derive-util = { version = "0.1.0", path = "../keyfork-derive-util" }
keyfork-frame = { version = "0.1.0", path = "../keyfork-frame" }
thiserror = "1.0.49"
[dev-dependencies]
keyfork-slip10-test-data = { path = "../keyfork-slip10-test-data" }
keyforkd = { path = "../keyforkd" }
tempdir = "0.3.7"
tokio = { version = "1.32.0", features = ["rt", "sync", "rt-multi-thread"] }

View File

@ -0,0 +1,73 @@
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};
#[cfg(test)]
mod tests;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Neither KEYFORK_SOCKET_PATH nor XDG_RUNTIME_DIR were set")]
EnvVarsNotFound,
#[error("Socket was unable to connect to {1}: {0}")]
Connect(std::io::Error, PathBuf),
#[error("Could not write to or from the socket: {0}")]
Io(#[from] std::io::Error),
#[error("Could not perform bincode transformation: {0}")]
Bincode(#[from] Box<bincode::ErrorKind>),
#[error("Could not perform frame transformation: {0}")]
FrameEnc(#[from] EncodeError),
#[error("Could not perform frame transformation: {0}")]
FrameDec(#[from] DecodeError),
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub fn get_socket() -> Result<UnixStream, Error> {
let socket_vars = std::env::vars()
.filter(|(key, _)| ["XDG_RUNTIME_DIR", "KEYFORKD_SOCKET_PATH"].contains(&key.as_str()))
.collect::<HashMap<String, String>>();
let mut socket_path: PathBuf;
#[allow(clippy::single_match_else)]
match socket_vars.get("KEYFORKD_SOCKET_PATH") {
Some(occupied) => {
socket_path = PathBuf::from(occupied);
}
None => {
socket_path = PathBuf::from(
socket_vars
.get("XDG_RUNTIME_DIR")
.ok_or(Error::EnvVarsNotFound)?,
);
socket_path.extend(["keyforkd", "keyforkd.sock"]);
}
}
UnixStream::connect(&socket_path).map_err(|e| Error::Connect(e, socket_path))
}
#[derive(Debug)]
pub struct Client {
socket: UnixStream,
}
impl Client {
pub fn new(socket: UnixStream) -> Self {
Self { socket }
}
pub fn discover_socket() -> Result<Self> {
get_socket().map(|socket| Self { socket })
}
pub fn request(&mut self, req: &DerivationRequest) -> Result<DerivationResponse> {
try_encode_to(&bincode::serialize(&req)?, &mut self.socket)?;
let resp = try_decode_from(&mut self.socket)?;
bincode::deserialize(&resp).map_err(From::from)
}
}

View File

@ -1,4 +1,4 @@
use crate::client::Client; use crate::Client;
use keyfork_derive_util::{request::*, DerivationPath}; use keyfork_derive_util::{request::*, DerivationPath};
use keyfork_slip10_test_data::test_data; use keyfork_slip10_test_data::test_data;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
@ -13,6 +13,7 @@ fn secp256k1() {
.remove(&"secp256k1".to_string()) .remove(&"secp256k1".to_string())
.unwrap(); .unwrap();
// todo: move to tokio::sync channels to avoid using multi thread tokio
let rt = Builder::new_multi_thread().enable_io().build().unwrap(); let rt = Builder::new_multi_thread().enable_io().build().unwrap();
let tempdir = TempDir::new("keyfork-seed").unwrap(); let tempdir = TempDir::new("keyfork-seed").unwrap();
for (i, per_seed) in tests.into_iter().enumerate() { for (i, per_seed) in tests.into_iter().enumerate() {