Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

gui: Add automated coin selection for spend #563

Merged

Conversation

jp1ac4
Copy link
Collaborator

@jp1ac4 jp1ac4 commented Jun 30, 2023

This adds automated coin selection from #560 to the GUI.

The new "Auto-select" button uses automated coin selection to select coins for a spend, which the user can then modify as required.

The button can only be clicked once the recipients and feerate have been validated, and it does not appear when creating a self-send.

I haven't added any validation on the amount before making the button clickable, but it may be hard to anticipate all coin selection errors once fees are taken into consideration.

@darosior
Copy link
Member

darosior commented Jul 3, 2023 via email

@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Jul 4, 2023

I think that should be fine. I've made an initial attempt at that now, which seems to work as you describe. It may need some refactoring and better handling of errors from coin selection.

@jp1ac4 jp1ac4 force-pushed the add-auto-coin-selection-to-gui branch from 454535b to 25cf513 Compare October 30, 2023 08:32
@jp1ac4 jp1ac4 force-pushed the add-auto-coin-selection-to-gui branch 5 times, most recently from 9dbcb41 to c890e56 Compare November 8, 2023 14:07
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 8, 2023

This is ready for initial testing.

When creating a new spend, coins are selected automatically unless the user edits the selection, after which point only manual selection will be used.

In case auto-selection fails due to insufficient funds, the amount left to select will show a positive value. If the user then edits the recipient amounts and/or feerate, coin selection will run again.

A spend created using auto-selection should pay the same fee and give the same change amount as another spend created using manual selection with the same auto-selected coins.

@jp1ac4 jp1ac4 force-pushed the add-auto-coin-selection-to-gui branch from c890e56 to 3ef2e9b Compare November 9, 2023 13:52
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 9, 2023

Updated liana dependency commit hash.

@darosior
Copy link
Member

darosior commented Nov 9, 2023

Got a crash on my first try :p. It might be because i used a receive address as destination address?

