/// <inheritdoc /> public async Task <UnspentOutputs> GetUnspentTransactionAsync(uint256 trxid) { CoinViews.FetchCoinsResponse response = null; if (this.ConsensusLoop?.UTXOSet != null) { response = await this.ConsensusLoop.UTXOSet.FetchCoinsAsync(new[] { trxid }).ConfigureAwait(false); } return(response?.UnspentOutputs?.SingleOrDefault()); }
/// <inheritdoc /> public override Task <FetchCoinsResponse> FetchCoinsAsync(uint256[] txIds) { Task <FetchCoinsResponse> task = Task.Run(() => { this.logger.LogTrace("({0}.{1}:{2})", nameof(txIds), nameof(txIds.Length), txIds?.Length); FetchCoinsResponse res = null; using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins"); transaction.ValuesLazyLoadingIsOn = false; using (new StopwatchDisposable(o => this.PerformanceCounter.AddQueryTime(o))) { uint256 blockHash = this.GetCurrentHash(transaction); UnspentOutputs[] result = new UnspentOutputs[txIds.Length]; this.PerformanceCounter.AddQueriedEntities(txIds.Length); int i = 0; foreach (uint256 input in txIds) { Row <byte[], Coins> row = transaction.Select <byte[], Coins>("Coins", input.ToBytes(false)); UnspentOutputs outputs = row.Exists ? new UnspentOutputs(input, row.Value) : null; result[i++] = outputs; } res = new FetchCoinsResponse(result, blockHash); } } this.logger.LogTrace("(-):*.{0}='{1}',*.{2}.{3}={4}", nameof(res.BlockHash), res.BlockHash, nameof(res.UnspentOutputs), nameof(res.UnspentOutputs.Length), res.UnspentOutputs.Length); return(res); }); return(task); }
/// <summary> /// Retrieves the block hash of the current tip of the coinview. /// </summary> /// <returns>Block hash of the current tip of the coinview.</returns> public async Task <uint256> GetBlockHashAsync() { FetchCoinsResponse response = await this.FetchCoinsAsync(new uint256[0]).ConfigureAwait(false); return(response.BlockHash); }
/// <inheritdoc /> public override async Task <FetchCoinsResponse> FetchCoinsAsync(uint256[] txIds) { Guard.NotNull(txIds, nameof(txIds)); this.logger.LogTrace("({0}.{1}:{2})", nameof(txIds), nameof(txIds.Length), txIds.Length); FetchCoinsResponse result = null; UnspentOutputs[] outputs = new UnspentOutputs[txIds.Length]; List <int> miss = new List <int>(); List <uint256> missedTxIds = new List <uint256>(); using (await this.lockobj.LockAsync().ConfigureAwait(false)) { for (int i = 0; i < txIds.Length; i++) { CacheItem cache; if (!this.unspents.TryGetValue(txIds[i], out cache)) { this.logger.LogTrace("Cache missed for transaction ID '{0}'.", txIds[i]); miss.Add(i); missedTxIds.Add(txIds[i]); } else { this.logger.LogTrace("Cache hit for transaction ID '{0}'.", txIds[i]); outputs[i] = cache.UnspentOutputs == null ? null : cache.UnspentOutputs.IsPrunable ? null : cache.UnspentOutputs.Clone(); } } this.PerformanceCounter.AddMissCount(miss.Count); this.PerformanceCounter.AddHitCount(txIds.Length - miss.Count); } this.logger.LogTrace("{0} cache missed transaction needs to be loaded from underlaying coinview.", missedTxIds.Count); FetchCoinsResponse fetchedCoins = await this.Inner.FetchCoinsAsync(missedTxIds.ToArray()).ConfigureAwait(false); using (await this.lockobj.LockAsync().ConfigureAwait(false)) { uint256 innerblockHash = fetchedCoins.BlockHash; if (this.blockHash == null) { Debug.Assert(this.unspents.Count == 0); this.innerBlockHash = innerblockHash; this.blockHash = this.innerBlockHash; } for (int i = 0; i < miss.Count; i++) { int index = miss[i]; UnspentOutputs unspent = fetchedCoins.UnspentOutputs[i]; outputs[index] = unspent; CacheItem cache = new CacheItem(); cache.ExistInInner = unspent != null; cache.IsDirty = false; cache.UnspentOutputs = unspent; cache.OriginalOutputs = unspent?.Outputs.ToArray(); this.unspents.TryAdd(txIds[index], cache); } result = new FetchCoinsResponse(outputs, this.blockHash); } int cacheEntryCount = this.CacheEntryCount; if (cacheEntryCount > this.MaxItems) { this.logger.LogTrace("Cache is full now with {0} entries, evicting ...", cacheEntryCount); await this.EvictAsync().ConfigureAwait(false); } this.logger.LogTrace("(-):*.{0}='{1}',*.{2}.{3}={4}", nameof(result.BlockHash), result.BlockHash, nameof(result.UnspentOutputs), nameof(result.UnspentOutputs.Length), result.UnspentOutputs.Length); return(result); }