From 809a8abff69fbf8c04641ccd352f0b1cb1c08047 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 9 Jun 2016 14:02:30 -0400 Subject: [PATCH 1/3] tests: expanded address index mempool testing --- qa/rpc-tests/addressindex.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 47102a02c7f5..54c018e3d081 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -246,17 +246,21 @@ def run_test(self): tx2 = CTransaction() tx2.vin = [CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))] amount = unspent[1]["amount"] * 100000000 - tx2.vout = [CTxOut(amount, scriptPubKey3)] + tx2.vout = [CTxOut(amount / 2, scriptPubKey3), CTxOut(amount / 2, scriptPubKey3)] tx2.rehash() signed_tx2 = self.nodes[2].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8")) memtxid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True) time.sleep(2) mempool = self.nodes[2].getaddressmempool({"addresses": [address3]}) - assert_equal(len(mempool), 2) + assert_equal(len(mempool), 3) assert_equal(mempool[0]["txid"], memtxid1) - assert_equal(mempool[1]["txid"], memtxid2) assert_equal(mempool[0]["address"], address3) + assert_equal(mempool[0]["index"], 0) + assert_equal(mempool[1]["txid"], memtxid2) + assert_equal(mempool[1]["index"], 0) + assert_equal(mempool[2]["txid"], memtxid2) + assert_equal(mempool[2]["index"], 1) self.nodes[2].generate(1); self.sync_all(); @@ -264,7 +268,7 @@ def run_test(self): assert_equal(len(mempool2), 0) tx = CTransaction() - tx.vin = [CTxIn(COutPoint(int(memtxid2, 16), 0))] + tx.vin = [CTxIn(COutPoint(int(memtxid2, 16), 0)), CTxIn(COutPoint(int(memtxid2, 16), 1))] tx.vout = [CTxOut(amount - 10000, scriptPubKey2)] tx.rehash() self.nodes[2].importprivkey(privKey3) @@ -273,9 +277,11 @@ def run_test(self): time.sleep(2) mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]}) - assert_equal(len(mempool3), 1) + assert_equal(len(mempool3), 2) assert_equal(mempool3[0]["prevtxid"], memtxid2) assert_equal(mempool3[0]["prevout"], 0) + assert_equal(mempool3[1]["prevtxid"], memtxid2) + assert_equal(mempool3[1]["prevout"], 1) print "Passed\n" From 4dcf3e821cc6b77476a61548238b2bf9dbd0f2d9 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 10 Jun 2016 14:02:51 -0400 Subject: [PATCH 2/3] mempool: fix bug with mempool address index iteration fixes a minor bug where iteration would not end when there are matching hashes for a p2sh and p2pkh address, and would return results for both addresses --- qa/rpc-tests/addressindex.py | 16 +++++++++++++--- src/txmempool.cpp | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 54c018e3d081..1ab5db616752 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -232,6 +232,8 @@ def run_test(self): address3 = "mw4ynwhS7MmrQ27hr82kgqu7zryNDK26JB" addressHash3 = "aa9872b5bbcdb511d89e0e11aa27da73fd2c3f50".decode("hex") scriptPubKey3 = CScript([OP_DUP, OP_HASH160, addressHash3, OP_EQUALVERIFY, OP_CHECKSIG]) + address4 = "2N8oFVB2vThAKury4vnLquW2zVjsYjjAkYQ" + scriptPubKey4 = CScript([OP_HASH160, addressHash3, OP_EQUAL]) unspent = self.nodes[2].listunspent() tx = CTransaction() @@ -246,7 +248,12 @@ def run_test(self): tx2 = CTransaction() tx2.vin = [CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))] amount = unspent[1]["amount"] * 100000000 - tx2.vout = [CTxOut(amount / 2, scriptPubKey3), CTxOut(amount / 2, scriptPubKey3)] + tx2.vout = [ + CTxOut(amount / 4, scriptPubKey3), + CTxOut(amount / 4, scriptPubKey3), + CTxOut(amount / 4, scriptPubKey4), + CTxOut(amount / 4, scriptPubKey4) + ] tx2.rehash() signed_tx2 = self.nodes[2].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8")) memtxid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True) @@ -268,8 +275,11 @@ def run_test(self): assert_equal(len(mempool2), 0) tx = CTransaction() - tx.vin = [CTxIn(COutPoint(int(memtxid2, 16), 0)), CTxIn(COutPoint(int(memtxid2, 16), 1))] - tx.vout = [CTxOut(amount - 10000, scriptPubKey2)] + tx.vin = [ + CTxIn(COutPoint(int(memtxid2, 16), 0)), + CTxIn(COutPoint(int(memtxid2, 16), 1)) + ] + tx.vout = [CTxOut(amount / 2 - 10000, scriptPubKey2)] tx.rehash() self.nodes[2].importprivkey(privKey3) signed_tx3 = self.nodes[2].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 6ed4edbfd5cc..384d33bf7a0f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -472,7 +472,7 @@ bool CTxMemPool::getAddressIndex(std::vector > &addresse LOCK(cs); for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { addressDeltaMap::iterator ait = mapAddress.lower_bound(CMempoolAddressDeltaKey((*it).second, (*it).first)); - while (ait != mapAddress.end() && (*ait).first.addressBytes == (*it).first) { + while (ait != mapAddress.end() && (*ait).first.addressBytes == (*it).first && (*ait).first.type == (*it).second) { results.push_back(*ait); ait++; } From c01f78375e20bfe8819ec03f9b5f3760e716fa79 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 10 Jun 2016 14:41:51 -0400 Subject: [PATCH 3/3] 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. --- qa/rpc-tests/addressindex.py | 28 ++++++++++++++++++++++++++++ src/addressindex.h | 11 ++++++++--- src/txmempool.cpp | 8 ++++---- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 1ab5db616752..5c4dab85ae8f 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -293,6 +293,34 @@ def run_test(self): assert_equal(mempool3[1]["prevtxid"], memtxid2) 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" diff --git a/src/addressindex.h b/src/addressindex.h index 43b49dca9b1c..9e734b84dcdc 100644 --- a/src/addressindex.h +++ b/src/addressindex.h @@ -37,9 +37,9 @@ struct CMempoolAddressDeltaKey uint160 addressBytes; uint256 txhash; 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; addressBytes = addressHash; txhash = hash; @@ -52,6 +52,7 @@ struct CMempoolAddressDeltaKey addressBytes = addressHash; txhash.SetNull(); index = 0; + spending = 0; } }; @@ -61,7 +62,11 @@ struct CMempoolAddressDeltaKeyCompare if (a.type == b.type) { if (a.addressBytes == b.addressBytes) { if (a.txhash == b.txhash) { - return a.index < b.index; + if (a.index == b.index) { + return a.spending < b.spending; + } else { + return a.index < b.index; + } } else { return a.txhash < b.txhash; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 384d33bf7a0f..2bb902f83abc 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -434,13 +434,13 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC const CTxOut &prevout = view.GetOutputFor(input); if (prevout.scriptPubKey.IsPayToScriptHash()) { vector 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); mapAddress.insert(make_pair(key, delta)); inserted.push_back(key); } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { vector 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); mapAddress.insert(make_pair(key, delta)); inserted.push_back(key); @@ -451,13 +451,13 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC const CTxOut &out = tx.vout[k]; if (out.scriptPubKey.IsPayToScriptHash()) { vector 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))); inserted.push_back(key); } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); std::pair 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))); inserted.push_back(key); }