Mercurial > hg > bitcoin
changeset 3201:ae3d061d9a9f draft
Merge branch 'chashwriter' of https://github.com/sipa/bitcoin
author | Gavin Andresen <gavinandresen@gmail.com> |
---|---|
date | Fri, 13 Jul 2012 08:35:58 -0400 |
parents | 2b044778b85f (diff) 784752694258 (current diff) |
children | 3c878ae8f5a7 bc3ba1726382 |
files | |
diffstat | 68 files changed, 2909 insertions(+), 2375 deletions(-) [+] |
line wrap: on
line diff
--- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -81,7 +81,7 @@ } # regenerate src/build.h -!windows || contains(USE_BUILD_INFO, 1) { +!windows|contains(USE_BUILD_INFO, 1) { genbuild.depends = FORCE genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h genbuild.target = $$OUT_PWD/build/build.h @@ -100,7 +100,7 @@ src/qt/optionsdialog.h \ src/qt/sendcoinsdialog.h \ src/qt/addressbookpage.h \ - src/qt/messagepage.h \ + src/qt/signverifymessagedialog.h \ src/qt/aboutdialog.h \ src/qt/editaddressdialog.h \ src/qt/bitcoinaddressvalidator.h \ @@ -160,8 +160,7 @@ src/qt/qtipcserver.h \ src/allocators.h \ src/ui_interface.h \ - src/qt/rpcconsole.h \ - src/qt/verifymessagedialog.h + src/qt/rpcconsole.h SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/transactiontablemodel.cpp \ @@ -169,7 +168,7 @@ src/qt/optionsdialog.cpp \ src/qt/sendcoinsdialog.cpp \ src/qt/addressbookpage.cpp \ - src/qt/messagepage.cpp \ + src/qt/signverifymessagedialog.cpp \ src/qt/aboutdialog.cpp \ src/qt/editaddressdialog.cpp \ src/qt/bitcoinaddressvalidator.cpp \ @@ -206,6 +205,8 @@ src/qt/walletmodel.cpp \ src/bitcoinrpc.cpp \ src/rpcdump.cpp \ + src/rpcnet.cpp \ + src/rpcrawtransaction.cpp \ src/qt/overviewpage.cpp \ src/qt/csvmodelwriter.cpp \ src/crypter.cpp \ @@ -218,7 +219,6 @@ src/qt/notificator.cpp \ src/qt/qtipcserver.cpp \ src/qt/rpcconsole.cpp \ - src/qt/verifymessagedialog.cpp \ src/noui.cpp RESOURCES += \ @@ -227,7 +227,7 @@ FORMS += \ src/qt/forms/sendcoinsdialog.ui \ src/qt/forms/addressbookpage.ui \ - src/qt/forms/messagepage.ui \ + src/qt/forms/signverifymessagedialog.ui \ src/qt/forms/aboutdialog.ui \ src/qt/forms/editaddressdialog.ui \ src/qt/forms/transactiondescdialog.ui \ @@ -235,7 +235,6 @@ src/qt/forms/sendcoinsentry.ui \ src/qt/forms/askpassphrasedialog.ui \ src/qt/forms/rpcconsole.ui \ - src/qt/forms/verifymessagedialog.ui \ src/qt/forms/optionsdialog.ui contains(USE_QRCODE, 1) {
--- a/contrib/gitian-descriptors/boost-win32.yml +++ b/contrib/gitian-descriptors/boost-win32.yml @@ -11,12 +11,28 @@ reference_datetime: "2011-01-30 00:00:00" remotes: [] files: -- "boost_1_47_0.tar.bz2" +- "boost_1_49_0.tar.bz2" script: | TMPDIR="$HOME/tmpdir" mkdir -p $TMPDIR/bin/$GBUILD_BITS $TMPDIR/include - tar xjf boost_1_47_0.tar.bz2 - cd boost_1_47_0 + tar xjf boost_1_49_0.tar.bz2 + cd boost_1_49_0 + echo "--- tmp_dir_helpers.orig.hpp 2012-06-10 01:39:25.403268210 +0200 ++++ tmp_dir_helpers.hpp 2012-06-10 01:41:14.653823479 +0200 +@@ -19,9 +19,9 @@ + #include <string> + + #if defined(BOOST_INTERPROCESS_WINDOWS) +- //#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME +- //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME +- //#include <boost/interprocess/detail/win32_api.hpp> ++ #define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME ++ #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME ++ #include <boost/interprocess/detail/win32_api.hpp> + #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) + //#include <sys/sysctl.h> + //#if defined(CTL_KERN) && defined (KERN_BOOTTIME)" > useboottime.patch + patch boost/interprocess/detail/tmp_dir_helpers.hpp useboottime.patch echo "using gcc : 4.4 : i586-mingw32msvc-g++ : <rc>i586-mingw32msvc-windres @@ -34,5 +50,5 @@ cd $TMPDIR export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME - zip -r boost-win32-1.47.0-gitian.zip * - cp boost-win32-1.47.0-gitian.zip $OUTDIR + zip -r boost-win32-1.49.0-gitian2.zip * + cp boost-win32-1.49.0-gitian2.zip $OUTDIR
--- a/contrib/gitian-descriptors/gitian-win32.yml +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -16,7 +16,7 @@ "dir": "bitcoin" files: - "qt-win32-4.7.4-gitian.zip" -- "boost-win32-1.47.0-gitian.zip" +- "boost-win32-1.49.0-gitian2.zip" - "bitcoin-deps-0.0.4.zip" script: | # @@ -26,10 +26,10 @@ cd $HOME/build/ export PATH=$PATH:$HOME/qt/bin/ # - mkdir boost_1_47_0 - cd boost_1_47_0 + mkdir boost_1_49_0 + cd boost_1_49_0 mkdir -p stage/lib - unzip ../boost-win32-1.47.0-gitian.zip + unzip ../boost-win32-1.49.0-gitian2.zip cd bin/$GBUILD_BITS for lib in *; do i586-mingw32msvc-ar rc ../../stage/lib/libboost_${lib}-mt-s.a $lib/*.o
--- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -28,32 +28,55 @@ bitcoin_xx_YY.ts or bitcoin_xx.ts -#### Source file +#### bitcoin_en.ts (Source file) `src/qt/locale/bitcoin_en.ts` is treated in a special way. It is used as the source for all other translations. Whenever a string in the code is changed -this file must be updated to reflect those changes. Usually, this can be -accomplished by running `lupdate` (included in the Qt SDK). +this file must be updated to reflect those changes. This can be accomplished +by running `lupdate` (included in the Qt SDK). Also, a custom script is used +to extract strings from the non-Qt parts: + + python share/qt/extract_strings_qt.py + lupdate bitcoin-qt.pro -no-obsolete -locations none -ts src/qt/locale/bitcoin_en.ts + +##### Handling of plurals in the source file + +When new plurals are added to the source file, it's important to do the following steps: -An updated source file should be merged to github and transifex will pick it -up from there. Afterwards the new strings show up as "Remaining" in transifex -and can be translated. +1. Open bitcoin_en.ts in Qt Linguist (also included in the Qt SDK) +2. Search for `%n`, which will take you to the parts in the translation that use plurals +3. Look for empty `English Translation (Singular)` and `English Translation (Plural)` fields +4. Add the appropriate strings for the singular and plural form of the base string +5. Mark the item as done (via the green arrow symbol in the toolbar) +6. Repeat from step 2. until all singular and plural forms are in the source file +7. Save the source file + +##### Creating the pull-request -Syncing with transifex +An updated source file should be merged to github and Transifex will pick it +up from there (can take some hours). Afterwards the new strings show up as "Remaining" +in Transifex and can be translated. + +To create the pull-request you have to do: + + git add src/qt/bitcoinstrings.cpp src/qt/locale/bitcoin_en.ts + git commit + +Syncing with Transifex ---------------------- -We are using http://transifex.net as a frontend for translating the client. +We are using https://transifex.com as a frontend for translating the client. -https://www.transifex.net/projects/p/bitcoin/resource/tx/ +https://www.transifex.com/projects/p/bitcoin/resource/tx/ -The "transifex client" (see: http://help.transifex.net/features/client/) -will help with fetching new translations from transifex. Use the following -config to be able to connect with the client. +The "Transifex client" (see: http://help.transifex.com/features/client/) +will help with fetching new translations from Transifex. Use the following +config to be able to connect with the client: ### .tx/config [main] - host = https://www.transifex.net + host = https://www.transifex.com [bitcoin.tx] file_filter = src/qt/locale/bitcoin_<lang>.ts @@ -63,14 +86,14 @@ ### .tx/config (for Windows) [main] - host = https://www.transifex.net + host = https://www.transifex.com [bitcoin.tx] file_filter = src\qt\locale\bitcoin_<lang>.ts source_file = src\qt\locale\bitcoin_en.ts source_lang = en -It is also possible to directly download new translations one by one from transifex. +It is also possible to directly download new translations one by one from the Transifex website. ### Fetching new translations
--- a/share/setup.nsi +++ b/share/setup.nsi @@ -98,12 +98,10 @@ WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1 WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1 - - # bitcoin: URI handling disabled for 0.6.0 - # WriteRegStr HKCR "bitcoin" "URL Protocol" "" - # WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin" - # WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe - # WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "$$1"' + WriteRegStr HKCR "bitcoin" "URL Protocol" "" + WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin" + WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe + WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "$$1"' SectionEnd # Macro for selecting uninstaller sections
--- a/src/addrman.h +++ b/src/addrman.h @@ -23,13 +23,13 @@ // 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)
--- a/src/base58.h +++ b/src/base58.h @@ -71,7 +71,7 @@ } // 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 @@ } // 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 @@ } // 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 @@ } // 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);
--- a/src/bignum.h +++ b/src/bignum.h @@ -131,15 +131,9 @@ 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;
--- 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 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 @@ 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 @@ return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); } -static std::string +std::string HelpRequiringPassphrase() { return pwalletMain->IsCrypted() @@ -128,40 +169,13 @@ : ""; } -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 @@ 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 @@ 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 @@ 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 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 @@ 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; - - AnyTxToJSON(hash, NULL, entry, - (params.size() > 1) ? params[1].get_obj() : emptyobj); + 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); + + 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; } @@ -2235,9 +2032,9 @@ 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 +2047,9 @@ 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 +2068,7 @@ { "stop", &stop, true }, { "getblockcount", &getblockcount, true }, { "getconnectioncount", &getconnectioncount, true }, + { "getpeerinfo", &getpeerinfo, true }, { "getdifficulty", &getdifficulty, true }, { "getgenerate", &getgenerate, true }, { "setgenerate", &setgenerate, true }, @@ -2352,7 +2111,12 @@ { "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 +2324,7 @@ 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 +2333,12 @@ 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"; } @@ -2768,7 +2538,7 @@ 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 +2628,8 @@ 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 +2645,7 @@ 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 +2663,7 @@ 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 +2677,95 @@ } 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]++; + { + LOCK(cs_THREAD_RPCHANDLER); + vnThreadsRunning[THREAD_RPCHANDLER]++; + } AcceptedConnection *conn = (AcceptedConnection *) parg; bool fRun = true; @@ -2921,7 +2774,10 @@ { conn->close(); delete conn; - --vnThreadsRunning[THREAD_RPCHANDLER]; + { + LOCK(cs_THREAD_RPCHANDLER); + --vnThreadsRunning[THREAD_RPCHANDLER]; + } return; } map<string, string> mapHeaders; @@ -2950,58 +2806,50 @@ 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(); + + string strReply; + + // 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(-32600, "Params must be an array"); - - Value result = tableRPC.execute(strMethod, params); - - // Send reply - string strReply = JSONRPCReply(result, Value::null, id); + 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 @@ -3128,9 +2976,7 @@ 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 +2990,13 @@ 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; }
--- 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 @@ /** 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
--- a/src/db.cpp +++ b/src/db.cpp @@ -510,7 +510,9 @@ 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);
--- 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,8 +40,13 @@ 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) @@ -150,11 +154,6 @@ 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) { @@ -240,7 +239,7 @@ " -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" +
--- a/src/main.cpp +++ b/src/main.cpp @@ -268,6 +268,9 @@ 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 @@ 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 @@ 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); @@ -970,8 +971,13 @@ 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"); } @@ -1325,19 +1331,8 @@ // 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; @@ -1351,6 +1346,17 @@ 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")); @@ -1381,7 +1387,7 @@ return false; } - mapQueuedChanges[tx.GetHash()] = CTxIndex(posThisTx, tx.vout.size()); + mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size()); } // Write queued txindex changes @@ -1613,7 +1619,27 @@ 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", ""); @@ -2574,11 +2600,15 @@ return error("message getdata size() = %d", vInv.size()); } + if (fDebugNet || (vInv.size() != 1)) + printf("received getdata (%d invsz)\n", vInv.size()); + BOOST_FOREACH(const CInv& inv, vInv) { if (fShutdown) return true; - printf("received getdata for: %s\n", inv.ToString().c_str()); + if (fDebugNet || (vInv.size() == 1)) + printf("received getdata for: %s\n", inv.ToString().c_str()); if (inv.type == MSG_BLOCK) {
--- a/src/main.h +++ b/src/main.h @@ -386,6 +386,7 @@ class CTransaction { public: + static const int CURRENT_VERSION=1; int nVersion; std::vector<CTxIn> vin; std::vector<CTxOut> vout; @@ -411,7 +412,7 @@ void SetNull() { - nVersion = 1; + nVersion = CTransaction::CURRENT_VERSION; vin.clear(); vout.clear(); nLockTime = 0; @@ -817,6 +818,7 @@ { public: // header + static const int CURRENT_VERSION=1; int nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -858,7 +860,7 @@ void SetNull() { - nVersion = 1; + nVersion = CBlock::CURRENT_VERSION; hashPrevBlock = 0; hashMerkleRoot = 0; nTime = 0; @@ -1602,7 +1604,7 @@ 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 queryHashes(std::vector<uint256>& vtxid);
--- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -7,14 +7,14 @@ 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 @@ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \
--- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -5,20 +5,20 @@ 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" 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" 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 @@ obj/protocol.o \ obj/bitcoinrpc.o \ obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcrawtransaction.o \ obj/script.o \ obj/sync.o \ obj/util.o \
--- a/src/makefile.osx +++ b/src/makefile.osx @@ -84,6 +84,8 @@ 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 @@ 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 @@ 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); \
--- a/src/makefile.unix +++ b/src/makefile.unix @@ -104,6 +104,8 @@ 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,7 +126,7 @@ 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); \ @@ -136,7 +138,7 @@ 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); \
--- a/src/net.cpp +++ b/src/net.cpp @@ -606,7 +606,23 @@ 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 @@ -922,8 +938,6 @@ pnode->CloseSocketDisconnect(); } } - if (vSend.size() > SendBufferSize()) - printf("socket send buffer full warning (%d bytes)\n", vSend.size()); } } } @@ -1123,10 +1137,10 @@ // 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"}, + {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"}, {"bluematt.me", "dnsseed.bluematt.me"}, - {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"}, {"dashjr.org", "dnsseed.bitcoin.dashjr.org"}, + {"xf2.org", "bitseed.xf2.org"}, }; void ThreadDNSAddressSeed(void* parg) @@ -1416,16 +1430,17 @@ // 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++; + } } }
--- a/src/net.h +++ b/src/net.h @@ -27,7 +27,7 @@ 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 @@ +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 @@ // 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 @@ 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); };
--- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -224,7 +224,7 @@ } 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)
--- a/src/protocol.h +++ b/src/protocol.h @@ -49,8 +49,16 @@ // 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;
--- 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 @@ QDialog(parent), ui(new Ui::AddressBookPage), model(0), + optionsModel(0), mode(mode), tab(tab) { @@ -65,6 +67,7 @@ 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 @@ 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 @@ 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))); @@ -139,6 +145,11 @@ selectionChanged(); } +void AddressBookPage::setOptionsModel(OptionsModel *optionsModel) +{ + this->optionsModel = optionsModel; +} + void AddressBookPage::on_copyToClipboard_clicked() { GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address); @@ -179,10 +190,22 @@ 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 +253,8 @@ 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 +263,8 @@ 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 +276,7 @@ ui->showQRCode->setEnabled(false); ui->copyToClipboard->setEnabled(false); ui->signMessage->setEnabled(false); + ui->verifyMessage->setEnabled(false); } } @@ -314,6 +342,8 @@ 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(); }
--- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -7,6 +7,7 @@ class AddressBookPage; } class AddressTableModel; +class OptionsModel; QT_BEGIN_NAMESPACE class QTableView; @@ -37,6 +38,7 @@ ~AddressBookPage(); void setModel(AddressTableModel *model); + void setOptionsModel(OptionsModel *optionsModel); const QString &getReturnValue() const { return returnValue; } public slots: @@ -46,6 +48,7 @@ private: Ui::AddressBookPage *ui; AddressTableModel *model; + OptionsModel *optionsModel; Mode mode; Tabs tab; QString returnValue; @@ -60,6 +63,7 @@ /** 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 @@ /** 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
--- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -116,9 +116,8 @@ #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++) { @@ -262,8 +261,8 @@ { 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();
--- 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" @@ -108,7 +107,7 @@ sendCoinsPage = new SendCoinsDialog(this); - messagePage = new MessagePage(this); + signVerifyMessageDialog = new SignVerifyMessageDialog(this); centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); @@ -117,7 +116,7 @@ centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); #ifdef FIRST_CLASS_MESSAGING - centralWidget->addWidget(messagePage); + centralWidget->addWidget(signVerifyMessageDialog); #endif setCentralWidget(centralWidget); @@ -166,6 +165,11 @@ 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 +216,20 @@ 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,8 +241,15 @@ 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")); @@ -258,8 +277,6 @@ 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 +286,6 @@ 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 +303,9 @@ file->addAction(backupWalletAction); file->addAction(exportAction); #ifndef FIRST_CLASS_MESSAGING - file->addAction(messageAction); + file->addAction(signMessageAction); + file->addAction(verifyMessageAction); #endif - file->addAction(verifyMessageAction); file->addSeparator(); file->addAction(quitAction); @@ -316,7 +332,7 @@ toolbar->addAction(historyAction); toolbar->addAction(addressBookAction); #ifdef FIRST_CLASS_MESSAGING - toolbar->addAction(messageAction); + toolbar->addAction(firstClassMessagingAction); #endif QToolBar *toolbar2 = addToolBar(tr("Actions toolbar")); @@ -357,6 +373,8 @@ 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 +393,7 @@ 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 +433,7 @@ #ifndef FIRST_CLASS_MESSAGING trayIconMenu->addSeparator(); #endif - trayIconMenu->addAction(messageAction); + trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(optionsAction); @@ -717,20 +735,42 @@ disconnect(exportAction, SIGNAL(triggered()), 0, 0); } -void BitcoinGUI::gotoMessagePage(QString addr) +void BitcoinGUI::gotoSignMessageTab(QString addr) { - if(!addr.isEmpty()) - messagePage->setAddress(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_SM(false); #else - messagePage->show(); + // call show() in showTab_SM() + signVerifyMessageDialog->showTab_SM(true); #endif + + if(!addr.isEmpty()) + signVerifyMessageDialog->setAddress_SM(addr); +} + +void BitcoinGUI::gotoVerifyMessageTab(QString addr) +{ +#ifdef FIRST_CLASS_MESSAGING + firstClassMessagingAction->setChecked(true); + centralWidget->setCurrentWidget(signVerifyMessageDialog); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + + signVerifyMessageDialog->showTab_VM(false); +#else + // call show() in showTab_VM() + signVerifyMessageDialog->showTab_VM(true); +#endif + + if(!addr.isEmpty()) + signVerifyMessageDialog->setAddress_VM(addr); } void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) @@ -833,13 +873,6 @@ dlg.exec(); } -void BitcoinGUI::verifyMessage() -{ - VerifyMessageDialog *dlg = new VerifyMessageDialog(this); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->show(); -} - void BitcoinGUI::unlockWallet() { if(!walletModel)
--- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -11,7 +11,7 @@ class OverviewPage; class AddressBookPage; class SendCoinsDialog; -class MessagePage; +class SignVerifyMessageDialog; class Notificator; class RPCConsole; @@ -64,7 +64,7 @@ AddressBookPage *addressBookPage; AddressBookPage *receiveCoinsPage; SendCoinsDialog *sendCoinsPage; - MessagePage *messagePage; + SignVerifyMessageDialog *signVerifyMessageDialog; QLabel *labelEncryptionIcon; QLabel *labelConnectionsIcon; @@ -78,8 +78,9 @@ QAction *quitAction; QAction *sendCoinsAction; QAction *addressBookAction; - QAction *messageAction; + QAction *signMessageAction; QAction *verifyMessageAction; + QAction *firstClassMessagingAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -131,8 +132,6 @@ 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 @@ /** 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 @@ void backupWallet(); /** Change encrypted wallet passphrase */ void changePassphrase(); - /** Verify a message signature */ - void verifyMessage(); /** Ask for pass phrase to unlock wallet temporarily */ void unlockWallet();
--- 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: 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", "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 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", "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
--- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -18,7 +18,7 @@ { numBlocksAtStartup = -1; - pollTimer = new QTimer(); + pollTimer = new QTimer(this); pollTimer->setInterval(MODEL_UPDATE_DELAY); pollTimer->start(); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
--- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>627</width> + <width>691</width> <height>347</height> </rect> </property> @@ -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>
deleted file mode 100644 --- 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>
--- 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>
--- 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 row="1" column="1"> + <widget class="QLineEdit" name="lnLabel"/> </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="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>
--- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -87,14 +87,17 @@ </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_12"> + <widget class="QLabel" name="label_14"> <property name="text"> - <string>Build date</string> + <string>Using OpenSSL version</string> + </property> + <property name="indent"> + <number>10</number> </property> </widget> </item> <item row="3" column="1"> - <widget class="QLabel" name="buildDate"> + <widget class="QLabel" name="openSSLVersion"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> </property> @@ -110,13 +113,36 @@ </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="4" column="1"> + <widget class="QLabel" name="buildDate"> + <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="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,38 +247,15 @@ </property> </widget> </item> - <item row="10" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Estimated total blocks</string> - </property> - </widget> - </item> - <item row="10" column="1"> - <widget class="QLabel" name="totalBlocks"> - <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="11" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_4"> <property name="text"> - <string>Last block time</string> + <string>Estimated total blocks</string> </property> </widget> </item> <item row="11" column="1"> - <widget class="QLabel" name="lastBlockTime"> + <widget class="QLabel" name="totalBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> </property> @@ -268,6 +271,29 @@ </widget> </item> <item row="12" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Last block time</string> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QLabel" name="lastBlockTime"> + <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="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> @@ -293,7 +319,7 @@ </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> @@ -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>
new file mode 100644 --- /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>Messaging - 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>
--- 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>
deleted file mode 100644 --- 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>
--- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -25,4 +25,10 @@ */ 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
--- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -5,17 +5,14 @@ <context> <name>AboutDialog</name> <message> - <location filename="../forms/aboutdialog.ui" line="14"/> <source>About Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/aboutdialog.ui" line="53"/> <source><b>Bitcoin</b> version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/aboutdialog.ui" line="97"/> <source>Copyright © 2009-2012 Bitcoin Developers This is experimental software. @@ -29,92 +26,82 @@ <context> <name>AddressBookPage</name> <message> - <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"/> <source>Double-click to edit address or label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="63"/> <source>Create a new address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="77"/> <source>Copy the currently selected address to the system clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="66"/> <source>&New Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="80"/> + <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> <source>&Copy Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="91"/> <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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/addressbookpage.ui" line="105"/> + <source>Sign a message to prove you own a Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> <source>&Sign Message</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/addressbookpage.ui" line="116"/> + <source>Verify a message to ensure it was signed with a specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Verify Message</source> + <translation type="unfinished"></translation> + </message> + <message> <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"/> <source>&Delete</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="63"/> <source>Copy &Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="65"/> <source>&Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="287"/> <source>Export Address Book Data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="288"/> <source>Comma separated file (*.csv)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="301"/> <source>Error exporting</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addressbookpage.cpp" line="301"/> <source>Could not write to file %1.</source> <translation type="unfinished"></translation> </message> @@ -122,17 +109,14 @@ <context> <name>AddressTableModel</name> <message> - <location filename="../addresstablemodel.cpp" line="142"/> <source>Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addresstablemodel.cpp" line="142"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../addresstablemodel.cpp" line="178"/> <source>(no label)</source> <translation type="unfinished"></translation> </message> @@ -140,131 +124,99 @@ <context> <name>AskPassphraseDialog</name> <message> - <location filename="../forms/askpassphrasedialog.ui" line="26"/> <source>Passphrase Dialog</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="47"/> <source>Enter passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="61"/> <source>New passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/askpassphrasedialog.ui" line="75"/> <source>Repeat new passphrase</source> <translation type="unfinished"></translation> </message> <message> - <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"/> <source>Encrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="37"/> <source>This operation needs your wallet passphrase to unlock the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="42"/> <source>Unlock wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="45"/> <source>This operation needs your wallet passphrase to decrypt the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="50"/> <source>Decrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="53"/> <source>Change passphrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="54"/> <source>Enter the old and new passphrase to the wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="100"/> <source>Confirm wallet encryption</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="101"/> <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"/> <source>Wallet encrypted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="111"/> <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"/> <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"/> <source>Wallet encryption failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="117"/> <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"/> <source>The supplied passphrases do not match.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="135"/> <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"/> <source>The passphrase entered for the wallet decryption was incorrect.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="146"/> <source>Wallet decryption failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="160"/> <source>Wallet passphrase was succesfully changed.</source> <translation type="unfinished"></translation> </message> @@ -272,127 +224,98 @@ <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"/> <source>Sign &message...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="248"/> <source>Show/Hide &Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="515"/> <source>Synchronizing with network...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="185"/> <source>&Overview</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="186"/> <source>Show general overview of wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="191"/> <source>&Transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="192"/> <source>Browse transaction history</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="197"/> <source>&Address Book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="198"/> <source>Edit the list of stored addresses and labels</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="203"/> <source>&Receive coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="204"/> <source>Show the list of addresses for receiving payments</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="209"/> <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"/> <source>E&xit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="236"/> <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"/> <source>Show information about Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="242"/> <source>About &Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="243"/> <source>Show information about Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="245"/> <source>&Options...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="252"/> <source>&Encrypt Wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="255"/> <source>&Backup Wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="257"/> <source>&Change Passphrase...</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="517"/> <source>~%n block(s) remaining</source> <translation> <numerusform>~%n block remaining</numerusform> @@ -400,109 +323,94 @@ </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="528"/> <source>Downloaded %1 of %2 blocks of transaction history (%3% done).</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="250"/> <source>&Export...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="210"/> <source>Send coins to a Bitcoin address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="246"/> + <source>Sign a message to prove you own a Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Verify a message to ensure it was signed with a specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>S&ignatures</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Modify configuration options for Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="249"/> <source>Show or hide the Bitcoin window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="251"/> <source>Export the data in the current tab to a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="253"/> <source>Encrypt or decrypt wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="256"/> <source>Backup wallet to another location</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="258"/> <source>Change the passphrase used for wallet encryption</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="259"/> <source>&Debug window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="260"/> <source>Open debugging and diagnostic console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="261"/> <source>&Verify message...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="262"/> - <source>Verify a message signature</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoingui.cpp" line="286"/> <source>&File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="296"/> <source>&Settings</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="302"/> <source>&Help</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="311"/> <source>Tabs toolbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="322"/> <source>Actions toolbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="334"/> - <location filename="../bitcoingui.cpp" line="343"/> <source>[testnet]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="343"/> - <location filename="../bitcoingui.cpp" line="399"/> <source>Bitcoin client</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="492"/> <source>%n active connection(s) to Bitcoin network</source> <translation> <numerusform>%n active connection to Bitcoin network</numerusform> @@ -510,12 +418,10 @@ </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="540"/> <source>Downloaded %1 blocks of transaction history.</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="555"/> <source>%n second(s) ago</source> <translation> <numerusform>%n second ago</numerusform> @@ -523,7 +429,6 @@ </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="559"/> <source>%n minute(s) ago</source> <translation> <numerusform>%n minute ago</numerusform> @@ -531,7 +436,6 @@ </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="563"/> <source>%n hour(s) ago</source> <translation> <numerusform>%n hour ago</numerusform> @@ -539,7 +443,6 @@ </translation> </message> <message numerus="yes"> - <location filename="../bitcoingui.cpp" line="567"/> <source>%n day(s) ago</source> <translation> <numerusform>%n day ago</numerusform> @@ -547,42 +450,34 @@ </translation> </message> <message> - <location filename="../bitcoingui.cpp" line="573"/> <source>Up to date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="580"/> <source>Catching up...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="590"/> <source>Last received block was generated %1.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="649"/> <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"/> <source>Confirm transaction fee</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="681"/> <source>Sent transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="682"/> <source>Incoming transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="683"/> <source>Date: %1 Amount: %2 Type: %3 @@ -591,37 +486,38 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="804"/> + <source>URI handling</source> + <translation type="unfinished"></translation> + </message> + <message> + <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> <source>Wallet is <b>encrypted</b> and currently <b>unlocked</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="812"/> <source>Wallet is <b>encrypted</b> and currently <b>locked</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="835"/> <source>Backup Wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="835"/> <source>Wallet Data (*.dat)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="838"/> <source>Backup Failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoingui.cpp" line="838"/> <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> <translation type="unfinished"></translation> </message> @@ -629,7 +525,6 @@ <context> <name>ClientModel</name> <message> - <location filename="../clientmodel.cpp" line="84"/> <source>Network Alert</source> <translation type="unfinished"></translation> </message> @@ -637,67 +532,54 @@ <context> <name>EditAddressDialog</name> <message> - <location filename="../forms/editaddressdialog.ui" line="14"/> <source>Edit Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="25"/> <source>&Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="35"/> <source>The label associated with this address book entry</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="42"/> <source>&Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/editaddressdialog.ui" line="52"/> <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"/> <source>New receiving address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="24"/> <source>New sending address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="27"/> <source>Edit receiving address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="31"/> <source>Edit sending address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="91"/> <source>The entered address "%1" is already in the address book.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="96"/> <source>The entered address "%1" is not a valid Bitcoin address.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="101"/> <source>Could not unlock wallet.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../editaddressdialog.cpp" line="106"/> <source>New key generation failed.</source> <translation type="unfinished"></translation> </message> @@ -705,349 +587,189 @@ <context> <name>GUIUtil::HelpMessageBox</name> <message> - <location filename="../guiutil.cpp" line="420"/> - <location filename="../guiutil.cpp" line="432"/> <source>Bitcoin-Qt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="420"/> <source>version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="422"/> <source>Usage:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="423"/> <source>command-line options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="427"/> <source>UI options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="428"/> <source>Set language, for example "de_DE" (default: system locale)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="429"/> <source>Start minimized</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../guiutil.cpp" line="430"/> <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"/> <source>Options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="30"/> <source>&Main</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="36"/> <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"/> <source>Pay transaction &fee</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="82"/> <source>Automatically start Bitcoin after logging in to the system.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="85"/> <source>&Start Bitcoin on system login</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="92"/> <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"/> <source>&Detach databases at shutdown</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="116"/> <source>&Network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="122"/> <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"/> <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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../forms/optionsdialog.ui" line="135"/> + <source>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</source> + <translation type="unfinished"></translation> + </message> + <message> <source>&Connect through SOCKS proxy:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="144"/> <source>Proxy &IP:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="163"/> <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"/> <source>&Port:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="189"/> <source>Port of the proxy (e.g. 9050)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="196"/> <source>SOCKS &Version:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="209"/> <source>SOCKS version of the proxy (e.g. 5)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="245"/> <source>&Window</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="251"/> <source>Show only a tray icon after minimizing the window.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="254"/> <source>&Minimize to the tray instead of the taskbar</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="261"/> <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"/> <source>M&inimize on close</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="285"/> <source>&Display</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="293"/> <source>User Interface &language:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="306"/> <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"/> <source>&Unit to show amounts in:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="330"/> <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"/> <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"/> <source>&Display addresses in transaction list</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="413"/> <source>&OK</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="420"/> <source>&Cancel</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/optionsdialog.ui" line="430"/> <source>&Apply</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="62"/> <source>default</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="173"/> - <location filename="../optionsdialog.cpp" line="182"/> <source>Warning</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="173"/> - <location filename="../optionsdialog.cpp" line="182"/> <source>This setting will take effect after restarting Bitcoin.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../optionsdialog.cpp" line="207"/> <source>The supplied proxy address is invalid.</source> <translation type="unfinished"></translation> </message> @@ -1055,69 +777,54 @@ <context> <name>OverviewPage</name> <message> - <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"/> <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"/> <source>Balance:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="147"/> <source>Number of transactions:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="118"/> <source>Unconfirmed:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="40"/> <source>Wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="164"/> <source>Immature:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="177"/> <source>Mined balance that has not yet matured</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="223"/> <source><b>Recent transactions</b></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="105"/> <source>Your current balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/overviewpage.ui" line="134"/> <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"/> <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"/> <source>out of sync</source> <translation type="unfinished"></translation> </message> @@ -1125,62 +832,46 @@ <context> <name>QRCodeDialog</name> <message> - <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"/> <source>Request Payment</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="70"/> <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"/> <source>Label:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="144"/> <source>Message:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/qrcodedialog.ui" line="186"/> <source>&Save As...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="45"/> <source>Error encoding URI into QR Code.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="63"/> + <source>The entered amount is invalid, please check.</source> + <translation type="unfinished"></translation> + </message> + <message> <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"/> <source>Save QR Code</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../qrcodedialog.cpp" line="120"/> <source>PNG Images (*.png)</source> <translation type="unfinished"></translation> </message> @@ -1188,140 +879,110 @@ <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"/> <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"/> <source>N/A</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="69"/> <source>Client version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="24"/> <source>&Information</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="39"/> <source>Client</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="115"/> + <source>Using OpenSSL version</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Startup time</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="144"/> <source>Network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="151"/> <source>Number of connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="174"/> <source>On testnet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="197"/> <source>Block chain</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="204"/> <source>Current number of blocks</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="227"/> <source>Estimated total blocks</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="250"/> <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"/> <source>&Open</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="318"/> <source>Command-line options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="325"/> <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"/> <source>&Show</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="352"/> <source>&Console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="92"/> <source>Build date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/rpcconsole.ui" line="401"/> <source>Clear console</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="209"/> <source>Welcome to the Bitcoin RPC console.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../rpcconsole.cpp" line="210"/> <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"/> <source>Type <b>help</b> for an overview of available commands.</source> <translation type="unfinished"></translation> </message> @@ -1329,109 +990,82 @@ <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"/> <source>Send Coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="64"/> <source>Send to multiple recipients at once</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="67"/> <source>&Add Recipient</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="84"/> <source>Remove all transaction fields</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="87"/> <source>Clear &All</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="106"/> <source>Balance:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="113"/> <source>123.456 BTC</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="144"/> <source>Confirm the send action</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsdialog.ui" line="147"/> <source>&Send</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="94"/> <source><b>%1</b> to %2 (%3)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="99"/> <source>Confirm send coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="100"/> <source>Are you sure you want to send %1?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="100"/> <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> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="128"/> <source>The amount to pay must be larger than 0.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="133"/> <source>The amount exceeds your balance.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="138"/> <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"/> <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"/> <source>Error: Transaction creation failed.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="154"/> <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 +1073,336 @@ <context> <name>SendCoinsEntry</name> <message> - <location filename="../forms/sendcoinsentry.ui" line="14"/> <source>Form</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="29"/> <source>A&mount:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="42"/> <source>Pay &To:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="66"/> - <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"/> <source>&Label:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="93"/> <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"/> <source>Choose address from address book</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="113"/> <source>Alt+A</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="120"/> + <source>Paste address from clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Alt+P</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Remove this recipient</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>SignVerifyMessageDialog</name> + <message> + <source>Messaging - Sign / Verify a Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Sign Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <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> + <source>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Choose an address from the address book</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Alt+A</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Paste address from clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="130"/> <source>Alt+P</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/sendcoinsentry.ui" line="137"/> - <source>Remove this recipient</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../sendcoinsentry.cpp" line="26"/> + <source>Enter the message you want to sign here</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Copy the current signature to the system clipboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Sign the message to prove you own this Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Reset all sign message fields</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Clear &All</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>&Verify Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <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> + <source>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Verify the message to ensure it was signed with the specified Bitcoin address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Reset all verify message fields</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source> <translation type="unfinished"></translation> </message> + <message> + <source>Click "Sign Message" to generate signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Enter Bitcoin signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>The entered address is invalid.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Please check the address and try again.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>The entered address does not refer to a key.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Wallet unlock was canceled.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Private key for the entered address is not available.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Message signing failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Message signed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>The signature could not be decoded.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Please check the signature and try again.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>The signature did not match the message digest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Message verification failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Message verified.</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>TransactionDesc</name> <message> - <location filename="../transactiondesc.cpp" line="21"/> - <source>Open for %1 blocks</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="23"/> <source>Open until %1</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../transactiondesc.cpp" line="29"/> - <source>%1/offline?</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="31"/> + <message numerus="yes"> + <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> + <source>%1/offline</source> + <translation type="unfinished"></translation> + </message> + <message> <source>%1/unconfirmed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="33"/> <source>%1 confirmations</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="51"/> - <source><b>Status:</b> </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="56"/> + <source>Status</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <source>, broadcast through %n node(s)</source> + <translation> + <numerusform>, broadcast through %n node</numerusform> + <numerusform>, broadcast through %n nodes</numerusform> + </translation> + </message> + <message> + <source>Date</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Source</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Generated</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>From</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>To</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>own address</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>label</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Credit</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <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> + <source>not accepted</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Debit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Transaction fee</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Net amount</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Message</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Comment</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Transaction ID</source> + <translation type="unfinished"></translation> + </message> + <message> + <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> + <source>Debug information</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Transaction</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Inputs</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Amount</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>true</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>false</source> + <translation type="unfinished"></translation> + </message> + <message> <source>, has not been successfully broadcast yet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiondesc.cpp" line="58"/> - <source>, broadcast through %1 node</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="60"/> - <source>, broadcast through %1 nodes</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="64"/> - <source><b>Date:</b> </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="71"/> - <source><b>Source:</b> Generated<br></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="77"/> - <location filename="../transactiondesc.cpp" line="94"/> - <source><b>From:</b> </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="94"/> <source>unknown</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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="98"/> - <source> (yours, label: </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="100"/> - <source> (yours)</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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="138"/> - <source>(%1 matures in %2 more blocks)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="142"/> - <source>(not accepted)</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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="200"/> - <source><b>Transaction fee:</b> </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="216"/> - <source><b>Net amount:</b> </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="222"/> - <source>Message:</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="224"/> - <source>Comment:</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../transactiondesc.cpp" line="226"/> - <source>Transaction ID:</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> - <translation type="unfinished"></translation> - </message> </context> <context> <name>TransactionDescDialog</name> <message> - <location filename="../forms/transactiondescdialog.ui" line="14"/> <source>Transaction details</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../forms/transactiondescdialog.ui" line="20"/> <source>This pane shows a detailed description of the transaction</source> <translation type="unfinished"></translation> </message> @@ -1657,27 +1410,22 @@ <context> <name>TransactionTableModel</name> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> <source>Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> <source>Type</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="226"/> <source>Amount</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../transactiontablemodel.cpp" line="281"/> <source>Open for %n block(s)</source> <translation> <numerusform>Open for %n block</numerusform> @@ -1685,95 +1433,77 @@ </translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="284"/> <source>Open until %1</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="287"/> <source>Offline (%1 confirmations)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="290"/> <source>Unconfirmed (%1 of %2 confirmations)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="293"/> <source>Confirmed (%1 confirmations)</source> <translation type="unfinished"></translation> </message> <message numerus="yes"> - <location filename="../transactiontablemodel.cpp" line="301"/> <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"/> <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"/> <source>Generated but not accepted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="352"/> <source>Received with</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="354"/> <source>Received from</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="357"/> <source>Sent to</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="359"/> <source>Payment to yourself</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="361"/> <source>Mined</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="399"/> <source>(n/a)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="598"/> <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"/> <source>Date and time that the transaction was received.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="602"/> <source>Type of transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="604"/> <source>Destination address of transaction.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactiontablemodel.cpp" line="606"/> <source>Amount removed from or added to balance.</source> <translation type="unfinished"></translation> </message> @@ -1781,256 +1511,137 @@ <context> <name>TransactionView</name> <message> - <location filename="../transactionview.cpp" line="55"/> - <location filename="../transactionview.cpp" line="71"/> <source>All</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="56"/> <source>Today</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="57"/> <source>This week</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="58"/> <source>This month</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="59"/> <source>Last month</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="60"/> <source>This year</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="61"/> <source>Range...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="72"/> <source>Received with</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="74"/> <source>Sent to</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="76"/> <source>To yourself</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="77"/> <source>Mined</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="78"/> <source>Other</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="85"/> <source>Enter address or label to search</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="92"/> <source>Min amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="126"/> <source>Copy address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="127"/> <source>Copy label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="128"/> <source>Copy amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="129"/> <source>Edit label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="130"/> <source>Show transaction details</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="270"/> <source>Export Transaction Data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="271"/> <source>Comma separated file (*.csv)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="279"/> <source>Confirmed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="280"/> <source>Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="281"/> <source>Type</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="282"/> <source>Label</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="283"/> <source>Address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="284"/> <source>Amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="285"/> <source>ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="289"/> <source>Error exporting</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="289"/> <source>Could not write to file %1.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="384"/> <source>Range:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../transactionview.cpp" line="392"/> <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"/> <source>Sending...</source> <translation type="unfinished"></translation> </message> @@ -2038,493 +1649,411 @@ <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="61"/> <source>Bitcoin version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="135"/> <source>Usage:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="113"/> <source>Send command to -server or bitcoind</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="95"/> <source>List commands</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="87"/> <source>Get help for a command</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="105"/> <source>Options:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="123"/> <source>Specify configuration file (default: bitcoin.conf)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="126"/> <source>Specify pid file (default: bitcoind.pid)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="86"/> <source>Generate coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="72"/> <source>Don't generate coins</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="125"/> <source>Specify data directory</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="120"/> <source>Set database cache size in megabytes (default: 25)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="121"/> <source>Set database disk log size in megabytes (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="124"/> <source>Specify connection timeout (in milliseconds)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="97"/> <source>Listen for connections on <port> (default: 8333 or testnet: 18333)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="101"/> <source>Maintain at most <n> connections to peers (default: 125)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="70"/> <source>Connect to a node to retrieve peer addresses, and disconnect</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="127"/> <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"/> <source>Bind to given address. Use [host]:port notation for IPv6</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="129"/> <source>Threshold for disconnecting misbehaving peers (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="35"/> <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> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../bitcoinstrings.cpp" line="103"/> - <source>Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)</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> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="54"/> <source>Accept command line and JSON-RPC commands</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> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="139"/> <source>Use the test network</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="106"/> - <source>Output extra debugging information</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> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="68"/> <source>Connect only to the specified node(s)</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> <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> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="108"/> + <source>Find peers using DNS lookup (default: 1 unless -connect)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Invalid -tor address: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Only connect to nodes in network <net> (IPv4, IPv6 or Tor)</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Output extra debugging information. Implies all other -debug* options</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Output extra network debugging information</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Prepend debug output with timestamp</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="112"/> <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"/> <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"/> <source>Send trace/debug info to debugger</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="137"/> <source>Use UPnP to map the listening port (default: 0)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="138"/> <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"/> + <source>Use proxy to reach tor hidden services (default: same as -proxy)</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Username for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="107"/> + <source>Warning: this version is obsolete, upgrade required</source> + <translation type="unfinished"></translation> + </message> + <message> <source>Password for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="96"/> <source>Listen for JSON-RPC connections on <port> (default: 8332)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="58"/> <source>Allow JSON-RPC connections from specified IP address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="114"/> <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"/> <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"/> <source>Upgrade wallet to latest format</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="122"/> <source>Set key pool size to <n> (default: 100)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="109"/> <source>Rescan the block chain for missing wallet transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="88"/> <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"/> <source>How thorough the block verification is (0-6, default: 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="90"/> <source>Imports blocks from external blk000?.dat file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="51"/> <source> SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="136"/> <source>Use OpenSSL (https) for JSON-RPC connections</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="118"/> <source>Server certificate file (default: server.cert)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="119"/> <source>Server private key (default: server.pem)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="17"/> <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"/> <source>Warning: Disk space is low</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="128"/> <source>This help message</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="20"/> <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"/> <source>Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="131"/> <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"/> <source>Connect through socks proxy</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="57"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="98"/> <source>Loading addresses...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="74"/> <source>Error loading blkindex.dat</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="76"/> <source>Error loading wallet.dat: Wallet corrupted</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="77"/> <source>Error loading wallet.dat: Wallet requires newer version of Bitcoin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="141"/> <source>Wallet needed to be rewritten: restart Bitcoin to complete</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="75"/> <source>Error loading wallet.dat</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="92"/> <source>Invalid -proxy address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="133"/> <source>Unknown network specified in -onlynet: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="132"/> <source>Unknown -socks proxy version requested: %i</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="65"/> <source>Cannot resolve -bind address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="66"/> <source>Cannot resolve -externalip address: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="93"/> <source>Invalid amount for -paytxfee=<amount>: '%s'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="81"/> <source>Error: could not start node</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="80"/> <source>Error: Wallet locked, unable to create transaction </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="29"/> <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"/> <source>Error: Transaction creation failed </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="117"/> <source>Sending...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="25"/> <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"/> <source>Invalid amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="91"/> <source>Insufficient funds</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="99"/> <source>Loading block index...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="56"/> <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"/> <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"/> <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"/> <source>Fee per KB to add to transactions you send</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="40"/> <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"/> <source>Loading wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="63"/> <source>Cannot downgrade wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="64"/> <source>Cannot initialize keypool</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="67"/> <source>Cannot write default address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="110"/> <source>Rescanning...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="73"/> <source>Done loading</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="130"/> <source>To use the %s option</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="8"/> <source>%s, you must set a rpcpassword in the configuration file: %s It is recommended you use the following random password: @@ -2536,24 +2065,20 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="78"/> <source>Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../bitcoinstrings.cpp" line="59"/> <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"/> <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"/> <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>
deleted file mode 100644 --- 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); -}
deleted file mode 100644 --- 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
--- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -40,7 +40,7 @@ { 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 @@ 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 @@ else return 9050; } + case ProxySocksVersion: + return settings.value("nSocksVersion", 5); case Fee: return QVariant(nTransactionFee); case DisplayUnit: @@ -192,11 +192,9 @@ 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 @@ 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 @@ settings.setValue("detachDB", fDetachDB); } break; - case Language: { + case Language: settings.setValue("language", value); - } break; default: break;
--- 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 @@ 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
--- 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->lblAmount->setVisible(enableReq); ui->lnReqAmount->setVisible(enableReq); - ui->lblAmount->setVisible(enableReq); - ui->lblBTC->setVisible(enableReq); ui->lnLabel->setText(label); + ui->btnSaveAs->setEnabled(false); + genCode(); } @@ -31,6 +37,17 @@ 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 @@ } } 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; - 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 @@ 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 @@ 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()); + } +}
--- 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 @@ 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; + OptionsModel *model; + QString address; QImage myImage; + void genCode(); QString getURI(); - QString address; - - void genCode(); }; #endif // QRCODEDIALOG_H
--- a/src/qt/qtipcserver.cpp +++ b/src/qt/qtipcserver.cpp @@ -6,6 +6,11 @@ #include <boost/interprocess/ipc/message_queue.hpp> #include <boost/tokenizer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/version.hpp> + +#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 #include "ui_interface.h" #include "qtipcserver.h" @@ -15,6 +20,14 @@ using namespace boost; using namespace std; +#ifdef MAC_OSX +// URI handling not implemented on OSX yet + +void ipcInit() { } +void ipcShutdown() { } + +#else + void ipcShutdown() { message_queue::remove(BITCOINURI_QUEUE_NAME); @@ -45,17 +58,6 @@ 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; char strBuf[257]; size_t nSize; @@ -87,3 +89,5 @@ delete mq; } } + +#endif
--- 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 @@ connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); + // set OpenSSL version label + ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); + startExecutor(); clear();
new file mode 100644 --- /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); +}
new file mode 100644 --- /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
--- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -59,7 +59,7 @@ 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));
--- 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 @@ { 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 @@ 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 @@ { 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 @@ // // 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 @@ 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 @@ // // 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 @@ 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 @@ } } - 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 @@ // 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 @@ // 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 @@ 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>"; }
deleted file mode 100644 --- 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); -}
deleted file mode 100644 --- 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
--- 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 @@ emit encryptionStatusChanged(newEncryptionStatus); } +void WalletModel::pollBalanceChanged() +{ + if(nBestHeight != cachedNumBlocks) + { + // Balance and number of transactions might have changed + cachedNumBlocks = nBestHeight; + checkBalanceChanged(); + } +} + +void WalletModel::checkBalanceChanged() +{ + qint64 newBalance = getBalance(); + qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + qint64 newImmatureBalance = getImmatureBalance(); + + 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 - qint64 newBalance = getBalance(); - qint64 newUnconfirmedBalance = getUnconfirmedBalance(); - qint64 newImmatureBalance = getImmatureBalance(); - int newNumTransactions = getNumTransactions(); - - if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); + 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)
--- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -10,6 +10,10 @@ class TransactionTableModel; class CWallet; +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + class SendCoinsRecipient { public: @@ -120,9 +124,14 @@ 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 @@ 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(); };
new file mode 100644 --- /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; +} +
new file mode 100644 --- /dev/null +++ b/src/rpcrawtransaction.cpp @@ -0,0 +1,483 @@ +// 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() > 3) + throw runtime_error( + "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...]\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" + "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); + + // 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); + + // ... 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(); +}
--- a/src/script.cpp +++ b/src/script.cpp @@ -1331,15 +1331,12 @@ { 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 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 @@ // 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 @@ 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); +} + +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 - return true; + 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
--- a/src/script.h +++ b/src/script.h @@ -452,7 +452,7 @@ 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 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
--- a/src/serialize.h +++ b/src/serialize.h @@ -809,7 +809,8 @@ 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 @@ 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 @@ #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);
--- a/src/sync.cpp +++ b/src/sync.cpp @@ -24,7 +24,7 @@ // --> 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
--- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -71,7 +71,7 @@ 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);
--- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -34,9 +34,9 @@ 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 @@ 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); }
--- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -328,5 +328,118 @@ 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()
--- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -121,7 +121,7 @@ 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);
--- a/src/util.cpp +++ b/src/util.cpp @@ -1142,7 +1142,7 @@ // "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
--- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -899,7 +899,7 @@ } // 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 @@ { 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)
--- a/src/wallet.h +++ b/src/wallet.h @@ -61,7 +61,6 @@ 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 @@ // 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 @@ // 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