Interactive onboard implemented

This commit is contained in:
Steven Roose
2024-01-17 13:17:14 +00:00
parent fd241ac574
commit 9933368b48
17 changed files with 664 additions and 65 deletions

View File

@@ -9,8 +9,12 @@ edition = "2021"
tonic-build = "0.10"
[dependencies]
ark-lib = { path = "../ark-lib" }
anyhow.workspace = true
lazy_static.workspace = true
serde.workspace = true
ciborium.workspace = true
bitcoin.workspace = true
bip39.workspace = true
bdk.workspace = true

View File

@@ -16,14 +16,11 @@ message ArkInfo {
}
message OnboardCosignRequest {
bytes onboard_tx = 1;
uint32 onboard_tx_vout = 2;
bytes exit_tx = 3;
bytes exit_tx_signature = 4;
bytes user_part = 1;
}
message OnboardCosignResponse {
bytes exit_tx_signature = 1;
bytes asp_part = 1;
}

View File

@@ -2,6 +2,7 @@
mod database;
mod rpc;
mod rpcserver;
use std::fs;
use std::net::SocketAddr;
@@ -90,7 +91,11 @@ impl App {
wallet: Mutex::new(wallet),
bitcoind: bitcoind,
});
ret.start_public_rpc_server();
let app = ret.clone();
let _ = tokio::spawn(async move {
app.start_public_rpc_server().await;
});
Ok(ret)
}
@@ -141,36 +146,7 @@ impl App {
Ok(Amount::from_sat(balance.total()))
}
pub async fn start_public_rpc_server(self: &Arc<Self>) {
let addr = self.config.public_rpc_address;
let server = rpc::ArkServiceServer::new(self.clone());
//TODO(stevenroose) capture thread so we can cancel later
let _ = tokio::spawn(async move {
tonic::transport::Server::builder()
.add_service(server)
.serve(addr)
.await
});
pub fn cosign_onboard(self: &Arc<Self>, user_part: ark::onboard::UserPart) -> ark::onboard::AspPart {
ark::onboard::new_asp(&user_part, self.master_key)
}
}
#[tonic::async_trait]
impl rpc::ArkService for Arc<App> {
async fn get_ark_info(
&self,
_: tonic::Request<rpc::Empty>,
) -> Result<tonic::Response<rpc::ArkInfo>, tonic::Status> {
let ret = rpc::ArkInfo {
pubkey: self.master_pubkey.serialize().to_vec(),
xonly_pubkey: self.master_pubkey.x_only_public_key().0.serialize().to_vec(),
};
Ok(tonic::Response::new(ret))
}
async fn request_onboard_cosign(
&self,
req: tonic::Request<rpc::OnboardCosignRequest>,
) -> Result<tonic::Response<rpc::OnboardCosignResponse>, tonic::Status> {
unimplemented!();
}
}

View File

@@ -10,19 +10,13 @@ pub struct ArkInfo {
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct OnboardCosignRequest {
#[prost(bytes = "vec", tag = "1")]
pub onboard_tx: ::prost::alloc::vec::Vec<u8>,
#[prost(uint32, tag = "2")]
pub onboard_tx_vout: u32,
#[prost(bytes = "vec", tag = "3")]
pub exit_tx: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "4")]
pub exit_tx_signature: ::prost::alloc::vec::Vec<u8>,
pub user_part: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct OnboardCosignResponse {
#[prost(bytes = "vec", tag = "1")]
pub exit_tx_signature: ::prost::alloc::vec::Vec<u8>,
pub asp_part: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]

74
arkd/src/rpcserver.rs Normal file
View File

@@ -0,0 +1,74 @@
use std::sync::Arc;
use crate::App;
use crate::rpc;
impl App {
pub async fn start_public_rpc_server(self: &Arc<Self>) {
let addr = self.config.public_rpc_address;
let server = rpc::ArkServiceServer::new(self.clone());
//TODO(stevenroose) capture thread so we can cancel later
let _ = tokio::spawn(async move {
tonic::transport::Server::builder()
.add_service(server)
.serve(addr)
.await
});
}
}
macro_rules! badarg {
($($arg:tt)*) => {{
tonic::Status::invalid_argument(format!($($arg)*))
}};
}
macro_rules! internal {
($($arg:tt)*) => {{
tonic::Status::internal(format!($($arg)*))
}};
}
/// Just a trait to easily convert some kind of errors to tonic things.
trait ToStatus<T> {
fn to_status(self) -> Result<T, tonic::Status>;
}
impl<T> ToStatus<T> for anyhow::Result<T> {
fn to_status(self) -> Result<T, tonic::Status> {
self.map_err(|e| tonic::Status::internal(format!("internal error: {}", e)))
}
}
#[tonic::async_trait]
impl rpc::ArkService for Arc<App> {
async fn get_ark_info(
&self,
_req: tonic::Request<rpc::Empty>,
) -> Result<tonic::Response<rpc::ArkInfo>, tonic::Status> {
let ret = rpc::ArkInfo {
pubkey: self.master_pubkey.serialize().to_vec(),
xonly_pubkey: self.master_pubkey.x_only_public_key().0.serialize().to_vec(),
};
Ok(tonic::Response::new(ret))
}
async fn request_onboard_cosign(
&self,
req: tonic::Request<rpc::OnboardCosignRequest>,
) -> Result<tonic::Response<rpc::OnboardCosignResponse>, tonic::Status> {
let req = req.into_inner();
let user_part = ciborium::from_reader(&req.user_part[..])
.map_err(|e| badarg!("invalid user part: {}", e))?;
let asp_part = self.cosign_onboard(user_part);
Ok(tonic::Response::new(rpc::OnboardCosignResponse {
asp_part: {
let mut buf = Vec::new();
ciborium::into_writer(&asp_part, &mut buf).unwrap();
buf
},
}))
}
}