main: remove spent address utxo indexes
This commit is contained in:
parent
6107ae66d2
commit
110adc6aa7
|
@ -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"
|
||||||
|
|
||||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -2274,7 +2274,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
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);
|
||||||
|
@ -2283,7 +2283,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
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;
|
||||||
|
@ -2348,6 +2348,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -2356,7 +2357,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
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()) {
|
||||||
|
@ -2366,7 +2367,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
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;
|
||||||
|
@ -2618,6 +2619,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);
|
||||||
|
@ -2626,7 +2628,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);
|
||||||
|
|
||||||
|
@ -2634,7 +2636,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;
|
||||||
|
@ -2674,7 +2676,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);
|
||||||
|
@ -2683,7 +2685,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;
|
||||||
|
|
23
src/main.h
23
src/main.h
|
@ -334,21 +334,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);
|
||||||
}
|
}
|
||||||
|
@ -356,18 +351,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;
|
||||||
}
|
}
|
||||||
|
@ -379,8 +369,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;
|
||||||
}
|
}
|
||||||
|
@ -408,14 +396,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 {
|
||||||
|
|
|
@ -586,7 +586,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));
|
||||||
|
|
Loading…
Reference in New Issue