System.Collections.Generic.List.Add(uint256)

Here are the examples of the csharp api System.Collections.Generic.List.Add(uint256) taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

8 Examples 7

19 View Source File : PromiseClientSession.cs
License : MIT License
Project Creator : BreezeHub

public State GetInternalState()
        {
            State state = Serializer.Clone(InternalState);
            state.FakeSalts = null;
            state.FeeVariations = null;
            state.Commitments = null;
            if (_Hashes != null)
            {
                var commitments = new List<ServerCommitment>();
                var fakeSalts = new List<uint256>();
                var feeVariations = new List<Money>();
                for (int i = 0; i < _Hashes.Length; i++)
                {
                    commitments.Add(_Hashes[i].Commitment);
                    if (_Hashes[i] is FakeHash fake)
                    {
                        fakeSalts.Add(fake.Salt);
                    }

                    if (_Hashes[i] is RealHash real)
                    {
                        feeVariations.Add(real.FeeVariation);
                    }
                }

                state.FakeSalts = fakeSalts.ToArray();
                state.FeeVariations = feeVariations.ToArray();
                state.Commitments = commitments.ToArray();
            }

            return state;
        }

19 View Source File : PromiseClientSession.cs
License : MIT License
Project Creator : BreezeHub

public ClientRevelation Reveal(ServerCommitment[] commitments)
        {
            if (commitments == null)
                throw new ArgumentNullException(nameof(commitments));
            if (commitments.Length != Parameters.GetTotalTransactionsCount())
                throw new ArgumentException("Expecting " + Parameters.GetTotalTransactionsCount() + " commitments");
            replacedertState(PromiseClientStates.WaitingCommitments);

            List<uint256> salts = new List<uint256>();
            List<int> indexes = new List<int>();
            foreach (var fakeHash in _Hashes.OfType<FakeHash>())
            {
                salts.Add(fakeHash.Salt);
                indexes.Add(fakeHash.Index);
            }

            for (int i = 0; i < commitments.Length; i++)
            {
                _Hashes[i].Commitment = commitments[i];
            }

            InternalState.Status = PromiseClientStates.WaitingCommitmentsProof;
            return new ClientRevelation(indexes.ToArray(), InternalState.IndexSalt, salts.ToArray());
        }

19 View Source File : CoinJoinClient.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

private async Task<AliceClientBase> CreateAliceClientV3Async(long roundId, RoundStateResponseBase stateParam, List<OutPoint> registrableCoins, (HdPubKey change, IEnumerable<HdPubKey> actives) outputAddresses)
		{
			var state = stateParam as RoundStateResponse;
			SchnorrPubKey[] schnorrPubKeys = state.SchnorrPubKeys.ToArray();
			List<Requester> requesters = new List<Requester>();
			var blindedOutputScriptHashes = new List<uint256>();

			var registeredAddresses = new List<BitcoinAddress>();
			for (int i = 0; i < state.MixLevelCount; i++)
			{
				if (outputAddresses.actives.Count() <= i)
				{
					break;
				}

				BitcoinAddress address = outputAddresses.actives.Select(x => x.GetP2wpkhAddress(Network)).ElementAt(i);

				SchnorrPubKey schnorrPubKey = schnorrPubKeys[i];
				var outputScriptHash = new uint256(NBitcoin.Crypto.Hashes.SHA256(address.ScriptPubKey.ToBytes()));
				var requester = new Requester();
				uint256 blindedOutputScriptHash = requester.BlindMessage(outputScriptHash, schnorrPubKey);
				requesters.Add(requester);
				blindedOutputScriptHashes.Add(blindedOutputScriptHash);
				registeredAddresses.Add(address);
			}

			byte[] blindedOutputScriptHashesByte = ByteHelpers.Combine(blindedOutputScriptHashes.Select(x => x.ToBytes()));
			uint256 blindedOutputScriptsHash = new uint256(NBitcoin.Crypto.Hashes.SHA256(blindedOutputScriptHashesByte));

			var inputProofs = new List<InputProofModel>();
			foreach (OutPoint coinReference in registrableCoins)
			{
				SmartCoin coin = State.GetSingleOrDefaultFromWaitingList(coinReference);
				if (coin is null)
				{
					throw new NotSupportedException("This is impossible.");
				}

				coin.Secret ??= KeyManager.GetSecrets(SaltSoup(), coin.ScriptPubKey).Single();
				var inputProof = new InputProofModel
				{
					Input = coin.OutPoint,
					Proof = coin.Secret.PrivateKey.SignCompact(blindedOutputScriptsHash)
				};
				inputProofs.Add(inputProof);
			}

			return await AliceClientBase.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, Network, outputAddresses.change.GetP2wpkhAddress(Network), blindedOutputScriptHashes, inputProofs, CcjHostUriAction, TorSocks5EndPoint).ConfigureAwait(false);
		}

