Esempio n. 1
0
        public async Task BanUtxosAsync(int severity, DateTimeOffset timeOfBan, bool forceNoted, long bannedForRound, params OutPoint[] toBan)
        {
            if (RoundConfig.DosSeverity == 0)
            {
                return;
            }

            var lines   = new List <string>();
            var updated = false;

            foreach (var utxo in toBan)
            {
                BannedUtxo foundElem = null;
                if (BannedUtxos.TryGetValue(utxo, out BannedUtxo fe))
                {
                    foundElem = fe;
                    bool bannedForTheSameRound = foundElem.BannedForRound == bannedForRound;
                    if (bannedForTheSameRound && (!forceNoted || foundElem.IsNoted))
                    {
                        continue;                         // We would be simply duplicating this ban.
                    }
                }

                var isNoted = true;
                if (!forceNoted)
                {
                    if (RoundConfig.DosNoteBeforeBan)
                    {
                        if (foundElem is { })
Esempio n. 2
0
        public UtxoReferee(Network network, string folderPath, RPCClient rpc, CoordinatorRoundConfig 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);

            BannedUtxos = new ConcurrentDictionary <OutPoint, BannedUtxo>();

            Directory.CreateDirectory(FolderPath);

            if (File.Exists(BannedUtxosFilePath))
            {
                try
                {
                    var      toRemove = new List <string>();               // what's been confirmed
                    string[] allLines = File.ReadAllLines(BannedUtxosFilePath);
                    foreach (string line in allLines)
                    {
                        var bannedRecord = BannedUtxo.FromString(line);

                        GetTxOutResponse getTxOutResponse = RpcClient.GetTxOut(bannedRecord.Utxo.Hash, (int)bannedRecord.Utxo.N, includeMempool: true);

                        // Check if inputs are unspent.
                        if (getTxOutResponse is null)
                        {
                            toRemove.Add(line);
                        }
                        else
                        {
                            BannedUtxos.TryAdd(bannedRecord.Utxo, bannedRecord);
                        }
                    }

                    if (toRemove.Count != 0)                     // a little performance boost, often it'll be empty
                    {
                        var newAllLines = allLines.Where(x => !toRemove.Contains(x));
                        File.WriteAllLines(BannedUtxosFilePath, newAllLines);
                    }

                    Logger.LogInfo($"{allLines.Length} banned UTXOs are loaded from {BannedUtxosFilePath}.");
                }
                catch (Exception ex)
                {
                    Logger.LogWarning($"Banned UTXO file got corrupted. Deleting {BannedUtxosFilePath}. {ex.GetType()}: {ex.Message}");
                    File.Delete(BannedUtxosFilePath);
                }
            }
            else
            {
                Logger.LogInfo($"No banned UTXOs are loaded from {BannedUtxosFilePath}.");
            }
        }
Esempio n. 3
0
        public async Task BanUtxosAsync(int severity, DateTimeOffset timeOfBan, bool forceNoted, long bannedForRound, params OutPoint[] toBan)
        {
            if (RoundConfig.DosSeverity == 0)
            {
                return;
            }

            var lines   = new List <string>();
            var updated = false;

            foreach (var utxo in toBan)
            {
                BannedUtxo foundElem = null;
                if (BannedUtxos.TryGetValue(utxo, out BannedUtxo fe))
                {
                    foundElem = fe;
                    bool bannedForTheSameRound = foundElem.BannedForRound == bannedForRound;
                    if (bannedForTheSameRound && (!forceNoted || foundElem.IsNoted))
                    {
                        continue;                         // We would be simply duplicating this ban.
                    }
                }

                var isNoted = true;
                if (!forceNoted)
                {
                    if (RoundConfig.DosNoteBeforeBan)
                    {
                        if (foundElem != null)
                        {
                            isNoted = false;
                        }
                    }
                    else
                    {
                        isNoted = false;
                    }
                }

                var newElem = new BannedUtxo(utxo, severity, timeOfBan, isNoted, bannedForRound);
                if (BannedUtxos.TryAdd(newElem.Utxo, newElem))
                {
                    string line = newElem.ToString();
                    lines.Add(line);
                }
                else
                {
                    var elem = BannedUtxos[utxo];
                    if (elem.IsNoted != isNoted || elem.BannedForRound != bannedForRound)
                    {
                        BannedUtxos[utxo] = new BannedUtxo(elem.Utxo, elem.Severity, elem.TimeOfBan, isNoted, bannedForRound);
                        updated           = true;
                    }
                }

                Logger.LogInfo($"UTXO {(isNoted ? "noted" : "banned")} with severity: {severity}. UTXO: {utxo.N}:{utxo.Hash} for disrupting Round {bannedForRound}.");
            }

            if (updated)             // If at any time we set updated then we must update the whole thing.
            {
                var allLines = BannedUtxos.Select(x => x.Value.ToString());
                await File.WriteAllLinesAsync(BannedUtxosFilePath, allLines).ConfigureAwait(false);
            }
            else if (lines.Count != 0)             // If we do not have to update the whole thing, we must check if we added a line and so only append.
            {
                await File.AppendAllLinesAsync(BannedUtxosFilePath, lines).ConfigureAwait(false);
            }
        }