Skip to content

Commit

Permalink
Store unblinding data for the tx
Browse files Browse the repository at this point in the history
  • Loading branch information
dangeross committed Dec 23, 2024
1 parent 34bc791 commit 54ef27d
Show file tree
Hide file tree
Showing 18 changed files with 115 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ typedef struct wire_cst_payment_details {
typedef struct wire_cst_payment {
struct wire_cst_list_prim_u_8_strict *destination;
struct wire_cst_list_prim_u_8_strict *tx_id;
struct wire_cst_list_prim_u_8_strict *unblinding_data;
uint32_t timestamp;
uint64_t amount_sat;
uint64_t fees_sat;
Expand Down
1 change: 1 addition & 0 deletions lib/bindings/src/breez_sdk_liquid.udl
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ dictionary Payment {
u64? swapper_fees_sat = null;
string? destination = null;
string? tx_id = null;
string? unblinding_data = null;
};

enum PaymentType {
Expand Down
2 changes: 2 additions & 0 deletions lib/core/src/chain_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ impl ChainSwapHandler {
fees_sat: lockup_tx_fees_sat + swap.claim_fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
unblinding_data: None,
}, None, false)?;

self.update_swap_info(&ChainSwapUpdate {
Expand Down Expand Up @@ -817,6 +818,7 @@ impl ChainSwapHandler {
fees_sat: 0,
payment_type: PaymentType::Receive,
is_confirmed: false,
unblinding_data: None,
},
None,
false,
Expand Down
7 changes: 7 additions & 0 deletions lib/core/src/frb_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,7 @@ impl SseDecode for crate::model::Payment {
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut var_destination = <Option<String>>::sse_decode(deserializer);
let mut var_txId = <Option<String>>::sse_decode(deserializer);
let mut var_unblindingData = <Option<String>>::sse_decode(deserializer);
let mut var_timestamp = <u32>::sse_decode(deserializer);
let mut var_amountSat = <u64>::sse_decode(deserializer);
let mut var_feesSat = <u64>::sse_decode(deserializer);
Expand All @@ -3598,6 +3599,7 @@ impl SseDecode for crate::model::Payment {
return crate::model::Payment {
destination: var_destination,
tx_id: var_txId,
unblinding_data: var_unblindingData,
timestamp: var_timestamp,
amount_sat: var_amountSat,
fees_sat: var_feesSat,
Expand Down Expand Up @@ -5658,6 +5660,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::Payment {
[
self.destination.into_into_dart().into_dart(),
self.tx_id.into_into_dart().into_dart(),
self.unblinding_data.into_into_dart().into_dart(),
self.timestamp.into_into_dart().into_dart(),
self.amount_sat.into_into_dart().into_dart(),
self.fees_sat.into_into_dart().into_dart(),
Expand Down Expand Up @@ -7720,6 +7723,7 @@ impl SseEncode for crate::model::Payment {
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<Option<String>>::sse_encode(self.destination, serializer);
<Option<String>>::sse_encode(self.tx_id, serializer);
<Option<String>>::sse_encode(self.unblinding_data, serializer);
<u32>::sse_encode(self.timestamp, serializer);
<u64>::sse_encode(self.amount_sat, serializer);
<u64>::sse_encode(self.fees_sat, serializer);
Expand Down Expand Up @@ -9730,6 +9734,7 @@ mod io {
crate::model::Payment {
destination: self.destination.cst_decode(),
tx_id: self.tx_id.cst_decode(),
unblinding_data: self.unblinding_data.cst_decode(),
timestamp: self.timestamp.cst_decode(),
amount_sat: self.amount_sat.cst_decode(),
fees_sat: self.fees_sat.cst_decode(),
Expand Down Expand Up @@ -10978,6 +10983,7 @@ mod io {
Self {
destination: core::ptr::null_mut(),
tx_id: core::ptr::null_mut(),
unblinding_data: core::ptr::null_mut(),
timestamp: Default::default(),
amount_sat: Default::default(),
fees_sat: Default::default(),
Expand Down Expand Up @@ -13163,6 +13169,7 @@ mod io {
pub struct wire_cst_payment {
destination: *mut wire_cst_list_prim_u_8_strict,
tx_id: *mut wire_cst_list_prim_u_8_strict,
unblinding_data: *mut wire_cst_list_prim_u_8_strict,
timestamp: u32,
amount_sat: u64,
fees_sat: u64,
Expand Down
10 changes: 10 additions & 0 deletions lib/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,10 @@ pub struct PaymentTxData {

/// Onchain tx status
pub is_confirmed: bool,

/// Data to use in the `blinded` param when unblinding the transaction in an explorer.
/// See: https://docs.liquid.net/docs/unblinding-transactions
pub unblinding_data: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
Expand Down Expand Up @@ -1344,6 +1348,10 @@ pub struct Payment {

pub tx_id: Option<String>,

/// Data to use in the `blinded` param when unblinding the transaction in an explorer.
/// See: https://docs.liquid.net/docs/unblinding-transactions
pub unblinding_data: Option<String>,

/// Composite timestamp that can be used for sorting or displaying the payment.
///
/// If this payment has an associated swap, it is the swap creation time. Otherwise, the point
Expand Down Expand Up @@ -1403,6 +1411,7 @@ impl Payment {
Payment {
destination: swap.bolt11.clone(),
tx_id: None,
unblinding_data: None,
timestamp: swap.created_at,
amount_sat,
fees_sat: swap.payer_amount_sat - swap.receiver_amount_sat,
Expand All @@ -1420,6 +1429,7 @@ impl Payment {
) -> Payment {
Payment {
tx_id: Some(tx.tx_id),
unblinding_data: tx.unblinding_data,
// When the swap is present and of type send and receive, we retrieve the destination from the invoice.
// If it's a chain swap instead, we use the `claim_address` field from the swap data (either pure Bitcoin or Liquid address).
// Otherwise, we specify the Liquid address (BIP21 or pure), set in `payment_details.address`.
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/persist/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,6 @@ pub(crate) fn current_migrations() -> Vec<&'static str> {
) STRICT;",
"ALTER TABLE receive_swaps DROP COLUMN mrh_script_pubkey;",
"ALTER TABLE payment_details ADD COLUMN lnurl_info_json TEXT;",
"ALTER TABLE payment_tx_data ADD COLUMN unblinding_data TEXT;",
]
}
93 changes: 52 additions & 41 deletions lib/core/src/persist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ impl Persister {
.iter()
.find(|output| output.is_some())
.and_then(|output| output.clone().map(|o| o.script_pubkey.to_hex()));
let unblinding_data = tx
.unblinded_url("")
.replace(&format!("tx/{}#blinded=", tx_id), "");
self.insert_or_update_payment(
PaymentTxData {
tx_id: tx_id.clone(),
Expand All @@ -121,6 +124,7 @@ impl Persister {
false => PaymentType::Send,
},
is_confirmed: is_tx_confirmed,
unblinding_data: Some(unblinding_data),
},
maybe_script_pubkey.map(|destination| PaymentTxDetails {
tx_id,
Expand All @@ -139,7 +143,8 @@ impl Persister {
amount_sat,
fees_sat,
payment_type,
is_confirmed
is_confirmed,
unblinding_data
FROM payment_tx_data
WHERE is_confirmed = 0",
)?;
Expand All @@ -152,6 +157,7 @@ impl Persister {
fees_sat: row.get(3)?,
payment_type: row.get(4)?,
is_confirmed: row.get(5)?,
unblinding_data: row.get(6)?,
})
})?
.map(|i| i.unwrap())
Expand All @@ -174,15 +180,17 @@ impl Persister {
amount_sat,
fees_sat,
payment_type,
is_confirmed
is_confirmed,
unblinding_data
)
VALUES (?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (tx_id)
DO UPDATE SET timestamp = CASE WHEN excluded.is_confirmed = 1 THEN excluded.timestamp ELSE timestamp END,
amount_sat = excluded.amount_sat,
fees_sat = excluded.fees_sat,
payment_type = excluded.payment_type,
is_confirmed = excluded.is_confirmed
is_confirmed = excluded.is_confirmed,
unblinding_data = excluded.unblinding_data
",
(
&ptx.tx_id,
Expand All @@ -191,6 +199,7 @@ impl Persister {
ptx.fees_sat,
ptx.payment_type,
ptx.is_confirmed,
ptx.unblinding_data,
),
)?;

Expand Down Expand Up @@ -344,6 +353,7 @@ impl Persister {
ptx.fees_sat,
ptx.payment_type,
ptx.is_confirmed,
ptx.unblinding_data,
rs.id,
rs.created_at,
rs.invoice,
Expand Down Expand Up @@ -428,57 +438,58 @@ impl Persister {
fees_sat: row.get(3)?,
payment_type: row.get(4)?,
is_confirmed: row.get(5)?,
unblinding_data: row.get(6)?,
}),
_ => None,
};

let maybe_receive_swap_id: Option<String> = row.get(6)?;
let maybe_receive_swap_created_at: Option<u32> = row.get(7)?;
let maybe_receive_swap_invoice: Option<String> = row.get(8)?;
let maybe_receive_swap_payment_hash: Option<String> = row.get(9)?;
let maybe_receive_swap_description: Option<String> = row.get(10)?;
let maybe_receive_swap_preimage: Option<String> = row.get(11)?;
let maybe_receive_swap_payer_amount_sat: Option<u64> = row.get(12)?;
let maybe_receive_swap_receiver_amount_sat: Option<u64> = row.get(13)?;
let maybe_receive_swap_receiver_state: Option<PaymentState> = row.get(14)?;
let maybe_receive_swap_pair_fees_json: Option<String> = row.get(15)?;
let maybe_receive_swap_id: Option<String> = row.get(7)?;
let maybe_receive_swap_created_at: Option<u32> = row.get(8)?;
let maybe_receive_swap_invoice: Option<String> = row.get(9)?;
let maybe_receive_swap_payment_hash: Option<String> = row.get(10)?;
let maybe_receive_swap_description: Option<String> = row.get(11)?;
let maybe_receive_swap_preimage: Option<String> = row.get(12)?;
let maybe_receive_swap_payer_amount_sat: Option<u64> = row.get(13)?;
let maybe_receive_swap_receiver_amount_sat: Option<u64> = row.get(14)?;
let maybe_receive_swap_receiver_state: Option<PaymentState> = row.get(15)?;
let maybe_receive_swap_pair_fees_json: Option<String> = row.get(16)?;
let maybe_receive_swap_pair_fees: Option<ReversePair> =
maybe_receive_swap_pair_fees_json.and_then(|pair| serde_json::from_str(&pair).ok());

let maybe_send_swap_id: Option<String> = row.get(16)?;
let maybe_send_swap_created_at: Option<u32> = row.get(17)?;
let maybe_send_swap_invoice: Option<String> = row.get(18)?;
let maybe_send_swap_bolt12_offer: Option<String> = row.get(19)?;
let maybe_send_swap_payment_hash: Option<String> = row.get(20)?;
let maybe_send_swap_description: Option<String> = row.get(21)?;
let maybe_send_swap_preimage: Option<String> = row.get(22)?;
let maybe_send_swap_refund_tx_id: Option<String> = row.get(23)?;
let maybe_send_swap_payer_amount_sat: Option<u64> = row.get(24)?;
let maybe_send_swap_receiver_amount_sat: Option<u64> = row.get(25)?;
let maybe_send_swap_state: Option<PaymentState> = row.get(26)?;
let maybe_send_swap_pair_fees_json: Option<String> = row.get(27)?;
let maybe_send_swap_id: Option<String> = row.get(17)?;
let maybe_send_swap_created_at: Option<u32> = row.get(18)?;
let maybe_send_swap_invoice: Option<String> = row.get(19)?;
let maybe_send_swap_bolt12_offer: Option<String> = row.get(20)?;
let maybe_send_swap_payment_hash: Option<String> = row.get(21)?;
let maybe_send_swap_description: Option<String> = row.get(22)?;
let maybe_send_swap_preimage: Option<String> = row.get(23)?;
let maybe_send_swap_refund_tx_id: Option<String> = row.get(24)?;
let maybe_send_swap_payer_amount_sat: Option<u64> = row.get(25)?;
let maybe_send_swap_receiver_amount_sat: Option<u64> = row.get(26)?;
let maybe_send_swap_state: Option<PaymentState> = row.get(27)?;
let maybe_send_swap_pair_fees_json: Option<String> = row.get(28)?;
let maybe_send_swap_pair_fees: Option<SubmarinePair> =
maybe_send_swap_pair_fees_json.and_then(|pair| serde_json::from_str(&pair).ok());

let maybe_chain_swap_id: Option<String> = row.get(28)?;
let maybe_chain_swap_created_at: Option<u32> = row.get(29)?;
let maybe_chain_swap_direction: Option<Direction> = row.get(30)?;
let maybe_chain_swap_preimage: Option<String> = row.get(31)?;
let maybe_chain_swap_description: Option<String> = row.get(32)?;
let maybe_chain_swap_refund_tx_id: Option<String> = row.get(33)?;
let maybe_chain_swap_payer_amount_sat: Option<u64> = row.get(34)?;
let maybe_chain_swap_receiver_amount_sat: Option<u64> = row.get(35)?;
let maybe_chain_swap_claim_address: Option<String> = row.get(36)?;
let maybe_chain_swap_state: Option<PaymentState> = row.get(37)?;
let maybe_chain_swap_pair_fees_json: Option<String> = row.get(38)?;
let maybe_chain_swap_id: Option<String> = row.get(29)?;
let maybe_chain_swap_created_at: Option<u32> = row.get(30)?;
let maybe_chain_swap_direction: Option<Direction> = row.get(31)?;
let maybe_chain_swap_preimage: Option<String> = row.get(32)?;
let maybe_chain_swap_description: Option<String> = row.get(33)?;
let maybe_chain_swap_refund_tx_id: Option<String> = row.get(34)?;
let maybe_chain_swap_payer_amount_sat: Option<u64> = row.get(35)?;
let maybe_chain_swap_receiver_amount_sat: Option<u64> = row.get(36)?;
let maybe_chain_swap_claim_address: Option<String> = row.get(37)?;
let maybe_chain_swap_state: Option<PaymentState> = row.get(38)?;
let maybe_chain_swap_pair_fees_json: Option<String> = row.get(39)?;
let maybe_chain_swap_pair_fees: Option<ChainPair> =
maybe_chain_swap_pair_fees_json.and_then(|pair| serde_json::from_str(&pair).ok());

let maybe_swap_refund_tx_amount_sat: Option<u64> = row.get(39)?;
let maybe_swap_refund_tx_amount_sat: Option<u64> = row.get(40)?;

let maybe_payment_details_destination: Option<String> = row.get(40)?;
let maybe_payment_details_description: Option<String> = row.get(41)?;
let maybe_payment_details_lnurl_info_json: Option<String> = row.get(42)?;
let maybe_payment_details_destination: Option<String> = row.get(41)?;
let maybe_payment_details_description: Option<String> = row.get(42)?;
let maybe_payment_details_lnurl_info_json: Option<String> = row.get(43)?;
let maybe_payment_details_lnurl_info: Option<LnUrlInfo> =
maybe_payment_details_lnurl_info_json.and_then(|info| serde_json::from_str(&info).ok());

Expand Down
1 change: 1 addition & 0 deletions lib/core/src/receive_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ impl ReceiveSwapHandler {
fees_sat: 0,
payment_type: PaymentType::Receive,
is_confirmed: false,
unblinding_data: None,
},
None,
false,
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ impl LiquidSdk {
fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
unblinding_data: None,
};

let description = address_data.message;
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/send_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ impl SendSwapHandler {
fees_sat: lockup_tx_fees_sat,
payment_type: PaymentType::Send,
is_confirmed: false,
unblinding_data: None,
},
None,
false,
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/test_utils/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,6 @@ pub(crate) fn new_payment_tx_data(payment_type: PaymentType) -> PaymentTxData {
fees_sat: 0,
payment_type,
is_confirmed: false,
unblinding_data: None,
}
}
20 changes: 12 additions & 8 deletions packages/dart/lib/src/frb_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2553,17 +2553,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
Payment dco_decode_payment(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 9) throw Exception('unexpected arr length: expect 9 but see ${arr.length}');
if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}');
return Payment(
destination: dco_decode_opt_String(arr[0]),
txId: dco_decode_opt_String(arr[1]),
timestamp: dco_decode_u_32(arr[2]),
amountSat: dco_decode_u_64(arr[3]),
feesSat: dco_decode_u_64(arr[4]),
swapperFeesSat: dco_decode_opt_box_autoadd_u_64(arr[5]),
paymentType: dco_decode_payment_type(arr[6]),
status: dco_decode_payment_state(arr[7]),
details: dco_decode_payment_details(arr[8]),
unblindingData: dco_decode_opt_String(arr[2]),
timestamp: dco_decode_u_32(arr[3]),
amountSat: dco_decode_u_64(arr[4]),
feesSat: dco_decode_u_64(arr[5]),
swapperFeesSat: dco_decode_opt_box_autoadd_u_64(arr[6]),
paymentType: dco_decode_payment_type(arr[7]),
status: dco_decode_payment_state(arr[8]),
details: dco_decode_payment_details(arr[9]),
);
}

Expand Down Expand Up @@ -4648,6 +4649,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
// Codec=Sse (Serialization based), see doc to use other codecs
var var_destination = sse_decode_opt_String(deserializer);
var var_txId = sse_decode_opt_String(deserializer);
var var_unblindingData = sse_decode_opt_String(deserializer);
var var_timestamp = sse_decode_u_32(deserializer);
var var_amountSat = sse_decode_u_64(deserializer);
var var_feesSat = sse_decode_u_64(deserializer);
Expand All @@ -4658,6 +4660,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return Payment(
destination: var_destination,
txId: var_txId,
unblindingData: var_unblindingData,
timestamp: var_timestamp,
amountSat: var_amountSat,
feesSat: var_feesSat,
Expand Down Expand Up @@ -6617,6 +6620,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_opt_String(self.destination, serializer);
sse_encode_opt_String(self.txId, serializer);
sse_encode_opt_String(self.unblindingData, serializer);
sse_encode_u_32(self.timestamp, serializer);
sse_encode_u_64(self.amountSat, serializer);
sse_encode_u_64(self.feesSat, serializer);
Expand Down
Loading

0 comments on commit 54ef27d

Please sign in to comment.