e4d9835464eed3a6873defac139c5ef0ee0836c9
[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
9 using namespace json_spirit;
10 using namespace std;
11
12 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry);
13 extern enum Checkpoints::CPMode CheckpointsMode;
14
15 double GetDifficulty(const CBlockIndex* blockindex)
16 {
17     // Floating point number that is a multiple of the minimum difficulty,
18     // minimum difficulty = 1.0.
19     if (blockindex == NULL)
20     {
21         if (pindexBest == NULL)
22             return 1.0;
23         else
24             blockindex = GetLastBlockIndex(pindexBest, false);
25     }
26
27     int nShift = (blockindex->nBits >> 24) & 0xff;
28
29     double dDiff =
30         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
31
32     while (nShift < 29)
33     {
34         dDiff *= 256.0;
35         nShift++;
36     }
37     while (nShift > 29)
38     {
39         dDiff /= 256.0;
40         nShift--;
41     }
42
43     return dDiff;
44 }
45
46 double GetPoWMHashPS()
47 {
48     int nPoWInterval = 72;
49     int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;
50
51     CBlockIndex* pindex = pindexGenesisBlock;
52     CBlockIndex* pindexPrevWork = pindexGenesisBlock;
53
54     while (pindex)
55     {
56         if (pindex->IsProofOfWork())
57         {
58             int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
59             nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1);
60             nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
61             pindexPrevWork = pindex;
62         }
63
64         pindex = pindex->pnext;
65     }
66
67     return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
68 }
69
70 double GetPoSKernelPS()
71 {
72     int nPoSInterval = 72;
73     double dStakeKernelsTriedAvg = 0;
74     int nStakesHandled = 0, nStakesTime = 0;
75
76     CBlockIndex* pindex = pindexBest;;
77     CBlockIndex* pindexPrevStake = NULL;
78
79     while (pindex && nStakesHandled < nPoSInterval)
80     {
81         if (pindex->IsProofOfStake())
82         {
83             dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0;
84             nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
85             pindexPrevStake = pindex;
86             nStakesHandled++;
87         }
88
89         pindex = pindex->pprev;
90     }
91
92     if (!nStakesHandled)
93         return 0;
94
95     return dStakeKernelsTriedAvg / nStakesTime;
96 }
97
98 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
99 {
100     Object result;
101     result.push_back(Pair("hash", block.GetHash().GetHex()));
102     CMerkleTx txGen(block.vtx[0]);
103     txGen.SetMerkleBranch(&block);
104     result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
105     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
106     result.push_back(Pair("height", blockindex->nHeight));
107     result.push_back(Pair("version", block.nVersion));
108     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
109     result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
110     result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
111     result.push_back(Pair("nonce", (uint64_t)block.nNonce));
112     result.push_back(Pair("bits", HexBits(block.nBits)));
113     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
114     result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
115     result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
116     if (blockindex->pprev)
117         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
118     if (blockindex->pnext)
119         result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
120
121     result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
122     result.push_back(Pair("proofhash", blockindex->IsProofOfStake()? blockindex->hashProofOfStake.GetHex() : blockindex->GetBlockHash().GetHex()));
123     result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
124     result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier)));
125     result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
126     Array txinfo;
127     BOOST_FOREACH (const CTransaction& tx, block.vtx)
128     {
129         if (fPrintTransactionDetail)
130         {
131             CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
132             ssTx << tx;
133             string strHex = HexStr(ssTx.begin(), ssTx.end());
134
135             txinfo.push_back(strHex);
136         }
137         else
138             txinfo.push_back(tx.GetHash().GetHex());
139     }
140
141     result.push_back(Pair("tx", txinfo));
142
143     if ( block.IsProofOfStake() )
144         result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));
145
146     return result;
147 }
148
149 Value getbestblockhash(const Array& params, bool fHelp)
150 {
151     if (fHelp || params.size() != 0)
152         throw runtime_error(
153             "getbestblockhash\n"
154             "Returns the hash of the best block in the longest block chain.");
155
156     return hashBestChain.GetHex();
157 }
158
159 Value getblockcount(const Array& params, bool fHelp)
160 {
161     if (fHelp || params.size() != 0)
162         throw runtime_error(
163             "getblockcount\n"
164             "Returns the number of blocks in the longest block chain.");
165
166     return nBestHeight;
167 }
168
169
170 Value getdifficulty(const Array& params, bool fHelp)
171 {
172     if (fHelp || params.size() != 0)
173         throw runtime_error(
174             "getdifficulty\n"
175             "Returns the difficulty as a multiple of the minimum difficulty.");
176
177     Object obj;
178     obj.push_back(Pair("proof-of-work",        GetDifficulty()));
179     obj.push_back(Pair("proof-of-stake",       GetDifficulty(GetLastBlockIndex(pindexBest, true))));
180     obj.push_back(Pair("search-interval",      (int)nLastCoinStakeSearchInterval));
181     return obj;
182 }
183
184
185 Value settxfee(const Array& params, bool fHelp)
186 {
187     if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
188         throw runtime_error(
189             "settxfee <amount>\n"
190             "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TX_FEE));
191
192     nTransactionFee = AmountFromValue(params[0]);
193     nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE;  // round to minimum fee
194
195     return true;
196 }
197
198 Value getrawmempool(const Array& params, bool fHelp)
199 {
200     if (fHelp || params.size() != 0)
201         throw runtime_error(
202             "getrawmempool\n"
203             "Returns all transaction ids in memory pool.");
204
205     vector<uint256> vtxid;
206     mempool.queryHashes(vtxid);
207
208     Array a;
209     BOOST_FOREACH(const uint256& hash, vtxid)
210         a.push_back(hash.ToString());
211
212     return a;
213 }
214
215 Value getblockhash(const Array& params, bool fHelp)
216 {
217     if (fHelp || params.size() != 1)
218         throw runtime_error(
219             "getblockhash <index>\n"
220             "Returns hash of block in best-block-chain at <index>.");
221
222     int nHeight = params[0].get_int();
223     if (nHeight < 0 || nHeight > nBestHeight)
224         throw runtime_error("Block number out of range.");
225
226     CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
227     return pblockindex->phashBlock->GetHex();
228 }
229
230 Value getblock(const Array& params, bool fHelp)
231 {
232     if (fHelp || params.size() < 1 || params.size() > 2)
233         throw runtime_error(
234             "getblock <hash> [txinfo]\n"
235             "txinfo optional to print more detailed tx info\n"
236             "Returns details of a block with given block-hash.");
237
238     std::string strHash = params[0].get_str();
239     uint256 hash(strHash);
240
241     if (mapBlockIndex.count(hash) == 0)
242         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
243
244     CBlock block;
245     CBlockIndex* pblockindex = mapBlockIndex[hash];
246     block.ReadFromDisk(pblockindex, true);
247
248     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
249 }
250
251 Value getblockbynumber(const Array& params, bool fHelp)
252 {
253     if (fHelp || params.size() < 1 || params.size() > 2)
254         throw runtime_error(
255             "getblockbynumber <number> [txinfo]\n"
256             "txinfo optional to print more detailed tx info\n"
257             "Returns details of a block with given block-number.");
258
259     int nHeight = params[0].get_int();
260     if (nHeight < 0 || nHeight > nBestHeight)
261         throw runtime_error("Block number out of range.");
262
263     CBlock block;
264     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
265     while (pblockindex->nHeight > nHeight)
266         pblockindex = pblockindex->pprev;
267
268     uint256 hash = *pblockindex->phashBlock;
269
270     pblockindex = mapBlockIndex[hash];
271     block.ReadFromDisk(pblockindex, true);
272
273     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
274 }
275
276 // get information of sync-checkpoint
277 Value getcheckpoint(const Array& params, bool fHelp)
278 {
279     if (fHelp || params.size() != 0)
280         throw runtime_error(
281             "getcheckpoint\n"
282             "Show info of synchronized checkpoint.\n");
283
284     Object result;
285     CBlockIndex* pindexCheckpoint;
286
287     result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
288     pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint];
289     result.push_back(Pair("height", pindexCheckpoint->nHeight));
290     result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));
291
292     if (Checkpoints::checkpointMessage.vchSig.size() != 0)
293     {
294         Object msgdata;
295         CUnsignedSyncCheckpoint checkpoint;
296
297         CDataStream sMsg(Checkpoints::checkpointMessage.vchMsg, SER_NETWORK, PROTOCOL_VERSION);
298         sMsg >> checkpoint;
299
300         Object parsed; // message version and data (block hash)
301         parsed.push_back(Pair("version", checkpoint.nVersion));
302         parsed.push_back(Pair("hash", checkpoint.hashCheckpoint.GetHex().c_str()));
303         msgdata.push_back(Pair("parsed", parsed));
304
305         Object raw; // raw checkpoint message data
306         raw.push_back(Pair("data", HexStr(Checkpoints::checkpointMessage.vchMsg).c_str()));
307         raw.push_back(Pair("signature", HexStr(Checkpoints::checkpointMessage.vchSig).c_str()));
308         msgdata.push_back(Pair("raw", raw));
309
310         result.push_back(Pair("data", msgdata));
311     }
312
313     // Check that the block satisfies synchronized checkpoint
314     if (CheckpointsMode == Checkpoints::STRICT)
315         result.push_back(Pair("policy", "strict"));
316
317     if (CheckpointsMode == Checkpoints::ADVISORY)
318         result.push_back(Pair("policy", "advisory"));
319
320     if (CheckpointsMode == Checkpoints::PERMISSIVE)
321         result.push_back(Pair("policy", "permissive"));
322
323     if (mapArgs.count("-checkpointkey"))
324         result.push_back(Pair("checkpointmaster", true));
325
326     return result;
327 }