diff options
Diffstat (limited to 'src')
112 files changed, 4124 insertions, 2482 deletions
diff --git a/src/addrman.h b/src/addrman.h index b996839e3c..0392654366 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -23,13 +23,13 @@ private: // where knowledge about this address first came from CNetAddr source; - // last succesfull connection by us + // last successful connection by us int64 nLastSuccess; // last try whatsoever by us: // int64 CAddress::nLastTry - // connection attempts since last succesful attempt + // connection attempts since last successful attempt int nAttempts; // reference count in new sets (memory only) diff --git a/src/base58.h b/src/base58.h index b492cd683c..215fd33324 100644 --- a/src/base58.h +++ b/src/base58.h @@ -71,7 +71,7 @@ inline std::string EncodeBase58(const std::vector<unsigned char>& vch) } // Decode a base58-encoded string psz into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet) { CAutoBN_CTX pctx; @@ -119,7 +119,7 @@ inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet) } // Decode a base58-encoded string str into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) { return DecodeBase58(str.c_str(), vchRet); @@ -139,7 +139,7 @@ inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) } // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) { if (!DecodeBase58(psz, vchRet)) @@ -160,7 +160,7 @@ inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRe } // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) { return DecodeBase58Check(str.c_str(), vchRet); diff --git a/src/bignum.h b/src/bignum.h index 9af934051a..9fea3f70fb 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -131,15 +131,9 @@ public: if (sn < (int64)0) { - // We negate in 2 steps to avoid signed subtraction overflow, - // i.e. -(-2^63), which is an undefined operation and causes SIGILL - // when compiled with -ftrapv. - // - // Note that uint64_t n = sn, when sn is an int64_t, is a - // well-defined operation and n will be equal to sn + 2^64 when sn - // is negative. - n = sn; - n = -n; + // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate + n = -(sn + 1); + ++n; fNegative = true; } else { n = sn; @@ -422,7 +416,7 @@ public: CBigNum& operator>>=(unsigned int shift) { // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number - // if built on ubuntu 9.04 or 9.10, probably depends on version of openssl + // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL CBigNum a = 1; a <<= shift; if (BN_cmp(&a, this) > 0) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 8d78b8b00a..3af298a58b 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -29,10 +29,6 @@ #include <list> #define printf OutputDebugStringF -// MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are -// precompiled in headers.h. The problem might be when the pch file goes over -// a certain size around 145MB. If we need access to json_spirit outside this -// file, we could use the compiled json_spirit option. using namespace std; using namespace boost; @@ -46,8 +42,16 @@ static std::string strRPCUserColonPass; static int64 nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; -extern Value dumpprivkey(const Array& params, bool fHelp); +extern Value getconnectioncount(const Array& params, bool fHelp); // in rpcnet.cpp +extern Value getpeerinfo(const Array& params, bool fHelp); +extern Value dumpprivkey(const Array& params, bool fHelp); // in rpcdump.cpp extern Value importprivkey(const Array& params, bool fHelp); +extern Value getrawtransaction(const Array& params, bool fHelp); // in rcprawtransaction.cpp +extern Value listunspent(const Array& params, bool fHelp); +extern Value createrawtransaction(const Array& params, bool fHelp); +extern Value decoderawtransaction(const Array& params, bool fHelp); +extern Value signrawtransaction(const Array& params, bool fHelp); +extern Value sendrawtransaction(const Array& params, bool fHelp); const Object emptyobj; @@ -61,6 +65,43 @@ Object JSONRPCError(int code, const string& message) return error; } +void RPCTypeCheck(const Array& params, + const list<Value_type>& typesExpected) +{ + unsigned int i = 0; + BOOST_FOREACH(Value_type t, typesExpected) + { + if (params.size() <= i) + break; + + const Value& v = params[i]; + if (v.type() != t) + { + string err = strprintf("Expected type %s, got %s", + Value_type_name[t], Value_type_name[v.type()]); + throw JSONRPCError(-3, err); + } + i++; + } +} + +void RPCTypeCheck(const Object& o, + const map<string, Value_type>& typesExpected) +{ + BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected) + { + const Value& v = find_value(o, t.first); + if (v.type() == null_type) + throw JSONRPCError(-3, strprintf("Missing %s", t.first.c_str())); + if (v.type() != t.second) + { + string err = strprintf("Expected type %s for %s, got %s", + Value_type_name[t.second], t.first.c_str(), Value_type_name[v.type()]); + throw JSONRPCError(-3, err); + } + } +} + double GetDifficulty(const CBlockIndex* blockindex = NULL) { // Floating point number that is a multiple of the minimum difficulty, @@ -120,7 +161,7 @@ HexBits(unsigned int nBits) return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } -static std::string +std::string HelpRequiringPassphrase() { return pwalletMain->IsCrypted() @@ -128,40 +169,13 @@ HelpRequiringPassphrase() : ""; } -static inline void +void EnsureWalletIsUnlocked() { if (pwalletMain->IsLocked()) throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); } -enum DecomposeMode { - DM_NONE = 0, - DM_HASH, - DM_HEX, - DM_ASM, - DM_OBJ, -}; - -enum DecomposeMode -FindDecompose(const Object& decompositions, const char* pcType, const char* pcDefault) -{ - Value val = find_value(decompositions, pcType); - std::string strDecompose = (val.type() == null_type) ? pcDefault : val.get_str(); - - if (strDecompose == "no") - return DM_NONE; - if (strDecompose == "hash") - return DM_HASH; - if (strDecompose == "hex") - return DM_HEX; - if (strDecompose == "asm") - return DM_ASM; - if (strDecompose == "obj") - return DM_OBJ; - throw JSONRPCError(-18, "Invalid decomposition"); -} - void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -177,141 +191,6 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) entry.push_back(Pair(item.first, item.second)); } -void -ScriptSigToJSON(const CTxIn& txin, Object& out) -{ - out.push_back(Pair("asm", txin.scriptSig.ToString())); - out.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); - - CTransaction txprev; - uint256 hashTxprevBlock; - if (!GetTransaction(txin.prevout.hash, txprev, hashTxprevBlock)) - return; - - txnouttype type; - vector<CTxDestination> addresses; - int nRequired; - - if (!ExtractDestinations(txprev.vout[txin.prevout.n].scriptPubKey, type, - addresses, nRequired)) - { - out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); - return; - } - - out.push_back(Pair("type", GetTxnOutputType(type))); - if (type == TX_MULTISIG) - { - // TODO: Need to handle this specially since not all input addresses are required... - return; - } - - Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - out.push_back(Pair("addresses", a)); -} - -void -ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) -{ - txnouttype type; - vector<CTxDestination> addresses; - int nRequired; - - out.push_back(Pair("asm", scriptPubKey.ToString())); - out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); - - if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) - { - out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); - return; - } - - out.push_back(Pair("reqSigs", nRequired)); - out.push_back(Pair("type", GetTxnOutputType(type))); - - Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - out.push_back(Pair("addresses", a)); -} - -void TxToJSON(const CTransaction &tx, Object& entry, const Object& decompositions) -{ - 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))); - - enum DecomposeMode decomposeScript = FindDecompose(decompositions, "script", "asm"); - - 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)); - switch (decomposeScript) { - case DM_NONE: - break; - case DM_HEX: - in.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); - break; - case DM_ASM: - in.push_back(Pair("scriptSig", txin.scriptSig.ToString())); - break; - case DM_OBJ: - { - Object o; - ScriptSigToJSON(txin, o); - in.push_back(Pair("scriptSig", o)); - break; - } - default: - throw JSONRPCError(-18, "Invalid script decomposition"); - } - } - 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))); - switch (decomposeScript) { - case DM_NONE: - break; - case DM_HEX: - out.push_back(Pair("scriptPubKey", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end()))); - break; - case DM_ASM: - out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString())); - break; - case DM_OBJ: - { - Object o; - ScriptPubKeyToJSON(txout.scriptPubKey, o); - out.push_back(Pair("scriptPubKey", o)); - break; - } - default: - throw JSONRPCError(-18, "Invalid script decomposition"); - } - vout.push_back(out); - } - entry.push_back(Pair("vout", vout)); -} - -void AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions); - string AccountFromValue(const Value& value) { string strAccount = value.get_str(); @@ -320,7 +199,7 @@ string AccountFromValue(const Value& value) return strAccount; } -Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions) +Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) { Object result; result.push_back(Pair("hash", block.GetHash().GetHex())); @@ -331,43 +210,15 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Obj result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + Array txs; + BOOST_FOREACH(const CTransaction&tx, block.vtx) + txs.push_back(tx.GetHash().GetHex()); + result.push_back(Pair("tx", txs)); result.push_back(Pair("time", (boost::int64_t)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))); - enum DecomposeMode decomposeTxn = FindDecompose(decompositions, "tx", "hash"); - if (decomposeTxn) - { - Array txs; - switch (decomposeTxn) { - case DM_OBJ: - BOOST_FOREACH (const CTransaction&tx, block.vtx) - { - Object entry; - AnyTxToJSON(tx.GetHash(), &tx, entry, decompositions); - txs.push_back(entry); - } - break; - case DM_HEX: - BOOST_FOREACH (const CTransaction&tx, block.vtx) - { - CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); - ssTx << tx; - - txs.push_back(HexStr(ssTx.begin(), ssTx.end())); - } - break; - case DM_HASH: - BOOST_FOREACH (const CTransaction&tx, block.vtx) - txs.push_back(tx.GetHash().GetHex()); - break; - default: - throw JSONRPCError(-18, "Invalid transaction decomposition"); - } - result.push_back(Pair("tx", txs)); - } - if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); if (blockindex->pnext) @@ -456,17 +307,6 @@ Value getblockcount(const Array& params, bool fHelp) } -Value getconnectioncount(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getconnectioncount\n" - "Returns the number of connections to other nodes."); - - return (int)vNodes.size(); -} - - Value getdifficulty(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -1660,78 +1500,35 @@ Value listsinceblock(const Array& params, bool fHelp) return ret; } -void -AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions) -{ - if (pwalletMain->mapWallet.count(hash)) - { - const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - - TxToJSON(wtx, entry, decompositions); - - int64 nCredit = wtx.GetCredit(); - int64 nDebit = wtx.GetDebit(); - int64 nNet = nCredit - nDebit; - int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); - - entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); - if (wtx.IsFromMe()) - entry.push_back(Pair("fee", ValueFromAmount(nFee))); - - 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 ((!ptx) && GetTransaction(hash, tx, hashBlock)) - ptx = &tx; - if (ptx) - { - entry.push_back(Pair("txid", hash.GetHex())); - TxToJSON(*ptx, entry, decompositions); - 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"); - } -} - Value gettransaction(const Array& params, bool fHelp) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (fHelp || params.size() != 1) throw runtime_error( - "gettransaction <txid> [decompositions]\n" - "Get detailed information about <txid>"); + "gettransaction <txid>\n" + "Get detailed information about in-wallet transaction <txid>"); uint256 hash; hash.SetHex(params[0].get_str()); Object entry; + if (!pwalletMain->mapWallet.count(hash)) + throw JSONRPCError(-5, "Invalid or non-wallet transaction id"); + 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); - AnyTxToJSON(hash, NULL, entry, - (params.size() > 1) ? params[1].get_obj() : emptyobj); + entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); + if (wtx.IsFromMe()) + entry.push_back(Pair("fee", ValueFromAmount(nFee))); + + WalletTxToJSON(wtx, entry); + + Array details; + ListTransactions(wtx, "*", 0, false, details); + entry.push_back(Pair("details", details)); return entry; } @@ -1772,11 +1569,17 @@ Value keypoolrefill(const Array& params, bool fHelp) void ThreadTopUpKeyPool(void* parg) { + // Make this thread recognisable as the key-topping-up thread + RenameThread("bitcoin-key-top"); + pwalletMain->TopUpKeyPool(); } void ThreadCleanWalletPassphrase(void* parg) { + // Make this thread recognisable as the wallet relocking thread + RenameThread("bitcoin-lock-wa"); + int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000; ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); @@ -2048,8 +1851,13 @@ Value getwork(const Array& params, bool fHelp) delete pblock; vNewBlock.clear(); } + + // Clear pindexPrev so future getworks make a new block, despite any failures from here on + pindexPrev = NULL; + + // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = nTransactionsUpdated; - pindexPrev = pindexBest; + CBlockIndex* pindexPrevNew = pindexBest; nStart = GetTime(); // Create new block @@ -2057,6 +1865,9 @@ Value getwork(const Array& params, bool fHelp) if (!pblock) throw JSONRPCError(-7, "Out of memory"); vNewBlock.push_back(pblock); + + // Need to update only after we know CreateNewBlock succeeded + pindexPrev = pindexPrevNew; } // Update nTime @@ -2147,16 +1958,26 @@ Value getmemorypool(const Array& params, bool fHelp) 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; - pindexPrev = pindexBest; + CBlockIndex* pindexPrevNew = pindexBest; nStart = GetTime(); // Create new block if(pblock) + { delete pblock; + pblock = NULL; + } pblock = CreateNewBlock(reservekey); if (!pblock) throw JSONRPCError(-7, "Out of memory"); + + // Need to update only after we know CreateNewBlock succeeded + pindexPrev = pindexPrevNew; } // Update nTime @@ -2235,9 +2056,9 @@ Value getblockhash(const Array& params, bool fHelp) Value getblock(const Array& params, bool fHelp) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (fHelp || params.size() != 1) throw runtime_error( - "getblock <hash> [decompositions]\n" + "getblock <hash>\n" "Returns details of a block with given block-hash."); std::string strHash = params[0].get_str(); @@ -2250,48 +2071,9 @@ Value getblock(const Array& params, bool fHelp) CBlockIndex* pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); - return blockToJSON(block, pblockindex, - (params.size() > 1) ? params[1].get_obj() : emptyobj); + return blockToJSON(block, pblockindex); } -Value sendrawtx(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 1) - throw runtime_error( - "sendrawtx <hex string>\n" - "Submits raw transaction (serialized, hex-encoded) to local node and network."); - - // parse hex string from parameter - vector<unsigned char> txData(ParseHex(params[0].get_str())); - CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - - // deserialize binary data stream - try { - ssData >> tx; - } - catch (std::exception &e) { - throw JSONRPCError(-22, "TX decode failed"); - } - - // push to local node - CTxDB txdb("r"); - if (!tx.AcceptToMemoryPool(txdb)) - throw JSONRPCError(-22, "TX rejected"); - - SyncWithWallets(tx, NULL, true); - - // relay to network - CInv inv(MSG_TX, tx.GetHash()); - RelayInventory(inv); - - return tx.GetHash().GetHex(); -} - - - - - @@ -2310,6 +2092,7 @@ static const CRPCCommand vRPCCommands[] = { "stop", &stop, true }, { "getblockcount", &getblockcount, true }, { "getconnectioncount", &getconnectioncount, true }, + { "getpeerinfo", &getpeerinfo, true }, { "getdifficulty", &getdifficulty, true }, { "getgenerate", &getgenerate, true }, { "setgenerate", &setgenerate, true }, @@ -2352,7 +2135,12 @@ static const CRPCCommand vRPCCommands[] = { "listsinceblock", &listsinceblock, false }, { "dumpprivkey", &dumpprivkey, false }, { "importprivkey", &importprivkey, false }, - { "sendrawtx", &sendrawtx, false }, + { "listunspent", &listunspent, false }, + { "getrawtransaction", &getrawtransaction, false }, + { "createrawtransaction", &createrawtransaction, false }, + { "decoderawtransaction", &decoderawtransaction, false }, + { "signrawtransaction", &signrawtransaction, false }, + { "sendrawtransaction", &sendrawtransaction, false }, }; CRPCTable::CRPCTable() @@ -2560,7 +2348,7 @@ string JSONRPCRequest(const string& strMethod, const Array& params, const Value& return write_string(Value(request), false) + "\n"; } -string JSONRPCReply(const Value& result, const Value& error, const Value& id) +Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id) { Object reply; if (error.type() != null_type) @@ -2569,6 +2357,12 @@ string JSONRPCReply(const Value& result, const Value& error, const Value& id) reply.push_back(Pair("result", result)); reply.push_back(Pair("error", error)); reply.push_back(Pair("id", id)); + return reply; +} + +string JSONRPCReply(const Value& result, const Value& error, const Value& id) +{ + Object reply = JSONRPCReplyObj(result, error, id); return write_string(Value(reply), false) + "\n"; } @@ -2709,6 +2503,10 @@ private: void ThreadRPCServer(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg)); + + // Make this thread recognisable as the RPC listener + RenameThread("bitcoin-rpclist"); + try { vnThreadsRunning[THREAD_RPCLISTENER]++; @@ -2768,7 +2566,7 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, vnThreadsRunning[THREAD_RPCLISTENER]++; // Immediately start accepting new connections, except when we're canceled or our socket is closed. - if (error != error::operation_aborted + if (error != asio::error::operation_aborted && acceptor->is_open()) RPCListen(acceptor, context, fUseSSL); @@ -2858,6 +2656,8 @@ void ThreadRPCServer2(void* parg) asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332)); + boost::signals2::signal<void ()> StopRequests; + try { boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service)); @@ -2873,7 +2673,7 @@ void ThreadRPCServer2(void* parg) RPCListen(acceptor, context, fUseSSL); // Cancel outstanding listen-requests for this acceptor when shutting down - uiInterface.QueueShutdown.connect(signals2::slot<void ()>( + StopRequests.connect(signals2::slot<void ()>( static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get()) .track(acceptor)); @@ -2891,7 +2691,7 @@ void ThreadRPCServer2(void* parg) RPCListen(acceptor, context, fUseSSL); // Cancel outstanding listen-requests for this acceptor when shutting down - uiInterface.QueueShutdown.connect(signals2::slot<void ()>( + StopRequests.connect(signals2::slot<void ()>( static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get()) .track(acceptor)); } @@ -2905,14 +2705,99 @@ void ThreadRPCServer2(void* parg) } vnThreadsRunning[THREAD_RPCLISTENER]--; - io_service.run(); + while (!fShutdown) + io_service.run_one(); vnThreadsRunning[THREAD_RPCLISTENER]++; + StopRequests(); +} + +class JSONRequest +{ +public: + Value id; + string strMethod; + Array params; + + JSONRequest() { id = Value::null; } + void parse(const Value& valRequest); +}; + +void JSONRequest::parse(const Value& valRequest) +{ + // Parse request + if (valRequest.type() != obj_type) + throw JSONRPCError(-32600, "Invalid Request object"); + const Object& request = valRequest.get_obj(); + + // Parse id now so errors from here on will have the id + id = find_value(request, "id"); + + // Parse method + Value valMethod = find_value(request, "method"); + if (valMethod.type() == null_type) + throw JSONRPCError(-32600, "Missing method"); + if (valMethod.type() != str_type) + throw JSONRPCError(-32600, "Method must be a string"); + strMethod = valMethod.get_str(); + if (strMethod != "getwork" && strMethod != "getmemorypool") + printf("ThreadRPCServer method=%s\n", strMethod.c_str()); + + // Parse params + Value valParams = find_value(request, "params"); + if (valParams.type() == array_type) + params = valParams.get_array(); + else if (valParams.type() == null_type) + params = Array(); + else + throw JSONRPCError(-32600, "Params must be an array"); } +static Object JSONRPCExecOne(const Value& req) +{ + Object rpc_result; + + JSONRequest jreq; + try { + jreq.parse(req); + + Value result = tableRPC.execute(jreq.strMethod, jreq.params); + rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id); + } + catch (Object& objError) + { + rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id); + } + catch (std::exception& e) + { + rpc_result = JSONRPCReplyObj(Value::null, + JSONRPCError(-32700, e.what()), jreq.id); + } + + return rpc_result; +} + +static string JSONRPCExecBatch(const Array& vReq) +{ + Array ret; + for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) + ret.push_back(JSONRPCExecOne(vReq[reqIdx])); + + return write_string(Value(ret), false) + "\n"; +} + +static CCriticalSection cs_THREAD_RPCHANDLER; + void ThreadRPCServer3(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer3(parg)); - vnThreadsRunning[THREAD_RPCHANDLER]++; + + // Make this thread recognisable as the RPC handler + RenameThread("bitcoin-rpchand"); + + { + LOCK(cs_THREAD_RPCHANDLER); + vnThreadsRunning[THREAD_RPCHANDLER]++; + } AcceptedConnection *conn = (AcceptedConnection *) parg; bool fRun = true; @@ -2921,7 +2806,10 @@ void ThreadRPCServer3(void* parg) { conn->close(); delete conn; - --vnThreadsRunning[THREAD_RPCHANDLER]; + { + LOCK(cs_THREAD_RPCHANDLER); + --vnThreadsRunning[THREAD_RPCHANDLER]; + } return; } map<string, string> mapHeaders; @@ -2950,58 +2838,50 @@ void ThreadRPCServer3(void* parg) if (mapHeaders["connection"] == "close") fRun = false; - Value id = Value::null; + JSONRequest jreq; try { // Parse request Value valRequest; - if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type) + if (!read_string(strRequest, valRequest)) throw JSONRPCError(-32700, "Parse error"); - const Object& request = valRequest.get_obj(); - - // Parse id now so errors from here on will have the id - id = find_value(request, "id"); - - // Parse method - Value valMethod = find_value(request, "method"); - if (valMethod.type() == null_type) - throw JSONRPCError(-32600, "Missing method"); - if (valMethod.type() != str_type) - throw JSONRPCError(-32600, "Method must be a string"); - string strMethod = valMethod.get_str(); - if (strMethod != "getwork" && strMethod != "getmemorypool") - printf("ThreadRPCServer method=%s\n", strMethod.c_str()); - - // Parse params - Value valParams = find_value(request, "params"); - Array params; - if (valParams.type() == array_type) - params = valParams.get_array(); - else if (valParams.type() == null_type) - params = Array(); - else - throw JSONRPCError(-32600, "Params must be an array"); - Value result = tableRPC.execute(strMethod, params); + string strReply; - // Send reply - string strReply = JSONRPCReply(result, Value::null, id); + // singleton request + if (valRequest.type() == obj_type) { + jreq.parse(valRequest); + + Value result = tableRPC.execute(jreq.strMethod, jreq.params); + + // Send reply + strReply = JSONRPCReply(result, Value::null, jreq.id); + + // array of requests + } else if (valRequest.type() == array_type) + strReply = JSONRPCExecBatch(valRequest.get_array()); + else + throw JSONRPCError(-32700, "Top-level object parse error"); + conn->stream() << HTTPReply(200, strReply, fRun) << std::flush; } catch (Object& objError) { - ErrorReply(conn->stream(), objError, id); + ErrorReply(conn->stream(), objError, jreq.id); break; } catch (std::exception& e) { - ErrorReply(conn->stream(), JSONRPCError(-32700, e.what()), id); + ErrorReply(conn->stream(), JSONRPCError(-32700, e.what()), jreq.id); break; } } delete conn; - vnThreadsRunning[THREAD_RPCHANDLER]--; + { + LOCK(cs_THREAD_RPCHANDLER); + vnThreadsRunning[THREAD_RPCHANDLER]--; + } } json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array ¶ms) const @@ -3095,8 +2975,9 @@ void ConvertTo(Value& value) { // reinterpret string as unquoted json value Value value2; - if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); value = value2.get_value<T>(); } else @@ -3128,9 +3009,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]); if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]); if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]); - if (strMethod == "getblock" && n > 1) ConvertTo<Object>(params[1]); if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]); - if (strMethod == "gettransaction" && n > 1) ConvertTo<Object>(params[1]); if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]); if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]); if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]); @@ -3144,6 +3023,13 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]); if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]); if (strMethod == "addmultisigaddress" && n > 1) ConvertTo<Array>(params[1]); + if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1]); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2]); return params; } diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 7a8273756d..b71d17ef29 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -7,6 +7,7 @@ #define _BITCOINRPC_H_ 1 #include <string> +#include <list> #include <map> #include "json/json_spirit_reader_template.h" @@ -21,6 +22,20 @@ int CommandLineRPC(int argc, char *argv[]); /** Convert parameter values for RPC call from strings to command-specific JSON objects. */ json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams); +/* + Type-check arguments; throws JSONRPCError if wrong type given. Does not check that + the right number of arguments are passed, just that any passed are the correct type. + Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type)); +*/ +void RPCTypeCheck(const json_spirit::Array& params, + const std::list<json_spirit::Value_type>& typesExpected); +/* + Check for expected keys/value types in an Object. + Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type)); +*/ +void RPCTypeCheck(const json_spirit::Object& o, + const std::map<std::string, json_spirit::Value_type>& typesExpected); + typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp); class CRPCCommand diff --git a/src/db.cpp b/src/db.cpp index ecdf32a8f0..5671993d37 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -42,7 +42,8 @@ void CDBEnv::EnvShutdown() { printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno()); } - DbEnv(0).remove(GetDataDir().string().c_str(), 0); + if (!fMockDb) + DbEnv(0).remove(GetDataDir().string().c_str(), 0); } CDBEnv::CDBEnv() : dbenv(0) @@ -103,12 +104,48 @@ bool CDBEnv::Open(boost::filesystem::path pathEnv_) return error("CDB() : error %d opening database environment", ret); fDbEnvInit = true; + fMockDb = false; return true; } +void CDBEnv::MakeMock() +{ + if (fDbEnvInit) + throw runtime_error("CDBEnv::MakeMock(): already initialized"); + + if (fShutdown) + throw runtime_error("CDBEnv::MakeMock(): during shutdown"); + + printf("CDBEnv::MakeMock()\n"); + + dbenv.set_cachesize(1, 0, 1); + dbenv.set_lg_bsize(10485760*4); + dbenv.set_lg_max(10485760); + dbenv.set_lk_max_locks(10000); + dbenv.set_lk_max_objects(10000); + dbenv.set_flags(DB_AUTO_COMMIT, 1); + dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); + int ret = dbenv.open(NULL, + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_PRIVATE, + S_IRUSR | S_IWUSR); + if (ret > 0) + throw runtime_error(strprintf("CDBEnv::MakeMock(): error %d opening database environment", ret)); + + fDbEnvInit = true; + fMockDb = true; +} + void CDBEnv::CheckpointLSN(std::string strFile) { dbenv.txn_checkpoint(0, 0, 0); + if (fMockDb) + return; dbenv.lsn_reset(strFile.c_str(), 0); } @@ -138,8 +175,17 @@ CDB::CDB(const char *pszFile, const char* pszMode) : { pdb = new Db(&bitdb.dbenv, 0); + bool fMockDb = bitdb.IsMock(); + if (fMockDb) + { + DbMpoolFile*mpf = pdb->get_mpf(); + ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); + if (ret != 0) + throw runtime_error(strprintf("CDB() : failed to configure for no temp file backing for database %s", pszFile)); + } + ret = pdb->open(NULL, // Txn pointer - pszFile, // Filename + fMockDb ? NULL : pszFile, // Filename "main", // Logical db name DB_BTREE, // Database type nFlags, // Flags @@ -337,7 +383,8 @@ void CDBEnv::Flush(bool fShutdown) dbenv.txn_checkpoint(0, 0, 0); if (!IsChainFile(strFile) || fDetachDB) { printf("%s detach\n", strFile.c_str()); - dbenv.lsn_reset(strFile.c_str(), 0); + if (!fMockDb) + dbenv.lsn_reset(strFile.c_str(), 0); } printf("%s closed\n", strFile.c_str()); mapFileUseCount.erase(mi++); @@ -510,7 +557,9 @@ bool CTxDB::LoadBlockIndex() pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; bnBestChainWork = pindexBest->bnChainWork; - printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight); + printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); // Load bnBestInvalidWork, OK if it doesn't exist ReadBestInvalidWork(bnBestInvalidWork); @@ -35,6 +35,7 @@ class CDBEnv private: bool fDetachDB; bool fDbEnvInit; + bool fMockDb; boost::filesystem::path pathEnv; void EnvShutdown(); @@ -47,6 +48,8 @@ public: CDBEnv(); ~CDBEnv(); + void MakeMock(); + bool IsMock() { return fMockDb; }; bool Open(boost::filesystem::path pathEnv_); void Close(); void Flush(bool fShutdown); diff --git a/src/init.cpp b/src/init.cpp index bb93342631..5fbe9d5d64 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -9,7 +9,6 @@ #include "init.h" #include "util.h" #include "ui_interface.h" -#include <boost/bind.hpp> #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> #include <boost/filesystem/convenience.hpp> @@ -41,14 +40,23 @@ void ExitTimeout(void* parg) void StartShutdown() { +#ifdef QT_GUI // ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards) uiInterface.QueueShutdown(); +#else + // Without UI, Shutdown() can simply be started in a new thread + CreateThread(Shutdown, NULL); +#endif } void Shutdown(void* parg) { static CCriticalSection cs_Shutdown; static bool fTaken; + + // Make this thread recognisable as the shutdown thread + RenameThread("bitcoin-shutoff"); + bool fFirstThread = false; { TRY_LOCK(cs_Shutdown, lockShutdown); @@ -150,11 +158,6 @@ bool AppInit(int argc, char* argv[]) exit(ret); } - // Create the shutdown thread when receiving a shutdown signal - boost::signals2::scoped_connection do_stop( - uiInterface.QueueShutdown.connect(boost::bind( - &CreateThread, &Shutdown, static_cast<void*>(0), false))); - fRet = AppInit2(); } catch (std::exception& e) { @@ -213,6 +216,7 @@ bool static Bind(const CService &addr, bool fError = true) { std::string HelpMessage() { string strUsage = _("Options:") + "\n" + + " -? " + _("This help message") + "\n" + " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n" + " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n" + " -gen " + _("Generate coins") + "\n" + @@ -240,7 +244,7 @@ std::string HelpMessage() " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n" + - " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 5000)") + "\n" + + " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n" + #ifdef USE_UPNP #if USE_UPNP " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n" + @@ -276,10 +280,13 @@ std::string HelpMessage() " -checkblocks=<n> " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" + " -checklevel=<n> " + _("How thorough the block verification is (0-6, default: 1)") + "\n" + " -loadblock=<file> " + _("Imports blocks from external blk000?.dat file") + "\n" + - " -? " + _("This help message") + "\n"; - strUsage += string() + - _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + + "\n" + _("Block creation options:") + "\n" + + " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n" + + " -blockmaxsize=<n> " + _("Set maximum block size in bytes (default: 250000)") + "\n" + + " -blockprioritysize=<n> " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n" + + + "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n" + " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n" + diff --git a/src/irc.cpp b/src/irc.cpp index 185be02f29..a790d3f4f9 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -189,6 +189,10 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet) void ThreadIRCSeed(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg)); + + // Make this thread recognisable as the IRC seeding thread + RenameThread("bitcoin-ircseed"); + try { ThreadIRCSeed2(parg); diff --git a/src/main.cpp b/src/main.cpp index d2cb154c1f..0c636cdec1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -268,6 +268,9 @@ bool CTransaction::ReadFromDisk(COutPoint prevout) bool CTransaction::IsStandard() const { + if (nVersion > CTransaction::CURRENT_VERSION) + return false; + BOOST_FOREACH(const CTxIn& txin, vin) { // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG @@ -600,7 +603,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); remove(*ptxOld); } - addUnchecked(tx); + addUnchecked(hash, tx); } ///// are we sure this is ok when loading transactions or restoring block txes @@ -619,13 +622,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs); } -bool CTxMemPool::addUnchecked(CTransaction &tx) +bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx) { // Add to memory pool without checking anything. Don't call this directly, // call CTxMemPool::accept to properly check the transaction first. { - LOCK(cs); - uint256 hash = tx.GetHash(); mapTx[hash] = tx; for (unsigned int i = 0; i < tx.vin.size(); i++) mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i); @@ -652,6 +653,15 @@ bool CTxMemPool::remove(CTransaction &tx) return true; } +void +CTxMemPool::clear() +{ + LOCK(cs); + mapTx.clear(); + mapNextTx.clear(); + ++nTransactionsUpdated; +} + void CTxMemPool::queryHashes(std::vector<uint256>& vtxid) { vtxid.clear(); @@ -827,7 +837,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees) { int64 nSubsidy = 50 * COIN; - // Subsidy is cut in half every 4 years + // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years nSubsidy >>= (nHeight / 210000); return nSubsidy + nFees; @@ -970,8 +980,13 @@ void static InvalidChainFound(CBlockIndex* pindexNew) CTxDB().WriteBestInvalidWork(bnBestInvalidWork); uiInterface.NotifyBlocksChanged(); } - printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str()); - printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); + printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n", + pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, + pindexNew->bnChainWork.ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S", + pindexNew->GetBlockTime()).c_str()); + printf("InvalidChainFound: current best=%s height=%d work=%s date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6) printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n"); } @@ -1310,10 +1325,10 @@ bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex) return true; } -bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) +bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) { // Check it again in case a previous version let a bad block in - if (!CheckBlock()) + if (!CheckBlock(!fJustCheck, !fJustCheck)) return false; // Do not allow blocks that contain transactions which 'overwrite' older transactions, @@ -1325,38 +1340,45 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) // This logic is not necessary for memory pool transactions, as AcceptToMemoryPool // already refuses previously-known transaction id's entirely. // This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC. - if (pindex->nTime > 1331769600) - { - BOOST_FOREACH(CTransaction& tx, vtx) - { - CTxIndex txindexOld; - if (txdb.ReadTxIndex(tx.GetHash(), txindexOld)) - { - BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent) - if (pos.IsNull()) - return false; - } - } - } + int64 nBIP30SwitchTime = 1331769600; + bool fEnforceBIP30 = (pindex->nTime > nBIP30SwitchTime); // BIP16 didn't become active until Apr 1 2012 int64 nBIP16SwitchTime = 1333238400; bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime); //// issue here: it doesn't know the version - unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - 1 + GetSizeOfCompactSize(vtx.size()); + unsigned int nTxPos; + if (fJustCheck) + // FetchInputs treats CDiskTxPos(1,1,1) as a special "refer to memorypool" indicator + // Since we're just checking the block and not actually connecting it, it might not (and probably shouldn't) be on the disk to get the transaction from + nTxPos = 1; + else + nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - 1 + GetSizeOfCompactSize(vtx.size()); map<uint256, CTxIndex> mapQueuedChanges; int64 nFees = 0; unsigned int nSigOps = 0; BOOST_FOREACH(CTransaction& tx, vtx) { + uint256 hashTx = tx.GetHash(); + + if (fEnforceBIP30) { + CTxIndex txindexOld; + if (txdb.ReadTxIndex(hashTx, txindexOld)) { + BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent) + if (pos.IsNull()) + return false; + } + } + nSigOps += tx.GetLegacySigOpCount(); if (nSigOps > MAX_BLOCK_SIGOPS) return DoS(100, error("ConnectBlock() : too many sigops")); CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos); - nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); + if (!fJustCheck) + nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); MapPrevTx mapInputs; if (!tx.IsCoinBase()) @@ -1381,9 +1403,15 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return false; } - mapQueuedChanges[tx.GetHash()] = CTxIndex(posThisTx, tx.vout.size()); + mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size()); } + if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) + return false; + + if (fJustCheck) + return true; + // Write queued txindex changes for (map<uint256, CTxIndex>::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi) { @@ -1391,9 +1419,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) return error("ConnectBlock() : UpdateTxIndex failed"); } - if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) - return false; - // Update block index on disk without changing it in memory. // The memory index structure will be changed after the db commits. if (pindex->pprev) @@ -1613,7 +1638,27 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) bnBestChainWork = pindexNew->bnChainWork; nTimeBestReceived = GetTime(); nTransactionsUpdated++; - printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str()); + printf("SetBestChain: new best=%s height=%d work=%s date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); + + // Check the version of the last 100 blocks to see if we need to upgrade: + if (!fIsInitialDownload) + { + int nUpgraded = 0; + const CBlockIndex* pindex = pindexBest; + for (int i = 0; i < 100 && pindex != NULL; i++) + { + if (pindex->nVersion > CBlock::CURRENT_VERSION) + ++nUpgraded; + pindex = pindex->pprev; + } + if (nUpgraded > 0) + printf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION); + if (nUpgraded > 100/2) + // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: + strMiscWarning = _("Warning: this version is obsolete, upgrade required"); + } std::string strCmd = GetArg("-blocknotify", ""); @@ -1677,7 +1722,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) -bool CBlock::CheckBlock() const +bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot) const { // These are checks that are independent of context // that can be verified before saving an orphan block. @@ -1687,7 +1732,7 @@ bool CBlock::CheckBlock() const return DoS(100, error("CheckBlock() : size limits failed")); // Check proof of work matches claimed amount - if (!CheckProofOfWork(GetHash(), nBits)) + if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits)) return DoS(50, error("CheckBlock() : proof of work failed")); // Check timestamp @@ -1725,7 +1770,7 @@ bool CBlock::CheckBlock() const return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount")); // Check merkleroot - if (hashMerkleRoot != BuildMerkleTree()) + if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree()) return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch")); return true; @@ -1933,10 +1978,10 @@ bool LoadBlockIndex(bool fAllowNew) { if (fTestNet) { - pchMessageStart[0] = 0xfa; - pchMessageStart[1] = 0xbf; - pchMessageStart[2] = 0xb5; - pchMessageStart[3] = 0xda; + pchMessageStart[0] = 0x0b; + pchMessageStart[1] = 0x11; + pchMessageStart[2] = 0x09; + pchMessageStart[3] = 0x07; hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); } @@ -3267,16 +3312,18 @@ public: CTransaction* ptx; set<uint256> setDependsOn; double dPriority; + double dFeePerKb; COrphan(CTransaction* ptxIn) { ptx = ptxIn; - dPriority = 0; + dPriority = dFeePerKb = 0; } void print() const { - printf("COrphan(hash=%s, dPriority=%.1f)\n", ptx->GetHash().ToString().substr(0,10).c_str(), dPriority); + printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n", + ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb); BOOST_FOREACH(uint256 hash, setDependsOn) printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str()); } @@ -3286,6 +3333,33 @@ public: uint64 nLastBlockTx = 0; uint64 nLastBlockSize = 0; +// We want to sort transactions by priority and fee, so: +typedef boost::tuple<double, double, CTransaction*> TxPriority; +class TxPriorityCompare +{ + bool byFee; +public: + TxPriorityCompare(bool _byFee) : byFee(_byFee) { } + bool operator()(const TxPriority& a, const TxPriority& b) + { + if (byFee) + { + if (a.get<1>() == b.get<1>()) + return a.get<0>() < b.get<0>(); + return a.get<1>() < b.get<1>(); + } + else + { + if (a.get<0>() == b.get<0>()) + return a.get<1>() < b.get<1>(); + return a.get<0>() < b.get<0>(); + } + } +}; + +const char* pszDummy = "\0\0"; +CScript scriptDummy(std::vector<unsigned char>(pszDummy, pszDummy + sizeof(pszDummy))); + CBlock* CreateNewBlock(CReserveKey& reservekey) { CBlockIndex* pindexPrev = pindexBest; @@ -3305,6 +3379,30 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Add our coinbase tx as first transaction pblock->vtx.push_back(txNew); + // Largest block you're willing to create: + unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2); + // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: + nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); + + // How much of the block should be dedicated to high-priority transactions, + // included regardless of the fees they pay + unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000); + nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); + + // Minimum block size you want to create; block will be filled with free transactions + // until there are no more or the block reaches this size: + unsigned int nBlockMinSize = GetArg("-blockminsize", 0); + nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); + + // Fee-per-kilobyte amount considered the same as "free" + // Be careful setting this: if you set it to zero then + // a transaction spammer can cheaply fill blocks using + // 1-satoshi-fee transactions. It should be set above the real + // cost to you of processing a transaction. + int64 nMinTxFee = MIN_TX_FEE; + if (mapArgs.count("-mintxfee")) + ParseMoney(mapArgs["-mintxfee"], nMinTxFee); + // Collect memory pool transactions into the block int64 nFees = 0; { @@ -3314,7 +3412,10 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) // Priority order to process transactions list<COrphan> vOrphan; // list memory doesn't move map<uint256, vector<COrphan*> > mapDependers; - multimap<double, CTransaction*> mapPriority; + + // This vector will be sorted into a priority queue: + vector<TxPriority> vecPriority; + vecPriority.reserve(mempool.mapTx.size()); for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) { CTransaction& tx = (*mi).second; @@ -3323,6 +3424,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) COrphan* porphan = NULL; double dPriority = 0; + int64 nTotalIn = 0; + bool fMissingInputs = false; BOOST_FOREACH(const CTxIn& txin, tx.vin) { // Read prev transaction @@ -3330,6 +3433,19 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) CTxIndex txindex; if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) { + // This should never happen; all transactions in the memory + // pool should connect to either transactions in the chain + // or other transactions in the memory pool. + if (!mempool.mapTx.count(txin.prevout.hash)) + { + printf("ERROR: mempool transaction missing input\n"); + if (fDebug) assert("mempool transaction missing input" == 0); + fMissingInputs = true; + if (porphan) + vOrphan.pop_back(); + break; + } + // Has to wait for dependencies if (!porphan) { @@ -3339,34 +3455,33 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) } mapDependers[txin.prevout.hash].push_back(porphan); porphan->setDependsOn.insert(txin.prevout.hash); + nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue; continue; } int64 nValueIn = txPrev.vout[txin.prevout.n].nValue; + nTotalIn += nValueIn; - // Read block header int nConf = txindex.GetDepthInMainChain(); - dPriority += (double)nValueIn * nConf; - - if (fDebug && GetBoolArg("-printpriority")) - printf("priority nValueIn=%-12"PRI64d" nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority); } + if (fMissingInputs) continue; // Priority is sum(valuein * age) / txsize - dPriority /= ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + dPriority /= nTxSize; - if (porphan) - porphan->dPriority = dPriority; - else - mapPriority.insert(make_pair(-dPriority, &(*mi).second)); + // This is a more accurate fee-per-kilobyte than is used by the client code, because the + // client code rounds up the size to the nearest 1K. That's good, because it gives an + // incentive to create smaller transactions. + double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0); - if (fDebug && GetBoolArg("-printpriority")) + if (porphan) { - printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str()); - if (porphan) - porphan->print(); - printf("\n"); + porphan->dPriority = dPriority; + porphan->dFeePerKb = dFeePerKb; } + else + vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &(*mi).second)); } // Collect transactions into block @@ -3374,16 +3489,24 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) uint64 nBlockSize = 1000; uint64 nBlockTx = 0; int nBlockSigOps = 100; - while (!mapPriority.empty()) + bool fSortedByFee = (nBlockPrioritySize <= 0); + + TxPriorityCompare comparer(fSortedByFee); + std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); + + while (!vecPriority.empty()) { - // Take highest priority transaction off priority queue - double dPriority = -(*mapPriority.begin()).first; - CTransaction& tx = *(*mapPriority.begin()).second; - mapPriority.erase(mapPriority.begin()); + // Take highest priority transaction off the priority queue: + double dPriority = vecPriority.front().get<0>(); + double dFeePerKb = vecPriority.front().get<1>(); + CTransaction& tx = *(vecPriority.front().get<2>()); + + std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer); + vecPriority.pop_back(); // Size limits unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); - if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN) + if (nBlockSize + nTxSize >= nBlockMaxSize) continue; // Legacy limits on sigOps: @@ -3391,9 +3514,19 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; - // Transaction fee required depends on block size - bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority)); - int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, GMF_BLOCK); + // Skip free transactions if we're past the minimum block size: + if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + continue; + + // Prioritize by fee once past the priority size or we run out of high-priority + // transactions: + if (!fSortedByFee && + ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250))) + { + fSortedByFee = true; + comparer = TxPriorityCompare(fSortedByFee); + std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); + } // Connecting shouldn't fail due to dependency on other memory pool transactions // because we're already processing them in order of dependency @@ -3404,8 +3537,6 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) continue; int64 nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); - if (nTxFees < nMinFee) - continue; nTxSigOps += tx.GetP2SHSigOpCount(mapInputs); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) @@ -3423,6 +3554,12 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) nBlockSigOps += nTxSigOps; nFees += nTxFees; + if (fDebug && GetBoolArg("-printpriority")) + { + printf("priority %.1f feeperkb %.1f txid %s\n", + dPriority, dFeePerKb, tx.GetHash().ToString().c_str()); + } + // Add transactions that depend on this one to the priority queue uint256 hash = tx.GetHash(); if (mapDependers.count(hash)) @@ -3433,7 +3570,10 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) { porphan->setDependsOn.erase(hash); if (porphan->setDependsOn.empty()) - mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx)); + { + vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx)); + std::push_heap(vecPriority.begin(), vecPriority.end(), comparer); + } } } } @@ -3443,16 +3583,22 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) nLastBlockSize = nBlockSize; printf("CreateNewBlock(): total size %lu\n", nBlockSize); - } pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees); // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->UpdateTime(pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get()); pblock->nNonce = 0; + pblock->vtx[0].vin[0].scriptSig = scriptDummy; + CBlockIndex indexDummy(1, 1, *pblock); + indexDummy.pprev = pindexPrev; + indexDummy.nHeight = pindexPrev->nHeight + 1; + if (!pblock->ConnectBlock(txdb, &indexDummy, true)) + throw std::runtime_error("CreateNewBlock() : ConnectBlock failed"); + } + return pblock.release(); } @@ -3568,6 +3714,9 @@ void static BitcoinMiner(CWallet *pwallet) printf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); + // Make this thread recognisable as the mining thread + RenameThread("bitcoin-miner"); + // Each thread has its own key and counter CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; @@ -3597,7 +3746,8 @@ void static BitcoinMiner(CWallet *pwallet) return; IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce); - printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size()); + printf("Running BitcoinMiner with %d transactions in block (%u bytes)\n", pblock->vtx.size(), + ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); // diff --git a/src/main.h b/src/main.h index bb094ad3c7..301badcca9 100644 --- a/src/main.h +++ b/src/main.h @@ -386,6 +386,7 @@ typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx; class CTransaction { public: + static const int CURRENT_VERSION=1; int nVersion; std::vector<CTxIn> vin; std::vector<CTxOut> vout; @@ -411,7 +412,7 @@ public: void SetNull() { - nVersion = 1; + nVersion = CTransaction::CURRENT_VERSION; vin.clear(); vout.clear(); nLockTime = 0; @@ -817,6 +818,7 @@ class CBlock { public: // header + static const int CURRENT_VERSION=1; int nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -858,7 +860,7 @@ public: void SetNull() { - nVersion = 1; + nVersion = CBlock::CURRENT_VERSION; hashPrevBlock = 0; hashMerkleRoot = 0; nTime = 0; @@ -1014,11 +1016,11 @@ public: bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); - bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex); + bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false); bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew); bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); - bool CheckBlock() const; + bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true) const; bool AcceptBlock(); private: @@ -1602,8 +1604,9 @@ public: bool accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, bool* pfMissingInputs); - bool addUnchecked(CTransaction &tx); + bool addUnchecked(const uint256& hash, CTransaction &tx); bool remove(CTransaction &tx); + void clear(); void queryHashes(std::vector<uint256>& vtxid); unsigned long size() diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index cd8e97080c..fc22bb76ee 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -1,20 +1,20 @@ # Copyright (c) 2009-2010 Satoshi Nakamoto # Distributed under the MIT/X11 software license, see the accompanying -# file license.txt or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or http://www.opensource.org/licenses/mit-license.php. DEPSDIR:=/usr/i586-mingw32msvc USE_UPNP:=0 INCLUDEPATHS= \ - -I"$(DEPSDIR)/boost_1_47_0" \ + -I"$(DEPSDIR)/boost_1_49_0" \ -I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \ -I"$(DEPSDIR)/openssl-1.0.1b/include" \ -I"$(DEPSDIR)" \ -I"$(CURDIR)"/obj \ LIBPATHS= \ - -L"$(DEPSDIR)/boost_1_47_0/stage/lib" \ + -L"$(DEPSDIR)/boost_1_49_0/stage/lib" \ -L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \ -L"$(DEPSDIR)/openssl-1.0.1b" @@ -60,6 +60,8 @@ OBJS= \ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \ diff --git a/src/makefile.mingw b/src/makefile.mingw index 919be007b6..47637f0bc6 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -1,24 +1,24 @@ # Copyright (c) 2009-2010 Satoshi Nakamoto # Distributed under the MIT/X11 software license, see the accompanying -# file license.txt or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or http://www.opensource.org/licenses/mit-license.php. USE_UPNP:=0 INCLUDEPATHS= \ - -I"C:\boost-1.47.0-mgw" \ + -I"C:\boost-1.49.0-mgw" \ -I"C:\db-4.8.30.NC-mgw\build_unix" \ - -I"C:\openssl-1.0.0d-mgw\include" + -I"C:\openssl-1.0.1b-mgw\include" LIBPATHS= \ - -L"C:\boost-1.47.0-mgw\stage\lib" \ + -L"C:\boost-1.49.0-mgw\stage\lib" \ -L"C:\db-4.8.30.NC-mgw\build_unix" \ - -L"C:\openssl-1.0.0d-mgw" + -L"C:\openssl-1.0.1b-mgw" LIBS= \ - -l boost_system-mgw45-mt-s-1_47 \ - -l boost_filesystem-mgw45-mt-s-1_47 \ - -l boost_program_options-mgw45-mt-s-1_47 \ - -l boost_thread-mgw45-mt-s-1_47 \ + -l boost_system-mgw45-mt-s-1_49 \ + -l boost_filesystem-mgw45-mt-s-1_49 \ + -l boost_program_options-mgw45-mt-s-1_49 \ + -l boost_thread-mgw45-mt-s-1_49 \ -l db_cxx \ -l ssl \ -l crypto @@ -57,6 +57,8 @@ OBJS= \ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \ diff --git a/src/makefile.osx b/src/makefile.osx index 9728733122..d64bed5617 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -1,7 +1,7 @@ # -*- mode: Makefile; -*- # Copyright (c) 2011 Bitcoin Developers # Distributed under the MIT/X11 software license, see the accompanying -# file license.txt or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # Mac OS X makefile for bitcoin # Originally by Laszlo Hanyecz (solar@heliacal.net) @@ -84,6 +84,8 @@ OBJS= \ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \ @@ -112,7 +114,7 @@ version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO obj/%.o: %.cpp - $(CXX) -c $(CFLAGS) -MMD -o $@ $< + $(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ @@ -124,7 +126,7 @@ bitcoind: $(OBJS:obj/%=obj/%) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -o $@ $< + $(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ diff --git a/src/makefile.unix b/src/makefile.unix index 9052891b4f..857f44531e 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -1,6 +1,6 @@ # Copyright (c) 2009-2010 Satoshi Nakamoto # Distributed under the MIT/X11 software license, see the accompanying -# file license.txt or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or http://www.opensource.org/licenses/mit-license.php. USE_UPNP:=0 @@ -66,13 +66,14 @@ LIBS+= \ # Make some important things such as the global offset table read only as soon as # the dynamic linker is finished building it. This will prevent overwriting of addresses # which would later be jumped to. - HARDENING+=-Wl,-z,relro -Wl,-z,now + LDHARDENING+=-Wl,-z,relro -Wl,-z,now # Build position independent code to take advantage of Address Space Layout Randomization # offered by some kernels. # see doc/build-unix.txt for more information. ifdef PIE - HARDENING+=-fPIE -pie + HARDENING+=-fPIE + LDHARDENING+=-pie endif # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in @@ -88,6 +89,10 @@ DEBUGFLAGS=-g xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \ $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) +# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only +# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work. +xLDFLAGS=$(LDHARDENING) $(LDFLAGS) + OBJS= \ obj/version.o \ obj/checkpoints.o \ @@ -104,6 +109,8 @@ OBJS= \ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \ @@ -124,26 +131,26 @@ version.cpp: obj/build.h DEFS += -DHAVE_BUILD_INFO obj/%.o: %.cpp - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ rm -f $(@:%.o=%.d) bitcoind: $(OBJS:obj/%=obj/%) - $(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) + $(CXX) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -o $@ $< + $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< @cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ rm -f $(@:%.o=%.d) test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%)) - $(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS) + $(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(xLDFLAGS) $(LIBS) clean: -rm -f bitcoind test_bitcoin diff --git a/src/net.cpp b/src/net.cpp index f1073e0a3e..cc1aeeff08 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -407,6 +407,9 @@ bool GetMyExternalIP(CNetAddr& ipRet) void ThreadGetMyExternalIP(void* parg) { + // Make this thread recognisable as the external IP detection thread + RenameThread("bitcoin-ext-ip"); + CNetAddr addrLocalHost; if (GetMyExternalIP(addrLocalHost)) { @@ -586,7 +589,7 @@ bool CNode::Misbehaving(int howmuch) { if (addr.IsLocal()) { - printf("Warning: local node %s misbehaving\n", addrName.c_str()); + printf("Warning: local node %s misbehaving (delta: %d)\n", addrName.c_str(), howmuch); return false; } @@ -594,19 +597,36 @@ bool CNode::Misbehaving(int howmuch) if (nMisbehavior >= GetArg("-banscore", 100)) { int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban + printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior); { LOCK(cs_setBanned); if (setBanned[addr] < banTime) setBanned[addr] = banTime; } CloseSocketDisconnect(); - printf("Disconnected %s for misbehavior (score=%d)\n", addrName.c_str(), nMisbehavior); return true; - } + } else + printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior); return false; } - +#undef X +#define X(name) stats.name = name +void CNode::copyStats(CNodeStats &stats) +{ + X(nServices); + X(nLastSend); + X(nLastRecv); + X(nTimeConnected); + X(addrName); + X(nVersion); + X(strSubVer); + X(fInbound); + X(nReleaseTime); + X(nStartingHeight); + X(nMisbehavior); +} +#undef X @@ -620,6 +640,10 @@ bool CNode::Misbehaving(int howmuch) void ThreadSocketHandler(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg)); + + // Make this thread recognisable as the networking thread + RenameThread("bitcoin-net"); + try { vnThreadsRunning[THREAD_SOCKETHANDLER]++; @@ -922,8 +946,6 @@ void ThreadSocketHandler2(void* parg) pnode->CloseSocketDisconnect(); } } - if (vSend.size() > SendBufferSize()) - printf("socket send buffer full warning (%d bytes)\n", vSend.size()); } } } @@ -974,6 +996,10 @@ void ThreadSocketHandler2(void* parg) void ThreadMapPort(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg)); + + // Make this thread recognisable as the UPnP thread + RenameThread("bitcoin-UPnP"); + try { vnThreadsRunning[THREAD_UPNP]++; @@ -1123,15 +1149,19 @@ void MapPort() // The first name is used as information source for addrman. // The second name should resolve to a list of seed addresses. static const char *strDNSSeed[][2] = { - {"xf2.org", "bitseed.xf2.org"}, - {"bluematt.me", "dnsseed.bluematt.me"}, {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"}, + {"bluematt.me", "dnsseed.bluematt.me"}, {"dashjr.org", "dnsseed.bitcoin.dashjr.org"}, + {"xf2.org", "bitseed.xf2.org"}, }; void ThreadDNSAddressSeed(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg)); + + // Make this thread recognisable as the DNS seeding thread + RenameThread("bitcoin-dnsseed"); + try { vnThreadsRunning[THREAD_DNSSEED]++; @@ -1301,6 +1331,10 @@ void ThreadDumpAddress2(void* parg) void ThreadDumpAddress(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadDumpAddress(parg)); + + // Make this thread recognisable as the address dumping thread + RenameThread("bitcoin-adrdump"); + try { ThreadDumpAddress2(parg); @@ -1314,6 +1348,10 @@ void ThreadDumpAddress(void* parg) void ThreadOpenConnections(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg)); + + // Make this thread recognisable as the connection opening thread + RenameThread("bitcoin-opencon"); + try { vnThreadsRunning[THREAD_OPENCONNECTIONS]++; @@ -1416,16 +1454,17 @@ void ThreadOpenConnections2(void* parg) // CAddress addrConnect; - // Only connect to one address per a.b.?.? range. + // Only connect out to one peer per network group (/16 for IPv4). // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. int nOutbound = 0; set<vector<unsigned char> > setConnected; { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { - setConnected.insert(pnode->addr.GetGroup()); - if (!pnode->fInbound) + if (!pnode->fInbound) { + setConnected.insert(pnode->addr.GetGroup()); nOutbound++; + } } } @@ -1466,6 +1505,10 @@ void ThreadOpenConnections2(void* parg) void ThreadOpenAddedConnections(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg)); + + // Make this thread recognisable as the connection opening thread + RenameThread("bitcoin-opencon"); + try { vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; @@ -1595,6 +1638,10 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu void ThreadMessageHandler(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg)); + + // Make this thread recognisable as the message handling thread + RenameThread("bitcoin-msghand"); + try { vnThreadsRunning[THREAD_MESSAGEHANDLER]++; @@ -1832,11 +1879,16 @@ void static Discover() } #endif - CreateThread(ThreadGetMyExternalIP, NULL); + // Don't use external IPv4 discovery, when -onlynet="IPv6" + if (!IsLimited(NET_IPV4)) + CreateThread(ThreadGetMyExternalIP, NULL); } void StartNode(void* parg) { + // Make this thread recognisable as the startup thread + RenameThread("bitcoin-start"); + if (semOutbound == NULL) { // initialize semaphore int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); @@ -27,7 +27,7 @@ extern int nBestHeight; inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } -inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 5*1000); } +inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } void AddOneShot(std::string strDest); bool RecvLine(SOCKET hSocket, std::string& strLine); @@ -128,6 +128,24 @@ extern std::map<CInv, int64> mapAlreadyAskedFor; +class CNodeStats +{ +public: + uint64 nServices; + int64 nLastSend; + int64 nLastRecv; + int64 nTimeConnected; + std::string addrName; + int nVersion; + std::string strSubVer; + bool fInbound; + int64 nReleaseTime; + int nStartingHeight; + int nMisbehavior; +}; + + + /** Information about a peer */ @@ -353,14 +371,14 @@ public: // Set the size unsigned int nSize = vSend.size() - nMessageStart; - memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); + memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize)); // Set the checksum uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end()); unsigned int nChecksum = 0; memcpy(&nChecksum, &hash, sizeof(nChecksum)); - assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum)); - memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum)); + assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); + memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum)); if (fDebug) { printf("(%d bytes)\n", nSize); @@ -617,6 +635,7 @@ public: static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot + void copyStats(CNodeStats &stats); }; diff --git a/src/netbase.cpp b/src/netbase.cpp index aa767cd3eb..0a54fdf46c 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -224,7 +224,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) } char pszSocks5Init[] = "\5\1\0"; char *pszSocks5 = pszSocks5Init; - ssize_t nSize = sizeof(pszSocks5Init); + ssize_t nSize = sizeof(pszSocks5Init) - 1; ssize_t ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL); if (ret != nSize) diff --git a/src/protocol.h b/src/protocol.h index b516f1b897..36f8b144cd 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -49,8 +49,16 @@ class CMessageHeader // TODO: make private (improves encapsulation) public: - enum { COMMAND_SIZE=12 }; - char pchMessageStart[sizeof(::pchMessageStart)]; + enum { + MESSAGE_START_SIZE=sizeof(::pchMessageStart), + COMMAND_SIZE=12, + MESSAGE_SIZE_SIZE=sizeof(int), + CHECKSUM_SIZE=sizeof(int), + + MESSAGE_SIZE_OFFSET=MESSAGE_START_SIZE+COMMAND_SIZE, + CHECKSUM_OFFSET=MESSAGE_SIZE_OFFSET+MESSAGE_SIZE_SIZE + }; + char pchMessageStart[MESSAGE_START_SIZE]; char pchCommand[COMMAND_SIZE]; unsigned int nMessageSize; unsigned int nChecksum; diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 5849f5b23d..8a74a47f58 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -2,6 +2,7 @@ #include "ui_addressbookpage.h" #include "addresstablemodel.h" +#include "optionsmodel.h" #include "bitcoingui.h" #include "editaddressdialog.h" #include "csvmodelwriter.h" @@ -20,6 +21,7 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), model(0), + optionsModel(0), mode(mode), tab(tab) { @@ -65,6 +67,7 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : QAction *editAction = new QAction(tr("&Edit"), this); QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this); QAction *signMessageAction = new QAction(ui->signMessage->text(), this); + QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this); deleteAction = new QAction(ui->deleteButton->text(), this); // Build context menu @@ -78,6 +81,8 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : contextMenu->addAction(showQRCodeAction); if(tab == ReceivingTab) contextMenu->addAction(signMessageAction); + else if(tab == SendingTab) + contextMenu->addAction(verifyMessageAction); // Connect signals for context menu actions connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked())); @@ -86,6 +91,7 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked())); connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked())); connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked())); connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); @@ -107,6 +113,8 @@ void AddressBookPage::setModel(AddressTableModel *model) proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(model); proxyModel->setDynamicSortFilter(true); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); switch(tab) { case ReceivingTab: @@ -139,6 +147,11 @@ void AddressBookPage::setModel(AddressTableModel *model) selectionChanged(); } +void AddressBookPage::setOptionsModel(OptionsModel *optionsModel) +{ + this->optionsModel = optionsModel; +} + void AddressBookPage::on_copyToClipboard_clicked() { GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address); @@ -179,10 +192,22 @@ void AddressBookPage::on_signMessage_clicked() addr = address.toString(); } - QObject *qoGUI = parent()->parent(); - BitcoinGUI *gui = qobject_cast<BitcoinGUI *>(qoGUI); - if (gui) - gui->gotoMessagePage(addr); + emit signMessage(addr); +} + +void AddressBookPage::on_verifyMessage_clicked() +{ + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + QString addr; + + foreach (QModelIndex index, indexes) + { + QVariant address = index.data(); + addr = address.toString(); + } + + emit verifyMessage(addr); } void AddressBookPage::on_newAddressButton_clicked() @@ -230,6 +255,8 @@ void AddressBookPage::selectionChanged() deleteAction->setEnabled(true); ui->signMessage->setEnabled(false); ui->signMessage->setVisible(false); + ui->verifyMessage->setEnabled(true); + ui->verifyMessage->setVisible(true); break; case ReceivingTab: // Deleting receiving addresses, however, is not allowed @@ -238,6 +265,8 @@ void AddressBookPage::selectionChanged() deleteAction->setEnabled(false); ui->signMessage->setEnabled(true); ui->signMessage->setVisible(true); + ui->verifyMessage->setEnabled(false); + ui->verifyMessage->setVisible(false); break; } ui->copyToClipboard->setEnabled(true); @@ -249,6 +278,7 @@ void AddressBookPage::selectionChanged() ui->showQRCode->setEnabled(false); ui->copyToClipboard->setEnabled(false); ui->signMessage->setEnabled(false); + ui->verifyMessage->setEnabled(false); } } @@ -314,6 +344,8 @@ void AddressBookPage::on_showQRCode_clicked() QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString(); QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this); + if(optionsModel) + dialog->setModel(optionsModel); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); } diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index b2e91c7cb2..df87486949 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -7,6 +7,7 @@ namespace Ui { class AddressBookPage; } class AddressTableModel; +class OptionsModel; QT_BEGIN_NAMESPACE class QTableView; @@ -37,6 +38,7 @@ public: ~AddressBookPage(); void setModel(AddressTableModel *model); + void setOptionsModel(OptionsModel *optionsModel); const QString &getReturnValue() const { return returnValue; } public slots: @@ -46,6 +48,7 @@ public slots: private: Ui::AddressBookPage *ui; AddressTableModel *model; + OptionsModel *optionsModel; Mode mode; Tabs tab; QString returnValue; @@ -60,6 +63,7 @@ private slots: /** Copy address of currently selected address entry to clipboard */ void on_copyToClipboard_clicked(); void on_signMessage_clicked(); + void on_verifyMessage_clicked(); void selectionChanged(); void on_showQRCode_clicked(); /** Spawn contextual menu (right mouse menu) for address book entry */ @@ -72,6 +76,10 @@ private slots: /** New entry/entries were added to address table */ void selectNewAddress(const QModelIndex &parent, int begin, int end); + +signals: + void signMessage(QString addr); + void verifyMessage(QString addr); }; #endif // ADDRESSBOOKDIALOG_H diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 0a8ace09df..3656cbea1f 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -157,7 +157,7 @@ void AskPassphraseDialog::accept() if(model->changePassphrase(oldpass, newpass1)) { QMessageBox::information(this, tr("Wallet encrypted"), - tr("Wallet passphrase was succesfully changed.")); + tr("Wallet passphrase was successfully changed.")); QDialog::accept(); // Success } else diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index b4e751077e..6bdac2ad70 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -109,16 +109,15 @@ static std::string Translate(const char* psz) static void handleRunawayException(std::exception *e) { PrintExceptionContinue(e, "Runaway exception"); - QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occured. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning)); + QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning)); exit(1); } #ifndef BITCOIN_QT_TEST int main(int argc, char *argv[]) { -#if !defined(MAC_OSX) && !defined(WIN32) -// TODO: implement qtipcserver.cpp for Mac and Windows - +// TODO: implement URI support on the Mac. +#if !defined(MAC_OSX) // Do this early as we don't want to bother initializing if we are just calling IPC for (int i = 1; i < argc; i++) { @@ -127,13 +126,21 @@ int main(int argc, char *argv[]) const char *strURI = argv[i]; try { boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME); - if(mq.try_send(strURI, strlen(strURI), 0)) + if (mq.try_send(strURI, strlen(strURI), 0)) + // if URI could be sent to the message queue exit here exit(0); else + // if URI could not be sent to the message queue do a normal Bitcoin-Qt startup break; } catch (boost::interprocess::interprocess_exception &ex) { - break; + // don't log the "file not found" exception, because that's normal for + // the first start of the first instance + if (ex.get_error_code() != boost::interprocess::not_found_error) + { + printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what()); + break; + } } } } @@ -262,8 +269,8 @@ int main(int argc, char *argv[]) { window.show(); } -#if !defined(MAC_OSX) && !defined(WIN32) -// TODO: implement qtipcserver.cpp for Mac and Windows +// TODO: implement URI support on the Mac. +#if !defined(MAC_OSX) // Place this here as guiref has to be defined if we dont want to lose URIs ipcInit(); @@ -279,6 +286,8 @@ int main(int argc, char *argv[]) mq.try_send(strURI, strlen(strURI), 0); } catch (boost::interprocess::interprocess_exception &ex) { + printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what()); + break; } } } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index c642f4aa0b..afb829e08a 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -8,8 +8,7 @@ #include "transactiontablemodel.h" #include "addressbookpage.h" #include "sendcoinsdialog.h" -#include "messagepage.h" -#include "verifymessagedialog.h" +#include "signverifymessagedialog.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" @@ -52,7 +51,6 @@ #include <QFileDialog> #include <QDesktopServices> #include <QTimer> - #include <QDragEnterEvent> #include <QUrl> @@ -70,7 +68,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): rpcConsole(0) { resize(850, 550); - setWindowTitle(tr("Bitcoin Wallet")); + setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet")); #ifndef Q_WS_MAC qApp->setWindowIcon(QIcon(":icons/bitcoin")); setWindowIcon(QIcon(":icons/bitcoin")); @@ -108,7 +106,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): sendCoinsPage = new SendCoinsDialog(this); - messagePage = new MessagePage(this); + signVerifyMessageDialog = new SignVerifyMessageDialog(this); centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); @@ -117,7 +115,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); #ifdef FIRST_CLASS_MESSAGING - centralWidget->addWidget(messagePage); + centralWidget->addWidget(signVerifyMessageDialog); #endif setCentralWidget(centralWidget); @@ -166,6 +164,11 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): rpcConsole = new RPCConsole(this); connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); + // Clicking on "Verify Message" in the address book sends you to the verify message tab + connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString))); + // Clicking on "Sign Message" in the receive coins page sends you to the sign message tab + connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString))); + gotoOverviewPage(); } @@ -212,12 +215,20 @@ void BitcoinGUI::createActions() sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); - messageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this); - messageAction->setToolTip(tr("Prove you control an address")); + signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this); + signMessageAction->setToolTip(tr("Sign a message to prove you own a Bitcoin address")); + tabGroup->addAction(signMessageAction); + + verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); + verifyMessageAction->setToolTip(tr("Verify a message to ensure it was signed with a specified Bitcoin address")); + tabGroup->addAction(verifyMessageAction); + #ifdef FIRST_CLASS_MESSAGING - messageAction->setCheckable(true); + firstClassMessagingAction = new QAction(QIcon(":/icons/edit"), tr("S&ignatures"), this); + firstClassMessagingAction->setToolTip(signMessageAction->toolTip() + QString(". / ") + verifyMessageAction->toolTip() + QString(".")); + firstClassMessagingAction->setCheckable(true); + tabGroup->addAction(firstClassMessagingAction); #endif - tabGroup->addAction(messageAction); connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); @@ -229,14 +240,21 @@ void BitcoinGUI::createActions() connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); - connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); - connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage())); + connect(signMessageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab())); +#ifdef FIRST_CLASS_MESSAGING + connect(firstClassMessagingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + // Always start with the sign message tab for FIRST_CLASS_MESSAGING + connect(firstClassMessagingAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); +#endif quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); quitAction->setToolTip(tr("Quit application")); quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); quitAction->setMenuRole(QAction::QuitRole); - aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About %1").arg(qApp->applicationName()), this); + aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this); aboutAction->setToolTip(tr("Show information about Bitcoin")); aboutAction->setMenuRole(QAction::AboutRole); aboutQtAction = new QAction(tr("About &Qt"), this); @@ -258,8 +276,6 @@ void BitcoinGUI::createActions() changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); - verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); - verifyMessageAction->setToolTip(tr("Verify a message signature")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); @@ -269,7 +285,6 @@ void BitcoinGUI::createActions() connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); - connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(verifyMessage())); } void BitcoinGUI::createMenuBar() @@ -287,9 +302,9 @@ void BitcoinGUI::createMenuBar() file->addAction(backupWalletAction); file->addAction(exportAction); #ifndef FIRST_CLASS_MESSAGING - file->addAction(messageAction); -#endif + file->addAction(signMessageAction); file->addAction(verifyMessageAction); +#endif file->addSeparator(); file->addAction(quitAction); @@ -316,7 +331,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(historyAction); toolbar->addAction(addressBookAction); #ifdef FIRST_CLASS_MESSAGING - toolbar->addAction(messageAction); + toolbar->addAction(firstClassMessagingAction); #endif QToolBar *toolbar2 = addToolBar(tr("Actions toolbar")); @@ -329,6 +344,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) this->clientModel = clientModel; if(clientModel) { + // Replace some strings and icons, when using the testnet if(clientModel->isTestNet()) { setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]")); @@ -344,6 +360,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet")); } + + aboutAction->setIcon(QIcon(":/icons/toolbar_testnet")); } // Keep up to date with client @@ -357,6 +375,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); rpcConsole->setClientModel(clientModel); + addressBookPage->setOptionsModel(clientModel->getOptionsModel()); + receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel()); } } @@ -375,7 +395,7 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) addressBookPage->setModel(walletModel->getAddressTableModel()); receiveCoinsPage->setModel(walletModel->getAddressTableModel()); sendCoinsPage->setModel(walletModel); - messagePage->setModel(walletModel); + signVerifyMessageDialog->setModel(walletModel); setEncryptionStatus(walletModel->getEncryptionStatus()); connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); @@ -415,7 +435,7 @@ void BitcoinGUI::createTrayIcon() #ifndef FIRST_CLASS_MESSAGING trayIconMenu->addSeparator(); #endif - trayIconMenu->addAction(messageAction); + trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(optionsAction); @@ -481,6 +501,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) return; } + QString strStatusBarWarnings = clientModel->getStatusBarWarnings(); QString tooltip; if(count < nTotalBlocks) @@ -488,7 +509,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) int nRemainingBlocks = nTotalBlocks - count; float nPercentageDone = count / (nTotalBlocks * 0.01f); - if (clientModel->getStatusBarWarnings() == "") + if (strStatusBarWarnings.isEmpty()) { progressBarLabel->setText(tr("Synchronizing with network...")); progressBarLabel->setVisible(true); @@ -497,30 +518,28 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) progressBar->setValue(count); progressBar->setVisible(true); } - else - { - progressBarLabel->setText(clientModel->getStatusBarWarnings()); - progressBarLabel->setVisible(true); - progressBar->setVisible(false); - } + tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2); } else { - if (clientModel->getStatusBarWarnings() == "") + if (strStatusBarWarnings.isEmpty()) progressBarLabel->setVisible(false); - else - { - progressBarLabel->setText(clientModel->getStatusBarWarnings()); - progressBarLabel->setVisible(true); - } + progressBar->setVisible(false); tooltip = tr("Downloaded %1 blocks of transaction history.").arg(count); } - QDateTime now = QDateTime::currentDateTime(); + // Override progressBarLabel text and hide progressBar, when we have warnings to display + if (!strStatusBarWarnings.isEmpty()) + { + progressBarLabel->setText(strStatusBarWarnings); + progressBarLabel->setVisible(true); + progressBar->setVisible(false); + } + QDateTime lastBlockDate = clientModel->getLastBlockDate(); - int secs = lastBlockDate.secsTo(now); + int secs = lastBlockDate.secsTo(QDateTime::currentDateTime()); QString text; // Represent time from last generated block in human readable text @@ -717,20 +736,42 @@ void BitcoinGUI::gotoSendCoinsPage() disconnect(exportAction, SIGNAL(triggered()), 0, 0); } -void BitcoinGUI::gotoMessagePage(QString addr) +void BitcoinGUI::gotoSignMessageTab(QString addr) { +#ifdef FIRST_CLASS_MESSAGING + firstClassMessagingAction->setChecked(true); + centralWidget->setCurrentWidget(signVerifyMessageDialog); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + + signVerifyMessageDialog->showTab_SM(false); +#else + // call show() in showTab_SM() + signVerifyMessageDialog->showTab_SM(true); +#endif + if(!addr.isEmpty()) - messagePage->setAddress(addr); + signVerifyMessageDialog->setAddress_SM(addr); +} +void BitcoinGUI::gotoVerifyMessageTab(QString addr) +{ #ifdef FIRST_CLASS_MESSAGING - messageAction->setChecked(true); - centralWidget->setCurrentWidget(messagePage); + firstClassMessagingAction->setChecked(true); + centralWidget->setCurrentWidget(signVerifyMessageDialog); exportAction->setEnabled(false); disconnect(exportAction, SIGNAL(triggered()), 0, 0); + + signVerifyMessageDialog->showTab_VM(false); #else - messagePage->show(); + // call show() in showTab_VM() + signVerifyMessageDialog->showTab_VM(true); #endif + + if(!addr.isEmpty()) + signVerifyMessageDialog->setAddress_VM(addr); } void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) @@ -833,13 +874,6 @@ void BitcoinGUI::changePassphrase() dlg.exec(); } -void BitcoinGUI::verifyMessage() -{ - VerifyMessageDialog *dlg = new VerifyMessageDialog(this); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->show(); -} - void BitcoinGUI::unlockWallet() { if(!walletModel) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 3c82cbc968..adc75b0481 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -11,7 +11,7 @@ class TransactionView; class OverviewPage; class AddressBookPage; class SendCoinsDialog; -class MessagePage; +class SignVerifyMessageDialog; class Notificator; class RPCConsole; @@ -64,7 +64,7 @@ private: AddressBookPage *addressBookPage; AddressBookPage *receiveCoinsPage; SendCoinsDialog *sendCoinsPage; - MessagePage *messagePage; + SignVerifyMessageDialog *signVerifyMessageDialog; QLabel *labelEncryptionIcon; QLabel *labelConnectionsIcon; @@ -78,8 +78,9 @@ private: QAction *quitAction; QAction *sendCoinsAction; QAction *addressBookAction; - QAction *messageAction; + QAction *signMessageAction; QAction *verifyMessageAction; + QAction *firstClassMessagingAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -111,7 +112,7 @@ public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks shown in the UI */ - void setNumBlocks(int count, int countOfPeers); + void setNumBlocks(int count, int nTotalBlocks); /** Set the encryption status as shown in the UI. @param[in] status current encryption status @see WalletModel::EncryptionStatus @@ -131,8 +132,6 @@ public slots: void askFee(qint64 nFeeRequired, bool *payFee); void handleURI(QString strURI); - void gotoMessagePage(QString addr = ""); - private slots: /** Switch to overview (home) page */ void gotoOverviewPage(); @@ -145,6 +144,11 @@ private slots: /** Switch to send coins page */ void gotoSendCoinsPage(); + /** Show Sign/Verify Message dialog and switch to sign message tab */ + void gotoSignMessageTab(QString addr = ""); + /** Show Sign/Verify Message dialog and switch to verify message tab */ + void gotoVerifyMessageTab(QString addr = ""); + /** Show configuration dialog */ void optionsClicked(); /** Show about dialog */ @@ -164,8 +168,6 @@ private slots: void backupWallet(); /** Change encrypted wallet passphrase */ void changePassphrase(); - /** Verify a message signature */ - void verifyMessage(); /** Ask for pass phrase to unlock wallet temporarily */ void unlockWallet(); diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 56214df7a7..219397dbf9 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -5,7 +5,8 @@ #else #define UNUSED #endif -static const char UNUSED *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", "" +static const char UNUSED *bitcoin_strings[] = { +QT_TRANSLATE_NOOP("bitcoin-core", "" "%s, you must set a rpcpassword in the configuration file:\n" " %s\n" "It is recommended you use the following random password:\n" @@ -81,7 +82,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transa QT_TRANSLATE_NOOP("bitcoin-core", "Error: could not start node"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"), -QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"), QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using internet relay chat (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins"), QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"), @@ -90,6 +91,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-6, QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000?.dat file"), QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -tor address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"), QT_TRANSLATE_NOOP("bitcoin-core", "List commands"), @@ -99,11 +101,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."), QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."), QT_TRANSLATE_NOOP("bitcoin-core", "Loading wallet..."), QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most <n> connections to peers (default: 125)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4 or IPv6)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4, IPv6 or Tor)"), QT_TRANSLATE_NOOP("bitcoin-core", "Options:"), -QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information"), +QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information. Implies all other -debug* options"), +QT_TRANSLATE_NOOP("bitcoin-core", "Output extra network debugging information"), QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp"), QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"), @@ -136,8 +139,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"), QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use proxy to reach tor hidden services (default: same as -proxy)"), QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"), QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"), QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: this version is obsolete, upgrade required"), };
\ No newline at end of file diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index cabbd5d240..8fcc4e650e 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -18,7 +18,7 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : { numBlocksAtStartup = -1; - pollTimer = new QTimer(); + pollTimer = new QTimer(this); pollTimer->setInterval(MODEL_UPDATE_DELAY); pollTimer->start(); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index 21fc7b2019..6632e311d0 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -98,7 +98,7 @@ This is experimental software. -Distributed under the MIT/X11 software license, see the accompanying file license.txt or http://www.opensource.org/licenses/mit-license.php. +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</string> </property> diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui index bca0a8dcdb..eac35c27ae 100644 --- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>627</width> - <height>347</height> + <width>760</width> + <height>380</height> </rect> </property> <property name="windowTitle"> @@ -17,10 +17,10 @@ <item> <widget class="QLabel" name="labelExplanation"> <property name="text"> - <string>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</string> + <string>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</string> </property> <property name="textFormat"> - <enum>Qt::AutoText</enum> + <enum>Qt::PlainText</enum> </property> <property name="wordWrap"> <bool>true</bool> @@ -99,7 +99,7 @@ <item> <widget class="QPushButton" name="signMessage"> <property name="toolTip"> - <string>Sign a message to prove you own this address</string> + <string>Sign a message to prove you own a Bitcoin address</string> </property> <property name="text"> <string>&Sign Message</string> @@ -111,6 +111,20 @@ </widget> </item> <item> + <widget class="QPushButton" name="verifyMessage"> + <property name="toolTip"> + <string>Verify a message to ensure it was signed with a specified Bitcoin address</string> + </property> + <property name="text"> + <string>&Verify Message</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset> + </property> + </widget> + </item> + <item> <widget class="QPushButton" name="deleteButton"> <property name="toolTip"> <string>Delete the currently selected address from the list. Only sending addresses can be deleted.</string> diff --git a/src/qt/forms/messagepage.ui b/src/qt/forms/messagepage.ui deleted file mode 100644 index 0b685aae1d..0000000000 --- a/src/qt/forms/messagepage.ui +++ /dev/null @@ -1,181 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>MessagePage</class> - <widget class="QWidget" name="MessagePage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>627</width> - <height>380</height> - </rect> - </property> - <property name="windowTitle"> - <string>Sign Message</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="labelExplanation"> - <property name="text"> - <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string> - </property> - <property name="textFormat"> - <enum>Qt::AutoText</enum> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <property name="spacing"> - <number>0</number> - </property> - <item> - <widget class="QValidatedLineEdit" name="signFrom"> - <property name="toolTip"> - <string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string> - </property> - <property name="maxLength"> - <number>34</number> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="addressBookButton"> - <property name="toolTip"> - <string>Choose adress from address book</string> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset> - </property> - <property name="shortcut"> - <string>Alt+A</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - <property name="flat"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pasteButton"> - <property name="toolTip"> - <string>Paste address from clipboard</string> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset> - </property> - <property name="shortcut"> - <string>Alt+P</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPlainTextEdit" name="message"> - <property name="toolTip"> - <string>Enter the message you want to sign here</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="signature"> - <property name="font"> - <font> - <italic>true</italic> - </font> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="signMessage"> - <property name="toolTip"> - <string>Sign a message to prove you own this address</string> - </property> - <property name="text"> - <string>&Sign Message</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="copyToClipboard"> - <property name="toolTip"> - <string>Copy the current signature to the system clipboard</string> - </property> - <property name="text"> - <string>&Copy Signature</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="clearButton"> - <property name="toolTip"> - <string>Reset all sign message fields</string> - </property> - <property name="text"> - <string>Clear &All</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>QValidatedLineEdit</class> - <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> - </customwidget> - </customwidgets> - <resources> - <include location="../bitcoin.qrc"/> - </resources> - <connections/> -</ui> diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 07e2324edb..270b7ae9ef 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -129,7 +129,7 @@ <item> <widget class="QCheckBox" name="connectSocks"> <property name="toolTip"> - <string>Connect to the Bitcon network through a SOCKS proxy (e.g. when connecting through Tor).</string> + <string>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</string> </property> <property name="text"> <string>&Connect through SOCKS proxy:</string> diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui index 6199b68749..52e9db3762 100644 --- a/src/qt/forms/qrcodedialog.ui +++ b/src/qt/forms/qrcodedialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>334</width> - <height>425</height> + <width>340</width> + <height>530</height> </rect> </property> <property name="windowTitle"> @@ -28,8 +28,8 @@ <height>300</height> </size> </property> - <property name="text"> - <string>QR Code</string> + <property name="textFormat"> + <enum>Qt::PlainText</enum> </property> <property name="alignment"> <set>Qt::AlignCenter</set> @@ -40,133 +40,122 @@ </widget> </item> <item> + <widget class="QPlainTextEdit" name="outUri"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> <widget class="QWidget" name="widget" native="true"> <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QCheckBox" name="chkReqPayment"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Request Payment</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="lblAmount"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Amount:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnReqAmount</cstring> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lnReqAmount"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>60</width> - <height>0</height> - </size> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="lblBTC"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>BTC</string> - </property> - <property name="buddy"> - <cstring>lnReqAmount</cstring> - </property> - </widget> - </item> - </layout> - </item> - </layout> + <widget class="QCheckBox" name="chkReqPayment"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Request Payment</string> + </property> + </widget> + </item> + <item> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="1" column="0"> + <widget class="QLabel" name="lblLabel"> + <property name="text"> + <string>Label:</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnLabel</cstring> + </property> + </widget> </item> - <item> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="lblLabel"> - <property name="text"> - <string>Label:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnLabel</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="lnLabel"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>0</height> - </size> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="lblMessage"> - <property name="text"> - <string>Message:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>lnMessage</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="lnMessage"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>0</height> - </size> - </property> - </widget> - </item> - </layout> + <item row="1" column="1"> + <widget class="QLineEdit" name="lnLabel"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="lblMessage"> + <property name="text"> + <string>Message:</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnMessage</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="lnMessage"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="lblAmount"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Amount:</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnReqAmount</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="BitcoinAmountField" name="lnReqAmount"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + </widget> </item> </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> <spacer name="horizontalSpacer"> <property name="orientation"> @@ -194,6 +183,13 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>BitcoinAmountField</class> + <extends>QSpinBox</extends> + <header>bitcoinamountfield.h</header> + </customwidget> + </customwidgets> <resources/> <connections> <connection> diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index be0f4ebe96..d1d8ab42a0 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -11,7 +11,7 @@ </rect> </property> <property name="windowTitle"> - <string>Bitcoin debug window</string> + <string>Bitcoin - Debug window</string> </property> <layout class="QVBoxLayout" name="verticalLayout_2"> <item> @@ -36,7 +36,7 @@ </font> </property> <property name="text"> - <string>Client</string> + <string>Bitcoin Core</string> </property> </widget> </item> @@ -87,13 +87,39 @@ </widget> </item> <item row="3" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Using OpenSSL version</string> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="openSSLVersion"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="4" column="0"> <widget class="QLabel" name="label_12"> <property name="text"> <string>Build date</string> </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <widget class="QLabel" name="buildDate"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -109,14 +135,14 @@ </property> </widget> </item> - <item row="4" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="label_13"> <property name="text"> <string>Startup time</string> </property> </widget> </item> - <item row="4" column="1"> + <item row="5" column="1"> <widget class="QLabel" name="startupTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -132,7 +158,7 @@ </property> </widget> </item> - <item row="5" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="label_11"> <property name="font"> <font> @@ -145,14 +171,14 @@ </property> </widget> </item> - <item row="6" column="0"> + <item row="7" column="0"> <widget class="QLabel" name="label_7"> <property name="text"> <string>Number of connections</string> </property> </widget> </item> - <item row="6" column="1"> + <item row="7" column="1"> <widget class="QLabel" name="numberOfConnections"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -168,14 +194,14 @@ </property> </widget> </item> - <item row="7" column="0"> + <item row="8" column="0"> <widget class="QLabel" name="label_8"> <property name="text"> <string>On testnet</string> </property> </widget> </item> - <item row="7" column="1"> + <item row="8" column="1"> <widget class="QCheckBox" name="isTestNet"> <property name="enabled"> <bool>false</bool> @@ -185,7 +211,7 @@ </property> </widget> </item> - <item row="8" column="0"> + <item row="9" column="0"> <widget class="QLabel" name="label_10"> <property name="font"> <font> @@ -198,14 +224,14 @@ </property> </widget> </item> - <item row="9" column="0"> + <item row="10" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Current number of blocks</string> </property> </widget> </item> - <item row="9" column="1"> + <item row="10" column="1"> <widget class="QLabel" name="numberOfBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -221,14 +247,14 @@ </property> </widget> </item> - <item row="10" column="0"> + <item row="11" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>Estimated total blocks</string> </property> </widget> </item> - <item row="10" column="1"> + <item row="11" column="1"> <widget class="QLabel" name="totalBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -244,14 +270,14 @@ </property> </widget> </item> - <item row="11" column="0"> + <item row="12" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> <string>Last block time</string> </property> </widget> </item> - <item row="11" column="1"> + <item row="12" column="1"> <widget class="QLabel" name="lastBlockTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -267,7 +293,7 @@ </property> </widget> </item> - <item row="12" column="0"> + <item row="13" column="0"> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -280,7 +306,7 @@ </property> </spacer> </item> - <item row="13" column="0"> + <item row="14" column="0"> <widget class="QLabel" name="labelDebugLogfile"> <property name="font"> <font> @@ -289,14 +315,14 @@ </font> </property> <property name="text"> - <string>Debug logfile</string> + <string>Debug log file</string> </property> </widget> </item> - <item row="14" column="0"> + <item row="15" column="0"> <widget class="QPushButton" name="openDebugLogfileButton"> <property name="toolTip"> - <string>Open the Bitcoin debug logfile from the current data directory. This can take a few seconds for large logfiles.</string> + <string>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</string> </property> <property name="text"> <string>&Open</string> @@ -306,7 +332,7 @@ </property> </widget> </item> - <item row="15" column="0"> + <item row="16" column="0"> <widget class="QLabel" name="labelCLOptions"> <property name="font"> <font> @@ -319,7 +345,7 @@ </property> </widget> </item> - <item row="16" column="0"> + <item row="17" column="0"> <widget class="QPushButton" name="showCLOptionsButton"> <property name="toolTip"> <string>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</string> @@ -332,7 +358,7 @@ </property> </widget> </item> - <item row="17" column="0"> + <item row="18" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui new file mode 100644 index 0000000000..8128bdf457 --- /dev/null +++ b/src/qt/forms/signverifymessagedialog.ui @@ -0,0 +1,386 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SignVerifyMessageDialog</class> + <widget class="QDialog" name="SignVerifyMessageDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>700</width> + <height>380</height> + </rect> + </property> + <property name="windowTitle"> + <string>Signatures - Sign / Verify a Message</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tabSignMessage"> + <attribute name="title"> + <string>&Sign Message</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_SM"> + <item> + <widget class="QLabel" name="infoLabel_SM"> + <property name="text"> + <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_1_SM"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QValidatedLineEdit" name="addressIn_SM"> + <property name="toolTip"> + <string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string> + </property> + <property name="maxLength"> + <number>34</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addressBookButton_SM"> + <property name="toolTip"> + <string>Choose an address from the address book</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset> + </property> + <property name="shortcut"> + <string>Alt+A</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pasteButton_SM"> + <property name="toolTip"> + <string>Paste address from clipboard</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset> + </property> + <property name="shortcut"> + <string>Alt+P</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPlainTextEdit" name="messageIn_SM"> + <property name="toolTip"> + <string>Enter the message you want to sign here</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2_SM"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLineEdit" name="signatureOut_SM"> + <property name="font"> + <font> + <italic>true</italic> + </font> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="copySignatureButton_SM"> + <property name="toolTip"> + <string>Copy the current signature to the system clipboard</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3_SM"> + <item> + <widget class="QPushButton" name="signMessageButton_SM"> + <property name="toolTip"> + <string>Sign the message to prove you own this Bitcoin address</string> + </property> + <property name="text"> + <string>&Sign Message</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="clearButton_SM"> + <property name="toolTip"> + <string>Reset all sign message fields</string> + </property> + <property name="text"> + <string>Clear &All</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_1_SM"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>48</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="statusLabel_SM"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string/> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2_SM"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>48</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tabVerifyMessage"> + <attribute name="title"> + <string>&Verify Message</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_VM"> + <item> + <widget class="QLabel" name="infoLabel_VM"> + <property name="text"> + <string>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_1_VM"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QValidatedLineEdit" name="addressIn_VM"> + <property name="toolTip"> + <string>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string> + </property> + <property name="maxLength"> + <number>34</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addressBookButton_VM"> + <property name="toolTip"> + <string>Choose an address from the address book</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset> + </property> + <property name="shortcut"> + <string>Alt+A</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPlainTextEdit" name="messageIn_VM"/> + </item> + <item> + <widget class="QValidatedLineEdit" name="signatureIn_VM"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2_VM"> + <item> + <widget class="QPushButton" name="verifyMessageButton_VM"> + <property name="toolTip"> + <string>Verify the message to ensure it was signed with the specified Bitcoin address</string> + </property> + <property name="text"> + <string>&Verify Message</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="clearButton_VM"> + <property name="toolTip"> + <string>Reset all verify message fields</string> + </property> + <property name="text"> + <string>Clear &All</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_1_VM"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>48</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="statusLabel_VM"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string/> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2_VM"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>48</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QValidatedLineEdit</class> + <extends>QLineEdit</extends> + <header>qvalidatedlineedit.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="../bitcoin.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/qt/forms/transactiondescdialog.ui b/src/qt/forms/transactiondescdialog.ui index 039cb082cc..b38dffcc12 100644 --- a/src/qt/forms/transactiondescdialog.ui +++ b/src/qt/forms/transactiondescdialog.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>600</width> + <width>620</width> <height>250</height> </rect> </property> diff --git a/src/qt/forms/verifymessagedialog.ui b/src/qt/forms/verifymessagedialog.ui deleted file mode 100644 index afe98b05ab..0000000000 --- a/src/qt/forms/verifymessagedialog.ui +++ /dev/null @@ -1,140 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>VerifyMessageDialog</class> - <widget class="QDialog" name="VerifyMessageDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>650</width> - <height>380</height> - </rect> - </property> - <property name="windowTitle"> - <string>Verify Signed Message</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Enter the signing address, signature and message below (be careful to correctly copy newlines, spaces, tabs and other invisible characters) to verify the message.</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QValidatedLineEdit" name="lnAddress"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item> - <widget class="QValidatedLineEdit" name="lnSig"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item> - <widget class="QPlainTextEdit" name="edMessage"/> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="verifyMessage"> - <property name="toolTip"> - <string>Verify a message to ensure it was signed with the specified Bitcoin address</string> - </property> - <property name="text"> - <string>&Verify Message</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="clearButton"> - <property name="toolTip"> - <string>Reset all verify message fields</string> - </property> - <property name="text"> - <string>Clear &All</string> - </property> - <property name="icon"> - <iconset resource="../bitcoin.qrc"> - <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="lblStatus"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>48</height> - </size> - </property> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string/> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>QValidatedLineEdit</class> - <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> - </customwidget> - </customwidgets> - <resources> - <include location="../bitcoin.qrc"/> - </resources> - <connections/> -</ui> diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 54e9d644fe..405ba396b7 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -4,10 +4,10 @@ /* Milliseconds between model updates */ static const int MODEL_UPDATE_DELAY = 500; -/* Maximum passphrase length */ +/* AskPassphraseDialog -- Maximum passphrase length */ static const int MAX_PASSPHRASE_SIZE = 1024; -/* Size of icons in status bar */ +/* BitcoinGUI -- Size of icons in status bar */ static const int STATUSBAR_ICONSIZE = 16; /* Invalid field background style */ @@ -25,4 +25,10 @@ static const int STATUSBAR_ICONSIZE = 16; */ static const int TOOLTIP_WRAP_THRESHOLD = 80; +/* Maximum allowed URI length */ +static const int MAX_URI_LENGTH = 255; + +/* QRCodeDialog -- size of exported QR Code image */ +#define EXPORT_IMAGE_SIZE 256 + #endif // GUICONSTANTS_H diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 50ed2eed04..e6af9c3608 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -412,7 +412,7 @@ bool SetStartOnSystemStartup(bool fAutoStart) #else // TODO: OSX startup stuff; see: -// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html +// https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html bool GetStartOnSystemStartup() { return false; } bool SetStartOnSystemStartup(bool fAutoStart) { return false; } diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 0240695505..a6d11081d6 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -30,7 +30,7 @@ namespace GUIUtil void setupAddressWidget(QLineEdit *widget, QWidget *parent); void setupAmountWidget(QLineEdit *widget, QWidget *parent); - // Parse "bitcoin:" URI into recipient object, return true on succesful parsing + // Parse "bitcoin:" URI into recipient object, return true on successful parsing // See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0 bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index 9006870b9f..d9dc925973 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -264,7 +264,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Паролата за портфейла беше променена успешно.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index deb7ea9040..a44eca9159 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -263,7 +263,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"/> </message> </context> diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index 528e17ae99..1a3b99ebbd 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -270,7 +270,7 @@ Jsi si jistý, že chceš peněženku zašifrovat?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Heslo k peněžence bylo v pořádku změněno.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 66166a74c4..70a5e2f9e7 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -264,7 +264,7 @@ Er du sikker på at du ønsker at kryptere din tegnebog?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Tegnebogskodeord blev ændret.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 2b9aaf3296..5b96fbe299 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -269,7 +269,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Die Passphrase der Brieftasche wurde erfolgreich geändert.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index 2058e1a123..63d7bd26a8 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Ο κωδικος του πορτοφολιού άλλαξε με επιτυχία.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index afa30caf87..c6baca2dd9 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -5,22 +5,22 @@ <context> <name>AboutDialog</name> <message> - <location filename="../forms/aboutdialog.ui" line="14"/> + <location filename="../forms/aboutdialog.ui" line="+14"/> <source>About Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/aboutdialog.ui" line="53"/> + <location line="+39"/> <source><b>Bitcoin</b> version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/aboutdialog.ui" line="97"/> + <location line="+44"/> <source>Copyright © 2009-2012 Bitcoin Developers This is experimental software. -Distributed under the MIT/X11 software license, see the accompanying file license.txt or http://www.opensource.org/licenses/mit-license.php. +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</source> <translation type="unfinished"></translation> @@ -29,92 +29,102 @@ This product includes software developed by the OpenSSL Project for use in the O <context> <name>AddressBookPage</name> <message> - <location filename="../forms/addressbookpage.ui" line="14"/> + <location filename="../forms/addressbookpage.ui" line="+14"/> <source>Address Book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="20"/> - <source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/addressbookpage.ui" line="36"/> + <location line="+22"/> <source>Double-click to edit address or label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="63"/> + <location line="+27"/> <source>Create a new address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="77"/> + <location line="+14"/> <source>Copy the currently selected address to the system clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="66"/> + <location line="-11"/> <source>&New Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="80"/> + <location line="-46"/> + <source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+60"/> <source>&Copy Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="91"/> + <location line="+11"/> <source>Show &QR Code</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="102"/> - <source>Sign a message to prove you own this address</source> + <location line="+11"/> + <source>Sign a message to prove you own a Bitcoin address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="105"/> + <location line="+3"/> <source>&Sign Message</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="116"/> + <location line="+11"/> + <source>Verify a message to ensure it was signed with a specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>&Verify Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+11"/> <source>Delete the currently selected address from the list. Only sending addresses can be deleted.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="119"/> + <location line="+3"/> <source>&Delete</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="63"/> + <location filename="../addressbookpage.cpp" line="+65"/> <source>Copy &Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="65"/> + <location line="+2"/> <source>&Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="287"/> + <location line="+250"/> <source>Export Address Book Data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="288"/> + <location line="+1"/> <source>Comma separated file (*.csv)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="301"/> + <location line="+13"/> <source>Error exporting</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="301"/> + <location line="+0"/> <source>Could not write to file %1.</source> <translation type="unfinished"></translation> </message> @@ -122,17 +132,17 @@ This product includes software developed by the OpenSSL Project for use in the O <context> <name>AddressTableModel</name> <message> - <location filename="../addresstablemodel.cpp" line="142"/> + <location filename="../addresstablemodel.cpp" line="+142"/> <source>Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addresstablemodel.cpp" line="142"/> + <location line="+0"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addresstablemodel.cpp" line="178"/> + <location line="+36"/> <source>(no label)</source> <translation type="unfinished"></translation> </message> @@ -140,259 +150,244 @@ This product includes software developed by the OpenSSL Project for use in the O <context> <name>AskPassphraseDialog</name> <message> - <location filename="../forms/askpassphrasedialog.ui" line="26"/> + <location filename="../forms/askpassphrasedialog.ui" line="+26"/> <source>Passphrase Dialog</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="47"/> + <location line="+21"/> <source>Enter passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="61"/> + <location line="+14"/> <source>New passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="75"/> + <location line="+14"/> <source>Repeat new passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="33"/> + <location filename="../askpassphrasedialog.cpp" line="+33"/> <source>Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="34"/> + <location line="+1"/> <source>Encrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="37"/> + <location line="+3"/> <source>This operation needs your wallet passphrase to unlock the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="42"/> + <location line="+5"/> <source>Unlock wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="45"/> + <location line="+3"/> <source>This operation needs your wallet passphrase to decrypt the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="50"/> + <location line="+5"/> <source>Decrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="53"/> + <location line="+3"/> <source>Change passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="54"/> + <location line="+1"/> <source>Enter the old and new passphrase to the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="100"/> + <location line="+46"/> <source>Confirm wallet encryption</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="101"/> + <location line="+1"/> <source>WARNING: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! Are you sure you wish to encrypt your wallet?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="110"/> - <location filename="../askpassphrasedialog.cpp" line="159"/> + <location line="+9"/> + <location line="+49"/> <source>Wallet encrypted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="111"/> + <location line="-48"/> <source>Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="207"/> - <location filename="../askpassphrasedialog.cpp" line="231"/> + <location line="+96"/> + <location line="+24"/> <source>Warning: The Caps Lock key is on.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="116"/> - <location filename="../askpassphrasedialog.cpp" line="123"/> - <location filename="../askpassphrasedialog.cpp" line="165"/> - <location filename="../askpassphrasedialog.cpp" line="171"/> + <location line="-115"/> + <location line="+7"/> + <location line="+42"/> + <location line="+6"/> <source>Wallet encryption failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="117"/> + <location line="-54"/> <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="124"/> - <location filename="../askpassphrasedialog.cpp" line="172"/> + <location line="+7"/> + <location line="+48"/> <source>The supplied passphrases do not match.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="135"/> + <location line="-37"/> <source>Wallet unlock failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="136"/> - <location filename="../askpassphrasedialog.cpp" line="147"/> - <location filename="../askpassphrasedialog.cpp" line="166"/> + <location line="+1"/> + <location line="+11"/> + <location line="+19"/> <source>The passphrase entered for the wallet decryption was incorrect.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="146"/> + <location line="-20"/> <source>Wallet decryption failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <location line="+14"/> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"></translation> </message> </context> <context> <name>BitcoinGUI</name> <message> - <location filename="../bitcoingui.cpp" line="73"/> - <source>Bitcoin Wallet</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoingui.cpp" line="215"/> + <location filename="../bitcoingui.cpp" line="+218"/> <source>Sign &message...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="248"/> + <location line="+48"/> <source>Show/Hide &Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="515"/> + <location line="+247"/> <source>Synchronizing with network...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="185"/> + <location line="-325"/> <source>&Overview</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="186"/> + <location line="+1"/> <source>Show general overview of wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="191"/> + <location line="+5"/> <source>&Transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="192"/> + <location line="+1"/> <source>Browse transaction history</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="197"/> + <location line="+5"/> <source>&Address Book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="198"/> + <location line="+1"/> <source>Edit the list of stored addresses and labels</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="203"/> + <location line="+5"/> <source>&Receive coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="204"/> + <location line="+1"/> <source>Show the list of addresses for receiving payments</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="209"/> + <location line="+5"/> <source>&Send coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="216"/> - <source>Prove you control an address</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoingui.cpp" line="235"/> + <location line="+41"/> <source>E&xit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="236"/> + <location line="+1"/> <source>Quit application</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="239"/> - <source>&About %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoingui.cpp" line="240"/> + <location line="+4"/> <source>Show information about Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="242"/> + <location line="+2"/> <source>About &Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="243"/> + <location line="+1"/> <source>Show information about Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="245"/> + <location line="+2"/> <source>&Options...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="252"/> + <location line="+7"/> <source>&Encrypt Wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="255"/> + <location line="+3"/> <source>&Backup Wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="257"/> + <location line="+2"/> <source>&Change Passphrase...</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="517"/> + <location line="+240"/> <source>~%n block(s) remaining</source> <translation> <numerusform>~%n block remaining</numerusform> @@ -400,109 +395,134 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="528"/> + <location line="+11"/> <source>Downloaded %1 of %2 blocks of transaction history (%3% done).</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="250"/> + <location line="-258"/> <source>&Export...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="210"/> + <location line="-55"/> <source>Send coins to a Bitcoin address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="246"/> + <location line="+6"/> + <source>Sign a message to prove you own a Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+4"/> + <source>Verify a message to ensure it was signed with a specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+4"/> + <source>S&ignatures</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+37"/> <source>Modify configuration options for Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="249"/> + <location line="+3"/> <source>Show or hide the Bitcoin window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="251"/> + <location line="+2"/> <source>Export the data in the current tab to a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="253"/> + <location line="+2"/> <source>Encrypt or decrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="256"/> + <location line="+3"/> <source>Backup wallet to another location</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="258"/> + <location line="+2"/> <source>Change the passphrase used for wallet encryption</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="259"/> + <location line="+1"/> <source>&Debug window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="260"/> + <location line="+1"/> <source>Open debugging and diagnostic console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="261"/> + <location line="-56"/> <source>&Verify message...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="262"/> - <source>Verify a message signature</source> + <location line="-151"/> + <source>Bitcoin</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+0"/> + <source>Wallet</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+186"/> + <source>&About Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="286"/> + <location line="+44"/> <source>&File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="296"/> + <location line="+10"/> <source>&Settings</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="302"/> + <location line="+6"/> <source>&Help</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="311"/> + <location line="+9"/> <source>Tabs toolbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="322"/> + <location line="+11"/> <source>Actions toolbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="334"/> - <location filename="../bitcoingui.cpp" line="343"/> + <location line="+13"/> + <location line="+9"/> <source>[testnet]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="343"/> - <location filename="../bitcoingui.cpp" line="399"/> + <location line="+0"/> + <location line="+60"/> <source>Bitcoin client</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="492"/> + <location line="+71"/> <source>%n active connection(s) to Bitcoin network</source> <translation> <numerusform>%n active connection to Bitcoin network</numerusform> @@ -510,12 +530,12 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="540"/> + <location line="+48"/> <source>Downloaded %1 blocks of transaction history.</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="555"/> + <location line="+15"/> <source>%n second(s) ago</source> <translation> <numerusform>%n second ago</numerusform> @@ -523,7 +543,7 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="559"/> + <location line="+4"/> <source>%n minute(s) ago</source> <translation> <numerusform>%n minute ago</numerusform> @@ -531,7 +551,7 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="563"/> + <location line="+4"/> <source>%n hour(s) ago</source> <translation> <numerusform>%n hour ago</numerusform> @@ -539,7 +559,7 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="567"/> + <location line="+4"/> <source>%n day(s) ago</source> <translation> <numerusform>%n day ago</numerusform> @@ -547,42 +567,42 @@ Are you sure you wish to encrypt your wallet?</source> </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="573"/> + <location line="+6"/> <source>Up to date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="580"/> + <location line="+7"/> <source>Catching up...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="590"/> + <location line="+10"/> <source>Last received block was generated %1.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="649"/> + <location line="+59"/> <source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="654"/> + <location line="+5"/> <source>Confirm transaction fee</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="681"/> + <location line="+27"/> <source>Sent transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="682"/> + <location line="+1"/> <source>Incoming transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="683"/> + <location line="+1"/> <source>Date: %1 Amount: %2 Type: %3 @@ -591,45 +611,57 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="804"/> + <location line="+120"/> + <location line="+15"/> + <source>URI handling</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-15"/> + <location line="+15"/> + <source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+16"/> <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="812"/> + <location line="+8"/> <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="835"/> + <location line="+23"/> <source>Backup Wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="835"/> + <location line="+0"/> <source>Wallet Data (*.dat)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="838"/> + <location line="+3"/> <source>Backup Failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="838"/> + <location line="+0"/> <source>There was an error trying to save the wallet data to the new location.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoin.cpp" line="112"/> - <source>A fatal error occured. Bitcoin can no longer continue safely and will quit.</source> + <location filename="../bitcoin.cpp" line="+112"/> + <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source> <translation type="unfinished"></translation> </message> </context> <context> <name>ClientModel</name> <message> - <location filename="../clientmodel.cpp" line="84"/> + <location filename="../clientmodel.cpp" line="+84"/> <source>Network Alert</source> <translation type="unfinished"></translation> </message> @@ -637,67 +669,67 @@ Address: %4 <context> <name>EditAddressDialog</name> <message> - <location filename="../forms/editaddressdialog.ui" line="14"/> + <location filename="../forms/editaddressdialog.ui" line="+14"/> <source>Edit Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="25"/> + <location line="+11"/> <source>&Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="35"/> + <location line="+10"/> <source>The label associated with this address book entry</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="42"/> + <location line="+7"/> <source>&Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="52"/> + <location line="+10"/> <source>The address associated with this address book entry. This can only be modified for sending addresses.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="20"/> + <location filename="../editaddressdialog.cpp" line="+20"/> <source>New receiving address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="24"/> + <location line="+4"/> <source>New sending address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="27"/> + <location line="+3"/> <source>Edit receiving address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="31"/> + <location line="+4"/> <source>Edit sending address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="91"/> + <location line="+60"/> <source>The entered address "%1" is already in the address book.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="96"/> + <location line="+5"/> <source>The entered address "%1" is not a valid Bitcoin address.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="101"/> + <location line="+5"/> <source>Could not unlock wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="106"/> + <location line="+5"/> <source>New key generation failed.</source> <translation type="unfinished"></translation> </message> @@ -705,349 +737,238 @@ Address: %4 <context> <name>GUIUtil::HelpMessageBox</name> <message> - <location filename="../guiutil.cpp" line="420"/> - <location filename="../guiutil.cpp" line="432"/> + <location filename="../guiutil.cpp" line="+425"/> + <location line="+12"/> <source>Bitcoin-Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="420"/> + <location line="-12"/> <source>version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="422"/> + <location line="+2"/> <source>Usage:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="423"/> + <location line="+1"/> <source>command-line options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="427"/> + <location line="+4"/> <source>UI options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="428"/> + <location line="+1"/> <source>Set language, for example "de_DE" (default: system locale)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="429"/> + <location line="+1"/> <source>Start minimized</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="430"/> + <location line="+1"/> <source>Show splash screen on startup (default: 1)</source> <translation type="unfinished"></translation> </message> </context> <context> - <name>MessagePage</name> - <message> - <location filename="../forms/messagepage.ui" line="14"/> - <source>Sign Message</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="20"/> - <source>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="38"/> - <source>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="48"/> - <source>Choose adress from address book</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="58"/> - <source>Alt+A</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="71"/> - <source>Paste address from clipboard</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="81"/> - <source>Alt+P</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="93"/> - <source>Enter the message you want to sign here</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="128"/> - <source>Copy the current signature to the system clipboard</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="131"/> - <source>&Copy Signature</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="142"/> - <source>Reset all sign message fields</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="145"/> - <source>Clear &All</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="31"/> - <source>Click "Sign Message" to get signature</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="114"/> - <source>Sign a message to prove you own this address</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/messagepage.ui" line="117"/> - <source>&Sign Message</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="30"/> - <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="83"/> - <location filename="../messagepage.cpp" line="90"/> - <location filename="../messagepage.cpp" line="105"/> - <location filename="../messagepage.cpp" line="117"/> - <source>Error signing</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="83"/> - <source>%1 is not a valid address.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="90"/> - <source>%1 does not refer to a key.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="105"/> - <source>Private key for %1 is not available.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../messagepage.cpp" line="117"/> - <source>Sign failed</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>OptionsDialog</name> <message> - <location filename="../forms/optionsdialog.ui" line="14"/> + <location filename="../forms/optionsdialog.ui" line="+14"/> <source>Options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="30"/> + <location line="+16"/> <source>&Main</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="36"/> + <location line="+6"/> <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="51"/> + <location line="+15"/> <source>Pay transaction &fee</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="82"/> + <location line="+31"/> <source>Automatically start Bitcoin after logging in to the system.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="85"/> + <location line="+3"/> <source>&Start Bitcoin on system login</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="92"/> + <location line="+7"/> <source>Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="95"/> + <location line="+3"/> <source>&Detach databases at shutdown</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="116"/> + <location line="+21"/> <source>&Network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="122"/> + <location line="+6"/> <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="125"/> + <location line="+3"/> <source>Map port using &UPnP</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="132"/> - <source>Connect to the Bitcon network through a SOCKS proxy (e.g. when connecting through Tor).</source> + <location line="+7"/> + <source>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="135"/> + <location line="+3"/> <source>&Connect through SOCKS proxy:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="144"/> + <location line="+9"/> <source>Proxy &IP:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="163"/> + <location line="+19"/> <source>IP address of the proxy (e.g. 127.0.0.1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="170"/> + <location line="+7"/> <source>&Port:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="189"/> + <location line="+19"/> <source>Port of the proxy (e.g. 9050)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="196"/> + <location line="+7"/> <source>SOCKS &Version:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="209"/> + <location line="+13"/> <source>SOCKS version of the proxy (e.g. 5)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="245"/> + <location line="+36"/> <source>&Window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="251"/> + <location line="+6"/> <source>Show only a tray icon after minimizing the window.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="254"/> + <location line="+3"/> <source>&Minimize to the tray instead of the taskbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="261"/> + <location line="+7"/> <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="264"/> + <location line="+3"/> <source>M&inimize on close</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="285"/> + <location line="+21"/> <source>&Display</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="293"/> + <location line="+8"/> <source>User Interface &language:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="306"/> + <location line="+13"/> <source>The user interface language can be set here. This setting will take effect after restarting Bitcoin.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="317"/> + <location line="+11"/> <source>&Unit to show amounts in:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="330"/> + <location line="+13"/> <source>Choose the default subdivision unit to show in the interface and when sending coins.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="339"/> + <location line="+9"/> <source>Whether to show Bitcoin addresses in the transaction list or not.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="342"/> + <location line="+3"/> <source>&Display addresses in transaction list</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="413"/> + <location line="+71"/> <source>&OK</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="420"/> + <location line="+7"/> <source>&Cancel</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="430"/> + <location line="+10"/> <source>&Apply</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="62"/> + <location filename="../optionsdialog.cpp" line="+63"/> <source>default</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="173"/> - <location filename="../optionsdialog.cpp" line="182"/> + <location line="+133"/> + <location line="+9"/> <source>Warning</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="173"/> - <location filename="../optionsdialog.cpp" line="182"/> + <location line="-9"/> + <location line="+9"/> <source>This setting will take effect after restarting Bitcoin.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="207"/> + <location line="+25"/> <source>The supplied proxy address is invalid.</source> <translation type="unfinished"></translation> </message> @@ -1055,69 +976,69 @@ Address: %4 <context> <name>OverviewPage</name> <message> - <location filename="../forms/overviewpage.ui" line="14"/> + <location filename="../forms/overviewpage.ui" line="+14"/> <source>Form</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="47"/> - <location filename="../forms/overviewpage.ui" line="230"/> + <location line="+33"/> + <location line="+183"/> <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="89"/> + <location line="-141"/> <source>Balance:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="147"/> + <location line="+58"/> <source>Number of transactions:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="118"/> + <location line="-29"/> <source>Unconfirmed:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="40"/> + <location line="-78"/> <source>Wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="164"/> + <location line="+124"/> <source>Immature:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="177"/> + <location line="+13"/> <source>Mined balance that has not yet matured</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="223"/> + <location line="+46"/> <source><b>Recent transactions</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="105"/> + <location line="-118"/> <source>Your current balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="134"/> + <location line="+29"/> <source>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="154"/> + <location line="+20"/> <source>Total number of transactions in wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../overviewpage.cpp" line="112"/> - <location filename="../overviewpage.cpp" line="113"/> + <location filename="../overviewpage.cpp" line="+112"/> + <location line="+1"/> <source>out of sync</source> <translation type="unfinished"></translation> </message> @@ -1125,62 +1046,57 @@ Address: %4 <context> <name>QRCodeDialog</name> <message> - <location filename="../forms/qrcodedialog.ui" line="14"/> + <location filename="../forms/qrcodedialog.ui" line="+14"/> <source>QR Code Dialog</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="32"/> - <source>QR Code</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/qrcodedialog.ui" line="55"/> + <location line="+59"/> <source>Request Payment</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="70"/> + <location line="+56"/> <source>Amount:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="105"/> - <source>BTC</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/qrcodedialog.ui" line="121"/> + <location line="-44"/> <source>Label:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="144"/> + <location line="+19"/> <source>Message:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="186"/> + <location line="+71"/> <source>&Save As...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="45"/> + <location filename="../qrcodedialog.cpp" line="+62"/> <source>Error encoding URI into QR Code.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="63"/> + <location line="+40"/> + <source>The entered amount is invalid, please check.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+23"/> <source>Resulting URI too long, try to reduce the text for label / message.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="120"/> + <location line="+25"/> <source>Save QR Code</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="120"/> + <location line="+0"/> <source>PNG Images (*.png)</source> <translation type="unfinished"></translation> </message> @@ -1188,140 +1104,146 @@ Address: %4 <context> <name>RPCConsole</name> <message> - <location filename="../forms/rpcconsole.ui" line="14"/> - <source>Bitcoin debug window</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/rpcconsole.ui" line="46"/> + <location filename="../forms/rpcconsole.ui" line="+46"/> <source>Client name</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="56"/> - <location filename="../forms/rpcconsole.ui" line="79"/> - <location filename="../forms/rpcconsole.ui" line="102"/> - <location filename="../forms/rpcconsole.ui" line="125"/> - <location filename="../forms/rpcconsole.ui" line="161"/> - <location filename="../forms/rpcconsole.ui" line="214"/> - <location filename="../forms/rpcconsole.ui" line="237"/> - <location filename="../forms/rpcconsole.ui" line="260"/> - <location filename="../rpcconsole.cpp" line="242"/> + <location line="+10"/> + <location line="+23"/> + <location line="+26"/> + <location line="+23"/> + <location line="+23"/> + <location line="+36"/> + <location line="+53"/> + <location line="+23"/> + <location line="+23"/> + <location filename="../rpcconsole.cpp" line="+246"/> <source>N/A</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="69"/> + <location line="-217"/> <source>Client version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="24"/> + <location line="-45"/> <source>&Information</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="39"/> - <source>Client</source> + <location line="+68"/> + <source>Using OpenSSL version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="115"/> + <location line="+49"/> <source>Startup time</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="144"/> + <location line="+29"/> <source>Network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="151"/> + <location line="+7"/> <source>Number of connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="174"/> + <location line="+23"/> <source>On testnet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="197"/> + <location line="+23"/> <source>Block chain</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="204"/> + <location line="+7"/> <source>Current number of blocks</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="227"/> + <location line="+23"/> <source>Estimated total blocks</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="250"/> + <location line="+23"/> <source>Last block time</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="292"/> - <source>Debug logfile</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/rpcconsole.ui" line="299"/> - <source>Open the Bitcoin debug logfile from the current data directory. This can take a few seconds for large logfiles.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/rpcconsole.ui" line="302"/> + <location line="+52"/> <source>&Open</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="318"/> + <location line="+16"/> <source>Command-line options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="325"/> + <location line="+7"/> <source>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="328"/> + <location line="+3"/> <source>&Show</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="352"/> + <location line="+24"/> <source>&Console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="92"/> + <location line="-260"/> <source>Build date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="401"/> + <location line="-104"/> + <source>Bitcoin - Debug window</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+25"/> + <source>Bitcoin Core</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+279"/> + <source>Debug log file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+102"/> <source>Clear console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="209"/> + <location filename="../rpcconsole.cpp" line="-33"/> <source>Welcome to the Bitcoin RPC console.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="210"/> + <location line="+1"/> <source>Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="211"/> + <location line="+1"/> <source>Type <b>help</b> for an overview of available commands.</source> <translation type="unfinished"></translation> </message> @@ -1329,109 +1251,109 @@ Address: %4 <context> <name>SendCoinsDialog</name> <message> - <location filename="../forms/sendcoinsdialog.ui" line="14"/> - <location filename="../sendcoinsdialog.cpp" line="122"/> - <location filename="../sendcoinsdialog.cpp" line="127"/> - <location filename="../sendcoinsdialog.cpp" line="132"/> - <location filename="../sendcoinsdialog.cpp" line="137"/> - <location filename="../sendcoinsdialog.cpp" line="143"/> - <location filename="../sendcoinsdialog.cpp" line="148"/> - <location filename="../sendcoinsdialog.cpp" line="153"/> + <location filename="../forms/sendcoinsdialog.ui" line="+14"/> + <location filename="../sendcoinsdialog.cpp" line="+123"/> + <location line="+5"/> + <location line="+5"/> + <location line="+5"/> + <location line="+6"/> + <location line="+5"/> + <location line="+5"/> <source>Send Coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="64"/> + <location line="+50"/> <source>Send to multiple recipients at once</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="67"/> + <location line="+3"/> <source>&Add Recipient</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="84"/> + <location line="+20"/> <source>Remove all transaction fields</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="87"/> + <location line="+3"/> <source>Clear &All</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="106"/> + <location line="+22"/> <source>Balance:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="113"/> + <location line="+10"/> <source>123.456 BTC</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="144"/> + <location line="+31"/> <source>Confirm the send action</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="147"/> + <location line="+3"/> <source>&Send</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="94"/> + <location filename="../sendcoinsdialog.cpp" line="-59"/> <source><b>%1</b> to %2 (%3)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="99"/> + <location line="+5"/> <source>Confirm send coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="100"/> + <location line="+1"/> <source>Are you sure you want to send %1?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="100"/> + <location line="+0"/> <source> and </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="123"/> - <source>The recepient address is not valid, please recheck.</source> + <location line="+23"/> + <source>The recipient address is not valid, please recheck.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="128"/> + <location line="+5"/> <source>The amount to pay must be larger than 0.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="133"/> + <location line="+5"/> <source>The amount exceeds your balance.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="138"/> + <location line="+5"/> <source>The total exceeds your balance when the %1 transaction fee is included.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="144"/> + <location line="+6"/> <source>Duplicate address found, can only send to each address once per send operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="149"/> + <location line="+5"/> <source>Error: Transaction creation failed.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="154"/> + <location line="+5"/> <source>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source> <translation type="unfinished"></translation> </message> @@ -1439,217 +1361,439 @@ Address: %4 <context> <name>SendCoinsEntry</name> <message> - <location filename="../forms/sendcoinsentry.ui" line="14"/> + <location filename="../forms/sendcoinsentry.ui" line="+14"/> <source>Form</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="29"/> + <location line="+15"/> <source>A&mount:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="42"/> + <location line="+13"/> <source>Pay &To:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="66"/> - <location filename="../sendcoinsentry.cpp" line="25"/> + <location line="+24"/> + <location filename="../sendcoinsentry.cpp" line="+25"/> <source>Enter a label for this address to add it to your address book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="75"/> + <location line="+9"/> <source>&Label:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="93"/> + <location line="+18"/> <source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="103"/> + <location line="+10"/> <source>Choose address from address book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="113"/> + <location line="+10"/> <source>Alt+A</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="120"/> + <location line="+7"/> <source>Paste address from clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="130"/> + <location line="+10"/> <source>Alt+P</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="137"/> + <location line="+7"/> <source>Remove this recipient</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsentry.cpp" line="26"/> + <location filename="../sendcoinsentry.cpp" line="+1"/> <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> <translation type="unfinished"></translation> </message> </context> <context> - <name>TransactionDesc</name> + <name>SignVerifyMessageDialog</name> + <message> + <location filename="../forms/signverifymessagedialog.ui" line="+14"/> + <source>Signatures - Sign / Verify a Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+13"/> + <location line="+124"/> + <source>&Sign Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-118"/> + <source>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+18"/> + <source>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+10"/> + <location line="+203"/> + <source>Choose an address from the address book</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-193"/> + <location line="+203"/> + <source>Alt+A</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-193"/> + <source>Paste address from clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+10"/> + <source>Alt+P</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+12"/> + <source>Enter the message you want to sign here</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+24"/> + <source>Copy the current signature to the system clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+21"/> + <source>Sign the message to prove you own this Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+17"/> + <source>Reset all sign message fields</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <location line="+146"/> + <source>Clear &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-87"/> + <location line="+70"/> + <source>&Verify Message</source> + <translation type="unfinished"></translation> + </message> <message> - <location filename="../transactiondesc.cpp" line="21"/> - <source>Open for %1 blocks</source> + <location line="-64"/> + <source>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="23"/> + <location line="+21"/> + <source>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+40"/> + <source>Verify the message to ensure it was signed with the specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+17"/> + <source>Reset all verify message fields</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../signverifymessagedialog.cpp" line="+27"/> + <location line="+3"/> + <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-2"/> + <source>Click "Sign Message" to generate signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Enter Bitcoin signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+82"/> + <location line="+81"/> + <source>The entered address is invalid.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-81"/> + <location line="+8"/> + <location line="+73"/> + <location line="+8"/> + <source>Please check the address and try again.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-81"/> + <location line="+81"/> + <source>The entered address does not refer to a key.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-73"/> + <source>Wallet unlock was canceled.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+8"/> + <source>Private key for the entered address is not available.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+12"/> + <source>Message signing failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> + <source>Message signed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+59"/> + <source>The signature could not be decoded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+0"/> + <location line="+13"/> + <source>Please check the signature and try again.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+0"/> + <source>The signature did not match the message digest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>Message verification failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> + <source>Message verified.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>TransactionDesc</name> + <message> + <location filename="../transactiondesc.cpp" line="+19"/> <source>Open until %1</source> <translation type="unfinished"></translation> </message> + <message numerus="yes"> + <location line="-2"/> + <source>Open for %n block(s)</source> + <translation type="unfinished"> + <numerusform>Open for %n block</numerusform> + <numerusform>Open for %n blocks</numerusform> + </translation> + </message> <message> - <location filename="../transactiondesc.cpp" line="29"/> - <source>%1/offline?</source> + <location line="+8"/> + <source>%1/offline</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="31"/> + <location line="+2"/> <source>%1/unconfirmed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="33"/> + <location line="+2"/> <source>%1 confirmations</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="51"/> - <source><b>Status:</b> </source> + <location line="+18"/> + <source>Status</source> <translation type="unfinished"></translation> </message> + <message numerus="yes"> + <location line="+7"/> + <source>, broadcast through %n node(s)</source> + <translation> + <numerusform>, broadcast through %n node</numerusform> + <numerusform>, broadcast through %n nodes</numerusform> + </translation> + </message> <message> - <location filename="../transactiondesc.cpp" line="56"/> - <source>, has not been successfully broadcast yet</source> + <location line="+4"/> + <source>Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="58"/> - <source>, broadcast through %1 node</source> + <location line="+7"/> + <source>Source</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="60"/> - <source>, broadcast through %1 nodes</source> + <location line="+0"/> + <source>Generated</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="64"/> - <source><b>Date:</b> </source> + <location line="+6"/> + <location line="+17"/> + <source>From</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="71"/> - <source><b>Source:</b> Generated<br></source> + <location line="+1"/> + <location line="+22"/> + <location line="+58"/> + <source>To</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="77"/> - <location filename="../transactiondesc.cpp" line="94"/> - <source><b>From:</b> </source> + <location line="-77"/> + <location line="+2"/> + <source>own address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="94"/> - <source>unknown</source> + <location line="-2"/> + <source>label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="95"/> - <location filename="../transactiondesc.cpp" line="118"/> - <location filename="../transactiondesc.cpp" line="178"/> - <source><b>To:</b> </source> + <location line="+37"/> + <location line="+12"/> + <location line="+45"/> + <location line="+17"/> + <location line="+30"/> + <source>Credit</source> <translation type="unfinished"></translation> </message> + <message numerus="yes"> + <location line="-102"/> + <source>matures in %n more block(s)</source> + <translation> + <numerusform>matures in %n more block</numerusform> + <numerusform>matures in %n more blocks</numerusform> + </translation> + </message> <message> - <location filename="../transactiondesc.cpp" line="98"/> - <source> (yours, label: </source> + <location line="+2"/> + <source>not accepted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="100"/> - <source> (yours)</source> + <location line="+44"/> + <location line="+8"/> + <location line="+15"/> + <location line="+30"/> + <source>Debit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="136"/> - <location filename="../transactiondesc.cpp" line="150"/> - <location filename="../transactiondesc.cpp" line="195"/> - <location filename="../transactiondesc.cpp" line="212"/> - <source><b>Credit:</b> </source> + <location line="-39"/> + <source>Transaction fee</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="138"/> - <source>(%1 matures in %2 more blocks)</source> + <location line="+16"/> + <source>Net amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="142"/> - <source>(not accepted)</source> + <location line="+6"/> + <source>Message</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="186"/> - <location filename="../transactiondesc.cpp" line="194"/> - <location filename="../transactiondesc.cpp" line="209"/> - <source><b>Debit:</b> </source> + <location line="+2"/> + <source>Comment</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="200"/> - <source><b>Transaction fee:</b> </source> + <location line="+2"/> + <source>Transaction ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="216"/> - <source><b>Net amount:</b> </source> + <location line="+3"/> + <source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="222"/> - <source>Message:</source> + <location line="+7"/> + <source>Debug information</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+8"/> + <source>Transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="224"/> - <source>Comment:</source> + <location line="+5"/> + <source>Inputs</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="226"/> - <source>Transaction ID:</source> + <location line="+23"/> + <source>Amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="229"/> - <source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, it's state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source> + <location line="+1"/> + <source>true</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+0"/> + <source>false</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-212"/> + <source>, has not been successfully broadcast yet</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+36"/> + <source>unknown</source> <translation type="unfinished"></translation> </message> </context> <context> <name>TransactionDescDialog</name> <message> - <location filename="../forms/transactiondescdialog.ui" line="14"/> + <location filename="../forms/transactiondescdialog.ui" line="+14"/> <source>Transaction details</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/transactiondescdialog.ui" line="20"/> + <location line="+6"/> <source>This pane shows a detailed description of the transaction</source> <translation type="unfinished"></translation> </message> @@ -1657,27 +1801,27 @@ Address: %4 <context> <name>TransactionTableModel</name> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> + <location filename="../transactiontablemodel.cpp" line="+226"/> <source>Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> + <location line="+0"/> <source>Type</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> + <location line="+0"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> + <location line="+0"/> <source>Amount</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../transactiontablemodel.cpp" line="281"/> + <location line="+57"/> <source>Open for %n block(s)</source> <translation> <numerusform>Open for %n block</numerusform> @@ -1685,95 +1829,95 @@ Address: %4 </translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="284"/> + <location line="+3"/> <source>Open until %1</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="287"/> + <location line="+3"/> <source>Offline (%1 confirmations)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="290"/> + <location line="+3"/> <source>Unconfirmed (%1 of %2 confirmations)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="293"/> + <location line="+3"/> <source>Confirmed (%1 confirmations)</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../transactiontablemodel.cpp" line="301"/> + <location line="+8"/> <source>Mined balance will be available when it matures in %n more block(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> + <translation> + <numerusform>Mined balance will be available when it matures in %n more block</numerusform> + <numerusform>Mined balance will be available when it matures in %n more blocks</numerusform> </translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="306"/> + <location line="+5"/> <source>This block was not received by any other nodes and will probably not be accepted!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="309"/> + <location line="+3"/> <source>Generated but not accepted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="352"/> + <location line="+43"/> <source>Received with</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="354"/> + <location line="+2"/> <source>Received from</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="357"/> + <location line="+3"/> <source>Sent to</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="359"/> + <location line="+2"/> <source>Payment to yourself</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="361"/> + <location line="+2"/> <source>Mined</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="399"/> + <location line="+38"/> <source>(n/a)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="598"/> + <location line="+199"/> <source>Transaction status. Hover over this field to show number of confirmations.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="600"/> + <location line="+2"/> <source>Date and time that the transaction was received.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="602"/> + <location line="+2"/> <source>Type of transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="604"/> + <location line="+2"/> <source>Destination address of transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="606"/> + <location line="+2"/> <source>Amount removed from or added to balance.</source> <translation type="unfinished"></translation> </message> @@ -1781,256 +1925,171 @@ Address: %4 <context> <name>TransactionView</name> <message> - <location filename="../transactionview.cpp" line="55"/> - <location filename="../transactionview.cpp" line="71"/> + <location filename="../transactionview.cpp" line="+55"/> + <location line="+16"/> <source>All</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="56"/> + <location line="-15"/> <source>Today</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="57"/> + <location line="+1"/> <source>This week</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="58"/> + <location line="+1"/> <source>This month</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="59"/> + <location line="+1"/> <source>Last month</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="60"/> + <location line="+1"/> <source>This year</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="61"/> + <location line="+1"/> <source>Range...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="72"/> + <location line="+11"/> <source>Received with</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="74"/> + <location line="+2"/> <source>Sent to</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="76"/> + <location line="+2"/> <source>To yourself</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="77"/> + <location line="+1"/> <source>Mined</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="78"/> + <location line="+1"/> <source>Other</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="85"/> + <location line="+7"/> <source>Enter address or label to search</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="92"/> + <location line="+7"/> <source>Min amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="126"/> + <location line="+34"/> <source>Copy address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="127"/> + <location line="+1"/> <source>Copy label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="128"/> + <location line="+1"/> <source>Copy amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="129"/> + <location line="+1"/> <source>Edit label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="130"/> + <location line="+1"/> <source>Show transaction details</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="270"/> + <location line="+142"/> <source>Export Transaction Data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="271"/> + <location line="+1"/> <source>Comma separated file (*.csv)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="279"/> + <location line="+8"/> <source>Confirmed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="280"/> + <location line="+1"/> <source>Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="281"/> + <location line="+1"/> <source>Type</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="282"/> + <location line="+1"/> <source>Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="283"/> + <location line="+1"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="284"/> + <location line="+1"/> <source>Amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="285"/> + <location line="+1"/> <source>ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="289"/> + <location line="+4"/> <source>Error exporting</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="289"/> + <location line="+0"/> <source>Could not write to file %1.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="384"/> + <location line="+95"/> <source>Range:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="392"/> + <location line="+8"/> <source>to</source> <translation type="unfinished"></translation> </message> </context> <context> - <name>VerifyMessageDialog</name> - <message> - <location filename="../forms/verifymessagedialog.ui" line="14"/> - <source>Verify Signed Message</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/verifymessagedialog.ui" line="55"/> - <source>&Verify Message</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/verifymessagedialog.ui" line="20"/> - <source>Enter the signing address, signature and message below (be careful to correctly copy newlines, spaces, tabs and other invisible characters) to verify the message.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/verifymessagedialog.ui" line="52"/> - <source>Verify a message to ensure it was signed with the specified Bitcoin address</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/verifymessagedialog.ui" line="66"/> - <source>Reset all verify message fields</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/verifymessagedialog.ui" line="69"/> - <source>Clear &All</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="27"/> - <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="28"/> - <source>Enter Bitcoin signature</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="51"/> - <source>"%1" is not a valid address.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="51"/> - <location filename="../verifymessagedialog.cpp" line="59"/> - <source>Please check the address and try again.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="59"/> - <source>"%1" does not refer to a key.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="70"/> - <source>The signature could not be decoded.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="70"/> - <location filename="../verifymessagedialog.cpp" line="83"/> - <source>Please check the signature and try again.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="83"/> - <source>The signature did not match the message digest.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="90"/> - <source>Message verification failed.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../verifymessagedialog.cpp" line="95"/> - <source>Message verified.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>WalletModel</name> <message> - <location filename="../walletmodel.cpp" line="167"/> + <location filename="../walletmodel.cpp" line="+192"/> <source>Sending...</source> <translation type="unfinished"></translation> </message> @@ -2038,493 +2097,513 @@ Address: %4 <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="61"/> + <location filename="../bitcoinstrings.cpp" line="+62"/> <source>Bitcoin version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="135"/> + <location line="+76"/> <source>Usage:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="113"/> + <location line="-22"/> <source>Send command to -server or bitcoind</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="95"/> + <location line="-19"/> <source>List commands</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="87"/> + <location line="-9"/> <source>Get help for a command</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="105"/> + <location line="+19"/> <source>Options:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="123"/> + <location line="+19"/> <source>Specify configuration file (default: bitcoin.conf)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="126"/> + <location line="+3"/> <source>Specify pid file (default: bitcoind.pid)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="86"/> + <location line="-42"/> <source>Generate coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="72"/> + <location line="-14"/> <source>Don't generate coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="125"/> + <location line="+55"/> <source>Specify data directory</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="120"/> + <location line="-5"/> <source>Set database cache size in megabytes (default: 25)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="121"/> + <location line="+1"/> <source>Set database disk log size in megabytes (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="124"/> + <location line="+3"/> <source>Specify connection timeout (in milliseconds)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="97"/> + <location line="-28"/> <source>Listen for connections on <port> (default: 8333 or testnet: 18333)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="101"/> + <location line="+4"/> <source>Maintain at most <n> connections to peers (default: 125)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="70"/> + <location line="-32"/> <source>Connect to a node to retrieve peer addresses, and disconnect</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="127"/> + <location line="+59"/> <source>Specify your own public address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="104"/> - <source>Only connect to nodes in network <net> (IPv4 or IPv6)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoinstrings.cpp" line="60"/> + <location line="-69"/> <source>Bind to given address. Use [host]:port notation for IPv6</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="129"/> + <location line="+71"/> <source>Threshold for disconnecting misbehaving peers (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="35"/> + <location line="-96"/> <source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="102"/> - <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)</source> + <location line="-12"/> + <source>Detach block and address databases. Increases shutdown time (default: 0)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="103"/> - <source>Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)</source> + <location line="+31"/> + <source>Accept command line and JSON-RPC commands</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="23"/> - <source>Detach block and address databases. Increases shutdown time (default: 0)</source> + <location line="+59"/> + <source>Run in the background as a daemon and accept commands</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="54"/> - <source>Accept command line and JSON-RPC commands</source> + <location line="+29"/> + <source>Use the test network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="111"/> - <source>Run in the background as a daemon and accept commands</source> + <location line="-87"/> + <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="139"/> - <source>Use the test network</source> + <location line="+13"/> + <source>Connect only to the specified node(s)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="106"/> - <source>Output extra debugging information</source> + <location line="+3"/> + <source>Discover own IP address (default: 1 when listening and no -externalip)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="55"/> - <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source> + <location line="+11"/> + <source>Failed to listen on any port. Use -listen=0 if you want this.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="68"/> - <source>Connect only to the specified node(s)</source> + <location line="+2"/> + <source>Find peers using DNS lookup (default: 1 unless -connect)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="71"/> - <source>Discover own IP address (default: 1 when listening and no -externalip)</source> + <location line="+9"/> + <source>Invalid -tor address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="82"/> - <source>Failed to listen on any port. Use -listen=0 if you want this.</source> + <location line="+10"/> + <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+1"/> + <source>Only connect to nodes in network <net> (IPv4, IPv6 or Tor)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> + <source>Output extra debugging information. Implies all other -debug* options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="108"/> + <location line="+1"/> + <source>Output extra network debugging information</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> <source>Prepend debug output with timestamp</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="112"/> + <location line="+4"/> <source>Select the version of socks proxy to use (4-5, default: 5)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="115"/> + <location line="+3"/> <source>Send trace/debug info to console instead of debug.log file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="116"/> + <location line="+1"/> <source>Send trace/debug info to debugger</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="137"/> + <location line="+21"/> <source>Use UPnP to map the listening port (default: 0)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="138"/> + <location line="+1"/> <source>Use UPnP to map the listening port (default: 1 when listening)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="140"/> + <location line="+1"/> + <source>Use proxy to reach tor hidden services (default: same as -proxy)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+2"/> <source>Username for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="107"/> + <location line="+3"/> + <source>Warning: this version is obsolete, upgrade required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="-37"/> <source>Password for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="96"/> + <location line="-12"/> <source>Listen for JSON-RPC connections on <port> (default: 8332)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="58"/> + <location line="-39"/> <source>Allow JSON-RPC connections from specified IP address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="114"/> + <location line="+58"/> <source>Send commands to node running on <ip> (default: 127.0.0.1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="32"/> + <location line="-84"/> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="134"/> + <location line="+104"/> <source>Upgrade wallet to latest format</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="122"/> + <location line="-12"/> <source>Set key pool size to <n> (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="109"/> + <location line="-13"/> <source>Rescan the block chain for missing wallet transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="88"/> + <location line="-23"/> <source>How many blocks to check at startup (default: 2500, 0 = all)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="89"/> + <location line="+1"/> <source>How thorough the block verification is (0-6, default: 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="90"/> + <location line="+1"/> <source>Imports blocks from external blk000?.dat file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="51"/> + <location line="-39"/> <source> SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="136"/> + <location line="+87"/> <source>Use OpenSSL (https) for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="118"/> + <location line="-18"/> <source>Server certificate file (default: server.cert)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="119"/> + <location line="+1"/> <source>Server private key (default: server.pem)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="17"/> + <location line="-104"/> <source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="142"/> + <location line="+128"/> <source>Warning: Disk space is low</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="128"/> + <location line="-15"/> <source>This help message</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="20"/> + <location line="-110"/> <source>Cannot obtain a lock on data directory %s. Bitcoin is probably already running.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="62"/> + <location line="+42"/> <source>Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="131"/> + <location line="+71"/> <source>Unable to bind to %s on this computer (bind returned error %d, %s)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="69"/> + <location line="-64"/> <source>Connect through socks proxy</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="57"/> + <location line="-12"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="98"/> + <location line="+42"/> <source>Loading addresses...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="74"/> + <location line="-25"/> <source>Error loading blkindex.dat</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="76"/> + <location line="+2"/> <source>Error loading wallet.dat: Wallet corrupted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="77"/> + <location line="+1"/> <source>Error loading wallet.dat: Wallet requires newer version of Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="141"/> + <location line="+67"/> <source>Wallet needed to be rewritten: restart Bitcoin to complete</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="75"/> + <location line="-69"/> <source>Error loading wallet.dat</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="92"/> + <location line="+17"/> <source>Invalid -proxy address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="133"/> + <location line="+43"/> <source>Unknown network specified in -onlynet: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="132"/> + <location line="-1"/> <source>Unknown -socks proxy version requested: %i</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="65"/> + <location line="-69"/> <source>Cannot resolve -bind address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="66"/> + <location line="+1"/> <source>Cannot resolve -externalip address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="93"/> + <location line="+28"/> <source>Invalid amount for -paytxfee=<amount>: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="81"/> + <location line="-13"/> <source>Error: could not start node</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="80"/> + <location line="-1"/> <source>Error: Wallet locked, unable to create transaction </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="29"/> + <location line="-51"/> <source>Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="79"/> + <location line="+50"/> <source>Error: Transaction creation failed </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="117"/> + <location line="+40"/> <source>Sending...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="25"/> + <location line="-94"/> <source>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="94"/> + <location line="+70"/> <source>Invalid amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="91"/> + <location line="-4"/> <source>Insufficient funds</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="99"/> + <location line="+9"/> <source>Loading block index...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="56"/> + <location line="-44"/> <source>Add a node to connect to and attempt to keep the connection open</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="38"/> + <location line="-18"/> <source>Unable to bind to %s on this computer. Bitcoin is probably already running.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="85"/> + <location line="+47"/> <source>Find peers using internet relay chat (default: 0)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="84"/> - <source>Find peers using DNS lookup (default: 1)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoinstrings.cpp" line="83"/> + <location line="-2"/> <source>Fee per KB to add to transactions you send</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="40"/> + <location line="-43"/> <source>Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="100"/> + <location line="+61"/> <source>Loading wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="63"/> + <location line="-38"/> <source>Cannot downgrade wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="64"/> + <location line="+1"/> <source>Cannot initialize keypool</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="67"/> + <location line="+3"/> <source>Cannot write default address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="110"/> + <location line="+45"/> <source>Rescanning...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="73"/> + <location line="-39"/> <source>Done loading</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="130"/> + <location line="+59"/> <source>To use the %s option</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="8"/> + <location line="-124"/> <source>%s, you must set a rpcpassword in the configuration file: %s It is recommended you use the following random password: @@ -2536,24 +2615,24 @@ If the file does not exist, create it with owner-readable-only file permissions. <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="78"/> + <location line="+70"/> <source>Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="59"/> + <location line="-19"/> <source>An error occured while setting up the RPC port %i for listening: %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="46"/> + <location line="-13"/> <source>You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="43"/> + <location line="-3"/> <source>Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.</source> <translation type="unfinished"></translation> </message> diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 2636d196d6..aa93097c4c 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>La contraseña del monedero ha sido cambiada correctamente.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index 89228e5a97..e1be3866a1 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>La contraseña de billetera ha sido cambiada con éxito.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index aafd7a214f..c4c18244e9 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -263,7 +263,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"/> </message> </context> diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts index 01a156c0b1..4466b568da 100644 --- a/src/qt/locale/bitcoin_eu_ES.ts +++ b/src/qt/locale/bitcoin_eu_ES.ts @@ -263,7 +263,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"/> </message> </context> diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index e918c460e5..7184b84b40 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -272,7 +272,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>عبارت عبور با موفقیت تغییر شد</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index 01958e81d7..fd5116a547 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -263,7 +263,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"/> </message> </context> diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index e9fcf50330..a6ad4f8f77 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -270,7 +270,7 @@ Tahdotko varmasti salata lompakon?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Lompakon tunnuslause on vaihdettu.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 03ff69e3c6..bc71752a87 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>La phrase de passe du porte-monnaie a été modifiée avec succès.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_fr_CA.ts index e3565d210b..a6bf6704b4 100644 --- a/src/qt/locale/bitcoin_fr_CA.ts +++ b/src/qt/locale/bitcoin_fr_CA.ts @@ -263,7 +263,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation type="unfinished"/> </message> </context> diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 224bf54d5d..de1d6aae30 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>סיסמת הארנק שונתה בהצלחה.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index 300bbd64b6..20d1520d90 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -270,7 +270,7 @@ Jeste li sigurni da želite šifrirati svoj novčanik?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Lozinka novčanika je uspješno promijenjena.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index e69453c8e6..67dd119650 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -264,7 +264,7 @@ Biztosan kódolni akarod a tárcát?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Jelszó megváltoztatva.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index 92d3b7cf2d..fb3ceaa40e 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -270,7 +270,7 @@ Si è sicuri di voler cifrare il portamonete?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Passphrase del portamonete modificata con successo.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index f14b5ecb86..d89080084e 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -271,7 +271,7 @@ Ar jūs tikrai norite užšifruoti savo piniginę?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Sėkmingai pakeistas piniginės slaptažodis</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 8f32f6b65f..4fe706a37b 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -270,7 +270,7 @@ Er du sikker på at du vil kryptere lommeboken?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Lommebokens adgangsfrase ble endret.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 8ffa7694ff..43ac38a211 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -271,7 +271,7 @@ Bent u er zeker van uw dat u uw portemonnee wilt versleutelen?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Portemonneewachtwoord is succesvol gewijzigd</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index fe44a97a03..62535cf803 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -275,7 +275,7 @@ Czy na pewno chcesz zaszyfrować swój portfel?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Hasło do portfela zostało pomyślnie zmienione.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 64e292358e..2252b3129a 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -269,7 +269,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>A frase de segurança da carteira foi alterada com êxito.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index bd7f74bb7f..30717fda8e 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -269,7 +269,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>A frase de segurança da carteira foi alterada com êxito.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index 6b8bbd3732..1f387b06cf 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -264,7 +264,7 @@ Sunteţi sigur că doriţi să criptaţi portofelul electronic?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Parola portofelului electronic a fost schimbată.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index f4e3c8c851..2d481ec7c2 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Пароль бумажника успешно изменён.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index bd56dd1bf6..d423ae44be 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -264,7 +264,7 @@ Ste si istí, že si želáte zašifrovať peňaženku?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Heslo k peňaženke bolo úspešne zmenené.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts index 89d8f77a5f..bac82f14b9 100644 --- a/src/qt/locale/bitcoin_sr.ts +++ b/src/qt/locale/bitcoin_sr.ts @@ -264,7 +264,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Лозинка за приступ новчанику је успешно промењена.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index d41390fb7c..9b03314d5e 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Plånbokens lösenord har ändrats.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index 4e0e82dc1d..b84e078cc1 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -270,7 +270,7 @@ Cüzdanınızı şifrelemek istediğinizden emin misiniz?</translation> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Cüzdan parolası başarılı bir şekilde değiştirildi.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index bf41f5113a..dda0e5b419 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>Пароль було успішно змінено.</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 087e19b00e..6029be0708 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>钱包口令修改成功</translation> </message> </context> diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index c2b318e990..74027800c1 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -270,7 +270,7 @@ Are you sure you wish to encrypt your wallet?</source> </message> <message> <location filename="../askpassphrasedialog.cpp" line="160"/> - <source>Wallet passphrase was succesfully changed.</source> + <source>Wallet passphrase was successfully changed.</source> <translation>錢包密碼變更成功.</translation> </message> </context> diff --git a/src/qt/messagepage.cpp b/src/qt/messagepage.cpp deleted file mode 100644 index ab3ea5a0c5..0000000000 --- a/src/qt/messagepage.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include <string> -#include <vector> - -#include <QClipboard> -#include <QInputDialog> -#include <QList> -#include <QListWidgetItem> -#include <QMessageBox> - -#include "main.h" -#include "wallet.h" -#include "init.h" -#include "base58.h" - -#include "messagepage.h" -#include "ui_messagepage.h" - -#include "addressbookpage.h" -#include "guiutil.h" -#include "walletmodel.h" - -MessagePage::MessagePage(QWidget *parent) : - QDialog(parent), - ui(new Ui::MessagePage) -{ - ui->setupUi(this); - -#if (QT_VERSION >= 0x040700) - /* Do not move this to the XML file, Qt before 4.7 will choke on it */ - ui->signFrom->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); - ui->signature->setPlaceholderText(tr("Click \"Sign Message\" to get signature")); -#endif - - GUIUtil::setupAddressWidget(ui->signFrom, this); - ui->signature->installEventFilter(this); - - ui->signFrom->setFocus(); -} - -MessagePage::~MessagePage() -{ - delete ui; -} - -void MessagePage::setModel(WalletModel *model) -{ - this->model = model; -} - -void MessagePage::setAddress(QString addr) -{ - ui->signFrom->setText(addr); - ui->message->setFocus(); -} - -void MessagePage::on_pasteButton_clicked() -{ - setAddress(QApplication::clipboard()->text()); -} - -void MessagePage::on_addressBookButton_clicked() -{ - AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this); - dlg.setModel(model->getAddressTableModel()); - if(dlg.exec()) - { - setAddress(dlg.getReturnValue()); - } -} - -void MessagePage::on_copyToClipboard_clicked() -{ - QApplication::clipboard()->setText(ui->signature->text()); -} - -void MessagePage::on_signMessage_clicked() -{ - QString address = ui->signFrom->text(); - - CBitcoinAddress addr(address.toStdString()); - if (!addr.IsValid()) - { - QMessageBox::critical(this, tr("Error signing"), tr("%1 is not a valid address.").arg(address), - QMessageBox::Abort, QMessageBox::Abort); - return; - } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) - { - QMessageBox::critical(this, tr("Error signing"), tr("%1 does not refer to a key.").arg(address), - QMessageBox::Abort, QMessageBox::Abort); - return; - } - - WalletModel::UnlockContext ctx(model->requestUnlock()); - if(!ctx.isValid()) - { - // Unlock wallet was cancelled - return; - } - - CKey key; - if (!pwalletMain->GetKey(keyID, key)) - { - QMessageBox::critical(this, tr("Error signing"), tr("Private key for %1 is not available.").arg(address), - QMessageBox::Abort, QMessageBox::Abort); - return; - } - - CDataStream ss(SER_GETHASH, 0); - ss << strMessageMagic; - ss << ui->message->document()->toPlainText().toStdString(); - - std::vector<unsigned char> vchSig; - if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) - { - QMessageBox::critical(this, tr("Error signing"), tr("Sign failed"), - QMessageBox::Abort, QMessageBox::Abort); - } - - ui->signature->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size()))); - ui->signature->setFont(GUIUtil::bitcoinAddressFont()); -} - -void MessagePage::on_clearButton_clicked() -{ - ui->signFrom->clear(); - ui->message->clear(); - ui->signature->clear(); - - ui->signFrom->setFocus(); -} - -bool MessagePage::eventFilter(QObject *object, QEvent *event) -{ - if(object == ui->signature && (event->type() == QEvent::MouseButtonPress || - event->type() == QEvent::FocusIn)) - { - ui->signature->selectAll(); - return true; - } - return QDialog::eventFilter(object, event); -} diff --git a/src/qt/messagepage.h b/src/qt/messagepage.h deleted file mode 100644 index d668ae98d0..0000000000 --- a/src/qt/messagepage.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef MESSAGEPAGE_H -#define MESSAGEPAGE_H - -#include <QDialog> - -namespace Ui { - class MessagePage; -} -class WalletModel; - -QT_BEGIN_NAMESPACE -QT_END_NAMESPACE - -class MessagePage : public QDialog -{ - Q_OBJECT - -public: - explicit MessagePage(QWidget *parent = 0); - ~MessagePage(); - - void setModel(WalletModel *model); - - void setAddress(QString); - -protected: - bool eventFilter(QObject *object, QEvent *event); - -private: - Ui::MessagePage *ui; - WalletModel *model; - -private slots: - void on_pasteButton_clicked(); - void on_addressBookButton_clicked(); - - void on_signMessage_clicked(); - void on_copyToClipboard_clicked(); - void on_clearButton_clicked(); -}; - -#endif // MESSAGEPAGE_H diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index e28b96b090..6bb7eaec2e 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -1,26 +1,17 @@ #include "optionsdialog.h" #include "ui_optionsdialog.h" -#include "bitcoinamountfield.h" #include "bitcoinunits.h" #include "monitoreddatamapper.h" #include "netbase.h" #include "optionsmodel.h" -#include "qvalidatedlineedit.h" -#include "qvaluecombobox.h" -#include <QCheckBox> #include <QDir> #include <QIntValidator> -#include <QLabel> -#include <QLineEdit> #include <QLocale> #include <QMessageBox> -#include <QPushButton> #include <QRegExp> #include <QRegExpValidator> -#include <QTabWidget> -#include <QWidget> OptionsDialog::OptionsDialog(QWidget *parent) : QDialog(parent), @@ -38,18 +29,19 @@ OptionsDialog::OptionsDialog(QWidget *parent) : ui->mapPortUpnp->setEnabled(false); #endif + ui->proxyIp->setEnabled(false); + ui->proxyPort->setEnabled(false); + ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); + ui->socksVersion->setEnabled(false); ui->socksVersion->addItem("5", 5); ui->socksVersion->addItem("4", 4); ui->socksVersion->setCurrentIndex(0); - ui->proxyIp->setEnabled(false); - ui->proxyPort->setEnabled(false); - ui->proxyPort->setValidator(new QIntValidator(0, 65535, this)); - - connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool))); + connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); + connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy())); ui->proxyIp->installEventFilter(this); @@ -68,21 +60,28 @@ OptionsDialog::OptionsDialog(QWidget *parent) : /** check if the locale name consists of 2 parts (language_country) */ if(langStr.contains("_")) { +#if QT_VERSION >= 0x040800 + /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */ + ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#else /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */ ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#endif } else { +#if QT_VERSION >= 0x040800 + /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */ + ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#else /** display language strings as "language (locale name)", e.g. "German (de)" */ ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#endif } } ui->unit->setModel(new BitcoinUnits(this)); - connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy())); - connect(ui->lang, SIGNAL(activated(int)), this, SLOT(showRestartWarning_Lang())); - /* Widget-to-option mapper */ mapper = new MonitoredDataMapper(this); mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); @@ -92,8 +91,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(mapper, SIGNAL(viewModified()), this, SLOT(enableSaveButtons())); /* disable save buttons when new data loaded */ connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableSaveButtons())); - /* disable/enable save buttons when proxy IP is invalid/valid */ - connect(this, SIGNAL(proxyIpValid(bool)), this, SLOT(setSaveButtonState(bool))); + /* setup/change UI elements when proxy IP is invalid/valid */ + connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); } OptionsDialog::~OptionsDialog() @@ -114,8 +113,11 @@ void OptionsDialog::setModel(OptionsModel *model) mapper->toFirst(); } - // update the display unit, to not use the default ("BTC") + /* update the display unit, to not use the default ("BTC") */ updateDisplayUnit(); + + /* warn only when language selection changes (placed here so init of ui->lang via mapper doesn't trigger this) */ + connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang())); } void OptionsDialog::setMapper() @@ -127,10 +129,11 @@ void OptionsDialog::setMapper() /* Network */ mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); + mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); - mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); + mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); /* Window */ #ifndef Q_WS_MAC @@ -146,7 +149,7 @@ void OptionsDialog::setMapper() void OptionsDialog::enableSaveButtons() { - // prevent enabling of the save buttons when data modified, if there is an invalid proxy address present + /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */ if(fProxyIpValid) setSaveButtonState(true); } @@ -201,30 +204,39 @@ void OptionsDialog::updateDisplayUnit() { if(model) { - // Update transactionFee with the current unit + /* Update transactionFee with the current unit */ ui->transactionFee->setDisplayUnit(model->getDisplayUnit()); } } +void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState) +{ + // this is used in a check before re-enabling the save buttons + fProxyIpValid = fState; + + if(fProxyIpValid) + { + enableSaveButtons(); + ui->statusLabel->clear(); + } + else + { + disableSaveButtons(); + object->setValid(fProxyIpValid); + ui->statusLabel->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel->setText(tr("The supplied proxy address is invalid.")); + } +} + bool OptionsDialog::eventFilter(QObject *object, QEvent *event) { - if(object == ui->proxyIp && event->type() == QEvent::FocusOut) + if(event->type() == QEvent::FocusOut) { - // Check proxyIP for a valid IPv4/IPv6 address - CService addr; - if(!LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr)) - { - ui->proxyIp->setValid(false); - fProxyIpValid = false; - ui->statusLabel->setStyleSheet("QLabel { color: red; }"); - ui->statusLabel->setText(tr("The supplied proxy address is invalid.")); - emit proxyIpValid(false); - } - else + if(object == ui->proxyIp) { - fProxyIpValid = true; - ui->statusLabel->clear(); - emit proxyIpValid(true); + CService addr; + /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */ + emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr)); } } return QDialog::eventFilter(object, event); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 7e91c96475..9e91000b63 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -8,6 +8,7 @@ class OptionsDialog; } class OptionsModel; class MonitoredDataMapper; +class QValidatedLineEdit; /** Preferences dialog. */ class OptionsDialog : public QDialog @@ -38,9 +39,10 @@ private slots: void showRestartWarning_Proxy(); void showRestartWarning_Lang(); void updateDisplayUnit(); + void handleProxyIpValid(QValidatedLineEdit *object, bool fState); signals: - void proxyIpValid(bool fValid); + void proxyIpValid(QValidatedLineEdit *object, bool fValid); private: Ui::OptionsDialog *ui; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index d6c6bbf409..caa33414b2 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -40,7 +40,7 @@ void OptionsModel::Init() { QSettings settings; - // These are QT-only settings: + // These are Qt-only settings: nDisplayUnit = settings.value("nDisplayUnit", BitcoinUnits::BTC).toInt(); bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool(); fMinimizeToTray = settings.value("fMinimizeToTray", false).toBool(); @@ -144,8 +144,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return QVariant(fMinimizeOnClose); case ProxyUse: return settings.value("fUseProxy", false); - case ProxySocksVersion: - return settings.value("nSocksVersion", 5); case ProxyIP: { CService addrProxy; if (GetProxy(NET_IPV4, addrProxy)) @@ -160,6 +158,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const else return 9050; } + case ProxySocksVersion: + return settings.value("nSocksVersion", 5); case Fee: return QVariant(nTransactionFee); case DisplayUnit: @@ -192,11 +192,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in settings.setValue("fMinimizeToTray", fMinimizeToTray); break; case MapPortUPnP: - { - fUseUPnP = value.toBool(); - settings.setValue("fUseUPnP", fUseUPnP); - MapPort(); - } + fUseUPnP = value.toBool(); + settings.setValue("fUseUPnP", fUseUPnP); + MapPort(); break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); @@ -206,60 +204,41 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in settings.setValue("fUseProxy", value.toBool()); ApplyProxySettings(); break; - case ProxySocksVersion: - settings.setValue("nSocksVersion", value.toInt()); - ApplyProxySettings(); - break; case ProxyIP: { CService addrProxy("127.0.0.1", 9050); GetProxy(NET_IPV4, addrProxy); CNetAddr addr(value.toString().toStdString()); - if (addr.IsValid()) - { - addrProxy.SetIP(addr); - settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); - successful = ApplyProxySettings(); - } - else - { - successful = false; - } + addrProxy.SetIP(addr); + settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); + successful = ApplyProxySettings(); } break; case ProxyPort: { CService addrProxy("127.0.0.1", 9050); GetProxy(NET_IPV4, addrProxy); - int nPort = atoi(value.toString().toAscii().data()); - if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max()) - { - addrProxy.SetPort(nPort); - settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); - successful = ApplyProxySettings(); - } - else - { - successful = false; - } + addrProxy.SetPort(value.toInt()); + settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); + successful = ApplyProxySettings(); } break; - case Fee: { + case ProxySocksVersion: + settings.setValue("nSocksVersion", value.toInt()); + ApplyProxySettings(); + break; + case Fee: nTransactionFee = value.toLongLong(); settings.setValue("nTransactionFee", nTransactionFee); - } break; - case DisplayUnit: { - int unit = value.toInt(); - nDisplayUnit = unit; + case DisplayUnit: + nDisplayUnit = value.toInt(); settings.setValue("nDisplayUnit", nDisplayUnit); - emit displayUnitChanged(unit); - } + emit displayUnitChanged(nDisplayUnit); break; - case DisplayAddresses: { + case DisplayAddresses: bDisplayAddresses = value.toBool(); settings.setValue("bDisplayAddresses", bDisplayAddresses); - } break; case DetachDatabases: { bool fDetachDB = value.toBool(); @@ -267,9 +246,8 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in settings.setValue("detachDB", fDetachDB); } break; - case Language: { + case Language: settings.setValue("language", value); - } break; default: break; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index c74a8dfb43..34724ad032 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -12,23 +12,24 @@ class OptionsModel : public QAbstractListModel { Q_OBJECT + public: explicit OptionsModel(QObject *parent = 0); enum OptionID { - StartAtStartup, // bool - MinimizeToTray, // bool - MapPortUPnP, // bool - MinimizeOnClose, // bool - ProxyUse, // bool + StartAtStartup, // bool + MinimizeToTray, // bool + MapPortUPnP, // bool + MinimizeOnClose, // bool + ProxyUse, // bool + ProxyIP, // QString + ProxyPort, // int ProxySocksVersion, // int - ProxyIP, // QString - ProxyPort, // QString - Fee, // qint64 - DisplayUnit, // BitcoinUnits::Unit - DisplayAddresses, // bool - DetachDatabases, // bool - Language, // QString + Fee, // qint64 + DisplayUnit, // BitcoinUnits::Unit + DisplayAddresses, // bool + DetachDatabases, // bool + Language, // QString OptionIDRowCount, }; @@ -48,17 +49,16 @@ public: int getDisplayUnit(); bool getDisplayAddresses(); QString getLanguage() { return language; } + private: int nDisplayUnit; bool bDisplayAddresses; bool fMinimizeToTray; bool fMinimizeOnClose; QString language; + signals: void displayUnitChanged(int unit); - -public slots: - }; #endif // OPTIONSMODEL_H diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp index 32e5462cee..ca94975128 100644 --- a/src/qt/qrcodedialog.cpp +++ b/src/qt/qrcodedialog.cpp @@ -1,28 +1,34 @@ #include "qrcodedialog.h" #include "ui_qrcodedialog.h" + +#include "bitcoinunits.h" +#include "guiconstants.h" #include "guiutil.h" +#include "optionsmodel.h" #include <QPixmap> #include <QUrl> -#include <QDebug> #include <qrencode.h> -#define EXPORT_IMAGE_SIZE 256 - QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) : - QDialog(parent), ui(new Ui::QRCodeDialog), address(addr) + QDialog(parent), + ui(new Ui::QRCodeDialog), + model(0), + address(addr) { ui->setupUi(this); + setWindowTitle(QString("%1").arg(address)); ui->chkReqPayment->setVisible(enableReq); - ui->lnReqAmount->setVisible(enableReq); ui->lblAmount->setVisible(enableReq); - ui->lblBTC->setVisible(enableReq); + ui->lnReqAmount->setVisible(enableReq); ui->lnLabel->setText(label); + ui->btnSaveAs->setEnabled(false); + genCode(); } @@ -31,6 +37,17 @@ QRCodeDialog::~QRCodeDialog() delete ui; } +void QRCodeDialog::setModel(OptionsModel *model) +{ + this->model = model; + + if (model) + connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + // update the display unit, to not use the default ("BTC") + updateDisplayUnit(); +} + void QRCodeDialog::genCode() { QString uri = getURI(); @@ -57,26 +74,34 @@ void QRCodeDialog::genCode() } } QRcode_free(code); + ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); + + ui->outUri->setPlainText(uri); } - else - ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); } QString QRCodeDialog::getURI() { QString ret = QString("bitcoin:%1").arg(address); - int paramCount = 0; - if (ui->chkReqPayment->isChecked() && !ui->lnReqAmount->text().isEmpty()) + + ui->outUri->clear(); + + if (ui->chkReqPayment->isChecked()) { - bool ok = false; - ui->lnReqAmount->text().toDouble(&ok); - if (ok) + if (ui->lnReqAmount->validate()) { - ret += QString("?amount=%1").arg(ui->lnReqAmount->text()); + // even if we allow a non BTC unit input in lnReqAmount, we generate the URI with BTC as unit (as defined in BIP21) + ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, ui->lnReqAmount->value())); paramCount++; } + else + { + ui->btnSaveAs->setEnabled(false); + ui->lblQRCode->setText(tr("The entered amount is invalid, please check.")); + return QString(""); + } } if (!ui->lnLabel->text().isEmpty()) @@ -93,24 +118,29 @@ QString QRCodeDialog::getURI() paramCount++; } - // limit URI length to 255 chars, to prevent a DoS against the QR-Code dialog - if (ret.length() < 256) - return ret; - else + // limit URI length to prevent a DoS against the QR-Code dialog + if (ret.length() > MAX_URI_LENGTH) + { + ui->btnSaveAs->setEnabled(false); + ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); return QString(""); + } + + ui->btnSaveAs->setEnabled(true); + return ret; } -void QRCodeDialog::on_lnReqAmount_textChanged(const QString &arg1) +void QRCodeDialog::on_lnReqAmount_textChanged() { genCode(); } -void QRCodeDialog::on_lnLabel_textChanged(const QString &arg1) +void QRCodeDialog::on_lnLabel_textChanged() { genCode(); } -void QRCodeDialog::on_lnMessage_textChanged(const QString &arg1) +void QRCodeDialog::on_lnMessage_textChanged() { genCode(); } @@ -122,7 +152,20 @@ void QRCodeDialog::on_btnSaveAs_clicked() myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn); } -void QRCodeDialog::on_chkReqPayment_toggled(bool) +void QRCodeDialog::on_chkReqPayment_toggled(bool fChecked) { + if (!fChecked) + // if chkReqPayment is not active, don't display lnReqAmount as invalid + ui->lnReqAmount->setValid(true); + genCode(); } + +void QRCodeDialog::updateDisplayUnit() +{ + if (model) + { + // Update lnReqAmount with the current unit + ui->lnReqAmount->setDisplayUnit(model->getDisplayUnit()); + } +} diff --git a/src/qt/qrcodedialog.h b/src/qt/qrcodedialog.h index ad0611605b..c55c34bce6 100644 --- a/src/qt/qrcodedialog.h +++ b/src/qt/qrcodedialog.h @@ -7,6 +7,7 @@ namespace Ui { class QRCodeDialog; } +class OptionsModel; class QRCodeDialog : public QDialog { @@ -16,22 +17,25 @@ public: explicit QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent = 0); ~QRCodeDialog(); + void setModel(OptionsModel *model); + private slots: - void on_lnReqAmount_textChanged(const QString &arg1); - void on_lnLabel_textChanged(const QString &arg1); - void on_lnMessage_textChanged(const QString &arg1); + void on_lnReqAmount_textChanged(); + void on_lnLabel_textChanged(); + void on_lnMessage_textChanged(); void on_btnSaveAs_clicked(); + void on_chkReqPayment_toggled(bool fChecked); - void on_chkReqPayment_toggled(bool checked); + void updateDisplayUnit(); private: Ui::QRCodeDialog *ui; - QImage myImage; - - QString getURI(); + OptionsModel *model; QString address; + QImage myImage; void genCode(); + QString getURI(); }; #endif // QRCODEDIALOG_H diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp index 3d7d90e902..ccdfc66bad 100644 --- a/src/qt/qtipcserver.cpp +++ b/src/qt/qtipcserver.cpp @@ -1,75 +1,97 @@ // 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. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "qtipcserver.h" +#include "guiconstants.h" +#include "ui_interface.h" +#include "util.h" -#include <boost/algorithm/string.hpp> -#include <boost/interprocess/ipc/message_queue.hpp> -#include <boost/tokenizer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/interprocess/ipc/message_queue.hpp> +#include <boost/version.hpp> -#include "ui_interface.h" -#include "qtipcserver.h" +#if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900) +#warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392 +#endif +using namespace boost; using namespace boost::interprocess; using namespace boost::posix_time; -using namespace boost; -using namespace std; -void ipcShutdown() +static void ipcThread2(void* pArg); + +#ifdef MAC_OSX +// URI handling not implemented on OSX yet + +void ipcInit() { } + +#else + +static void ipcThread(void* pArg) { - message_queue::remove(BITCOINURI_QUEUE_NAME); + IMPLEMENT_RANDOMIZE_STACK(ipcThread(pArg)); + + // Make this thread recognisable as the GUI-IPC thread + RenameThread("bitcoin-gui-ipc"); + + try + { + ipcThread2(pArg); + } + catch (std::exception& e) { + PrintExceptionContinue(&e, "ipcThread()"); + } catch (...) { + PrintExceptionContinue(NULL, "ipcThread()"); + } + printf("ipcThread exited\n"); } -void ipcThread(void* parg) +static void ipcThread2(void* pArg) { - message_queue* mq = (message_queue*)parg; - char strBuf[257]; - size_t nSize; - unsigned int nPriority; + printf("ipcThread started\n"); + + message_queue* mq = (message_queue*)pArg; + char buffer[MAX_URI_LENGTH + 1] = ""; + size_t nSize = 0; + unsigned int nPriority = 0; + loop { ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100); - if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) + if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d)) { - uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize)); + uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize)); Sleep(1000); } + if (fShutdown) - { - ipcShutdown(); break; - } } - ipcShutdown(); + + // Remove message queue + message_queue::remove(BITCOINURI_QUEUE_NAME); + // Cleanup allocated memory + delete mq; } void ipcInit() { -#ifdef MAC_OSX - // TODO: implement bitcoin: URI handling the Mac Way - return; -#endif -#ifdef WIN32 - // TODO: THOROUGHLY test boost::interprocess fix, - // and make sure there are no Windows argument-handling exploitable - // problems. - return; -#endif + message_queue* mq = NULL; + char buffer[MAX_URI_LENGTH + 1] = ""; + size_t nSize = 0; + unsigned int nPriority = 0; - message_queue* mq; - char strBuf[257]; - size_t nSize; - unsigned int nPriority; try { - mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256); + mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH); // Make sure we don't lose any bitcoin: URIs for (int i = 0; i < 2; i++) { ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1); - if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) + if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d)) { - uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize)); + uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize)); } else break; @@ -77,13 +99,20 @@ void ipcInit() // Make sure only one bitcoin instance is listening message_queue::remove(BITCOINURI_QUEUE_NAME); - mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256); + delete mq; + + mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH); } catch (interprocess_exception &ex) { + printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what()); return; } + if (!CreateThread(ipcThread, mq)) { delete mq; + return; } } + +#endif diff --git a/src/qt/qtipcserver.h b/src/qt/qtipcserver.h index fcff10d8da..484b6222eb 100644 --- a/src/qt/qtipcserver.h +++ b/src/qt/qtipcserver.h @@ -1,4 +1,9 @@ +#ifndef QTIPCSERVER_H +#define QTIPCSERVER_H + +// Define Bitcoin-Qt message queue name #define BITCOINURI_QUEUE_NAME "BitcoinURI" void ipcInit(); -void ipcShutdown(); + +#endif // QTIPCSERVER_H diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 7b40db0765..08f936e719 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -14,6 +14,7 @@ #include <QScrollBar> #include <boost/tokenizer.hpp> +#include <openssl/crypto.h> // TODO: make it possible to filter out categories (esp debug messages when implemented) // TODO: receive errors and debug messages through ClientModel @@ -119,6 +120,9 @@ RPCConsole::RPCConsole(QWidget *parent) : connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); + // set OpenSSL version label + ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); + startExecutor(); clear(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 86c2b01fec..2c46ea5a70 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -121,7 +121,7 @@ void SendCoinsDialog::on_sendButton_clicked() { case WalletModel::InvalidAddress: QMessageBox::warning(this, tr("Send Coins"), - tr("The recepient address is not valid, please recheck."), + tr("The recipient address is not valid, please recheck."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::InvalidAmount: diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp new file mode 100644 index 0000000000..f8edbf80ea --- /dev/null +++ b/src/qt/signverifymessagedialog.cpp @@ -0,0 +1,274 @@ +#include "signverifymessagedialog.h" +#include "ui_signverifymessagedialog.h" + +#include "addressbookpage.h" +#include "base58.h" +#include "guiutil.h" +#include "init.h" +#include "main.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" + +#include <string> +#include <vector> + +#include <QClipboard> + +SignVerifyMessageDialog::SignVerifyMessageDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SignVerifyMessageDialog), + model(0) +{ + ui->setupUi(this); + +#if (QT_VERSION >= 0x040700) + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + ui->addressIn_SM->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); + ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature")); + + ui->addressIn_VM->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); + ui->signatureIn_VM->setPlaceholderText(tr("Enter Bitcoin signature")); +#endif + + GUIUtil::setupAddressWidget(ui->addressIn_SM, this); + GUIUtil::setupAddressWidget(ui->addressIn_VM, this); + + ui->addressIn_SM->installEventFilter(this); + ui->messageIn_SM->installEventFilter(this); + ui->signatureOut_SM->installEventFilter(this); + ui->addressIn_VM->installEventFilter(this); + ui->messageIn_VM->installEventFilter(this); + ui->signatureIn_VM->installEventFilter(this); + + ui->signatureOut_SM->setFont(GUIUtil::bitcoinAddressFont()); + ui->signatureIn_VM->setFont(GUIUtil::bitcoinAddressFont()); +} + +SignVerifyMessageDialog::~SignVerifyMessageDialog() +{ + delete ui; +} + +void SignVerifyMessageDialog::setModel(WalletModel *model) +{ + this->model = model; +} + +void SignVerifyMessageDialog::setAddress_SM(QString address) +{ + ui->addressIn_SM->setText(address); + ui->messageIn_SM->setFocus(); +} + +void SignVerifyMessageDialog::setAddress_VM(QString address) +{ + ui->addressIn_VM->setText(address); + ui->messageIn_VM->setFocus(); +} + +void SignVerifyMessageDialog::showTab_SM(bool fShow) +{ + ui->tabWidget->setCurrentIndex(0); + + if (fShow) + this->show(); +} + +void SignVerifyMessageDialog::showTab_VM(bool fShow) +{ + ui->tabWidget->setCurrentIndex(1); + if (fShow) + this->show(); +} + +void SignVerifyMessageDialog::on_addressBookButton_SM_clicked() +{ + if (model && model->getAddressTableModel()) + { + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this); + dlg.setModel(model->getAddressTableModel()); + if (dlg.exec()) + { + setAddress_SM(dlg.getReturnValue()); + } + } +} + +void SignVerifyMessageDialog::on_pasteButton_SM_clicked() +{ + setAddress_SM(QApplication::clipboard()->text()); +} + +void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() +{ + /* Clear old signature to ensure users don't get confused on error with an old signature displayed */ + ui->signatureOut_SM->clear(); + + CBitcoinAddress addr(ui->addressIn_SM->text().toStdString()); + if (!addr.IsValid()) + { + ui->addressIn_SM->setValid(false); + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + { + ui->addressIn_SM->setValid(false); + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + + WalletModel::UnlockContext ctx(model->requestUnlock()); + if (!ctx.isValid()) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("Wallet unlock was canceled.")); + return; + } + + CKey key; + if (!pwalletMain->GetKey(keyID, key)) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("Private key for the entered address is not available.")); + return; + } + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->messageIn_SM->document()->toPlainText().toStdString(); + + std::vector<unsigned char> vchSig; + if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>")); + return; + } + + ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }"); + ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>")); + + ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size()))); +} + +void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked() +{ + QApplication::clipboard()->setText(ui->signatureOut_SM->text()); +} + +void SignVerifyMessageDialog::on_clearButton_SM_clicked() +{ + ui->addressIn_SM->clear(); + ui->messageIn_SM->clear(); + ui->signatureOut_SM->clear(); + ui->statusLabel_SM->clear(); + + ui->addressIn_SM->setFocus(); +} + +void SignVerifyMessageDialog::on_addressBookButton_VM_clicked() +{ + if (model && model->getAddressTableModel()) + { + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this); + dlg.setModel(model->getAddressTableModel()); + if (dlg.exec()) + { + setAddress_VM(dlg.getReturnValue()); + } + } +} + +void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked() +{ + CBitcoinAddress addr(ui->addressIn_VM->text().toStdString()); + if (!addr.IsValid()) + { + ui->addressIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + { + ui->addressIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + + bool fInvalid = false; + std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid); + + if (fInvalid) + { + ui->signatureIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again.")); + return; + } + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->messageIn_VM->document()->toPlainText().toStdString(); + + CKey key; + if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) + { + ui->signatureIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again.")); + return; + } + + if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr)) + { + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")); + return; + } + + ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }"); + ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>")); +} + +void SignVerifyMessageDialog::on_clearButton_VM_clicked() +{ + ui->addressIn_VM->clear(); + ui->signatureIn_VM->clear(); + ui->messageIn_VM->clear(); + ui->statusLabel_VM->clear(); + + ui->addressIn_VM->setFocus(); +} + +bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn) + { + if (ui->tabWidget->currentIndex() == 0) + { + /* Clear status message on focus change */ + ui->statusLabel_SM->clear(); + + /* Select generated signature */ + if (object == ui->signatureOut_SM) + { + ui->signatureOut_SM->selectAll(); + return true; + } + } + else if (ui->tabWidget->currentIndex() == 1) + { + /* Clear status message on focus change */ + ui->statusLabel_VM->clear(); + } + } + return QDialog::eventFilter(object, event); +} diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h new file mode 100644 index 0000000000..5569c8bf33 --- /dev/null +++ b/src/qt/signverifymessagedialog.h @@ -0,0 +1,49 @@ +#ifndef SIGNVERIFYMESSAGEDIALOG_H +#define SIGNVERIFYMESSAGEDIALOG_H + +#include <QDialog> + +namespace Ui { + class SignVerifyMessageDialog; +} +class WalletModel; + +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE + +class SignVerifyMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SignVerifyMessageDialog(QWidget *parent = 0); + ~SignVerifyMessageDialog(); + + void setModel(WalletModel *model); + void setAddress_SM(QString address); + void setAddress_VM(QString address); + + void showTab_SM(bool fShow); + void showTab_VM(bool fShow); + +protected: + bool eventFilter(QObject *object, QEvent *event); + +private: + Ui::SignVerifyMessageDialog *ui; + WalletModel *model; + +private slots: + /* sign message */ + void on_addressBookButton_SM_clicked(); + void on_pasteButton_SM_clicked(); + void on_signMessageButton_SM_clicked(); + void on_copySignatureButton_SM_clicked(); + void on_clearButton_SM_clicked(); + /* verify message */ + void on_addressBookButton_VM_clicked(); + void on_verifyMessageButton_VM_clicked(); + void on_clearButton_VM_clicked(); +}; + +#endif // SIGNVERIFYMESSAGEDIALOG_H diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 70c20be0ea..a281c39ca5 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -59,7 +59,7 @@ void URITests::uriTests() QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); - // We currently dont implement the message paramenter (ok, yea, we break spec...) + // We currently don't implement the message parameter (ok, yea, we break spec...) uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index dc0f28de92..3e7eca59ca 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -9,16 +9,12 @@ #include "ui_interface.h" #include "base58.h" -#include <QString> - -using namespace std; - QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { if (!wtx.IsFinal()) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) - return tr("Open for %1 blocks").arg(nBestHeight - wtx.nLockTime); + return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } @@ -26,7 +22,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { int nDepth = wtx.GetDepthInMainChain(); if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) - return tr("%1/offline?").arg(nDepth); + return tr("%1/offline").arg(nDepth); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); else @@ -48,33 +44,31 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; - strHTML += tr("<b>Status:</b> ") + FormatTxStatus(wtx); + strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) { if (nRequests == 0) strHTML += tr(", has not been successfully broadcast yet"); - else if (nRequests == 1) - strHTML += tr(", broadcast through %1 node").arg(nRequests); - else - strHTML += tr(", broadcast through %1 nodes").arg(nRequests); + else if (nRequests > 0) + strHTML += tr(", broadcast through %n node(s)", "", nRequests); } strHTML += "<br>"; - strHTML += tr("<b>Date:</b> ") + (nTime ? GUIUtil::dateTimeStr(nTime) : QString("")) + "<br>"; + strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.IsCoinBase()) { - strHTML += tr("<b>Source:</b> Generated<br>"); + strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (!wtx.mapValue["from"].empty()) { // Online transaction if (!wtx.mapValue["from"].empty()) - strHTML += tr("<b>From:</b> ") + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; + strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { @@ -91,13 +85,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { if (wallet->mapAddressBook.count(address)) { - strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>"; - strHTML += tr("<b>To:</b> "); + strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; + strHTML += "<b>" + tr("To") + ":</b> "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); if (!wallet->mapAddressBook[address].empty()) - strHTML += tr(" (yours, label: ") + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; + strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; else - strHTML += tr(" (yours)"); + strHTML += " (" + tr("own address") + ")"; strHTML += "<br>"; } } @@ -110,12 +104,11 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) // // To // - string strAddress; if (!wtx.mapValue["to"].empty()) { // Online transaction - strAddress = wtx.mapValue["to"]; - strHTML += tr("<b>To:</b> "); + std::string strAddress = wtx.mapValue["to"]; + strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = CBitcoinAddress(strAddress).Get(); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; @@ -133,13 +126,11 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) int64 nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) nUnmatured += wallet->GetCredit(txout); - strHTML += tr("<b>Credit:</b> "); + strHTML += "<b>" + tr("Credit") + ":</b> "; if (wtx.IsInMainChain()) - strHTML += tr("(%1 matures in %2 more blocks)") - .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)) - .arg(wtx.GetBlocksToMaturity()); + strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; else - strHTML += tr("(not accepted)"); + strHTML += "(" + tr("not accepted") + ")"; strHTML += "<br>"; } else if (nNet > 0) @@ -147,7 +138,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) // // Credit // - strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>"; + strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>"; } else { @@ -175,7 +166,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { - strHTML += tr("<b>To:</b> "); + strHTML += "<b>" + tr("To") + ":</b> "; if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); @@ -183,7 +174,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) } } - strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>"; + strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>"; } if (fAllToMe) @@ -191,13 +182,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) // Payment to self int64 nChange = wtx.GetChange(); int64 nValue = nCredit - nChange; - strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>"; - strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>"; + strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>"; + strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>"; } int64 nTxFee = nDebit - wtx.GetValueOut(); if (nTxFee > 0) - strHTML += tr("<b>Transaction fee:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-nTxFee) + "<br>"; + strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>"; } else { @@ -206,47 +197,47 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>"; + strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>"; + strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>"; } } - strHTML += tr("<b>Net amount:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,nNet, true) + "<br>"; + strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>"; // // Message // if (!wtx.mapValue["message"].empty()) - strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>"; + strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>"; if (!wtx.mapValue["comment"].empty()) - strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>"; + strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>"; - strHTML += QString("<b>") + tr("Transaction ID:") + "</b> " + wtx.GetHash().ToString().c_str() + "<br>"; + strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>"; if (wtx.IsCoinBase()) - strHTML += QString("<br>") + tr("Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, it's state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>"; + strHTML += "<br>" + tr("Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>"; // // Debug view // if (fDebug) { - strHTML += "<hr><br>Debug information<br><br>"; + strHTML += "<hr><br>" + tr("Debug information") + "<br><br>"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "<b>Debit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>"; + strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>"; + strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>"; - strHTML += "<br><b>Transaction:</b><br>"; + strHTML += "<br><b>" + tr("Transaction") + ":</b><br>"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); CTxDB txdb("r"); // To fetch source txouts - strHTML += "<br><b>Inputs:</b>"; + strHTML += "<br><b>" + tr("Inputs") + ":</b>"; strHTML += "<ul>"; { @@ -269,12 +260,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); } - strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue); - strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>"; + strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue); + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>"; } } } } + strHTML += "</ul>"; } diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a0e7dd4e77..1370a30ce4 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -160,6 +160,8 @@ void TransactionView::setModel(WalletModel *model) transactionProxyModel = new TransactionFilterProxy(this); transactionProxyModel->setSourceModel(model->getTransactionTableModel()); transactionProxyModel->setDynamicSortFilter(true); + transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); transactionProxyModel->setSortRole(Qt::EditRole); diff --git a/src/qt/verifymessagedialog.cpp b/src/qt/verifymessagedialog.cpp deleted file mode 100644 index 92f58328a4..0000000000 --- a/src/qt/verifymessagedialog.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "verifymessagedialog.h" -#include "ui_verifymessagedialog.h" - -#include <string> -#include <vector> - -#include <QDialog> -#include <QLabel> -#include <QLineEdit> -#include <QPlainTextEdit> -#include <QPushButton> - -#include "main.h" -#include "wallet.h" -#include "walletmodel.h" -#include "guiutil.h" -#include "base58.h" - -VerifyMessageDialog::VerifyMessageDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::VerifyMessageDialog) -{ - ui->setupUi(this); - -#if (QT_VERSION >= 0x040700) - /* Do not move this to the XML file, Qt before 4.7 will choke on it */ - ui->lnAddress->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); - ui->lnSig->setPlaceholderText(tr("Enter Bitcoin signature")); -#endif - - GUIUtil::setupAddressWidget(ui->lnAddress, this); - ui->lnAddress->installEventFilter(this); - - ui->lnSig->setFont(GUIUtil::bitcoinAddressFont()); - - ui->lnAddress->setFocus(); -} - -VerifyMessageDialog::~VerifyMessageDialog() -{ - delete ui; -} - -void VerifyMessageDialog::on_verifyMessage_clicked() -{ - CBitcoinAddress addr(ui->lnAddress->text().toStdString()); - if (!addr.IsValid()) - { - ui->lnAddress->setValid(false); - ui->lblStatus->setStyleSheet("QLabel { color: red; }"); - ui->lblStatus->setText(tr("\"%1\" is not a valid address.").arg(ui->lnAddress->text()) + QString(" ") + tr("Please check the address and try again.")); - return; - } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) - { - ui->lnAddress->setValid(false); - ui->lblStatus->setStyleSheet("QLabel { color: red; }"); - ui->lblStatus->setText(tr("\"%1\" does not refer to a key.").arg(ui->lnAddress->text()) + QString(" ") + tr("Please check the address and try again.")); - return; - } - - bool fInvalid = false; - std::vector<unsigned char> vchSig = DecodeBase64(ui->lnSig->text().toStdString().c_str(), &fInvalid); - - if (fInvalid) - { - ui->lnSig->setValid(false); - ui->lblStatus->setStyleSheet("QLabel { color: red; }"); - ui->lblStatus->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again.")); - return; - } - - CDataStream ss(SER_GETHASH, 0); - ss << strMessageMagic; - ss << ui->edMessage->document()->toPlainText().toStdString(); - - CKey key; - if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) - { - ui->lnSig->setValid(false); - ui->lblStatus->setStyleSheet("QLabel { color: red; }"); - ui->lblStatus->setText(tr("The signature did not match the message digest.")+ QString(" ") + tr("Please check the signature and try again.")); - return; - } - - if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr)) - { - ui->lblStatus->setStyleSheet("QLabel { color: red; }"); - ui->lblStatus->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")); - return; - } - - ui->lblStatus->setStyleSheet("QLabel { color: green; }"); - ui->lblStatus->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>")); -} - -void VerifyMessageDialog::on_clearButton_clicked() -{ - ui->lnAddress->clear(); - ui->lnSig->clear(); - ui->edMessage->clear(); - ui->lblStatus->clear(); - - ui->edMessage->setFocus(); -} - -bool VerifyMessageDialog::eventFilter(QObject *object, QEvent *event) -{ - if (object == ui->lnAddress && (event->type() == QEvent::MouseButtonPress || - event->type() == QEvent::FocusIn)) - { - // set lnAddress to valid, as QEvent::FocusIn would not reach QValidatedLineEdit::focusInEvent - ui->lnAddress->setValid(true); - ui->lnAddress->selectAll(); - return true; - } - return QDialog::eventFilter(object, event); -} diff --git a/src/qt/verifymessagedialog.h b/src/qt/verifymessagedialog.h deleted file mode 100644 index 0bed442d4c..0000000000 --- a/src/qt/verifymessagedialog.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef VERIFYMESSAGEDIALOG_H -#define VERIFYMESSAGEDIALOG_H - -#include <QDialog> - -namespace Ui { - class VerifyMessageDialog; -} -class AddressTableModel; - -QT_BEGIN_NAMESPACE -QT_END_NAMESPACE - -class VerifyMessageDialog : public QDialog -{ - Q_OBJECT - -public: - explicit VerifyMessageDialog(QWidget *parent); - ~VerifyMessageDialog(); - -protected: - bool eventFilter(QObject *object, QEvent *event); - -private: - Ui::VerifyMessageDialog *ui; - -private slots: - void on_verifyMessage_clicked(); - void on_clearButton_clicked(); -}; - -#endif // VERIFYMESSAGEDIALOG_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 9245f774a4..3568616cd3 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -10,17 +10,24 @@ #include "base58.h" #include <QSet> +#include <QTimer> WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), transactionTableModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), cachedNumTransactions(0), - cachedEncryptionStatus(Unencrypted) + cachedEncryptionStatus(Unencrypted), + cachedNumBlocks(0) { addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); + // This timer will be fired repeatedly to update the balance + pollTimer = new QTimer(this); + connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); + pollTimer->start(MODEL_UPDATE_DELAY); + subscribeToCoreSignals(); } @@ -62,27 +69,45 @@ void WalletModel::updateStatus() emit encryptionStatusChanged(newEncryptionStatus); } -void WalletModel::updateTransaction(const QString &hash, int status) +void WalletModel::pollBalanceChanged() { - if(transactionTableModel) - transactionTableModel->updateTransaction(hash, status); + if(nBestHeight != cachedNumBlocks) + { + // Balance and number of transactions might have changed + cachedNumBlocks = nBestHeight; + checkBalanceChanged(); + } +} - // Balance and number of transactions might have changed +void WalletModel::checkBalanceChanged() +{ qint64 newBalance = getBalance(); qint64 newUnconfirmedBalance = getUnconfirmedBalance(); qint64 newImmatureBalance = getImmatureBalance(); - int newNumTransactions = getNumTransactions(); if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + { + cachedBalance = newBalance; + cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedImmatureBalance = newImmatureBalance; emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); + } +} + +void WalletModel::updateTransaction(const QString &hash, int status) +{ + if(transactionTableModel) + transactionTableModel->updateTransaction(hash, status); + // Balance and number of transactions might have changed + checkBalanceChanged(); + + int newNumTransactions = getNumTransactions(); if(cachedNumTransactions != newNumTransactions) + { + cachedNumTransactions = newNumTransactions; emit numTransactionsChanged(newNumTransactions); - - cachedBalance = newBalance; - cachedUnconfirmedBalance = newUnconfirmedBalance; - cachedImmatureBalance = newImmatureBalance; - cachedNumTransactions = newNumTransactions; + } } void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, int status) diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index c973c5cf53..62558a49df 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -10,6 +10,10 @@ class AddressTableModel; class TransactionTableModel; class CWallet; +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + class SendCoinsRecipient { public: @@ -120,9 +124,14 @@ private: qint64 cachedImmatureBalance; qint64 cachedNumTransactions; EncryptionStatus cachedEncryptionStatus; + int cachedNumBlocks; + + QTimer *pollTimer; void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); + void checkBalanceChanged(); + signals: // Signal that balance in wallet changed void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); @@ -148,6 +157,8 @@ public slots: void updateTransaction(const QString &hash, int status); /* New, updated or removed address book entry */ void updateAddressBook(const QString &address, const QString &label, bool isMine, int status); + /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ + void pollBalanceChanged(); }; diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp new file mode 100644 index 0000000000..f0038dea9f --- /dev/null +++ b/src/rpcnet.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2009-2012 Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "net.h" +#include "bitcoinrpc.h" + +using namespace json_spirit; +using namespace std; + +Value getconnectioncount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getconnectioncount\n" + "Returns the number of connections to other nodes."); + + LOCK(cs_vNodes); + return (int)vNodes.size(); +} + +static void CopyNodeStats(std::vector<CNodeStats>& vstats) +{ + vstats.clear(); + + LOCK(cs_vNodes); + vstats.reserve(vNodes.size()); + BOOST_FOREACH(CNode* pnode, vNodes) { + CNodeStats stats; + pnode->copyStats(stats); + vstats.push_back(stats); + } +} + +Value getpeerinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getpeerinfo\n" + "Returns data about each connected network node."); + + vector<CNodeStats> vstats; + CopyNodeStats(vstats); + + Array ret; + + BOOST_FOREACH(const CNodeStats& stats, vstats) { + Object obj; + + obj.push_back(Pair("addr", stats.addrName)); + obj.push_back(Pair("services", strprintf("%08"PRI64x, stats.nServices))); + obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); + obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); + obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected)); + obj.push_back(Pair("version", stats.nVersion)); + obj.push_back(Pair("subver", stats.strSubVer)); + obj.push_back(Pair("inbound", stats.fInbound)); + obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime)); + obj.push_back(Pair("startingheight", stats.nStartingHeight)); + obj.push_back(Pair("banscore", stats.nMisbehavior)); + + ret.push_back(obj); + } + + return ret; +} + diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp new file mode 100644 index 0000000000..66e4d85f37 --- /dev/null +++ b/src/rpcrawtransaction.cpp @@ -0,0 +1,504 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <boost/assign/list_of.hpp> + +#include "base58.h" +#include "bitcoinrpc.h" +#include "db.h" +#include "init.h" +#include "main.h" +#include "net.h" +#include "wallet.h" + +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace json_spirit; + +// These are all in bitcoinrpc.cpp: +extern Object JSONRPCError(int code, const string& message); +extern int64 AmountFromValue(const Value& value); +extern Value ValueFromAmount(int64 amount); +extern std::string HelpRequiringPassphrase(); +extern void EnsureWalletIsUnlocked(); + +void +ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) +{ + txnouttype type; + vector<CTxDestination> addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD))); + return; + } + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + out.push_back(Pair("addresses", a)); +} + +void +TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + 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 + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (boost::int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + 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)); + } + } +} + +Value getrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction <txid> [verbose=0]\n" + "If verbose=0, returns a string that is\n" + "serialized, hex-encoded data for <txid>.\n" + "If verbose is non-zero, returns an Object\n" + "with information about <txid>."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + + bool fVerbose = false; + if (params.size() > 1) + fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(-5, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "listunspent [minconf=1] [maxconf=999999]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + RPCTypeCheck(params, list_of(int_type)(int_type)); + + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + int nMaxDepth = 999999; + if (params.size() > 1) + nMaxDepth = params[1].get_int(); + + Array results; + vector<COutput> vecOutputs; + pwalletMain->AvailableCoins(vecOutputs, false); + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) + continue; + + int64 nValue = out.tx->vout[out.i].nValue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + Object entry; + entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); + entry.push_back(Pair("vout", out.i)); + entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end()))); + entry.push_back(Pair("amount",ValueFromAmount(nValue))); + entry.push_back(Pair("confirmations",out.nDepth)); + results.push_back(entry); + } + + return results; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\n" + "Returns hex-encoded raw transaction.\n" + "Note that the transaction's inputs are not signed, and\n" + "it is not stored in the wallet or transmitted to the network."); + + RPCTypeCheck(params, list_of(array_type)(obj_type)); + + Array inputs = params[0].get_array(); + Object sendTo = params[1].get_obj(); + + CTransaction rawTx; + + BOOST_FOREACH(Value& input, inputs) + { + const Object& o = input.get_obj(); + + const Value& txid_v = find_value(o, "txid"); + if (txid_v.type() != str_type) + throw JSONRPCError(-8, "Invalid parameter, missing txid key"); + string txid = txid_v.get_str(); + if (!IsHex(txid)) + throw JSONRPCError(-8, "Invalid parameter, expected hex txid"); + + const Value& vout_v = find_value(o, "vout"); + if (vout_v.type() != int_type) + throw JSONRPCError(-8, "Invalid parameter, missing vout key"); + int nOutput = vout_v.get_int(); + if (nOutput < 0) + throw JSONRPCError(-8, "Invalid parameter, vout must be positive"); + + CTxIn in(COutPoint(uint256(txid), nOutput)); + rawTx.vin.push_back(in); + } + + set<CBitcoinAddress> setAddress; + BOOST_FOREACH(const Pair& s, sendTo) + { + CBitcoinAddress address(s.name_); + if (!address.IsValid()) + throw JSONRPCError(-5, string("Invalid Bitcoin address:")+s.name_); + + if (setAddress.count(address)) + throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_); + setAddress.insert(address); + + CScript scriptPubKey; + scriptPubKey.SetDestination(address.Get()); + int64 nAmount = AmountFromValue(s.value_); + + CTxOut out(nAmount, scriptPubKey); + rawTx.vout.push_back(out); + } + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << rawTx; + return HexStr(ss.begin(), ss.end()); +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction <hex string>\n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + + RPCTypeCheck(params, list_of(str_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "Second optional argument is an array of previous transaction outputs that\n" + "this transaction depends on but may not yet be in the blockchain.\n" + "Third optional argument is an array of base58-encoded private\n" + "keys that, if given, will be the only keys used to sign the transaction.\n" + "Fourth option is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + + HelpRequiringPassphrase()); + + if (params.size() < 3) + EnsureWalletIsUnlocked(); + + RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)); + + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + vector<CTransaction> txVariants; + while (!ssData.empty()) + { + try { + CTransaction tx; + ssData >> tx; + txVariants.push_back(tx); + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + } + + if (txVariants.empty()) + throw JSONRPCError(-22, "Missing transaction"); + + // mergedTx will end up with all the signatures; it + // starts as a clone of the rawtx: + CTransaction mergedTx(txVariants[0]); + bool fComplete = true; + + // Fetch previous transactions (inputs): + map<COutPoint, CScript> mapPrevOut; + { + MapPrevTx mapPrevTx; + CTxDB txdb("r"); + map<uint256, CTxIndex> unused; + bool fInvalid; + mergedTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid); + + // Copy results into mapPrevOut: + BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) + { + const uint256& prevHash = txin.prevout.hash; + if (mapPrevTx.count(prevHash)) + mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey; + } + } + + // Add previous txouts given in the RPC call: + if (params.size() > 1) + { + Array prevTxs = params[1].get_array(); + BOOST_FOREACH(Value& p, prevTxs) + { + if (p.type() != obj_type) + throw JSONRPCError(-22, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); + + Object prevOut = p.get_obj(); + + RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)); + + string txidHex = find_value(prevOut, "txid").get_str(); + if (!IsHex(txidHex)) + throw JSONRPCError(-22, "txid must be hexadecimal"); + uint256 txid; + txid.SetHex(txidHex); + + int nOut = find_value(prevOut, "vout").get_int(); + if (nOut < 0) + throw JSONRPCError(-22, "vout must be positive"); + + string pkHex = find_value(prevOut, "scriptPubKey").get_str(); + if (!IsHex(pkHex)) + throw JSONRPCError(-22, "scriptPubKey must be hexadecimal"); + vector<unsigned char> pkData(ParseHex(pkHex)); + CScript scriptPubKey(pkData.begin(), pkData.end()); + + COutPoint outpoint(txid, nOut); + if (mapPrevOut.count(outpoint)) + { + // Complain if scriptPubKey doesn't match + if (mapPrevOut[outpoint] != scriptPubKey) + { + string err("Previous output scriptPubKey mismatch:\n"); + err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+ + scriptPubKey.ToString(); + throw JSONRPCError(-22, err); + } + } + else + mapPrevOut[outpoint] = scriptPubKey; + } + } + + bool fGivenKeys = false; + CBasicKeyStore tempKeystore; + if (params.size() > 2) + { + fGivenKeys = true; + Array keys = params[2].get_array(); + BOOST_FOREACH(Value k, keys) + { + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(k.get_str()); + if (!fGood) + throw JSONRPCError(-5,"Invalid private key"); + CKey key; + bool fCompressed; + CSecret secret = vchSecret.GetSecret(fCompressed); + key.SetSecret(secret, fCompressed); + tempKeystore.AddKey(key); + } + } + const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain); + + int nHashType = SIGHASH_ALL; + if (params.size() > 3) + { + static map<string, int> mapSigHashValues = + boost::assign::map_list_of + (string("ALL"), int(SIGHASH_ALL)) + (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) + (string("NONE"), int(SIGHASH_NONE)) + (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) + (string("SINGLE"), int(SIGHASH_SINGLE)) + (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) + ; + string strHashType = params[3].get_str(); + if (mapSigHashValues.count(strHashType)) + nHashType = mapSigHashValues[strHashType]; + else + throw JSONRPCError(-8, "Invalid sighash param"); + } + + // Sign what we can: + for (unsigned int i = 0; i < mergedTx.vin.size(); i++) + { + CTxIn& txin = mergedTx.vin[i]; + if (mapPrevOut.count(txin.prevout) == 0) + { + fComplete = false; + continue; + } + const CScript& prevPubKey = mapPrevOut[txin.prevout]; + + txin.scriptSig.clear(); + SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + + // ... and merge in other signatures: + BOOST_FOREACH(const CTransaction& txv, txVariants) + { + txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); + } + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, true, 0)) + fComplete = false; + } + + Object result; + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << mergedTx; + result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end()))); + result.push_back(Pair("complete", fComplete)); + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction <hex string>\n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + + RPCTypeCheck(params, list_of(str_type)); + + // parse hex string from parameter + vector<unsigned char> txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + + // deserialize binary data stream + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "TX decode failed"); + } + uint256 hashTx = tx.GetHash(); + + // See if the transaction is already in a block + // or in the memory pool: + CTransaction existingTx; + uint256 hashBlock = 0; + if (GetTransaction(hashTx, existingTx, hashBlock)) + { + if (hashBlock != 0) + throw JSONRPCError(-5, string("transaction already in block ")+hashBlock.GetHex()); + // Not in block, but already in the memory pool; will drop + // through to re-relay it. + } + else + { + // push to local node + CTxDB txdb("r"); + if (!tx.AcceptToMemoryPool(txdb)) + throw JSONRPCError(-22, "TX rejected"); + + SyncWithWallets(tx, NULL, true); + } + RelayMessage(CInv(MSG_TX, hashTx), tx); + + return hashTx.GetHex(); +} diff --git a/src/script.cpp b/src/script.cpp index 2e1e1ad7de..c29648c2bc 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1331,15 +1331,12 @@ bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint2 { int nSigned = 0; int nRequired = multisigdata.front()[0]; - for (vector<valtype>::const_iterator it = multisigdata.begin()+1; it != multisigdata.begin()+multisigdata.size()-1; it++) + for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++) { - const valtype& pubkey = *it; + const valtype& pubkey = multisigdata[i]; CKeyID keyID = CPubKey(pubkey).GetID(); if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) - { ++nSigned; - if (nSigned == nRequired) break; - } } return nSigned==nRequired; } @@ -1590,19 +1587,17 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C } -bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType) +bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType) { assert(nIn < txTo.vin.size()); CTxIn& txin = txTo.vin[nIn]; - assert(txin.prevout.n < txFrom.vout.size()); - const CTxOut& txout = txFrom.vout[txin.prevout.n]; // Leave out the signature from the hash, since a signature can't sign itself. // The checksig op will also drop the signatures from its hash. - uint256 hash = SignatureHash(txout.scriptPubKey, txTo, nIn, nHashType); + uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType); txnouttype whichType; - if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig, whichType)) + if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType)) return false; if (whichType == TX_SCRIPTHASH) @@ -1614,21 +1609,28 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTrans // Recompute txn hash using subscript in place of scriptPubKey: uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType); + txnouttype subType; - if (!Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType)) - return false; - if (subType == TX_SCRIPTHASH) - return false; - txin.scriptSig << static_cast<valtype>(subscript); // Append serialized subscript + bool fSolved = + Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH; + // Append serialized subscript whether or not it is completely signed: + txin.scriptSig << static_cast<valtype>(subscript); + if (!fSolved) return false; } // Test solution - if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, true, 0)) - return false; - - return true; + return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, true, 0); } +bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType) +{ + assert(nIn < txTo.vin.size()); + CTxIn& txin = txTo.vin[nIn]; + assert(txin.prevout.n < txFrom.vout.size()); + const CTxOut& txout = txFrom.vout[txin.prevout.n]; + + return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); +} bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType) { @@ -1641,10 +1643,129 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig if (txin.prevout.hash != txFrom.GetHash()) return false; - if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, fValidatePayToScriptHash, nHashType)) - return false; + return VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, fValidatePayToScriptHash, nHashType); +} - return true; +static CScript PushAll(const vector<valtype>& values) +{ + CScript result; + BOOST_FOREACH(const valtype& v, values) + result << v; + return result; +} + +static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const vector<valtype>& vSolutions, + vector<valtype>& sigs1, vector<valtype>& sigs2) +{ + // Combine all the signatures we've got: + set<valtype> allsigs; + BOOST_FOREACH(const valtype& v, sigs1) + { + if (!v.empty()) + allsigs.insert(v); + } + BOOST_FOREACH(const valtype& v, sigs2) + { + if (!v.empty()) + allsigs.insert(v); + } + + // Build a map of pubkey -> signature by matching sigs to pubkeys: + assert(vSolutions.size() > 1); + unsigned int nSigsRequired = vSolutions.front()[0]; + unsigned int nPubKeys = vSolutions.size()-2; + map<valtype, valtype> sigs; + BOOST_FOREACH(const valtype& sig, allsigs) + { + for (unsigned int i = 0; i < nPubKeys; i++) + { + const valtype& pubkey = vSolutions[i+1]; + if (sigs.count(pubkey)) + continue; // Already got a sig for this pubkey + + if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0)) + { + sigs[pubkey] = sig; + break; + } + } + } + // Now build a merged CScript: + unsigned int nSigsHave = 0; + CScript result; result << OP_0; // pop-one-too-many workaround + for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) + { + if (sigs.count(vSolutions[i+1])) + { + result << sigs[vSolutions[i+1]]; + ++nSigsHave; + } + } + // Fill any missing with OP_0: + for (unsigned int i = nSigsHave; i < nSigsRequired; i++) + result << OP_0; + + return result; +} + +static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const txnouttype txType, const vector<valtype>& vSolutions, + vector<valtype>& sigs1, vector<valtype>& sigs2) +{ + switch (txType) + { + case TX_NONSTANDARD: + // Don't know anything about this, assume bigger one is correct: + if (sigs1.size() >= sigs2.size()) + return PushAll(sigs1); + return PushAll(sigs2); + case TX_PUBKEY: + case TX_PUBKEYHASH: + // Signatures are bigger than placeholders or empty scripts: + if (sigs1.empty() || sigs1[0].empty()) + return PushAll(sigs2); + return PushAll(sigs1); + case TX_SCRIPTHASH: + if (sigs1.empty() || sigs1.back().empty()) + return PushAll(sigs2); + else if (sigs2.empty() || sigs2.back().empty()) + return PushAll(sigs1); + else + { + // Recurse to combine: + valtype spk = sigs1.back(); + CScript pubKey2(spk.begin(), spk.end()); + + txnouttype txType2; + vector<vector<unsigned char> > vSolutions2; + Solver(pubKey2, txType2, vSolutions2); + sigs1.pop_back(); + sigs2.pop_back(); + CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2); + result << spk; + return result; + } + case TX_MULTISIG: + return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2); + } + + return CScript(); +} + +CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const CScript& scriptSig1, const CScript& scriptSig2) +{ + txnouttype txType; + vector<vector<unsigned char> > vSolutions; + Solver(scriptPubKey, txType, vSolutions); + + vector<valtype> stack1; + EvalScript(stack1, scriptSig1, CTransaction(), 0, 0); + vector<valtype> stack2; + EvalScript(stack2, scriptSig2, CTransaction(), 0, 0); + + return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); } unsigned int CScript::GetSigOpCount(bool fAccurate) const diff --git a/src/script.h b/src/script.h index d490cd1824..f4db112dd6 100644 --- a/src/script.h +++ b/src/script.h @@ -452,7 +452,7 @@ public: memcpy(&nSize, &pc[0], 4); pc += 4; } - if (end() - pc < nSize) + if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize) return false; if (pvchRet) pvchRet->assign(pc, pc + nSize); @@ -591,7 +591,14 @@ bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet); +bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + bool fValidatePayToScriptHash, int nHashType); bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType); +// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders, +// combine them intelligently and return the result. +CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2); + #endif diff --git a/src/serialize.h b/src/serialize.h index 349a40bfe8..abc4f04a0d 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -809,7 +809,8 @@ public: void insert(iterator it, const_iterator first, const_iterator last) { - if (it == vch.begin() + nReadPos && last - first <= nReadPos) + assert(last - first >= 0); + if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) { // special case for inserting at the front when there's room nReadPos -= (last - first); @@ -821,7 +822,8 @@ public: void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last) { - if (it == vch.begin() + nReadPos && last - first <= nReadPos) + assert(last - first >= 0); + if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) { // special case for inserting at the front when there's room nReadPos -= (last - first); @@ -834,7 +836,8 @@ public: #if !defined(_MSC_VER) || _MSC_VER >= 1300 void insert(iterator it, const char* first, const char* last) { - if (it == vch.begin() + nReadPos && last - first <= nReadPos) + assert(last - first >= 0); + if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) { // special case for inserting at the front when there's room nReadPos -= (last - first); diff --git a/src/sync.cpp b/src/sync.cpp index dbd9ebdaee..54ad7de4e6 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -24,7 +24,7 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine) // --> may result in deadlock between the two threads, depending on when they run. // Solution implemented here: // Keep track of pairs of locks: (A before B), (A before C), etc. -// Complain if any thread trys to lock in a different order. +// Complain if any thread tries to lock in a different order. // struct CLockLocation diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 5712b4a1b1..3c6039541e 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -1,12 +1,202 @@ #include <boost/test/unit_test.hpp> +#include "init.h" +#include "main.h" #include "uint256.h" #include "util.h" +#include "wallet.h" extern void SHA256Transform(void* pstate, void* pinput, const void* pinit); BOOST_AUTO_TEST_SUITE(miner_tests) +static +struct { + unsigned char extranonce; + unsigned int nonce; +} blockinfo[] = { + {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5}, + {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84}, + {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4}, + {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa}, + {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb}, + {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406}, + {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38}, + {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9}, + {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7}, + {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34}, + {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c}, + {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f}, + {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81}, + {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78}, + {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c}, + {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049}, + {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169}, + {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10}, + {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d}, + {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323}, + {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6}, + {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408}, + {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602}, + {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459}, + {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668}, + {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce}, + {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e}, + {2, 0xbbbeb305}, {2, 0xfe1c810a}, +}; + +// NOTE: These tests rely on CreateNewBlock doing its own self-validation! +BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) +{ + CReserveKey reservekey(pwalletMain); + CBlock *pblock; + CTransaction tx; + CScript script; + uint256 hash; + + // Simple block creation, nothing special yet: + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + + // We can't make transactions until we have inputs + // Therefore, load 100 blocks :) + std::vector<CTransaction*>txFirst; + for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) + { + pblock->nTime = pindexBest->GetMedianTimePast()+1; + pblock->vtx[0].vin[0].scriptSig = CScript(); + pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce); + pblock->vtx[0].vin[0].scriptSig.push_back(pindexBest->nHeight); + pblock->vtx[0].vout[0].scriptPubKey = CScript(); + if (txFirst.size() < 2) + txFirst.push_back(new CTransaction(pblock->vtx[0])); + pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + pblock->nNonce = blockinfo[i].nonce; + assert(ProcessBlock(NULL, pblock)); + pblock->hashPrevBlock = pblock->GetHash(); + } + delete pblock; + + // Just to make sure we can still make simple blocks + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + + // block sigops > limit: 1000 CHECKMULTISIG + 1 + tx.vin.resize(1); + // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG + tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1; + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].prevout.n = 0; + tx.vout.resize(1); + tx.vout[0].nValue = 5000000000LL; + for (unsigned int i = 0; i < 1001; ++i) + { + tx.vout[0].nValue -= 1000000; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + tx.vin[0].prevout.hash = hash; + } + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // block size > limit + tx.vin[0].scriptSig = CScript(); + // 18 * (520char + DROP) + OP_1 = 9433 bytes + std::vector<unsigned char> vchData(520); + for (unsigned int i = 0; i < 18; ++i) + tx.vin[0].scriptSig << vchData << OP_DROP; + tx.vin[0].scriptSig << OP_1; + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vout[0].nValue = 5000000000LL; + for (unsigned int i = 0; i < 128; ++i) + { + tx.vout[0].nValue -= 10000000; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + tx.vin[0].prevout.hash = hash; + } + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // orphan in mempool + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // child with higher priority than parent + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vin[0].prevout.hash = txFirst[1]->GetHash(); + tx.vout[0].nValue = 4900000000LL; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + tx.vin[0].prevout.hash = hash; + tx.vin.resize(2); + tx.vin[1].scriptSig = CScript() << OP_1; + tx.vin[1].prevout.hash = txFirst[0]->GetHash(); + tx.vin[1].prevout.n = 0; + tx.vout[0].nValue = 5900000000LL; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // coinbase in mempool + tx.vin.resize(1); + tx.vin[0].prevout.SetNull(); + tx.vin[0].scriptSig = CScript() << OP_0 << OP_1; + tx.vout[0].nValue = 0; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // invalid (pre-p2sh) txn in mempool + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].prevout.n = 0; + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vout[0].nValue = 4900000000LL; + script = CScript() << OP_0; + tx.vout[0].scriptPubKey.SetDestination(script.GetID()); + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + tx.vin[0].prevout.hash = hash; + tx.vin[0].scriptSig = CScript() << (std::vector<unsigned char>)script; + tx.vout[0].nValue -= 1000000; + hash = tx.GetHash(); + mempool.addUnchecked(hash,tx); + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // double spend txn pair in mempool + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vout[0].nValue = 4900000000LL; + tx.vout[0].scriptPubKey = CScript() << OP_1; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + tx.vout[0].scriptPubKey = CScript() << OP_2; + hash = tx.GetHash(); + mempool.addUnchecked(hash, tx); + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + mempool.clear(); + + // subsidy changing + int nHeight = pindexBest->nHeight; + pindexBest->nHeight = 209999; + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + pindexBest->nHeight = 210000; + BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + delete pblock; + pindexBest->nHeight = nHeight; +} + BOOST_AUTO_TEST_CASE(sha256transform_equality) { unsigned int pSHA256InitState[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index ca5a1f1b12..64a6678a73 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -71,7 +71,7 @@ int static permute(int n) return ret; } -// Test that an mruset acts like a moving window, if no duplcate elements are added +// Test that an mruset acts like a moving window, if no duplicate elements are added BOOST_AUTO_TEST_CASE(mruset_window) { mruset<int> mru(MAX_SIZE); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 7a438e5d51..e6c00e39d8 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -34,9 +34,9 @@ BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture) rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor; // old, 65-byte-long: - const char* address1Hex = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"; + const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"; // new, compressed: - const char* address2Hex = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; + const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; Value v; CBitcoinAddress address; @@ -62,7 +62,7 @@ BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture) string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); - string short2(address1Hex+2, address1Hex+sizeof(address1Hex)); // first byte missing + string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index a30e3ccbc2..61d9a64eeb 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -328,5 +328,118 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0)); } +BOOST_AUTO_TEST_CASE(script_combineSigs) +{ + // Test the CombineSignatures function + CBasicKeyStore keystore; + vector<CKey> keys; + for (int i = 0; i < 3; i++) + { + CKey key; + key.MakeNewKey(i%2 == 1); + keys.push_back(key); + keystore.AddKey(key); + } + + CTransaction txFrom; + txFrom.vout.resize(1); + txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID()); + CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; + CTransaction txTo; + txTo.vin.resize(1); + txTo.vout.resize(1); + txTo.vin[0].prevout.n = 0; + txTo.vin[0].prevout.hash = txFrom.GetHash(); + CScript& scriptSig = txTo.vin[0].scriptSig; + txTo.vout[0].nValue = 1; + + CScript empty; + CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty); + BOOST_CHECK(combined.empty()); + + // Single signature case: + SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + CScript scriptSigCopy = scriptSig; + // Signing again will give a different, valid signature: + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + + // P2SH, single-signature case: + CScript pkSingle; pkSingle << keys[0].GetPubKey() << OP_CHECKSIG; + keystore.AddCScript(pkSingle); + scriptPubKey.SetDestination(pkSingle.GetID()); + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + scriptSigCopy = scriptSig; + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + // dummy scriptSigCopy with placeholder, should always choose non-placeholder: + scriptSigCopy = CScript() << OP_0 << static_cast<vector<unsigned char> >(pkSingle); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy); + BOOST_CHECK(combined == scriptSig); + + // Hardest case: Multisig 2-of-3 + scriptPubKey.SetMultisig(2, keys); + keystore.AddCScript(scriptPubKey); + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + + // A couple of partially-signed versions: + vector<unsigned char> sig1; + uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL); + BOOST_CHECK(keys[0].Sign(hash1, sig1)); + sig1.push_back(SIGHASH_ALL); + vector<unsigned char> sig2; + uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE); + BOOST_CHECK(keys[1].Sign(hash2, sig2)); + sig2.push_back(SIGHASH_NONE); + vector<unsigned char> sig3; + uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE); + BOOST_CHECK(keys[2].Sign(hash3, sig3)); + sig3.push_back(SIGHASH_SINGLE); + + // Not fussy about order (or even existence) of placeholders or signatures: + CScript partial1a = CScript() << OP_0 << sig1 << OP_0; + CScript partial1b = CScript() << OP_0 << OP_0 << sig1; + CScript partial2a = CScript() << OP_0 << sig2; + CScript partial2b = CScript() << sig2 << OP_0; + CScript partial3a = CScript() << sig3; + CScript partial3b = CScript() << OP_0 << OP_0 << sig3; + CScript partial3c = CScript() << OP_0 << sig3 << OP_0; + CScript complete12 = CScript() << OP_0 << sig1 << sig2; + CScript complete13 = CScript() << OP_0 << sig1 << sig3; + CScript complete23 = CScript() << OP_0 << sig2 << sig3; + + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b); + BOOST_CHECK(combined == partial1a); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b); + BOOST_CHECK(combined == complete13); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a); + BOOST_CHECK(combined == complete23); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b); + BOOST_CHECK(combined == complete23); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a); + BOOST_CHECK(combined == partial3c); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 96d63bff97..cae0bb6baf 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -1,6 +1,7 @@ #define BOOST_TEST_MODULE Bitcoin Test Suite #include <boost/test/unit_test.hpp> +#include "db.h" #include "main.h" #include "wallet.h" @@ -14,13 +15,18 @@ struct TestingSetup { TestingSetup() { fPrintToConsole = true; // don't want to write to debug.log file noui_connect(); - pwalletMain = new CWallet(); + bitdb.MakeMock(); + LoadBlockIndex(true); + bool fFirstRun; + pwalletMain = new CWallet("wallet.dat"); + pwalletMain->LoadWallet(fFirstRun); RegisterWallet(pwalletMain); } ~TestingSetup() { delete pwalletMain; pwalletMain = NULL; + bitdb.Flush(true); } }; diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 9b77b284e6..2f6da932a6 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK_EQUAL(nValueRet, 10 * CENT); BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); - // now clear out the wallet and start again to test chosing between subsets of smaller coins and the next biggest coin + // now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin empty_wallet(); add_coin( 6*CENT); diff --git a/src/util.cpp b/src/util.cpp index 9d0f9ab347..4cb8a214da 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -51,6 +51,8 @@ namespace boost { #endif #include <io.h> /* for _commit */ #include "shlobj.h" +#elif defined(__linux__) +# include <sys/prctl.h> #endif using namespace std; @@ -73,7 +75,7 @@ bool fLogTimestamps = false; CMedianFilter<int64> vTimeOffsets(200,0); bool fReopenDebugLog = false; -// Init openssl library multithreading support +// Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) { @@ -90,7 +92,7 @@ class CInit public: CInit() { - // Init openssl library multithreading support + // Init OpenSSL library multithreading support ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*)); for (int i = 0; i < CRYPTO_num_locks(); i++) ppmutexOpenSSL[i] = new CCriticalSection(); @@ -106,7 +108,7 @@ public: } ~CInit() { - // Shutdown openssl library multithreading support + // Shutdown OpenSSL library multithreading support CRYPTO_set_locking_callback(NULL); for (int i = 0; i < CRYPTO_num_locks(); i++) delete ppmutexOpenSSL[i]; @@ -1142,7 +1144,7 @@ void ShrinkDebugFile() // "Never go to sea with two chronometers; take one or three." // Our three time sources are: // - System clock -// - Median of other nodes's clocks +// - Median of other nodes clocks // - The user (asking the user to fix the system clock if the first two disagree) // static int64 nMockTime = 0; // For unit testing @@ -1275,3 +1277,20 @@ void runCommand(std::string strCommand) printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr); } +void RenameThread(const char* name) +{ +#if defined(PR_SET_NAME) + // Only the first 15 characters are used (16 - NUL terminator) + ::prctl(PR_SET_NAME, name, 0, 0, 0); +#elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__)) + // TODO: This is currently disabled because it needs to be verified to work + // on FreeBSD or OpenBSD first. When verified the '0 &&' part can be + // removed. + pthread_set_name_np(pthread_self(), name); +#elif defined(MAC_OSX) + pthread_setname_np(name); +#else + // Prevent warnings for unused parameters... + (void)name; +#endif +} diff --git a/src/util.h b/src/util.h index 7b2c678916..4423d2ff58 100644 --- a/src/util.h +++ b/src/util.h @@ -391,6 +391,46 @@ inline uint256 Hash(const T1 pbegin, const T1 pend) return hash2; } +class CHashWriter +{ +private: + SHA256_CTX ctx; + +public: + int nType; + int nVersion; + + void Init() { + SHA256_Init(&ctx); + } + + CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { + Init(); + } + + CHashWriter& write(const char *pch, size_t size) { + SHA256_Update(&ctx, pch, size); + return (*this); + } + + // invalidates the object + uint256 GetHash() { + uint256 hash1; + SHA256_Final((unsigned char*)&hash1, &ctx); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; + } + + template<typename T> + CHashWriter& operator<<(const T& obj) { + // Serialize to this stream + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } +}; + + template<typename T1, typename T2> inline uint256 Hash(const T1 p1begin, const T1 p1end, const T2 p2begin, const T2 p2end) @@ -428,13 +468,9 @@ inline uint256 Hash(const T1 p1begin, const T1 p1end, template<typename T> uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) { - // Most of the time is spent allocating and deallocating CDataStream's - // buffer. If this ever needs to be optimized further, make a CStaticStream - // class with its buffer on the stack. - CDataStream ss(nType, nVersion); - ss.reserve(10000); + CHashWriter ss(nType, nVersion); ss << obj; - return Hash(ss.begin(), ss.end()); + return ss.GetHash(); } inline uint160 Hash160(const std::vector<unsigned char>& vch) @@ -585,9 +621,7 @@ inline void ExitThread(size_t nExitCode) } #endif - - - +void RenameThread(const char* name); inline uint32_t ByteReverse(uint32_t value) { diff --git a/src/wallet.cpp b/src/wallet.cpp index 127d580803..4d99ce6560 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -899,7 +899,7 @@ int64 CWallet::GetImmatureBalance() const } // populate vCoins with vector of spendable COutputs -void CWallet::AvailableCoins(vector<COutput>& vCoins) const +void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const { vCoins.clear(); @@ -909,7 +909,10 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins) const { const CWalletTx* pcoin = &(*it).second; - if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) + if (!pcoin->IsFinal()) + continue; + + if (fOnlyConfirmed && !pcoin->IsConfirmed()) continue; if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) diff --git a/src/wallet.h b/src/wallet.h index b2e0e5260e..5bf38699ef 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -61,7 +61,6 @@ public: class CWallet : public CCryptoKeyStore { private: - void AvailableCoins(std::vector<COutput>& vCoins) const; bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const; CWalletDB *pwalletdbEncryption; @@ -69,7 +68,7 @@ private: // the current wallet version: clients below this version are not able to load the wallet int nWalletVersion; - // the maxmimum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded + // the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded int nWalletMaxVersion; public: @@ -113,6 +112,7 @@ public: // check whether we are allowed to upgrade (or already support) to the named feature bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; } + void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true) const; bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const; // keystore implementation diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 2c4d4c0ef0..72c548e602 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -323,6 +323,9 @@ int CWalletDB::LoadWallet(CWallet* pwallet) void ThreadFlushWalletDB(void* parg) { + // Make this thread recognisable as the wallet flushing thread + RenameThread("bitcoin-wallet"); + const string& strFile = ((const string*)parg)[0]; static bool fOneThread; if (fOneThread) |