main: update address index during reorgs
This commit is contained in:
parent
38a7d6d323
commit
186e11fde7
@ -118,10 +118,12 @@ class AddressIndexTest(BitcoinTestFramework):
|
||||
assert_equal(txidsmany[3], sent_txid)
|
||||
|
||||
# Check that balances are correct
|
||||
print "Testing balances..."
|
||||
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(balance0["balance"], 45 * 100000000 + 21)
|
||||
|
||||
# Check that balances are correct after spending
|
||||
print "Testing balances after spending..."
|
||||
privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||
address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||
addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||
@ -158,14 +160,27 @@ class AddressIndexTest(BitcoinTestFramework):
|
||||
|
||||
# Check that deltas are returned correctly
|
||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 0, "end": 200})
|
||||
balance3 = 0;
|
||||
balance3 = 0
|
||||
for delta in deltas:
|
||||
balance3 += delta["satoshis"]
|
||||
assert_equal(balance3, change_amount)
|
||||
|
||||
# Check that deltas can be returned from range of block heights
|
||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 113, "end": 113})
|
||||
assert_equal(len(deltas), 1);
|
||||
assert_equal(len(deltas), 1)
|
||||
|
||||
# Check that indexes will be updated with a reorg
|
||||
print "Testing reorg..."
|
||||
|
||||
best_hash = self.nodes[0].getbestblockhash()
|
||||
self.nodes[0].invalidateblock(best_hash)
|
||||
self.nodes[1].invalidateblock(best_hash)
|
||||
self.nodes[2].invalidateblock(best_hash)
|
||||
self.nodes[3].invalidateblock(best_hash)
|
||||
self.sync_all()
|
||||
|
||||
balance4 = self.nodes[1].getaddressbalance(address2)
|
||||
assert_equal(balance4, balance1)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
46
src/main.cpp
46
src/main.cpp
@ -2079,6 +2079,52 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
|
||||
}
|
||||
}
|
||||
|
||||
// undo address indexes
|
||||
if (fAddressIndex) {
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++) {
|
||||
const CTransaction &tx = block.vtx[i];
|
||||
const uint256 txhash = tx.GetHash();
|
||||
|
||||
if (!tx.IsCoinBase()) {
|
||||
for (size_t j = 0; j < tx.vin.size(); j++) {
|
||||
const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
|
||||
if (prevout.scriptPubKey.IsPayToScriptHash()) {
|
||||
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
|
||||
addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
|
||||
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
|
||||
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
|
||||
addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int k = 0; k < tx.vout.size(); k++) {
|
||||
const CTxOut &out = tx.vout[k];
|
||||
|
||||
if (out.scriptPubKey.IsPayToScriptHash()) {
|
||||
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
|
||||
addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
|
||||
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
|
||||
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
|
||||
addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!pblocktree->EraseAddressIndex(addressIndex)) {
|
||||
return AbortNode(state, "Failed to delete address index");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// move best block pointer to prevout block
|
||||
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
||||
|
||||
|
@ -172,6 +172,13 @@ bool CBlockTreeDB::WriteAddressIndex(const std::vector<std::pair<CAddressIndexKe
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
|
||||
CDBBatch batch(&GetObfuscateKey());
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
batch.Erase(make_pair(DB_ADDRESSINDEX, it->first));
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||
int start, int end) {
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
|
||||
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
||||
bool WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
||||
bool EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
||||
bool ReadAddressIndex(uint160 addressHash, int type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||
int start = 0, int end = 0);
|
||||
|
Loading…
Reference in New Issue
Block a user