RPC: initial scaninput implementation.
[novacoin.git] / src / rpcmining.cpp
index 02109a5..8f02836 100644 (file)
@@ -5,12 +5,39 @@
 
 #include "main.h"
 #include "db.h"
+#include "txdb.h"
 #include "init.h"
+#include "miner.h"
+#include "kernel.h"
 #include "bitcoinrpc.h"
 
 using namespace json_spirit;
 using namespace std;
 
+extern uint256 nPoWBase;
+
+Value getsubsidy(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() > 1)
+        throw runtime_error(
+            "getsubsidy [nTarget]\n"
+            "Returns proof-of-work subsidy value for the specified value of target.");
+
+    unsigned int nBits = 0;
+
+    if (params.size() != 0)
+    {
+        CBigNum bnTarget(uint256(params[0].get_str()));
+        nBits = bnTarget.GetCompact();
+    }
+    else
+    {
+        nBits = GetNextTargetRequired(pindexBest, false);
+    }
+
+    return (uint64_t)GetProofOfWorkReward(nBits);
+}
+
 Value getmininginfo(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 0)
@@ -18,44 +45,83 @@ Value getmininginfo(const Array& params, bool fHelp)
             "getmininginfo\n"
             "Returns an object containing mining-related information.");
 
-    int64 nTargetSpacingWorkMin = 30;
-    int64 nTargetSpacingWork = nTargetSpacingWorkMin;
-    int64 nPoWInterval = 72;
-    int64 nTargetSpacingStake = 600;
-
-    CBlockIndex* pindex = pindexGenesisBlock;
-    CBlockIndex* pindexPrevWork = pindexGenesisBlock;
+    float nKernelsRate = 0, nCoinDaysRate = 0;
+    pwalletMain->GetStakeStats(nKernelsRate, nCoinDaysRate);
 
-    while (pindex)
-    {
-        if (pindex->IsProofOfWork())
-        {
-            int64 nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
-            nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
-            nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
-            pindexPrevWork = pindex;
-        }
-
-        pindex = pindex->pnext;
-    }
-    
-    double dNetworkMhps = GetDifficulty() * 4294.967296 / nTargetSpacingWork;
-    int nNetworkWeight = GetDifficulty(GetLastBlockIndex(pindexBest, true)) * 4294967296 / nTargetSpacingStake;
-
-    Object obj;
+    Object obj, diff, weight;
     obj.push_back(Pair("blocks",        (int)nBestHeight));
     obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
     obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
-    obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
-    obj.push_back(Pair("netmhashps",     dNetworkMhps));
-    obj.push_back(Pair("netstakeweight", nNetworkWeight));
+
+    diff.push_back(Pair("proof-of-work",        GetDifficulty()));
+    diff.push_back(Pair("proof-of-stake",       GetDifficulty(GetLastBlockIndex(pindexBest, true))));
+    diff.push_back(Pair("search-interval",      (int)nLastCoinStakeSearchInterval));
+    obj.push_back(Pair("difficulty",    diff));
+
+    obj.push_back(Pair("blockvalue",    (uint64_t)GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits)));
+    obj.push_back(Pair("netmhashps",     GetPoWMHashPS()));
+    obj.push_back(Pair("netstakeweight", GetPoSKernelPS()));
     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
     obj.push_back(Pair("pooledtx",      (uint64_t)mempool.size()));
-    obj.push_back(Pair("stakepower",    (uint64_t)pwalletMain->GetStakeMintPower(*pwalletMain)));
+
+    weight.push_back(Pair("kernelsrate",   nKernelsRate));
+    weight.push_back(Pair("cdaysrate",   nCoinDaysRate));
+    obj.push_back(Pair("stakestats", weight));
+
+    obj.push_back(Pair("stakeinterest",    (uint64_t)GetProofOfStakeReward(0, GetLastBlockIndex(pindexBest, true)->nBits, GetLastBlockIndex(pindexBest, true)->nTime, true)));
     obj.push_back(Pair("testnet",       fTestNet));
     return obj;
 }
 