19 View Source File : Coordinator.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

private async void Round_StatusChangedAsync(object sender, CoordinatorRoundStatus status)
		{
			try
			{
				var round = sender as CoordinatorRound;

				// If success save the coinjoin.
				if (status == CoordinatorRoundStatus.Succeded)
				{
					uint256[] mempoolHashes = null;
					try
					{
						mempoolHashes = await RpcClient.GetRawMempoolAsync().ConfigureAwait(false);
					}
					catch (Exception ex)
					{
						Logger.LogError(ex);
					}

					using (await CoinJoinsLock.LockAsync().ConfigureAwait(false))
					{
						if (mempoolHashes is { })
						{
							var fallOuts = UnconfirmedCoinJoins.Where(x => !mempoolHashes.Contains(x));
							CoinJoins.RemoveAll(x => fallOuts.Contains(x));
							UnconfirmedCoinJoins.RemoveAll(x => fallOuts.Contains(x));
						}

						uint256 coinJoinHash = round.CoinJoin.GetHash();
						CoinJoins.Add(coinJoinHash);
						UnconfirmedCoinJoins.Add(coinJoinHash);
						LastSuccessfulCoinJoinTime = DateTimeOffset.UtcNow;
						await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }).ConfigureAwait(false);

						// When a round succeeded, adjust the denomination as to users still be able to register with the latest round's active output amount.
						IEnumerable<(Money value, int count)> outputs = round.CoinJoin.GetIndistinguishableOutputs(includeSingle: true);
						var bestOutput = outputs.OrderByDescending(x => x.count).FirstOrDefault();
						if (bestOutput != default)
						{
							Money activeOutputAmount = bestOutput.value;

							int currentConfirmationTarget = await AdjustConfirmationTargetAsync(lockCoinJoins: false).ConfigureAwait(false);
							var fees = await CoordinatorRound.CalculateFeesAsync(RpcClient, currentConfirmationTarget).ConfigureAwait(false);
							var feePerInputs = fees.feePerInputs;
							var feePerOutputs = fees.feePerOutputs;

							Money newDenominationToGetInWithactiveOutputs = activeOutputAmount - (feePerInputs + (2 * feePerOutputs));
							if (newDenominationToGetInWithactiveOutputs < RoundConfig.Denomination)
							{
								if (newDenominationToGetInWithactiveOutputs > Money.Coins(0.01m))
								{
									RoundConfig.Denomination = newDenominationToGetInWithactiveOutputs;
									RoundConfig.ToFile();
								}
							}
						}
					}
				}

				// If aborted in signing phase, then ban Alices that did not sign.
				if (status == CoordinatorRoundStatus.Aborted && round.Phase == RoundPhase.Signing)
				{
					IEnumerable<Alice> alicesDidntSign = round.GetAlicesByNot(AliceState.SignedCoinJoin, syncLock: false);

					CoordinatorRound nextRound = GetCurrentInputRegisterableRoundOrDefault(syncLock: false);

					if (nextRound != null)
					{
						int nextRoundAlicesCount = nextRound.CountAlices(syncLock: false);
						var alicesSignedCount = round.AnonymitySet - alicesDidntSign.Count();

						// New round's anonset should be the number of alices that signed in this round.
						// Except if the number of alices in the next round is already larger.
						var newAnonymitySet = Math.Max(alicesSignedCount, nextRoundAlicesCount);

						// But it cannot be larger than the current anonset of that round.
						newAnonymitySet = Math.Min(newAnonymitySet, nextRound.AnonymitySet);

						// Only change the anonymity set of the next round if new anonset does not equal and newanonset is larger than 1.
						if (nextRound.AnonymitySet != newAnonymitySet && newAnonymitySet > 1)
						{
							nextRound.UpdateAnonymitySet(newAnonymitySet, syncLock: false);

							if (nextRoundAlicesCount >= nextRound.AnonymitySet)
							{
								// Progress to the next phase, which will be OutputRegistration
								await nextRound.ExecuteNextPhaseAsync(RoundPhase.ConnectionConfirmation).ConfigureAwait(false);
							}
						}
					}

					foreach (Alice alice in alicesDidntSign) // Because the event sometimes is raised from inside the lock.
					{
						// If it is from any coinjoin, then do not ban.
						IEnumerable<OutPoint> utxosToBan = alice.Inputs.Select(x => x.Outpoint);
						await UtxoReferee.BanUtxosAsync(1, DateTimeOffset.UtcNow, forceNoted: false, round.RoundId, utxosToBan.ToArray()).ConfigureAwait(false);
					}
				}

				// If finished start a new round.
				if (status == CoordinatorRoundStatus.Aborted || status == CoordinatorRoundStatus.Succeded)
				{
					round.StatusChanged -= Round_StatusChangedAsync;
					round.PhaseChanged -= Round_PhaseChangedAsync;
					round.CoinJoinBroadcasted -= Round_CoinJoinBroadcasted;
					await MakeSureInputregistrableRoundRunningAsync().ConfigureAwait(false);
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning(ex);
			}
		}

