changeset 29638:12075709f6b0

main: fixed bug with overlapping address index keys There was a bug where the spending address index could have the same key as the receiving address index if the input and output indexes matched. This lead to the output always overwriting the input index leading to incorrect balances with missing spent amounts. This patch separates the two so that they have unique keys so balances will be correctly calculated.
author Braydon Fuller <courier@braydon.com>
date Wed, 23 Mar 2016 14:41:08 -0400
parents 1e8c0ab15f0c
children 4f8a7d36390b
files qa/rpc-tests/addressindex.py src/main.cpp src/main.h
diffstat 3 files changed, 13 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/qa/rpc-tests/addressindex.py	Wed Mar 23 14:14:36 2016 -0400
+++ b/qa/rpc-tests/addressindex.py	Wed Mar 23 14:41:08 2016 -0400
@@ -145,7 +145,7 @@
         tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))]
         send_amount = 1 * 100000000 + 12840
         change_amount = amount - send_amount - 10000
-        tx.vout = [CTxOut(send_amount, scriptPubKey), CTxOut(change_amount, scriptPubKey2)]
+        tx.vout = [CTxOut(change_amount, scriptPubKey2), CTxOut(send_amount, scriptPubKey)]
         tx.rehash()
 
         signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
--- a/src/main.cpp	Wed Mar 23 14:14:36 2016 -0400
+++ b/src/main.cpp	Wed Mar 23 14:41:08 2016 -0400
@@ -2384,10 +2384,10 @@
                     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), prevout.nValue * -1));
+                        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), prevout.nValue * -1));
+                        addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
                     } else {
                         continue;
                     }
@@ -2421,10 +2421,10 @@
 
                 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), out.nValue));
+                    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), out.nValue));
+                    addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
                 } else {
                     continue;
                 }
--- a/src/main.h	Wed Mar 23 14:14:36 2016 -0400
+++ b/src/main.h	Wed Mar 23 14:41:08 2016 -0400
@@ -360,6 +360,7 @@
     unsigned int txindex;
     uint256 txhash;
     size_t outindex;
+    bool spending;
 
     size_t GetSerializeSize(int nType, int nVersion) const {
         return 65;
@@ -373,6 +374,8 @@
         ser_writedata32be(s, txindex);
         txhash.Serialize(s, nType, nVersion);
         ser_writedata32(s, outindex);
+        char f = spending;
+        ser_writedata8(s, f);
     }
     template<typename Stream>
     void Unserialize(Stream& s, int nType, int nVersion) {
@@ -382,16 +385,19 @@
         txindex = ser_readdata32be(s);
         txhash.Unserialize(s, nType, nVersion);
         outindex = ser_readdata32(s);
+        char f = ser_readdata8(s);
+        spending = f;
     }
 
     CAddressIndexKey(unsigned int addressType, uint160 addressHash, int height, int blockindex,
-                     uint256 txid, size_t outputIndex) {
+                     uint256 txid, size_t outputIndex, bool isSpending) {
         type = addressType;
         hashBytes = addressHash;
         blockHeight = height;
         txindex = blockindex;
         txhash = txid;
         outindex = outputIndex;
+        spending = isSpending;
     }
 
     CAddressIndexKey() {
@@ -405,6 +411,7 @@
         txindex = 0;
         txhash.SetNull();
         outindex = 0;
+        spending = false;
     }
 
 };