private AddressIndexData GetOrCreateAddressData(Script scriptPubKey) { byte[] scriptPubKeyBytes = scriptPubKey.ToBytes(); AddressIndexData addrData = this.addressesIndex.AddressIndexDatas.SingleOrDefault(x => StructuralComparisons.StructuralEqualityComparer.Equals(scriptPubKeyBytes, x.ScriptPubKeyBytes)); if (addrData == null) { addrData = new AddressIndexData() { ScriptPubKeyBytes = scriptPubKeyBytes, Changes = new List <AddressBalanceChange>() }; this.addressesIndex.AddressIndexDatas.Add(addrData); return(addrData); } return(addrData); }
/// <summary>Processes block that was added or removed from consensus chain.</summary> private void ProcessBlockAddedOrRemoved(KeyValuePair <bool, ChainedHeaderBlock> item) { // Make sure it's on top of the tip. bool blockAdded = item.Key; Block block = item.Value.Block; int currentHeight = item.Value.ChainedHeader.Height; // Process inputs var inputs = new List <TxIn>(); // Collect all inputs excluding coinbases. foreach (TxInList inputsCollection in block.Transactions.Where(x => !x.IsCoinBase).Select(x => x.Inputs)) { inputs.AddRange(inputsCollection); } Transaction[] transactions = this.blockStore.GetTransactionsByIds(inputs.Select(x => x.PrevOut.Hash).ToArray()); // TODO is it possible that transactions is null because block with requested ID was reorged away already? for (int i = 0; i < inputs.Count; i++) { TxIn currentInput = inputs[i]; TxOut txOut = transactions[i].Outputs[currentInput.PrevOut.N]; Money amountSpent = txOut.Value; AddressIndexData addrData = this.GetOrCreateAddressData(txOut.ScriptPubKey); if (blockAdded) { // Record money being spent. addrData.Changes.Add(new AddressBalanceChange() { BalanceChangedHeight = currentHeight, Satoshi = amountSpent.Satoshi, Deposited = false }); } else { // Remove changes. addrData.Changes.RemoveAll(x => x.BalanceChangedHeight == currentHeight); } } // Process outputs. foreach (Transaction tx in block.Transactions) { foreach (TxOut txOut in tx.Outputs) { Money amountReceived = txOut.Value; AddressIndexData addrData = this.GetOrCreateAddressData(txOut.ScriptPubKey); if (blockAdded) { // Record money being sent. addrData.Changes.Add(new AddressBalanceChange() { BalanceChangedHeight = currentHeight, Satoshi = amountReceived.Satoshi, Deposited = true }); } else { // Remove changes. addrData.Changes.RemoveAll(x => x.BalanceChangedHeight == currentHeight); } } } this.addressesIndex.TipHash = item.Value.ChainedHeader.HashBlock.ToString(); }