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

[VDG] UI Decoupling #50 #11644

Merged
merged 35 commits into from
Oct 25, 2023
Merged

[VDG] UI Decoupling #50 #11644

merged 35 commits into from
Oct 25, 2023

Conversation

ichthus1604
Copy link
Contributor

@ichthus1604 ichthus1604 commented Oct 6, 2023

  • Introduces TransactionModel
  • Introduces TransactionTreeBuilder
  • Decouples HistoryViewModel
  • Decouples CoinjoinHistoryItemViewModel
  • Decouples CoinjoinsHistoryItemViewModel
  • Decouples HistoryItemViewModelBase
  • Decouples SpeedUpHistoryItemViewModel
  • Decouples TransactionHistoryItemViewModel

@soosr
Copy link
Contributor

soosr commented Oct 6, 2023

@ichthus1604 Could you fix conflicts?

@ichthus1604 ichthus1604 marked this pull request as ready for review October 9, 2023 19:57
@ichthus1604
Copy link
Contributor Author

@soosr Ready for review ;)

@soosr
Copy link
Contributor

soosr commented Oct 12, 2023

2023-10-12 12:25:13.019 [1] ERROR       HistoryViewModel.Update (267)   System.NotImplementedException: Unsupported Transaction Type: Unknown
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.CreateViewModel(TransactionModel transaction, HistoryItemViewModelBase parent) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 282
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.<Update>b__22_0(TransactionModel x) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 256
   at System.Linq.Enumerable.SelectEnumerableIterator`2.ToList()
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.Update(IEnumerable`1 transactions) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 255

One of my wallet has a CJ item which was detected as a self spend transaction and the transaction fee is higher than the amount the wallet received back which causes the history to have an item with a negative outgoing amount.
This is a bug that can mostly come out on RegTest and TestNet and obviously should be fixed.

However, the History building shouldn't fail. On master currently, the icon is empty and that's all.

@soosr
Copy link
Contributor

soosr commented Oct 12, 2023

If I remove the exception and just return a transactionviewmodel in the issue mentioned before.

I get another exception.

2023-10-12 12:57:16.899 [1] ERROR       HistoryViewModel.Update (267)   System.ArgumentNullException: Value cannot be null. (Parameter 'parent')
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.CreateViewModel(TransactionModel transaction, HistoryItemViewModelBase parent) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 281
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.<Update>b__22_0(TransactionModel x) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 256
   at System.Linq.Enumerable.SelectEnumerableIterator`2.ToList()
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.Update(IEnumerable`1 transactions) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 255

On master I can see it was a CPFP speed up transaction.
image

transaction = TransactionModel
 Amount = {Money} 0.20000000
 Balance = {Money} 1.70424800
 CanCancelTransaction = {bool} false
 CanSpeedUpTransaction = {bool} false
 Changed = Cast<object, IReactivePropertyChangedEventArgs<IReactiveObject>>
 Changing = Cast<object, IReactivePropertyChangedEventArgs<IReactiveObject>>
 Children = {List<TransactionModel>} Count = 2
 Confirmations = {int} 23
 ConfirmedTooltip = {string} "Confirmed (23 confirmations)"
 Date = {DateTimeOffset} 09/05/2023 10:18:20 +02:00
 DateString = {string} "2023-09-05 10:18"
 Fee = {Money} null
 Id = {uint256} 25fce942d9b5f2eec77bec61541d8f48acee813664403dff63f20e77e1cf2b38
 IncomingAmount = {Money} 0.20000000
 IsCancellation = {bool} false
 IsChild = {bool} false
 IsCoinjoin = {bool} false
 IsCoinjoinGroup = {bool} false
 IsConfirmed = {bool} true
 Labels = {LabelsArray} asd, TestCoins
 OrderIndex = {int} 102
 OutgoingAmount = {Money} null
 Status = {TransactionStatus} Confirmed
 ThrownExceptions = ScheduledSubject<Exception>
 TransactionSummary = TransactionSummary
 Type = {TransactionType} CPFP
 _changed = {Lazy<IObservable<IReactivePropertyChangedEventArgs<IReactiveObject>>>} ThreadSafetyMode=null, IsValueCreated=true, IsValueFaulted=false, Value=Cast<object, IReactivePropertyChangedEventArgs<IReactiveObject>>
 _changing = {Lazy<IObservable<IReactivePropertyChangedEventArgs<IReactiveObject>>>} ThreadSafetyMode=null, IsValueCreated=true, IsValueFaulted=false, Value=Cast<object, IReactivePropertyChangedEventArgs<IReactiveObject>>
 _children = {List<TransactionModel>} Count = 2
 _propertyChangedEventsSubscribed = {Lazy<Unit>} ThreadSafetyMode=PublicationOnly, IsValueCreated=false, IsValueFaulted=false, Value=()
 _propertyChangingEventsSubscribed = {Lazy<Unit>} ThreadSafetyMode=PublicationOnly, IsValueCreated=false, IsValueFaulted=false, Value=()
 _thrownExceptions = {Lazy<IObservable<Exception>>} ThreadSafetyMode=null, IsValueCreated=true, IsValueFaulted=false, Value=ScheduledSubject<Exception>

