changeset 29645:8719b8e89af9

main: update unspent address index during reorgs
author Braydon Fuller <courier@braydon.com>
date Tue, 29 Mar 2016 17:56:57 -0400
parents 36e0b92bf2c5
children 55405cb34cf5
files qa/rpc-tests/addressindex.py src/main.cpp
diffstat 2 files changed, 35 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/qa/rpc-tests/addressindex.py	Tue Mar 29 17:46:59 2016 -0400
+++ b/qa/rpc-tests/addressindex.py	Tue Mar 29 17:56:57 2016 -0400
@@ -174,6 +174,7 @@
         utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
         assert_equal(len(utxos), 2)
         assert_equal(utxos[0]["satoshis"], 5000000000)
+        assert_equal(utxos[1]["satoshis"], 4899977160)
 
         # Check that indexes will be updated with a reorg
         print "Testing reorg..."
@@ -188,6 +189,11 @@
         balance4 = self.nodes[1].getaddressbalance(address2)
         assert_equal(balance4, balance1)
 
+        utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]})
+        assert_equal(len(utxos2), 2)
+        assert_equal(utxos2[0]["satoshis"], 5000000000)
+        assert_equal(utxos2[1]["satoshis"], 5000000000)
+
         print "Passed\n"
 
 
--- a/src/main.cpp	Tue Mar 29 17:46:59 2016 -0400
+++ b/src/main.cpp	Tue Mar 29 17:56:57 2016 -0400
@@ -2054,6 +2054,7 @@
         return error("DisconnectBlock(): block and undo data inconsistent");
 
     std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
+    std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
 
     // undo transactions in reverse order
     for (int i = block.vtx.size() - 1; i >= 0; i--) {
@@ -2067,10 +2068,22 @@
 
                 if (out.scriptPubKey.IsPayToScriptHash()) {
                     vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
+
+                    // undo receiving activity
                     addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
+
+                    // undo unspent index
+                    addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k), CAddressUnspentValue()));
+
                 } else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
                     vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
+
+                    // undo receiving activity
                     addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
+
+                    // undo unspent index
+                    addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k), CAddressUnspentValue()));
+
                 } else {
                     continue;
                 }
@@ -2113,10 +2126,23 @@
                     const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
                     if (prevout.scriptPubKey.IsPayToScriptHash()) {
                         vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
+
+                        // undo spending activity
                         addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
+
+                        // restore unspent index
+                        addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey)));
+
+
                     } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
                         vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
+
+                        // undo spending activity
                         addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
+
+                        // restore unspent index
+                        addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey)));
+
                     } else {
                         continue;
                     }
@@ -2130,6 +2156,9 @@
         if (!pblocktree->EraseAddressIndex(addressIndex)) {
             return AbortNode(state, "Failed to delete address index");
         }
+        if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) {
+            return AbortNode(state, "Failed to write address unspent index");
+        }
     }
 
     // move best block pointer to prevout block