Myriadcoin 0.11 port

This commit is contained in:
nzsquirrell
2016-02-24 20:34:22 +13:00
parent 5e70510c51
commit 5efd59f935
991 changed files with 109184 additions and 168045 deletions
+324 -78
View File
@@ -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;
}