return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
}
+unsigned int BitsHex(std::string HexBits)
+{
+ union {
+ int32_t nBits;
+ char cBits[4];
+ } uBits;
+
+ vector<unsigned char> vchBits = ParseHex(HexBits);
+ copy(vchBits.begin(), vchBits.begin() + 4, uBits.cBits);
+ uBits.nBits = htonl((int32_t)uBits.nBits);
+ return uBits.nBits;
+}
+
+void TxToJSON(const CTransaction &tx, Object& entry)
+{
+ entry.push_back(Pair("version", tx.nVersion));
+ entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
+ entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
+ Array vin;
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ {
+ Object in;
+ if (tx.IsCoinBase())
+ in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
+ else
+ {
+ Object prevout;
+ prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
+ prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
+ in.push_back(Pair("prevout", prevout));
+ in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
+ }
+ in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
+ vin.push_back(in);
+ }
+ entry.push_back(Pair("vin", vin));
+ Array vout;
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ {
+ Object out;
+ out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
+ out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
+ vout.push_back(out);
+ }
+ entry.push_back(Pair("vout", vout));
+}
+
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
{
int confirms = wtx.GetDepthInMainChain();
{
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());
+ Object entry;
+
+ entry.push_back(Pair("txid", tx.GetHash().GetHex()));
+ TxToJSON(tx, entry);
+ entry.push_back(Pair("time", (boost::int64_t)tx.nTime));
+
+ txinfo.push_back(entry);
}
else
txinfo.push_back(tx.GetHash().GetHex());
}
- result.push_back(Pair("tx", txinfo));
+ result.push_back(Pair("tx", txinfo));
+
return result;
}
}
+Value getpowreward(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 1)
+ throw runtime_error(
+ "getpowreward [nBits]\n"
+ "Returns PoW reward for block with provided difficulty.");
+
+ if (params.size() == 0)
+ throw JSONRPCError(-200, "no bits provided");
+
+ std::string sBits = params[0].get_str();
+
+ if (sBits.length() != 8)
+ throw JSONRPCError(-201, "incorrect bits provided");
+
+ unsigned int nBits = BitsHex(sBits);
+
+ return (int)GetProofOfWorkReward(nBits);
+}
+
+
+
Value movecmd(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 3 || params.size() > 5)
Object entry;
- if (!pwalletMain->mapWallet.count(hash))
- throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
- const CWalletTx& wtx = pwalletMain->mapWallet[hash];
+ if (pwalletMain->mapWallet.count(hash))
+ {
+ const CWalletTx& wtx = pwalletMain->mapWallet[hash];
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+ TxToJSON(wtx, entry);
- entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
- if (wtx.IsFromMe())
- entry.push_back(Pair("fee", ValueFromAmount(nFee)));
+ int64 nCredit = wtx.GetCredit();
+ int64 nDebit = wtx.GetDebit();
+ int64 nNet = nCredit - nDebit;
+ int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
- WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
+ entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
+ if (wtx.IsFromMe())
+ entry.push_back(Pair("fee", ValueFromAmount(nFee)));
- Array details;
- ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
- entry.push_back(Pair("details", details));
+ WalletTxToJSON(wtx, entry);
+
+ Array details;
+ ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
+ entry.push_back(Pair("details", details));
+ }
+ else
+ {
+ CTransaction tx;
+ uint256 hashBlock = 0;
+ if (GetTransaction(hash, tx, hashBlock))
+ {
+ entry.push_back(Pair("txid", hash.GetHex()));
+ TxToJSON(tx, entry);
+ if (hashBlock == 0)
+ entry.push_back(Pair("confirmations", 0));
+ else
+ {
+ entry.push_back(Pair("blockhash", hashBlock.GetHex()));
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi != mapBlockIndex.end() && (*mi).second)
+ {
+ CBlockIndex* pindex = (*mi).second;
+ if (pindex->IsInMainChain())
+ {
+ entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
+ entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
+ }
+ else
+ entry.push_back(Pair("confirmations", 0));
+ }
+ }
+ }
+ else
+ throw JSONRPCError(-5, "No information available about transaction");
+ }
return entry;
}
return ret;
}
+Value validatepubkey(const Array& params, bool fHelp)
+{
+ if (fHelp || !params.size() || params.size() > 2)
+ throw runtime_error(
+ "validatepubkey <novacoinpubkey>\n"
+ "Return information about <novacoinpubkey>.");
+
+ std::vector<unsigned char> 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 getworkex(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2)
+ throw runtime_error(
+ "getworkex [data, coinbase]\n"
+ "If [data, coinbase] is not specified, returns extended work data.\n"
+ );
+
+ if (vNodes.empty())
+ throw JSONRPCError(-9, "NovaCoin is not connected!");
+
+ if (IsInitialBlockDownload())
+ throw JSONRPCError(-10, "NovaCoin is downloading blocks...");
+
+ typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
+ static mapNewBlock_t mapNewBlock;
+ static vector<CBlock*> vNewBlock;
+ static CReserveKey reservekey(pwalletMain);
+
+ if (params.size() == 0)
+ {
+ // Update block
+ static unsigned int nTransactionsUpdatedLast;
+ static CBlockIndex* pindexPrev;
+ static int64 nStart;
+ static CBlock* pblock;
+ if (pindexPrev != pindexBest ||
+ (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
+ {
+ if (pindexPrev != pindexBest)
+ {
+ // Deallocate old blocks since they're obsolete now
+ mapNewBlock.clear();
+ BOOST_FOREACH(CBlock* pblock, vNewBlock)
+ delete pblock;
+ vNewBlock.clear();
+ }
+ nTransactionsUpdatedLast = nTransactionsUpdated;
+ pindexPrev = pindexBest;
+ nStart = GetTime();
+
+ // Create new block
+ pblock = CreateNewBlock(pwalletMain);
+ if (!pblock)
+ throw JSONRPCError(-7, "Out of memory");
+ vNewBlock.push_back(pblock);
+ }
+
+ // Update nTime
+ pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->nNonce = 0;
+
+ // Update nExtraNonce
+ static unsigned int nExtraNonce = 0;
+ IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
+
+ // Save
+ mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
+
+ // Prebuild hash buffers
+ char pmidstate[32];
+ char pdata[128];
+ char phash1[64];
+ FormatHashBuffers(pblock, pmidstate, pdata, phash1);
+
+ uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+
+ CTransaction coinbaseTx = pblock->vtx[0];
+ std::vector<uint256> merkle = pblock->GetMerkleBranch(0);
+
+ Object result;
+ result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
+ result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
+
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << coinbaseTx;
+ result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end())));
+
+ Array merkle_arr;
+ printf("DEBUG: merkle size %i\n", merkle.size());
+
+ BOOST_FOREACH(uint256 merkleh, merkle) {
+ printf("%s\n", merkleh.ToString().c_str());
+ merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh)));
+ }
+
+ result.push_back(Pair("merkle", merkle_arr));
+
+
+ return result;
+ }
+ else
+ {
+ // Parse parameters
+ vector<unsigned char> vchData = ParseHex(params[0].get_str());
+ vector<unsigned char> coinbase;
+
+ if(params.size() == 2)
+ coinbase = ParseHex(params[1].get_str());
+
+ if (vchData.size() != 128)
+ throw JSONRPCError(-8, "Invalid parameter");
+
+ CBlock* pdata = (CBlock*)&vchData[0];
+
+ // Byte reverse
+ for (int i = 0; i < 128/4; i++)
+ ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
+
+ // Get saved block
+ if (!mapNewBlock.count(pdata->hashMerkleRoot))
+ return false;
+ CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
+
+ pblock->nTime = pdata->nTime;
+ pblock->nNonce = pdata->nNonce;
+
+ if(coinbase.size() == 0)
+ pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
+ else
+ CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0]; // FIXME - HACK!
+
+ pblock->hashMerkleRoot = pblock->BuildMerkleTree();
+
+ if (!pblock->SignBlock(*pwalletMain))
+ throw JSONRPCError(-100, "Unable to sign block, wallet locked?");
+
+ return CheckWork(pblock, *pwalletMain, reservekey);
+ }
+}
+
+
Value getwork(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
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)
{
{ "getblocknumber", &getblocknumber, true },
{ "getconnectioncount", &getconnectioncount, true },
{ "getdifficulty", &getdifficulty, true },
+ { "getpowreward", &getpowreward, true },
{ "getgenerate", &getgenerate, true },
{ "setgenerate", &setgenerate, true },
{ "gethashespersec", &gethashespersec, true },
{ "walletlock", &walletlock, true },
{ "encryptwallet", &encryptwallet, false },
{ "validateaddress", &validateaddress, true },
+ { "validatepubkey", &validatepubkey, true },
{ "getbalance", &getbalance, false },
{ "move", &movecmd, false },
{ "sendfrom", &sendfrom, false },
{ "signmessage", &signmessage, false },
{ "verifymessage", &verifymessage, false },
{ "getwork", &getwork, true },
+ { "getworkex", &getworkex, true },
{ "listaccounts", &listaccounts, false },
{ "settxfee", &settxfee, false },
{ "getmemorypool", &getmemorypool, true },
{ "reservebalance", &reservebalance, false},
{ "checkwallet", &checkwallet, false},
{ "repairwallet", &repairwallet, false},
+ { "resendtx", &resendtx, false},
{ "makekeypair", &makekeypair, false},
{ "sendalert", &sendalert, false},
};