示例#1
0
        public CcjCoordinator(Network network, TrustedNodeNotifyingBehavior trustedNodeNotifyingBehavior, string folderPath, RPCClient rpc, CcjRoundConfig roundConfig)
        {
            Network = Guard.NotNull(nameof(network), network);
            TrustedNodeNotifyingBehavior = Guard.NotNull(nameof(trustedNodeNotifyingBehavior), trustedNodeNotifyingBehavior);
            FolderPath  = Guard.NotNullOrEmptyOrWhitespace(nameof(folderPath), folderPath, trim: true);
            RpcClient   = Guard.NotNull(nameof(rpc), rpc);
            RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig);

            Rounds         = new List <CcjRound>();
            RoundsListLock = new AsyncLock();

            CoinJoins     = new List <uint256>();
            CoinJoinsLock = new AsyncLock();

            Directory.CreateDirectory(FolderPath);

            UtxoReferee = new UtxoReferee(Network, FolderPath, RpcClient, RoundConfig);

            if (File.Exists(CoinJoinsFilePath))
            {
                try
                {
                    var      toRemove = new List <string>();
                    string[] allLines = File.ReadAllLines(CoinJoinsFilePath);
                    foreach (string line in allLines)
                    {
                        try
                        {
                            uint256     txHash = new uint256(line);
                            RPCResponse getRawTransactionResponse = RpcClient.SendCommand(RPCOperations.getrawtransaction, txHash.ToString(), true);
                            CoinJoins.Add(txHash);
                        }
                        catch (Exception ex)
                        {
                            toRemove.Add(line);

                            var logEntry = ex is RPCException rpce && rpce.RPCCode == RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY
                                                                ? $"CoinJoins file contains invalid transaction ID {line}"
                                                                : $"CoinJoins file got corrupted. Deleting offending line \"{line.Substring(0, 20)}\".";

                            Logger.LogWarning <CcjCoordinator>($"{logEntry}. {ex.GetType()}: {ex.Message}");
                        }
                    }

                    if (toRemove.Count != 0)                     // a little performance boost, it'll be empty almost always
                    {
                        var newAllLines = allLines.Where(x => !toRemove.Contains(x));
                        File.WriteAllLines(CoinJoinsFilePath, newAllLines);
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning <CcjCoordinator>($"CoinJoins file got corrupted. Deleting {CoinJoinsFilePath}. {ex.GetType()}: {ex.Message}");
                    File.Delete(CoinJoinsFilePath);
                }
            }

            try
            {
                string roundCountFilePath = Path.Combine(folderPath, "RoundCount.txt");
                if (File.Exists(roundCountFilePath))
                {
                    string roundCount = File.ReadAllText(roundCountFilePath);
                    CcjRound.RoundCount = long.Parse(roundCount);
                }
                else
                {
                    // First time initializes (so the first constructor will increment it and we'll start from 1.)
                    CcjRound.RoundCount = 0;
                }
            }
            catch (Exception ex)
            {
                CcjRound.RoundCount = 0;
                Logger.LogInfo <CcjCoordinator>($"{nameof(CcjRound.RoundCount)} file was corrupt. Resetting to 0.");
                Logger.LogDebug <CcjCoordinator>(ex);
            }

            TrustedNodeNotifyingBehavior.Block += TrustedNodeNotifyingBehavior_BlockAsync;
        }
        public CcjCoordinator(Network network, string folderPath, RPCClient rpc, CcjRoundConfig roundConfig)
        {
            Network     = Guard.NotNull(nameof(network), network);
            FolderPath  = Guard.NotNullOrEmptyOrWhitespace(nameof(folderPath), folderPath, trim: true);
            RpcClient   = Guard.NotNull(nameof(rpc), rpc);
            RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig);

            Rounds         = new List <CcjRound>();
            RoundsListLock = new AsyncLock();

            CoinJoins            = new List <uint256>();
            UnconfirmedCoinJoins = new List <uint256>();
            CoinJoinsLock        = new AsyncLock();

            Directory.CreateDirectory(FolderPath);

            UtxoReferee = new UtxoReferee(Network, FolderPath, RpcClient);

            // Initialize RsaKey
            string rsaKeyPath = Path.Combine(FolderPath, "RsaKey.json");

            if (File.Exists(rsaKeyPath))
            {
                string rsaKeyJson = File.ReadAllText(rsaKeyPath, encoding: Encoding.UTF8);
                RsaKey = BlindingRsaKey.CreateFromJson(rsaKeyJson);
            }
            else
            {
                RsaKey = new BlindingRsaKey();
                File.WriteAllText(rsaKeyPath, RsaKey.ToJson(), encoding: Encoding.UTF8);
                Logger.LogInfo <CcjCoordinator>($"Created RSA key at: {rsaKeyPath}");
            }

            if (File.Exists(CoinJoinsFilePath))
            {
                try
                {
                    var      toRemove = new List <string>();
                    string[] allLines = File.ReadAllLines(CoinJoinsFilePath);
                    foreach (string line in allLines)
                    {
                        uint256     txHash = new uint256(line);
                        RPCResponse getRawTransactionResponse = RpcClient.SendCommand(RPCOperations.getrawtransaction, txHash.ToString(), true);
                        if (string.IsNullOrWhiteSpace(getRawTransactionResponse?.ResultString))
                        {
                            toRemove.Add(line);
                        }
                        else
                        {
                            CoinJoins.Add(txHash);
                            if (getRawTransactionResponse.Result.Value <int>("confirmations") <= 0)
                            {
                                UnconfirmedCoinJoins.Add(txHash);
                            }
                        }
                    }

                    if (toRemove.Count != 0)                     // a little performance boost, it'll be empty almost always
                    {
                        var newAllLines = allLines.Where(x => !toRemove.Contains(x));
                        File.WriteAllLines(CoinJoinsFilePath, newAllLines);
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning <CcjCoordinator>($"CoinJoins file got corrupted. Deleting {CoinJoinsFilePath}. {ex.GetType()}: {ex.Message}");
                    File.Delete(CoinJoinsFilePath);
                }
            }
        }