+Value scaninput(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() > 4 || params.size() < 2)
+        throw runtime_error(
+            "scaninput <txid> <nout> [difficulty] [days]\n"
+            "Scan specified input for suitable kernel solutions.\n"
+            "    [difficulty] - upper limit for difficulty, current difficulty by default;\n"
+            "    [days] - time window, 365 days by default.\n"
+        );
+
+
+    uint256 hash;
+    hash.SetHex(params[0].get_str());
+
+    uint32_t nOut = params[1].get_int(), nBits = GetNextTargetRequired(pindexBest, true), nDays = 365;
+
+    if (params.size() > 2)
+    {
+        CBigNum bnTarget(nPoWBase);
+        bnTarget *= 1000;
+        bnTarget /= (int) (params[2].get_real() * 1000);
+        nBits = bnTarget.GetCompact();
+    }
+
+    if (params.size() > 3)
+    {
+        nDays = params[3].get_int();
+    }
+
+    CTransaction tx;
+    uint256 hashBlock = 0;
+    if (GetTransaction(hash, tx, hashBlock))
+    {
+        std::pair<uint256, uint32_t> solution;
+        if (ScanInputForStakeKernelHash(tx, nOut, nBits, nDays * 86400, solution))
+        {
+            Object r;
+            r.push_back(Pair("hash", solution.first.GetHex()));
+            r.push_back(Pair("time", DateTimeStrFormat(solution.second)));
+
+            return r;
+        }
+    }
+    else
+        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
+
+    return Value::null;
+}
+
 Value getworkex(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() > 2)
@@ -80,7 +146,7 @@ Value getworkex(const Array& params, bool fHelp)
         // Update block
         static unsigned int nTransactionsUpdatedLast;
         static CBlockIndex* pindexPrev;
-        static int64 nStart;
+        static int64_t nStart;
         static CBlock* pblock;
         if (pindexPrev != pindexBest ||
             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
@@ -178,12 +244,6 @@ Value getworkex(const Array& params, bool fHelp)
 
         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
 
-        if (!fTestNet && pblock->GetBlockTime() < CHAINCHECKS_SWITCH_TIME)
-        {
-            if (!pblock->SignBlock(*pwalletMain))
-                throw JSONRPCError(-100, "Unable to sign block, wallet locked?");
-        }
-
         return CheckWork(pblock, *pwalletMain, reservekey);
     }
 }
@@ -217,7 +277,7 @@ Value getwork(const Array& params, bool fHelp)
         // Update block
         static unsigned int nTransactionsUpdatedLast;
         static CBlockIndex* pindexPrev;
-        static int64 nStart;
+        static int64_t nStart;
         static CBlock* pblock;
         if (pindexPrev != pindexBest ||
             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
@@ -297,12 +357,6 @@ Value getwork(const Array& params, bool fHelp)
         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
 
-        if (!fTestNet && pblock->GetBlockTime() < CHAINCHECKS_SWITCH_TIME)
-        {
-            if (!pblock->SignBlock(*pwalletMain))
-                throw JSONRPCError(-100, "Unable to sign block, wallet locked?");
-        }
-
         return CheckWork(pblock, *pwalletMain, reservekey);
     }
 }
@@ -359,7 +413,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
     // Update block
     static unsigned int nTransactionsUpdatedLast;
     static CBlockIndex* pindexPrev;
-    static int64 nStart;
+    static int64_t nStart;
     static CBlock* pblock;
     if (pindexPrev != pindexBest ||
         (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
@@ -484,12 +538,6 @@ Value submitblock(const Array& params, bool fHelp)
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
     }
 
-    if (!fTestNet && block.GetBlockTime() < CHAINCHECKS_SWITCH_TIME)
-    {
-        if (!block.SignBlock(*pwalletMain))
-            throw JSONRPCError(-100, "Unable to sign block, wallet locked?");
-    }
-
     bool fAccepted = ProcessBlock(NULL, &block);
     if (!fAccepted)
         return "rejected";