logs
  2023-11-09T14:37:31.604594Z  INFO liana::bitcoin::poller::looper:360: Block chain synchronization progress: 100.00% (815999 blocks / 815999 headers)                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                (PUSH) branch=[1☐, 0☐, 2☐, 3☐, 4☐] inclusion=true lb=Ordf32(42.090916) score=None                                                                                                                                                                                                                                                                                                                                       
                (PUSH) branch=[1✔, 0☐, 2☐, 3☐, 4☐] inclusion=true lb=Ordf32(900001500.0) score=Some(Ordf32(900001500.0))                                                                                                                                                                                                                                                                                                                
  2023-11-09T14:48:04.968686Z ERROR liana:55: panic occurred at line 183 of file /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/metrics/lowest_fee.rs: Some("value:weight ratio must stay the same: vpw=509454.28 perfect_vpw=509454.25 perfect_value=200000200 perfect_weight=392.57733")                                                                                                    
   0: liana::setup_panic_hook::{{closure}}                                                                                                                                                                                                                                                                                                                                                                                              
             at /home/darosior/.cargo/git/checkouts/liana-d9e0035d1d73e045/ae5c1c3/src/lib.rs:49:18                                                                                                                                                                                                                                                                                                                                     
   1: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call                                                                                                                                                                                                                                                                                                                                                                   
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/boxed.rs:2021:9                                                                                                                                                                                                                                                                                                                                       
      std::panicking::rust_panic_with_hook                                                                                                                                                                                                                                                                                                                                                                                              
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:711:13                                                                                                                                                                                                                                                                                                                                     
   2: std::panicking::begin_panic_handler::{{closure}}                                                                                                                                                                                                                                                                                                                                                                                  
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:599:13                                                                                                                                                                                                                                                                                                                                     
   3: std::sys_common::backtrace::__rust_end_short_backtrace                                                                                                                                                                                                                                                                                                                                                                            
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/sys_common/backtrace.rs:170:18                                                                                                                                                                                                                                                                                                                          
   4: rust_begin_unwind                                                                                                                                                                                                                                                                                                                                                                                                                 
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:595:5                                                                                                                                                                                                                                                                                                                                      
   5: core::panicking::panic_fmt                                                                                                                                                                                   
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:67:14                                                                                                                
   6: bdk_coin_select::metrics::lowest_fee::slurp                                                                                                                                                                  
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/metrics/lowest_fee.rs:183:13                                                                              
   7: <bdk_coin_select::metrics::lowest_fee::LowestFee<C> as bdk_coin_select::bnb::BnbMetric>::bound                                                                                                               
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/metrics/lowest_fee.rs:160:36                                                                              
   8: bdk_coin_select::bnb::BnbIter<M>::consider_adding_to_queue                                                                                                                                                   
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/bnb.rs:93:21                                                                                              
   9: bdk_coin_select::bnb::BnbIter<M>::insert_new_branches                                                                                                                                                        
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/bnb.rs:157:9                                                                                              
  10: <bdk_coin_select::bnb::BnbIter<M> as core::iter::traits::iterator::Iterator>::next                                                                                                                           
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/bnb.rs:54:9                                                                                               
  11: core::iter::traits::iterator::Iterator::try_fold                                                                                                                                                             
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/traits/iterator.rs:2460:29                                                                                                   
  12: <core::iter::adapters::inspect::Inspect<I,F> as core::iter::traits::iterator::Iterator>::try_fold                                                                                                            
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/inspect.rs:92:9                                                                                                     
  13: <core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::try_fold                                                                                                                    
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/take.rs:97:13                                                                                                       
  14: <core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::fold                                                                                                                        
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/mod.rs:378:13                                                                                                                
  15: <core::iter::adapters::fuse::Fuse<I> as core::iter::traits::iterator::Iterator>::fold                                                                                                                        
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/fuse.rs:91:19                                                                                                       
  16: core::iter::adapters::flatten::FlattenCompat<I,U>::iter_fold                                                                                                                                                 
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/flatten.rs:353:15                                                                                                   
  17: <core::iter::adapters::flatten::FlattenCompat<I,U> as core::iter::traits::iterator::Iterator>::last                                                                                                          
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/flatten.rs:577:9                                                                                                    
      <core::iter::adapters::flatten::Flatten<I> as core::iter::traits::iterator::Iterator>::last                                                                                                                  
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/iter/adapters/flatten.rs:237:20                                                                                                   
  18: bdk_coin_select::coin_selector::CoinSelector::run_bnb                                                                                                                                                        
             at /home/darosior/.cargo/git/checkouts/bdk-0dee5b29605e7dd4/7607975/nursery/coin_select/src/coin_selector.rs:493:33                                                                                   
  19: liana::commands::utils::select_coins_for_spend                                                                                                                                                               
             at /home/darosior/.cargo/git/checkouts/liana-d9e0035d1d73e045/ae5c1c3/src/commands/utils.rs:170:21                                                                                                    
  20: liana::commands::<impl liana::DaemonControl>::create_spend                                                                                                                                                   
             at /home/darosior/.cargo/git/checkouts/liana-d9e0035d1d73e045/ae5c1c3/src/commands/mod.rs:479:13                                                                                                      
  21: <liana_gui::daemon::embedded::EmbeddedDaemon as liana_gui::daemon::Daemon>::create_spend_tx                                                                                                                  
             at src/daemon/embedded.rs:91:9                                                                                                                                                                        
  22: liana_gui::app::state::spend::step::DefineSpend::auto_select_coins                                                                                                                                           
             at src/app/state/spend/step.rs:189:15                                                                                                                                                                 
  23: <liana_gui::app::state::spend::step::DefineSpend as liana_gui::app::state::spend::step::Step>::update                                                                                                        
             at src/app/state/spend/step.rs:385:21                                                                                                                                                                 
  24: <liana_gui::app::state::spend::CreateSpendPanel as liana_gui::app::state::State>::update                                                                                                                     
             at src/app/state/spend/mod.rs:105:20                                                                                                                                                                  
  25: liana_gui::app::App::update                                                                                                                                                                                  
             at src/app/mod.rs:174:18                                                                                                                                                                              
  26: <liana_gui::GUI as iced::application::Application>::update                                                                                                                                                   
             at src/main.rs:248:17
  27: <iced::application::Instance<A> as iced_native::program::Program>::update                    
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.9.0/src/application.rs:227:9                                                                                             
  28: iced_winit::application::update::{{closure}}                                                                                                                                                                 
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_winit-0.9.1/src/application.rs:664:40                                                                                      
  29: iced_futures::backend::native::tokio::<impl iced_futures::executor::Executor for tokio::runtime::runtime::Runtime>::enter      
             at /home/darosior/.cargo/git/checkouts/iced-01eedf742052ef90/2d8318b/futures/src/backend/native/tokio.rs:19:9                                                                                          
  30: iced_futures::runtime::Runtime<Hasher,Event,Executor,Sender,Message>::enter                                                                                                                                  
             at /home/darosior/.cargo/git/checkouts/iced-01eedf742052ef90/2d8318b/futures/src/runtime.rs:53:9                                                                                                       
  31: iced_winit::application::update                                                                                                                                                                              
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_winit-0.9.1/src/application.rs:664:23                                                                                      
  32: iced_glutin::application::run_instance::{{closure}}                                                                                                                                                          
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_glutin-0.8.0/src/application.rs:308:21                                                                                     
  33: iced_glutin::application::run::{{closure}}                                                                                                                                                                   
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_glutin-0.8.0/src/application.rs:187:24                                                                                     
  34: winit::platform_impl::platform::sticky_exit_callback                                                
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.27.5/src/platform_impl/linux/mod.rs:849:9                                                                               
  35: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run_return                       
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.27.5/src/platform_impl/linux/wayland/event_loop/mod.rs:488:13                                                           
  36: winit::platform_impl::platform::EventLoop<T>::run_return                                            
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.27.5/src/platform_impl/linux/mod.rs:748:56                                                                              
  37: <winit::event_loop::EventLoop<T> as winit::platform::run_return::EventLoopExtRunReturn>::run_return                                                                                                           
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.27.5/src/platform/run_return.rs:62:9                                                                                    
  38: iced_glutin::application::run                                                                       
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_glutin-0.8.0/src/application.rs:162:13                                                                                     
  39: iced::application::Application::run                                                                 
             at /home/darosior/.cargo/registry/src/index.crates.io-6f17d22bba15001f/iced-0.9.0/src/application.rs:209:12                                                                                            
  40: liana_gui::main                                                                                     
             at src/main.rs:396:21                                                                        
  41: core::ops::function::FnOnce::call_once                                                              
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/ops/function.rs:250:5    
  42: std::sys_common::backtrace::__rust_begin_short_backtrace                                            
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/sys_common/backtrace.rs:154:18                                                                                                      
  43: std::rt::lang_start::{{closure}}                                                                    
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/rt.rs:166:18              
  44: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once                 
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/ops/function.rs:284:13   
      std::panicking::try::do_call                                                                        
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:502:40       
      std::panicking::try                                                                                 
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:466:19       
      std::panic::catch_unwind                                                                            
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panic.rs:142:14           
      std::rt::lang_start_internal::{{closure}}                                                           
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/rt.rs:148:48              