19 View Source File : BlockNotifier.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

private void AddHeader(BlockHeader block)
		{
			ProcessedBlocks.Add(block.GetHash());
		}

19 View Source File : BlockchainController.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

[HttpGet("transaction-hexes")]
		[ProducesResponseType(200)]
		[ProducesResponseType(400)]
		public async Task<IActionResult> GetTransactionsAsync([FromQuery, Required] IEnumerable<string> transactionIds)
		{
			if (!ModelState.IsValid)
			{
				return BadRequest("Invalid transaction Ids.");
			}

			var maxTxToRequest = 10;
			if (transactionIds.Count() > maxTxToRequest)
			{
				return BadRequest($"Maximum {maxTxToRequest} transactions can be requested.");
			}

			var parsedIds = new List<uint256>();
			try
			{
				// Remove duplicates, do not use Distinct(), order is not guaranteed.
				foreach (var txid in transactionIds.Select(x => new uint256(x)))
				{
					if (!parsedIds.Contains(txid))
					{
						parsedIds.Add(txid);
					}
				}
			}
			catch
			{
				return BadRequest("Invalid transaction Ids.");
			}

			try
			{
				var hexes = new Dictionary<uint256, string>();
				var queryRpc = false;
				IRPCClient batchingRpc = null;
				List<Task<Transaction>> tasks = null;
				lock (TransactionHexCacheLock)
				{
					foreach (var txid in parsedIds)
					{
						if (TransactionHexCache.TryGetValue(txid, out string hex))
						{
							hexes.Add(txid, hex);
						}
						else
						{
							if (!queryRpc)
							{
								queryRpc = true;
								batchingRpc = RpcClient.PrepareBatch();
								tasks = new List<Task<Transaction>>();
							}
							tasks.Add(batchingRpc.GetRawTransactionAsync(txid));
						}
					}
				}

				if (queryRpc)
				{
					await batchingRpc.SendBatchAsync();

					foreach (var tx in await Task.WhenAll(tasks))
					{
						string hex = tx.ToHex();
						hexes.Add(tx.GetHash(), hex);

						lock (TransactionHexCacheLock)
						{
							if (TransactionHexCache.TryAdd(tx.GetHash(), hex) && TransactionHexCache.Count >= 1000)
							{
								TransactionHexCache.Remove(TransactionHexCache.Keys.First());
							}
						}
					}
				}

				// Order hexes according to the order of the query.
				var orderedResult = parsedIds.Where(x => hexes.ContainsKey(x)).Select(x => hexes[x]);
				return Ok(orderedResult);
			}
			catch (Exception ex)
			{
				Logger.LogDebug(ex);
				return BadRequest(ex.Message);
			}
		}

