main: update address index during reorgs
This commit is contained in:
parent
372ae61bfb
commit
230783d4b3
|
@ -118,10 +118,12 @@ class AddressIndexTest(BitcoinTestFramework):
|
||||||
assert_equal(txidsmany[3], sent_txid)
|
assert_equal(txidsmany[3], sent_txid)
|
||||||
|
|
||||||
# Check that balances are correct
|
# Check that balances are correct
|
||||||
|
print "Testing balances..."
|
||||||
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||||
assert_equal(balance0["balance"], 45 * 100000000 + 21)
|
assert_equal(balance0["balance"], 45 * 100000000 + 21)
|
||||||
|
|
||||||
# Check that balances are correct after spending
|
# Check that balances are correct after spending
|
||||||
|
print "Testing balances after spending..."
|
||||||
privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||||
address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||||
addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||||
|
@ -158,14 +160,27 @@ class AddressIndexTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Check that deltas are returned correctly
|
# Check that deltas are returned correctly
|
||||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 0, "end": 200})
|
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 0, "end": 200})
|
||||||
balance3 = 0;
|
balance3 = 0
|
||||||
for delta in deltas:
|
for delta in deltas:
|
||||||
balance3 += delta["satoshis"]
|
balance3 += delta["satoshis"]
|
||||||
assert_equal(balance3, change_amount)
|
assert_equal(balance3, change_amount)
|
||||||
|
|
||||||
# Check that deltas can be returned from range of block heights
|
# Check that deltas can be returned from range of block heights
|
||||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 113, "end": 113})
|
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"
|
print "Passed\n"
|
||||||
|
|
||||||
|
|
46
src/main.cpp
46
src/main.cpp
|
@ -2297,6 +2297,52 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
view.PopAnchor(SaplingMerkleTree::empty_root(), SAPLING);
|
view.PopAnchor(SaplingMerkleTree::empty_root(), SAPLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// move best block pointer to prevout block
|
||||||
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,13 @@ bool CBlockTreeDB::WriteAddressIndex(const std::vector<std::pair<CAddressIndexKe
|
||||||
return WriteBatch(batch);
|
return WriteBatch(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
|
||||||
|
CDBBatch batch(*this);
|
||||||
|
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,
|
bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
|
||||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||||
int start, int end) {
|
int start, int end) {
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
|
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
|
||||||
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
||||||
bool WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
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,
|
bool ReadAddressIndex(uint160 addressHash, int type,
|
||||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||||
int start = 0, int end = 0);
|
int start = 0, int end = 0);
|
||||||
|
|
Loading…
Reference in New Issue