X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbitcoinrpc.cpp;h=a8ad00017272267f9128d33e3a23b7cb24730d55;hb=f1af842f0fd26cb19d6f1161f7b161ae5386b980;hp=04faea9972d91ca254076a5b129137df6023b0a1;hpb=58561410692c520d91def67c36aadf8edd992272;p=novacoin.git diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 04faea9..a8ad000 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers -// Copyright (c) 2011-2012 The PPCoin developers +// Copyright (c) 2011-2013 The PPCoin developers +// Copyright (c) 2013 NovaCoin Developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -136,7 +137,7 @@ string AccountFromValue(const Value& value) return strAccount; } -Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) +Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail) { Object result; result.push_back(Pair("hash", block.GetHash().GetHex())); @@ -144,19 +145,36 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime())); + result.push_back(Pair("time", DateTimeStrFormat(block.GetBlockTime()))); result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce)); result.push_back(Pair("bits", HexBits(block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - Array txhashes; - BOOST_FOREACH (const CTransaction&tx, block.vtx) - txhashes.push_back(tx.GetHash().GetHex()); - result.push_back(Pair("tx", txhashes)); - + result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint))); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); if (blockindex->pnext) result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); + result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": ""))); + result.push_back(Pair("proofhash", blockindex->IsProofOfStake()? blockindex->hashProofOfStake.GetHex() : blockindex->GetBlockHash().GetHex())); + result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit())); + result.push_back(Pair("modifier", strprintf("%016"PRI64x, blockindex->nStakeModifier))); + result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum))); + Array txinfo; + BOOST_FOREACH (const CTransaction& tx, block.vtx) + { + if (fPrintTransactionDetail) + { + txinfo.push_back(tx.ToStringShort()); + txinfo.push_back(DateTimeStrFormat(tx.nTime)); + BOOST_FOREACH(const CTxIn& txin, tx.vin) + txinfo.push_back(txin.ToStringShort()); + BOOST_FOREACH(const CTxOut& txout, tx.vout) + txinfo.push_back(txout.ToStringShort()); + } + else + txinfo.push_back(tx.GetHash().GetHex()); + } + result.push_back(Pair("tx", txinfo)); return result; } @@ -225,10 +243,10 @@ Value stop(const Array& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( "stop\n" - "Stop ppcoin server."); + "Stop novacoin server."); // Shutdown will take long enough that the response should get back StartShutdown(); - return "ppcoin server stopping"; + return "novacoin server stopping"; } @@ -271,9 +289,13 @@ Value getdifficulty(const Array& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( "getdifficulty\n" - "Returns the proof-of-work difficulty as a multiple of the minimum difficulty."); + "Returns difficulty as a multiple of the minimum difficulty."); - return GetDifficulty(); + Object obj; + obj.push_back(Pair("proof-of-work", GetDifficulty())); + obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); + obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); + return obj; } @@ -342,6 +364,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); @@ -384,7 +407,7 @@ Value getnewaddress(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw runtime_error( "getnewaddress [account]\n" - "Returns a new ppcoin address for receiving payments. " + "Returns a new novacoin address for receiving payments. " "If [account] is specified (recommended), it is added to the address book " "so payments received with the address will be credited to [account]."); @@ -451,7 +474,7 @@ Value getaccountaddress(const Array& params, bool fHelp) if (fHelp || params.size() != 1) throw runtime_error( "getaccountaddress \n" - "Returns the current ppcoin address for receiving payments to this account."); + "Returns the current novacoin address for receiving payments to this account."); // Parse the account first so we don't generate a key if there's an error string strAccount = AccountFromValue(params[0]); @@ -469,12 +492,12 @@ Value setaccount(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "setaccount \n" + "setaccount \n" "Sets the account associated with the given address."); CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid ppcoin address"); + throw JSONRPCError(-5, "Invalid novacoin address"); string strAccount; @@ -499,12 +522,12 @@ Value getaccount(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "getaccount \n" + "getaccount \n" "Returns the account associated with the given address."); CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid ppcoin address"); + throw JSONRPCError(-5, "Invalid novacoin address"); string strAccount; map::iterator mi = pwalletMain->mapAddressBook.find(address); @@ -552,20 +575,22 @@ Value sendtoaddress(const Array& params, bool fHelp) { if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4)) throw runtime_error( - "sendtoaddress [comment] [comment-to]\n" + "sendtoaddress [comment] [comment-to]\n" " is a real and is rounded to the nearest 0.000001\n" "requires wallet passphrase to be set with walletpassphrase first"); if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4)) throw runtime_error( - "sendtoaddress [comment] [comment-to]\n" + "sendtoaddress [comment] [comment-to]\n" " is a real and is rounded to the nearest 0.000001"); CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid ppcoin address"); + throw JSONRPCError(-5, "Invalid novacoin address"); // Amount int64 nAmount = AmountFromValue(params[1]); + if (nAmount < MIN_TXOUT_AMOUNT) + throw JSONRPCError(-101, "Send amount too small"); // Wallet comments CWalletTx wtx; @@ -588,7 +613,7 @@ Value signmessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) throw runtime_error( - "signmessage \n" + "signmessage \n" "Sign a message with the private key of an address"); if (pwalletMain->IsLocked()) @@ -620,7 +645,7 @@ Value verifymessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 3) throw runtime_error( - "verifymessage \n" + "verifymessage \n" "Verify a signed message"); string strAddress = params[0].get_str(); @@ -653,14 +678,14 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getreceivedbyaddress [minconf=1]\n" - "Returns the total amount received by in transactions with at least [minconf] confirmations."); + "getreceivedbyaddress [minconf=1]\n" + "Returns the total amount received by in transactions with at least [minconf] confirmations."); // Bitcoin address CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); CScript scriptPubKey; if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid ppcoin address"); + throw JSONRPCError(-5, "Invalid novacoin address"); scriptPubKey.SetBitcoinAddress(address); if (!IsMine(*pwalletMain,scriptPubKey)) return (double)0.0; @@ -875,19 +900,21 @@ Value sendfrom(const Array& params, bool fHelp) { if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6)) throw runtime_error( - "sendfrom [minconf=1] [comment] [comment-to]\n" + "sendfrom [minconf=1] [comment] [comment-to]\n" " is a real and is rounded to the nearest 0.000001\n" "requires wallet passphrase to be set with walletpassphrase first"); if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6)) throw runtime_error( - "sendfrom [minconf=1] [comment] [comment-to]\n" + "sendfrom [minconf=1] [comment] [comment-to]\n" " is a real and is rounded to the nearest 0.000001"); string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid ppcoin address"); + throw JSONRPCError(-5, "Invalid novacoin address"); int64 nAmount = AmountFromValue(params[2]); + if (nAmount < MIN_TXOUT_AMOUNT) + throw JSONRPCError(-101, "Send amount too small"); int nMinDepth = 1; if (params.size() > 3) nMinDepth = params[3].get_int(); @@ -947,7 +974,7 @@ Value sendmany(const Array& params, bool fHelp) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(-5, string("Invalid ppcoin address:")+s.name_); + throw JSONRPCError(-5, string("Invalid novacoin address:")+s.name_); if (setAddress.count(address)) throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_); @@ -956,6 +983,8 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetBitcoinAddress(address); int64 nAmount = AmountFromValue(s.value_); + if (nAmount < MIN_TXOUT_AMOUNT) + throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; vecSend.push_back(make_pair(scriptPubKey, nAmount)); @@ -963,8 +992,8 @@ Value sendmany(const Array& params, bool fHelp) if (pwalletMain->IsLocked()) throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); - if (fWalletUnlockStakeOnly) - throw JSONRPCError(-13, "Error: Wallet unlocked for coinstake only."); + if (fWalletUnlockMintOnly) + throw JSONRPCError(-13, "Error: Wallet unlocked for block minting only."); // Check funds int64 nBalance = GetAccountBalance(strAccount, nMinDepth); @@ -1592,9 +1621,9 @@ Value walletpassphrase(const Array& params, bool fHelp) { if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 3)) throw runtime_error( - "walletpassphrase [stakeonly]\n" + "walletpassphrase [mintonly]\n" "Stores the wallet decryption key in memory for seconds.\n" - "stakeonly is optional true/false allowing only stake creation."); + "mintonly is optional true/false allowing only block minting."); if (fHelp) return true; if (!pwalletMain->IsCrypted()) @@ -1626,9 +1655,9 @@ Value walletpassphrase(const Array& params, bool fHelp) // ppcoin: if user OS account compromised prevent trivial sendmoney commands if (params.size() > 2) - fWalletUnlockStakeOnly = params[2].get_bool(); + fWalletUnlockMintOnly = params[2].get_bool(); else - fWalletUnlockStakeOnly = false; + fWalletUnlockMintOnly = false; return Value::null; } @@ -1719,7 +1748,7 @@ Value encryptwallet(const Array& params, bool fHelp) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; ppcoin server stopping, restart to run with encrypted wallet"; + return "wallet encrypted; novacoin server stopping, restart to run with encrypted wallet"; } @@ -1727,8 +1756,8 @@ Value validateaddress(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "validateaddress \n" - "Return information about ."); + "validateaddress \n" + "Return information about ."); CBitcoinAddress address(params[0].get_str()); bool isValid = address.IsValid(); @@ -1777,6 +1806,50 @@ Value validateaddress(const Array& params, bool fHelp) return ret; } +Value validatepubkey(const Array& params, bool fHelp) +{ + if (fHelp || !params.size() || params.size() > 2) + throw runtime_error( + "validatepubkey \n" + "Return information about ."); + + std::vector vchPubKey = ParseHex(params[0].get_str()); + bool isValid; + + if(vchPubKey.size() == 33) // Compressed key + isValid = (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03); + else if(vchPubKey.size() == 65) // Uncompressed key + isValid = vchPubKey[0] == 0x04; + else + isValid = false; + + CBitcoinAddress address(vchPubKey); + isValid = isValid ? address.IsValid() : false; + + Object ret; + ret.push_back(Pair("isvalid", isValid)); + if (isValid) + { + // Call Hash160ToAddress() so we always return current ADDRESSVERSION + // version of the address: + string currentAddress = address.ToString(); + ret.push_back(Pair("address", currentAddress)); + if (pwalletMain->HaveKey(address)) + { + ret.push_back(Pair("ismine", true)); + CKey key; + key.SetPubKey(vchPubKey); + ret.push_back(Pair("iscompressed", key.IsCompressed())); + } + else + ret.push_back(Pair("ismine", false)); + if (pwalletMain->mapAddressBook.count(address)) + ret.push_back(Pair("account", pwalletMain->mapAddressBook[address])); + } + return ret; +} + + Value getwork(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) @@ -1790,10 +1863,10 @@ Value getwork(const Array& params, bool fHelp) "If [data] is specified, tries to solve the block and returns true if it was successful."); if (vNodes.empty()) - throw JSONRPCError(-9, "PPCoin is not connected!"); + throw JSONRPCError(-9, "NovaCoin is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "PPCoin is downloading blocks..."); + throw JSONRPCError(-10, "NovaCoin is downloading blocks..."); typedef map > mapNewBlock_t; static mapNewBlock_t mapNewBlock; @@ -1823,7 +1896,7 @@ Value getwork(const Array& params, bool fHelp) nStart = GetTime(); // Create new block - pblock = CreateNewBlock(pwalletMain, true); + pblock = CreateNewBlock(pwalletMain); if (!pblock) throw JSONRPCError(-7, "Out of memory"); vNewBlock.push_back(pblock); @@ -1877,12 +1950,196 @@ Value getwork(const Array& params, bool fHelp) pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; pblock->hashMerkleRoot = pblock->BuildMerkleTree(); if (!pblock->SignBlock(*pwalletMain)) - throw JSONRPCError(-100, "Unable to sign block"); + throw JSONRPCError(-100, "Unable to sign block, wallet locked?"); return CheckWork(pblock, *pwalletMain, reservekey); } } +Value getblocktemplate(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getblocktemplate [params]\n" + "Returns data needed to construct a block to work on:\n" + " \"version\" : block version\n" + " \"previousblockhash\" : hash of current highest block\n" + " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n" + " \"coinbaseaux\" : data that should be included in coinbase\n" + " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n" + " \"target\" : hash target\n" + " \"mintime\" : minimum timestamp appropriate for next block\n" + " \"curtime\" : current timestamp\n" + " \"mutable\" : list of ways the block template may be changed\n" + " \"noncerange\" : range of valid nonces\n" + " \"sigoplimit\" : limit of sigops in blocks\n" + " \"sizelimit\" : limit of block size\n" + " \"bits\" : compressed target of next block\n" + " \"height\" : height of the next block\n" + "See https://en.bitcoin.it/wiki/BIP_0022 for full specification."); + + std::string strMode = "template"; + if (params.size() > 0) + { + const Object& oparam = params[0].get_obj(); + const Value& modeval = find_value(oparam, "mode"); + if (modeval.type() == str_type) + strMode = modeval.get_str(); + else + throw JSONRPCError(-8, "Invalid mode"); + } + + if (strMode != "template") + throw JSONRPCError(-8, "Invalid mode"); + + if (vNodes.empty()) + throw JSONRPCError(-9, "NovaCoin is not connected!"); + + if (IsInitialBlockDownload()) + throw JSONRPCError(-10, "NovaCoin is downloading blocks..."); + + static CReserveKey reservekey(pwalletMain); + + // Update block + static unsigned int nTransactionsUpdatedLast; + static CBlockIndex* pindexPrev; + static int64 nStart; + static CBlock* pblock; + if (pindexPrev != pindexBest || + (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5)) + { + // Clear pindexPrev so future calls make a new block, despite any failures from here on + pindexPrev = NULL; + + // Store the pindexBest used before CreateNewBlock, to avoid races + nTransactionsUpdatedLast = nTransactionsUpdated; + CBlockIndex* pindexPrevNew = pindexBest; + nStart = GetTime(); + + // Create new block + if(pblock) + { + delete pblock; + pblock = NULL; + } + pblock = CreateNewBlock(pwalletMain); + if (!pblock) + throw JSONRPCError(-7, "Out of memory"); + + // Need to update only after we know CreateNewBlock succeeded + pindexPrev = pindexPrevNew; + } + + // Update nTime + pblock->UpdateTime(pindexPrev); + pblock->nNonce = 0; + + Array transactions; + map setTxIndex; + int i = 0; + CTxDB txdb("r"); + BOOST_FOREACH (CTransaction& tx, pblock->vtx) + { + uint256 txHash = tx.GetHash(); + setTxIndex[txHash] = i++; + + if (tx.IsCoinBase() || tx.IsCoinStake()) + continue; + + Object entry; + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end()))); + + entry.push_back(Pair("hash", txHash.GetHex())); + + MapPrevTx mapInputs; + map mapUnused; + bool fInvalid = false; + if (tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) + { + entry.push_back(Pair("fee", (int64_t)(tx.GetValueIn(mapInputs) - tx.GetValueOut()))); + + Array deps; + BOOST_FOREACH (MapPrevTx::value_type& inp, mapInputs) + { + if (setTxIndex.count(inp.first)) + deps.push_back(setTxIndex[inp.first]); + } + entry.push_back(Pair("depends", deps)); + + int64_t nSigOps = tx.GetLegacySigOpCount(); + nSigOps += tx.GetP2SHSigOpCount(mapInputs); + entry.push_back(Pair("sigops", nSigOps)); + } + + transactions.push_back(entry); + } + + Object aux; + aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); + + uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + + static Array aMutable; + if (aMutable.empty()) + { + aMutable.push_back("time"); + aMutable.push_back("transactions"); + aMutable.push_back("prevblock"); + } + + Object result; + result.push_back(Pair("version", pblock->nVersion)); + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); + result.push_back(Pair("transactions", transactions)); + result.push_back(Pair("coinbaseaux", aux)); + result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + result.push_back(Pair("target", hashTarget.GetHex())); + result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); + result.push_back(Pair("mutable", aMutable)); + result.push_back(Pair("noncerange", "00000000ffffffff")); + result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); + result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); + result.push_back(Pair("curtime", (int64_t)pblock->nTime)); + result.push_back(Pair("bits", HexBits(pblock->nBits))); + result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); + + return result; +} + +Value submitblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "submitblock [optional-params-obj]\n" + "[optional-params-obj] parameter is currently ignored.\n" + "Attempts to submit new block to network.\n" + "See https://en.bitcoin.it/wiki/BIP_0022 for full specification."); + + vector blockData(ParseHex(params[0].get_str())); + CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); + CBlock block; + try { + ssBlock >> block; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "Block decode failed"); + } + + static CReserveKey reservekey(pwalletMain); + + if(!block.SignBlock(*pwalletMain)) + throw JSONRPCError(-100, "Unable to sign block, wallet locked?"); + + bool fAccepted = CheckWork(&block, *pwalletMain, reservekey); + if (!fAccepted) + return "rejected"; + + return Value::null; +} + Value getmemorypool(const Array& params, bool fHelp) { @@ -1904,10 +2161,10 @@ Value getmemorypool(const Array& params, bool fHelp) if (params.size() == 0) { if (vNodes.empty()) - throw JSONRPCError(-9, "PPCoin is not connected!"); + throw JSONRPCError(-9, "NovaCoin is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "PPCoin is downloading blocks..."); + throw JSONRPCError(-10, "NovaCoin is downloading blocks..."); static CReserveKey reservekey(pwalletMain); @@ -1966,10 +2223,42 @@ Value getmemorypool(const Array& params, bool fHelp) CBlock pblock; ssBlock >> pblock; - return ProcessBlock(NULL, &pblock); + static CReserveKey reservekey(pwalletMain); + + if(!pblock.SignBlock(*pwalletMain)) + throw JSONRPCError(-100, "Unable to sign block, wallet locked?"); + + return CheckWork(&pblock, *pwalletMain, reservekey); } } +Value getnewpubkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getnewpubkey [account]\n" + "Returns new public key for coinbase generation."); + + // Parse the account first so we don't generate a key if there's an error + string strAccount; + if (params.size() > 0) + strAccount = AccountFromValue(params[0]); + + if (!pwalletMain->IsLocked()) + pwalletMain->TopUpKeyPool(); + + // Generate a new key that is added to wallet + std::vector newKey = pwalletMain->GenerateNewKey(false); + + if(!newKey.size()) + throw JSONRPCError(-12, "Error: Unable to create key"); + + CBitcoinAddress address(newKey); + pwalletMain->SetAddressBookName(address, strAccount); + + return HexStr(newKey.begin(), newKey.end()); +} + Value getblockhash(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1990,9 +2279,10 @@ Value getblockhash(const Array& params, bool fHelp) Value getblock(const Array& params, bool fHelp) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getblock \n" + "getblock [txinfo]\n" + "txinfo optional to print more detailed tx info\n" "Returns details of a block with given block-hash."); std::string strHash = params[0].get_str(); @@ -2005,9 +2295,33 @@ Value getblock(const Array& params, bool fHelp) CBlockIndex* pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); - return blockToJSON(block, pblockindex); + return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); } +Value getblockbynumber(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblock [txinfo]\n" + "txinfo optional to print more detailed tx info\n" + "Returns details of a block with given block-number."); + + int nHeight = params[0].get_int(); + if (nHeight < 0 || nHeight > nBestHeight) + throw runtime_error("Block number out of range."); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; + while (pblockindex->nHeight > nHeight) + pblockindex = pblockindex->pprev; + + uint256 hash = *pblockindex->phashBlock; + + pblockindex = mapBlockIndex[hash]; + block.ReadFromDisk(pblockindex, true); + + return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); +} // ppcoin: get information of sync-checkpoint Value getcheckpoint(const Array& params, bool fHelp) @@ -2024,7 +2338,9 @@ Value getcheckpoint(const Array& params, bool fHelp) pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); - + if (mapArgs.count("-checkpointkey")) + result.push_back(Pair("checkpointmaster", true)); + return result; } @@ -2081,14 +2397,16 @@ Value checkwallet(const Array& params, bool fHelp) int nMismatchSpent; int64 nBalanceInQuestion; - if (!pwalletMain->CheckSpentCoins(nMismatchSpent, nBalanceInQuestion)) + pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion, true); + Object result; + if (nMismatchSpent == 0) + result.push_back(Pair("wallet check passed", true)); + else { - Object result; result.push_back(Pair("mismatched spent coins", nMismatchSpent)); result.push_back(Pair("amount in question", ValueFromAmount(nBalanceInQuestion))); - return result; } - return Value::null; + return result; } @@ -2105,9 +2423,7 @@ Value repairwallet(const Array& params, bool fHelp) pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion); Object result; if (nMismatchSpent == 0) - { result.push_back(Pair("wallet check passed", true)); - } else { result.push_back(Pair("mismatched spent coins", nMismatchSpent)); @@ -2116,6 +2432,21 @@ Value repairwallet(const Array& params, bool fHelp) return result; } +// NovaCoin: resend unconfirmed wallet transactions +Value resendtx(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "resendtx\n" + "Re-send unconfirmed transactions.\n" + ); + + ResendWalletTransactions(); + + return Value::null; +} + + // ppcoin: make a public-private key pair Value makekeypair(const Array& params, bool fHelp) { @@ -2156,16 +2487,17 @@ extern map mapAlerts; // ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() Value sendalert(const Array& params, bool fHelp) { - if (fHelp || params.size() < 5) + if (fHelp || params.size() < 6) throw runtime_error( - "sendalert [cancelupto]\n" + "sendalert [cancelupto]\n" " is the alert text message\n" " is hex string of alert master private key\n" - " is the minimum applicable client version\n" - " is the maximum applicable client version\n" + " is the minimum applicable internal client version\n" + " is the maximum applicable internal client version\n" + " is integer priority number\n" " is the alert id\n" "[cancelupto] cancels all alert id's up to this number\n" - "Returns true or false."); + "Returns true or false."); CAlert alert; CKey key; @@ -2173,13 +2505,13 @@ Value sendalert(const Array& params, bool fHelp) alert.strStatusBar = params[0].get_str(); alert.nMinVer = params[2].get_int(); alert.nMaxVer = params[3].get_int(); - alert.nID = params[4].get_int(); - if (params.size() > 5) - alert.nCancel = params[5].get_int(); + alert.nPriority = params[4].get_int(); + alert.nID = params[5].get_int(); + if (params.size() > 6) + alert.nCancel = params[6].get_int(); alert.nVersion = PROTOCOL_VERSION; alert.nRelayUntil = GetAdjustedTime() + 365*24*60*60; alert.nExpiration = GetAdjustedTime() + 365*24*60*60; - alert.nPriority = 1; CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); sMsg << (CUnsignedAlert)alert; @@ -2205,37 +2537,13 @@ Value sendalert(const Array& params, bool fHelp) result.push_back(Pair("nVersion", alert.nVersion)); result.push_back(Pair("nMinVer", alert.nMinVer)); result.push_back(Pair("nMaxVer", alert.nMaxVer)); + result.push_back(Pair("nPriority", alert.nPriority)); result.push_back(Pair("nID", alert.nID)); if (alert.nCancel > 0) result.push_back(Pair("nCancel", alert.nCancel)); return result; } -// ppcoin: set checkpoint key -Value setcheckpointkey(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "setcheckpointkey \n" - " is hex string of checkpoint master private key\n"); - - CSyncCheckpoint checkpoint; - checkpoint.hashCheckpoint = hashGenesisBlock; - CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); - sMsg << (CUnsignedSyncCheckpoint)checkpoint; - checkpoint.vchMsg = vector(sMsg.begin(), sMsg.end()); - - vector vchPrivKey = ParseHex(params[0].get_str()); - CKey key; - key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash - if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) - throw runtime_error( - "Unable to sign checkpoint, check private key?\n"); - - CSyncCheckpoint::strMasterPrivKey = params[0].get_str(); - - return "checkpoint master key has been set."; -} // @@ -2258,6 +2566,7 @@ static const CRPCCommand vRPCCommands[] = { "getinfo", &getinfo, true }, { "getmininginfo", &getmininginfo, true }, { "getnewaddress", &getnewaddress, true }, + { "getnewpubkey", &getnewpubkey, true }, { "getaccountaddress", &getaccountaddress, true }, { "setaccount", &setaccount, true }, { "getaccount", &getaccount, false }, @@ -2274,6 +2583,7 @@ static const CRPCCommand vRPCCommands[] = { "walletlock", &walletlock, true }, { "encryptwallet", &encryptwallet, false }, { "validateaddress", &validateaddress, true }, + { "validatepubkey", &validatepubkey, true }, { "getbalance", &getbalance, false }, { "move", &movecmd, false }, { "sendfrom", &sendfrom, false }, @@ -2281,6 +2591,7 @@ static const CRPCCommand vRPCCommands[] = { "addmultisigaddress", &addmultisigaddress, false }, { "getblock", &getblock, false }, { "getblockhash", &getblockhash, false }, + { "getblockbynumber", &getblockbynumber, false }, { "gettransaction", &gettransaction, false }, { "listtransactions", &listtransactions, false }, { "signmessage", &signmessage, false }, @@ -2289,6 +2600,8 @@ static const CRPCCommand vRPCCommands[] = { "listaccounts", &listaccounts, false }, { "settxfee", &settxfee, false }, { "getmemorypool", &getmemorypool, true }, + { "getblocktemplate", &getblocktemplate, true }, + { "submitblock", &submitblock, false }, { "listsinceblock", &listsinceblock, false }, { "dumpprivkey", &dumpprivkey, false }, { "importprivkey", &importprivkey, false }, @@ -2296,9 +2609,9 @@ static const CRPCCommand vRPCCommands[] = { "reservebalance", &reservebalance, false}, { "checkwallet", &checkwallet, false}, { "repairwallet", &repairwallet, false}, + { "resendtx", &resendtx, false}, { "makekeypair", &makekeypair, false}, { "sendalert", &sendalert, false}, - { "setcheckpointkey", &setcheckpointkey, false}, }; CRPCTable::CRPCTable() @@ -2332,7 +2645,7 @@ string HTTPPost(const string& strMsg, const map& mapRequestHeader { ostringstream s; s << "POST / HTTP/1.1\r\n" - << "User-Agent: ppcoin-json-rpc/" << FormatFullVersion() << "\r\n" + << "User-Agent: novacoin-json-rpc/" << FormatFullVersion() << "\r\n" << "Host: 127.0.0.1\r\n" << "Content-Type: application/json\r\n" << "Content-Length: " << strMsg.size() << "\r\n" @@ -2363,7 +2676,7 @@ static string HTTPReply(int nStatus, const string& strMsg) if (nStatus == 401) return strprintf("HTTP/1.0 401 Authorization Required\r\n" "Date: %s\r\n" - "Server: ppcoin-json-rpc/%s\r\n" + "Server: novacoin-json-rpc/%s\r\n" "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n" "Content-Type: text/html\r\n" "Content-Length: 296\r\n" @@ -2390,7 +2703,7 @@ static string HTTPReply(int nStatus, const string& strMsg) "Connection: close\r\n" "Content-Length: %d\r\n" "Content-Type: application/json\r\n" - "Server: ppcoin-json-rpc/%s\r\n" + "Server: novacoin-json-rpc/%s\r\n" "\r\n" "%s", nStatus, @@ -2604,7 +2917,7 @@ void ThreadRPCServer2(void* parg) { unsigned char rand_pwd[32]; RAND_bytes(rand_pwd, 32); - string strWhatAmI = "To use ppcoind"; + string strWhatAmI = "To use novacoind"; if (mapArgs.count("-server")) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); else if (mapArgs.count("-daemon")) @@ -2612,7 +2925,7 @@ void ThreadRPCServer2(void* parg) ThreadSafeMessageBox(strprintf( _("%s, you must set a rpcpassword in the configuration file:\n %s\n" "It is recommended you use the following random password:\n" - "rpcuser=bitcoinrpc\n" + "rpcuser=novarpc\n" "rpcpassword=%s\n" "(you do not need to remember this password)\n" "If the file does not exist, create it with owner-readable-only file permissions.\n"), @@ -2902,6 +3215,9 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); + if (strMethod == "getblockbynumber" && n > 0) ConvertTo(params[0]); + if (strMethod == "getblockbynumber" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); if (strMethod == "move" && n > 2) ConvertTo(params[2]); if (strMethod == "move" && n > 3) ConvertTo(params[3]); if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); @@ -2916,6 +3232,7 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "sendalert" && n > 3) ConvertTo(params[3]); if (strMethod == "sendalert" && n > 4) ConvertTo(params[4]); if (strMethod == "sendalert" && n > 5) ConvertTo(params[5]); + if (strMethod == "sendalert" && n > 6) ConvertTo(params[6]); if (strMethod == "sendmany" && n > 1) { string s = params[1].get_str();