Refactor back end
MODIFY
HiddenWallet.Daemon/Wrappers/WalletWrapper.cs
HiddenWallet.Daemon/Wrappers/WalletWrapper.cs
@@ -90,17 +90,13 @@ namespace HiddenWallet.Daemon.Wrappers
WalletJob = new WalletJob();
await WalletJob.InitializeAsync(Tor.SocksPortHandler, Tor.ControlPortClient, safe, trackDefaultSafe: false, accountsToTrack: new SafeAccount[] { AliceAccount, BobAccount });
- WalletJob.StateChanged += _walletJob_StateChanged;
+ WalletJob.StateChanged += WalletJob_StateChanged;
+ WalletJob.MemPoolJob.NewTransaction += MemPoolJob_NewTransaction;
+ WalletJob.HeaderHeightChanged += WalletJob_HeaderHeightChanged;
+ (await WalletJob.GetTrackerAsync()).BestHeightChanged += WalletWrapper_BestHeightChanged;
+ WalletJob.ConnectedNodeCountChanged += WalletJob_ConnectedNodeCountChanged;
+ WalletJob.CoinJoinService.PeerCountChanged += CoinJoinService_PeerCountChanged;
- WalletJob.MempoolChanged += _walletJob_MempoolChanged;
-
- WalletJob.HeaderHeightChanged += _walletJob_HeaderHeightChanged;
-
- WalletJob.TrackerHeightAnnounce += _walletJob_TrackerHeightAnnounce;
-
- WalletJob.ConnectedNodeCountAnnounce += _walletJob_ConnectedNodeCountAnnounce;
-
- WalletJob.CoinJoinStatusChanged += _walletJob_CoinJoinStatusChanged;
(await WalletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;
@@ -124,6 +120,38 @@ namespace HiddenWallet.Daemon.Wrappers
}
}
+ private void WalletWrapper_BestHeightChanged(object sender, Height height)
+ {
+ NotificationBroadcaster.Instance.BroadcastTrackerHeight(height.Value.ToString());
+ }
+
+ private void WalletJob_StateChanged(object sender, EventArgs e)
+ {
+ _walletState = WalletJob.State.ToString();
+ NotificationBroadcaster.Instance.BroadcastWalletState(_walletState);
+ }
+
+ private void WalletJob_ConnectedNodeCountChanged(object sender, int count)
+ {
+ NotificationBroadcaster.Instance.BroadcastNodeCount(count.ToString());
+ }
+
+ private void WalletJob_HeaderHeightChanged(object sender, Height headerHeight)
+ {
+ NotificationBroadcaster.Instance.BroadcastHeaderHeight(headerHeight.Value.ToString());
+ }
+
+ private void MemPoolJob_NewTransaction(object sender, NewTransactionEventArgs e)
+ {
+ NotificationBroadcaster.Instance.BroadcastMempool(e.MempoolTxCount.ToString());
+ }
+
+ private void CoinJoinService_PeerCountChanged(object sender, int peerCount)
+ {
+ TumblerStatusResponse status = GetTumblerStatusResponse();
+ NotificationBroadcaster.Instance.BroadcastTumblerStatus(status);
+ }
+
public async Task RecoverAsync(string password, string mnemonic, string creationTime)
{
await Safe.RecoverAsync(
@@ -150,7 +178,6 @@ namespace HiddenWallet.Daemon.Wrappers
{
_changeBump++;
}
-
NotificationBroadcaster.Instance.BroadcastChangeBump();
}
@@ -170,7 +197,8 @@ namespace HiddenWallet.Daemon.Wrappers
}
else height = "";
- hra.Add(new HistoryRecordModel {
+ hra.Add(new HistoryRecordModel
+ {
Amount = rec.Amount.ToString(true, true),
Confirmed = rec.Confirmed,
Height = height,
@@ -226,38 +254,34 @@ namespace HiddenWallet.Daemon.Wrappers
_receiveResponseAlice.TraditionalAddress = (await WalletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2PublicKeyHash, AliceAccount, HdPathType.Receive)).FirstOrDefault().GetDestinationAddress(network).ToString();
_receiveResponseBob.TraditionalAddress = (await WalletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2PublicKeyHash, BobAccount, HdPathType.Receive)).FirstOrDefault().GetDestinationAddress(network).ToString();
}
- private void _walletJob_StateChanged(object sender, EventArgs e)
- {
- _walletState = WalletJob.State.ToString();
- NotificationBroadcaster.Instance.BroadcastWalletState(_walletState);
- }
- private void _walletJob_MempoolChanged(object sender, string count)
- {
- NotificationBroadcaster.Instance.BroadcastMempool(count);
- }
+ #endregion
- private void _walletJob_TrackerHeightAnnounce(object sender, string trackerHeight)
+ private volatile bool _endCalled = false;
+ public async Task EndAsync()
{
- NotificationBroadcaster.Instance.BroadcastTrackerHeight(trackerHeight);
- }
-
- private void _walletJob_HeaderHeightChanged(object sender, string headerHeight)
+ if (_endCalled) return;
+ _endCalled = true;
+ Console.WriteLine("Gracefully shutting down...");
+ if (WalletJob != null)
{
- NotificationBroadcaster.Instance.BroadcastHeaderHeight(headerHeight);
+ WalletJob.StateChanged -= WalletJob_StateChanged;
+ WalletJob.MemPoolJob.NewTransaction -= MemPoolJob_NewTransaction;
+ WalletJob.HeaderHeightChanged -= WalletJob_HeaderHeightChanged;
+ (await WalletJob.GetTrackerAsync()).BestHeightChanged -= WalletWrapper_BestHeightChanged;
+ WalletJob.ConnectedNodeCountChanged -= WalletJob_ConnectedNodeCountChanged;
+ WalletJob.CoinJoinService.PeerCountChanged -= CoinJoinService_PeerCountChanged;
+ (await WalletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged -= TrackedTransactions_CollectionChangedAsync;
}
- private void _walletJob_ConnectedNodeCountAnnounce(object sender, string nodeCount)
- {
- NotificationBroadcaster.Instance.BroadcastNodeCount(nodeCount);
- }
+ _cts.Cancel();
+ await Task.WhenAll(_walletJobTask);
- private void _walletJob_CoinJoinStatusChanged(object sender, EventArgs e)
- {
- TumblerStatusResponse status = GetTumblerStatusResponse();
- NotificationBroadcaster.Instance.BroadcastTumblerStatus(status);
+ Tor.Kill();
+
+ _cts?.Dispose();
+ _walletJobTask?.Dispose();
}
- #endregion
public TumblerStatusResponse GetTumblerStatusResponse()
{
@@ -271,7 +295,7 @@ namespace HiddenWallet.Daemon.Wrappers
var tas = tumblerStatus?.AnonymitySet ?? 0;
- var tnop = WalletJob.CoinJoinService?.NumberOfPeers ?? 0;
+ var tnop = WalletJob.CoinJoinService?.PeerCount ?? 0;
string tfr = "0";
try
@@ -316,32 +340,6 @@ namespace HiddenWallet.Daemon.Wrappers
}
}
- private volatile bool _endCalled = false;
- public async Task EndAsync()
- {
- if (_endCalled) return;
- _endCalled = true;
- Console.WriteLine("Gracefully shutting down...");
- if (WalletJob != null)
- {
- WalletJob.StateChanged -= _walletJob_StateChanged;
- WalletJob.MempoolChanged -= _walletJob_MempoolChanged;
- WalletJob.HeaderHeightChanged -= _walletJob_HeaderHeightChanged;
- WalletJob.TrackerHeightAnnounce -= _walletJob_TrackerHeightAnnounce;
- WalletJob.ConnectedNodeCountAnnounce -= _walletJob_ConnectedNodeCountAnnounce;
- WalletJob.CoinJoinStatusChanged -= _walletJob_CoinJoinStatusChanged;
- (await WalletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged -= TrackedTransactions_CollectionChangedAsync;
- }
-
- _cts.Cancel();
- await Task.WhenAll(_walletJobTask);
-
- Tor.Kill();
-
- _cts?.Dispose();
- _walletJobTask?.Dispose();
- }
-
public async Task<StatusResponse> GetStatusResponseAsync()
{
var ts = Tor.State.ToString();
@@ -379,7 +377,7 @@ namespace HiddenWallet.Daemon.Wrappers
var tas = tumblerStatus?.AnonymitySet ?? 0;
- var tnop = WalletJob.CoinJoinService?.NumberOfPeers ?? 0;
+ var tnop = WalletJob.CoinJoinService?.PeerCount ?? 0;
string tfr = "0";
try
@@ -404,7 +402,8 @@ namespace HiddenWallet.Daemon.Wrappers
var cb = _changeBump;
- return new StatusResponse {
+ return new StatusResponse
+ {
HeaderHeight = hh,
TrackingHeight = th,
ConnectedNodeCount = nc,
@@ -418,7 +417,8 @@ namespace HiddenWallet.Daemon.Wrappers
TumblerFeePerRound = tfr,
TumblerWaitedInInputRegistration = twiir,
TumblerPhase = tp,
- ChangeBump = cb };
+ ChangeBump = cb
+ };
}
else return new StatusResponse { HeaderHeight = 0, TrackingHeight = 0, ConnectedNodeCount = 0, MemPoolTransactionCount = 0, WalletState = WalletState.NotStarted.ToString(), TorState = ts, IsTumblerOnline = false, TumblerDenomination = "0", TumblerAnonymitySet = 0, TumblerNumberOfPeers = 0, TumblerFeePerRound = "0", TumblerWaitedInInputRegistration = 0, TumblerPhase = "", ChangeBump = 0 };
}

MODIFY
HiddenWallet.FullSpvWallet/ChaumianCoinJoin/CoinJoinService.cs
HiddenWallet.FullSpvWallet/ChaumianCoinJoin/CoinJoinService.cs
@@ -44,6 +44,25 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
public Money Denomination => Money.Parse(StatusResponse?.Denomination ?? "0");
public StatusResponse StatusResponse { get; set; }
+ private int _peerCount;
+ public int PeerCount
+ {
+ get
+ {
+ return _peerCount;
+ }
+ set
+ {
+ if (value != _peerCount)
+ {
+ _peerCount = value;
+ OnPeerCountChanged(value);
+ }
+ }
+ }
+ public event EventHandler<int> PeerCountChanged;
+ public void OnPeerCountChanged(int peerCount) => PeerCountChanged?.Invoke(this, peerCount);
+
public string UniqueAliceId { get; private set; }
public BitcoinWitPubKeyAddress ActiveOutput { get; private set; }
public BitcoinAddress ChangeOutput { get; private set; }
@@ -52,7 +71,6 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
public ConcurrentHashSet<Coin> Inputs { get; private set; }
public string UnblindedSignature { get; private set; }
public string RoundHash { get; private set; }
- private int _numberOfPeers;
public CoinJoinService(WalletJob walletJob)
{
@@ -75,19 +93,6 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
TumblerClient = new ChaumianTumblerClient(correctedAddress, handler, disposeHandler);
}
- public int NumberOfPeers
- {
- get { return _numberOfPeers; }
- private set
- {
- if (value != _numberOfPeers)
- {
- _numberOfPeers = value;
- WalletJob.OnCoinJoinStatusChanged();
- }
- }
- }
-
#region Notifications
public async Task SubscribeNotificationsAsync()
@@ -129,7 +134,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
{
var jObject = JObject.Parse(data);
var numberOfPeers = jObject.Value<int>("NewRegistration");
- NumberOfPeers = numberOfPeers;
+ PeerCount = numberOfPeers;
Debug.WriteLine($"Number of Tumbler peers: {numberOfPeers}");
});
@@ -147,7 +152,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
try
{
var inputRegistrationResponse = await TumblerClient.GetInputRegistrationStatusAsync(CancellationToken.None);
- NumberOfPeers = inputRegistrationResponse.RegisteredPeerCount;
+ PeerCount = inputRegistrationResponse.RegisteredPeerCount;
}
catch
{

MODIFY
HiddenWallet.FullSpvWallet/MemPool/MemPoolJob.cs
HiddenWallet.FullSpvWallet/MemPool/MemPoolJob.cs
@@ -13,10 +13,12 @@ namespace HiddenWallet.FullSpv.MemPool
public class NewTransactionEventArgs : EventArgs
{
public Transaction Transaction { get; }
+ public int MempoolTxCount { get; }
- public NewTransactionEventArgs(Transaction transaction)
+ public NewTransactionEventArgs(Transaction transaction, int mempoolTxCount)
{
Transaction = transaction;
+ MempoolTxCount = mempoolTxCount;
}
}
public class MemPoolJob
@@ -26,15 +28,12 @@ namespace HiddenWallet.FullSpv.MemPool
private ConcurrentHashSet<uint256> _notNeededTransactions = new ConcurrentHashSet<uint256>();
public event EventHandler<NewTransactionEventArgs> NewTransaction;
- private void OnNewTransaction(Transaction transaction) => NewTransaction?.Invoke(this, new NewTransactionEventArgs(transaction));
+ private void OnNewTransaction(Transaction transaction) => NewTransaction?.Invoke(this, new NewTransactionEventArgs(transaction, Transactions.Count));
public bool SyncedOnce { get; private set; } = false;
public event EventHandler Synced;
private void OnSynced() => Synced?.Invoke(this, EventArgs.Empty);
- public event EventHandler<string> MempoolChanged;
- private void OnMempoolChanged(string mempoolCount) => MempoolChanged?.Invoke(this, mempoolCount);
-
public bool ForcefullyStopped { get; set; } = false;
internal bool Enabled { get; set; } = true;
private bool ShouldNotRunYet => !Enabled || ForcefullyStopped || WalletJob.Nodes.ConnectedNodes.Count <= 3;
@@ -236,7 +235,6 @@ namespace HiddenWallet.FullSpv.MemPool
{
Transactions.TryRemove(tx);
}
- OnMempoolChanged(Transactions.Count.ToString());
}
public bool TryAddNewTransaction(Transaction tx)
@@ -249,7 +247,6 @@ namespace HiddenWallet.FullSpv.MemPool
{
if (Transactions.Add(hash))
{
- OnMempoolChanged(Transactions.Count.ToString());
OnNewTransaction(tx);
return true;
}

MODIFY
HiddenWallet.FullSpvWallet/Tracker.cs
HiddenWallet.FullSpvWallet/Tracker.cs
@@ -94,11 +94,11 @@ namespace HiddenWallet.FullSpv
{
if (_bestHeight == value) return;
_bestHeight = value;
- OnBestHeightChanged();
+ OnBestHeightChanged(value);
}
}
- public event EventHandler BestHeightChanged;
- private void OnBestHeightChanged() => BestHeightChanged?.Invoke(this, EventArgs.Empty);
+ public event EventHandler<Height> BestHeightChanged;
+ private void OnBestHeightChanged(Height height) => BestHeightChanged?.Invoke(this, height);
public int BlockCount => MerkleChain.Count;

