diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs index b80650835..aa6ff0f45 100644 --- a/lib/core/src/model.rs +++ b/lib/core/src/model.rs @@ -1597,3 +1597,16 @@ macro_rules! get_invoice_description { } }; } + +#[macro_export] +macro_rules! get_updated_fields { + ($($var:ident),* $(,)?) => {{ + let mut options = Vec::new(); + $( + if $var.is_some() { + options.push(stringify!($var).to_string()); + } + )* + options + }}; +} diff --git a/lib/core/src/persist/chain.rs b/lib/core/src/persist/chain.rs index 2425b9c42..84e073adf 100644 --- a/lib/core/src/persist/chain.rs +++ b/lib/core/src/persist/chain.rs @@ -2,22 +2,25 @@ use std::collections::HashMap; use anyhow::Result; use boltz_client::swaps::boltz::{ChainSwapDetails, CreateChainResponse}; -use rusqlite::{named_params, params, Connection, Row}; +use rusqlite::{named_params, params, Connection, Row, TransactionBehavior}; use sdk_common::bitcoin::hashes::{hex::ToHex, sha256, Hash}; use serde::{Deserialize, Serialize}; -use crate::ensure_sdk; use crate::error::PaymentError; use crate::model::*; use crate::persist::{get_where_clause_state_in, Persister}; +use crate::sync::model::RecordType; +use crate::{ensure_sdk, get_updated_fields}; impl Persister { pub(crate) fn insert_chain_swap(&self, chain_swap: &ChainSwap) -> Result<()> { - let con = self.get_connection()?; + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(TransactionBehavior::Immediate)?; // There is a limit of 16 param elements in a single tuple in rusqlite, // so we split up the insert into two statements. - let mut stmt = con.prepare( + let id_hash = sha256::Hash::hash(chain_swap.id.as_bytes()).to_hex(); + tx.execute( " INSERT INTO chain_swaps ( id, @@ -38,28 +41,27 @@ impl Persister { state ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + &chain_swap.id, + &id_hash, + &chain_swap.direction, + &chain_swap.claim_address, + &chain_swap.lockup_address, + &chain_swap.timeout_block_height, + &chain_swap.preimage, + &chain_swap.payer_amount_sat, + &chain_swap.receiver_amount_sat, + &chain_swap.accept_zero_conf, + &chain_swap.create_response_json, + &chain_swap.claim_private_key, + &chain_swap.refund_private_key, + &chain_swap.claim_fees_sat, + &chain_swap.created_at, + &chain_swap.state, + ), )?; - let id_hash = sha256::Hash::hash(chain_swap.id.as_bytes()).to_hex(); - _ = stmt.execute(( - &chain_swap.id, - &id_hash, - &chain_swap.direction, - &chain_swap.claim_address, - &chain_swap.lockup_address, - &chain_swap.timeout_block_height, - &chain_swap.preimage, - &chain_swap.payer_amount_sat, - &chain_swap.receiver_amount_sat, - &chain_swap.accept_zero_conf, - &chain_swap.create_response_json, - &chain_swap.claim_private_key, - &chain_swap.refund_private_key, - &chain_swap.claim_fees_sat, - &chain_swap.created_at, - &chain_swap.state, - ))?; - con.execute( + tx.execute( "UPDATE chain_swaps SET description = :description, @@ -79,6 +81,10 @@ impl Persister { }, )?; + Self::commit_new_outgoing(&tx, &chain_swap.id, RecordType::Chain)?; + + tx.commit()?; + Ok(()) } @@ -319,8 +325,10 @@ impl Persister { refund_tx_id: Option<&str>, ) -> Result<(), PaymentError> { // Do not overwrite server_lockup_tx_id, user_lockup_tx_id, claim_tx_id, refund_tx_id - let con: Connection = self.get_connection()?; - con.execute( + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(TransactionBehavior::Immediate)?; + + tx.execute( "UPDATE chain_swaps SET server_lockup_tx_id = @@ -360,6 +368,11 @@ impl Persister { }, )?; + let updated_fields = get_updated_fields!(server_lockup_tx_id); + Self::commit_updated_fields(&tx, swap_id, RecordType::Chain, updated_fields)?; + + tx.commit()?; + Ok(()) } } diff --git a/lib/core/src/persist/receive.rs b/lib/core/src/persist/receive.rs index 13a31f004..c8e444f24 100644 --- a/lib/core/src/persist/receive.rs +++ b/lib/core/src/persist/receive.rs @@ -2,20 +2,23 @@ use std::collections::HashMap; use anyhow::Result; use boltz_client::swaps::boltz::CreateReverseResponse; -use rusqlite::{named_params, params, Connection, Row}; +use rusqlite::{named_params, params, Connection, Row, TransactionBehavior}; use sdk_common::bitcoin::hashes::{hex::ToHex, sha256, Hash}; use serde::{Deserialize, Serialize}; -use crate::ensure_sdk; use crate::error::PaymentError; use crate::model::*; use crate::persist::{get_where_clause_state_in, Persister}; +use crate::sync::model::RecordType; +use crate::{ensure_sdk, get_updated_fields}; impl Persister { pub(crate) fn insert_receive_swap(&self, receive_swap: &ReceiveSwap) -> Result<()> { - let con = self.get_connection()?; + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(TransactionBehavior::Immediate)?; - let mut stmt = con.prepare( + let id_hash = sha256::Hash::hash(receive_swap.id.as_bytes()).to_hex(); + tx.execute( " INSERT INTO receive_swaps ( id, @@ -34,26 +37,25 @@ impl Persister { state ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + &receive_swap.id, + id_hash, + &receive_swap.preimage, + &receive_swap.create_response_json, + &receive_swap.claim_private_key, + &receive_swap.invoice, + &receive_swap.payment_hash, + &receive_swap.payer_amount_sat, + &receive_swap.receiver_amount_sat, + &receive_swap.created_at, + &receive_swap.claim_fees_sat, + &receive_swap.mrh_address, + &receive_swap.mrh_script_pubkey, + &receive_swap.state, + ), )?; - let id_hash = sha256::Hash::hash(receive_swap.id.as_bytes()).to_hex(); - _ = stmt.execute(( - &receive_swap.id, - id_hash, - &receive_swap.preimage, - &receive_swap.create_response_json, - &receive_swap.claim_private_key, - &receive_swap.invoice, - &receive_swap.payment_hash, - &receive_swap.payer_amount_sat, - &receive_swap.receiver_amount_sat, - &receive_swap.created_at, - &receive_swap.claim_fees_sat, - &receive_swap.mrh_address, - &receive_swap.mrh_script_pubkey, - &receive_swap.state, - ))?; - con.execute( + tx.execute( "UPDATE receive_swaps SET description = :description, @@ -69,6 +71,10 @@ impl Persister { }, )?; + Self::commit_new_outgoing(&tx, &receive_swap.id, RecordType::Receive)?; + + tx.commit()?; + Ok(()) } @@ -282,8 +288,10 @@ impl Persister { mrh_amount_sat: Option, ) -> Result<(), PaymentError> { // Do not overwrite claim_tx_id or lockup_tx_id - let con: Connection = self.get_connection()?; - con.execute( + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate)?; + + tx.execute( "UPDATE receive_swaps SET claim_tx_id = @@ -316,6 +324,11 @@ impl Persister { }, )?; + let updated_fields = get_updated_fields!(mrh_tx_id, mrh_amount_sat); + Self::commit_updated_fields(&tx, swap_id, RecordType::Receive, updated_fields)?; + + tx.commit()?; + Ok(()) } } diff --git a/lib/core/src/persist/send.rs b/lib/core/src/persist/send.rs index f956d1714..a81e77e44 100644 --- a/lib/core/src/persist/send.rs +++ b/lib/core/src/persist/send.rs @@ -6,16 +6,19 @@ use rusqlite::{named_params, params, Connection, Row}; use sdk_common::bitcoin::hashes::{hex::ToHex, sha256, Hash}; use serde::{Deserialize, Serialize}; -use crate::ensure_sdk; use crate::error::PaymentError; use crate::model::*; use crate::persist::{get_where_clause_state_in, Persister}; +use crate::sync::model::RecordType; +use crate::{ensure_sdk, get_updated_fields}; impl Persister { pub(crate) fn insert_send_swap(&self, send_swap: &SendSwap) -> Result<()> { - let con = self.get_connection()?; + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate)?; - let mut stmt = con.prepare( + let id_hash = sha256::Hash::hash(send_swap.id.as_bytes()).to_hex(); + tx.execute( " INSERT INTO send_swaps ( id, @@ -33,23 +36,26 @@ impl Persister { state ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + &send_swap.id, + &id_hash, + &send_swap.invoice, + &send_swap.payment_hash, + &send_swap.description, + &send_swap.payer_amount_sat, + &send_swap.receiver_amount_sat, + &send_swap.create_response_json, + &send_swap.refund_private_key, + &send_swap.lockup_tx_id, + &send_swap.refund_tx_id, + &send_swap.created_at, + &send_swap.state, + ), )?; - let id_hash = sha256::Hash::hash(send_swap.id.as_bytes()).to_hex(); - _ = stmt.execute(( - &send_swap.id, - &id_hash, - &send_swap.invoice, - &send_swap.payment_hash, - &send_swap.description, - &send_swap.payer_amount_sat, - &send_swap.receiver_amount_sat, - &send_swap.create_response_json, - &send_swap.refund_private_key, - &send_swap.lockup_tx_id, - &send_swap.refund_tx_id, - &send_swap.created_at, - &send_swap.state, - ))?; + + Self::commit_new_outgoing(&tx, &send_swap.id, RecordType::Send)?; + + tx.commit()?; Ok(()) } @@ -203,8 +209,10 @@ impl Persister { refund_tx_id: Option<&str>, ) -> Result<(), PaymentError> { // Do not overwrite preimage, lockup_tx_id, refund_tx_id - let con: Connection = self.get_connection()?; - con.execute( + let mut con = self.get_connection()?; + let tx = con.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate)?; + + tx.execute( "UPDATE send_swaps SET preimage = @@ -237,6 +245,11 @@ impl Persister { }, )?; + let updated_fields = get_updated_fields!(preimage); + Self::commit_updated_fields(&tx, swap_id, RecordType::Send, updated_fields)?; + + tx.commit()?; + Ok(()) }