From 363358101373af438f57181db57df5bafee96550 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sun, 29 Mar 2015 02:05:08 +0300 Subject: [PATCH] RPC: initial scaninput implementation. Your personal deterministic Vanga. --- src/bitcoinrpc.cpp | 5 ++++ src/bitcoinrpc.h | 1 + src/kernel.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel.h | 2 + src/rpcmining.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 0 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index d944b92..37bc530 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -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 0) ConvertTo(params[0]); if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); + if (strMethod == "scaninput" && n > 1) ConvertTo(params[1]); + if (strMethod == "scaninput" && n > 2) ConvertTo(params[2]); + if (strMethod == "scaninput" && n > 3) ConvertTo(params[3]); + if (strMethod == "sendalert" && n > 2) ConvertTo(params[2]); if (strMethod == "sendalert" && n > 3) ConvertTo(params[3]); if (strMethod == "sendalert" && n > 4) ConvertTo(params[4]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 9ec5c9e..83e8eed 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -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); diff --git a/src/kernel.cpp b/src/kernel.cpp index c9d3f49..553f407 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -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 &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= 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) { diff --git a/src/kernel.h b/src/kernel.h index 1b639a6..9772782 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -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 &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); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index e73e441..8f02836 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -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 [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 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) -- 1.7.1