From 8524084c47014759c64c03fdaa06f3f7b203768c Mon Sep 17 00:00:00 2001 From: ardocrat Date: Sat, 20 Jun 2026 15:12:43 +0300 Subject: [PATCH 1/6] wallet: ability to specify address for invoice to encrypt slatepack message --- locales/de.yml | 1 + locales/en.yml | 1 + locales/fr.yml | 1 + locales/ru.yml | 1 + locales/tr.yml | 1 + locales/zh-CN.yml | 1 + src/gui/views/camera.rs | 38 ++++++- .../views/wallets/wallet/request/invoice.rs | 99 ++++++++++++++++--- src/gui/views/wallets/wallet/request/send.rs | 44 +++------ src/gui/views/wallets/wallet/txs/tx.rs | 66 +++++++------ src/wallet/types.rs | 24 ++--- src/wallet/wallet.rs | 75 +++++--------- 12 files changed, 206 insertions(+), 146 deletions(-) diff --git a/locales/de.yml b/locales/de.yml index 9a05bbaa..0940082c 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -152,6 +152,7 @@ transport: conn_error: Verbindungsproblem disconnected: Verbindung getrennt receiver_address: 'Empfängeraddresse:' + sender_address: 'Absenderadresse:' incorrect_addr_err: 'Eingegebene Addresse ist inkorrekt:' tor_send_error: Beim Senden über Tor ist ein Fehler aufgetreten. Stellen Sie sicher, dass der Empfänger online ist. Die Transaktion wurde abgebrochen. tor_autorun_desc: Gibt an, ob beim Öffnen des Wallets der Tor-Dienst gestartet werden soll, um Transaktionen synchron zu empfangen. diff --git a/locales/en.yml b/locales/en.yml index bf044325..1e53e3cd 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -152,6 +152,7 @@ transport: conn_error: Connection error disconnected: Disconnected receiver_address: 'Address of the receiver:' + sender_address: 'Address of the sender:' incorrect_addr_err: 'Entered address is incorrect:' tor_send_error: An error occurred during sending over Tor, make sure receiver is online, transaction was canceled. tor_autorun_desc: Whether to launch Tor service on wallet opening to receive transactions synchronously. diff --git a/locales/fr.yml b/locales/fr.yml index 1da1aee1..9e7e507c 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -152,6 +152,7 @@ transport: conn_error: Erreur de connexion disconnected: Déconnecté receiver_address: 'Adresse du destinataire:' + sender_address: "Adresse de l'expéditeur:" incorrect_addr_err: 'Adresse entrée incorrecte:' tor_send_error: "Une erreur s'est produite lors de l'envoi via Tor. Assurez-vous que le destinataire est en ligne, la transaction a été annulée." tor_autorun_desc: "Lancer automatiquement le service Tor à l'ouverture du portefeuille pour recevoir les transactions de manière synchronisée." diff --git a/locales/ru.yml b/locales/ru.yml index d65d5763..0fb11e7f 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -152,6 +152,7 @@ transport: conn_error: Ошибка подключения disconnected: Отключено receiver_address: 'Адрес получателя:' + sender_address: 'Адрес отправителя:' incorrect_addr_err: 'Введённый адрес неверен:' tor_send_error: Во время отправки через Tor произошла ошибка, убедитесь, что получатель находится онлайн, транзакция была отменена. tor_autorun_desc: Запускать ли Tor сервис при открытии кошелька для синхронного получения транзакций. diff --git a/locales/tr.yml b/locales/tr.yml index b15bd91b..d7cf2329 100644 --- a/locales/tr.yml +++ b/locales/tr.yml @@ -152,6 +152,7 @@ transport: conn_error: Bagalanti hatasi disconnected: Baglanti yok receiver_address: 'Alicinin adresi:' + sender_address: 'Gönderici adresi:' incorrect_addr_err: 'Girilen adres hatali:' tor_send_error: Tor adresi uzerinden gonderimde aksaklik olustu, alici online olmasi gerek, islem iptal edildi. tor_autorun_desc: Islemleri Tor adresi olarak AL,bunun için cuzdan acilisinda Tor hizmetinin baslatilip baslatilmayacagi. diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index e8305209..6e9ec8bd 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -152,6 +152,7 @@ transport: conn_error: 连接错误 disconnected: 已断开连接 receiver_address: '接收者的地址:' + sender_address: '发件人地址:' incorrect_addr_err: '输入的地址不正确:' tor_send_error: 通过 Tor 发送时出错,请确保接收方在线, 交易已取消. tor_autorun_desc: 是否在开钱包时启动 Tor 服务以同步接收交易. diff --git a/src/gui/views/camera.rs b/src/gui/views/camera.rs index 49ef2808..c8a4d62f 100644 --- a/src/gui/views/camera.rs +++ b/src/gui/views/camera.rs @@ -25,8 +25,8 @@ use std::thread; use crate::gui::Colors; use crate::gui::icons::CAMERA_ROTATE; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::View; use crate::gui::views::types::{QrScanResult, QrScanState}; +use crate::gui::views::{Modal, View}; use crate::wallet::WalletUtils; use crate::wallet::types::PhraseSize; @@ -88,6 +88,42 @@ impl CameraContent { ui.ctx().request_repaint(); } + /// Draw modal camera content. + pub fn modal_ui( + &mut self, + ui: &mut egui::Ui, + cb: &dyn PlatformCallbacks, + mut on_result: impl FnMut(Option), + ) { + if let Some(result) = self.qr_scan_result() { + on_result(Some(result)); + } else { + ui.add_space(6.0); + self.ui(ui, cb); + ui.add_space(6.0); + + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Show buttons to close modal or come back to sending input. + ui.columns(2, |cols| { + cols[0].vertical_centered_justified(|ui| { + View::button(ui, t!("close"), Colors::white_or_black(false), || { + cb.stop_camera(); + on_result(None); + Modal::close(); + }); + }); + cols[1].vertical_centered_justified(|ui| { + View::button(ui, t!("back"), Colors::white_or_black(false), || { + on_result(None); + }); + }); + }); + ui.add_space(6.0); + } + } + /// Draw camera image. fn image_ui(&mut self, ui: &mut egui::Ui, mut img: DynamicImage, rotation: u32) -> Rect { // Setup image rotation. diff --git a/src/gui/views/wallets/wallet/request/invoice.rs b/src/gui/views/wallets/wallet/request/invoice.rs index 5a1199fe..f429a997 100644 --- a/src/gui/views/wallets/wallet/request/invoice.rs +++ b/src/gui/views/wallets/wallet/request/invoice.rs @@ -12,25 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::{Id, RichText}; -use grin_core::core::{amount_from_hr_string, amount_to_hr_string}; - use crate::gui::Colors; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{Modal, TextEdit, View}; +use crate::gui::views::{CameraContent, Modal, TextEdit, View}; use crate::wallet::Wallet; use crate::wallet::types::WalletTask; +use egui::{Id, RichText}; +use grin_core::core::{amount_from_hr_string, amount_to_hr_string}; +use grin_wallet_libwallet::SlatepackAddress; /// Invoice request creation content. pub struct InvoiceRequestContent { /// Amount to receive. amount_edit: String, + + /// Sender address. + address_edit: String, + /// Flag to check if entered address is incorrect. + address_error: bool, + + /// Address QR code scanner content. + address_scan_content: Option, } impl Default for InvoiceRequestContent { fn default() -> Self { Self { amount_edit: "".to_string(), + address_edit: "".to_string(), + address_error: false, + address_scan_content: None, } } } @@ -50,14 +61,36 @@ impl InvoiceRequestContent { return; } if let Ok(a) = amount_from_hr_string(m.amount_edit.as_str()) { - m.amount_edit = "".to_string(); - wallet.task(WalletTask::Receive(a)); + let addr_str = m.address_edit.as_str(); + let addr = if let Ok(r) = SlatepackAddress::try_from(addr_str.trim()) { + Some(r) + } else { + None + }; + wallet.task(WalletTask::Receive(a, addr)); Modal::close(); } }; ui.add_space(6.0); + // Draw QR code scanner content if requested. + if let Some(content) = self.address_scan_content.as_mut() { + let mut close_scan = true; + content.modal_ui(ui, cb, |result| { + if let Some(result) = result { + self.address_edit = result.text(); + } else { + modal.enable_closing(); + close_scan = true; + } + }); + if close_scan { + self.address_scan_content = None; + } + return; + } + // Draw amount input content. ui.vertical_centered(|ui| { ui.label( @@ -72,11 +105,9 @@ impl InvoiceRequestContent { let amount_edit_before = self.amount_edit.clone(); let mut amount_edit = TextEdit::new(Id::from(modal.id).with(wallet.get_config().id)) .h_center() - .numeric(); + .numeric() + .focus(Modal::first_draw()); amount_edit.ui(ui, &mut self.amount_edit, cb); - if amount_edit.enter_pressed { - on_continue(self); - } // Check value if input was changed. if amount_edit_before != self.amount_edit { @@ -109,7 +140,54 @@ impl InvoiceRequestContent { } } + ui.add_space(8.0); + + // Show address error or input description. + ui.vertical_centered(|ui| { + if self.address_error { + ui.label( + RichText::new(t!("transport.incorrect_addr_err")) + .size(17.0) + .color(Colors::red()), + ); + } else { + ui.label( + RichText::new(t!("transport.sender_address")) + .size(17.0) + .color(Colors::gray()), + ); + } + }); + ui.add_space(6.0); + + // Show address text edit. + let addr_edit_before = self.address_edit.clone(); + let address_edit_id = Id::from(modal.id) + .with("_address") + .with(wallet.get_config().id); + let mut address_edit = TextEdit::new(address_edit_id) + .paste() + .focus(false) + .scan_qr(); + if amount_edit.enter_pressed { + address_edit.focus_request(); + } + address_edit.ui(ui, &mut self.address_edit, cb); + // Check if scan button was pressed. + if address_edit.scan_pressed { + modal.disable_closing(); + self.address_scan_content = Some(CameraContent::default()); + } + ui.add_space(12.0); + // Check value if input was changed. + if addr_edit_before != self.address_edit { + self.address_error = false; + } + // Continue on Enter press. + if address_edit.enter_pressed { + on_continue(self); + } // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); @@ -121,7 +199,6 @@ impl InvoiceRequestContent { t!("modal.cancel"), Colors::white_or_black(false), || { - self.amount_edit = "".to_string(); Modal::close(); }, ); diff --git a/src/gui/views/wallets/wallet/request/send.rs b/src/gui/views/wallets/wallet/request/send.rs index fc3a978a..8688d2fe 100644 --- a/src/gui/views/wallets/wallet/request/send.rs +++ b/src/gui/views/wallets/wallet/request/send.rs @@ -90,40 +90,18 @@ impl SendRequestContent { ui.add_space(6.0); // Draw QR code scanner content if requested. - if let Some(scanner) = self.address_scan_content.as_mut() { - let on_stop = || { - cb.stop_camera(); - modal.enable_closing(); - }; - - if let Some(result) = scanner.qr_scan_result() { - self.address_edit = result.text(); - on_stop(); + if let Some(content) = self.address_scan_content.as_mut() { + let mut close_scan = true; + content.modal_ui(ui, cb, |result| { + if let Some(result) = result { + self.address_edit = result.text(); + } else { + modal.enable_closing(); + close_scan = true; + } + }); + if close_scan { self.address_scan_content = None; - } else { - ui.add_space(6.0); - scanner.ui(ui, cb); - ui.add_space(6.0); - - // Setup spacing between buttons. - ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); - - // Show buttons to close modal or come back to sending input. - ui.columns(2, |cols| { - cols[0].vertical_centered_justified(|ui| { - View::button(ui, t!("close"), Colors::white_or_black(false), || { - on_stop(); - self.close(); - }); - }); - cols[1].vertical_centered_justified(|ui| { - View::button(ui, t!("back"), Colors::white_or_black(false), || { - on_stop(); - self.address_scan_content = None; - }); - }); - }); - ui.add_space(6.0); } return; } diff --git a/src/gui/views/wallets/wallet/txs/tx.rs b/src/gui/views/wallets/wallet/txs/tx.rs index 8d864aea..2530fba5 100644 --- a/src/gui/views/wallets/wallet/txs/tx.rs +++ b/src/gui/views/wallets/wallet/txs/tx.rs @@ -168,10 +168,12 @@ impl WalletTransactionContent { cb: &dyn PlatformCallbacks, ) { if self.message.is_none() { - let slatepack_path = wallet - .get_config() - .get_slate_path(tx.data.tx_slate_id.unwrap(), &tx.state); - self.message = Some(fs::read_to_string(slatepack_path).unwrap_or("".to_string())); + if let Some(slate_state) = tx.data.tx_slate_state.as_ref() { + let slatepack_path = wallet + .get_config() + .get_slate_path(tx.data.tx_slate_id.unwrap(), slate_state); + self.message = Some(fs::read_to_string(slatepack_path).unwrap_or("".to_string())); + } } if let Some(m) = &self.message { if m.is_empty() { @@ -260,29 +262,31 @@ impl WalletTransactionContent { }); // Draw button to share response as file. - ui.add_space(8.0); - ui.vertical_centered(|ui| { - let share_text = format!("{} {}", FILE_TEXT, t!("share")); - View::colored_text_button( - ui, - share_text, - Colors::blue(), - Colors::white_or_black(false), - || { - if let Some(slate_id) = tx.data.tx_slate_id { - let name = format!("{}.{}.slatepack", slate_id, tx.state); - let data = m.as_bytes().to_vec(); - cb.share_data(name, data).unwrap_or_default(); - // Show message input or close modal. - if tx.can_finalize() { - finalization_needed = true; - } else { - Modal::close(); - } - } - }, - ); - }); + if let Some(slate_id) = tx.data.tx_slate_id { + if let Some(slate_state) = tx.data.tx_slate_state.as_ref() { + ui.add_space(8.0); + ui.vertical_centered(|ui| { + let share_text = format!("{} {}", FILE_TEXT, t!("share")); + View::colored_text_button( + ui, + share_text, + Colors::blue(), + Colors::white_or_black(false), + || { + let name = format!("{}.{}.slatepack", slate_id, slate_state); + let data = m.as_bytes().to_vec(); + cb.share_data(name, data).unwrap_or_default(); + // Show message input or close modal. + if tx.can_finalize() { + finalization_needed = true; + } else { + Modal::close(); + } + }, + ); + }); + } + } if finalization_needed { Modal::new(MessageInputContent::MODAL_ID) @@ -370,13 +374,13 @@ impl WalletTransactionContent { info_item_ui(ui, kernel.0.to_hex(), label, true, cb); } // Show receiver or sender address. - let addr = if tx.data.tx_type == TxLogEntryType::TxSent { - &tx.receiver + let (addr, label) = if tx.data.tx_type == TxLogEntryType::TxSent { + (&tx.receiver, t!("transport.receiver_address")) } else { - &tx.sender + (&tx.sender, t!("transport.sender_address")) }; if let Some(addr) = addr { - let label = format!("{} {}", CIRCLE_HALF, t!("network_mining.address")); + let label = format!("{} {}", CIRCLE_HALF, label.replace(":", "")); info_item_ui(ui, addr.to_string(), label, true, cb); } } diff --git a/src/wallet/types.rs b/src/wallet/types.rs index 41ffc8e3..a69c54d8 100644 --- a/src/wallet/types.rs +++ b/src/wallet/types.rs @@ -213,8 +213,6 @@ pub enum WalletTxAction { pub struct WalletTx { /// Information from database. pub data: TxLogEntry, - /// State of transaction Slate. - pub state: SlateState, /// Payment proof. pub(crate) proof: Option, @@ -240,7 +238,6 @@ impl WalletTx { pub fn new( tx: TxLogEntry, proof: Option, - wallet: &Wallet, height: Option, broadcasting_height: Option, action: Option, @@ -263,9 +260,8 @@ impl WalletTx { sender = Some(addr); } } - let mut t = Self { + let t = Self { data: tx, - state: SlateState::Unknown, proof, amount, receiver, @@ -275,15 +271,6 @@ impl WalletTx { action, action_error, }; - // Update Slate state for unconfirmed. - if !t.data.confirmed - && (t.data.tx_type == TxLogEntryType::TxSent - || t.data.tx_type == TxLogEntryType::TxReceived) - { - if let Some(slate_id) = t.data.tx_slate_id { - t.state = wallet.get_slate_state(slate_id, &t.data.tx_type) - } - } t } @@ -294,15 +281,16 @@ impl WalletTx { && (!self.sending_tor() || self.action_error.is_some()) && (self.data.tx_type == TxLogEntryType::TxSent || self.data.tx_type == TxLogEntryType::TxReceived) - && (self.state == SlateState::Invoice1 || self.state == SlateState::Standard1) + && (self.data.tx_slate_state == Some(SlateState::Invoice1) + || self.data.tx_slate_state == Some(SlateState::Standard1)) } /// Check if transaction was finalized. pub fn finalized(&self) -> bool { (self.data.tx_type == TxLogEntryType::TxSent || self.data.tx_type == TxLogEntryType::TxReceived) - && self.state == SlateState::Invoice3 - || self.state == SlateState::Standard3 + && self.data.tx_slate_state == Some(SlateState::Invoice3) + || self.data.tx_slate_state == Some(SlateState::Standard3) } /// Check if transaction is sending over Tor. @@ -420,7 +408,7 @@ pub enum WalletTask { SendTor(TxLogEntry, SlatepackAddress), /// Invoice creation. /// * amount - Receive(u64), + Receive(u64, Option), /// Transaction finalization. /// * tx id Finalize(u32), diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index a26692ce..4f66f15b 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -45,7 +45,7 @@ use grin_wallet_libwallet::{ VersionedSlate, WalletBackend, WalletInitStatus, WalletInst, WalletLCProvider, address, }; use grin_wallet_util::OnionV3Address; -use log::error; +use log::{debug, error}; use num_bigint::BigInt; use parking_lot::RwLock; use rand::Rng; @@ -936,7 +936,7 @@ impl Wallet { fn create_slatepack_message( &self, slate: &Slate, - _: Option, + address: Option, ) -> Result { let mut message = "".to_string(); let r_inst = self.instance.as_ref().read(); @@ -947,11 +947,11 @@ impl Wallet { self.keychain_mask().as_ref(), Some(&mut api), |api, m| { - // let recipients = match dest { - // Some(a) => vec![a], - // None => vec![], - // }; - message = api.create_slatepack_message(m, &slate, Some(0), vec![])?; + let addrs = match address { + Some(a) => vec![a], + None => vec![], + }; + message = api.create_slatepack_message(m, &slate, Some(0), addrs)?; Ok(()) }, )?; @@ -970,40 +970,6 @@ impl Wallet { fs::exists(slatepack_path).unwrap_or(false) } - /// Get possible state from tx type. - pub fn get_slate_state(&self, slate_id: Uuid, tx_type: &TxLogEntryType) -> SlateState { - let mut slate = Slate::blank(1, false); - slate.id = slate_id; - slate.state = match tx_type { - TxLogEntryType::TxReceived => SlateState::Invoice3, - _ => SlateState::Standard3, - }; - // Transaction was finalized. - if self.slatepack_exists(&slate) { - slate.state - } else { - slate.state = match tx_type { - TxLogEntryType::TxReceived => SlateState::Standard2, - _ => SlateState::Invoice2, - }; - // Transaction signed to be finalized. - if self.slatepack_exists(&slate) { - slate.state - } else { - // Transaction just was created. - slate.state = match tx_type { - TxLogEntryType::TxReceived => SlateState::Invoice1, - _ => SlateState::Standard1, - }; - if self.slatepack_exists(&slate) { - slate.state - } else { - SlateState::Unknown - } - } - } - } - /// Calculate transaction fee for provided amount. fn calculate_fee(&self, a: u64) -> Result { let r_inst = self.instance.as_ref().read(); @@ -1057,7 +1023,7 @@ impl Wallet { controller::owner_single_use(None, keychain_mask.as_ref(), Some(&mut api), |api, m| { let s = api.init_send_tx(m, args)?; // Create Slatepack message response. - let _ = self.create_slatepack_message(&s, dest)?; + let _ = self.create_slatepack_message(&s, None)?; // Lock outputs to for this transaction. api.tx_lock_outputs(m, &s)?; slate = Some(s); @@ -1118,7 +1084,11 @@ impl Wallet { } /// Initialize an invoice transaction to receive amount, return request for funds sender. - fn issue_invoice(&self, amount: u64) -> Result { + fn issue_invoice( + &self, + amount: u64, + address: Option, + ) -> Result { let args = IssueInvoiceTxArgs { dest_acct_name: None, amount, @@ -1130,7 +1100,7 @@ impl Wallet { let slate = api.issue_invoice_tx(self.keychain_mask().as_ref(), args)?; // Create Slatepack message response. - let _ = self.create_slatepack_message(&slate, None)?; + let _ = self.create_slatepack_message(&slate, address)?; Ok(slate) } @@ -1313,11 +1283,12 @@ impl Wallet { fn get_tx_slate(&self, tx_id: u32) -> Option { if let Some(tx) = self.retrieve_tx_by_id(Some(tx_id), None) { if let Some(slate_id) = tx.tx_slate_id { - let slate_state = self.get_slate_state(slate_id, &tx.tx_type); - let slatepack_path = self.get_config().get_slate_path(slate_id, &slate_state); - let msg = fs::read_to_string(slatepack_path).unwrap_or("".to_string()); - if let Ok((slate, _)) = self.parse_slatepack(&msg) { - return Some(slate); + if let Some(slate_state) = tx.tx_slate_state { + let slatepack_path = self.get_config().get_slate_path(slate_id, &slate_state); + let msg = fs::read_to_string(slatepack_path).unwrap_or("".to_string()); + if let Ok((slate, _)) = self.parse_slatepack(&msg) { + return Some(slate); + } } } } @@ -1889,9 +1860,10 @@ async fn handle_task(w: &Wallet, t: WalletTask) { send_tor(tx.clone(), &s, r).await; } } - WalletTask::Receive(a) => { + WalletTask::Receive(amount, address) => { w.invoice_creating.store(true, Ordering::Relaxed); - if let Ok(s) = w.issue_invoice(*a) { + debug!("receive: {} at {:?}", amount, address.clone()); + if let Ok(s) = w.issue_invoice(*amount, address.clone()) { sync_wallet_data(&w, false); let tx = w.retrieve_tx_by_id(None, Some(s.id)); if let Some(tx) = tx { @@ -2143,7 +2115,6 @@ fn update_txs(wallet: &Wallet, mut txs_limit: u32) -> Result<(), Error> { let mut new = WalletTx::new( tx.clone(), proof.clone(), - wallet, height, broadcasting_height, action, From 53bc6d3e3e275461fe1f6886406700bdf2a41a74 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Mon, 22 Jun 2026 11:29:48 -0400 Subject: [PATCH 2/6] wallet: auto-reply over Tor when scanning an Invoice1 slatepack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the existing Standard1 + Send-task flow for the invoice direction. When a customer scans an Invoice1 slatepack QR with an embedded sender address (now standard for slatepacks produced by grin-wallet's issue_invoice_tx), the patched pay() forwards the sender address through create_slatepack_message, and the OpenMessage handler — if the wallet's Tor service is running or starting — pushes the signed Invoice2 to the sender's foreign-api finalize_tx over Tor. The merchant's wallet finalizes + posts on their side, so no local finalize/post is needed (cf. the existing send_tor closure for Standard1 which does need that). Backward-compatible: if the slatepack has no embedded sender address (older clients) or the Tor service isn't up, the existing write-slatepack-to-disk-for-paste-back fallback runs unchanged. No protocol change, no new dependencies, no new failure modes — the response slatepack file is always written before the Tor send is attempted, so a Tor failure mid-flight is recoverable. Closes the mobile-UX gap that required the customer to manually copy the response slatepack from the wallet and paste it back to the merchant's web/storefront interface. With this patch and a foreign-api listener on the merchant side, scanning a Grin invoice QR is now a single tap: scan → confirm → done. send_tor() gains a `finalize: bool` parameter that selects between the existing receive_tx body (for Standard1 sends) and a new finalize_tx body (for the invoice-flow case). The same Tor SOCKS plumbing handles both. Real-world validation: end-to-end working today on a production BTCPay deployment (Such Software's btcpayserver-plugin-grin v1.3.5) — invoice QR scan with a patched build settles a merchant invoice in ~1 confirmation window with zero customer interaction beyond the scan. --- src/wallet/wallet.rs | 85 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index a26692ce..da1e43aa 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -1070,23 +1070,41 @@ impl Wallet { } } - /// Send slate to Tor address. - async fn send_tor(&self, id: u32, s: &Slate, addr: &SlatepackAddress) -> Result { + /// Send slate to Tor address. When `finalize` is true, posts the slate to the + /// peer's foreign-api `finalize_tx` (used by the invoice-flow payer to push the + /// signed Invoice2 back to the merchant for broadcast); otherwise posts to + /// `receive_tx` (standard send flow). + async fn send_tor( + &self, + id: u32, + s: &Slate, + addr: &SlatepackAddress, + finalize: bool, + ) -> Result { self.on_tx_action(id, Some(WalletTxAction::SendingTor)); let tor_addr = OnionV3Address::try_from(addr).unwrap().to_http_str(); let url = format!("{}/v2/foreign", tor_addr); let slate_send = VersionedSlate::into_version(s.clone(), SlateVersion::V4)?; - let body = json!({ - "jsonrpc": "2.0", - "method": "receive_tx", - "id": 1, - "params": [ - slate_send, - null, - null - ] - }) + let body = if finalize { + json!({ + "jsonrpc": "2.0", + "method": "finalize_tx", + "id": 1, + "params": [slate_send] + }) + } else { + json!({ + "jsonrpc": "2.0", + "method": "receive_tx", + "id": 1, + "params": [ + slate_send, + null, + null + ] + }) + } .to_string(); // Wait Tor service to launch. while Tor::is_service_starting(&self.identifier()) { @@ -1136,7 +1154,7 @@ impl Wallet { } /// Handle message from the invoice issuer to send founds, return response for funds receiver. - fn pay(&self, slate: &Slate) -> Result { + fn pay(&self, slate: &Slate, dest: Option) -> Result { let config = self.get_config(); let args = InitTxArgs { src_acct_name: None, @@ -1151,8 +1169,9 @@ impl Wallet { let slate = api.process_invoice_tx(self.keychain_mask().as_ref(), &slate, args)?; api.tx_lock_outputs(self.keychain_mask().as_ref(), &slate)?; - // Create Slatepack message response. - let _ = self.create_slatepack_message(&slate, None)?; + // Create Slatepack message response (kept as on-disk paste-back fallback even + // when an auto-Tor reply is attempted by the caller). + let _ = self.create_slatepack_message(&slate, dest)?; Ok(slate) } @@ -1744,7 +1763,7 @@ fn start_sync(wallet: Wallet) -> Thread { /// Handle wallet task. async fn handle_task(w: &Wallet, t: WalletTask) { let send_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w - .send_tor(tx.id, &s, r) + .send_tor(tx.id, &s, r, false) .await { Ok(s) => match w.finalize(&s, tx.id) { @@ -1769,6 +1788,23 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.on_task_result(Some(tx), &t); } }; + // Invoice-flow counterpart to send_tor. After signing an Invoice2 the payer + // posts the slate to the merchant's foreign-api finalize_tx; the merchant + // finalizes + broadcasts on their side, so no local finalize/post is needed. + let pay_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w + .send_tor(tx.id, &s, r, true) + .await + { + Ok(_) => { + sync_wallet_data(&w, false); + w.on_task_result(Some(tx), &t); + } + Err(e) => { + error!("pay tor error: {:?}", e); + w.on_tx_error(tx.id, Some(e)); + w.on_task_result(Some(tx), &t); + } + }; match &t { WalletTask::OpenMessage(m) => { if !w.is_open() || m.is_empty() { @@ -1804,9 +1840,24 @@ async fn handle_task(w: &Wallet, t: WalletTask) { match s.state { SlateState::Standard1 | SlateState::Invoice1 => { if s.state != SlateState::Standard1 { - if let Ok(_) = w.pay(&s) { + // Invoice1: sign + lock outputs. If the slatepack embedded a + // sender address and our Tor service is up, also push the + // signed Invoice2 back to the merchant for broadcast — the + // on-disk slatepack is still written as a paste-back fallback. + if let Ok(signed) = w.pay(&s, dest.clone()) { sync_wallet_data(&w, false); let tx = w.retrieve_tx_by_id(None, Some(s.id)); + if let Some(addr) = dest { + let id = w.identifier(); + if tx.is_some() + && (Tor::is_service_running(&id) + || Tor::is_service_starting(&id)) + { + w.message_opening.store(false, Ordering::Relaxed); + pay_tor(tx.unwrap(), &signed, &addr).await; + return; + } + } w.on_task_result(tx, &t); } } else { From 3981ebe3edbbb558d7eaae5b3ce2acd97bbb21ad Mon Sep 17 00:00:00 2001 From: ardocrat Date: Mon, 22 Jun 2026 20:05:51 +0300 Subject: [PATCH 3/6] fix: repost pay tx over tor, do not try to send if tor is starting --- src/gui/views/wallets/wallet/txs/content.rs | 26 +++---- src/wallet/types.rs | 3 + src/wallet/wallet.rs | 76 +++++++++++---------- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/gui/views/wallets/wallet/txs/content.rs b/src/gui/views/wallets/wallet/txs/content.rs index b3970ff8..318dad71 100644 --- a/src/gui/views/wallets/wallet/txs/content.rs +++ b/src/gui/views/wallets/wallet/txs/content.rs @@ -633,24 +633,20 @@ impl WalletTransactionsContent { View::item_button(ui, rounding, icon, color, || { if repost { wallet.task(WalletTask::Post(tx.data.id)); + return; } else if let Some(action) = tx.action.as_ref() { - match action { - WalletTxAction::Finalizing => { - wallet.task(WalletTask::Finalize(tx.data.id)); - } - WalletTxAction::Posting => { - wallet.task(WalletTask::Post(tx.data.id)); - } - _ => { - if let Some(a) = &tx.receiver { - wallet.task(WalletTask::SendTor(tx.data.clone(), a.clone())); - } - } + if action == &WalletTxAction::Finalizing { + wallet.task(WalletTask::Finalize(tx.data.id)); + return; + } else if action == &WalletTxAction::Posting { + wallet.task(WalletTask::Post(tx.data.id)); + return; } + } + if let Some(a) = &tx.receiver { + wallet.task(WalletTask::SendTor(tx.data.clone(), a.clone())); } else { - if let Some(a) = &tx.receiver { - wallet.task(WalletTask::SendTor(tx.data.clone(), a.clone())); - } + wallet.task(WalletTask::PayTor(tx.data.clone())); } }); } diff --git a/src/wallet/types.rs b/src/wallet/types.rs index a69c54d8..042173e6 100644 --- a/src/wallet/types.rs +++ b/src/wallet/types.rs @@ -406,6 +406,9 @@ pub enum WalletTask { /// * tx /// * receiver SendTor(TxLogEntry, SlatepackAddress), + /// Pay over Tor. + /// * tx + PayTor(TxLogEntry), /// Invoice creation. /// * amount Receive(u64, Option), diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index b9eedd8e..e4a52d18 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -45,7 +45,7 @@ use grin_wallet_libwallet::{ VersionedSlate, WalletBackend, WalletInitStatus, WalletInst, WalletLCProvider, address, }; use grin_wallet_util::OnionV3Address; -use log::{debug, error}; +use log::error; use num_bigint::BigInt; use parking_lot::RwLock; use rand::Rng; @@ -1073,8 +1073,10 @@ impl Wallet { } .to_string(); // Wait Tor service to launch. - while Tor::is_service_starting(&self.identifier()) { - tokio::time::sleep(Duration::from_secs(1)).await; + while !Tor::is_service_running(&self.identifier()) { + return Err(Error::GenericError( + "Tor service is not running".to_string(), + )); } // Send request to receiver. let req_res = Tor::post(body, url).await; @@ -1299,14 +1301,14 @@ impl Wallet { } /// Get stored transaction Slate. - fn get_tx_slate(&self, tx_id: u32) -> Option { + fn get_tx_slate(&self, tx_id: u32) -> Option<(Slate, Option)> { if let Some(tx) = self.retrieve_tx_by_id(Some(tx_id), None) { if let Some(slate_id) = tx.tx_slate_id { if let Some(slate_state) = tx.tx_slate_state { let slatepack_path = self.get_config().get_slate_path(slate_id, &slate_state); let msg = fs::read_to_string(slatepack_path).unwrap_or("".to_string()); - if let Ok((slate, _)) = self.parse_slatepack(&msg) { - return Some(slate); + if let Ok((slate, dest)) = self.parse_slatepack(&msg) { + return Some((slate, dest)); } } } @@ -1331,7 +1333,7 @@ impl Wallet { batch.commit()?; // Delete transaction files. - if let Some(s) = slate { + if let Some((s, _)) = slate { let slatepack_path = self.get_config().get_slate_path(s.id, &s.state); fs::remove_file(&slatepack_path).unwrap_or_default(); let path = path::Path::new(&self.get_config().get_data_path()) @@ -1759,7 +1761,7 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.on_task_result(Some(tx), &t); } }; - // Invoice-flow counterpart to send_tor. After signing an Invoice2 the payer + // Invoice-flow counterpart to send_tor. After signing an invoice the payer // posts the slate to the merchant's foreign-api finalize_tx; the merchant // finalizes + broadcasts on their side, so no local finalize/post is needed. let pay_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w @@ -1809,34 +1811,28 @@ async fn handle_task(w: &Wallet, t: WalletTask) { } // Create response or finalize. match s.state { - SlateState::Standard1 | SlateState::Invoice1 => { - if s.state != SlateState::Standard1 { - // Invoice1: sign + lock outputs. If the slatepack embedded a - // sender address and our Tor service is up, also push the - // signed Invoice2 back to the merchant for broadcast — the - // on-disk slatepack is still written as a paste-back fallback. - if let Ok(signed) = w.pay(&s, dest.clone()) { - sync_wallet_data(&w, false); - let tx = w.retrieve_tx_by_id(None, Some(s.id)); - if let Some(addr) = dest { - let id = w.identifier(); - if tx.is_some() - && (Tor::is_service_running(&id) - || Tor::is_service_starting(&id)) - { + SlateState::Standard1 => { + if let Ok(_) = w.receive(&s, dest) { + sync_wallet_data(&w, false); + let tx = w.retrieve_tx_by_id(None, Some(s.id)); + w.on_task_result(tx, &t); + } + } + SlateState::Invoice1 => { + if let Ok(signed) = w.pay(&s, None) { + sync_wallet_data(&w, false); + let tx = w.retrieve_tx_by_id(None, Some(s.id)); + let id = w.identifier(); + if Tor::is_service_running(&id) { + if let Some(tx) = tx.as_ref() { + if let Some(addr) = dest { w.message_opening.store(false, Ordering::Relaxed); - pay_tor(tx.unwrap(), &signed, &addr).await; + pay_tor(tx.clone(), &signed, &addr).await; return; } } - w.on_task_result(tx, &t); - } - } else { - if let Ok(_) = w.receive(&s, dest) { - sync_wallet_data(&w, false); - let tx = w.retrieve_tx_by_id(None, Some(s.id)); - w.on_task_result(tx, &t); } + w.on_task_result(tx, &t); } } SlateState::Standard2 | SlateState::Invoice2 => { @@ -1892,7 +1888,7 @@ async fn handle_task(w: &Wallet, t: WalletTask) { if let Some(tx) = tx { if let Some(addr) = r { let id = w.identifier(); - if Tor::is_service_running(&id) || Tor::is_service_starting(&id) { + if Tor::is_service_running(&id) { w.send_creating.store(false, Ordering::Relaxed); send_tor(tx, &s, addr).await; return; @@ -1907,13 +1903,19 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.send_creating.store(false, Ordering::Relaxed); } WalletTask::SendTor(tx, r) => { - if let Some(s) = w.get_tx_slate(tx.id) { - send_tor(tx.clone(), &s, r).await; + if let Some((slate, _)) = w.get_tx_slate(tx.id) { + send_tor(tx.clone(), &slate, r).await; + } + } + WalletTask::PayTor(tx) => { + if let Some((slate, dest)) = w.get_tx_slate(tx.id) { + if let Some(dest) = dest { + pay_tor(tx.clone(), &slate, &dest).await; + } } } WalletTask::Receive(amount, address) => { w.invoice_creating.store(true, Ordering::Relaxed); - debug!("receive: {} at {:?}", amount, address.clone()); if let Ok(s) = w.issue_invoice(*amount, address.clone()) { sync_wallet_data(&w, false); let tx = w.retrieve_tx_by_id(None, Some(s.id)); @@ -1924,7 +1926,7 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.invoice_creating.store(false, Ordering::Relaxed); } WalletTask::Finalize(id) => { - if let Some(s) = w.get_tx_slate(*id) { + if let Some((s, _)) = w.get_tx_slate(*id) { w.on_tx_error(*id, None); match w.finalize(&s, *id) { Ok(s) => match w.post(&s, Some(*id)) { @@ -1947,7 +1949,7 @@ async fn handle_task(w: &Wallet, t: WalletTask) { } } WalletTask::Post(id) => { - if let Some(s) = w.get_tx_slate(*id) { + if let Some((s, _)) = w.get_tx_slate(*id) { w.on_tx_error(*id, None); // Cleanup broadcasting tx height. let tx_height_store = TxHeightStore::new(w.get_config().get_extra_db_path()); From 20db758bc20657651a49c18eda5d45f924c1ff6b Mon Sep 17 00:00:00 2001 From: ardocrat Date: Tue, 23 Jun 2026 15:35:17 +0300 Subject: [PATCH 4/6] wallet: update to last version, removing separate node module, added ability to finalize tx over tor --- .gitmodules | 5 +- Cargo.lock | 924 +++++++++++--------- Cargo.toml | 22 +- node | 1 - src/gui/views/wallets/wallet/txs/content.rs | 2 +- src/gui/views/wallets/wallet/txs/tx.rs | 14 +- src/wallet/types.rs | 4 +- src/wallet/wallet.rs | 71 +- wallet | 2 +- 9 files changed, 574 insertions(+), 471 deletions(-) delete mode 160000 node diff --git a/.gitmodules b/.gitmodules index 544acfd5..fc549fb5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,7 @@ -[submodule "node"] - path = node - url = https://code.gri.mw/ardocrat/node [submodule "wallet"] path = wallet url = https://code.gri.mw/ardocrat/wallet - branch = grim + branch = grim-staging [submodule "tor/webtunnel"] path = tor/webtunnel url = https://code.gri.mw/WEB/webtunnel diff --git a/Cargo.lock b/Cargo.lock index 76dcfcb6..af3145e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,8 +290,8 @@ dependencies = [ "bitflags 2.10.0", "cc", "cesu8", - "jni", - "jni-sys", + "jni 0.21.1", + "jni-sys 0.3.0", "libc", "log", "ndk", @@ -756,7 +756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da2537846e16b96d2972ee52a3b355663872a1a687ce6d57a3b6f6b6a181c89" dependencies = [ "thiserror 1.0.69", - "tokio 1.49.0", + "tokio 1.52.3", ] [[package]] @@ -836,7 +836,7 @@ dependencies = [ "futures-util", "pin-project", "rustc_version", - "tokio 1.49.0", + "tokio 1.52.3", ] [[package]] @@ -987,6 +987,28 @@ dependencies = [ "arrayvec 0.7.6", ] +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "backtrace" version = "0.3.76" @@ -1368,16 +1390,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - [[package]] name = "bytes" version = "0.5.6" @@ -1600,6 +1612,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "coarsetime" version = "0.1.37" @@ -1987,9 +2008,9 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array 0.14.7", "subtle", @@ -2002,7 +2023,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", - "itoa 1.0.17", + "itoa", "ryu", "serde_core", ] @@ -2551,6 +2572,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -2731,7 +2758,7 @@ dependencies = [ "atomic_float", "bitflags 2.10.0", "egui", - "tokio 1.49.0", + "tokio 1.52.3", "tracing", "wasm-bindgen-futures", ] @@ -3400,6 +3427,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "fslock-guard" version = "0.7.0" @@ -3906,7 +3939,6 @@ version = "0.3.6" dependencies = [ "android-activity", "android_logger", - "anyhow", "arboard", "arti-client", "async-std", @@ -3939,14 +3971,14 @@ dependencies = [ "grin_wallet_libwallet", "grin_wallet_util", "http-body-util", - "hyper 1.8.1", + "hyper 1.10.1", "hyper-proxy2", "hyper-socks2", - "hyper-tls 0.6.0", + "hyper-tls", "hyper-util", "image", "interprocess", - "jni", + "jni 0.21.1", "lazy_static", "local-ip-address", "log", @@ -3954,7 +3986,6 @@ dependencies = [ "nokhwa", "num-bigint 0.4.6", "parking_lot 0.12.5", - "pin-project", "qrcode", "qrcodegen", "rand 0.9.2", @@ -3969,15 +4000,11 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sys-locale", - "thiserror 2.0.18", - "tls-api", - "tls-api-native-tls", "tokio 0.2.25", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.2.0", "toml 0.9.11+spec-1.1.0", "tor-config", - "tor-error", "tor-hscrypto", "tor-hsrproxy", "tor-hsservice", @@ -3994,7 +4021,7 @@ dependencies = [ [[package]] name = "grin_api" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "async-stream", "bytes 1.11.1", @@ -4020,14 +4047,14 @@ dependencies = [ "serde_derive", "serde_json", "thiserror 1.0.69", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-rustls 0.23.4", "url", ] [[package]] name = "grin_chain" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "bit-vec 0.6.3", "bitflags 1.3.2", @@ -4049,7 +4076,7 @@ dependencies = [ [[package]] name = "grin_config" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "dirs 2.0.2", "grin_core", @@ -4064,7 +4091,7 @@ dependencies = [ [[package]] name = "grin_core" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "blake2-rfc", "byteorder", @@ -4089,7 +4116,7 @@ dependencies = [ [[package]] name = "grin_keychain" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "blake2-rfc", "byteorder", @@ -4110,7 +4137,7 @@ dependencies = [ [[package]] name = "grin_p2p" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "bitflags 1.3.2", "built", @@ -4132,7 +4159,7 @@ dependencies = [ [[package]] name = "grin_pool" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "blake2-rfc", "chrono", @@ -4163,7 +4190,7 @@ dependencies = [ [[package]] name = "grin_servers" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "async-stream", "chrono", @@ -4186,14 +4213,14 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.7.18", "walkdir", ] [[package]] name = "grin_store" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "byteorder", "croaring", @@ -4211,7 +4238,7 @@ dependencies = [ [[package]] name = "grin_util" -version = "5.4.1" +version = "5.5.1-alpha.0" dependencies = [ "anyhow", "backtrace", @@ -4232,7 +4259,7 @@ dependencies = [ [[package]] name = "grin_wallet_api" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ "base64 0.12.3", "chrono", @@ -4256,7 +4283,7 @@ dependencies = [ [[package]] name = "grin_wallet_config" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ "dirs 2.0.2", "grin_core", @@ -4270,7 +4297,7 @@ dependencies = [ [[package]] name = "grin_wallet_controller" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ "chrono", "easy-jsonrpc-mw", @@ -4297,21 +4324,24 @@ dependencies = [ "serde_json", "term 0.6.1", "thiserror 1.0.69", - "tokio 0.2.25", + "tokio 1.52.3", "url", "uuid 0.8.2", ] [[package]] name = "grin_wallet_impls" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ + "arti-client", "base64 0.12.3", "blake2-rfc", - "byteorder", + "bytes 1.11.1", "chrono", - "data-encoding", + "curve25519-dalek 4.1.3", "ed25519-dalek 1.0.1", + "ed25519-dalek 2.2.0", + "fs-mistrust", "futures 0.3.31", "grin_api", "grin_chain", @@ -4322,6 +4352,9 @@ dependencies = [ "grin_wallet_config", "grin_wallet_libwallet", "grin_wallet_util", + "http-body-util", + "hyper 1.10.1", + "hyper-util", "lazy_static", "log", "rand 0.6.5", @@ -4331,18 +4364,24 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "sha2 0.10.9", "sysinfo 0.29.11", "thiserror 1.0.69", "timer", - "tokio 0.2.25", + "tokio 1.52.3", + "tor-hscrypto", + "tor-hsrproxy", + "tor-hsservice", + "tor-keymgr", + "tor-llcrypto", + "tor-rtcompat", "url", "uuid 0.8.2", - "x25519-dalek 0.6.0", ] [[package]] name = "grin_wallet_libwallet" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ "age", "base64 0.9.3", @@ -4380,7 +4419,7 @@ dependencies = [ [[package]] name = "grin_wallet_util" -version = "5.4.0-alpha.1" +version = "5.4.1" dependencies = [ "data-encoding", "ed25519-dalek 1.0.1", @@ -4415,26 +4454,6 @@ dependencies = [ "xxhash-rust", ] -[[package]] -name = "h2" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" -dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 1.9.3", - "slab", - "tokio 0.2.25", - "tokio-util 0.3.1", - "tracing", - "tracing-futures", -] - [[package]] name = "h2" version = "0.3.27" @@ -4449,16 +4468,16 @@ dependencies = [ "http 0.2.12", "indexmap 2.13.0", "slab", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.7.18", "tracing", ] [[package]] name = "h2" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes 1.11.1", @@ -4468,7 +4487,7 @@ dependencies = [ "http 1.4.0", "indexmap 2.13.0", "slab", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.7.18", "tracing", ] @@ -4536,7 +4555,7 @@ dependencies = [ "bytes 1.11.1", "headers-core", "http 1.4.0", - "httpdate 1.0.3", + "httpdate", "mime", "sha1", ] @@ -4682,7 +4701,7 @@ checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes 1.11.1", "fnv", - "itoa 1.0.17", + "itoa", ] [[package]] @@ -4692,17 +4711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes 1.11.1", - "itoa 1.0.17", -] - -[[package]] -name = "http-body" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -dependencies = [ - "bytes 0.5.6", - "http 0.2.12", + "itoa", ] [[package]] @@ -4745,12 +4754,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" -[[package]] -name = "httpdate" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" - [[package]] name = "httpdate" version = "1.0.3" @@ -4773,30 +4776,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hyper" -version = "0.13.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" -dependencies = [ - "bytes 0.5.6", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.2.7", - "http 0.2.12", - "http-body 0.3.1", - "httparse", - "httpdate 0.3.2", - "itoa 0.4.8", - "pin-project", - "socket2 0.3.19", - "tokio 0.2.25", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "0.14.32" @@ -4811,11 +4790,11 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "httparse", - "httpdate 1.0.3", - "itoa 1.0.17", + "httpdate", + "itoa", "pin-project-lite 0.2.16", "socket2 0.5.10", - "tokio 1.49.0", + "tokio 1.52.3", "tower-service", "tracing", "want", @@ -4823,24 +4802,23 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes 1.11.1", "futures-channel", "futures-core", - "h2 0.4.13", + "h2 0.4.15", "http 1.4.0", "http-body 1.0.1", "httparse", - "httpdate 1.0.3", - "itoa 1.0.17", + "httpdate", + "itoa", "pin-project-lite 0.2.16", - "pin-utils", "smallvec", - "tokio 1.49.0", + "tokio 1.52.3", "want", ] @@ -4854,32 +4832,16 @@ dependencies = [ "futures-util", "headers", "http 1.4.0", - "hyper 1.8.1", - "hyper-tls 0.6.0", + "hyper 1.10.1", + "hyper-tls", "hyper-util", "native-tls", "pin-project-lite 0.2.16", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-native-tls", "tower-service", ] -[[package]] -name = "hyper-rustls" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" -dependencies = [ - "bytes 0.5.6", - "futures-util", - "hyper 0.13.10", - "log", - "rustls 0.18.1", - "tokio 0.2.25", - "tokio-rustls 0.14.1", - "webpki 0.21.4", -] - [[package]] name = "hyper-rustls" version = "0.23.2" @@ -4890,11 +4852,26 @@ dependencies = [ "hyper 0.14.32", "log", "rustls 0.20.9", - "rustls-native-certs", - "tokio 1.49.0", + "rustls-native-certs 0.6.3", + "tokio 1.52.3", "tokio-rustls 0.23.4", ] +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http 1.4.0", + "hyper 1.10.1", + "hyper-util", + "rustls 0.23.41", + "tokio 1.52.3", + "tokio-rustls 0.26.4", + "tower-service", +] + [[package]] name = "hyper-socks2" version = "0.9.1" @@ -4903,11 +4880,11 @@ checksum = "51c227614c208f7e7c2e040526912604a1a957fe467c9c2f5b06c5d032337dab" dependencies = [ "async-socks5", "http 1.4.0", - "hyper 1.8.1", - "hyper-tls 0.6.0", + "hyper 1.10.1", + "hyper-tls", "hyper-util", "thiserror 1.0.69", - "tokio 1.49.0", + "tokio 1.52.3", "tower-service", ] @@ -4919,23 +4896,10 @@ checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ "hyper 0.14.32", "pin-project-lite 0.2.16", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-io-timeout", ] -[[package]] -name = "hyper-tls" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" -dependencies = [ - "bytes 0.5.6", - "hyper 0.13.10", - "native-tls", - "tokio 0.2.25", - "tokio-tls", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -4944,10 +4908,10 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes 1.11.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.10.1", "hyper-util", "native-tls", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-native-tls", "tower-service", ] @@ -4958,18 +4922,23 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64 0.22.1", "bytes 1.11.1", "futures-channel", "futures-util", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper 1.10.1", + "ipnet", "libc", + "percent-encoding", "pin-project-lite 0.2.16", - "socket2 0.6.2", - "tokio 1.49.0", + "socket2 0.5.10", + "system-configuration", + "tokio 1.52.3", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -5324,7 +5293,7 @@ dependencies = [ "futures-core", "libc", "recvmsg", - "tokio 1.49.0", + "tokio 1.52.3", "widestring", "windows-sys 0.52.0", ] @@ -5407,12 +5376,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.17" @@ -5452,19 +5415,68 @@ dependencies = [ "cesu8", "cfg-if 1.0.4", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if 1.0.4", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.44", + "rustc_version", + "simd_cesu8", + "syn 2.0.114", +] + [[package]] name = "jni-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote 1.0.44", + "syn 2.0.114", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -5613,9 +5625,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.181" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libfuzzer-sys" @@ -5852,6 +5864,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -5962,16 +5980,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "mime_guess2" version = "2.3.1" @@ -6041,9 +6049,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -6155,10 +6163,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -6170,7 +6178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.10.0", - "jni-sys", + "jni-sys 0.3.0", "log", "ndk-sys", "num_enum", @@ -6190,7 +6198,7 @@ version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", + "jni-sys 0.3.0", ] [[package]] @@ -6368,7 +6376,7 @@ dependencies = [ "kqueue", "libc", "log", - "mio 1.1.1", + "mio 1.2.1", "notify-types", "walkdir", "windows-sys 0.60.2", @@ -6948,6 +6956,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-src" version = "300.6.0+3.6.2" @@ -7144,9 +7158,9 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.2.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e0b28ace46c5a396546bcf443bf422b57049617433d8854227352a4a9b24e7" +checksum = "c1a5d4e9c205d2c1ae73b84aab6240e98218c0e72e63b50422cfb2d1ca952282" dependencies = [ "base64ct", "rand_core 0.6.4", @@ -7193,16 +7207,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -[[package]] -name = "pem" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" -dependencies = [ - "base64 0.22.1", - "serde_core", -] - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -7707,6 +7711,62 @@ dependencies = [ "serde", ] +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes 1.11.1", + "cfg_aliases", + "pin-project-lite 0.2.16", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls 0.23.41", + "socket2 0.5.10", + "thiserror 2.0.18", + "tokio 1.52.3", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" +dependencies = [ + "aws-lc-rs", + "bytes 1.11.1", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring 0.17.14", + "rustc-hash 2.1.1", + "rustls 0.23.41", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "0.6.13" @@ -8227,42 +8287,40 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "reqwest" -version = "0.10.10" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ - "base64 0.13.1", - "bytes 0.5.6", + "base64 0.22.1", + "bytes 1.11.1", "encoding_rs", "futures-core", - "futures-util", - "http 0.2.12", - "http-body 0.3.1", - "hyper 0.13.10", - "hyper-rustls 0.21.0", - "hyper-tls 0.4.3", - "ipnet", + "h2 0.4.15", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.10.1", + "hyper-rustls 0.27.9", + "hyper-util", "js-sys", - "lazy_static", "log", "mime", - "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite 0.2.16", - "rustls 0.18.1", - "serde", - "serde_urlencoded", - "tokio 0.2.25", - "tokio-rustls 0.14.1", - "tokio-socks", - "tokio-tls", + "quinn", + "rustls 0.23.41", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio 1.52.3", + "tokio-rustls 0.26.4", + "tower", + "tower-http", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", - "winreg", ] [[package]] @@ -8607,19 +8665,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" -dependencies = [ - "base64 0.12.3", - "log", - "ring 0.16.20", - "sct 0.6.1", - "webpki 0.21.4", -] - [[package]] name = "rustls" version = "0.20.9" @@ -8628,8 +8673,22 @@ checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ "log", "ring 0.16.20", - "sct 0.7.1", - "webpki 0.22.4", + "sct", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.23.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] @@ -8638,10 +8697,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", ] [[package]] @@ -8653,6 +8724,55 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys 0.8.7", + "jni 0.22.4", + "log", + "once_cell", + "rustls 0.23.41", + "rustls-native-certs 0.8.4", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "aws-lc-rs", + "ring 0.17.14", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -8792,16 +8912,6 @@ dependencies = [ "sha2 0.10.9", ] -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "sct" version = "0.7.1" @@ -8870,6 +8980,19 @@ dependencies = [ "security-framework-sys", ] +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-foundation-sys 0.8.7", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" version = "2.15.0" @@ -8967,7 +9090,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "itoa 1.0.17", + "itoa", "memchr", "serde", "serde_core", @@ -9003,18 +9126,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa 1.0.17", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.16.1" @@ -9053,7 +9164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap 2.13.0", - "itoa 1.0.17", + "itoa", "ryu", "serde", "unsafe-libyaml", @@ -9175,6 +9286,16 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + [[package]] name = "simd_helpers" version = "0.1.0" @@ -9184,6 +9305,12 @@ dependencies = [ "quote 1.0.44", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "simplecss" version = "0.2.2" @@ -9312,17 +9439,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.4", - "libc", - "winapi 0.3.9", -] - [[package]] name = "socket2" version = "0.5.10" @@ -9335,12 +9451,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -9493,9 +9609,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svgtypes" @@ -9545,6 +9661,9 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] [[package]] name = "synchronoise" @@ -9604,6 +9723,27 @@ dependencies = [ "windows 0.62.2", ] +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys 0.8.7", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -9733,7 +9873,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", - "itoa 1.0.17", + "itoa", "num-conv", "powerfmt", "serde_core", @@ -9818,32 +9958,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tls-api" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb75b7304e6c157a435fff36a9ddc111ad410015d5260b306f10a18cffad72" -dependencies = [ - "anyhow", - "pem", - "tempfile", - "thiserror 2.0.18", - "tokio 1.49.0", -] - -[[package]] -name = "tls-api-native-tls" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e596bdd9afb0c372ab14f42ac9fbbda71af4ffc2daaad1e1606d9f1538fc0e36" -dependencies = [ - "anyhow", - "native-tls", - "thiserror 2.0.18", - "tls-api", - "tokio 1.49.0", -] - [[package]] name = "tokio" version = "0.2.25" @@ -9870,18 +9984,18 @@ dependencies = [ [[package]] name = "tokio" -version = "1.49.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes 1.11.1", "libc", - "mio 1.1.1", + "mio 1.2.1", "parking_lot 0.12.5", "pin-project-lite 0.2.16", "signal-hook-registry", - "socket2 0.6.2", - "tokio-macros 2.6.0", + "socket2 0.6.4", + "tokio-macros 2.7.0", "windows-sys 0.61.2", ] @@ -9892,7 +10006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" dependencies = [ "pin-project-lite 0.2.16", - "tokio 1.49.0", + "tokio 1.52.3", ] [[package]] @@ -9908,9 +10022,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2 1.0.106", "quote 1.0.44", @@ -9924,19 +10038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.49.0", -] - -[[package]] -name = "tokio-rustls" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" -dependencies = [ - "futures-core", - "rustls 0.18.1", - "tokio 0.2.25", - "webpki 0.21.4", + "tokio 1.52.3", ] [[package]] @@ -9946,31 +10048,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls 0.20.9", - "tokio 1.49.0", - "webpki 0.22.4", + "tokio 1.52.3", + "webpki", ] [[package]] -name = "tokio-socks" -version = "0.3.0" +name = "tokio-rustls" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d611fd5d241872372d52a0a3d309c52d0b95a6a67671a6c8f7ab2c4a37fb2539" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.3.31", - "thiserror 1.0.69", - "tokio 0.2.25", -] - -[[package]] -name = "tokio-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" -dependencies = [ - "native-tls", - "tokio 0.2.25", + "rustls 0.23.41", + "tokio 1.52.3", ] [[package]] @@ -9987,20 +10076,6 @@ dependencies = [ "tokio 0.2.25", ] -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.1.12", - "tokio 0.2.25", -] - [[package]] name = "tokio-util" version = "0.7.18" @@ -10012,7 +10087,7 @@ dependencies = [ "futures-io", "futures-sink", "pin-project-lite 0.2.16", - "tokio 1.49.0", + "tokio 1.52.3", ] [[package]] @@ -10429,7 +10504,7 @@ dependencies = [ "hex", "http 1.4.0", "httparse", - "httpdate 1.0.3", + "httpdate", "itertools 0.14.0", "memchr", "thiserror 2.0.18", @@ -11106,7 +11181,7 @@ dependencies = [ "subtle", "sync_wrapper", "thiserror 2.0.18", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.7.18", "tor-async-utils", "tor-basic-utils", @@ -11214,9 +11289,9 @@ dependencies = [ "native-tls", "paste", "pin-project", - "socket2 0.6.2", + "socket2 0.6.4", "thiserror 2.0.18", - "tokio 1.49.0", + "tokio 1.52.3", "tokio-util 0.7.18", "tor-error", "tor-general-addr", @@ -11286,6 +11361,45 @@ dependencies = [ "tor-memquota", ] +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite 0.2.16", + "sync_wrapper", + "tokio 1.52.3", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.10.0", + "bytes 1.11.1", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "pin-project-lite 0.2.16", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -11325,16 +11439,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -11564,9 +11668,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ "generic-array 0.14.7", "subtle", @@ -11829,8 +11933,6 @@ dependencies = [ "cfg-if 1.0.4", "once_cell", "rustversion", - "serde", - "serde_json", "wasm-bindgen-macro", "wasm-bindgen-shared", ] @@ -12092,7 +12194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" dependencies = [ "core-foundation 0.10.1", - "jni", + "jni 0.21.1", "log", "ndk-context", "objc2 0.6.3", @@ -12101,16 +12203,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "webpki" version = "0.22.4" @@ -12122,12 +12214,12 @@ dependencies = [ ] [[package]] -name = "webpki-roots" -version = "0.20.0" +name = "webpki-root-certs" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ - "webpki 0.21.4", + "rustls-pki-types", ] [[package]] @@ -12538,6 +12630,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -12909,15 +13012,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" -[[package]] -name = "winreg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/Cargo.toml b/Cargo.toml index e1918fee..ef4c7ae7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,14 +29,14 @@ panic = "abort" log = "0.4.27" # node -grin_api = { path = "node/api" } -grin_chain = { path = "node/chain" } -grin_config = { path = "node/config" } -grin_core = { path = "node/core" } -grin_p2p = { path = "node/p2p" } -grin_servers = { path = "node/servers" } -grin_keychain = { path = "node/keychain" } -grin_util = { path = "node/util" } +grin_api = { path = "wallet/grin/api" } +grin_chain = { path = "wallet/grin/chain" } +grin_config = { path = "wallet/grin/config" } +grin_core = { path = "wallet/grin/core" } +grin_p2p = { path = "wallet/grin/p2p" } +grin_servers = { path = "wallet/grin/servers" } +grin_keychain = { path = "wallet/grin/keychain" } +grin_util = { path = "wallet/grin/util" } # wallet grin_wallet_impls = { path = "wallet/impls" } @@ -53,10 +53,7 @@ rust-i18n = "3.1.5" ## other log4rs = "1.4.0" -anyhow = "1.0.97" -pin-project = "1.1.10" backtrace = "0.3.76" -thiserror = "2.0.18" futures = "0.3.31" dirs = "6.0.0" sys-locale = "0.3.2" @@ -101,12 +98,9 @@ tor-hsrproxy = "0.43.0" tor-keymgr = "0.43.0" tor-llcrypto = "0.43.0" tor-hscrypto = "0.43.0" -tor-error = "0.43.0" sha2 = "0.10.8" ed25519-dalek = "2.1.1" curve25519-dalek = "4.1.3" -tls-api = "0.12.0" -tls-api-native-tls = "0.12.1" safelog = "0.8.1" ## stratum server diff --git a/node b/node deleted file mode 160000 index bce5a714..00000000 --- a/node +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bce5a7144be4085dc9f4bcbb66d860ffeef9b4ca diff --git a/src/gui/views/wallets/wallet/txs/content.rs b/src/gui/views/wallets/wallet/txs/content.rs index 318dad71..b5246880 100644 --- a/src/gui/views/wallets/wallet/txs/content.rs +++ b/src/gui/views/wallets/wallet/txs/content.rs @@ -646,7 +646,7 @@ impl WalletTransactionsContent { if let Some(a) = &tx.receiver { wallet.task(WalletTask::SendTor(tx.data.clone(), a.clone())); } else { - wallet.task(WalletTask::PayTor(tx.data.clone())); + wallet.task(WalletTask::FinalizeTor(tx.data.clone())); } }); } diff --git a/src/gui/views/wallets/wallet/txs/tx.rs b/src/gui/views/wallets/wallet/txs/tx.rs index 2530fba5..20216daf 100644 --- a/src/gui/views/wallets/wallet/txs/tx.rs +++ b/src/gui/views/wallets/wallet/txs/tx.rs @@ -12,13 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::scroll_area::ScrollBarVisibility; -use egui::{Align, CornerRadius, Id, Layout, RichText, ScrollArea, StrokeKind}; -use grin_core::core::amount_to_hr_string; -use grin_util::ToHex; -use grin_wallet_libwallet::TxLogEntryType; -use std::fs; - use crate::AppConfig; use crate::gui::Colors; use crate::gui::icons::{ @@ -34,6 +27,13 @@ use crate::gui::views::{Modal, QrCodeContent, View}; use crate::wallet::Wallet; use crate::wallet::types::{WalletTask, WalletTx}; +use egui::scroll_area::ScrollBarVisibility; +use egui::{Align, CornerRadius, Id, Layout, RichText, ScrollArea, StrokeKind}; +use grin_core::core::amount_to_hr_string; +use grin_util::ToHex; +use grin_wallet_libwallet::TxLogEntryType; +use std::fs; + /// Transaction information [`Modal`] content. pub struct WalletTransactionContent { /// Transaction identifier. diff --git a/src/wallet/types.rs b/src/wallet/types.rs index 042173e6..5bff0da4 100644 --- a/src/wallet/types.rs +++ b/src/wallet/types.rs @@ -406,9 +406,9 @@ pub enum WalletTask { /// * tx /// * receiver SendTor(TxLogEntry, SlatepackAddress), - /// Pay over Tor. + /// Finalize over Tor. /// * tx - PayTor(TxLogEntry), + FinalizeTor(TxLogEntry), /// Invoice creation. /// * amount Receive(u64, Option), diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index e4a52d18..f30f7ae4 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -39,6 +39,7 @@ use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient}; use grin_wallet_libwallet::api_impl::owner::{ cancel_tx, init_send_tx, retrieve_summary_info, retrieve_txs, verify_payment_proof, }; +use grin_wallet_libwallet::api_impl::types::update_tx_slate_state; use grin_wallet_libwallet::{ Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, Slate, SlateState, SlateVersion, SlatepackAddress, StatusMessage, StoredProofInfo, TxLogEntry, TxLogEntryType, @@ -1316,6 +1317,18 @@ impl Wallet { None } + /// Update transaction slate state. + fn update_slate_state(&self, slate: &Slate) -> Result<(), Error> { + let r_inst = self.instance.as_ref().read(); + let instance = r_inst.clone().unwrap(); + let mut w_lock = instance.lock(); + let w = w_lock.lc_provider()?.wallet_inst()?; + let keychain_mask = self.keychain_mask(); + let parent_key = w.parent_key_id(); + update_tx_slate_state(w, keychain_mask.as_ref(), &parent_key, slate)?; + Ok(()) + } + /// Delete transaction from database. fn delete_tx(&self, id: u32) -> Result<(), Error> { self.on_tx_action(id, Some(WalletTxAction::Deleting)); @@ -1735,6 +1748,7 @@ fn start_sync(wallet: Wallet) -> Thread { /// Handle wallet task. async fn handle_task(w: &Wallet, t: WalletTask) { + // Send amount over Tor. let send_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w .send_tor(tx.id, &s, r, false) .await @@ -1746,34 +1760,35 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.on_task_result(Some(tx), &t); } Err(e) => { - error!("send tor post error: {:?}", e); + error!("Send Tor post error: {:?}", e); w.on_tx_error(tx.id, Some(e)); } }, Err(e) => { - error!("send tor finalize error: {:?}", e); + error!("Send Tor finalize error: {:?}", e); w.task(WalletTask::Cancel(tx.id)); } }, Err(e) => { - error!("send tor error: {:?}", e); + error!("Send Tor error: {:?}", e); w.on_tx_error(tx.id, Some(e)); w.on_task_result(Some(tx), &t); } }; - // Invoice-flow counterpart to send_tor. After signing an invoice the payer - // posts the slate to the merchant's foreign-api finalize_tx; the merchant - // finalizes + broadcasts on their side, so no local finalize/post is needed. - let pay_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w + // Finalize tx over Tor. + let finalize_tor = async |tx: TxLogEntry, s: &Slate, r: &SlatepackAddress| match w .send_tor(tx.id, &s, r, true) .await { - Ok(_) => { + Ok(s) => { + w.on_tx_action(tx.id, None); + let _ = w.update_slate_state(&s); + let _ = w.create_slatepack_message(&s, None); sync_wallet_data(&w, false); w.on_task_result(Some(tx), &t); } Err(e) => { - error!("pay tor error: {:?}", e); + error!("Finalize Tor error: {:?}", e); w.on_tx_error(tx.id, Some(e)); w.on_task_result(Some(tx), &t); } @@ -1809,29 +1824,33 @@ async fn handle_task(w: &Wallet, t: WalletTask) { w.message_opening.store(false, Ordering::Relaxed); return; } + // Finalize over Tor if service is running. + let maybe_finalize_tor = async |s: Slate| { + sync_wallet_data(&w, false); + let tx = w.retrieve_tx_by_id(None, Some(s.id)); + let id = w.identifier(); + if Tor::is_service_running(&id) { + if let Some(tx) = tx.as_ref() { + if let Some(addr) = dest { + w.message_opening.store(false, Ordering::Relaxed); + finalize_tor(tx.clone(), &s, &addr).await; + return; + } + } + } + }; // Create response or finalize. match s.state { SlateState::Standard1 => { - if let Ok(_) = w.receive(&s, dest) { - sync_wallet_data(&w, false); - let tx = w.retrieve_tx_by_id(None, Some(s.id)); + if let Ok(s) = w.receive(&s, None) { + maybe_finalize_tor(s).await; w.on_task_result(tx, &t); } } SlateState::Invoice1 => { - if let Ok(signed) = w.pay(&s, None) { + if let Ok(s) = w.pay(&s, None) { sync_wallet_data(&w, false); - let tx = w.retrieve_tx_by_id(None, Some(s.id)); - let id = w.identifier(); - if Tor::is_service_running(&id) { - if let Some(tx) = tx.as_ref() { - if let Some(addr) = dest { - w.message_opening.store(false, Ordering::Relaxed); - pay_tor(tx.clone(), &signed, &addr).await; - return; - } - } - } + maybe_finalize_tor(s).await; w.on_task_result(tx, &t); } } @@ -1907,10 +1926,10 @@ async fn handle_task(w: &Wallet, t: WalletTask) { send_tor(tx.clone(), &slate, r).await; } } - WalletTask::PayTor(tx) => { + WalletTask::FinalizeTor(tx) => { if let Some((slate, dest)) = w.get_tx_slate(tx.id) { if let Some(dest) = dest { - pay_tor(tx.clone(), &slate, &dest).await; + finalize_tor(tx.clone(), &slate, &dest).await; } } } diff --git a/wallet b/wallet index c2db7545..5c54e7cf 160000 --- a/wallet +++ b/wallet @@ -1 +1 @@ -Subproject commit c2db754552b9e5c57c4a843c68744df0cc744ff8 +Subproject commit 5c54e7cf8d4cca2354b47ace80016e1bd23deb8c From ee8841590a112c299af9fc551cd07b09fb0da544 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Tue, 23 Jun 2026 15:42:43 +0300 Subject: [PATCH 5/6] ci: recursive submodules --- .forgejo/workflows/build.yaml | 2 +- .forgejo/workflows/release.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 3a8cfa39..32d7d70e 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -16,7 +16,7 @@ jobs: - name: Checkout submodules run: | sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Check commit id: check run: | diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml index 98b11c97..8b5e69b2 100644 --- a/.forgejo/workflows/release.yaml +++ b/.forgejo/workflows/release.yaml @@ -21,7 +21,7 @@ jobs: - name: Checkout submodules run: | sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Get version id: version run: | @@ -86,7 +86,7 @@ jobs: - name: Checkout submodules run: | sed -i -- 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Restore cargo cache id: cache-cargo-restore uses: actions/cache/restore@v5 @@ -188,7 +188,7 @@ jobs: - name: Checkout submodules run: | sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Restore cargo cache id: cache-cargo-restore uses: actions/cache/restore@v5 @@ -255,7 +255,7 @@ jobs: - name: Checkout submodules run: | sed -i 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Restore cargo cache id: cache-cargo-restore uses: actions/cache/restore@v5 @@ -307,7 +307,7 @@ jobs: - name: Checkout submodules run: | sed -i -- 's#https://code\.gri\.mw#${{ secrets.REPO_HOST }}#g' .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - run: mkdir release - name: Restore cargo cache id: cache-cargo-restore @@ -360,7 +360,7 @@ jobs: - name: Checkout submodules run: | (Get-content .gitmodules) | Foreach-Object {$_ -replace "https://code.gri.mw", "${{ secrets.REPO_HOST }}"} | Set-Content .gitmodules - git submodule update --init + git submodule update --init --recursive --remote - name: Update UpgradeCode shell: powershell run: | From f891c8f516c44ea5b395e836eec5076a8f7e4f47 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Wed, 8 Jul 2026 23:02:35 +0300 Subject: [PATCH 6/6] tor: fix send timeout --- src/tor/tor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tor/tor.rs b/src/tor/tor.rs index c376a90f..1bc08185 100644 --- a/src/tor/tor.rs +++ b/src/tor/tor.rs @@ -323,7 +323,7 @@ impl Tor { .block_on(async move { let res = c .runtime() - .timeout(Duration::from_millis(600000), async { + .timeout(Duration::from_millis(60000), async { if let Ok(stream) = c .connect((uri.host().unwrap(), uri.port_u16().unwrap_or(80))) .await