Skip to content

Commit

Permalink
Use password for DB and init properly
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyGiorgio committed May 14, 2024
1 parent 2acdcc7 commit 5050492
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 144 deletions.
270 changes: 139 additions & 131 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use iced::{
futures::{channel::mpsc::Sender, SinkExt},
subscription::{self, Subscription},
};
use log::error;
use log::{error, warn};
use tokio::sync::RwLock;

use crate::fedimint_client::{
Expand Down Expand Up @@ -50,15 +50,9 @@ struct HarborCore {
stop: Arc<AtomicBool>,
}

impl HarborCore {
async fn core_loaded(&self, ui_handle: Arc<bridge::UIHandle>) {
self.tx
.clone()
.send(Message::CoreLoaded(ui_handle))
.await
.unwrap();
}
const INVITE: &str = "fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er";

impl HarborCore {
async fn msg(&self, msg: CoreUIMsg) {
self.tx
.clone()
Expand Down Expand Up @@ -205,152 +199,166 @@ pub fn run_core() -> Subscription<Message> {
subscription::channel(
std::any::TypeId::of::<Connect>(),
100,
|tx: Sender<Message>| async move {
enum State {
NeedsInit,
Running,
}
let mut state = State::NeedsInit;

|mut tx: Sender<Message>| async move {
// Setup UI Handle
let (ui_handle, mut core_handle) = bridge::create_handles();
let arc_ui_handle = Arc::new(ui_handle);
tx.send(Message::UIHandlerLoaded(arc_ui_handle.clone()))
.await
.expect("should send");

let network = Network::Signet;

// Create the datadir if it doesn't exist
let path = PathBuf::from(&conf::data_dir(network));
std::fs::create_dir_all(path.clone()).expect("Could not create datadir");

log::info!("Using datadir: {path:?}");

// Create or get the database
// FIXME: pass in password
let db = setup_db(
path.join("harbor.sqlite")
.to_str()
.expect("path must be correct"),
"password123".to_string(),
);

let mnemonic = get_mnemonic(db.clone()).expect("should get seed");

let stop = Arc::new(AtomicBool::new(false));

// fixme, properly initialize this
let client = FedimintClient::new(
db.clone(),
InviteCode::from_str("fed11qgqzc2nhwden5te0vejkg6tdd9h8gepwvejkg6tdd9h8garhduhx6at5d9h8jmn9wshxxmmd9uqqzgxg6s3evnr6m9zdxr6hxkdkukexpcs3mn7mj3g5pc5dfh63l4tj6g9zk4er").unwrap(),
&mnemonic,
network,
stop.clone(),
)
.await
.expect("Could not create fedimint client");
loop {
let msg = core_handle.recv().await;

match msg {
Some(UICoreMsg::Unlock(password)) => {
tx.send(Message::CoreMessage(CoreUIMsg::Unlocking))
.await
.expect("should send");

// attempting to unlock
let db = setup_db(
path.join("harbor.sqlite")
.to_str()
.expect("path must be correct"),
password,
);

if let Err(e) = db {
// probably invalid password
error!("error using password: {e}");

tx.send(Message::CoreMessage(CoreUIMsg::UnlockFailed(
"Invalid Password".to_string(),
)))
.await
.expect("should send");
continue;
}
let db = db.expect("no error");

let mut clients = HashMap::new();
clients.insert(client.fedimint_client.federation_id(), client);
let mnemonic = get_mnemonic(db.clone()).expect("should get seed");

let mut balance = Amount::ZERO;
for client in clients.values() {
balance += client.fedimint_client.get_balance().await;
}
let stop = Arc::new(AtomicBool::new(false));

let core = HarborCore {
storage: db,
balance,
tx,
mnemonic,
network,
clients: Arc::new(RwLock::new(clients)),
stop,
};
// fixme, properly initialize this
let client = FedimintClient::new(
db.clone(),
InviteCode::from_str(INVITE).unwrap(),
&mnemonic,
network,
stop.clone(),
)
.await
.expect("Could not create fedimint client");

loop {
match &mut state {
State::NeedsInit => {
// Hand the frontend its handle for talking to us
core.core_loaded(arc_ui_handle.clone()).await;
let mut clients = HashMap::new();
clients.insert(client.fedimint_client.federation_id(), client);

// Initialize the ui's state
core.set_balance().await;
let mut balance = Amount::ZERO;
for client in clients.values() {
balance += client.fedimint_client.get_balance().await;
}

state = State::Running;
let core = HarborCore {
storage: db.clone(),
balance,
tx: tx.clone(),
mnemonic,
network,
clients: Arc::new(RwLock::new(clients)),
stop,
};

tx.send(Message::CoreMessage(CoreUIMsg::UnlockSuccess))
.await
.expect("should send");

process_core(&mut core_handle, &core).await;
}
State::Running => {
let msg = core_handle.recv().await;

if let Some(msg) = msg {
match msg {
UICoreMsg::SendLightning(invoice) => {
log::info!("Got UICoreMsg::Send");
core.msg(CoreUIMsg::Sending).await;
if let Err(e) = core.send_lightning(invoice).await {
error!("Error sending: {e}");
core.msg(CoreUIMsg::SendFailure(e.to_string())).await;
}
}
UICoreMsg::ReceiveLightning(amount) => {
core.msg(CoreUIMsg::ReceiveGenerating).await;
match core.receive_lightning(amount).await {
Err(e) => {
core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await;
}
Ok(invoice) => {
core.msg(CoreUIMsg::ReceiveInvoiceGenerated(invoice))
.await;
}
}
}
UICoreMsg::SendOnChain {
address,
amount_sats,
} => {
log::info!("Got UICoreMsg::SendOnChain");
core.msg(CoreUIMsg::Sending).await;
if let Err(e) = core.send_onchain(address, amount_sats).await {
error!("Error sending: {e}");
core.msg(CoreUIMsg::SendFailure(e.to_string())).await;
}
}
UICoreMsg::ReceiveOnChain => {
core.msg(CoreUIMsg::ReceiveGenerating).await;
match core.receive_onchain().await {
Err(e) => {
core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await;
}
Ok(address) => {
core.msg(CoreUIMsg::ReceiveAddressGenerated(address))
.await;
}
}
}
UICoreMsg::AddFederation(invite_code) => {
if let Err(e) = core.add_federation(invite_code).await {
error!("Error adding federation: {e}");
core.msg(CoreUIMsg::AddFederationFailed(e.to_string()))
.await;
} else {
core.msg(CoreUIMsg::AddFederationSuccess).await;
}
}
// TODO: actually use this to unlock
UICoreMsg::Unlock(_password) => {
core.msg(CoreUIMsg::Unlocking).await;
// if let Err(e) = core.unlock(password).await {
// error!("Error unlocking: {e}");
// core.msg(CoreUIMsg::UnlockFailed(e.to_string())).await;
// }
core.msg(CoreUIMsg::UnlockSuccess).await;
}
}
}
_ => {
warn!("Ignoring unrelated message to locked core")
}
}
}
},
)
}

async fn process_core(core_handle: &mut bridge::CoreHandle, core: &HarborCore) {
// Initialize the ui's state
core.set_balance().await;

loop {
let msg = core_handle.recv().await;

if let Some(msg) = msg {
match msg {
UICoreMsg::SendLightning(invoice) => {
log::info!("Got UICoreMsg::Send");
core.msg(CoreUIMsg::Sending).await;
if let Err(e) = core.send_lightning(invoice).await {
error!("Error sending: {e}");
core.msg(CoreUIMsg::SendFailure(e.to_string())).await;
}
}
UICoreMsg::ReceiveLightning(amount) => {
core.msg(CoreUIMsg::ReceiveGenerating).await;
match core.receive_lightning(amount).await {
Err(e) => {
core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await;
}
Ok(invoice) => {
core.msg(CoreUIMsg::ReceiveInvoiceGenerated(invoice)).await;
}
}
}
UICoreMsg::SendOnChain {
address,
amount_sats,
} => {
log::info!("Got UICoreMsg::SendOnChain");
core.msg(CoreUIMsg::Sending).await;
if let Err(e) = core.send_onchain(address, amount_sats).await {
error!("Error sending: {e}");
core.msg(CoreUIMsg::SendFailure(e.to_string())).await;
}
}
UICoreMsg::ReceiveOnChain => {
core.msg(CoreUIMsg::ReceiveGenerating).await;
match core.receive_onchain().await {
Err(e) => {
core.msg(CoreUIMsg::ReceiveFailed(e.to_string())).await;
}
Ok(address) => {
core.msg(CoreUIMsg::ReceiveAddressGenerated(address)).await;
}
}
}
UICoreMsg::AddFederation(invite_code) => {
if let Err(e) = core.add_federation(invite_code).await {
error!("Error adding federation: {e}");
core.msg(CoreUIMsg::AddFederationFailed(e.to_string()))
.await;
} else {
core.msg(CoreUIMsg::AddFederationSuccess).await;
}
}
UICoreMsg::Unlock(_password) => {
unreachable!("should already be unlocked")
}
}
}
}
}

#[cfg(test)]
mod tests {
#[tokio::test]
Expand Down
11 changes: 7 additions & 4 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ use std::{sync::Arc, time::Duration};

pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();

pub(crate) fn setup_db(url: &str, password: String) -> Arc<dyn DBConnection + Send + Sync> {
pub(crate) fn setup_db(
url: &str,
password: String,
) -> anyhow::Result<Arc<dyn DBConnection + Send + Sync>> {
let manager = ConnectionManager::<SqliteConnection>::new(url);
let pool = Pool::builder()
.max_size(50)
.connection_timeout(Duration::from_secs(5))
.connection_customizer(Box::new(ConnectionOptions {
key: password,
enable_wal: true,
enable_foreign_keys: true,
busy_timeout: Some(Duration::from_secs(15)),
}))
.test_on_check_out(true)
.build(manager)
.expect("Unable to build DB connection pool");
Arc::new(SQLConnection { db: pool })
.build(manager)?;
Ok(Arc::new(SQLConnection { db: pool }))
}

pub trait DBConnection {
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ enum UnlockStatus {
#[derive(Debug, Clone)]
pub enum Message {
// Setup
CoreLoaded(Arc<bridge::UIHandle>),
UIHandlerLoaded(Arc<bridge::UIHandle>),
// Local state changes
Navigate(Route),
TransferAmountChanged(String),
Expand Down Expand Up @@ -210,7 +210,7 @@ impl HarborWallet {
fn update(&mut self, message: Message) -> Command<Message> {
match message {
// Setup
Message::CoreLoaded(ui_handle) => {
Message::UIHandlerLoaded(ui_handle) => {
self.ui_handle = Some(ui_handle);
println!("Core loaded");

Expand Down
Loading

0 comments on commit 5050492

Please sign in to comment.