Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Real-time Sync: Add pull and merge #556

Merged
merged 8 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 110 additions & 6 deletions lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions lib/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ x509-parser = { version = "0.16.0" }
tempfile = "3"
tonic = { version = "0.12.3", features = ["tls"] }
prost = "0.13.3"
uuid = { version = "1.8.0", features = ["v4"] }
ecies = "0.2.7"
semver = "1.0.23"
lazy_static = "1.5.0"

[dev-dependencies]
lazy_static = "1.5.0"
paste = "1.0.15"
tempdir = "0.3.7"
uuid = { version = "1.8.0", features = ["v4"] }
Expand Down
8 changes: 7 additions & 1 deletion lib/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ pub trait Signer: Send + Sync {
/// HMAC-SHA256 using the private key derived from the given derivation path
/// This is used to calculate the linking key of lnurl-auth specification: https://github.com/lnurl/luds/blob/luds/05.md
fn hmac_sha256(&self, msg: Vec<u8>, derivation_path: String) -> Result<Vec<u8>, SignerError>;

/// Encrypts a message using (ECIES)[ecies::encrypt]
fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;

/// Decrypts a message using (ECIES)[ecies::decrypt]
fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;
}

/// An argument when calling [crate::sdk::LiquidSdk::connect].
Expand Down Expand Up @@ -592,7 +598,7 @@ impl SwapScriptV2 {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Serialize)]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum Direction {
Incoming = 0,
Outgoing = 1,
Expand Down
8 changes: 6 additions & 2 deletions lib/core/src/persist/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ use std::collections::HashMap;
use anyhow::Result;
use rusqlite::{named_params, Connection, OptionalExtension, Row, Statement, TransactionBehavior};

use super::Persister;
use super::{PaymentState, Persister};
use crate::{
sync::model::{sync::Record, RecordType, SyncOutgoingChanges, SyncSettings, SyncState},
sync::model::{
data::{ChainSyncData, ReceiveSyncData, SendSyncData},
sync::Record,
RecordType, SyncOutgoingChanges, SyncSettings, SyncState,
},
utils,
};

Expand Down
21 changes: 20 additions & 1 deletion lib/core/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use boltz_client::PublicKey;
use lwk_common::Signer as LwkSigner;
use lwk_wollet::bitcoin::bip32::Xpriv;
use lwk_wollet::bitcoin::Network;
use lwk_wollet::elements_miniscript;
use lwk_wollet::elements_miniscript::{self, ToPublicKey as _};
use lwk_wollet::elements_miniscript::{
bitcoin::{self, bip32::DerivationPath},
elements::{
Expand Down Expand Up @@ -253,6 +253,25 @@ impl Signer for SdkSigner {
.as_byte_array()
.to_vec())
}

fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
let keypair = self.xprv.to_keypair(&self.secp);
let rc_pub = keypair.public_key().to_public_key().to_bytes();
Ok(
ecies::encrypt(&rc_pub, msg).map_err(|err| SignerError::Generic {
err: format!("Could not encrypt data: {err}"),
})?,
)
}

fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
let rc_prv = self.xprv.to_priv().to_bytes();
Ok(
ecies::decrypt(&rc_prv, msg).map_err(|err| SignerError::Generic {
err: format!("Could not decrypt data: {err}"),
})?,
)
}
}

#[cfg(test)]
Expand Down
59 changes: 59 additions & 0 deletions lib/core/src/sync/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use anyhow::{anyhow, Result};

use async_trait::async_trait;
use log::debug;
use tokio::sync::Mutex;

use super::model::sync::{
syncer_client::SyncerClient as ProtoSyncerClient, ListChangesReply, ListChangesRequest,
SetRecordReply, SetRecordRequest,
};

#[async_trait]
pub(crate) trait SyncerClient: Send + Sync {
async fn connect(&self, connect_url: String) -> Result<()>;
async fn push(&self, req: SetRecordRequest) -> Result<SetRecordReply>;
async fn pull(&self, req: ListChangesRequest) -> Result<ListChangesReply>;
async fn disconnect(&self) -> Result<()>;
}

pub(crate) struct BreezSyncerClient {
inner: Mutex<Option<ProtoSyncerClient<tonic::transport::Channel>>>,
}

impl BreezSyncerClient {
pub(crate) fn new() -> Self {
Self {
inner: Default::default(),
}
}
}

#[async_trait]
impl SyncerClient for BreezSyncerClient {
async fn connect(&self, connect_url: String) -> Result<()> {
let mut client = self.inner.lock().await;
*client = Some(ProtoSyncerClient::connect(connect_url.clone()).await?);
debug!("Successfully connected to {connect_url}");
Ok(())
}

async fn push(&self, req: SetRecordRequest) -> Result<SetRecordReply> {
let Some(mut client) = self.inner.lock().await.clone() else {
return Err(anyhow!("Cannot run `set_record`: client not connected"));
};
Ok(client.set_record(req).await?.into_inner())
}
async fn pull(&self, req: ListChangesRequest) -> Result<ListChangesReply> {
let Some(mut client) = self.inner.lock().await.clone() else {
return Err(anyhow!("Cannot run `list_changes`: client not connected"));
};
Ok(client.list_changes(req).await?.into_inner())
}

async fn disconnect(&self) -> Result<()> {
let mut client = self.inner.lock().await;
*client = None;
Ok(())
}
}
Loading
Loading