private async Task RenewAssets() { var assets = (await _assetRepository.GetBitcoinAssets()).Where(o => !string.IsNullOrEmpty(o.AssetAddress) && !o.IsDisabled && o.IssueAllowed).ToList(); foreach (var asset in assets) { try { var queue = _queueFactory.Create(asset.BlockChainAssetId); var count = await queue.Count(); for (int i = 0; i < count; i++) { var coin = await queue.DequeueCoin(); if (coin == null) { return; } await queue.EnqueueOutputs(coin); } } catch (BackendException) { //ignore } catch (Exception e) { await _logger.WriteErrorAsync("PregeneratedOutputsRenewFunction", "RenewAssets", $"Asset {asset.Id}", e); } } }
private async Task GenerateAssetOutputs() { await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateAssetOutputs", null, "Start process"); var hotWallet = new BitcoinPubKeyAddress(_baseSettings.HotWalletForPregeneratedOutputs, _connectionParams.Network); var assets = (await _assetRepository.GetBitcoinAssets()).Where(o => !string.IsNullOrEmpty(o.AssetAddress) && !o.IsDisabled && o.IssueAllowed).ToList(); foreach (var asset in assets) { try { if (asset.DefinitionUrl == null) { await _logger.WriteWarningAsync("GenerateOutputsFunction", "GenerateAssetOutputs", $"Asset: {asset.Id} has no DefinitionUrl", ""); continue; } var queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId); while (await queue.Count() < _baseSettings.MinPregeneratedAssetOutputsCount) { var coins = await _bitcoinOutputsService.GetUncoloredUnspentOutputs(hotWallet.ToString()); TransactionBuilder builder = new TransactionBuilder(); builder.AddCoins(coins); for (var i = 0; i < _baseSettings.GenerateAssetOutputsBatchSize; i++) { builder.Send(new BitcoinPubKeyAddress(asset.AssetAddress, _connectionParams.Network), _dustSize); } builder.SetChange(hotWallet); builder.SendFees(await _feeProvider.CalcFeeForTransaction(builder)); var signedHex = await _signatureApiProvider.SignTransaction(builder.BuildTransaction(true).ToHex()); var signedTr = new Transaction(signedHex); var transactionId = Guid.NewGuid(); await _bitcoinClient.BroadcastTransaction(signedTr, transactionId); await queue.EnqueueOutputs(signedTr.Outputs.AsCoins() .Where(o => o.ScriptPubKey.GetDestinationAddress(_connectionParams.Network).ToString() == asset.AssetAddress && o.TxOut.Value == _dustSize).ToArray()); await FinishOutputs(transactionId, signedTr, hotWallet); } } catch (Exception e) { await _logger.WriteWarningAsync("GenerateOutputsFunction", "GenerateAssetOutputs", $"Asset {asset.Id}", e); } } await _logger.WriteInfoAsync("GenerateOutputsFunction", "GenerateAssetOutputs", null, "End process"); }
public Task <CreateTransactionResponse> GetIssueTransaction(BitcoinAddress bitcoinAddres, decimal amount, IAsset asset, Guid transactionId) { return(Retry.Try(async() => { var context = _transactionBuildContextFactory.Create(_connectionParams.Network); return await context.Build(async() => { var builder = new TransactionBuilder(); var queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId); var coin = await queue.DequeueCoin(); try { var issueCoin = new IssuanceCoin(coin) { DefinitionUrl = new Uri(asset.DefinitionUrl) }; var assetId = new BitcoinAssetId(asset.BlockChainAssetId, _connectionParams.Network).AssetId; builder.AddCoins(issueCoin) .IssueAsset(bitcoinAddres, new AssetMoney(assetId, amount, asset.MultiplierPower)); context.IssueAsset(assetId); await _transactionBuildHelper.AddFee(builder, context); var buildedTransaction = builder.BuildTransaction(true); await _spentOutputService.SaveSpentOutputs(transactionId, buildedTransaction); await SaveNewOutputs(transactionId, buildedTransaction, context); return new CreateTransactionResponse(buildedTransaction.ToHex(), transactionId); } catch (Exception) { await queue.EnqueueOutputs(coin); throw; } }); }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _log)); }
private async Task GenerateIssueAllowedCoins() { foreach (var asset in await _assetRepostory.Values()) { if (OpenAssetsHelper.IsBitcoin(asset.Id) || OpenAssetsHelper.IsLkk(asset.Id) || !asset.IssueAllowed) { continue; } try { var setting = await GetAssetSetting(asset.Id); if (setting.HotWallet != setting.ChangeWallet) { continue; } var hotWallet = OpenAssetsHelper.ParseAddress(setting.HotWallet); var assetId = new BitcoinAssetId(asset.BlockChainAssetId).AssetId; var coins = await _bitcoinOutputsService.GetColoredUnspentOutputs(setting.HotWallet, assetId); var outputSize = new AssetMoney(assetId, setting.OutputSize, asset.MultiplierPower); await _logger.WriteInfoAsync("GenerateOffchainOutputsFunction", "GenerateIssueAllowedCoins", "AssetId " + asset.Id, "Start process"); var existingCoinsCount = coins.Count(o => o.Amount <= outputSize && o.Amount * 2 > outputSize); if (existingCoinsCount > setting.MinOutputsCount) { continue; } var generateCnt = setting.MaxOutputsCount - existingCoinsCount; var generated = 0; while (generated < generateCnt) { var outputsCount = Math.Min(setting.MaxOutputsCountInTx, generateCnt - generated); var context = _transactionBuildContextFactory.Create(_connectionParams.Network); await context.Build(async() => { var builder = new TransactionBuilder(); var queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId); var coin = await queue.DequeueCoin(); try { var issueCoin = new IssuanceCoin(coin) { DefinitionUrl = new Uri(asset.DefinitionUrl) }; builder.AddCoins(issueCoin); for (var i = 0; i < outputsCount; i++) { builder.IssueAsset(hotWallet, outputSize); } context.IssueAsset(assetId); await _transactionBuildHelper.AddFee(builder, context); var tr = builder.BuildTransaction(true); await SignAndBroadcastTransaction(tr, context); return(""); } catch (Exception) { await queue.EnqueueOutputs(coin); throw; } }); generated += outputsCount; } } catch (Exception ex) { await _logger.WriteWarningAsync("GenerateOffchainOutputsFunction", "GenerateIssueAllowedCoins", "AssetId " + asset.Id, ex); } finally { await _logger.WriteInfoAsync("GenerateOffchainOutputsFunction", "GenerateIssueAllowedCoins", "AssetId " + asset.Id, "End process"); } } }
private async Task RefreshOutputs(string type, string assetId) { Console.WriteLine($"Start process: type={type}" + (assetId != null ? $", asset={assetId}" : null)); IPregeneratedOutputsQueue queue; string address; if (type == "fee") { queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue(); address = _feeAddress; } else { var asset = await _assetRepository.GetAssetById(assetId); queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId); address = asset.AssetAddress; Console.WriteLine("BlockchainAssetId : " + asset.BlockChainAssetId); } var count = await queue.Count(); Console.WriteLine($"Start collect {count} outputs from queue"); var set = new HashSet <OutPoint>(); while (count-- > 0) { Coin coin = null; try { coin = await queue.DequeueCoin(); } catch (Exception) { } finally { if (coin != null && !set.Contains(coin.Outpoint)) { set.Add(coin.Outpoint); await queue.EnqueueOutputs(coin); } } } Console.WriteLine($"Coins collected"); var coins = (await _bitcoinOutputsService.GetOnlyNinjaOutputs(address, 1, int.MaxValue)).OfType <Coin>().ToArray(); Console.WriteLine($"Received {coins.Length} outputs from qbitninja"); coins = coins.Where(x => !set.Contains(x.Outpoint)).ToArray(); Console.WriteLine($"Got {coins.Length} missing outputs"); await queue.EnqueueOutputs(coins); //Console.WriteLine("Start remove outputs from queue"); //int i = 0; //while (true) // try // { // await queue.DequeueCoin(); // i++; // } // catch (BackendException) // { // break; // } //Console.WriteLine($"Removed {i} coins from queue"); //var coins = (await _bitcoinOutputsService.GetUncoloredUnspentOutputs(address)).OfType<Coin>().ToArray(); //Console.WriteLine($"Received {coins.Length} outputs from qbitninja"); //Console.WriteLine("Start add coins to queue"); //await queue.EnqueueOutputs(coins); Console.WriteLine("All coins successfuly added to queue"); Console.WriteLine(Environment.NewLine); }