From 4725b25e601f3a82d640943125d23b4bfc560c8a Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 29 Mar 2016 17:56:57 -0400 Subject: [PATCH] main: update unspent address index during reorgs --- qa/rpc-tests/addressindex.py | 6 ++++++ src/main.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 5448af6c6..d051d170a 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -174,6 +174,7 @@ class AddressIndexTest(BitcoinTestFramework): 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 @@ class AddressIndexTest(BitcoinTestFramework): 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" diff --git a/src/main.cpp b/src/main.cpp index 89b1823ed..c3f44d0b0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2255,6 +2255,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex return error("DisconnectBlock(): block and undo data inconsistent"); std::vector > addressIndex; + std::vector > addressUnspentIndex; // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { @@ -2268,10 +2269,22 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (out.scriptPubKey.IsPayToScriptHash()) { vector 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 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; } @@ -2338,10 +2351,23 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); if (prevout.scriptPubKey.IsPayToScriptHash()) { vector 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 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; } @@ -2358,6 +2384,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex 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