public static ImmutableList <TimeSpan> SamplePoissonDelays(this TimeSpan timeFrame, int numberOfEvents) { using var random = new SecureRandom(); TimeSpan Sample(int milliseconds) => milliseconds <= 0 ? TimeSpan.Zero : TimeSpan.FromMilliseconds(random.GetInt(0, milliseconds)); return(Enumerable .Range(0, numberOfEvents) .Select(_ => 0.8 * Sample((int)timeFrame.TotalMilliseconds)) .OrderBy(t => t) .ToImmutableList()); }
public static ImmutableList <DateTimeOffset> SamplePoisson(this TimeSpan timeFrame, int numberOfEvents) { var startTime = DateTimeOffset.UtcNow; using var random = new SecureRandom(); TimeSpan Sample(int milliseconds) => milliseconds <= 0 ? TimeSpan.Zero : TimeSpan.FromMilliseconds(random.GetInt(0, milliseconds)); return(Enumerable .Range(0, numberOfEvents) .Select(_ => startTime + (0.8 * Sample((int)timeFrame.TotalMilliseconds))) .OrderBy(t => t) .ToImmutableList()); }
ProceedWithSigningStateAsync(uint256 roundId, ImmutableArray <AliceClient> registeredAliceClients, IEnumerable <TxOut> outputTxOuts, CancellationToken cancellationToken) { // Signing. var roundState = await RoundStatusUpdater.CreateRoundAwaiter(roundId, Phase.TransactionSigning, cancellationToken).ConfigureAwait(false); var remainingTime = roundState.CoinjoinState.Parameters.TransactionSigningTimeout - RoundStatusUpdater.Period; var signingStateEndTime = DateTimeOffset.UtcNow + remainingTime; CoinJoinClientProgress.SafeInvoke(this, new EnteringSigningPhase(roundState, signingStateEndTime)); using CancellationTokenSource phaseTimeoutCts = new(remainingTime + ExtraPhaseTimeoutMargin); using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, phaseTimeoutCts.Token); roundState.LogDebug($"Transaction signing phase started - it will end in: {signingStateEndTime - DateTimeOffset.UtcNow:hh\\:mm\\:ss}."); var signingState = roundState.Assert <SigningState>(); var unsignedCoinJoin = signingState.CreateUnsignedTransaction(); // If everything is okay, then sign all the inputs. Otherwise, in case there are missing outputs, the server is // lying (it lied us before when it responded with 200 OK to the OutputRegistration requests or it is lying us // now when we identify as satoshi. // In this scenario we should ban the coordinator and stop dealing with it. // see more: https://github.com/zkSNACKs/WalletWasabi/issues/8171 bool mustSignAllInputs = SanityCheck(outputTxOuts, unsignedCoinJoin); if (!mustSignAllInputs) { roundState.LogInfo($"There are missing outputs. A subset of inputs will be signed."); } // Send signature. var combinedToken = linkedCts.Token; var alicesToSign = mustSignAllInputs ? registeredAliceClients : registeredAliceClients.RemoveAt(SecureRandom.GetInt(0, registeredAliceClients.Length)); await SignTransactionAsync(alicesToSign, unsignedCoinJoin, signingStateEndTime, combinedToken).ConfigureAwait(false); roundState.LogDebug($"{alicesToSign.Length} out of {registeredAliceClients.Length} Alices have signed the coinjoin tx."); return(unsignedCoinJoin, alicesToSign); }