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
19
View Source File : PromiseClientSession.cs
License : MIT License
Project Creator : BreezeHub
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
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
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
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
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
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
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
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();
}
}