Copy link
Contributor

@soosr soosr left a comment

Choose a reason for hiding this comment

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

Couldn't continue the testing due to the issues above.

Copy link
Contributor

@soosr soosr left a comment

Choose a reason for hiding this comment

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

History initial sorting is wrong

Copy link
Contributor

@soosr soosr left a comment

Choose a reason for hiding this comment

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

Speeding up a self spend, doesn't work properly. It should have replaced the original transaction in the history, instead of adding new items.
image

Same is true for canceling. (Order is wrong too, but that doesn't matter)
image

Child items order is wrong in a CPFP Speed up.
image

@soosr
Copy link
Contributor

soosr commented Oct 24, 2023

@ichthus1604 @SuperJMN What's the status of this PR?

@SuperJMN
Copy link
Contributor

@ichthus1604 @SuperJMN What's the status of this PR?

As of this weekend, it still had some problems with speed up. Not sure if @ichthus1604 has fixed it, though.
I'll ask him when he's available to offer some help.

@soosr
Copy link
Contributor

soosr commented Oct 24, 2023

Speeding up a self spend, doesn't work properly. It should have replaced the original transaction in the history, instead of adding new items. image

Same is true for canceling. (Order is wrong too, but that doesn't matter) image

Child items order is wrong in a CPFP Speed up. image

Might be related: #11788

@ichthus1604
Copy link
Contributor Author

@soosr there is an issue I haven't identified yet, which causes the problem you described here. We've been doing pair debugging together with @SuperJMN several times in the last few days, and haven't been able to figure out the cause yet.

Basically, the Model returns a list of 2 items and the TDG shows 3. The root cause of this is yet unknown. The TransactionTreeBuilder logic returns the proper structure (self-spend showing as accelerated and with speedup child), but that's not reflected in the UI.

We will continue to debug this.

@SuperJMN
Copy link
Contributor

Should fix #11788

@SuperJMN
Copy link
Contributor

OK, here's the cause for the record:

The changesets we were generating could only contain additions or updates, but never deletions. Why? Because we always refreshed items in an additive way. Thus, items could be new or updated ONLY. We never actually compared the 'previous state' to the 'new state", so there was no way to know which items were deleted.

What I have done is precisely a new way of updating that generates a full list of diffs, by introducing a class that acts as a 'facilitator.' Underneath, it uses a SourceCache that actually manages all the differences for us.

If you have any more questions or need further assistance, feel free to ask.

@soosr
Copy link
Contributor

soosr commented Oct 25, 2023

The order of CPFP speed up children is still reversed:
image

I got a crash when I tried to speed up a transaction that I sent from wallet A to wallet B (both wallets are in Wasabi).

Exception type: System.ArgumentNullException

Message: Value cannot be null. (Parameter 'parent')

Stack Trace:    at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.CreateViewModel(TransactionModel transaction, HistoryItemViewModelBase parent) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 246
   at WalletWasabi.Fluent.ViewModels.Wallets.Home.History.HistoryViewModel.<OnActivated>b__17_1(TransactionModel x) in WalletWasabi.Fluent\ViewModels\Wallets\Home\History\HistoryViewModel.cs:line 223
   at DynamicData.Cache.Internal.Transform`3.<RunImpl>b__6_0(ChangeAwareCache`2 cache, IChangeSet`2 changes) in /_/src/DynamicData/Cache/Internal/Transform.cs:line 95
   at System.Reactive.Linq.ObservableImpl.Scan`2._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs:line 49
--- End of stack trace from previous location ---
   at System.Reactive.PlatformServices.ExceptionServicesImpl.Rethrow(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServicesImpl.cs:line 19
   at System.Reactive.ExceptionHelpers.Throw(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServices.cs:line 16
   at System.Reactive.Stubs.<>c.<.cctor>b__2_1(Exception ex) in /_/Rx.NET/Source/src/System.Reactive/Internal/Stubs.cs:line 16
   at System.Reactive.AnonymousObserver`1.OnErrorCore(Exception error) in /_/Rx.NET/Source/src/System.Reactive/AnonymousObserver.cs:line 73
   at System.Reactive.ObserverBase`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/ObserverBase.cs:line 59
   at System.Reactive.AutoDetachObserver`1.OnErrorCore(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs:line 77
   at System.Reactive.ObserverBase`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/ObserverBase.cs:line 59
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Concurrency.Synchronize`1._.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.Synchronize.cs:line 50
   at System.Reactive.AutoDetachObserver`1.OnErrorCore(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs:line 77
   at System.Reactive.ObserverBase`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/ObserverBase.cs:line 59
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Sink`2.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 94
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Linq.ObservableImpl.Scan`2._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs:line 49
   at System.Reactive.AutoDetachObserver`1.OnNextCore(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs:line 71
   at System.Reactive.Subjects.Subject`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/Subject.cs:line 141
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at DynamicData.Binding.ObservableCollectionAdaptor`2.Adapt(IChangeSet`2 changes, IObservableCollection`1 collection) in /_/src/DynamicData/Binding/ObservableCollectionAdaptor.cs:line 112
   at DynamicData.ObservableCacheEx.<>c__DisplayClass26_0`2.<Bind>b__1(IChangeSet`2 changes) in /_/src/DynamicData/Cache/ObservableCacheEx.cs:line 642
   at System.Reactive.Linq.ObservableImpl.Select`2.Selector._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs:line 48
--- End of stack trace from previous location ---
   at System.Reactive.PlatformServices.ExceptionServicesImpl.Rethrow(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServicesImpl.cs:line 19
   at System.Reactive.ExceptionHelpers.Throw(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServices.cs:line 16
   at System.Reactive.Stubs.<>c.<.cctor>b__2_1(Exception ex) in /_/Rx.NET/Source/src/System.Reactive/Internal/Stubs.cs:line 16
   at System.Reactive.AnonymousObserver`1.OnErrorCore(Exception error) in /_/Rx.NET/Source/src/System.Reactive/AnonymousObserver.cs:line 73
   at System.Reactive.ObserverBase`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/ObserverBase.cs:line 59
   at System.Reactive.AutoDetachObserver`1.OnErrorCore(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs:line 77
   at System.Reactive.ObserverBase`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/ObserverBase.cs:line 59
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Linq.ObservableImpl.Select`2.Selector._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs:line 48
   at System.Reactive.Concurrency.Synchronize`1._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.Synchronize.cs:line 44
   at System.Reactive.AutoDetachObserver`1.OnNextCore(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs:line 71
   at System.Reactive.Subjects.Subject`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/Subject.cs:line 141
   at DynamicData.ObservableCache`2.InvokeNext(ChangeSet`2 changes) in /_/src/DynamicData/Cache/ObservableCache.cs:line 239
   at DynamicData.ObservableCache`2.UpdateFromSource(Action`1 updateAction) in /_/src/DynamicData/Cache/ObservableCache.cs:line 226
   at WalletWasabi.Fluent.Helpers.SignaledFetcher`2.<>c__DisplayClass1_1.<.ctor>b__1(IEnumerable`1 items) in WalletWasabi.Fluent\Helpers\SignaledFetcher.cs:line 20
   at System.Reactive.Linq.ObservableImpl.Do`1.OnNext._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs:line 47
--- End of stack trace from previous location ---
   at System.Reactive.PlatformServices.ExceptionServicesImpl.Rethrow(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServicesImpl.cs:line 19
   at System.Reactive.ExceptionHelpers.Throw(Exception exception) in /_/Rx.NET/Source/src/System.Reactive/Internal/ExceptionServices.cs:line 16
   at System.Reactive.Stubs.<>c.<.cctor>b__2_1(Exception ex) in /_/Rx.NET/Source/src/System.Reactive/Internal/Stubs.cs:line 16
   at System.Reactive.AnonymousSafeObserver`1.OnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/AnonymousSafeObserver.cs:line 62
   at System.Reactive.Sink`1.ForwardOnError(Exception error) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 60
   at System.Reactive.Linq.ObservableImpl.Do`1.OnNext._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs:line 47
   at System.Reactive.ObserveOnObserverNew`1.DrainStep(ConcurrentQueue`1 q) in /_/Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs:line 573
   at System.Reactive.ObserveOnObserverNew`1.DrainShortRunning(IScheduler recursiveScheduler) in /_/Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs:line 516
   at Avalonia.ReactiveUI.AvaloniaScheduler.<>c__DisplayClass4_1`1.<Schedule>b__1()
   at Avalonia.Threading.DispatcherOperation.InvokeCore()
   at Avalonia.Threading.DispatcherOperation.Execute()
   at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation job)
   at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean fromExplicitBackgroundProcessingCallback)
   at Avalonia.Threading.Dispatcher.Signaled()
   at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam)
   at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG& lpmsg)
   at Avalonia.Win32.Win32DispatcherImpl.RunLoop(CancellationToken cancellationToken)
   at Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl)
   at Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
   at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args)
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, ShutdownMode shutdownMode)
   at WalletWasabi.Fluent.Desktop.WasabiAppExtensions.<>c__DisplayClass0_0.<RunAsGuiAsync>b__0() in WalletWasabi.Fluent.Desktop\Program.cs:line 196
   at WalletWasabi.Daemon.WasabiApplication.RunAsync(Func`1 afterStarting) in WalletWasabi.Daemon\WasabiAppBuilder.cs:line 66
   at WalletWasabi.Fluent.Desktop.WasabiAppExtensions.RunAsGuiAsync(WasabiApplication app) in WalletWasabi.Fluent.Desktop\Program.cs:line 150
   at WalletWasabi.Fluent.Desktop.Program.Main(String[] args) in WalletWasabi.Fluent.Desktop\Program.cs:line 63

Inner Exception: 

@ichthus1604
Copy link
Contributor Author

@soosr Latest commit fixes the crash.

Credit to @SuperJMN for fixing the sorting issue ;)

Copy link
Contributor

@soosr soosr left a comment

Choose a reason for hiding this comment

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

tACK

@soosr soosr merged commit d998765 into WalletWasabi:master Oct 25, 2023
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants