Ejemplo n.º 1
0
 internal void Add(RebroadcastResult a)
 {
     UnknownFailure.AddRange(a.UnknownFailure);
     Rebroadcasted.AddRange(a.Rebroadcasted);
     MissingInputs.AddRange(a.MissingInputs);
     Cleaned.AddRange(a.Cleaned);
 }
Ejemplo n.º 2
0
        public async Task <RebroadcastResult> RebroadcastAll()
        {
            List <Task <RebroadcastResult> > rebroadcast = new List <Task <RebroadcastResult> >();

            foreach (var broadcastedTransactions in _BroadcastedTransactionsByCryptoCode.Select(c => c.Value))
            {
                var txs = broadcastedTransactions.RetrieveTransactions();
                if (txs.Count == 0)
                {
                    continue;
                }
                foreach (var tx in txs)
                {
                    rebroadcast.Add(Rebroadcast(broadcastedTransactions.Network, tx.TrackedSource, tx.OrderedKeys));
                }
            }
            var result = new RebroadcastResult();

            foreach (var broadcast in rebroadcast)
            {
                result.Add(await broadcast);
            }
            return(result);
        }
Ejemplo n.º 3
0
        private async Task <RebroadcastResult> Rebroadcast(NBXplorerNetwork network, TrackedSource trackedSource, IEnumerable <TrackedTransactionKey> txIds)
        {
            var result     = new RebroadcastResult();
            var repository = _Repositories.GetRepository(network);
            var waiter     = _Waiters.GetWaiter(repository.Network);

            if (!waiter.RPCAvailable)
            {
                return(result);
            }
            List <TrackedTransaction>       cleaned = new List <TrackedTransaction>();
            HashSet <TrackedTransactionKey> processedTrackedTransactionKeys = new HashSet <TrackedTransactionKey>();
            HashSet <uint256> processedTransactionId = new HashSet <uint256>();

            foreach (var trackedTxId in txIds)
            {
                if (!processedTransactionId.Add(trackedTxId.TxId))
                {
                    continue;
                }
                var tx = (await repository.GetSavedTransactions(trackedTxId.TxId))?.Select(t => t.Transaction).FirstOrDefault();
                if (tx == null)
                {
                    continue;
                }
                try
                {
                    await waiter.RPC.SendRawTransactionAsync(tx);

                    result.Rebroadcasted.Add(tx);
                    Logs.Explorer.LogInformation($"{repository.Network.CryptoCode}: Rebroadcasted {trackedTxId.TxId}");
                }
                catch (RPCException ex) when(
                    ex.RPCCode == RPCErrorCode.RPC_TRANSACTION_ALREADY_IN_CHAIN ||
                    ex.Message.EndsWith("Missing inputs", StringComparison.OrdinalIgnoreCase) ||
                    ex.Message.EndsWith("bad-txns-inputs-spent", StringComparison.OrdinalIgnoreCase) ||
                    ex.Message.EndsWith("txn-mempool-conflict", StringComparison.OrdinalIgnoreCase))
                {
                    result.MissingInputs.Add(tx);
                    var txs = await repository.GetTransactions(trackedSource, trackedTxId.TxId);

                    foreach (var savedTx in txs)
                    {
                        if (!processedTrackedTransactionKeys.Add(savedTx.Key))
                        {
                            continue;
                        }
                        if (savedTx.BlockHash == null)
                        {
                            cleaned.Add(savedTx);
                            result.Cleaned.Add(savedTx);
                        }
                        else
                        {
                            var resultRPC = await waiter.RPC.SendCommandAsync(new RPCRequest("getblockheader", new[] { savedTx.BlockHash }), throwIfRPCError : false);

                            if (resultRPC.Error?.Code is RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY)
                            {
                                cleaned.Add(savedTx);
                                result.Cleaned.Add(savedTx);
                            }
                            else if (resultRPC.Result.Value <int>("confirmations") == -1)
                            {
                                cleaned.Add(savedTx);
                                result.Cleaned.Add(savedTx);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    result.UnknownFailure.Add(tx);
                    Logs.Explorer.LogInformation($"{repository.Network.CryptoCode}: Unknown exception when broadcasting {tx.GetHash()} ({ex.Message})");
                }
            }

            if (cleaned.Count != 0)
            {
                foreach (var tx in cleaned)
                {
                    EventAggregator.Publish(new EvictedTransactionEvent(tx.TransactionHash));
                }
                await repository.CleanTransactions(trackedSource, cleaned.ToList());
            }
            return(result);
        }