EDIT: this was reported upstream (bitcoindevkit/bdk#1072 (comment)).

@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 13, 2023

Due to how the feerate will be converted from u64 to f32 in the daemon function (see #560 (comment) and #800), the GUI now panics if a feerate larger than u16::MAX is entered. Currently, if a value larger than u64::MAX is entered, the GUI displays "Invalid feerate".

Perhaps we should modify the GUI to use u16 for feerate and/or check for the CommandError::InsaneValue and then display a message.

@darosior
Copy link
Member

darosior commented Nov 13, 2023

The latter seems preferable, the GUI shouldn't crash just because an error is returned by a command.

EDIT: arf, i read too quickly. It implies we tackle #800 first..

@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 14, 2023

Updated Cargo.lock with latest commit hashes for liana and bdk_coin_select dependencies.

With the latest changes from #560, the GUI will no longer crash if a feerate larger than u16::MAX is entered, but will instead show an error like the one shown in #810 (comment). In v3.0, a u64 parsing error for the feerate gives "Invalid feerate" below the feerate input field.

@jp1ac4 jp1ac4 force-pushed the add-auto-coin-selection-to-gui branch from fc9bd8b to 9e2407e Compare November 15, 2023 20:02
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 15, 2023

Reverted liana dependency to master 🎉

@darosior
Copy link
Member

darosior commented Nov 15, 2023 via email

@jp1ac4 jp1ac4 changed the title [WIP] gui: Add automated coin selection for spend gui: Add automated coin selection for spend Nov 16, 2023
@jp1ac4 jp1ac4 marked this pull request as ready for review November 16, 2023 08:38
@jp1ac4
Copy link
Collaborator Author

jp1ac4 commented Nov 16, 2023

Have now set as ready for review.

Copy link
Member

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

light ACK 9e2407e


fn check_valid(&mut self) {
self.is_valid =
self.form_values_are_valid() && self.coins.iter().any(|(_, selected)| *selected);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup

}
let feerate_vb = self.feerate.value.parse::<u64>().unwrap_or(0);
// Create a spend with empty inputs in order to use auto-selection.
match daemon.create_spend_tx(&[], &outputs, feerate_vb) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One issue with creating a spend on every update is how the change address derivation index will keep being increased over and over. I think that's fine for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After #821, we could call create_spend here with a fixed change address just for coin selection purposes, and then increment the change index only when the user clicks "Next" and the PSBT is generated on screen.

@darosior darosior merged commit 639cac7 into wizardsardine:master Nov 17, 2023
18 checks passed
@jp1ac4 jp1ac4 deleted the add-auto-coin-selection-to-gui branch November 17, 2023 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants