Ejemplo n.º 1
0
        public IActionResult GetUtxoSet(int atBlockHeight)
        {
            try
            {
                ReconstructedCoinviewContext coinView = this.utxoIndexer.GetCoinviewAtHeight(atBlockHeight);

                var outputs = new List <UtxoModel>();

                foreach (OutPoint outPoint in coinView.UnspentOutputs)
                {
                    TxOut txOut = coinView.Transactions[outPoint.Hash].Outputs[outPoint.N];
                    var   utxo  = new UtxoModel()
                    {
                        TxId = outPoint.Hash, Index = outPoint.N, ScriptPubKey = txOut.ScriptPubKey, Value = txOut.Value
                    };

                    outputs.Add(utxo);
                }

                return(this.Json(outputs));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
Ejemplo n.º 2
0
        public LastBalanceDecreaseTransactionModel GetLastBalanceDecreaseTransaction(string address)
        {
            if (address == null)
            {
                return(null);
            }

            (bool isQueryable, string reason) = this.IsQueryable();

            if (!isQueryable)
            {
                return(null);
            }

            int lastBalanceHeight;

            lock (this.lockObject)
            {
                AddressIndexerData indexData = this.addressIndexRepository.GetOrCreateAddress(address);

                AddressBalanceChange lastBalanceUpdate = indexData.BalanceChanges.Where(a => !a.Deposited).OrderByDescending(b => b.BalanceChangedHeight).FirstOrDefault();

                if (lastBalanceUpdate == null)
                {
                    return(null);
                }

                lastBalanceHeight = lastBalanceUpdate.BalanceChangedHeight;
            }

            // Height 0 is used as a placeholder height for compacted address balance records, so ignore them if they are the only record.
            if (lastBalanceHeight == 0)
            {
                return(null);
            }

            ChainedHeader header = this.chainIndexer.GetHeader(lastBalanceHeight);

            if (header == null)
            {
                return(null);
            }

            Block block = this.consensusManager.GetBlockData(header.HashBlock).Block;

            if (block == null)
            {
                return(null);
            }

            // Get the UTXO snapshot as of one block lower than the last balance change, so that we are definitely able to look up the inputs of each transaction in the next block.
            ReconstructedCoinviewContext utxos = this.utxoIndexer.GetCoinviewAtHeight(lastBalanceHeight - 1);

            Transaction foundTransaction = null;

            foreach (Transaction transaction in block.Transactions)
            {
                if (transaction.IsCoinBase)
                {
                    continue;
                }

                foreach (TxIn txIn in transaction.Inputs)
                {
                    Transaction prevTx = utxos.Transactions[txIn.PrevOut.Hash];

                    foreach (TxOut txOut in prevTx.Outputs)
                    {
                        if (this.scriptAddressReader.GetAddressFromScriptPubKey(this.network, txOut.ScriptPubKey) == address)
                        {
                            foundTransaction = transaction;
                        }
                    }
                }
            }

            return(foundTransaction == null ? null : new LastBalanceDecreaseTransactionModel()
            {
                BlockHeight = lastBalanceHeight, Transaction = new TransactionVerboseModel(foundTransaction, this.network)
            });
        }