internal void Add(RebroadcastResult a) { UnknownFailure.AddRange(a.UnknownFailure); Rebroadcasted.AddRange(a.Rebroadcasted); MissingInputs.AddRange(a.MissingInputs); Cleaned.AddRange(a.Cleaned); }
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); }
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); }