Update CMakeLists.txt - play with openssl
[novacoin.git] / src / rpcblockchain.cpp
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.
5
6 #include "main.h"
7 #include "bitcoinrpc.h"
8 #include <boost/filesystem.hpp>
9 #include <boost/iostreams/device/file.hpp>
10 #include <boost/iostreams/stream.hpp>
11
12 using namespace json_spirit;
13 using namespace std;
14
15 extern void TxToJSON(const CTransaction& tx, const uint256& hashBlock, json_spirit::Object& entry);
16 extern enum Checkpoints::CPMode CheckpointsMode;
17
18 double GetDifficulty(const CBlockIndex* blockindex)
19 {
20     // Floating point number that is a multiple of the minimum difficulty,
21     // minimum difficulty = 1.0.
22     if (blockindex == NULL)
23     {
24         if (pindexBest == NULL)
25             return 1.0;
26         else
27             blockindex = GetLastBlockIndex(pindexBest, false);
28     }
29
30     int nShift = (blockindex->nBits >> 24) & 0xff;
31
32     double dDiff =
33         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
34
35     while (nShift < 29)
36     {
37         dDiff *= 256.0;
38         nShift++;
39     }
40     while (nShift > 29)
41     {
42         dDiff /= 256.0;
43         nShift--;
44     }
45
46     return dDiff;
47 }
48
49 double GetPoWMHashPS()
50 {
51     int nPoWInterval = 72;
52     int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;
53
54     CBlockIndex* pindex = pindexGenesisBlock;
55     CBlockIndex* pindexPrevWork = pindexGenesisBlock;
56
57     while (pindex)
58     {
59         if (pindex->IsProofOfWork())
60         {
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;
65         }
66
67         pindex = pindex->pnext;
68     }
69
70     return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
71 }
72
73 double GetPoSKernelPS()
74 {
75     int nPoSInterval = 72;
76     double dStakeKernelsTriedAvg = 0;
77     int nStakesHandled = 0, nStakesTime = 0;
78
79     CBlockIndex* pindex = pindexBest;
80     CBlockIndex* pindexPrevStake = NULL;
81
82     while (pindex && nStakesHandled < nPoSInterval)
83     {
84         if (pindex->IsProofOfStake())
85         {
86             dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0;
87             nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
88             pindexPrevStake = pindex;
89             nStakesHandled++;
90         }
91
92         pindex = pindex->pprev;
93     }
94
95     if (!nStakesHandled)
96         return 0;
97
98     return dStakeKernelsTriedAvg / nStakesTime;
99 }
100
101 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
102 {
103     Object result;
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()));
123
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)));
129     Array txinfo;
130     for (const CTransaction& tx : block.vtx)
131     {
132         if (fPrintTransactionDetail)
133         {
134             CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
135             ssTx << tx;
136             string strHex = HexStr(ssTx.begin(), ssTx.end());
137
138             txinfo.push_back(strHex);
139         }
140         else
141             txinfo.push_back(tx.GetHash().GetHex());
142     }
143
144     result.push_back(Pair("tx", txinfo));
145
146     if ( block.IsProofOfStake() )
147         result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));
148
149     return result;
150 }
151
152 Value getbestblockhash(const Array& params, bool fHelp)
153 {
154     if (fHelp || params.size() != 0)
155         throw runtime_error(
156             "getbestblockhash\n"
157             "Returns the hash of the best block in the longest block chain.");
158
159     return hashBestChain.GetHex();
160 }
161
162 Value getblockcount(const Array& params, bool fHelp)
163 {
164     if (fHelp || params.size() != 0)
165         throw runtime_error(
166             "getblockcount\n"
167             "Returns the number of blocks in the longest block chain.");
168
169     return nBestHeight;
170 }
171
172
173 Value getdifficulty(const Array& params, bool fHelp)
174 {
175     if (fHelp || params.size() != 0)
176         throw runtime_error(
177             "getdifficulty\n"
178             "Returns the difficulty as a multiple of the minimum difficulty.");
179
180     Object obj;
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));
184     return obj;
185 }
186
187
188 Value settxfee(const Array& params, bool fHelp)
189 {
190     if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
191         throw runtime_error(
192             "settxfee <amount>\n"
193             "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TX_FEE));
194
195     nTransactionFee = AmountFromValue(params[0]);
196     nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE;  // round to minimum fee
197
198     return true;
199 }
200
201 Value getrawmempool(const Array& params, bool fHelp)
202 {
203     if (fHelp || params.size() != 0)
204         throw runtime_error(
205             "getrawmempool\n"
206             "Returns all transaction ids in memory pool.");
207
208     vector<uint256> vtxid;
209     mempool.queryHashes(vtxid);
210
211     Array a;
212     for (const uint256& hash : vtxid)
213         a.push_back(hash.ToString());
214
215     return a;
216 }
217
218 Value getblockhash(const Array& params, bool fHelp)
219 {
220     if (fHelp || params.size() != 1)
221         throw runtime_error(
222             "getblockhash <index>\n"
223             "Returns hash of block in best-block-chain at <index>.");
224
225     int nHeight = params[0].get_int();
226     if (nHeight < 0 || nHeight > nBestHeight)
227         throw runtime_error("Block number out of range.");
228
229     CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
230     return pblockindex->phashBlock->GetHex();
231 }
232
233 Value getblock(const Array& params, bool fHelp)
234 {
235     if (fHelp || params.size() < 1 || params.size() > 2)
236         throw runtime_error(
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.");
240
241     std::string strHash = params[0].get_str();
242     uint256 hash(strHash);
243
244     if (mapBlockIndex.count(hash) == 0)
245         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
246
247     CBlock block;
248     CBlockIndex* pblockindex = mapBlockIndex[hash];
249     block.ReadFromDisk(pblockindex, true);
250
251     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
252 }
253
254 Value getblockbynumber(const Array& params, bool fHelp)
255 {
256     if (fHelp || params.size() < 1 || params.size() > 2)
257         throw runtime_error(
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.");
261
262     int nHeight = params[0].get_int();
263     if (nHeight < 0 || nHeight > nBestHeight)
264         throw runtime_error("Block number out of range.");
265
266     CBlock block;
267     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
268     while (pblockindex->nHeight > nHeight)
269         pblockindex = pblockindex->pprev;
270
271     pblockindex = mapBlockIndex[*pblockindex->phashBlock];
272     block.ReadFromDisk(pblockindex, true);
273
274     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
275 }
276
277 bool ExportBlock(const string& strBlockHash, const CDataStream& ssBlock)
278 {
279     boost::filesystem::path pathDest = GetDataDir() / strBlockHash;
280     if (boost::filesystem::is_directory(pathDest))
281         pathDest /= strBlockHash;
282
283     try {
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();
288
289         printf("Successfully exported block to %s\n", pathDest.string().c_str());
290         return true;
291     } catch(const boost::filesystem::filesystem_error &e) {
292         printf("error exporting the block data %s (%s)\n", pathDest.string().c_str(), e.what());
293         return false;
294     }
295 }
296
297
298 Value dumpblock(const Array& params, bool fHelp)
299 {
300     if (fHelp || params.size() < 1 || params.size() > 2)
301         throw runtime_error(
302             "dumpblock <hash> [destination]\n"
303             "Returns serialized contents of a block with given block-hash.");
304
305     std::string strHash = params[0].get_str();
306     uint256 hash(strHash);
307
308     if (mapBlockIndex.count(hash) == 0)
309         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
310
311     CBlock block;
312     CBlockIndex* pblockindex = mapBlockIndex[hash];
313     block.ReadFromDisk(pblockindex, true);
314
315     CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
316     ssBlock << block;
317
318     if (params.size() > 1)
319     {
320         return ExportBlock(params[1].get_str(), ssBlock);
321     }
322
323     return HexStr(ssBlock.begin(), ssBlock.end());
324 }
325
326
327 Value dumpblockbynumber(const Array& params, bool fHelp)
328 {
329     if (fHelp || params.size() < 1 || params.size() > 2)
330         throw runtime_error(
331             "dumpblockbynumber <number>  [destination]\n"
332             "Returns serialized contents of a block with given block-number.");
333
334     int nHeight = params[0].get_int();
335     if (nHeight < 0 || nHeight > nBestHeight)
336         throw runtime_error("Block number out of range.");
337
338     CBlock block;
339     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
340     while (pblockindex->nHeight > nHeight)
341         pblockindex = pblockindex->pprev;
342
343     pblockindex = mapBlockIndex[*pblockindex->phashBlock];
344     block.ReadFromDisk(pblockindex, true);
345
346     CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
347     ssBlock << block;
348
349     if (params.size() > 1)
350     {
351         return ExportBlock(params[1].get_str(), ssBlock);
352     }
353
354     return HexStr(ssBlock.begin(), ssBlock.end());
355 }
356
357
358 // get information of sync-checkpoint
359 Value getcheckpoint(const Array& params, bool fHelp)
360 {
361     if (fHelp || params.size() != 0)
362         throw runtime_error(
363             "getcheckpoint\n"
364             "Show info of synchronized checkpoint.\n");
365
366     Object result;
367     CBlockIndex* pindexCheckpoint;
368
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()));
373
374     if (Checkpoints::checkpointMessage.vchSig.size() != 0)
375     {
376         Object msgdata;
377         CUnsignedSyncCheckpoint checkpoint;
378
379         CDataStream sMsg(Checkpoints::checkpointMessage.vchMsg, SER_NETWORK, PROTOCOL_VERSION);
380         sMsg >> checkpoint;
381
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));
386
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));
391
392         result.push_back(Pair("data", msgdata));
393     }
394
395     // Check that the block satisfies synchronized checkpoint
396     if (CheckpointsMode == Checkpoints::STRICT)
397         result.push_back(Pair("policy", "strict"));
398
399     if (CheckpointsMode == Checkpoints::ADVISORY)
400         result.push_back(Pair("policy", "advisory"));
401
402     if (CheckpointsMode == Checkpoints::PERMISSIVE)
403         result.push_back(Pair("policy", "permissive"));
404
405     if (mapArgs.count("-checkpointkey"))
406         result.push_back(Pair("checkpointmaster", true));
407
408     return result;
409 }