diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | doc/build-unix.txt | 39 | ||||
-rw-r--r-- | doc/release-notes.txt | 101 | ||||
-rw-r--r-- | share/setup.nsi | 2 | ||||
-rw-r--r-- | src/addrman.cpp | 4 | ||||
-rw-r--r-- | src/addrman.h | 2 | ||||
-rw-r--r-- | src/base58.h | 2 | ||||
-rw-r--r-- | src/bitcoinrpc.cpp | 27 | ||||
-rw-r--r-- | src/clientversion.h | 2 | ||||
-rw-r--r-- | src/db.cpp | 4 | ||||
-rw-r--r-- | src/key.h | 2 | ||||
-rw-r--r-- | src/main.cpp | 65 | ||||
-rw-r--r-- | src/main.h | 50 | ||||
-rw-r--r-- | src/makefile.linux-mingw | 2 | ||||
-rw-r--r-- | src/makefile.mingw | 6 | ||||
-rw-r--r-- | src/makefile.osx | 5 | ||||
-rw-r--r-- | src/makefile.unix | 5 | ||||
-rw-r--r-- | src/netbase.cpp | 8 | ||||
-rw-r--r-- | src/qt/transactionrecord.cpp | 14 | ||||
-rw-r--r-- | src/rpcnet.cpp | 2 | ||||
-rw-r--r-- | src/rpcwallet.cpp | 4 | ||||
-rw-r--r-- | src/serialize.h | 52 | ||||
-rw-r--r-- | src/sync.cpp | 2 | ||||
-rw-r--r-- | src/test/accounting_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/data/tx_invalid.json | 40 | ||||
-rw-r--r-- | src/test/data/tx_valid.json | 21 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 10 | ||||
-rw-r--r-- | src/util.h | 4 | ||||
-rw-r--r-- | src/wallet.cpp | 11 | ||||
-rw-r--r-- | src/wallet.h | 9 | ||||
-rw-r--r-- | src/walletdb.cpp | 4 | ||||
-rw-r--r-- | src/walletdb.h | 6 |
32 files changed, 240 insertions, 268 deletions
diff --git a/.gitignore b/.gitignore index 2b70e2cca5..95152ce4fb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ src/*.exe src/bitcoin src/bitcoind src/test_bitcoin -src/build.h .*.swp *.*~* *.bak diff --git a/doc/build-unix.txt b/doc/build-unix.txt index 784d86e63d..b02a20a760 100644 --- a/doc/build-unix.txt +++ b/doc/build-unix.txt @@ -28,7 +28,6 @@ Dependencies libdb4.8 Berkeley DB Blockchain & wallet storage libboost Boost C++ Library miniupnpc UPnP Support Optional firewall-jumping support - libqrencode QRCode generation Optional QRCode generation miniupnpc may be used for UPnP port mapping. It can be downloaded from http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and @@ -37,13 +36,7 @@ turned off by default. Set USE_UPNP to a different value to control this: USE_UPNP=0 (the default) UPnP support turned off by default at runtime USE_UPNP=1 UPnP support turned on by default at runtime -libqrencode may be used for QRCode image generation. It can be downloaded -from http://fukuchi.org/works/qrencode/index.html.en, or installed via -your package manager. Set USE_QRCODE to control this: - USE_QRCODE=0 (the default) No QRCode support - libqrcode not required - USE_QRCODE=1 QRCode support enabled - -IPv6 support may be enabled by setting +IPv6 support may be enabled by setting: USE_IPV6=1 Enable IPv6 support Licenses of statically linked libraries: @@ -61,15 +54,27 @@ Versions used in this release: Dependency Build Instructions: Ubuntu & Debian ---------------------------------------------- -sudo apt-get install build-essential -sudo apt-get install libssl-dev -sudo apt-get install libdb4.8-dev -sudo apt-get install libdb4.8++-dev - Boost 1.40+: sudo apt-get install libboost-all-dev - or Boost 1.37: sudo apt-get install libboost1.37-dev -sudo apt-get install libqrencode-dev - -If using Boost 1.37, append -mt to the boost libraries in the makefile. +Build requirements: + sudo apt-get install build-essential + sudo apt-get install libssl-dev + +for Ubuntu 12.04: + sudo apt-get install libboost-all-dev + + db4.8 packages are available at: + https://launchpad.net/~bitcoin/+archive/bitcoin + + Ubuntu precise has packages for libdb5.1-dev and libdb5.1++-dev, + but using these will break binary wallet compatibility, and is not recommended. + +for other Ubuntu & Debian: + sudo apt-get install libdb4.8-dev + sudo apt-get install libdb4.8++-dev + sudo apt-get install libboost1.37-dev + (If using Boost 1.37, append -mt to the boost libraries in the makefile) + +Optional: + sudo apt-get install libminiupnpc-dev (see USE_UPNP compile flag) Dependency Build Instructions: Gentoo diff --git a/doc/release-notes.txt b/doc/release-notes.txt index c2fdc425fd..3c975af92f 100644 --- a/doc/release-notes.txt +++ b/doc/release-notes.txt @@ -3,7 +3,7 @@ release time) Building this from - $ git shortlog --no-merges v0.6.3.. + $ git shortlog --no-merges v0.7.0.. How to Upgrade -------------- @@ -19,99 +19,8 @@ Ubuntu PPA version), then run the old version again with the -detachdb argument and shut it down; if you do not, then the new version will not be able to read the database files and will exit with an error. -Incompatible Changes --------------------- -* Replaced the 'getmemorypool' RPC command with 'getblocktemplate/submitblock' - and 'getrawmempool' commands. -* Remove deprecated RPC 'getblocknumber' +Bug fixes +--------- +* Fixed an uninitialized variable bug that could cause transactions to + be reported out of order. -Bitcoin Improvement Proposals implemented ------------------------------------------ -BIP 22 - 'getblocktemplate', 'submitblock' RPCs -BIP 34 - block version 2, height in coinbase -BIP 35 - 'mempool' message, extended 'getdata' message behavior - - -Core bitcoin handling and blockchain database ---------------------------------------------- -* Reduced CPU usage, by eliminating some redundant hash calculations -* Cache signature verifications, to eliminate redundant signature checks -* Transactions with zero-value outputs are considered non-standard -* Mining: when creating new blocks, sort 'paid' area by fee-per-kb -* Database: better validation of on-disk stored data -* Database: minor optimizations and reliability improvements -* -loadblock=FILE will import an external block file -* Additional DoS (denial-of-service) prevention measures -* New blockchain checkpoint at block 193,000 -* (Windows only): enable ASLR and DEP for bitcoind.exe - - -JSON-RPC API ------------- -* Internal HTTP server is now thread-per-connection, rather than - a single-threaded queue that would stall on network I/O. -* Internal HTTP server supports HTTP/1.1, pipelined requests and - connection keep-alive. -* Support JSON-RPC 2.0 batches, to encapsulate multiple JSON-RPC requests - within a single HTTP request. -* IPv6 support -* Added raw transaction API. See https://gist.github.com/2839617 -* Added 'getrawmempool', to list contents of TX memory pool -* Added 'getpeerinfo', to list data about each connected network peer -* Added 'listaddressgroupings' for better coin control -* Rework gettransaction, getblock calls. 'gettransaction' responds for - non-wallet TXs now. -* Remove deprecated RPC 'getblocknumber' -* Remove superceded RPC 'getmemorypool' (see BIP 22, above) -* listtransactions output now displays "smart" times for transactions, - and 'blocktime' and 'timereceived' fields were added - - -P2P networking --------------- -* IPv6 support -* Tor hidden service support (see doc/Tor.txt) -* Attempts to fix "stuck blockchain download" problems -* Replace BDB database "addr.dat" with internally-managed "peers.dat" - file containing peer address data. -* Lower default send buffer from 10MB to 1MB -* proxy: SOCKS5 by default -* Support connecting by hostnames passed to proxy -* Add -seednode connections, and use this instead of DNS seeds when proxied -* Added -externalip and -discover -* Add -onlynet to connect only to a given network (IPv4, IPv6, or Tor) -* Separate listening sockets, -bind=<addr> - - -Qt GUI ------- -* Add UI RPC console / debug window -* Re-Enable URI handling on Windows, add safety checks and tray-notifications -* Harmonize the use of ellipsis ("...") to be used in menus, but not on buttons -* Add 2 labels to the overviewpage that display Wallet and Transaction status (obsolete or current) -* Extend the optionsdialog (e.g. language selection) and re-work it to a tabbed UI -* Merge sign/verify message into a single window with tabbed UI -* Ensure a changed bitcoin unit immediately updates all GUI elements that use units -* Update QR Code dialog -* Improve error reporting at startup -* Fine-grained UI updates for a much smoother UI during block downloads -* Remove autocorrection of 0/i in addresses in UI -* Reorganize tray icon menu into more logical order -* Persistently poll for balance change when number of blocks changed -* Much better translations -* Override progress bar design on platforms with segmented progress bars to assist with readability -* Added 'immature balance' display on the overview page -* (Windows only): enable ASLR and DEP for bitcoin-qt.exe -* (Windows only): add meta-data to bitcoin-qt.exe (e.g. description and version) - -Internal codebase ------------------ -* Additional unit tests -* Compile warning fixes - - -Miscellaneous -------------- -* Reopen debug.log upon SIGHUP -* Bash programmable completion for bitcoind(1) -* On supported OSes, each thread is given a useful name diff --git a/share/setup.nsi b/share/setup.nsi index d46e1e68ae..4e48718a49 100644 --- a/share/setup.nsi +++ b/share/setup.nsi @@ -51,7 +51,7 @@ CRCCheck on XPStyle on
BrandingText " "
ShowInstDetails show
-VIProductVersion 0.7.0.2
+VIProductVersion 0.7.0.3
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
diff --git a/src/addrman.cpp b/src/addrman.cpp index 321ebd1e2b..4428cd169a 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -187,7 +187,7 @@ int CAddrMan::ShrinkNew(int nUBucket) } assert(mapInfo.count(nOldest) == 1); CAddrInfo &info = mapInfo[nOldest]; - if (--info.nRefCount == 0) + if (--info.nRefCount == 0) { SwapRandom(info.nRandomPos, vRandom.size()-1); vRandom.pop_back(); @@ -241,7 +241,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) infoOld.nRefCount = 1; // do not update nTried, as we are going to move something else there immediately - // check whether there is place in that one, + // check whether there is place in that one, if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE) { // if so, move it back there diff --git a/src/addrman.h b/src/addrman.h index 7c141c427b..7af6afd78f 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -214,7 +214,7 @@ protected: // This is the only place where actual deletes occur. // They are never deleted while in the "tried" table, only possibly evicted back to the "new" table. int ShrinkNew(int nUBucket); - + // Move an entry from the "new" table(s) to the "tried" table // @pre vvUnkown[nOrigin].count(nId) != 0 void MakeTried(CAddrInfo& info, int nId, int nOrigin); diff --git a/src/base58.h b/src/base58.h index fc8c8aa5de..9dfea86ff5 100644 --- a/src/base58.h +++ b/src/base58.h @@ -403,7 +403,7 @@ class CBitcoinSecret : public CBase58Data { public: void SetSecret(const CSecret& vchSecret, bool fCompressed) - { + { assert(vchSecret.size() == 32); SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size()); if (fCompressed) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 84a6d6f896..1a3f51ea4d 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -761,17 +761,19 @@ void ThreadRPCServer2(void* parg) const bool loopback = !mapArgs.count("-rpcallowip"); asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332)); + boost::system::error_code v6_only_error; + boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service)); boost::signals2::signal<void ()> StopRequests; + bool fListening = false; + std::string strerr; try { - boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service)); acceptor->open(endpoint.protocol()); acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); // Try making the socket dual IPv6/IPv4 (if listening on the "any" address) - boost::system::error_code v6_only_error; acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); acceptor->bind(endpoint); @@ -783,8 +785,16 @@ void ThreadRPCServer2(void* parg) static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get()) .track(acceptor)); + fListening = true; + } + catch(boost::system::system_error &e) + { + strerr = strprintf(_("An error occurred while setting up the RPC port %i for listening on IPv6, falling back to IPv4: %s"), endpoint.port(), e.what()); + } + + try { // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately - if (loopback || v6_only_error) + if (!fListening || loopback || v6_only_error) { bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any(); endpoint.address(bindAddress); @@ -800,12 +810,17 @@ void ThreadRPCServer2(void* parg) StopRequests.connect(signals2::slot<void ()>( static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get()) .track(acceptor)); + + fListening = true; } } catch(boost::system::system_error &e) { - uiInterface.ThreadSafeMessageBox(strprintf(_("An error occurred while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()), - _("Error"), CClientUIInterface::OK | CClientUIInterface::MODAL); + strerr = strprintf(_("An error occurred while setting up the RPC port %i for listening on IPv4: %s"), endpoint.port(), e.what()); + } + + if (!fListening) { + uiInterface.ThreadSafeMessageBox(strerr, _("Error"), CClientUIInterface::OK | CClientUIInterface::MODAL); StartShutdown(); return; } @@ -968,7 +983,7 @@ void ThreadRPCServer3(void* parg) strReply = JSONRPCExecBatch(valRequest.get_array()); else throw JSONRPCError(-32700, "Top-level object parse error"); - + conn->stream() << HTTPReply(200, strReply, fRun) << std::flush; } catch (Object& objError) diff --git a/src/clientversion.h b/src/clientversion.h index 844eaa37bb..548105383c 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 7 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 99 // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! diff --git a/src/db.cpp b/src/db.cpp index 015e7ec2de..867703fbd2 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -281,7 +281,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); Db* pdbCopy = new Db(&bitdb.dbenv, 0); - + int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename "main", // Logical db name @@ -293,7 +293,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) printf("Cannot create database file %s\n", strFileRes.c_str()); fSuccess = false; } - + Dbc* pcursor = db.GetCursor(); if (pcursor) while (fSuccess) @@ -99,7 +99,7 @@ public: }; -// secure_allocator is defined in serialize.h +// secure_allocator is defined in allocators.h // CPrivKey is a serialized private key, with all parameters included (279 bytes) typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; // CSecret is a serialization of just the secret parameter (32 bytes) diff --git a/src/main.cpp b/src/main.cpp index 302292ee29..fbaf05dfc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -477,6 +477,55 @@ bool CTransaction::CheckTransaction() const return true; } +int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, + enum GetMinFee_mode mode) const +{ + // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE + int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; + + unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); + unsigned int nNewBlockSize = nBlockSize + nBytes; + int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; + + if (fAllowFree) + { + if (nBlockSize == 1) + { + // Transactions under 10K are free + // (about 4500 BTC if made of 50 BTC inputs) + if (nBytes < 10000) + nMinFee = 0; + } + else + { + // Free transaction area + if (nNewBlockSize < 27000) + nMinFee = 0; + } + } + + // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 + if (nMinFee < nBaseFee) + { + BOOST_FOREACH(const CTxOut& txout, vout) + if (txout.nValue < CENT) + nMinFee = nBaseFee; + } + + // Raise the price as the block approaches full + if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) + { + if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) + return MAX_MONEY; + nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize); + } + + if (!MoneyRange(nMinFee)) + nMinFee = MAX_MONEY; + return nMinFee; +} + + bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, bool* pfMissingInputs) { @@ -563,8 +612,11 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); // Don't accept it if it can't get into a block - if (nFees < tx.GetMinFee(1000, true, GMF_RELAY)) - return error("CTxMemPool::accept() : not enough fees"); + int64 txMinFee = tx.GetMinFee(1000, true, GMF_RELAY); + if (nFees < txMinFee) + return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d, + hash.ToString().c_str(), + nFees, txMinFee); // Continuously rate-limit free transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to @@ -1360,9 +1412,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) // See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information. // This logic is not necessary for memory pool transactions, as AcceptToMemoryPool // already refuses previously-known transaction ids entirely. - // This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC. - int64 nBIP30SwitchTime = 1331769600; - bool fEnforceBIP30 = (pindex->nTime > nBIP30SwitchTime); + // This rule was originally applied all blocks whose timestamp was after March 15, 2012, 0:00 UTC. + // Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the + // two in the chain that violate it. This prevents exploiting the issue against nodes in their + // initial block download. + bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || + (pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); // BIP16 didn't become active until Apr 1 2012 int64 nBIP16SwitchTime = 1333238400; diff --git a/src/main.h b/src/main.h index e61cbdd46b..2e208fed4f 100644 --- a/src/main.h +++ b/src/main.h @@ -540,53 +540,7 @@ public: return dPriority > COIN * 144 / 250; } - int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const - { - // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE - int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; - - unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); - unsigned int nNewBlockSize = nBlockSize + nBytes; - int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; - - if (fAllowFree) - { - if (nBlockSize == 1) - { - // Transactions under 10K are free - // (about 4500 BTC if made of 50 BTC inputs) - if (nBytes < 10000) - nMinFee = 0; - } - else - { - // Free transaction area - if (nNewBlockSize < 27000) - nMinFee = 0; - } - } - - // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 - if (nMinFee < nBaseFee) - { - BOOST_FOREACH(const CTxOut& txout, vout) - if (txout.nValue < CENT) - nMinFee = nBaseFee; - } - - // Raise the price as the block approaches full - if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) - { - if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) - return MAX_MONEY; - nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize); - } - - if (!MoneyRange(nMinFee)) - nMinFee = MAX_MONEY; - return nMinFee; - } - + int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const; bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) { @@ -799,7 +753,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + }; diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index 4ba0cf06f0..2804f14055 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -111,6 +111,6 @@ clean: -rm -f bitcoind.exe -rm -f obj-test/*.o -rm -f test_bitcoin.exe - -rm -f src/build.h + -rm -f obj/build.h FORCE: diff --git a/src/makefile.mingw b/src/makefile.mingw index 55c5b7e387..5cb2c84f4d 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -83,6 +83,9 @@ OBJS= \ all: bitcoind.exe +test check: test_bitcoin.exe FORCE + test_bitcoin.exe + obj/%.o: %.cpp $(HEADERS) g++ -c $(CFLAGS) -o $@ $< @@ -101,4 +104,5 @@ clean: -del /Q bitcoind test_bitcoin -del /Q obj\* -del /Q obj-test\* - -del /Q build.h + +FORCE: diff --git a/src/makefile.osx b/src/makefile.osx index 2666caa918..359739bd5e 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -116,6 +116,9 @@ endif all: bitcoind +test check: test_bitcoin FORCE + ./test_bitcoin + # auto-generated dependencies: -include obj/*.P -include obj-test/*.P @@ -153,6 +156,6 @@ clean: -rm -f obj-test/*.o -rm -f obj/*.P -rm -f obj-test/*.P - -rm -f src/build.h + -rm -f obj/build.h FORCE: diff --git a/src/makefile.unix b/src/makefile.unix index 37a1917973..a41b57b4fc 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -132,6 +132,9 @@ OBJS= \ all: bitcoind +test check: test_bitcoin FORCE + ./test_bitcoin + # auto-generated dependencies: -include obj/*.P -include obj-test/*.P @@ -169,6 +172,6 @@ clean: -rm -f obj-test/*.o -rm -f obj/*.P -rm -f obj-test/*.P - -rm -f src/build.h + -rm -f obj/build.h FORCE: diff --git a/src/netbase.cpp b/src/netbase.cpp index b66c366641..76a3d25d3a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -246,7 +246,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) string strSocks5("\5\1"); strSocks5 += '\000'; strSocks5 += '\003'; strSocks5 += static_cast<char>(std::min((int)strDest.size(), 255)); - strSocks5 += strDest; + strSocks5 += strDest; strSocks5 += static_cast<char>((port >> 8) & 0xFF); strSocks5 += static_cast<char>((port >> 0) & 0xFF); ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL); @@ -478,7 +478,7 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) // first connect to proxy server if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) return false; - + // do socks negotiation switch (proxy.second) { case 4: @@ -617,8 +617,8 @@ bool CNetAddr::IsIPv6() const bool CNetAddr::IsRFC1918() const { return IsIPv4() && ( - GetByte(3) == 10 || - (GetByte(3) == 192 && GetByte(2) == 168) || + GetByte(3) == 10 || + (GetByte(3) == 192 && GetByte(2) == 168) || (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31))); } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index cc60e2732b..4c3071984f 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -9,18 +9,8 @@ bool TransactionRecord::showTransaction(const CWalletTx &wtx) { if (wtx.IsCoinBase()) { - // Don't show generated coin until confirmed by at least one block after it - // so we don't get the user's hopes up until it looks like it's probably accepted. - // - // It is not an error when generated blocks are not accepted. By design, - // some percentage of blocks, like 10% or more, will end up not accepted. - // This is the normal mechanism by which the network copes with latency. - // - // We display regular transactions right away before any confirmation - // because they can always get into some block eventually. Generated coins - // are special because if their block is not accepted, they are not valid. - // - if (wtx.GetDepthInMainChain() < 2) + // Ensures we show generated coins / mined transactions at depth 1 + if (!wtx.IsInMainChain()) { return false; } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index f0038dea9f..491297eb1d 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -61,7 +61,7 @@ Value getpeerinfo(const Array& params, bool fHelp) ret.push_back(obj); } - + return ret; } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 929dde9c15..3d0d05de84 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -573,7 +573,7 @@ Value movecmd(const Array& params, bool fHelp) // Debit CAccountingEntry debit; - debit.nOrderPos = pwalletMain->nOrderPosNext++; + debit.nOrderPos = pwalletMain->IncOrderPosNext(); debit.strAccount = strFrom; debit.nCreditDebit = -nAmount; debit.nTime = nNow; @@ -583,7 +583,7 @@ Value movecmd(const Array& params, bool fHelp) // Credit CAccountingEntry credit; - credit.nOrderPos = pwalletMain->nOrderPosNext++; + credit.nOrderPos = pwalletMain->IncOrderPosNext(); credit.strAccount = strTo; credit.nCreditDebit = nAmount; credit.nTime = nNow; diff --git a/src/serialize.h b/src/serialize.h index abc4f04a0d..63df3160a6 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -243,7 +243,6 @@ uint64 ReadCompactSize(Stream& is) #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) /** Wrapper for serializing arrays and POD. - * There's a clever template way to make arrays serialize normally, but MSVC6 doesn't support it. */ class CFlatData { @@ -1010,57 +1009,6 @@ public: } }; -#ifdef TESTCDATASTREAM -// VC6sp6 -// CDataStream: -// n=1000 0 seconds -// n=2000 0 seconds -// n=4000 0 seconds -// n=8000 0 seconds -// n=16000 0 seconds -// n=32000 0 seconds -// n=64000 1 seconds -// n=128000 1 seconds -// n=256000 2 seconds -// n=512000 4 seconds -// n=1024000 8 seconds -// n=2048000 16 seconds -// n=4096000 32 seconds -// stringstream: -// n=1000 1 seconds -// n=2000 1 seconds -// n=4000 13 seconds -// n=8000 87 seconds -// n=16000 400 seconds -// n=32000 1660 seconds -// n=64000 6749 seconds -// n=128000 27241 seconds -// n=256000 109804 seconds -#include <iostream> -int main(int argc, char *argv[]) -{ - vector<unsigned char> vch(0xcc, 250); - printf("CDataStream:\n"); - for (int n = 1000; n <= 4500000; n *= 2) - { - CDataStream ss; - time_t nStart = time(NULL); - for (int i = 0; i < n; i++) - ss.write((char*)&vch[0], vch.size()); - printf("n=%-10d %d seconds\n", n, time(NULL) - nStart); - } - printf("stringstream:\n"); - for (int n = 1000; n <= 4500000; n *= 2) - { - stringstream ss; - time_t nStart = time(NULL); - for (int i = 0; i < n; i++) - ss.write((char*)&vch[0], vch.size()); - printf("n=%-10d %d seconds\n", n, time(NULL) - nStart); - } -} -#endif - diff --git a/src/sync.cpp b/src/sync.cpp index 54ad7de4e6..1ac4403beb 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -105,7 +105,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void pop_lock() { - if (fDebug) + if (fDebug) { const CLockLocation& locklocation = (*lockstack).rbegin()->second; printf("Unlocked: %s\n", locklocation.ToString().c_str()); diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index c474fd65c1..8ac657288b 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333330; ae.strOtherAccount = "d"; - ae.nOrderPos = pwalletMain->nOrderPosNext++; + ae.nOrderPos = pwalletMain->IncOrderPosNext(); walletdb.WriteAccountingEntry(ae); GetResults(walletdb, results); diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 432dd3f496..f01ee06cfa 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -21,6 +21,44 @@ ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true] +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], +["Tests for CTransaction::CheckTransaction()"], +["No inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"0100000000010000000000000000015100000000", true], + +["No outputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], + +["Negative output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", true], + +["MAX_MONEY + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], + +["MAX_MONEY output + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], + +["Duplicate inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]], +"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", true], + +["Coinbase of size 1"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 101"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], + +["Null txin"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index cc4b28f6b4..5528ae7243 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -48,5 +48,24 @@ ["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true] +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], + +["Tests for CTransaction::CheckTransaction()"], +["MAX_MONEY output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], + +["MAX_MONEY output + 0 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], + +["Coinbase of size 2"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 100"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true] ] diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index de6e18f14d..c230458866 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -66,6 +66,8 @@ BOOST_AUTO_TEST_CASE(tx_valid) CTransaction tx; stream >> tx; + BOOST_CHECK_MESSAGE(tx.CheckTransaction(), strTest); + for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -131,7 +133,9 @@ BOOST_AUTO_TEST_CASE(tx_invalid) CTransaction tx; stream >> tx; - for (unsigned int i = 0; i < tx.vin.size(); i++) + fValid = tx.CheckTransaction(); + + for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) { @@ -139,8 +143,10 @@ BOOST_AUTO_TEST_CASE(tx_invalid) break; } - BOOST_CHECK_MESSAGE(!VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest); + fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0); } + + BOOST_CHECK_MESSAGE(!fValid, strTest); } } } diff --git a/src/util.h b/src/util.h index 65923e68a3..2409ccb79c 100644 --- a/src/util.h +++ b/src/util.h @@ -483,7 +483,7 @@ inline uint160 Hash160(const std::vector<unsigned char>& vch) } -/** Median filter over a stream of values. +/** Median filter over a stream of values. * Returns the median of the last N numbers */ template <typename T> class CMedianFilter @@ -500,7 +500,7 @@ public: vValues.push_back(initial_value); vSorted = vValues; } - + void input(T value) { if(vValues.size() == nSize) diff --git a/src/wallet.cpp b/src/wallet.cpp index f88a0e1413..a10f187309 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -291,6 +291,13 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } +int64 CWallet::IncOrderPosNext() +{ + int64 nRet = nOrderPosNext; + CWalletDB(strWalletFile).WriteOrderPosNext(++nOrderPosNext); + return nRet; +} + CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount) { CWalletDB walletdb(strWalletFile); @@ -362,7 +369,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) if (fInsertedNew) { wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = nOrderPosNext++; + wtx.nOrderPos = IncOrderPosNext(); wtx.nTimeSmart = wtx.nTimeReceived; if (wtxIn.hashBlock != 0) @@ -953,7 +960,7 @@ int64 CWallet::GetImmatureBalance() const for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx& pcoin = (*it).second; - if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.GetDepthInMainChain() >= 2) + if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain()) nTotal += GetCredit(pcoin); } } diff --git a/src/wallet.h b/src/wallet.h index 7fd33629fe..22795b75ba 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -98,6 +98,7 @@ public: fFileBacked = false; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; + nOrderPosNext = 0; } CWallet(std::string strWalletFileIn) { @@ -107,6 +108,7 @@ public: fFileBacked = true; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; + nOrderPosNext = 0; } std::map<uint256, CWalletTx> mapWallet; @@ -144,6 +146,11 @@ public: bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); + /** Increment the next transaction order id + @return next transaction order id + */ + int64 IncOrderPosNext(); + typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; typedef std::multimap<int64, TxPair > TxItems; @@ -346,7 +353,7 @@ static void WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue) } -/** A transaction with a bunch of additional info that only the owner cares about. +/** A transaction with a bunch of additional info that only the owner cares about. * It includes any unrecorded transactions needed to link it back to the block chain. */ class CWalletTx : public CMerkleTx diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 164b68e11f..0fac0109c8 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -392,6 +392,10 @@ int CWalletDB::LoadWallet(CWallet* pwallet) return DB_CORRUPT; } } + else if (strType == "orderposnext") + { + ssValue >> pwallet->nOrderPosNext; + } } pcursor->close(); } diff --git a/src/walletdb.h b/src/walletdb.h index 187be65a97..d339d4c3f1 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -115,6 +115,12 @@ public: return Read(std::string("bestblock"), locator); } + bool WriteOrderPosNext(int64 nOrderPosNext) + { + nWalletDBUpdated++; + return Write(std::string("orderposnext"), nOrderPosNext); + } + bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey) { vchPubKey.clear(); |