/// <summary> /// Get transactions in Azure Table /// </summary> /// <param name="txIds"></param> /// <returns>All transactions (with null entries for unfound transactions)</returns> public async Task <TransactionEntry[]> GetTransactionsAsync(bool lazyLoadPreviousOutput, bool fetchColor, uint256[] txIds) { var result = new TransactionEntry[txIds.Length]; var queries = new TableQuery[txIds.Length]; var tasks = Enumerable.Range(0, txIds.Length) .Select(async(i) => { result[i] = await GetTransactionAsync(lazyLoadPreviousOutput, fetchColor, txIds[i]).ConfigureAwait(false); }).ToArray(); await Task.WhenAll(tasks).ConfigureAwait(false); return(result); }
/// <summary> /// Get transactions in Azure Table /// </summary> /// <param name="txIds"></param> /// <returns>All transactions (with null entries for unfound transactions)</returns> public async Task <TransactionEntry[]> GetTransactionsAsync(bool lazyLoadPreviousOutput, bool fetchColor, uint256[] txIds) { var result = new TransactionEntry[txIds.Length]; var queries = new TableQuery[txIds.Length]; var tasks = Enumerable.Range(0, txIds.Length) .Select(i => new { TxId = txIds[i], Index = i }) .GroupBy(o => o.TxId, o => o.Index) .Select(async(o) => { var transaction = await GetTransactionAsync(lazyLoadPreviousOutput, fetchColor, o.Key).ConfigureAwait(false); foreach (var index in o) { result[index] = transaction; } }).ToArray(); await Task.WhenAll(tasks).ConfigureAwait(false); return(result); }
public async Task<TransactionEntry> GetTransactionAsync(bool loadPreviousOutput, bool fetchColor, uint256 txId) { if(txId == null) return null; TransactionEntry result = null; var table = Configuration.GetTransactionTable(); var searchedEntity = new TransactionEntry.Entity(txId); var query = new TableQuery() .Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, searchedEntity.PartitionKey), TableOperators.And, TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, txId.ToString() + "-"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, txId.ToString() + "|") ) )); query.TakeCount = 10; //Should not have more List<TransactionEntry.Entity> entities = new List<TransactionEntry.Entity>(); foreach(var e in await table.ExecuteQuerySegmentedAsync(query, null).ConfigureAwait(false)) { if(e.IsFat()) entities.Add(new TransactionEntry.Entity(await FetchFatEntity(e).ConfigureAwait(false))); else entities.Add(new TransactionEntry.Entity(e)); } if(entities.Count == 0) result = null; else { result = new TransactionEntry(entities.ToArray()); if(result.Transaction == null) { foreach(var block in result.BlockIds.Select(id => GetBlock(id)).Where(b => b != null)) { result.Transaction = block.Transactions.FirstOrDefault(t => t.GetHash() == txId); entities[0].Transaction = result.Transaction; if(entities[0].Transaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } break; } } if(fetchColor && result.ColoredTransaction == null) { result.ColoredTransaction = await ColoredTransaction.FetchColorsAsync(txId, result.Transaction, new CachedColoredTransactionRepository(new IndexerColoredTransactionRepository(Configuration))).ConfigureAwait(false); entities[0].ColoredTransaction = result.ColoredTransaction; if(entities[0].ColoredTransaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } var needTxOut = result.SpentCoins == null && loadPreviousOutput && result.Transaction != null; if(needTxOut) { var inputs = result.Transaction.Inputs.Select(o => o.PrevOut).ToArray(); var parents = await GetTransactionsAsync(false, false, inputs .Select(i => i.Hash) .ToArray()).ConfigureAwait(false); for(int i = 0; i < parents.Length; i++) { if(parents[i] == null) { IndexerTrace.MissingTransactionFromDatabase(result.Transaction.Inputs[i].PrevOut.Hash); return null; } } var outputs = parents.Select((p, i) => p.Transaction.Outputs[inputs[i].N]).ToArray(); result.SpentCoins = Enumerable .Range(0, inputs.Length) .Select(i => new Spendable(inputs[i], outputs[i])) .ToList(); entities[0].PreviousTxOuts.Clear(); entities[0].PreviousTxOuts.AddRange(outputs); if(entities[0].IsLoaded) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } } return result != null && result.Transaction != null ? result : null; }
/// <summary> /// Get transactions in Azure Table /// </summary> /// <param name="txIds"></param> /// <returns>All transactions (with null entries for unfound transactions)</returns> public async Task<TransactionEntry[]> GetTransactionsAsync(bool lazyLoadPreviousOutput, bool fetchColor, uint256[] txIds) { var result = new TransactionEntry[txIds.Length]; var queries = new TableQuery[txIds.Length]; var tasks = Enumerable.Range(0, txIds.Length) .Select(i => new { TxId = txIds[i], Index = i }) .GroupBy(o => o.TxId, o => o.Index) .Select(async (o) => { var transaction = await GetTransactionAsync(lazyLoadPreviousOutput, fetchColor, o.Key).ConfigureAwait(false); foreach(var index in o) { result[index] = transaction; } }).ToArray(); await Task.WhenAll(tasks).ConfigureAwait(false); return result; }
public async Task <TransactionEntry> GetTransactionAsync(bool loadPreviousOutput, bool fetchColor, uint256 txId) { if (txId == null) { return(null); } TransactionEntry result = null; var table = Configuration.GetTransactionTable(); var searchedEntity = new TransactionEntry.Entity(txId); var query = new TableQuery <DynamicTableEntity>() .Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, searchedEntity.PartitionKey), TableOperators.And, TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, txId.ToString() + "-"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, txId.ToString() + "|") ) )); query.TakeCount = 10; //Should not have more List <TransactionEntry.Entity> entities = new List <TransactionEntry.Entity>(); foreach (var e in await table.ExecuteQuerySegmentedAsync(query, null).ConfigureAwait(false)) { if (e.IsFat()) { entities.Add(new TransactionEntry.Entity(await FetchFatEntity(e).ConfigureAwait(false), ConsensuFactory)); } else { entities.Add(new TransactionEntry.Entity(e, ConsensuFactory)); } } if (entities.Count == 0) { result = null; } else { result = new TransactionEntry(entities.ToArray()); if (result.Transaction == null) { foreach (var block in result.BlockIds.Select(id => GetBlock(id)).Where(b => b != null)) { result.Transaction = block.Transactions.FirstOrDefault(t => t.GetHash() == txId); entities[0].Transaction = result.Transaction; if (entities[0].Transaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } break; } } if (fetchColor && result.ColoredTransaction == null) { result.ColoredTransaction = await ColoredTransaction.FetchColorsAsync(txId, result.Transaction, new CachedColoredTransactionRepository(new IndexerColoredTransactionRepository(Configuration))).ConfigureAwait(false); entities[0].ColoredTransaction = result.ColoredTransaction; if (entities[0].ColoredTransaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } var needTxOut = result.SpentCoins == null && loadPreviousOutput && result.Transaction != null; if (needTxOut) { var inputs = result.Transaction.Inputs.Select(o => o.PrevOut).ToArray(); var parents = await GetTransactionsAsync(false, false, inputs .Select(i => i.Hash) .ToArray()).ConfigureAwait(false); for (int i = 0; i < parents.Length; i++) { if (parents[i] == null) { IndexerTrace.MissingTransactionFromDatabase(result.Transaction.Inputs[i].PrevOut.Hash); return(null); } } var outputs = parents.Select((p, i) => p.Transaction.Outputs[inputs[i].N]).ToArray(); result.SpentCoins = Enumerable .Range(0, inputs.Length) .Select(i => new Spendable(inputs[i], outputs[i])) .ToList(); entities[0].PreviousTxOuts.Clear(); entities[0].PreviousTxOuts.AddRange(outputs); if (entities[0].IsLoaded) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } } return(result != null && result.Transaction != null ? result : null); }
public async Task <TransactionEntry> GetTransactionAsync(bool lazyLoadPreviousOutput, bool fetchColor, uint256 txId) { if (txId == null) { return(null); } TransactionEntry result = null; var table = Configuration.GetTransactionTable(); var searchedEntity = new TransactionEntry.Entity(txId); var query = new TableQuery() .Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, searchedEntity.PartitionKey), TableOperators.And, TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, txId.ToString() + "-"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, txId.ToString() + "|") ) )); query.TakeCount = 10; //Should not have more var entities = (await table.ExecuteQuerySegmentedAsync(query, null).ConfigureAwait(false)) .Select(e => new TransactionEntry.Entity(e)).ToArray(); if (entities.Length == 0) { result = null; } else { result = new TransactionEntry(entities); if (result.Transaction == null) { foreach (var block in result.BlockIds.Select(id => GetBlock(id)).Where(b => b != null)) { result.Transaction = block.Transactions.FirstOrDefault(t => t.GetHash() == txId); entities[0].Transaction = result.Transaction; if (entities[0].Transaction != null) { await table.ExecuteAsync(TableOperation.Merge(entities[0].CreateTableEntity())).ConfigureAwait(false); } break; } } if (fetchColor && result.ColoredTransaction == null) { result.ColoredTransaction = ColoredTransaction.FetchColors(txId, result.Transaction, new IndexerColoredTransactionRepository(Configuration)); entities[0].ColoredTransaction = result.ColoredTransaction; if (entities[0].ColoredTransaction != null) { await table.ExecuteAsync(TableOperation.Merge(entities[0].CreateTableEntity())).ConfigureAwait(false); } } var needTxOut = result.SpentCoins == null && lazyLoadPreviousOutput && result.Transaction != null; if (needTxOut) { var tasks = result.Transaction .Inputs .Select(async txin => { var parentTx = await GetTransactionAsync(false, false, txin.PrevOut.Hash).ConfigureAwait(false); if (parentTx == null) { IndexerTrace.MissingTransactionFromDatabase(txin.PrevOut.Hash); return(null); } return(parentTx.Transaction.Outputs[(int)txin.PrevOut.N]); }) .ToArray(); await Task.WhenAll(tasks).ConfigureAwait(false); if (tasks.All(t => t.Result != null)) { var outputs = tasks.Select(t => t.Result).ToArray(); result.SpentCoins = outputs.Select((o, n) => new Spendable(result.Transaction.Inputs[n].PrevOut, o)).ToList(); entities[0].PreviousTxOuts.Clear(); entities[0].PreviousTxOuts.AddRange(outputs); if (entities[0].IsLoaded) { await table.ExecuteAsync(TableOperation.Merge(entities[0].CreateTableEntity())).ConfigureAwait(false); } } } if (result.Transaction == null) { result = null; } } return(result); }