mirror of
https://github.com/jwinterm/myriadcoin.git
synced 2026-10-27 06:18:45 +01:00
Myriadcoin 0.11 port
This commit is contained in:
+324
-78
@@ -1,13 +1,17 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "rpcserver.h"
|
||||
#include "main.h"
|
||||
#include "sync.h"
|
||||
#include "chainparams.h"
|
||||
#include "checkpoints.h"
|
||||
#include "auxpow.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "main.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "rpcserver.h"
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -16,30 +20,28 @@
|
||||
using namespace json_spirit;
|
||||
using namespace std;
|
||||
|
||||
// from rpcraw.cpp
|
||||
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
|
||||
|
||||
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
|
||||
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
|
||||
|
||||
double GetDifficulty(const CBlockIndex* blockindex, int algo)
|
||||
{
|
||||
unsigned int nBits;
|
||||
|
||||
unsigned int powLimit = UintToArith256(Params().GetConsensus().powLimit).GetCompact();
|
||||
// Floating point number that is a multiple of the minimum difficulty,
|
||||
// minimum difficulty = 1.0.
|
||||
if (blockindex == NULL)
|
||||
{
|
||||
CBlockIndex* tip = chainActive.Tip();
|
||||
if (tip == NULL)
|
||||
nBits = Params().ProofOfWorkLimit(ALGO_SHA256D).GetCompact();
|
||||
if (chainActive.Tip() == NULL)
|
||||
nBits = powLimit;
|
||||
else
|
||||
{
|
||||
blockindex = GetLastBlockIndexForAlgo(tip, algo);
|
||||
//blockindex = chainActive.Tip();
|
||||
blockindex = GetLastBlockIndexForAlgo(chainActive.Tip(), algo);
|
||||
if (blockindex == NULL)
|
||||
nBits = Params().ProofOfWorkLimit(algo).GetCompact();
|
||||
nBits = powLimit;
|
||||
else
|
||||
nBits = blockindex->nBits;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
nBits = blockindex->nBits;
|
||||
@@ -63,64 +65,74 @@ double GetDifficulty(const CBlockIndex* blockindex, int algo)
|
||||
return dDiff;
|
||||
}
|
||||
|
||||
static Object auxpowToJSON(const CAuxPow& auxpow)
|
||||
{
|
||||
Object tx;
|
||||
tx.push_back(Pair("hex", EncodeHexTx(auxpow)));
|
||||
TxToJSON(auxpow, auxpow.parentBlock.GetHash(), tx);
|
||||
|
||||
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||
Object result;
|
||||
result.push_back(Pair("tx", tx));
|
||||
result.push_back(Pair("index", auxpow.nIndex));
|
||||
result.push_back(Pair("chainindex", auxpow.nChainIndex));
|
||||
|
||||
Array branch;
|
||||
BOOST_FOREACH (const uint256& node, auxpow.vMerkleBranch)
|
||||
branch.push_back(node.GetHex());
|
||||
result.push_back(Pair("merklebranch", branch));
|
||||
|
||||
branch.clear();
|
||||
BOOST_FOREACH (const uint256& node, auxpow.vChainMerkleBranch)
|
||||
branch.push_back(node.GetHex());
|
||||
result.push_back(Pair("chainmerklebranch", branch));
|
||||
|
||||
CDataStream ssParent(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssParent << auxpow.parentBlock;
|
||||
const std::string strHex = HexStr(ssParent.begin(), ssParent.end());
|
||||
result.push_back(Pair("parentblock", strHex));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
|
||||
{
|
||||
Object result;
|
||||
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
||||
CMerkleTx txGen(block.vtx[0]);
|
||||
txGen.SetMerkleBranch(&block);
|
||||
result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
|
||||
int confirmations = -1;
|
||||
// Only report confirmations if the block is on the main chain
|
||||
if (chainActive.Contains(blockindex))
|
||||
confirmations = chainActive.Height() - blockindex->nHeight + 1;
|
||||
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("version", block.nVersion.GetFullVersion()));
|
||||
int algo = block.GetAlgo();
|
||||
result.push_back(Pair("pow_algo_id", algo));
|
||||
result.push_back(Pair("pow_algo", GetAlgoName(algo)));
|
||||
result.push_back(Pair("pow_hash", block.GetPoWHash(algo).GetHex()));
|
||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||
if (block.nVersion & BLOCK_VERSION_AUXPOW) {
|
||||
// this block includes auxpow
|
||||
Object auxpow;
|
||||
auxpow.push_back(Pair("size", (int)::GetSerializeSize(*block.auxpow, SER_NETWORK, PROTOCOL_VERSION)));
|
||||
|
||||
Object coinbasetx;
|
||||
TxToJSON(*block.auxpow, 0, coinbasetx);
|
||||
auxpow.push_back(Pair("coinbasetx", Value(coinbasetx)));
|
||||
|
||||
Array coinbaseMerkle;
|
||||
BOOST_FOREACH(const uint256 &hash, block.auxpow->vMerkleBranch)
|
||||
coinbaseMerkle.push_back(hash.GetHex());
|
||||
auxpow.push_back(Pair("coinbaseMerkleBranch", coinbaseMerkle));
|
||||
auxpow.push_back(Pair("coinbaseIndex", block.auxpow->nIndex));
|
||||
|
||||
Array chainMerkle;
|
||||
BOOST_FOREACH(const uint256 &hash, block.auxpow->vChainMerkleBranch)
|
||||
chainMerkle.push_back(hash.GetHex());
|
||||
auxpow.push_back(Pair("chainMerkleBranch", chainMerkle));
|
||||
auxpow.push_back(Pair("chainIndex", (boost::uint64_t)block.auxpow->nChainIndex));
|
||||
|
||||
Object parent_block;
|
||||
parent_block.push_back(Pair("hash", block.auxpow->parentBlockHeader.GetHash().GetHex()));
|
||||
parent_block.push_back(Pair("version", (boost::uint64_t)block.auxpow->parentBlockHeader.nVersion));
|
||||
parent_block.push_back(Pair("previousblockhash", block.auxpow->parentBlockHeader.hashPrevBlock.GetHex()));
|
||||
parent_block.push_back(Pair("merkleroot", block.auxpow->parentBlockHeader.hashMerkleRoot.GetHex()));
|
||||
parent_block.push_back(Pair("time", (boost::int64_t)block.auxpow->parentBlockHeader.nTime));
|
||||
parent_block.push_back(Pair("bits", HexBits(block.auxpow->parentBlockHeader.nBits)));
|
||||
parent_block.push_back(Pair("nonce", (boost::uint64_t)block.auxpow->parentBlockHeader.nNonce));
|
||||
auxpow.push_back(Pair("parent_block", Value(parent_block)));
|
||||
result.push_back(Pair("auxpow", Value(auxpow)));
|
||||
}
|
||||
Array txs;
|
||||
BOOST_FOREACH(const CTransaction&tx, block.vtx)
|
||||
txs.push_back(tx.GetHash().GetHex());
|
||||
{
|
||||
if(txDetails)
|
||||
{
|
||||
Object objTx;
|
||||
TxToJSON(tx, uint256(), objTx);
|
||||
txs.push_back(objTx);
|
||||
}
|
||||
else
|
||||
txs.push_back(tx.GetHash().GetHex());
|
||||
}
|
||||
result.push_back(Pair("tx", txs));
|
||||
result.push_back(Pair("time", block.GetBlockTime()));
|
||||
result.push_back(Pair("nonce", (uint64_t)block.nNonce));
|
||||
result.push_back(Pair("bits", HexBits(block.nBits)));
|
||||
result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
|
||||
result.push_back(Pair("difficulty", GetDifficulty(blockindex, miningAlgo)));
|
||||
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
|
||||
|
||||
if (block.auxpow)
|
||||
result.push_back(Pair("auxpow", auxpowToJSON(*block.auxpow)));
|
||||
|
||||
if (blockindex->pprev)
|
||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||
CBlockIndex *pnext = chainActive.Next(blockindex);
|
||||
@@ -143,6 +155,7 @@ Value getblockcount(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getblockcount", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
return chainActive.Height();
|
||||
}
|
||||
|
||||
@@ -159,6 +172,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getbestblockhash", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
return chainActive.Tip()->GetBlockHash().GetHex();
|
||||
}
|
||||
|
||||
@@ -175,6 +189,7 @@ Value getdifficulty(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getdifficulty", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
return GetDifficulty(NULL, miningAlgo);
|
||||
}
|
||||
|
||||
@@ -205,12 +220,14 @@ Value getrawmempool(const Array& params, bool fHelp)
|
||||
" \"transactionid\", (string) parent transaction id\n"
|
||||
" ... ]\n"
|
||||
" }, ...\n"
|
||||
"]\n"
|
||||
"}\n"
|
||||
"\nExamples\n"
|
||||
+ HelpExampleCli("getrawmempool", "true")
|
||||
+ HelpExampleRpc("getrawmempool", "true")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
bool fVerbose = false;
|
||||
if (params.size() > 0)
|
||||
fVerbose = params[0].get_bool();
|
||||
@@ -271,9 +288,11 @@ Value getblockhash(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getblockhash", "1000")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
int nHeight = params[0].get_int();
|
||||
if (nHeight < 0 || nHeight > chainActive.Height())
|
||||
throw runtime_error("Block number out of range.");
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
|
||||
CBlockIndex* pblockindex = chainActive[nHeight];
|
||||
return pblockindex->GetBlockHash().GetHex();
|
||||
@@ -292,10 +311,11 @@ Value getblock(const Array& params, bool fHelp)
|
||||
"\nResult (for verbose = true):\n"
|
||||
"{\n"
|
||||
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations\n"
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
|
||||
" \"size\" : n, (numeric) The block size\n"
|
||||
" \"height\" : n, (numeric) The block height or index\n"
|
||||
" \"version\" : n, (numeric) The block version\n"
|
||||
" \"pow_hash\" : \"xxxx\", (string) The proof-of-work hash\n"
|
||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
|
||||
" \"tx\" : [ (array of string) The transaction ids\n"
|
||||
" \"transactionid\" (string) The transaction id\n"
|
||||
@@ -315,8 +335,10 @@ Value getblock(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(strHash);
|
||||
uint256 hash(uint256S(strHash));
|
||||
|
||||
bool fVerbose = true;
|
||||
if (params.size() > 1)
|
||||
@@ -327,7 +349,12 @@ Value getblock(const Array& params, bool fHelp)
|
||||
|
||||
CBlock block;
|
||||
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||
ReadBlockFromDisk(block, pblockindex);
|
||||
|
||||
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
|
||||
|
||||
if(!ReadBlockFromDisk(block, pblockindex))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
|
||||
|
||||
if (!fVerbose)
|
||||
{
|
||||
@@ -362,9 +389,12 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("gettxoutsetinfo", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
Object ret;
|
||||
|
||||
CCoinsStats stats;
|
||||
FlushStateToDisk();
|
||||
if (pcoinsTip->GetStats(stats)) {
|
||||
ret.push_back(Pair("height", (int64_t)stats.nHeight));
|
||||
ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
|
||||
@@ -391,14 +421,14 @@ Value gettxout(const Array& params, bool fHelp)
|
||||
"{\n"
|
||||
" \"bestblock\" : \"hash\", (string) the block hash\n"
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations\n"
|
||||
" \"value\" : x.xxx, (numeric) The transaction value in btc\n"
|
||||
" \"value\" : x.xxx, (numeric) The transaction value in myr\n"
|
||||
" \"scriptPubKey\" : { (json object)\n"
|
||||
" \"asm\" : \"code\", (string) \n"
|
||||
" \"hex\" : \"hex\", (string) \n"
|
||||
" \"reqSigs\" : n, (numeric) Number of required signatures\n"
|
||||
" \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
|
||||
" \"addresses\" : [ (array of string) array of myriadcoin addresses\n"
|
||||
" \"myriadcoinaddress\" (string) myriadcoin address\n"
|
||||
" \"myriadcoinaddress\" (string) myriadcoin address\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
@@ -415,10 +445,12 @@ Value gettxout(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("gettxout", "\"txid\", 1")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
Object ret;
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(strHash);
|
||||
uint256 hash(uint256S(strHash));
|
||||
int n = params[1].get_int();
|
||||
bool fMempool = true;
|
||||
if (params.size() > 2)
|
||||
@@ -427,7 +459,7 @@ Value gettxout(const Array& params, bool fHelp)
|
||||
CCoins coins;
|
||||
if (fMempool) {
|
||||
LOCK(mempool.cs);
|
||||
CCoinsViewMemPool view(*pcoinsTip, mempool);
|
||||
CCoinsViewMemPool view(pcoinsTip, mempool);
|
||||
if (!view.GetCoins(hash, coins))
|
||||
return Value::null;
|
||||
mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
|
||||
@@ -438,7 +470,7 @@ Value gettxout(const Array& params, bool fHelp)
|
||||
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
|
||||
return Value::null;
|
||||
|
||||
std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
|
||||
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
|
||||
CBlockIndex *pindex = it->second;
|
||||
ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
|
||||
if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
|
||||
@@ -471,6 +503,8 @@ Value verifychain(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("verifychain", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
int nCheckLevel = GetArg("-checklevel", 3);
|
||||
int nCheckDepth = GetArg("-checkblocks", 288);
|
||||
if (params.size() > 0)
|
||||
@@ -478,7 +512,7 @@ Value verifychain(const Array& params, bool fHelp)
|
||||
if (params.size() > 1)
|
||||
nCheckDepth = params[1].get_int();
|
||||
|
||||
return VerifyDB(nCheckLevel, nCheckDepth);
|
||||
return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
|
||||
}
|
||||
|
||||
Value getblockchaininfo(const Array& params, bool fHelp)
|
||||
@@ -489,8 +523,9 @@ Value getblockchaininfo(const Array& params, bool fHelp)
|
||||
"Returns an object containing various state info regarding block chain processing.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"chain\": \"xxxx\", (string) current chain (main, testnet3, regtest)\n"
|
||||
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
|
||||
" \"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\": xxxxxx, (numeric) the current difficulty\n"
|
||||
" \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
|
||||
@@ -501,18 +536,229 @@ Value getblockchaininfo(const Array& params, bool fHelp)
|
||||
+ HelpExampleRpc("getblockchaininfo", "")
|
||||
);
|
||||
|
||||
proxyType proxy;
|
||||
GetProxy(NET_IPV4, proxy);
|
||||
LOCK(cs_main);
|
||||
|
||||
Object obj;
|
||||
std::string chain = Params().DataDir();
|
||||
if(chain.empty())
|
||||
chain = "main";
|
||||
obj.push_back(Pair("chain", chain));
|
||||
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||
obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty(NULL, miningAlgo)));
|
||||
obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(chainActive.Tip())));
|
||||
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
|
||||
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", (double)GetDifficulty(NULL, miningAlgo)));
|
||||
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));
|
||||
if (fPruneMode)
|
||||
{
|
||||
CBlockIndex *block = chainActive.Tip();
|
||||
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
|
||||
block = block->pprev;
|
||||
|
||||
obj.push_back(Pair("pruneheight", block->nHeight));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Comparison function for sorting the getchaintips heads. */
|
||||
struct CompareBlocksByHeight
|
||||
{
|
||||
bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
|
||||
{
|
||||
/* Make sure that unequal blocks with the same height do not compare
|
||||
equal. Use the pointers themselves to make a distinction. */
|
||||
|
||||
if (a->nHeight != b->nHeight)
|
||||
return (a->nHeight > b->nHeight);
|
||||
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
Value getchaintips(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getchaintips\n"
|
||||
"Return information about all known tips in the block tree,"
|
||||
" including the main chain as well as orphaned branches.\n"
|
||||
"\nResult:\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"height\": xxxx, (numeric) height of the chain tip\n"
|
||||
" \"hash\": \"xxxx\", (string) block hash of the tip\n"
|
||||
" \"branchlen\": 0 (numeric) zero for main chain\n"
|
||||
" \"status\": \"active\" (string) \"active\" for the main chain\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"height\": xxxx,\n"
|
||||
" \"hash\": \"xxxx\",\n"
|
||||
" \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
|
||||
" \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
"Possible values for status:\n"
|
||||
"1. \"invalid\" This branch contains at least one invalid block\n"
|
||||
"2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
|
||||
"3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
|
||||
"4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
|
||||
"5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getchaintips", "")
|
||||
+ HelpExampleRpc("getchaintips", "")
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
/* 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;
|
||||
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
|
||||
setTips.insert(item.second);
|
||||
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
|
||||
{
|
||||
const CBlockIndex* pprev = item.second->pprev;
|
||||
if (pprev)
|
||||
setTips.erase(pprev);
|
||||
}
|
||||
|
||||
// Always report the currently active tip.
|
||||
setTips.insert(chainActive.Tip());
|
||||
|
||||
/* Construct the output array. */
|
||||
Array res;
|
||||
BOOST_FOREACH(const CBlockIndex* block, setTips)
|
||||
{
|
||||
Object obj;
|
||||
obj.push_back(Pair("height", block->nHeight));
|
||||
obj.push_back(Pair("hash", block->phashBlock->GetHex()));
|
||||
|
||||
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
|
||||
obj.push_back(Pair("branchlen", branchLen));
|
||||
|
||||
string status;
|
||||
if (chainActive.Contains(block)) {
|
||||
// This block is part of the currently active chain.
|
||||
status = "active";
|
||||
} else if (block->nStatus & BLOCK_FAILED_MASK) {
|
||||
// This block or one of its ancestors is invalid.
|
||||
status = "invalid";
|
||||
} else if (block->nChainTx == 0) {
|
||||
// This block cannot be connected because full block data for it or one of its parents is missing.
|
||||
status = "headers-only";
|
||||
} else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
|
||||
// This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
|
||||
status = "valid-fork";
|
||||
} else if (block->IsValid(BLOCK_VALID_TREE)) {
|
||||
// The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
|
||||
status = "valid-headers";
|
||||
} else {
|
||||
// No clue.
|
||||
status = "unknown";
|
||||
}
|
||||
obj.push_back(Pair("status", status));
|
||||
|
||||
res.push_back(obj);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Value getmempoolinfo(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getmempoolinfo\n"
|
||||
"\nReturns details on the active state of the TX memory pool.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"size\": xxxxx (numeric) Current tx count\n"
|
||||
" \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getmempoolinfo", "")
|
||||
+ HelpExampleRpc("getmempoolinfo", "")
|
||||
);
|
||||
|
||||
Object ret;
|
||||
ret.push_back(Pair("size", (int64_t) mempool.size()));
|
||||
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Value invalidateblock(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"invalidateblock \"hash\"\n"
|
||||
"\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
|
||||
"\nArguments:\n"
|
||||
"1. hash (string, required) the hash of the block to mark as invalid\n"
|
||||
"\nResult:\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("invalidateblock", "\"blockhash\"")
|
||||
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
|
||||
);
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(uint256S(strHash));
|
||||
CValidationState state;
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (mapBlockIndex.count(hash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||
InvalidateBlock(state, pblockindex);
|
||||
}
|
||||
|
||||
if (state.IsValid()) {
|
||||
ActivateBestChain(state);
|
||||
}
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
||||
}
|
||||
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
Value reconsiderblock(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"reconsiderblock \"hash\"\n"
|
||||
"\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
|
||||
"This can be used to undo the effects of invalidateblock.\n"
|
||||
"\nArguments:\n"
|
||||
"1. hash (string, required) the hash of the block to reconsider\n"
|
||||
"\nResult:\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("reconsiderblock", "\"blockhash\"")
|
||||
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
|
||||
);
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(uint256S(strHash));
|
||||
CValidationState state;
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (mapBlockIndex.count(hash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||
ReconsiderBlock(state, pblockindex);
|
||||
}
|
||||
|
||||
if (state.IsValid()) {
|
||||
ActivateBestChain(state);
|
||||
}
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
||||
}
|
||||
|
||||
return Value::null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user