19 View Source File : ChaumianCoinJoinController.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

[HttpPost("inputs")]
		[ProducesResponseType(200)]
		[ProducesResponseType(400)]
		[ProducesResponseType(404)]
		public async Task<IActionResult> PostInputsAsync([FromBody, Required]InputsRequest request)
		{
			// Validate request.
			if (request.RoundId < 0 || !ModelState.IsValid)
			{
				return BadRequest("Invalid request.");
			}

			if (request.Inputs.Count() > 7)
			{
				return BadRequest("Maximum 7 inputs can be registered.");
			}

			using (await InputsLock.LockAsync())
			{
				CoordinatorRound round = Coordinator.TryGetRound(request.RoundId);

				if (round is null || round.Phase != RoundPhase.InputRegistration)
				{
					return NotFound("No such running round in InputRegistration. Try another round.");
				}

				// Do more checks.
				try
				{
					uint256[] blindedOutputs = request.BlindedOutputScripts.ToArray();
					int blindedOutputCount = blindedOutputs.Length;
					int maxBlindedOutputCount = round.MixingLevels.Count();
					if (blindedOutputCount > maxBlindedOutputCount)
					{
						return BadRequest($"Too many blinded output was provided: {blindedOutputCount}, maximum: {maxBlindedOutputCount}.");
					}

					if (blindedOutputs.Distinct().Count() < blindedOutputs.Length)
					{
						return BadRequest("Duplicate blinded output found.");
					}

					if (round.ContainsAnyBlindedOutputScript(blindedOutputs))
					{
						return BadRequest("Blinded output has already been registered.");
					}

					if (request.ChangeOutputAddress.Network != Network)
					{
						// RegTest and TestNet address formats are sometimes the same.
						if (Network == Network.Main)
						{
							return BadRequest($"Invalid ChangeOutputAddress Network.");
						}
					}

					var uniqueInputs = new HashSet<OutPoint>();
					foreach (InputProofModel inputProof in request.Inputs)
					{
						var outpoint = inputProof.Input;
						if (uniqueInputs.Contains(outpoint))
						{
							return BadRequest("Cannot register an input twice.");
						}
						uniqueInputs.Add(outpoint);
					}

					var alicesToRemove = new HashSet<Guid>();
					var getTxOutResponses = new List<(InputProofModel inputModel, Task<GetTxOutResponse> getTxOutTask)>();

					var batch = RpcClient.PrepareBatch();

					foreach (InputProofModel inputProof in request.Inputs)
					{
						if (round.ContainsInput(inputProof.Input, out List<Alice> tr))
						{
							alicesToRemove.UnionWith(tr.Select(x => x.UniqueId)); // Input is already registered by this alice, remove it later if all the checks are completed fine.
						}
						if (Coordinator.AnyRunningRoundContainsInput(inputProof.Input, out List<Alice> tnr))
						{
							if (tr.Union(tnr).Count() > tr.Count)
							{
								return BadRequest("Input is already registered in another round.");
							}
						}

						OutPoint outpoint = inputProof.Input;
						var bannedElem = await Coordinator.UtxoReferee.TryGetBannedAsync(outpoint, notedToo: false);
						if (bannedElem != null)
						{
							return BadRequest($"Input is banned from participation for {(int)bannedElem.BannedRemaining.TotalMinutes} minutes: {inputProof.Input.N}:{inputProof.Input.Hash}.");
						}

						var txOutResponseTask = batch.GetTxOutAsync(inputProof.Input.Hash, (int)inputProof.Input.N, includeMempool: true);
						getTxOutResponses.Add((inputProof, txOutResponseTask));
					}

					// Perform all RPC request at once
					await batch.SendBatchAsync();

					byte[] blindedOutputScriptHashesByte = ByteHelpers.Combine(blindedOutputs.Select(x => x.ToBytes()));
					uint256 blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedOutputScriptHashesByte));

					var inputs = new HashSet<Coin>();

					var allInputsConfirmed = true;
					foreach (var responses in getTxOutResponses)
					{
						var (inputProof, getTxOutResponseTask) = responses;
						var getTxOutResponse = await getTxOutResponseTask;

						// Check if inputs are unspent.
						if (getTxOutResponse is null)
						{
							return BadRequest($"Provided input is not unspent: {inputProof.Input.N}:{inputProof.Input.Hash}.");
						}

						// Check if unconfirmed.
						if (getTxOutResponse.Confirmations <= 0)
						{
							// If it spends a CJ then it may be acceptable to register.
							if (!await Coordinator.ContainsUnconfirmedCoinJoinAsync(inputProof.Input.Hash))
							{
								return BadRequest("Provided input is neither confirmed, nor is from an unconfirmed coinjoin.");
							}
							allInputsConfirmed = false;
						}

						// Check if immature.
						if (getTxOutResponse.IsCoinBase && getTxOutResponse.Confirmations <= 100)
						{
							return BadRequest("Provided input is immature.");
						}

						// Check if inputs are native segwit.
						if (getTxOutResponse.ScriptPubKeyType != "witness_v0_keyhash")
						{
							return BadRequest("Provided input must be witness_v0_keyhash.");
						}

						TxOut txOut = getTxOutResponse.TxOut;

						var address = (BitcoinWitPubKeyAddress)txOut.ScriptPubKey.GetDestinationAddress(Network);
						// Check if proofs are valid.
						if (!address.VerifyMessage(blindedOutputScriptsHash, inputProof.Proof))
						{
							return BadRequest("Provided proof is invalid.");
						}

						inputs.Add(new Coin(inputProof.Input, txOut));
					}

					if (!allInputsConfirmed)
					{
						// Check if mempool would accept a fake transaction created with the registered inputs.
						// Fake outputs: mixlevels + 1 maximum, +1 because there can be a change.
						var result = await RpcClient.TestMempoolAcceptAsync(inputs, fakeOutputCount: round.MixingLevels.Count() + 1, round.FeePerInputs, round.FeePerOutputs);
						if (!result.accept)
						{
							return BadRequest($"Provided input is from an unconfirmed coinjoin, but a limit is reached: {result.rejectReason}");
						}
					}

					var acceptedBlindedOutputScripts = new List<uint256>();

					// Calculate expected networkfee to pay after base denomination.
					int inputCount = inputs.Count;
					Money networkFeeToPayAfterBaseDenomination = (inputCount * round.FeePerInputs) + (2 * round.FeePerOutputs);

					// Check if inputs have enough coins.
					Money inputSum = inputs.Sum(x => x.Amount);
					Money changeAmount = (inputSum - (round.MixingLevels.GetBaseDenomination() + networkFeeToPayAfterBaseDenomination));
					if (changeAmount < Money.Zero)
					{
						return BadRequest($"Not enough inputs are provided. Fee to pay: {networkFeeToPayAfterBaseDenomination.ToString(false, true)} BTC. Round denomination: {round.MixingLevels.GetBaseDenomination().ToString(false, true)} BTC. Only provided: {inputSum.ToString(false, true)} BTC.");
					}
					acceptedBlindedOutputScripts.Add(blindedOutputs.First());

					Money networkFeeToPay = networkFeeToPayAfterBaseDenomination;
					// Make sure we sign the proper number of additional blinded outputs.
					var moneySoFar = Money.Zero;
					for (int i = 1; i < blindedOutputCount; i++)
					{
						if (!round.MixingLevels.TryGetDenomination(i, out Money denomination))
						{
							break;
						}

						Money coordinatorFee = denomination.Percentage(round.CoordinatorFeePercent * round.AnonymitySet); // It should be the number of bobs, but we must make sure they'd have money to pay all.
						changeAmount -= (denomination + round.FeePerOutputs + coordinatorFee);
						networkFeeToPay += round.FeePerOutputs;

						if (changeAmount < Money.Zero)
						{
							break;
						}

						acceptedBlindedOutputScripts.Add(blindedOutputs[i]);
					}

					// Make sure Alice checks work.
					var alice = new Alice(inputs, networkFeeToPayAfterBaseDenomination, request.ChangeOutputAddress, acceptedBlindedOutputScripts);

					foreach (Guid aliceToRemove in alicesToRemove)
					{
						round.RemoveAlicesBy(aliceToRemove);
					}

					// if alice is counted in queued count already, remove it
					round.DequeueAnyFamiliarAlice(request.Inputs);
					round.AddAlice(alice);
					// All checks are good. Sign.
					var blindSignatures = new List<uint256>();
					for (int i = 0; i < acceptedBlindedOutputScripts.Count; i++)
					{
						var blindedOutput = acceptedBlindedOutputScripts[i];
						var signer = round.MixingLevels.GetLevel(i).Signer;
						uint256 blindSignature = signer.Sign(blindedOutput);
						blindSignatures.Add(blindSignature);
					}
					alice.BlindedOutputSignatures = blindSignatures.ToArray();

					// Check if phase changed since.
					if (round.Status != CoordinatorRoundStatus.Running || round.Phase != RoundPhase.InputRegistration)
					{
						return StatusCode(StatusCodes.Status503ServiceUnavailable, "The state of the round changed while handling the request. Try again.");
					}

					// Progress round if needed.
					if (round.CountAlices() >= round.AnonymitySet)
					{
						await round.RemoveAlicesIfAnInputRefusedByMempoolAsync();

						if (round.CountAlices() >= round.AnonymitySet)
						{
							await round.ExecuteNextPhaseAsync(RoundPhase.ConnectionConfirmation);
						}
					}

					var resp = new InputsResponse
					{
						UniqueId = alice.UniqueId,
						RoundId = round.RoundId
					};
					return Ok(resp);
				}
				catch (Exception ex)
				{
					Logger.LogDebug(ex);
					return BadRequest(ex.Message);
				}
			}
		}

