// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2011 The Bitcoin developers
+// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
- obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
- obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("testnet", fTestNet));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
}
+Value getmininginfo(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getmininginfo\n"
+ "Returns an object containing mining-related information.");
+
+ Object obj;
+ obj.push_back(Pair("blocks", (int)nBestHeight));
+ obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
+ obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
+ obj.push_back(Pair("difficulty", (double)GetDifficulty()));
+ obj.push_back(Pair("errors", GetWarnings("statusbar")));
+ obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
+ obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
+ obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
+ obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
+ obj.push_back(Pair("testnet", fTestNet));
+ return obj;
+}
+
+
Value getnewaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
return wtx.GetHash().GetHex();
}
-static const string strMessageMagic = "Bitcoin Signed Message:\n";
-
Value signmessage(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 2)
{
string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
"Add a nrequired-to-sign multisignature address to the wallet\"\n"
- "each key is a bitcoin address, hex or base58 public key\n"
+ "each key is a bitcoin address or hex-encoded public key\n"
"If [account] is specified, assign address to [account].";
throw runtime_error(msg);
}
strAccount = AccountFromValue(params[2]);
// Gather public keys
- if (keys.size() < nRequired)
+ if (nRequired < 1 || keys.size() < nRequired)
throw runtime_error(
- strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
+ strprintf("wrong number of keys"
+ "(got %d, need at least %d)", keys.size(), nRequired));
std::vector<CKey> pubkeys;
pubkeys.resize(keys.size());
for (int i = 0; i < keys.size(); i++)
{
const std::string& ks = keys[i].get_str();
- if (ks.size() == 130) // hex public key
- pubkeys[i].SetPubKey(ParseHex(ks));
- else if (ks.size() > 34) // base58-encoded
+
+ // Case 1: bitcoin address and we have full public key:
+ CBitcoinAddress address(ks);
+ if (address.IsValid())
{
+ if (address.IsScript())
+ throw runtime_error(
+ strprintf("%s is a pay-to-script address",ks.c_str()));
std::vector<unsigned char> vchPubKey;
- if (DecodeBase58(ks, vchPubKey))
- pubkeys[i].SetPubKey(vchPubKey);
- else
- throw runtime_error("Error base58 decoding key: "+ks);
+ if (!pwalletMain->GetPubKey(address, vchPubKey))
+ throw runtime_error(
+ strprintf("no full public key for address %s",ks.c_str()));
+ if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
+ throw runtime_error(" Invalid public key: "+ks);
}
- else // bitcoin address for key in this wallet
+
+ // Case 2: hex public key
+ else if (IsHex(ks))
{
- CBitcoinAddress address(ks);
- if (!pwalletMain->GetKey(address, pubkeys[i]))
- throw runtime_error(
- strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
+ vector<unsigned char> vchPubKey = ParseHex(ks);
+ if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
+ throw runtime_error(" Invalid public key: "+ks);
+ }
+ else
+ {
+ throw runtime_error(" Invalid public key: "+ks);
}
}
- // Construct using OP_EVAL
+ // Construct using pay-to-script-hash:
CScript inner;
inner.SetMultisig(nRequired, pubkeys);
uint160 scriptHash = Hash160(inner);
CScript scriptPubKey;
- scriptPubKey.SetEval(inner);
- pwalletMain->AddCScript(scriptHash, inner);
+ scriptPubKey.SetPayToScriptHash(inner);
+ pwalletMain->AddCScript(inner);
CBitcoinAddress address;
address.SetScriptHash160(scriptHash);
{
int64 nMyWakeTime = GetTime() + *((int*)parg);
+ ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
+
if (nWalletUnlockTime == 0)
{
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
- {
- nWalletUnlockTime = nMyWakeTime;
- }
+ nWalletUnlockTime = nMyWakeTime;
while (GetTime() < nWalletUnlockTime)
- Sleep(GetTime() - nWalletUnlockTime);
-
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
{
- nWalletUnlockTime = 0;
+ int64 nToSleep = GetTime() - nWalletUnlockTime;
+
+ LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
+ Sleep(nToSleep);
+ ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
}
+
+ nWalletUnlockTime = 0;
+ pwalletMain->Lock();
}
else
{
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
- {
- if (nWalletUnlockTime < nMyWakeTime)
- nWalletUnlockTime = nMyWakeTime;
- }
- free(parg);
- return;
+ if (nWalletUnlockTime < nMyWakeTime)
+ nWalletUnlockTime = nMyWakeTime;
}
- pwalletMain->Lock();
+ LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
delete (int*)parg;
}
std::vector<unsigned char> vchPubKey;
pwalletMain->GetPubKey(address, vchPubKey);
ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
- std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
- ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
CKey key;
key.SetPubKey(vchPubKey);
ret.push_back(Pair("iscompressed", key.IsCompressed()));
" \"previousblockhash\" : hash of current highest block\n"
" \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
" \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
+ " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
" \"time\" : timestamp appropriate for next block\n"
+ " \"mintime\" : minimum timestamp appropriate for next block\n"
+ " \"curtime\" : current timestamp\n"
" \"bits\" : compressed target of next block\n"
"If [data] is specified, tries to solve the block and returns true if it was successful.");
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
result.push_back(Pair("transactions", transactions));
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
+ result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
result.push_back(Pair("time", (int64_t)pblock->nTime));
+ result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
+ result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
union {
int32_t nBits;
make_pair("setgenerate", &setgenerate),
make_pair("gethashespersec", &gethashespersec),
make_pair("getinfo", &getinfo),
+ make_pair("getmininginfo", &getmininginfo),
make_pair("getnewaddress", &getnewaddress),
make_pair("getaccountaddress", &getaccountaddress),
make_pair("setaccount", &setaccount),
"setgenerate",
"gethashespersec",
"getinfo",
+ "getmininginfo",
"getnewaddress",
"getaccountaddress",
"getaccount",
printf("ThreadRPCServer started\n");
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
- if (strRPCUserColonPass == ":")
+ if (mapArgs["-rpcpassword"] == "")
{
+ unsigned char rand_pwd[32];
+ RAND_bytes(rand_pwd, 32);
string strWhatAmI = "To use bitcoind";
if (mapArgs.count("-server"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
PrintConsole(
- _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
+ _("Error: %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"
+ "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"),
strWhatAmI.c_str(),
- GetConfigFile().c_str());
+ GetConfigFile().c_str(),
+ EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
#ifndef QT_GUI
CreateThread(Shutdown, NULL);
#endif
}
if (!HTTPAuthorized(mapHeaders))
{
- // Deter brute-forcing short passwords
- if (mapArgs["-rpcpassword"].size() < 15)
- Sleep(50);
+ printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
+ /* Deter brute-forcing short passwords.
+ If this results in a DOS the user really
+ shouldn't have their RPC port exposed.*/
+ if (mapArgs["-rpcpassword"].size() < 20)
+ Sleep(250);
stream << HTTPReply(401, "") << std::flush;
- printf("ThreadRPCServer incorrect password attempt\n");
continue;
}
string s = params[1].get_str();
Value v;
if (!read_string(s, v) || v.type() != array_type)
- throw runtime_error("addmultisigaddress: type mismatch "+s);
+ throw runtime_error("type mismatch "+s);
params[1] = v.get_array();
}