예제 #1
0
        async Task EnsureMineToAddresses()
        {
            var mineToAddresses = new List <BitcoinWitPubKeyAddress>();

            if (this.appConfiguration.MineToAddress != null)
            {
                mineToAddresses.Add(this.appConfiguration.MineToAddress);
                this.logger.LogInformation($"Mining to address {this.appConfiguration.MineToAddress} (set in x1-producer.config).");
                AddressCache.SetMineToAddresses(mineToAddresses);
                return;
            }

            this.logger.LogInformation("Trying to extract mine-to-addresses from the wallet. The wallet must contain at least one unspent output.");

            while (true)
            {
                try
                {
                    var getUnspentOutputsResponse = await this.rpcClient.GetUnspentOutputs();

                    if (getUnspentOutputsResponse.Status != 200)
                    {
                        throw new InvalidOperationException(getUnspentOutputsResponse.StatusText);
                    }

                    var unspentOutputs = getUnspentOutputsResponse.Result.result
                                         .Where(x => x.address != null)
                                         .DistinctBy(x => x.address).ToArray();

                    if (unspentOutputs.Length == 0)
                    {
                        throw new InvalidOperationException($"Unable to extract addresses for mining from the wallet because it doesn't contain unspent outputs. " +
                                                            $"You can set an address in x1-producer config: minetoaddress=x11...");
                    }

                    bool useMiningLabelPrefix = unspentOutputs.Any(x => HasMiningLabelPrefix(x.label));
                    this.logger.LogInformation(useMiningLabelPrefix
                            ? $"Extracting mine-to addresses where its label is prefixed with '{MiningLabelPrefix}'."
                            : $"Using all addresses as mine-to addresses, because no address has its label prefixed with '{MiningLabelPrefix}'.");

                    foreach (var output in unspentOutputs)
                    {
                        if (!output.spendable || !output.solvable)
                        {
                            continue;
                        }

                        if (useMiningLabelPrefix && !HasMiningLabelPrefix(output.label))
                        {
                            continue;
                        }

                        try
                        {
                            // use every address that is a valid WPKH address.
                            mineToAddresses.Add(new BitcoinWitPubKeyAddress(output.address, C.Network));
                        }
                        // ReSharper disable once EmptyGeneralCatchClause
                        catch
                        {
                        }
                    }

                    if (mineToAddresses.Count > 0)
                    {
                        this.logger.LogInformation($"Imported {mineToAddresses.Count} addresses for mining.");
                        AddressCache.SetMineToAddresses(mineToAddresses);
                        return;
                    }

                    throw new InvalidOperationException("No addresses for mining.");
                }
                catch (Exception e)
                {
                    this.logger.LogError($"Error retrieving addresses for mining: {e.Message} Retrying...");
                    await Task.Delay(2000);
                }
            }
        }