changeset 29700:dfeac91b4d23

Merge pull request #31 from braydonf/hashes rpc: option to include chain info in address index results
author Chris Kleeschulte <kleetus@users.noreply.github.com>
date Mon, 19 Sep 2016 14:28:59 -0400
parents 1bb854ed1680 881542a51011
children a16168f5f091
files
diffstat 2 files changed, 87 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/qa/rpc-tests/addressindex.py	Thu Aug 18 14:00:21 2016 -0400
+++ b/qa/rpc-tests/addressindex.py	Mon Sep 19 14:28:59 2016 -0400
@@ -171,7 +171,7 @@
         assert_equal(balance2["balance"], change_amount)
 
         # Check that deltas are returned correctly
-        deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 0, "end": 200})
+        deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 1, "end": 200})
         balance3 = 0
         for delta in deltas:
             balance3 += delta["satoshis"]
@@ -321,6 +321,27 @@
         mempool_deltas = self.nodes[2].getaddressmempool({"addresses": [address1]})
         assert_equal(len(mempool_deltas), 2)
 
+        # Include chaininfo in results
+        print "Testing results with chain info..."
+
+        deltas_with_info = self.nodes[1].getaddressdeltas({
+            "addresses": [address2],
+            "start": 1,
+            "end": 200,
+            "chainInfo": True
+        })
+        start_block_hash = self.nodes[1].getblockhash(1);
+        end_block_hash = self.nodes[1].getblockhash(200);
+        assert_equal(deltas_with_info["start"]["height"], 1)
+        assert_equal(deltas_with_info["start"]["hash"], start_block_hash)
+        assert_equal(deltas_with_info["end"]["height"], 200)
+        assert_equal(deltas_with_info["end"]["hash"], end_block_hash)
+
+        utxos_with_info = self.nodes[1].getaddressutxos({"addresses": [address2], "chainInfo": True})
+        expected_tip_block_hash = self.nodes[1].getblockhash(267);
+        assert_equal(utxos_with_info["height"], 267)
+        assert_equal(utxos_with_info["hash"], expected_tip_block_hash)
+
         print "Passed\n"
 
 
--- a/src/rpcmisc.cpp	Thu Aug 18 14:00:21 2016 -0400
+++ b/src/rpcmisc.cpp	Mon Sep 19 14:28:59 2016 -0400
@@ -539,7 +539,8 @@
             "    [\n"
             "      \"address\"  (string) The base58check encoded address\n"
             "      ,...\n"
-            "    ]\n"
+            "    ],\n"
+            "  \"chainInfo\"  (boolean) Include chain info with results\n"
             "}\n"
             "\nResult\n"
             "[\n"
@@ -555,7 +556,15 @@
             "\nExamples:\n"
             + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'")
             + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}")
-        );
+            );
+
+    bool includeChainInfo = false;
+    if (params[0].isObject()) {
+        UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
+        if (chainInfo.isBool()) {
+            includeChainInfo = chainInfo.get_bool();
+        }
+    }
 
     std::vector<std::pair<uint160, int> > addresses;
 
@@ -573,7 +582,7 @@
 
     std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort);
 
-    UniValue result(UniValue::VARR);
+    UniValue utxos(UniValue::VARR);
 
     for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) {
         UniValue output(UniValue::VOBJ);
@@ -588,10 +597,20 @@
         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("height", it->second.blockHeight));
-        result.push_back(output);
+        utxos.push_back(output);
     }
 
-    return result;
+    if (includeChainInfo) {
+        UniValue result(UniValue::VOBJ);
+        result.push_back(Pair("utxos", utxos));
+
+        LOCK(cs_main);
+        result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex()));
+        result.push_back(Pair("height", (int)chainActive.Height()));
+        return result;
+    } else {
+        return utxos;
+    }
 }
 
 UniValue getaddressdeltas(const UniValue& params, bool fHelp)
@@ -609,6 +628,7 @@
             "    ]\n"
             "  \"start\" (number) The start block height\n"
             "  \"end\" (number) The end block height\n"
+            "  \"chainInfo\" (boolean) Include chain info in results, only applies if start and end specified\n"
             "}\n"
             "\nResult:\n"
             "[\n"
@@ -629,12 +649,21 @@
     UniValue startValue = find_value(params[0].get_obj(), "start");
     UniValue endValue = find_value(params[0].get_obj(), "end");
 
+    UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo");
+    bool includeChainInfo = false;
+    if (chainInfo.isBool()) {
+        includeChainInfo = chainInfo.get_bool();
+    }
+
     int start = 0;
     int end = 0;
 
     if (startValue.isNum() && endValue.isNum()) {
         start = startValue.get_int();
         end = endValue.get_int();
+        if (start <= 0 || end <= 0) {
+            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start and end is expected to be greater than zero");
+        }
         if (end < start) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "End value is expected to be greater than start");
         }
@@ -660,7 +689,7 @@
         }
     }
 
-    UniValue result(UniValue::VARR);
+    UniValue deltas(UniValue::VARR);
 
     for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
         std::string address;
@@ -675,10 +704,38 @@
         delta.push_back(Pair("blockindex", (int)it->first.txindex));
         delta.push_back(Pair("height", it->first.blockHeight));
         delta.push_back(Pair("address", address));
-        result.push_back(delta);
+        deltas.push_back(delta);
     }
 
-    return result;
+    UniValue result(UniValue::VOBJ);
+
+    if (includeChainInfo && start > 0 && end > 0) {
+        LOCK(cs_main);
+
+        if (start > chainActive.Height() || end > chainActive.Height()) {
+            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range");
+        }
+
+        CBlockIndex* startIndex = chainActive[start];
+        CBlockIndex* endIndex = chainActive[end];
+
+        UniValue startInfo(UniValue::VOBJ);
+        UniValue endInfo(UniValue::VOBJ);
+
+        startInfo.push_back(Pair("hash", startIndex->GetBlockHash().GetHex()));
+        startInfo.push_back(Pair("height", start));
+
+        endInfo.push_back(Pair("hash", endIndex->GetBlockHash().GetHex()));
+        endInfo.push_back(Pair("height", end));
+
+        result.push_back(Pair("deltas", deltas));
+        result.push_back(Pair("start", startInfo));
+        result.push_back(Pair("end", endInfo));
+
+        return result;
+    } else {
+        return deltas;
+    }
 }
 
 UniValue getaddressbalance(const UniValue& params, bool fHelp)