public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer) { Nodes = nodes; Synchronizer = synchronizer; HashChain = synchronizer.BitcoinStore.HashChain; UseTor = Global.Config.UseTor; // Do not make it dynamic, because if you change this config settings only next time will it activate. UseBitcoinCore = Global.Config.StartLocalBitcoinCoreOnStartup; var hostedServices = Global.HostedServices; var updateChecker = hostedServices.FirstOrDefault <UpdateChecker>(); Guard.NotNull(nameof(updateChecker), updateChecker); UpdateStatus = updateChecker.UpdateStatus; var rpcMonitor = hostedServices.FirstOrDefault <RpcMonitor>(); BitcoinCoreStatus = rpcMonitor?.RpcStatus ?? RpcStatus.Unresponsive; _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.Status) .DisposeWith(Disposables); Observable .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added)).Select(x => true) .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)).Select(x => true) .Merge(Synchronizer.WhenAnyValue(x => x.TorStatus).Select(x => true)))) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => Peers = Synchronizer.TorStatus == TorStatus.NotRunning ? 0 : Nodes.Count) // Set peers to 0 if Tor is not running, because we get Tor status from backend answer so it seems to the user that peers are connected over clearnet, while they are not. .DisposeWith(Disposables); Peers = Tor == TorStatus.NotRunning ? 0 : Nodes.Count; Observable.FromEventPattern <bool>(typeof(WalletService), nameof(WalletService.DownloadingBlockChanged)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => DownloadingBlock = x.EventArgs) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.TorStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(status => Tor = UseTor ? status : TorStatus.TurnedOff) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.BackendStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => Backend = Synchronizer.BackendStatus) .DisposeWith(Disposables); _filtersLeft = HashChain.WhenAnyValue(x => x.HashesLeft) .Throttle(TimeSpan.FromMilliseconds(100)) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.FiltersLeft) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.UsdExchangeRate) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(usd => BtcPrice = $"${(long)usd}") .DisposeWith(Disposables); if (rpcMonitor is { })
private static void AssertEverythingDefault(HashChain hashChain) { Assert.Equal(0, hashChain.HashCount); Assert.Equal(0, hashChain.HashesLeft); Assert.Equal(0, hashChain.ServerTipHeight); Assert.Null(hashChain.TipHash); Assert.Equal(0, hashChain.TipHeight); }
public void Constructor4Test() { HashChain chain = new HashChain(new Crc(CrcParameters.GetParameters(CrcStandard.Crc32Bit)), TestVectors.Battery.NumericRepeated, 0, 10, 5); for (int i = 0; i < NumericCrc32VectorChain.Length; i++) { CustomAssert.AreEqual(NumericCrc32VectorChain[i], chain[i]); } }
public void Enumerator1Test() { HashChain chain = new HashChain(new Crc(CrcParameters.GetParameters(CrcStandard.Crc32Bit)), TestVectors.Battery.Numeric); int i = 0; foreach (byte[] hash in chain) { CustomAssert.AreEqual(NumericCrc32VectorChain[i], hash); i++; } }
public void Enumerator3Test() { HashChain chain = new HashChain(new Crc(CrcParameters.GetParameters(CrcStandard.Crc32Bit)), TestVectors.Battery.Numeric); IEnumerator e = ((IEnumerable)chain).GetEnumerator(); int i = 0; while (e.MoveNext()) { CustomAssert.AreEqual(NumericCrc32VectorChain[i], (byte[])e.Current); i++; } }
public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker) { Nodes = nodes; Synchronizer = synchronizer; HashChain = synchronizer.BitcoinStore.HashChain; UseTor = Global.Config.UseTor.Value; // Don't make it dynamic, because if you change this config settings only next time will it activate. _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.Status) .DisposeWith(Disposables); Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); SetPeers(Nodes.Count); Observable.FromEventPattern <int>(typeof(WalletService), nameof(WalletService.ConcurrentBlockDownloadNumberChanged)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { BlocksLeft = x.EventArgs; }).DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.TorStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(status => { SetTor(status); SetPeers(Nodes.Count); }).DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.BackendStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { Backend = Synchronizer.BackendStatus; }).DisposeWith(Disposables); _filtersLeft = HashChain.WhenAnyValue(x => x.HashesLeft) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.FiltersLeft) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.UsdExchangeRate) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(usd => { BtcPrice = $"${(long)usd}"; }).DisposeWith(Disposables); Observable.FromEventPattern <bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(e => { OnResponseArrivedIsGenSocksServFail(e.EventArgs); }).DisposeWith(Disposables); this.WhenAnyValue(x => x.FiltersLeft, x => x.BlocksLeft) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(tup => { (int filtersLeft, int blocksLeft) = tup.ToValueTuple(); if (filtersLeft == 0 && blocksLeft == 0) { TryRemoveStatus(StatusBarStatus.Synchronizing); } else { TryAddStatus(StatusBarStatus.Synchronizing); } }); this.WhenAnyValue(x => x.Tor, x => x.Backend, x => x.Peers) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(tup => { (TorStatus tor, BackendStatus backend, int peers) = tup.ToValueTuple(); if (tor == TorStatus.NotRunning || backend != BackendStatus.Connected || peers < 1) { TryAddStatus(StatusBarStatus.Connecting); } else { TryRemoveStatus(StatusBarStatus.Connecting); } }); this.WhenAnyValue(x => x.UpdateStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { if (x == UpdateStatus.Critical) { TryAddStatus(StatusBarStatus.CriticalUpdate); } else { TryRemoveStatus(StatusBarStatus.CriticalUpdate); } if (x == UpdateStatus.Optional) { TryAddStatus(StatusBarStatus.OptionalUpdate); } else { TryRemoveStatus(StatusBarStatus.OptionalUpdate); } }); UpdateCommand = ReactiveCommand.Create(() => { try { IoHelpers.OpenBrowser("https://wasabiwallet.io/#download"); } catch (Exception ex) { Logging.Logger.LogWarning <StatusBarViewModel>(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } }, this.WhenAnyValue(x => x.UpdateStatus) .ObserveOn(RxApp.MainThreadScheduler) .Select(x => x != UpdateStatus.Latest)); this.RaisePropertyChanged(nameof(UpdateCommand)); // The binding happens after the constructor. So, if the command is not in constructor, then we need this line. updateChecker.Start(TimeSpan.FromMinutes(7), () => { UpdateStatus = UpdateStatus.Critical; return(Task.CompletedTask); }, () => { if (UpdateStatus != UpdateStatus.Critical) { UpdateStatus = UpdateStatus.Optional; } return(Task.CompletedTask); }); }
public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker) { Nodes = nodes; Synchronizer = synchronizer; HashChain = synchronizer.BitcoinStore.HashChain; UseTor = Global.Config.UseTor.Value; // Don't make it dynamic, because if you change this config settings only next time will it activate. Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added)) .Subscribe(x => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)) .Subscribe(x => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); SetPeers(Nodes.Count); Observable.FromEventPattern <int>(typeof(WalletService), nameof(WalletService.ConcurrentBlockDownloadNumberChanged)) .Subscribe(x => { BlocksLeft = x.EventArgs; }).DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.TorStatus).Subscribe(status => { SetTor(status); SetPeers(Nodes.Count); }).DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.BackendStatus).Subscribe(_ => { Backend = Synchronizer.BackendStatus; }).DisposeWith(Disposables); HashChain.WhenAnyValue(x => x.HashesLeft).Subscribe(x => { FiltersLeft = x; }).DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Subscribe(usd => { BtcPrice = $"${(long)usd}"; }).DisposeWith(Disposables); Observable.FromEventPattern <bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail)) .Subscribe(e => { OnResponseArrivedIsGenSocksServFail(e.EventArgs); }).DisposeWith(Disposables); this.WhenAnyValue(x => x.BlocksLeft).Subscribe(blocks => { RefreshStatus(); }); this.WhenAnyValue(x => x.FiltersLeft).Subscribe(filters => { RefreshStatus(); }); this.WhenAnyValue(x => x.Tor).Subscribe(tor => { RefreshStatus(); }); this.WhenAnyValue(x => x.Backend).Subscribe(backend => { RefreshStatus(); }); this.WhenAnyValue(x => x.Peers).Subscribe(peers => { RefreshStatus(); }); this.WhenAnyValue(x => x.UpdateStatus).Subscribe(_ => { RefreshStatus(); }); UpdateCommand = ReactiveCommand.Create(() => { try { IoHelpers.OpenBrowser("https://wasabiwallet.io/#download"); } catch (Exception ex) { Logging.Logger.LogWarning <StatusBarViewModel>(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } }, this.WhenAnyValue(x => x.UpdateStatus).Select(x => x != UpdateStatus.Latest)); updateChecker.Start(TimeSpan.FromMinutes(7), () => { UpdateStatus = UpdateStatus.Critical; return(Task.CompletedTask); }, () => { if (UpdateStatus != UpdateStatus.Critical) { UpdateStatus = UpdateStatus.Optional; } return(Task.CompletedTask); }); }
public void HashChainTests() { var hashChain = new HashChain(); // ASSERT PROPERTIES // Assert everything is default value. AssertEverythingDefault(hashChain); // ASSERT EVENTS // Assert some functions does not raise any events when default. Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashCount), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHash), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHeight), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); // Assert the correct events are thrown and not thrown when applicable. var newServerHeight = hashChain.ServerTipHeight + 1; Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), () => { // ASSERT FUNCTION // Assert update server height raises. hashChain.UpdateServerTipHeight(newServerHeight); }); newServerHeight++; Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), () => { // ASSERT FUNCTION // Assert update server height raises. hashChain.UpdateServerTipHeight(newServerHeight); }); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashCount), () => { // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. hashChain.UpdateServerTipHeight(newServerHeight); })); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHash), () => { // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. hashChain.UpdateServerTipHeight(newServerHeight); })); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHeight), () => { // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. hashChain.UpdateServerTipHeight(newServerHeight); })); var sameServerheight = newServerHeight; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), () => { // ASSERT FUNCTIONS // Assert update server height does not raise without actually changing. hashChain.UpdateServerTipHeight(sameServerheight); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), () => { // ASSERT FUNCTIONS // Assert update server height does not raise without actually changing. hashChain.UpdateServerTipHeight(sameServerheight); })); // ASSERT PROPERTIES Assert.Equal(0, hashChain.HashCount); var hashesLeft = sameServerheight; Assert.Equal(hashesLeft, hashChain.HashesLeft); Assert.Equal(hashesLeft, hashChain.ServerTipHeight); Assert.Null(hashChain.TipHash); Assert.Equal(0, hashChain.TipHeight); }
public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker) { Nodes = nodes; Synchronizer = synchronizer; HashChain = synchronizer.BitcoinStore.HashChain; UseTor = Global.Config.UseTor; // Do not make it dynamic, because if you change this config settings only next time will it activate. _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.Status) .DisposeWith(Disposables); Observable .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added)).Select(x => true) .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)).Select(x => true) .Merge(Synchronizer.WhenAnyValue(x => x.TorStatus).Select(x => true)))) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => Peers = Synchronizer.TorStatus == TorStatus.NotRunning ? 0 : Nodes.Count) // Set peers to 0 if Tor is not running, because we get Tor status from backend answer so it seems to the user that peers are connected over clearnet, while they are not. .DisposeWith(Disposables); Peers = Tor == TorStatus.NotRunning ? 0 : Nodes.Count; Observable.FromEventPattern <bool>(typeof(WalletService), nameof(WalletService.DownloadingBlockChanged)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => DownloadingBlock = x.EventArgs) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.TorStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(status => Tor = UseTor ? status : TorStatus.TurnedOff) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.BackendStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => Backend = Synchronizer.BackendStatus) .DisposeWith(Disposables); _filtersLeft = HashChain.WhenAnyValue(x => x.HashesLeft) .Throttle(TimeSpan.FromMilliseconds(100)) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.FiltersLeft) .DisposeWith(Disposables); Synchronizer.WhenAnyValue(x => x.UsdExchangeRate) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(usd => BtcPrice = $"${(long)usd}") .DisposeWith(Disposables); Observable.FromEventPattern <bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(e => OnResponseArrivedIsGenSocksServFail(e.EventArgs)) .DisposeWith(Disposables); this.WhenAnyValue(x => x.FiltersLeft, x => x.DownloadingBlock) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(tup => { (int filtersLeft, bool downloadingBlock) = tup.ToValueTuple(); if (filtersLeft == 0 && !downloadingBlock) { TryRemoveStatus(StatusBarStatus.Synchronizing); } else { TryAddStatus(StatusBarStatus.Synchronizing); } }); this.WhenAnyValue(x => x.Tor, x => x.Backend, x => x.Peers) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(tup => { (TorStatus tor, BackendStatus backend, int peers) = tup.ToValueTuple(); if (tor == TorStatus.NotRunning || backend != BackendStatus.Connected || peers < 1) { TryAddStatus(StatusBarStatus.Connecting); } else { TryRemoveStatus(StatusBarStatus.Connecting); } }); this.WhenAnyValue(x => x.UpdateStatus) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { if (x == UpdateStatus.Critical) { TryAddStatus(StatusBarStatus.CriticalUpdate); } else { TryRemoveStatus(StatusBarStatus.CriticalUpdate); } if (x == UpdateStatus.Optional) { TryAddStatus(StatusBarStatus.OptionalUpdate); } else { TryRemoveStatus(StatusBarStatus.OptionalUpdate); } }); UpdateCommand = ReactiveCommand.Create(() => { try { IoHelpers.OpenBrowser("https://wasabiwallet.io/#download"); } catch (Exception ex) { Logger.LogWarning(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel(Global)); } }, this.WhenAnyValue(x => x.UpdateStatus) .ObserveOn(RxApp.MainThreadScheduler) .Select(x => x != UpdateStatus.Latest)); this.RaisePropertyChanged(nameof(UpdateCommand)); // The binding happens after the constructor. So, if the command is not in constructor, then we need this line. Observable.FromEventPattern <UpdateStatusResult>(updateChecker, nameof(updateChecker.UpdateChecked)) .Select(x => x.EventArgs) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { if (x.BackendCompatible) { if (x.ClientUpToDate) { UpdateStatus = UpdateStatus.Latest; } else { UpdateStatus = UpdateStatus.Optional; } } else { UpdateStatus = UpdateStatus.Critical; } UpdateAvailable = !x.ClientUpToDate; CriticalUpdateAvailable = !x.BackendCompatible; }).DisposeWith(Disposables); updateChecker.Start(TimeSpan.FromMinutes(7)); }
public void ConstructorBadHasherTest() { HashChain chain = new HashChain(null, TestVectors.Battery.Numeric); }
public void BadIndexTest() { HashChain chain = new HashChain(new Crc(CrcParameters.GetParameters(CrcStandard.Crc32Bit)), TestVectors.Battery.Numeric); byte[] test = chain[-1]; }
public void ConstructorBadInitTest() { HashChain chain = new HashChain(new Crc(CrcParameters.GetParameters(CrcStandard.Crc32Bit)), TestVectors.Battery.Numeric, 0); }