Prepare rpcblockchain.cpp and rpcmining.cpp for further actions

This commit is contained in:
lateminer
2018-01-06 01:57:40 +03:00
parent 6bab17dc2d
commit 135dab2ee4
2 changed files with 43 additions and 584 deletions

View File

@@ -4,7 +4,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "amount.h"
#include "base58.h"
#include "chain.h"
#include "chainparams.h"
#include "checkpoints.h"
@@ -14,23 +13,16 @@
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "rpcserver.h"
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
#include "script/standard.h"
#include "streams.h"
#include "sync.h"
#include "txmempool.h"
#include "util.h"
#include "utilstrencodings.h"
#include "hash.h"
#include <stdint.h>
#include <univalue.h>
#include <boost/thread/thread.hpp> // boost::thread::interrupt
using namespace std;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
@@ -45,7 +37,7 @@ double GetDifficulty(const CBlockIndex* blockindex)
if (chainActive.Tip() == NULL)
return 1.0;
else
blockindex = GetLastBlockIndex(chainActive.Tip(), false);
blockindex = chainActive.Tip();
}
int nShift = (blockindex->nBits >> 24) & 0xff;
@@ -78,171 +70,26 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", blockindex->nVersion));
result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (int64_t)blockindex->nTime));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetPastTimeLimit()));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
result.push_back(Pair("modifier", blockindex->nStakeModifier.GetHex()));
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
return result;
}
UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
{
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
if (chainActive.Contains(blockindex)) {
confirmations = chainActive.Height() - blockindex->nHeight + 1;
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan");
}
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue deltas(UniValue::VARR);
for (unsigned int i = 0; i < block.vtx.size(); i++) {
const CTransaction &tx = block.vtx[i];
const uint256 txhash = tx.GetHash();
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", txhash.GetHex()));
entry.push_back(Pair("index", (int)i));
UniValue inputs(UniValue::VARR);
if (!tx.IsCoinBase()) {
for (size_t j = 0; j < tx.vin.size(); j++) {
const CTxIn input = tx.vin[j];
UniValue delta(UniValue::VOBJ);
CSpentIndexValue spentInfo;
CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n);
if (GetSpentIndex(spentKey, spentInfo)) {
if (spentInfo.addressType == 1) {
delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString()));
} else if (spentInfo.addressType == 2) {
delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString()));
} else {
continue;
}
delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis));
delta.push_back(Pair("index", (int)j));
delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex()));
delta.push_back(Pair("prevout", (int)input.prevout.n));
inputs.push_back(delta);
} else {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available");
}
}
}
entry.push_back(Pair("inputs", inputs));
UniValue outputs(UniValue::VARR);
for (unsigned int k = 0; k < tx.vout.size(); k++) {
const CTxOut &out = tx.vout[k];
UniValue delta(UniValue::VOBJ);
if (out.scriptPubKey.IsPayToScriptHash()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString()));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString()));
} else {
continue;
}
delta.push_back(Pair("satoshis", out.nValue));
delta.push_back(Pair("index", (int)k));
outputs.push_back(delta);
}
entry.push_back(Pair("outputs", outputs));
deltas.push_back(entry);
}
result.push_back(Pair("deltas", deltas));
result.push_back(Pair("time", block.GetBlockTime()));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetPastTimeLimit()));
result.push_back(Pair("nonce", (uint64_t)block.nNonce));
result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
return result;
}
double GetPoSKernelPS()
{
int nPoSInterval = 72;
double dStakeKernelsTriedAvg = 0;
int nStakesHandled = 0, nStakesTime = 0;
CBlockIndex* pindex = chainActive.Tip();;
CBlockIndex* pindexPrevStake = NULL;
while (pindex && nStakesHandled < nPoSInterval)
{
if (pindex->IsProofOfStake())
{
if (pindexPrevStake)
{
dStakeKernelsTriedAvg += GetDifficulty(pindexPrevStake) * 4294967296.0;
nStakesTime += pindexPrevStake->nTime - pindex->nTime;
nStakesHandled++;
}
pindexPrevStake = pindex;
}
pindex = pindex->pprev;
}
double result = 0;
if (nStakesTime)
result = dStakeKernelsTriedAvg / nStakesTime;
result *= 16;
return result;
}
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
result.push_back(Pair("hash", block.GetHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
if (chainActive.Contains(blockindex))
@@ -251,7 +98,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
@@ -267,7 +113,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
}
result.push_back(Pair("tx", txs));
result.push_back(Pair("time", block.GetBlockTime()));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetPastTimeLimit()));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
result.push_back(Pair("nonce", (uint64_t)block.nNonce));
result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
@@ -278,10 +124,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
result.push_back(Pair("flags", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work"));
result.push_back(Pair("modifier", blockindex->nStakeModifier.GetHex()));
if (block.IsProofOfStake())
result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));
return result;
}
@@ -321,26 +163,19 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
UniValue getdifficulty(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getdifficulty\n"
"\nReturns the difficulty as a multiple of the minimum difficulty.\n"
"\nResult:\n"
"{ (json object)\n"
" \"proof-of-work\" : n.nnn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
" \"proof-of-stake\" : n.nnn (numeric) the proof-of-stake difficulty as a multiple of the minimum difficulty.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getdifficulty", "")
+ HelpExampleRpc("getdifficulty", "")
);
if (fHelp || params.size() != 0)
throw runtime_error(
"getdifficulty\n"
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
"\nResult:\n"
"n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
"\nExamples:\n"
+ HelpExampleCli("getdifficulty", "")
+ HelpExampleRpc("getdifficulty", "")
);
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("proof-of-work", GetDifficulty()));
obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(chainActive.Tip(), true))));
return obj;
return GetDifficulty();
}
UniValue mempoolToJSON(bool fVerbose = false)
@@ -431,6 +266,8 @@ UniValue getrawmempool(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getrawmempool", "true")
);
LOCK(cs_main);
bool fVerbose = false;
if (params.size() > 0)
fVerbose = params[0].get_bool();
@@ -438,102 +275,6 @@ UniValue getrawmempool(const UniValue& params, bool fHelp)
return mempoolToJSON(fVerbose);
}
UniValue getblockdeltas(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error("");
std::string strHash = params[0].get_str();
uint256 hash(uint256S(strHash));
if (mapBlockIndex.count(hash) == 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash];
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
return blockToDeltasJSON(block, pblockindex);
}
UniValue getblockhashes(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2)
throw runtime_error(
"getblockhashes timestamp\n"
"\nReturns array of hashes of blocks within the timestamp range provided.\n"
"\nArguments:\n"
"1. high (numeric, required) The newer block timestamp\n"
"2. low (numeric, required) The older block timestamp\n"
"3. options (string, required) A json object\n"
" {\n"
" \"noOrphans\":true (boolean) will only include blocks on the main chain\n"
" \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n"
" }\n"
"\nResult:\n"
"[\n"
" \"hash\" (string) The block hash\n"
"]\n"
"[\n"
" {\n"
" \"blockhash\": (string) The block hash\n"
" \"logicalts\": (numeric) The logical timestamp\n"
" }\n"
"]\n"
"\nExamples:\n"
+ HelpExampleCli("getblockhashes", "1231614698 1231024505")
+ HelpExampleRpc("getblockhashes", "1231614698, 1231024505")
+ HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'")
);
unsigned int high = params[0].get_int();
unsigned int low = params[1].get_int();
bool fActiveOnly = false;
bool fLogicalTS = false;
if (params.size() > 2) {
if (params[2].isObject()) {
UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans");
UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes");
if (noOrphans.isBool())
fActiveOnly = noOrphans.get_bool();
if (returnLogical.isBool())
fLogicalTS = returnLogical.get_bool();
}
}
std::vector<std::pair<uint256, unsigned int> > blockHashes;
if (fActiveOnly)
LOCK(cs_main);
if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes");
}
UniValue result(UniValue::VARR);
for (std::vector<std::pair<uint256, unsigned int> >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) {
if (fLogicalTS) {
UniValue item(UniValue::VOBJ);
item.push_back(Pair("blockhash", it->first.GetHex()));
item.push_back(Pair("logicalts", (int)it->second));
result.push_back(item);
} else {
result.push_back(it->first.GetHex());
}
}
return result;
}
UniValue getblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -575,7 +316,6 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -635,7 +375,6 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"size\" : n, (numeric) The block size\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"tx\" : [ (array of string) The transaction ids\n"
" \"transactionid\" (string) The transaction id\n"
@@ -689,60 +428,6 @@ UniValue getblock(const UniValue& params, bool fHelp)
return blockToJSON(block, pblockindex);
}
struct CCoinsStats
{
int nHeight;
uint256 hashBlock;
uint64_t nTransactions;
uint64_t nTransactionOutputs;
uint64_t nSerializedSize;
uint256 hashSerialized;
CAmount nTotalAmount;
CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {}
};
//! Calculate statistics about the unspent transaction output set
static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
{
boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor());
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
stats.hashBlock = pcursor->GetBestBlock();
{
LOCK(cs_main);
stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
}
ss << stats.hashBlock;
CAmount nTotalAmount = 0;
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
uint256 key;
CCoins coins;
if (pcursor->GetKey(key) && pcursor->GetValue(coins)) {
stats.nTransactions++;
ss << key;
for (unsigned int i=0; i<coins.vout.size(); i++) {
const CTxOut &out = coins.vout[i];
if (!out.IsNull()) {
stats.nTransactionOutputs++;
ss << VARINT(i+1);
ss << out;
nTotalAmount += out.nValue;
}
}
stats.nSerializedSize += 32 + pcursor->GetValueSize();
ss << VARINT(0);
} else {
return error("%s: unable to read value", __func__);
}
pcursor->Next();
}
stats.hashSerialized = ss.GetHash();
stats.nTotalAmount = nTotalAmount;
return true;
}
UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -769,7 +454,7 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
CCoinsStats stats;
FlushStateToDisk();
if (GetUTXOStats(pcoinsTip, stats)) {
if (pcoinsTip->GetStats(stats)) {
ret.push_back(Pair("height", (int64_t)stats.nHeight));
ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
@@ -808,7 +493,6 @@ UniValue gettxout(const UniValue& params, bool fHelp)
" },\n"
" \"version\" : n, (numeric) The version\n"
" \"coinbase\" : true|false (boolean) Coinbase or not\n"
" \"coinstake\" : true|false (boolean) Coinstake or not\n"
"}\n"
"\nExamples:\n"
@@ -858,7 +542,6 @@ UniValue gettxout(const UniValue& params, bool fHelp)
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
ret.push_back(Pair("coinbase", coins.fCoinBase));
ret.push_back(Pair("coinstake", coins.fCoinStake));
return ret;
}
@@ -921,35 +604,6 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}
static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
UniValue rv(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
switch (thresholdState) {
case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
}
if (THRESHOLD_STARTED == thresholdState)
{
rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
}
rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
return rv;
}
void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// Deployments with timeout value of 0 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when softfork codes are merged without specifying the deployment schedule.
if (consensusParams.vDeployments[id].nTimeout > 0)
bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id)));
}
UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -962,10 +616,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
" \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
" \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
" \"difficulty\": { (json object)\n"
" \"proof-of-work\": xxxxxx, (numeric) the current proof-of-work difficulty\n"
" \"proof-of-stake\": xxxxxx (numeric) the current proof-of-stake difficulty\n"
" },\n"
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
" \"mediantime\": xxxxxx, (numeric) median time for the current best block\n"
" \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
" \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
@@ -983,15 +634,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" },\n"
" \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
" ],\n"
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
" \"xxxx\" : { (string) name of the softfork\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
" \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n"
" \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
" \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
" }\n"
" }\n"
" ]\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getblockchaininfo", "")
@@ -1000,17 +643,13 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
LOCK(cs_main);
UniValue diff(UniValue::VOBJ);
diff.push_back(Pair("proof-of-work", (double)GetDifficulty()));
diff.push_back(Pair("proof-of-stake", (double)GetDifficulty(GetLastBlockIndex(chainActive.Tip(), true))));
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
obj.push_back(Pair("difficulty", diff));
obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetPastTimeLimit()));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast()));
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
obj.push_back(Pair("pruned", fPruneMode));
@@ -1018,10 +657,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
const Consensus::Params& consensusParams = Params().GetConsensus();
CBlockIndex* tip = chainActive.Tip();
UniValue softforks(UniValue::VARR);
UniValue bip9_softforks(UniValue::VOBJ);
BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
obj.push_back(Pair("softforks", softforks));
obj.push_back(Pair("bip9_softforks", bip9_softforks));
if (fPruneMode)
{
@@ -1084,30 +723,17 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
LOCK(cs_main);
/*
* Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
* Algorithm:
* - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
* - add chainActive.Tip()
*/
/* Build up a list of chain tips. We start with the list of all
known blocks, and successively remove blocks that appear as pprev
of another block. */
std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs;
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
setTips.insert(item.second);
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
if (!chainActive.Contains(item.second)) {
setOrphans.insert(item.second);
setPrevs.insert(item.second->pprev);
}
}
for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
{
if (setPrevs.erase(*it) == 0) {
setTips.insert(*it);
}
const CBlockIndex* pprev = item.second->pprev;
if (pprev)
setTips.erase(pprev);
}
// Always report the currently active tip.