MODIFY
HiddenWallet.FullSpvWallet/WalletJob.cs
HiddenWallet.FullSpvWallet/WalletJob.cs
@@ -84,13 +84,16 @@ namespace HiddenWallet.FullSpv
}
}
+ public event EventHandler<Height> HeaderHeightChanged;
+ private void OnHeaderHeightChanged(Height height) => HeaderHeightChanged?.Invoke(this, height);
+
public async Task<Height> GetBestHeightAsync()
{
var tracker = (await GetTrackerAsync());
return (await GetHeaderChainAsync()).Height < tracker.BestHeight ? Height.Unknown : tracker.BestHeight;
}
- public event EventHandler BestHeightChanged;
- private void OnBestHeightChanged() => BestHeightChanged?.Invoke(this, EventArgs.Empty);
+ public event EventHandler<int> BestHeightChanged;
+ private void OnBestHeightChanged(int height) => BestHeightChanged?.Invoke(this, height);
public int ConnectedNodeCount
{
@@ -108,14 +111,8 @@ namespace HiddenWallet.FullSpv
return Nodes.MaximumNodeConnection;
}
}
- public event EventHandler ConnectedNodeCountChanged;
- private void OnConnectedNodeCountChanged() => ConnectedNodeCountChanged?.Invoke(this, EventArgs.Empty);
-
- public event EventHandler<string> ConnectedNodeCountAnnounce;
- private void OnConnectedNodeCountAnnounce(string nodeCount) => ConnectedNodeCountAnnounce?.Invoke(this, nodeCount);
-
- public event EventHandler CoinJoinStatusChanged;
- public void OnCoinJoinStatusChanged() => CoinJoinStatusChanged?.Invoke(this, EventArgs.Empty);
+ public event EventHandler<int> ConnectedNodeCountChanged;
+ private void OnConnectedNodeCountChanged(int count) => ConnectedNodeCountChanged?.Invoke(this, count);
private WalletState _state;
public WalletState State
@@ -131,15 +128,6 @@ namespace HiddenWallet.FullSpv
public event EventHandler StateChanged;
private void OnStateChanged() => StateChanged?.Invoke(this, EventArgs.Empty);
- public event EventHandler<string> MempoolChanged;
- private void OnMempoolChanged(string mempoolCount) => MempoolChanged?.Invoke(this, mempoolCount);
-
- public event EventHandler<string> TrackerHeightAnnounce;
- private void OnTrackerHeightAnnounce(string trackerHeight) => TrackerHeightAnnounce?.Invoke(this, trackerHeight);
-
- public event EventHandler<string> HeaderHeightChanged;
- private void OnHeaderHeightChanged(string headerHeight) => HeaderHeightChanged?.Invoke(this, headerHeight);
-
private readonly AsyncLock _asyncLockSave = new AsyncLock();
private NodeConnectionParameters _connectionParameters;
public NodesGroup Nodes { get; private set; }
@@ -210,7 +198,7 @@ namespace HiddenWallet.FullSpv
return height;
}
- private async Task<ConcurrentChain> GetHeaderChainAsync()
+ public async Task<ConcurrentChain> GetHeaderChainAsync()
{
if (_connectionParameters != null)
{
@@ -305,11 +293,6 @@ namespace HiddenWallet.FullSpv
Nodes.ConnectedNodes.Removed += ConnectedNodes_Removed;
Nodes.ConnectedNodes.Added += ConnectedNodes_Added;
- MemPoolJob.MempoolChanged += MemPoolJob_MempoolChanged;
- Nodes.ConnectedNodes.Removed += ConnectedNodes_Removed;
-
- (await GetTrackerAsync()).BestHeightChanged += WalletJob_BestHeightChanged;
- (await GetTrackerAsync()).BestHeightChanged += WalletJob_HeightsChangedAsync;
}
private async void TrackedTransactions_CollectionChangedAsync(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
@@ -317,30 +300,14 @@ namespace HiddenWallet.FullSpv
await UpdateSafeTrackingAsync();
}
- private void WalletJob_BestHeightChanged(object sender, EventArgs e)
- {
- OnBestHeightChanged();
- }
-
- private async void WalletJob_HeightsChangedAsync(object sender, EventArgs e)
- {
- var tracker = (await GetTrackerAsync());
- var headerHeight = (await GetHeaderChainAsync()).Height;
- var trackerBestHeight = tracker.BestHeight;
- OnHeaderHeightChanged(headerHeight.ToString());
- OnTrackerHeightAnnounce(trackerBestHeight.ToString());
- }
-
private void ConnectedNodes_Added(object sender, NodeEventArgs e)
{
- OnConnectedNodeCountChanged();
- OnConnectedNodeCountAnnounce(Nodes.ConnectedNodes.Count().ToString());
+ OnConnectedNodeCountChanged(ConnectedNodeCount);
}
private void ConnectedNodes_Removed(object sender, NodeEventArgs e)
{
- OnConnectedNodeCountChanged();
- OnConnectedNodeCountAnnounce(Nodes.ConnectedNodes.Count().ToString());
+ OnConnectedNodeCountChanged(ConnectedNodeCount);
}
private async void MemPoolJob_NewTransactionAsync(object sender, NewTransactionEventArgs e)
@@ -369,13 +336,6 @@ namespace HiddenWallet.FullSpv
Debug.WriteLine("MemPool updated");
}
- private void MemPoolJob_MempoolChanged(object sender, string count)
- {
- {
- OnMempoolChanged(count);
- }
- }
-
public async Task StartAsync(CancellationToken ctsToken)
{
var tasks = new HashSet<Task>();
@@ -389,6 +349,7 @@ public async Task StartAsync(CancellationToken ctsToken)
tasks = new HashSet<Task>
{
PeriodicSaveAsync(TimeSpan.FromMinutes(3), ctsToken),
+ HeaderHeightMonitorAsync(TimeSpan.FromSeconds(1), ctsToken),
BlockDownloadingJobAsync(ctsToken),
MemPoolJob.StartAsync(ctsToken),
BlockDownloader.StartAsync(ctsToken),
@@ -405,9 +366,6 @@ public async Task StartAsync(CancellationToken ctsToken)
MemPoolJob.NewTransaction -= MemPoolJob_NewTransactionAsync;
Nodes.ConnectedNodes.Removed -= ConnectedNodes_Removed;
Nodes.ConnectedNodes.Added -= ConnectedNodes_Added;
- MemPoolJob.MempoolChanged -= MemPoolJob_MempoolChanged;
- (await GetTrackerAsync()).BestHeightChanged -= WalletJob_HeightsChangedAsync;
- (await GetTrackerAsync()).BestHeightChanged -= WalletJob_BestHeightChanged;
await SaveAllChangedAsync();
Nodes?.Dispose();
foreach (var task in tasks)
@@ -482,6 +440,35 @@ public async Task StartAsync(CancellationToken ctsToken)
#region Misc
+ private async Task HeaderHeightMonitorAsync(TimeSpan delay, CancellationToken ctsToken)
+ {
+ Height headerHeight = Height.Unknown;
+ while (true)
+ {
+ try
+ {
+ if (ctsToken.IsCancellationRequested) return;
+
+ var heightResult = await TryGetHeaderHeightAsync();
+ if (heightResult.Success)
+ {
+ if (heightResult.Height != headerHeight)
+ {
+ headerHeight = heightResult.Height;
+ OnHeaderHeightChanged(headerHeight);
+ }
+ }
+
+ await Task.Delay(delay, ctsToken).ContinueWith(tsk => { });
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"Ignoring {nameof(HeaderHeightMonitorAsync)} exception:");
+ Debug.WriteLine(ex);
+ }
+ }
+ }
+
/// <summary>
///
/// </summary>

Refactor back end