コード例 #1
0
        private void AdjustCoinviewForBlock(Block block, ReconstructedCoinviewContext coinView)
        {
            foreach (Transaction tx in block.Transactions)
            {
                // Add outputs
                for (int i = 0; i < tx.Outputs.Count; i++)
                {
                    TxOut output = tx.Outputs[i];

                    if (output.Value <= 0 || output.ScriptPubKey.IsUnspendable)
                    {
                        continue;
                    }

                    coinView.UnspentOutputs.Add(new OutPoint(tx, i));
                    coinView.Transactions[tx.GetHash()] = tx;
                }

                // Spend inputs. Coinbases are special in that they don't reference previous transactions for their inputs, so ignore them.
                if (tx.IsCoinBase)
                {
                    continue;
                }

                foreach (TxIn txIn in tx.Inputs)
                {
                    // TODO: This is inefficient because the Transactions dictionary entry does not get deleted, so extra memory gets used
                    if (!coinView.UnspentOutputs.Remove(txIn.PrevOut))
                    {
                        throw new Exception("Attempted to spend a prevOut that isn't in the coinview at this time.");
                    }
                }
            }
        }
コード例 #2
0
        public ReconstructedCoinviewContext GetCoinviewAtHeight(int blockHeight)
        {
            var coinView = new ReconstructedCoinviewContext();

            // TODO: Make this a command line option
            const int batchSize = 1000;

            IEnumerable <ChainedHeader> allBlockHeaders = this.chainIndexer.EnumerateToTip(this.chainIndexer.Genesis);

            int totalBlocksCounted = 0;

            int i = 0;

            while (true)
            {
                List <ChainedHeader> headers = allBlockHeaders.Skip(i * batchSize).Take(batchSize).ToList();
                List <Block>         blocks  = this.blockStore.GetBlocks(headers.Select(x => x.HashBlock).ToList());

                foreach (Block block in blocks)
                {
                    this.AdjustCoinviewForBlock(block, coinView);
                    totalBlocksCounted += 1;

                    // We have reached the block height asked for.
                    if (totalBlocksCounted >= blockHeight)
                    {
                        break;
                    }
                }

                // We have seen every block up to the tip or the chosen block height.
                if (headers.Count < batchSize || totalBlocksCounted >= blockHeight)
                {
                    break;
                }

                // Give the user some feedback every 10k blocks
                if (i % 10 == 9)
                {
                    this.logger.LogInformation($"Processed {totalBlocksCounted} blocks for UTXO indexing.");
                }

                i++;
            }

            return(coinView);
        }