19 View Source File : P2pTests.cs
License : GNU General Public License v3.0
Project Creator : chaincase-app

[Theory]
		// [InlineData("test")] - ToDo, this test fails for some reason.
		[InlineData("main")]
		public async Task TestServicesAsync(string networkString)
		{
			await RuntimeParams.LoadAsync();
			var network = Network.GetNetwork(networkString);
			var blocksToDownload = new List<uint256>();
			if (network == Network.Main)
			{
				blocksToDownload.Add(new uint256("00000000000000000037c2de35bd85f3e57f14ddd741ce6cee5b28e51473d5d0"));
				blocksToDownload.Add(new uint256("000000000000000000115315a43cb0cdfc4ea54a0e92bed127f4e395e718d8f9"));
				blocksToDownload.Add(new uint256("00000000000000000011b5b042ad0522b69aae36f7de796f563c895714bbd629"));
			}
			else if (network == Network.TestNet)
			{
				blocksToDownload.Add(new uint256("0000000097a664c4084b49faa6fd4417055cb8e5aac480abc31ddc57a8208524"));
				blocksToDownload.Add(new uint256("000000009ed5b82259ecd2aa4cd1f119db8da7a70e7ea78d9c9f603e01f93bcc"));
				blocksToDownload.Add(new uint256("00000000e6da8c2da304e9f5ad99c079df2c3803b49efded3061ecaf206ddc66"));
			}
			else
			{
				throw new NotSupportedNetworkException(network);
			}
			var dataDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

			BitcoinStore bitcoinStore = new BitcoinStore(Path.Combine(dataDir, EnvironmentHelpers.GetMethodName()), network,
				new IndexStore(network, new SmartHeaderChain()), new AllTransactionStore(), new MempoolService());
			
			await bitcoinStore.InitializeAsync();

			var addressManagerFolderPath = Path.Combine(dataDir, "AddressManager");
			var addressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{network}.dat");
			var blocksFolderPath = Path.Combine(dataDir, "Blocks", network.ToString());
			var connectionParameters = new NodeConnectionParameters();
			AddressManager addressManager = null;
			try
			{
				addressManager = await NBitcoinHelpers.LoadAddressManagerFromPeerFileAsync(addressManagerFilePath);
				Logger.LogInfo($"Loaded {nameof(AddressManager)} from `{addressManagerFilePath}`.");
			}
			catch (DirectoryNotFoundException)
			{
				addressManager = new AddressManager();
			}
			catch (FileNotFoundException)
			{
				addressManager = new AddressManager();
			}
			catch (OverflowException)
			{
				File.Delete(addressManagerFilePath);
				addressManager = new AddressManager();
			}
			catch (FormatException)
			{
				File.Delete(addressManagerFilePath);
				addressManager = new AddressManager();
			}

			connectionParameters.TemplateBehaviors.Add(new AddressManagerBehavior(addressManager));
			connectionParameters.TemplateBehaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior());

			using var nodes = new NodesGroup(network, connectionParameters, requirements: Constants.NodeRequirements);

			KeyManager keyManager = KeyManager.CreateNew(out _, "preplacedword");
			WasabiSynchronizer syncer = new WasabiSynchronizer(network, bitcoinStore, new Uri("http://localhost:12345"), Global.Instance.TorSocks5Endpoint);
			ServiceConfiguration serviceConfig = new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelStrong.ToString(), 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold));
			CachedBlockProvider blockProvider = new CachedBlockProvider(
				new P2pBlockProvider(nodes, null, syncer, serviceConfig, network),
				new FileSystemBlockRepository(blocksFolderPath, network));

			using Wallet wallet = Wallet.CreateAndRegisterServices(
				network,
				bitcoinStore,
				keyManager,
				syncer,
				nodes,
				dataDir,
				new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelStrong.ToString(), 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold)),
				syncer,
				blockProvider);
			replacedert.True(Directory.Exists(blocksFolderPath));

			try
			{
				var mempoolTransactionAwaiter = new EventsAwaiter<SmartTransaction>(
					h => bitcoinStore.MempoolService.TransactionReceived += h,
					h => bitcoinStore.MempoolService.TransactionReceived -= h,
					3);

				var nodeConnectionAwaiter = new EventsAwaiter<NodeEventArgs>(
					h => nodes.ConnectedNodes.Added += h,
					h => nodes.ConnectedNodes.Added -= h,
					3);

				nodes.Connect();

				var downloadTasks = new List<Task<Block>>();
				using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(4));
				foreach (var hash in blocksToDownload)
				{
					downloadTasks.Add(blockProvider.GetBlockAsync(hash, cts.Token));
				}

				await nodeConnectionAwaiter.WaitAsync(TimeSpan.FromMinutes(3));

				var i = 0;
				var hashArray = blocksToDownload.ToArray();
				foreach (var block in await Task.WhenAll(downloadTasks))
				{
					replacedert.True(File.Exists(Path.Combine(blocksFolderPath, hashArray[i].ToString())));
					i++;
				}

				await mempoolTransactionAwaiter.WaitAsync(TimeSpan.FromMinutes(1));
			}
			finally
			{
				// So next test will download the block.
				foreach (var hash in blocksToDownload)
				{
					await blockProvider.BlockRepository.RemoveAsync(hash, CancellationToken.None);
				}
				if (wallet is { })
				{
					await wallet.StopAsync(CancellationToken.None);
				}

				if (Directory.Exists(blocksFolderPath))
				{
					Directory.Delete(blocksFolderPath, recursive: true);
				}

				IoHelpers.EnsureContainingDirectoryExists(addressManagerFilePath);
				addressManager?.SavePeerFile(addressManagerFilePath, network);
				Logger.LogInfo($"Saved {nameof(AddressManager)} to `{addressManagerFilePath}`.");

				await syncer?.StopAsync();
			}
		}