main: remove spent address utxo indexes

This commit is contained in:
Braydon Fuller 2016-03-30 15:12:19 -04:00 committed by Braydon Fuller
parent 21c675855f
commit d0483c9aa0
4 changed files with 18 additions and 32 deletions

View File

@ -172,9 +172,8 @@ class AddressIndexTest(BitcoinTestFramework):
# Check that unspent outputs can be queried # Check that unspent outputs can be queried
print "Testing utxos..." print "Testing utxos..."
utxos = self.nodes[1].getaddressutxos({"addresses": [address2]}) utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
assert_equal(len(utxos), 2) assert_equal(len(utxos), 1)
assert_equal(utxos[0]["satoshis"], 5000000000) assert_equal(utxos[0]["satoshis"], change_amount)
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..."
@ -190,9 +189,8 @@ class AddressIndexTest(BitcoinTestFramework):
assert_equal(balance4, balance1) assert_equal(balance4, balance1)
utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]}) utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]})
assert_equal(len(utxos2), 2) assert_equal(len(utxos2), 1)
assert_equal(utxos2[0]["satoshis"], 5000000000) assert_equal(utxos2[0]["satoshis"], 5000000000)
assert_equal(utxos2[1]["satoshis"], 5000000000)
print "Passed\n" print "Passed\n"

View File

@ -2073,7 +2073,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
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 // undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k), CAddressUnspentValue())); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), 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);
@ -2082,7 +2082,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
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 // undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k), CAddressUnspentValue())); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else { } else {
continue; continue;
@ -2123,6 +2123,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
fClean = false; fClean = false;
if (fAddressIndex) { if (fAddressIndex) {
const CTxIn input = tx.vin[j];
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);
@ -2131,7 +2132,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
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 // restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey))); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey)));
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
@ -2141,7 +2142,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
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 // restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey))); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey)));
} else { } else {
continue; continue;
@ -2465,6 +2466,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (fAddressIndex) if (fAddressIndex)
{ {
for (size_t j = 0; j < tx.vin.size(); j++) { for (size_t j = 0; j < tx.vin.size(); j++) {
const CTxIn input = tx.vin[j];
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);
@ -2473,7 +2475,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1)); addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
// remove address from unspent index // remove address from unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, j), CAddressUnspentValue())); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
} 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);
@ -2481,7 +2483,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1)); addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
// remove address from unspent index // remove address from unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, j), CAddressUnspentValue())); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
} else { } else {
continue; continue;
@ -2521,7 +2523,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue)); addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output // record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey))); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey)));
} 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);
@ -2530,7 +2532,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue)); addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output // record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey))); addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey)));
} else { } else {
continue; continue;

View File

@ -356,21 +356,16 @@ struct CTimestampIndexKey {
struct CAddressUnspentKey { struct CAddressUnspentKey {
unsigned int type; unsigned int type;
uint160 hashBytes; uint160 hashBytes;
int blockHeight;
unsigned int txindex;
uint256 txhash; uint256 txhash;
size_t index; size_t index;
size_t GetSerializeSize(int nType, int nVersion) const { size_t GetSerializeSize(int nType, int nVersion) const {
return 65; return 57;
} }
template<typename Stream> template<typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const { void Serialize(Stream& s, int nType, int nVersion) const {
ser_writedata8(s, type); ser_writedata8(s, type);
hashBytes.Serialize(s, nType, nVersion); hashBytes.Serialize(s, nType, nVersion);
// Heights are stored big-endian for key sorting in LevelDB
ser_writedata32be(s, blockHeight);
ser_writedata32be(s, txindex);
txhash.Serialize(s, nType, nVersion); txhash.Serialize(s, nType, nVersion);
ser_writedata32(s, index); ser_writedata32(s, index);
} }
@ -378,18 +373,13 @@ struct CAddressUnspentKey {
void Unserialize(Stream& s, int nType, int nVersion) { void Unserialize(Stream& s, int nType, int nVersion) {
type = ser_readdata8(s); type = ser_readdata8(s);
hashBytes.Unserialize(s, nType, nVersion); hashBytes.Unserialize(s, nType, nVersion);
blockHeight = ser_readdata32be(s);
txindex = ser_readdata32be(s);
txhash.Unserialize(s, nType, nVersion); txhash.Unserialize(s, nType, nVersion);
index = ser_readdata32(s); index = ser_readdata32(s);
} }
CAddressUnspentKey(unsigned int addressType, uint160 addressHash, int height, int blockindex, CAddressUnspentKey(unsigned int addressType, uint160 addressHash, uint256 txid, size_t indexValue) {
uint256 txid, size_t indexValue) {
type = addressType; type = addressType;
hashBytes = addressHash; hashBytes = addressHash;
blockHeight = height;
txindex = blockindex;
txhash = txid; txhash = txid;
index = indexValue; index = indexValue;
} }
@ -401,8 +391,6 @@ struct CAddressUnspentKey {
void SetNull() { void SetNull() {
type = 0; type = 0;
hashBytes.SetNull(); hashBytes.SetNull();
blockHeight = 0;
txindex = 0;
txhash.SetNull(); txhash.SetNull();
index = 0; index = 0;
} }
@ -430,14 +418,13 @@ struct CAddressUnspentValue {
} }
void SetNull() { void SetNull() {
satoshis = 0; satoshis = -1;
script = CScript(); script.clear();
} }
bool IsNull() const { bool IsNull() const {
return (satoshis == 0); return (satoshis == -1);
} }
}; };
struct CAddressIndexKey { struct CAddressIndexKey {

View File

@ -475,7 +475,6 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp)
output.push_back(Pair("addressType", (int)it->first.type)); output.push_back(Pair("addressType", (int)it->first.type));
output.push_back(Pair("addressHash", it->first.hashBytes.GetHex())); output.push_back(Pair("addressHash", it->first.hashBytes.GetHex()));
output.push_back(Pair("txid", it->first.txhash.GetHex())); output.push_back(Pair("txid", it->first.txhash.GetHex()));
output.push_back(Pair("height", it->first.blockHeight));
output.push_back(Pair("outputIndex", it->first.index)); output.push_back(Pair("outputIndex", it->first.index));
output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end()))); output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end())));
output.push_back(Pair("satoshis", it->second.satoshis)); output.push_back(Pair("satoshis", it->second.satoshis));