1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #include "bitcoinrpc.h"
8 #include <boost/filesystem.hpp>
9 #include <boost/iostreams/device/file.hpp>
10 #include <boost/iostreams/stream.hpp>
12 using namespace json_spirit;
15 extern void TxToJSON(const CTransaction& tx, const uint256& hashBlock, json_spirit::Object& entry);
16 extern enum Checkpoints::CPMode CheckpointsMode;
18 double GetDifficulty(const CBlockIndex* blockindex)
20 // Floating point number that is a multiple of the minimum difficulty,
21 // minimum difficulty = 1.0.
22 if (blockindex == NULL)
24 if (pindexBest == NULL)
27 blockindex = GetLastBlockIndex(pindexBest, false);
30 int nShift = (blockindex->nBits >> 24) & 0xff;
33 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
49 double GetPoWMHashPS()
51 int nPoWInterval = 72;
52 int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;
54 CBlockIndex* pindex = pindexGenesisBlock;
55 CBlockIndex* pindexPrevWork = pindexGenesisBlock;
59 if (pindex->IsProofOfWork())
61 int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
62 nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
63 nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
64 pindexPrevWork = pindex;
67 pindex = pindex->pnext;
70 return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
73 double GetPoSKernelPS()
75 int nPoSInterval = 72;
76 double dStakeKernelsTriedAvg = 0;
77 int nStakesHandled = 0, nStakesTime = 0;
79 CBlockIndex* pindex = pindexBest;
80 CBlockIndex* pindexPrevStake = NULL;
82 while (pindex && nStakesHandled < nPoSInterval)
84 if (pindex->IsProofOfStake())
86 dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0;
87 nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
88 pindexPrevStake = pindex;
92 pindex = pindex->pprev;
98 return dStakeKernelsTriedAvg / nStakesTime;
101 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
104 result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
105 CMerkleTx txGen(block.vtx[0]);
106 txGen.SetMerkleBranch(&block);
107 result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
108 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
109 result.push_back(Pair("height", blockindex->nHeight));
110 result.push_back(Pair("version", block.nVersion));
111 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
112 result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
113 result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
114 result.push_back(Pair("nonce", (uint64_t)block.nNonce));
115 result.push_back(Pair("bits", HexBits(block.nBits)));
116 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
117 result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
118 result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
119 if (blockindex->pprev)
120 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
121 if (blockindex->pnext)
122 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
124 result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
125 result.push_back(Pair("proofhash", blockindex->IsProofOfStake()? blockindex->hashProofOfStake.GetHex() : blockindex->GetBlockHash().GetHex()));
126 result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
127 result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier)));
128 result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
130 for (const CTransaction& tx : block.vtx)
132 if (fPrintTransactionDetail)
134 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
136 string strHex = HexStr(ssTx.begin(), ssTx.end());
138 txinfo.push_back(strHex);
141 txinfo.push_back(tx.GetHash().GetHex());
144 result.push_back(Pair("tx", txinfo));
146 if ( block.IsProofOfStake() )
147 result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));
152 Value getbestblockhash(const Array& params, bool fHelp)
154 if (fHelp || params.size() != 0)
157 "Returns the hash of the best block in the longest block chain.");
159 return hashBestChain.GetHex();
162 Value getblockcount(const Array& params, bool fHelp)
164 if (fHelp || params.size() != 0)
167 "Returns the number of blocks in the longest block chain.");
173 Value getdifficulty(const Array& params, bool fHelp)
175 if (fHelp || params.size() != 0)
178 "Returns the difficulty as a multiple of the minimum difficulty.");
181 obj.push_back(Pair("proof-of-work", GetDifficulty()));
182 obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true))));
183 obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval));
188 Value settxfee(const Array& params, bool fHelp)
190 if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
192 "settxfee <amount>\n"
193 "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TX_FEE));
195 nTransactionFee = AmountFromValue(params[0]);
196 nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE; // round to minimum fee
201 Value getrawmempool(const Array& params, bool fHelp)
203 if (fHelp || params.size() != 0)
206 "Returns all transaction ids in memory pool.");
208 vector<uint256> vtxid;
209 mempool.queryHashes(vtxid);
212 for (const uint256& hash : vtxid)
213 a.push_back(hash.ToString());
218 Value getblockhash(const Array& params, bool fHelp)
220 if (fHelp || params.size() != 1)
222 "getblockhash <index>\n"
223 "Returns hash of block in best-block-chain at <index>.");
225 int nHeight = params[0].get_int();
226 if (nHeight < 0 || nHeight > nBestHeight)
227 throw runtime_error("Block number out of range.");
229 CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
230 return pblockindex->phashBlock->GetHex();
233 Value getblock(const Array& params, bool fHelp)
235 if (fHelp || params.size() < 1 || params.size() > 2)
237 "getblock <hash> [txinfo]\n"
238 "txinfo optional to print more detailed tx info\n"
239 "Returns details of a block with given block-hash.");
241 std::string strHash = params[0].get_str();
242 uint256 hash(strHash);
244 if (mapBlockIndex.count(hash) == 0)
245 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
248 CBlockIndex* pblockindex = mapBlockIndex[hash];
249 block.ReadFromDisk(pblockindex, true);
251 return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
254 Value getblockbynumber(const Array& params, bool fHelp)
256 if (fHelp || params.size() < 1 || params.size() > 2)
258 "getblockbynumber <number> [txinfo]\n"
259 "txinfo optional to print more detailed tx info\n"
260 "Returns details of a block with given block-number.");
262 int nHeight = params[0].get_int();
263 if (nHeight < 0 || nHeight > nBestHeight)
264 throw runtime_error("Block number out of range.");
267 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
268 while (pblockindex->nHeight > nHeight)
269 pblockindex = pblockindex->pprev;
271 pblockindex = mapBlockIndex[*pblockindex->phashBlock];
272 block.ReadFromDisk(pblockindex, true);
274 return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
277 bool ExportBlock(const string& strBlockHash, const CDataStream& ssBlock)
279 boost::filesystem::path pathDest = GetDataDir() / strBlockHash;
280 if (boost::filesystem::is_directory(pathDest))
281 pathDest /= strBlockHash;
284 boost::iostreams::stream_buffer<boost::iostreams::file_sink> buf(pathDest.string());
285 ostream exportStream(&buf);
286 exportStream << HexStr(ssBlock.begin(), ssBlock.end());
287 exportStream.flush();
289 printf("Successfully exported block to %s\n", pathDest.string().c_str());
291 } catch(const boost::filesystem::filesystem_error &e) {
292 printf("error exporting the block data %s (%s)\n", pathDest.string().c_str(), e.what());
298 Value dumpblock(const Array& params, bool fHelp)
300 if (fHelp || params.size() < 1 || params.size() > 2)
302 "dumpblock <hash> [destination]\n"
303 "Returns serialized contents of a block with given block-hash.");
305 std::string strHash = params[0].get_str();
306 uint256 hash(strHash);
308 if (mapBlockIndex.count(hash) == 0)
309 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
312 CBlockIndex* pblockindex = mapBlockIndex[hash];
313 block.ReadFromDisk(pblockindex, true);
315 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
318 if (params.size() > 1)
320 return ExportBlock(params[1].get_str(), ssBlock);
323 return HexStr(ssBlock.begin(), ssBlock.end());
327 Value dumpblockbynumber(const Array& params, bool fHelp)
329 if (fHelp || params.size() < 1 || params.size() > 2)
331 "dumpblockbynumber <number> [destination]\n"
332 "Returns serialized contents of a block with given block-number.");
334 int nHeight = params[0].get_int();
335 if (nHeight < 0 || nHeight > nBestHeight)
336 throw runtime_error("Block number out of range.");
339 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
340 while (pblockindex->nHeight > nHeight)
341 pblockindex = pblockindex->pprev;
343 pblockindex = mapBlockIndex[*pblockindex->phashBlock];
344 block.ReadFromDisk(pblockindex, true);
346 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
349 if (params.size() > 1)
351 return ExportBlock(params[1].get_str(), ssBlock);
354 return HexStr(ssBlock.begin(), ssBlock.end());
358 // get information of sync-checkpoint
359 Value getcheckpoint(const Array& params, bool fHelp)
361 if (fHelp || params.size() != 0)
364 "Show info of synchronized checkpoint.\n");
367 CBlockIndex* pindexCheckpoint;
369 result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
370 pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint];
371 result.push_back(Pair("height", pindexCheckpoint->nHeight));
372 result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));
374 if (Checkpoints::checkpointMessage.vchSig.size() != 0)
377 CUnsignedSyncCheckpoint checkpoint;
379 CDataStream sMsg(Checkpoints::checkpointMessage.vchMsg, SER_NETWORK, PROTOCOL_VERSION);
382 Object parsed; // message version and data (block hash)
383 parsed.push_back(Pair("version", checkpoint.nVersion));
384 parsed.push_back(Pair("hash", checkpoint.hashCheckpoint.GetHex().c_str()));
385 msgdata.push_back(Pair("parsed", parsed));
387 Object raw; // raw checkpoint message data
388 raw.push_back(Pair("data", HexStr(Checkpoints::checkpointMessage.vchMsg).c_str()));
389 raw.push_back(Pair("signature", HexStr(Checkpoints::checkpointMessage.vchSig).c_str()));
390 msgdata.push_back(Pair("raw", raw));
392 result.push_back(Pair("data", msgdata));
395 // Check that the block satisfies synchronized checkpoint
396 if (CheckpointsMode == Checkpoints::STRICT)
397 result.push_back(Pair("policy", "strict"));
399 if (CheckpointsMode == Checkpoints::ADVISORY)
400 result.push_back(Pair("policy", "advisory"));
402 if (CheckpointsMode == Checkpoints::PERMISSIVE)
403 result.push_back(Pair("policy", "permissive"));
405 if (mapArgs.count("-checkpointkey"))
406 result.push_back(Pair("checkpointmaster", true));