public async Task CheckCommitmentBroadcast() { using (OffchainMonitorContext context = new OffchainMonitorContext()) { var commitmentsToSearchFor = (from c in context.Commitments where c.Punished == false select c).ToArray(); if (commitmentsToSearchFor.Count() > 0) { for (int i = 0; i < commitmentsToSearchFor.Count(); i++) { var c = commitmentsToSearchFor[i]; bool found = false; try { await rpcBitcoinClient.GetTransactionHex(c.CommitmentTxId); found = true; } catch (RPCException exp) { if (!exp.Message.Contains("No such mempool or blockchain transaction.")) { throw exp; } else { continue; } } catch (Exception exp) { throw exp; } if (found) { try { await rpcBitcoinClient.BroadcastTransaction(new Transaction(c.Punishment), new Guid()); c.Punished = true; } catch (Exception exp) { throw exp; } } } } await context.SaveChangesAsync(); } }
private async Task Broadcast(Guid transactionId, Transaction tx, IPerformanceMonitor monitor, string hash, bool savePaidFees = true) { monitor?.Step("Broadcast transaction"); try { await _rpcBitcoinClient.BroadcastTransaction(tx, transactionId); } catch (RPCException ex) { var builder = new StringBuilder(); builder.AppendLine($"[{transactionId}], "); builder.AppendLine(ex.Message + ":"); foreach (var input in tx.Inputs) { builder.AppendLine(input.PrevOut.ToString()); } await _logger.WriteWarningAsync(nameof(BitcoinBroadcastService), nameof(BroadcastTransaction), builder.ToString(), ex); throw; } monitor?.Step("Set transaction hash and add to monitoring"); await Task.WhenAll( savePaidFees?_paidFeesTaskWriter.AddTask(hash, DateTime.UtcNow, null, null) : Task.CompletedTask, _broadcastedOutputRepository.SetTransactionHash(transactionId, hash), _monitoringWriter.AddToMonitoring(transactionId, hash) ); }
public async Task <string> Broadcast(string transaction, Guid?trId) { trId = trId ?? Guid.NewGuid(); var tr = new Transaction(transaction); await _rpcBitcoinClient.BroadcastTransaction(tr, trId.Value); await SaveSpentOutputs(trId.Value, tr); await _log.WriteInfoAsync(nameof(BccTransactionService), nameof(Broadcast), null, $"Broadcast BCC transaction {tr.GetHash()}"); return(tr.GetHash().ToString()); }
public async Task BroadcastTransaction(Guid transactionId, Transaction tx) { var hash = tx.GetHash().ToString(); if (_settings.UseLykkeApi) { await _apiProvider.SendPreBroadcastNotification(new LykkeTransactionNotification(transactionId, hash)); } await _rpcBitcoinClient.BroadcastTransaction(tx, transactionId); await _broadcastedOutputRepository.SetTransactionHash(transactionId, hash); if (_settings.UseLykkeApi) { await _apiProvider.SendPostBroadcastNotification(new LykkeTransactionNotification(transactionId, hash)); } await _monitoringWriter.AddToMonitoring(transactionId, tx.GetHash().ToString()); }
private async Task GenerateFeeOutputs() { await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateFeeOutputs", null, "Start process"); var queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue(); try { while (await queue.Count() < _baseSettings.MinPregeneratedOutputsCount) { var uncoloredOutputs = await _bitcoinOutputsService.GetUncoloredUnspentOutputs(_baseSettings.HotWalletForPregeneratedOutputs); var outputs = uncoloredOutputs.ToList(); var totalRequiredAmount = Money.FromUnit(_baseSettings.GenerateOutputsBatchSize * _baseSettings.PregeneratedFeeAmount, MoneyUnit.BTC); // Convert to satoshi var feeAmount = new Money(_baseSettings.PregeneratedFeeAmount, MoneyUnit.BTC); if (outputs.Sum(o => o.TxOut.Value) < totalRequiredAmount) { throw new BackendException($"The sum of total applicable outputs is less than the required: {totalRequiredAmount} satoshis.", ErrorCode.NotEnoughBitcoinAvailable); } var hotWallet = new BitcoinPubKeyAddress(_baseSettings.HotWalletForPregeneratedOutputs, _connectionParams.Network); var builder = new TransactionBuilder(); builder.AddCoins(outputs); builder.SetChange(hotWallet); for (var i = 0; i < _baseSettings.GenerateOutputsBatchSize; i++) { builder.Send(new BitcoinPubKeyAddress(_baseSettings.FeeAddress, _connectionParams.Network), feeAmount); } builder.SendFees(await _feeProvider.CalcFeeForTransaction(builder)); var signedHex = await _signatureApiProvider.SignTransaction(builder.BuildTransaction(false).ToHex()); var signedTr = new Transaction(signedHex); var transactionId = Guid.NewGuid(); await _bitcoinClient.BroadcastTransaction(signedTr, transactionId); await queue.EnqueueOutputs(signedTr.Outputs.AsCoins().Where(o => o.TxOut.Value == feeAmount).ToArray()); await FinishOutputs(transactionId, signedTr, hotWallet); } } finally { if (await queue.Count() < _baseSettings.MinPregeneratedOutputsCount && (DateTime.UtcNow - _lastWarningFeeSentTime).TotalHours > 1) { var message = $"Count of fee outputs is less than {_baseSettings.MinPregeneratedOutputsCount}"; await _slackNotifier.FinanceWarningAsync(message); await _emailNotifier.WarningAsync("Bitcoin job", message); _lastWarningFeeSentTime = DateTime.UtcNow; } await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateFeeOutputs", null, "End process"); } }