Ejemplo n.º 1
0
 /// <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());
 }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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 (this.lockobj.LockRead())
            {
                this.WaitOngoingTasks();
                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 (this.lockobj.LockWrite())
            {
                this.flushingTask.Wait();
                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);
                this.Evict();
            }

            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);
        }
Ejemplo n.º 4
0
        /// <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);
        }