RPC: initial scaninput implementation.
authorCryptoManiac <balthazar@yandex.ru>
Sat, 28 Mar 2015 23:05:08 +0000 (02:05 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 28 Mar 2015 23:05:08 +0000 (02:05 +0300)
Your personal deterministic Vanga.

src/bitcoinrpc.cpp
src/bitcoinrpc.h
src/kernel.cpp
src/kernel.h
src/rpcmining.cpp

index d944b92..37bc530 100644 (file)
@@ -250,6 +250,7 @@ static const CRPCCommand vRPCCommands[] =
     { "getinfo",                &getinfo,                true,   false },
     { "getsubsidy",             &getsubsidy,             true,   false },
     { "getmininginfo",          &getmininginfo,          true,   false },
+    { "scaninput",              &scaninput,              true,   true },
     { "getnewaddress",          &getnewaddress,          true,   false },
     { "getnettotals",           &getnettotals,           true,   true  },
     { "getaccountaddress",      &getaccountaddress,      true,   false },
@@ -1219,6 +1220,10 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
     if (strMethod == "getblocktemplate"       && n > 0) ConvertTo<Object>(params[0]);
     if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
 
+    if (strMethod == "scaninput"              && n > 1) ConvertTo<int>(params[1]);
+    if (strMethod == "scaninput"              && n > 2) ConvertTo<double>(params[2]);
+    if (strMethod == "scaninput"              && n > 3) ConvertTo<int>(params[3]);
+
     if (strMethod == "sendalert"              && n > 2) ConvertTo<boost::int64_t>(params[2]);
     if (strMethod == "sendalert"              && n > 3) ConvertTo<boost::int64_t>(params[3]);
     if (strMethod == "sendalert"              && n > 4) ConvertTo<boost::int64_t>(params[4]);
index 9ec5c9e..83e8eed 100644 (file)
@@ -161,6 +161,7 @@ extern json_spirit::Value sendalert(const json_spirit::Array& params, bool fHelp
 
 extern json_spirit::Value getsubsidy(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value scaninput(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value getworkex(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
index c9d3f49..553f407 100644 (file)
@@ -509,6 +509,66 @@ bool ScanForStakeKernelHash(MetaMap &mapMeta, uint32_t nBits, uint32_t nTime, ui
     return false;
 }
 
+// Scan given input for kernel solutions
+bool ScanInputForStakeKernelHash(CTransaction &tx, uint32_t nOut, uint32_t nBits, uint32_t nSearchInterval, std::pair<uint256, uint32_t> &solution)
+{
+    CBlock block;
+    CTxIndex txindex;
+    uint256 hashProofOfStake;
+
+    int nTime = GetTime();
+
+    CTxDB txdb("r");
+
+    // Load transaction index item
+    if (!txdb.ReadTxIndex(tx.GetHash(), txindex))
+        return false;
+
+    // Read block header
+    if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+        return false;
+
+    uint64_t nStakeModifier = 0;
+    if (!GetKernelStakeModifier(block.GetHash(), nStakeModifier))
+        return false;
+
+    // Transaction offset inside block
+    uint32_t nTxOffset = txindex.pos.nTxPos - txindex.pos.nBlockPos;
+
+    uint32_t nBlockTime = block.nTime;
+    CBigNum bnTargetPerCoinDay;
+    bnTargetPerCoinDay.SetCompact(nBits);
+    int64_t nValueIn = tx.vout[nOut].nValue;
+
+    // Search backward in time from the given timestamp 
+    // Search nSearchInterval seconds back
+    // Stopping search in case of shutting down
+    for (unsigned int n=0; n<nSearchInterval && !fShutdown; n++)
+    {
+        uint32_t nTimeTx = nTime + n;
+        CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)tx.nTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60);
+        CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay;
+
+        // Build kernel
+        CDataStream ss(SER_GETHASH, 0);
+        ss << nStakeModifier;
+        ss << nBlockTime << nTxOffset << tx.nTime << nOut << nTimeTx;
+
+        // Calculate kernel hash
+        hashProofOfStake = Hash(ss.begin(), ss.end());
+
+        if (bnTargetProofOfStake >= CBigNum(hashProofOfStake))
+        {
+            solution.first = hashProofOfStake;
+            solution.second = nTimeTx;
+
+            return true;
+        }
+    }
+
+    return false;
+}
+
 // Check kernel hash target and coinstake signature
 bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake)
 {
index 1b639a6..9772782 100644 (file)
@@ -36,6 +36,8 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, uint32_t
 // Scan given coins set for kernel solution
 bool ScanForStakeKernelHash(MetaMap &mapMeta, uint32_t nBits, uint32_t nTime, uint32_t nSearchInterval, CoinsSet::value_type &kernelcoin, uint32_t &nTimeTx, uint32_t &nBlockTime, uint64_t &nKernelsTried, uint64_t &nCoinDaysTried);
 
+bool ScanInputForStakeKernelHash(CTransaction &tx, uint32_t nOut, uint32_t nBits, uint32_t nSearchInterval, std::pair<uint256, uint32_t> &solution);
+
 // Check kernel hash target and coinstake signature
 // Sets hashProofOfStake on success return
 bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake);
index e73e441..8f02836 100644 (file)
@@ -8,11 +8,14 @@
 #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)
@@ -70,6 +73,55 @@ Value getmininginfo(const Array& params, bool fHelp)
     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)