public void AddOrReplaceRound(CcjClientRound round) { lock (StateLock) { foreach (var r in Rounds.Where(x => x.State.RoundId == round.State.RoundId)) { r?.Registration?.AliceClient?.Dispose(); Logger.LogInfo <CcjClientState>($"Round ({round.State.RoundId}) removed. Reason: It's being replaced."); } Rounds.RemoveAll(x => x.State.RoundId == round.State.RoundId); Rounds.Add(round); Logger.LogInfo <CcjClientState>($"Round ({round.State.RoundId}) added."); } }
public void UpdateRoundsByStates(ConcurrentDictionary <TxoRef, IEnumerable <HdPubKeyBlindedPair> > exposedLinks, params CcjRunningRoundState[] allRunningRoundsStates) { Guard.NotNullOrEmpty(nameof(allRunningRoundsStates), allRunningRoundsStates); IsInErrorState = false; lock (StateLock) { // Find the rounds those aren't running anymore // Put their coins back to the waiting list // Remove them // Find the rounds those needs to be updated // Update them IEnumerable <long> roundsToRemove = Rounds.Select(x => x.State.RoundId).Where(y => !allRunningRoundsStates.Select(z => z.RoundId).Contains(y)); foreach (CcjClientRound round in Rounds.Where(x => roundsToRemove.Contains(x.State.RoundId))) { var newSuccessfulRoundCount = allRunningRoundsStates.FirstOrDefault()?.SuccessfulRoundCount; bool roundFailed = newSuccessfulRoundCount != null && round.State.SuccessfulRoundCount == newSuccessfulRoundCount; if (roundFailed) { IsInErrorState = true; } foreach (SmartCoin coin in round.CoinsRegistered) { if (round.Registration.IsPhaseActionsComleted(CcjRoundPhase.Signing)) { var delayRegistration = TimeSpan.FromSeconds(60); WaitingList.Add(coin, DateTimeOffset.UtcNow + delayRegistration); Logger.LogInfo <CcjClientState>($"Coin added to the waiting list: {coin.Index}:{coin.TransactionId}, but its registration is not allowed till {delayRegistration.TotalSeconds} seconds, because this coin might already be spent."); if (roundFailed) { // Cleanup non-exposed links. foreach (TxoRef input in round.Registration.CoinsRegistered.Select(x => x.GetTxoRef())) { if (exposedLinks.ContainsKey(input)) // This should always be the case. { exposedLinks[input] = exposedLinks[input].Where(x => !x.IsBlinded); } } } } else { WaitingList.Add(coin, DateTimeOffset.UtcNow); Logger.LogInfo <CcjClientState>($"Coin added to the waiting list: {coin.Index}:{coin.TransactionId}."); } } round?.Registration?.AliceClient?.Dispose(); Logger.LogInfo <CcjClientState>($"Round ({round.State.RoundId}) removed. Reason: It's not running anymore."); } Rounds.RemoveAll(x => roundsToRemove.Contains(x.State.RoundId)); foreach (CcjClientRound round in Rounds) { if (allRunningRoundsStates.Select(x => x.RoundId).Contains(round.State.RoundId)) { round.State = allRunningRoundsStates.Single(x => x.RoundId == round.State.RoundId); } } foreach (CcjRunningRoundState state in allRunningRoundsStates) { if (!Rounds.Select(x => x.State.RoundId).Contains(state.RoundId)) { var r = new CcjClientRound(state); Rounds.Add(r); Logger.LogInfo <CcjClientState>($"Round ({r.State.RoundId}) added."); } } } }