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 dbbeef8f9..4d6872d2d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2054,6 +2054,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI 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--) { @@ -2067,10 +2068,22 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI 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; } @@ -2113,10 +2126,23 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI 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; } @@ -2130,6 +2156,9 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI 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