mempool: same address and index for an input and output bug

fixes a bug that would happen when an output would match an input with
the same address and index, and would lead to the outputs not appearing
in results.
This commit is contained in:
Braydon Fuller 2016-06-10 14:41:51 -04:00 committed by Simon
parent cf27a26fc9
commit b97bdbb690
3 changed files with 40 additions and 7 deletions

View File

@ -293,6 +293,34 @@ class AddressIndexTest(BitcoinTestFramework):
assert_equal(mempool3[1]["prevtxid"], memtxid2) assert_equal(mempool3[1]["prevtxid"], memtxid2)
assert_equal(mempool3[1]["prevout"], 1) assert_equal(mempool3[1]["prevout"], 1)
# sending and receiving to the same address
privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8"
address1 = "myAUWSHnwsQrhuMWv4Br6QsCnpB41vFwHn"
address1hash = "c192bff751af8efec15135d42bfeedf91a6f3e34".decode("hex")
address1script = CScript([OP_DUP, OP_HASH160, address1hash, OP_EQUALVERIFY, OP_CHECKSIG])
self.nodes[0].sendtoaddress(address1, 10)
self.nodes[0].generate(1)
self.sync_all()
utxos = self.nodes[1].getaddressutxos({"addresses": [address1]})
assert_equal(len(utxos), 1)
tx = CTransaction()
tx.vin = [
CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["outputIndex"]))
]
amount = utxos[0]["satoshis"] - 1000
tx.vout = [CTxOut(amount, address1script)]
tx.rehash()
self.nodes[0].importprivkey(privkey1)
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
mem_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
self.sync_all()
mempool_deltas = self.nodes[2].getaddressmempool({"addresses": [address1]})
assert_equal(len(mempool_deltas), 2)
print "Passed\n" print "Passed\n"

View File

@ -37,9 +37,9 @@ struct CMempoolAddressDeltaKey
uint160 addressBytes; uint160 addressBytes;
uint256 txhash; uint256 txhash;
unsigned int index; unsigned int index;
bool spending; int spending;
CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, bool s) { CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) {
type = addressType; type = addressType;
addressBytes = addressHash; addressBytes = addressHash;
txhash = hash; txhash = hash;
@ -52,6 +52,7 @@ struct CMempoolAddressDeltaKey
addressBytes = addressHash; addressBytes = addressHash;
txhash.SetNull(); txhash.SetNull();
index = 0; index = 0;
spending = 0;
} }
}; };
@ -61,7 +62,11 @@ struct CMempoolAddressDeltaKeyCompare
if (a.type == b.type) { if (a.type == b.type) {
if (a.addressBytes == b.addressBytes) { if (a.addressBytes == b.addressBytes) {
if (a.txhash == b.txhash) { if (a.txhash == b.txhash) {
if (a.index == b.index) {
return a.spending < b.spending;
} else {
return a.index < b.index; return a.index < b.index;
}
} else { } else {
return a.txhash < b.txhash; return a.txhash < b.txhash;
} }

View File

@ -133,13 +133,13 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC
const CTxOut &prevout = view.GetOutputFor(input); const CTxOut &prevout = view.GetOutputFor(input);
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);
CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, j, true); CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
mapAddress.insert(make_pair(key, delta)); mapAddress.insert(make_pair(key, delta));
inserted.push_back(key); inserted.push_back(key);
} 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);
CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, j, true); CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
mapAddress.insert(make_pair(key, delta)); mapAddress.insert(make_pair(key, delta));
inserted.push_back(key); inserted.push_back(key);
@ -150,13 +150,13 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC
const CTxOut &out = tx.vout[k]; const CTxOut &out = tx.vout[k];
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);
CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, k, false); CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, k, 0);
mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
inserted.push_back(key); inserted.push_back(key);
} 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);
std::pair<addressDeltaMap::iterator,bool> ret; std::pair<addressDeltaMap::iterator,bool> ret;
CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, k, false); CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, k, 0);
mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
inserted.push_back(key); inserted.push_back(key);
} }