main: update unspent address index during reorgs
This commit is contained in:
parent
08836972c0
commit
24894cb748
@ -174,6 +174,7 @@ class AddressIndexTest(BitcoinTestFramework):
|
|||||||
utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
|
utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
|
||||||
assert_equal(len(utxos), 2)
|
assert_equal(len(utxos), 2)
|
||||||
assert_equal(utxos[0]["satoshis"], 5000000000)
|
assert_equal(utxos[0]["satoshis"], 5000000000)
|
||||||
|
assert_equal(utxos[1]["satoshis"], 4899977160)
|
||||||
|
|
||||||
# Check that indexes will be updated with a reorg
|
# Check that indexes will be updated with a reorg
|
||||||
print "Testing reorg..."
|
print "Testing reorg..."
|
||||||
@ -188,6 +189,11 @@ class AddressIndexTest(BitcoinTestFramework):
|
|||||||
balance4 = self.nodes[1].getaddressbalance(address2)
|
balance4 = self.nodes[1].getaddressbalance(address2)
|
||||||
assert_equal(balance4, balance1)
|
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"
|
print "Passed\n"
|
||||||
|
|
||||||
|
|
||||||
|
29
src/main.cpp
29
src/main.cpp
@ -2054,6 +2054,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
|
|||||||
return error("DisconnectBlock(): block and undo data inconsistent");
|
return error("DisconnectBlock(): block and undo data inconsistent");
|
||||||
|
|
||||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||||
|
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||||
|
|
||||||
// undo transactions in reverse order
|
// undo transactions in reverse order
|
||||||
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
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()) {
|
if (out.scriptPubKey.IsPayToScriptHash()) {
|
||||||
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
|
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));
|
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()) {
|
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
|
||||||
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
|
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));
|
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 {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2113,10 +2126,23 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
|
|||||||
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
|
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
|
||||||
if (prevout.scriptPubKey.IsPayToScriptHash()) {
|
if (prevout.scriptPubKey.IsPayToScriptHash()) {
|
||||||
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
|
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));
|
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()) {
|
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
|
||||||
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
|
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));
|
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 {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2130,6 +2156,9 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
|
|||||||
if (!pblocktree->EraseAddressIndex(addressIndex)) {
|
if (!pblocktree->EraseAddressIndex(addressIndex)) {
|
||||||
return AbortNode(state, "Failed to delete address index");
|
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
|
// move best block pointer to prevout block
|
||||||
|
Loading…
Reference in New Issue
Block a user