View File

@@ -14,16 +14,11 @@
#include "miner.h"
#include "net.h"
#include "pow.h"
#include "pos.h"
#include "rpcserver.h"
#include "txmempool.h"
#include "timedata.h"
#include "util.h"
#include "utilstrencodings.h"
#include "validationinterface.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include <stdint.h>
@@ -73,7 +68,7 @@ UniValue GetNetworkHashPS(int lookup, int height) {
arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
int64_t timeDiff = maxTime - minTime;
return workDiff.getdouble() / timeDiff;
return (int64_t)(workDiff.getdouble() / timeDiff);
}
UniValue getnetworkhashps(const UniValue& params, bool fHelp)
@@ -162,7 +157,7 @@ UniValue generate(const UniValue& params, bool fHelp)
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd)
{
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript, 0, false));
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
@@ -170,17 +165,16 @@ UniValue generate(const UniValue& params, bool fHelp)
LOCK(cs_main);
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
}
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
// Yes, there is a chance every nonce could fail to satisfy the -regtest
// target -- 1 in 2^(2^32). That ain't gonna happen.
++pblock->nNonce;
}
CValidationState state;
uint256 hash = pblock->GetHash();
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, hash))
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(hash.GetHex());
blockHashes.push_back(pblock->GetHash().GetHex());
//mark script as important because it was used at least for one coinbase output
coinbaseScript->KeepScript();
@@ -274,42 +268,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
return obj;
}
UniValue getstakinginfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getstakinginfo\n"
"Returns an object containing staking-related information.");
uint64_t nWeight = 0;
if (pwalletMain)
nWeight = pwalletMain->GetStakeWeight();
uint64_t nNetworkWeight = GetPoSKernelPS();
bool staking = nLastCoinStakeSearchInterval && nWeight;
uint64_t nExpectedTime = staking ? 1.0455 * 64 * nNetworkWeight / nWeight : 0;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("enabled", GetBoolArg("-staking", true)));
obj.push_back(Pair("staking", staking));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("difficulty", GetDifficulty(GetLastBlockIndex(chainActive.Tip(), true))));
obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval));
obj.push_back(Pair("weight", (uint64_t)nWeight));
obj.push_back(Pair("netstakeweight", (uint64_t)nNetworkWeight));
obj.push_back(Pair("expectedtime", nExpectedTime));
return obj;
}
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
UniValue prioritisetransaction(const UniValue& params, bool fHelp)
@@ -468,7 +426,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
CValidationState state;
TestBlockValidity(state, Params(), block, pindexPrev, false, true, true);
TestBlockValidity(state, Params(), block, pindexPrev, false, true);
return BIP22ValidationResult(state);
}
}
@@ -482,9 +440,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
if (chainActive.Tip()->nHeight > Params().GetConsensus().nLastPOWBlock)
throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks");
static unsigned int nTransactionsUpdatedLast;
if (!lpval.isNull())
@@ -555,7 +510,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
pblocktemplate = NULL;
}
CScript scriptDummy = CScript() << OP_TRUE;
pblocktemplate = CreateNewBlock(Params(), scriptDummy, 0, false);
pblocktemplate = CreateNewBlock(Params(), scriptDummy);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@@ -623,7 +578,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetPastTimeLimit()+1));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
@@ -695,9 +650,9 @@ UniValue submitblock(const UniValue& params, bool fHelp)
}
CValidationState state;
submitblock_StateCatcher sc(hash);
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, hash);
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
@@ -745,128 +700,6 @@ UniValue estimatefee(const UniValue& params, bool fHelp)
return ValueFromAmount(feeRate.GetFeePerK());
}
UniValue checkkernel(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"checkkernel [{\"txid\":txid,\"vout\":n},...] [createblocktemplate=false]\n"
"Check if one of given inputs is a kernel input at the moment.\n"
);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VBOOL));
UniValue inputs = params[0].get_array();
bool fCreateBlockTemplate = params.size() > 1 ? params[1].get_bool() : false;
if (vNodes.empty())
throw JSONRPCError(-9, "BlackCoin is not connected!");
if (IsInitialBlockDownload())
throw JSONRPCError(-10, "BlackCoin is downloading blocks...");
COutPoint kernel;
CBlockIndex* pindexPrev = chainActive.Tip();
CBlockHeader blockHeader = pindexPrev->GetBlockHeader();
unsigned int nBits = GetNextTargetRequired(pindexPrev, &blockHeader, true, Params().GetConsensus());
int64_t nTime = GetAdjustedTime();
nTime &= ~Params().GetConsensus().nStakeTimestampMask;
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
const UniValue& txid_v = find_value(o, "txid");
if (!txid_v.isStr())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
string txid = txid_v.get_str();
if (!IsHex(txid))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
const UniValue& vout_v = find_value(o, "vout");
if (!vout_v.isNum())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
int nOutput = vout_v.get_int();
if (nOutput < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
COutPoint cInput(uint256S(txid), nOutput);
if (CheckKernel(pindexPrev, nBits, nTime, cInput))
{
kernel = cInput;
break;
}
}
UniValue result(UniValue::VOBJ);
result.push_back(Pair("found", !kernel.IsNull()));
if (kernel.IsNull())
return result;
UniValue oKernel(UniValue::VOBJ);
oKernel.push_back(Pair("txid", kernel.hash.GetHex()));
oKernel.push_back(Pair("vout", (int64_t)kernel.n));
oKernel.push_back(Pair("time", nTime));
result.push_back(Pair("kernel", oKernel));
if (!fCreateBlockTemplate)
return result;
int64_t nFees;
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
CReserveKey pMiningKey(pwalletMain);
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), pMiningKey.reserveScript, &nFees, true));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
pblock->nTime = pblock->vtx[0].nTime = nTime;
CDataStream ss(SER_DISK, PROTOCOL_VERSION);
ss << *pblock;
result.push_back(Pair("blocktemplate", HexStr(ss.begin(), ss.end())));
result.push_back(Pair("blocktemplatefees", nFees));
CPubKey pubkey;
if (!pMiningKey.GetReservedKey(pubkey))
throw JSONRPCError(RPC_MISC_ERROR, "GetReservedKey failed");
result.push_back(Pair("blocktemplatesignkey", HexStr(pubkey)));
return result;
if (fHelp || params.size() != 1)
throw runtime_error(
"estimatefee nblocks\n"
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
"confirmation within nblocks blocks.\n"
"\nArguments:\n"
"1. nblocks (numeric)\n"
"\nResult:\n"
"n (numeric) estimated fee-per-kilobyte\n"
"\n"
"A negative value is returned if not enough transactions and blocks\n"
"have been observed to make an estimate.\n"
"\nExample:\n"
+ HelpExampleCli("estimatefee", "6")
);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)
nBlocks = 1;
CFeeRate feeRate = mempool.estimateFee(nBlocks);
if (feeRate == CFeeRate(0))
return -1.0;
return ValueFromAmount(feeRate.GetFeePerK());
}
UniValue estimatepriority(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)