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>
13 using namespace json_spirit;
16 extern void TxToJSON(const CTransaction& tx, const uint256& hashBlock, json_spirit::Object& entry);
17 extern enum Checkpoints::CPMode CheckpointsMode;
19 double GetDifficulty(const CBlockIndex* blockindex)
21 // Floating point number that is a multiple of the minimum difficulty,
22 // minimum difficulty = 1.0.
23 if (blockindex == NULL)
25 if (pindexBest == NULL)
28 blockindex = GetLastBlockIndex(pindexBest, false);
31 int nShift = (blockindex->nBits >> 24) & 0xff;
34 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
50 double GetPoWMHashPS()
52 int nPoWInterval = 72;
53 int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;
55 CBlockIndex* pindex = pindexGenesisBlock;
56 CBlockIndex* pindexPrevWork = pindexGenesisBlock;
60 if (pindex->IsProofOfWork())
62 int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
63 nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
64 nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
65 pindexPrevWork = pindex;
68 pindex = pindex->pnext;
71 return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
74 double GetPoSKernelPS()
76 int nPoSInterval = 72;
77 double dStakeKernelsTriedAvg = 0;
78 int nStakesHandled = 0, nStakesTime = 0;
80 CBlockIndex* pindex = pindexBest;;
81 CBlockIndex* pindexPrevStake = NULL;
83 while (pindex && nStakesHandled < nPoSInterval)
85 if (pindex->IsProofOfStake())
87 dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0;
88 nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
89 pindexPrevStake = pindex;
93 pindex = pindex->pprev;
96 if (!nStakesHandled || nStakesTime == 0)
99 return dStakeKernelsTriedAvg / nStakesTime;
102 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
105 result.push_back(Pair("hash", block.GetHash().GetHex()));
106 CMerkleTx txGen(block.vtx[0]);
107 txGen.SetMerkleBranch(&block);
108 result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
109 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
110 result.push_back(Pair("height", blockindex->nHeight));
111 result.push_back(Pair("version", block.nVersion));
112 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
113 result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
114 result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
115 result.push_back(Pair("nonce", (uint64_t)block.nNonce));
116 result.push_back(Pair("bits", HexBits(block.nBits)));
117 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
118 result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
119 result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
120 if (blockindex->pprev)
121 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
122 if (blockindex->pnext)
123 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
125 result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
126 result.push_back(Pair("proofhash", blockindex->IsProofOfStake()? blockindex->hashProofOfStake.GetHex() : blockindex->GetBlockHash().GetHex()));
127 result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
128 result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier)));
129 result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
131 for(const auto& tx : block.vtx)
133 if (fPrintTransactionDetail)
135 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
137 string strHex = HexStr(ssTx.begin(), ssTx.end());
139 txinfo.push_back(strHex);
142 txinfo.push_back(tx.GetHash().GetHex());
145 result.push_back(Pair("tx", txinfo));
147 if ( block.IsProofOfStake() )
148 result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));
153 Value getbestblockhash(const Array& params, bool fHelp)
155 if (fHelp || params.size() != 0)
158 "Returns the hash of the best block in the longest block chain.");
160 return hashBestChain.GetHex();
163 Value getblockcount(const Array& params, bool fHelp)
165 if (fHelp || params.size() != 0)
168 "Returns the number of blocks in the longest block chain.");
174 Value getdifficulty(const Array& params, bool fHelp)
176 if (fHelp || params.size() != 0)
179 "Returns the difficulty as a multiple of the minimum difficulty.");
182 obj.push_back(Pair("proof-of-work", GetDifficulty()));
183 obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true))));
184 obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval));
189 Value settxfee(const Array& params, bool fHelp)
191 if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
193 "settxfee <amount>\n"
194 "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TX_FEE));
196 nTransactionFee = AmountFromValue(params[0]);
197 nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE; // round to minimum fee
202 Value getrawmempool(const Array& params, bool fHelp)
204 if (fHelp || params.size() != 0)
207 "Returns all transaction ids in memory pool.");
209 vector<uint256> vtxid;
210 mempool.queryHashes(vtxid);
213 for(const uint256& hash : vtxid)
214 a.push_back(hash.ToString());
219 Value getblockhash(const Array& params, bool fHelp)
221 if (fHelp || params.size() != 1)
223 "getblockhash <index>\n"
224 "Returns hash of block in best-block-chain at <index>.");
226 int nHeight = params[0].get_int();
227 if (nHeight < 0 || nHeight > nBestHeight)
228 throw runtime_error("Block number out of range.");
230 CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
231 return pblockindex->phashBlock->GetHex();
234 Value getblock(const Array& params, bool fHelp)
236 if (fHelp || params.size() < 1 || params.size() > 2)
238 "getblock <hash> [txinfo]\n"
239 "txinfo optional to print more detailed tx info\n"
240 "Returns details of a block with given block-hash.");
242 std::string strHash = params[0].get_str();
243 uint256 hash(strHash);
245 if (mapBlockIndex.count(hash) == 0)
246 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
249 CBlockIndex* pblockindex = mapBlockIndex[hash];
250 block.ReadFromDisk(pblockindex, true);
252 return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
255 Value getblockbynumber(const Array& params, bool fHelp)
257 if (fHelp || params.size() < 1 || params.size() > 2)
259 "getblockbynumber <number> [txinfo]\n"
260 "txinfo optional to print more detailed tx info\n"
261 "Returns details of a block with given block-number.");
263 int nHeight = params[0].get_int();
264 if (nHeight < 0 || nHeight > nBestHeight)
265 throw runtime_error("Block number out of range.");
268 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
269 while (pblockindex->nHeight > nHeight)
270 pblockindex = pblockindex->pprev;
272 pblockindex = mapBlockIndex[*pblockindex->phashBlock];
273 block.ReadFromDisk(pblockindex, true);
275 return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
278 bool ExportBlock(const string& strBlockHash, const CDataStream& ssBlock)
280 boost::filesystem::path pathDest = GetDataDir() / strBlockHash;
281 if (boost::filesystem::is_directory(pathDest))
282 pathDest /= strBlockHash;
285 boost::iostreams::stream_buffer<boost::iostreams::file_sink> buf(pathDest.string());
286 ostream exportStream(&buf);
287 exportStream << HexStr(ssBlock.begin(), ssBlock.end());
288 exportStream.flush();
290 printf("Successfully exported block to %s\n", pathDest.string().c_str());
292 } catch(const boost::filesystem::filesystem_error &e) {
293 printf("error exporting the block data %s (%s)\n", pathDest.string().c_str(), e.what());
299 Value dumpblock(const Array& params, bool fHelp)
301 if (fHelp || params.size() < 1 || params.size() > 2)
303 "dumpblock <hash> [destination]\n"
304 "Returns serialized contents of a block with given block-hash.");
306 std::string strHash = params[0].get_str();
307 uint256 hash(strHash);
309 if (mapBlockIndex.count(hash) == 0)
310 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
313 CBlockIndex* pblockindex = mapBlockIndex[hash];
314 block.ReadFromDisk(pblockindex, true);
316 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
319 if (params.size() > 1)
321 return ExportBlock(params[1].get_str(), ssBlock);
324 return HexStr(ssBlock.begin(), ssBlock.end());
328 Value dumpblockbynumber(const Array& params, bool fHelp)
330 if (fHelp || params.size() < 1 || params.size() > 2)
332 "dumpblockbynumber <number> [destination]\n"
333 "Returns serialized contents of a block with given block-number.");
335 int nHeight = params[0].get_int();
336 if (nHeight < 0 || nHeight > nBestHeight)
337 throw runtime_error("Block number out of range.");
340 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
341 while (pblockindex->nHeight > nHeight)
342 pblockindex = pblockindex->pprev;
344 pblockindex = mapBlockIndex[*pblockindex->phashBlock];
345 block.ReadFromDisk(pblockindex, true);
347 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
350 if (params.size() > 1)
352 return ExportBlock(params[1].get_str(), ssBlock);
355 return HexStr(ssBlock.begin(), ssBlock.end());
359 // get information of sync-checkpoint
360 Value getcheckpoint(const Array& params, bool fHelp)
362 if (fHelp || params.size() != 0)
365 "Show info of synchronized checkpoint.\n");
368 CBlockIndex* pindexCheckpoint;
370 result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
371 pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint];
372 result.push_back(Pair("height", pindexCheckpoint->nHeight));
373 result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));
375 if (Checkpoints::checkpointMessage.vchSig.size() != 0)
378 CUnsignedSyncCheckpoint checkpoint;
380 CDataStream sMsg(Checkpoints::checkpointMessage.vchMsg, SER_NETWORK, PROTOCOL_VERSION);
383 Object parsed; // message version and data (block hash)
384 parsed.push_back(Pair("version", checkpoint.nVersion));
385 parsed.push_back(Pair("hash", checkpoint.hashCheckpoint.GetHex().c_str()));
386 msgdata.push_back(Pair("parsed", parsed));
388 Object raw; // raw checkpoint message data
389 raw.push_back(Pair("data", HexStr(Checkpoints::checkpointMessage.vchMsg).c_str()));
390 raw.push_back(Pair("signature", HexStr(Checkpoints::checkpointMessage.vchSig).c_str()));
391 msgdata.push_back(Pair("raw", raw));
393 result.push_back(Pair("data", msgdata));
396 // Check that the block satisfies synchronized checkpoint
397 if (CheckpointsMode == Checkpoints::CP_STRICT)
398 result.push_back(Pair("policy", "strict"));
400 if (CheckpointsMode == Checkpoints::CP_ADVISORY)
401 result.push_back(Pair("policy", "advisory"));
403 if (CheckpointsMode == Checkpoints::CP_PERMISSIVE)
404 result.push_back(Pair("policy", "permissive"));
406 if (mapArgs.count("-checkpointkey"))
407 result.push_back(Pair("checkpointmaster", true));