diff options
Diffstat (limited to 'src/rpcblockchain.cpp')
| -rw-r--r-- | src/rpcblockchain.cpp | 150 |
1 files changed, 144 insertions, 6 deletions
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 7919fb1a0..293d6d561 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers +// 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. @@ -16,6 +16,7 @@ using namespace json_spirit; using namespace std; +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) @@ -50,7 +51,7 @@ double GetDifficulty(const CBlockIndex* blockindex) } -Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) +Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { Object result; result.push_back(Pair("hash", block.GetHash().GetHex())); @@ -65,7 +66,16 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); 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)); @@ -95,6 +105,7 @@ Value getblockcount(const Array& params, bool fHelp) + HelpExampleRpc("getblockcount", "") ); + LOCK(cs_main); return chainActive.Height(); } @@ -111,6 +122,7 @@ Value getbestblockhash(const Array& params, bool fHelp) + HelpExampleRpc("getbestblockhash", "") ); + LOCK(cs_main); return chainActive.Tip()->GetBlockHash().GetHex(); } @@ -127,6 +139,7 @@ Value getdifficulty(const Array& params, bool fHelp) + HelpExampleRpc("getdifficulty", "") ); + LOCK(cs_main); return GetDifficulty(); } @@ -163,6 +176,8 @@ Value getrawmempool(const Array& params, bool fHelp) + HelpExampleRpc("getrawmempool", "true") ); + LOCK(cs_main); + bool fVerbose = false; if (params.size() > 0) fVerbose = params[0].get_bool(); @@ -223,6 +238,8 @@ 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 JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); @@ -267,8 +284,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) @@ -316,10 +335,12 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) + HelpExampleRpc("gettxoutsetinfo", "") ); + LOCK(cs_main); + Object ret; CCoinsStats stats; - pcoinsTip->Flush(); + FlushStateToDisk(); if (pcoinsTip->GetStats(stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); @@ -370,10 +391,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) @@ -426,6 +449,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) @@ -457,6 +482,8 @@ Value getblockchaininfo(const Array& params, bool fHelp) + HelpExampleRpc("getblockchaininfo", "") ); + LOCK(cs_main); + Object obj; obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("blocks", (int)chainActive.Height())); @@ -496,18 +523,28 @@ Value getchaintips(const Array& params, bool fHelp) " \"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. */ @@ -521,6 +558,9 @@ Value getchaintips(const Array& params, bool fHelp) 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) @@ -532,6 +572,28 @@ Value getchaintips(const Array& params, bool fHelp) 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); } @@ -561,3 +623,79 @@ Value getmempoolinfo(const Array& params, bool fHelp) 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; +} |