diff options
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | contrib/gitian-downloader/centaur1-key.pgp | 30 | ||||
-rw-r--r-- | contrib/linearize/README.md | 6 | ||||
-rwxr-xr-x | contrib/linearize/linearize-data.py | 12 | ||||
-rw-r--r-- | doc/README.md | 1 | ||||
-rw-r--r-- | doc/REST-interface.md | 3 | ||||
-rw-r--r-- | doc/gitian-building.md | 2 | ||||
-rw-r--r-- | doc/shared-libraries.md | 42 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/coins.cpp | 14 | ||||
-rw-r--r-- | src/coins.h | 4 | ||||
-rw-r--r-- | src/compat.h | 8 | ||||
-rw-r--r-- | src/core_memusage.h | 62 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/memusage.h | 66 | ||||
-rw-r--r-- | src/net.cpp | 18 | ||||
-rw-r--r-- | src/netbase.cpp | 3 | ||||
-rw-r--r-- | src/primitives/transaction.cpp | 5 | ||||
-rw-r--r-- | src/primitives/transaction.h | 9 | ||||
-rw-r--r-- | src/qt/coincontroldialog.cpp | 15 | ||||
-rw-r--r-- | src/qt/paymentrequestplus.cpp | 4 | ||||
-rw-r--r-- | src/qt/paymentserver.cpp | 4 | ||||
-rw-r--r-- | src/qt/transactiondesc.cpp | 6 | ||||
-rw-r--r-- | src/qt/walletmodel.cpp | 2 | ||||
-rw-r--r-- | src/rpcblockchain.cpp | 2 | ||||
-rw-r--r-- | src/script/script.cpp | 5 | ||||
-rw-r--r-- | src/script/script.h | 3 | ||||
-rw-r--r-- | src/test/coins_tests.cpp | 4 | ||||
-rw-r--r-- | src/txmempool.cpp | 2 |
29 files changed, 209 insertions, 132 deletions
diff --git a/configure.ac b/configure.ac index 8a54c2f76e..7f90b5f395 100644 --- a/configure.ac +++ b/configure.ac @@ -147,12 +147,13 @@ AC_ARG_ENABLE([debug], [enable_debug=no]) if test "x$enable_debug" = xyes; then + CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then - CFLAGS="-g3 -O0 -DDEBUG" + CFLAGS="$CFLAGS -g3 -O0" fi if test "x$GXX" = xyes; then - CXXFLAGS="-g3 -O0 -DDEBUG" + CXXFLAGS="$CXXFLAGS -g3 -O0" fi fi diff --git a/contrib/gitian-downloader/centaur1-key.pgp b/contrib/gitian-downloader/centaur1-key.pgp new file mode 100644 index 0000000000..71a42e5148 --- /dev/null +++ b/contrib/gitian-downloader/centaur1-key.pgp @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQENBFTjy20BCAC7q/tpPQ9tdEALpDqe8kpVAT5ysOJDLDeFEE1J5O8NuDFuibiN +XYkb2nAt4Vdr23in9z0LAiTSgr7znndnab/rOSn6pXbXQfLTHrSnAeClTHVQVPSq +m5kNg1vWvNxFtIpZ/fGsc6LLmIHxdgeLn+NOpvNx7RzF/N5ctX51vMxMUeDq3daZ +tLneJVRj5tXHRJcjW62cyiNFasYAZ3JC8wjwzr0SOndc7kygbEVCTWNkTAGd1Lax +KSJW6TjhBPK7j+RljS5nfx/Tf+OG4AoA7/53593YL7Shfx8rwWVIeF4nS6efFnuf +eIj+aS5haGyFvNgw8DE7QUCrPiUxeA8wuXu7ABEBAAG0H2NlbnRhdXIgPGNlbnRh +dXJAcGhvbmVib29rLmNvbT6JATgEEwECACIFAlTjy20CGwMGCwkIBwMCBhUIAgkK +CwQWAgMBAh4BAheAAAoJEP+V+qlxaXQF8r4IAKnE8D9AOTdM/YvYxpCeI6ndEUUs +8NcotpbIBJ67vr1Dsot7Ee0PrmIYOiInA+T81lPUDecJYrnemVefhquiyJ5VJ4/d +z2zUKBfxjeOsj/PHgcowVxMco8fNEWQa2fZX6X8RVADIsUnIIwpRFVUcbssK/3xJ +k46vjWwYNQywht/ZgFBesOgywyz5GozmwrK6TixJxKk8M69GFz2fHhJjp1bxDZuk +Rs3YmWeOcCasoJ6GbvIboKQSPHGyEOCqIuiBL63YMa0n1FU0ooDteNZ04eRinIhc +fo9JC66fQrUFn8CmmRTtdZOrZ/efYjQtfLAunCkzSM3p6DE9u4Y7d8E5Ar65AQ0E +VOPLbQEIANhxtouZuQmw+k89toBWXw75s+csxKHKZuhw8QntaFyFYq3IOnIeV1sK +PRENkWsqDInjEM8k9eZ6pnS11EQ1rrFffss+mprTbL3I4S489tJETYZKHrmmox7h +ustRi5eXBEmGeKW0mqpb/9r4okpTaIfs+EJ4C9jj0ghWkqU0acyzanJiUY/0R46F +vPfGfHnhZ5TAl3eiL0H2JkF6taG8K1XOLemahdZHE9wJh0ZFWnDDkA1l6j2rtYga +jEi/ucOp5GkmumxbFiVgponDBqBpsscRrCV6SbZs9gz3dQNgqe5A3CKGZRuVCY6s +djRJelgqCF5+dV0fAT0oF3C/3E5KAgcAEQEAAYkBHwQYAQIACQUCVOPLbQIbDAAK +CRD/lfqpcWl0BUSxCACjEFwQSHcfZINWD+KdNMayxyHQlBwsEDX+xQkgnn+/Q3hW +9VI3SSSfFV3ustlUa3IaNHwuWzsrSqG6mLG47LAQ6vPAWVh723gVCpyJf42Oms/e +qeyn0f/PT/6RuNMXQeHbfddmRp4PFjyKOms5Bmf3oi4t4JSvOS4yABBBKzhDQYC9 +e+qv6Y1sDYpSiCxstQLzIHKiB5bfZ8Szfk09EyyLdqLGkiB0MFhHoXWwQxKiLVc+ +xNFj2a/jw0rQVgN5DZgHBWU5WqvS5CWIczi+2S9MFI26iBhCn3urZToaaQ/DObqC +qmekFrJ/GOj5vB1Mm014lWjG2X3EovLZ1XkgWI7W +=vtNZ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index 157586e4d4..06f278f3b3 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -3,7 +3,7 @@ Construct a linear, no-fork, best version of the blockchain. ## Step 1: Download hash list - $ ./linearize-hashes.py linearize.cfg > hashlist.txt + $ ./linearize-hashes.py linearize.cfg > hashlist.txt Required configuration file settings for linearize-hashes: * RPC: rpcuser, rpcpassword @@ -14,7 +14,7 @@ Optional config file setting for linearize-hashes: ## Step 2: Copy local block data - $ ./linearize-data.py linearize.cfg + $ ./linearize-data.py linearize.cfg Required configuration file settings: * "input": bitcoind blocks/ directory containing blkNNNNN.dat @@ -26,7 +26,7 @@ output. Optional config file setting for linearize-data: * "netmagic": network magic number -* "max_out_sz": maximum output file size (default 1000*1000*1000) +* "max_out_sz": maximum output file size (default `1000*1000*1000`) * "split_timestamp": Split files when a new month is first seen, in addition to reaching a maximum file size. * "file_timestamp": Set each file's last-modified time to that of the diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 7947c6bf72..0f6fde2a6e 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -12,6 +12,7 @@ import json import struct import re import os +import os.path import base64 import httplib import sys @@ -115,19 +116,20 @@ class BlockDataCopier: self.setFileTime = True if settings['split_timestamp'] != 0: self.timestampSplit = True - # Extents and cache for out-of-order blocks + # Extents and cache for out-of-order blocks self.blockExtents = {} self.outOfOrderData = {} self.outOfOrderSize = 0 # running total size for items in outOfOrderData def writeBlock(self, inhdr, blk_hdr, rawblock): - if not self.fileOutput and ((self.outsz + self.inLen) > self.maxOutSz): + blockSizeOnDisk = len(inhdr) + len(blk_hdr) + len(rawblock) + if not self.fileOutput and ((self.outsz + blockSizeOnDisk) > self.maxOutSz): self.outF.close() if self.setFileTime: os.utime(outFname, (int(time.time()), highTS)) self.outF = None self.outFname = None - self.outFn = outFn + 1 + self.outFn = self.outFn + 1 self.outsz = 0 (blkDate, blkTS) = get_blk_dt(blk_hdr) @@ -147,7 +149,7 @@ class BlockDataCopier: if self.fileOutput: outFname = self.settings['output_file'] else: - outFname = "%s/blk%05d.dat" % (self.settings['output'], outFn) + outFname = os.path.join(self.settings['output'], "blk%05d.dat" % self.outFn) print("Output file " + outFname) self.outF = open(outFname, "wb") @@ -165,7 +167,7 @@ class BlockDataCopier: (self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex))) def inFileName(self, fn): - return "%s/blk%05d.dat" % (self.settings['input'], fn) + return os.path.join(self.settings['input'], "blk%05d.dat" % fn) def fetchBlock(self, extent): '''Fetch block contents from disk given extents''' diff --git a/doc/README.md b/doc/README.md index ecddf50d4b..7b0c39d383 100644 --- a/doc/README.md +++ b/doc/README.md @@ -58,6 +58,7 @@ The Bitcoin repo's [root README](https://github.com/bitcoin/bitcoin/blob/master/ - [Translation Strings Policy](translation_strings_policy.md) - [Unit Tests](unit-tests.md) - [Unauthenticated REST Interface](REST-interface.md) +- [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) - [Dnsseed Policy](dnsseed-policy.md) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 3268ade7a5..ac7cd45f70 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -40,6 +40,9 @@ Only supports JSON as output format. * difficulty : (numeric) the current difficulty * verificationprogress : (numeric) estimate of verification progress [0..1] * chainwork : (string) total amount of work in active chain, in hexadecimal +* pruned : (boolean) if the blocks are subject to pruning +* pruneheight : (numeric) heighest block available +* softforks : (array) status of softforks in progress ####Query UTXO set `GET /rest/getutxos/<checkmempool>/<txid>-<n>/<txid>-<n>/.../<txid>-<n>.<bin|hex|json>` diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 1fa5b5f989..630b3c04a7 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -74,7 +74,7 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the - Disk size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side - Push the `Create` button -Get the [Debian 7.8 net installer](http://cdimage.debian.org/debian-cd/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +Get the [Debian 7.8 net installer](http://cdimage.debian.org/cdimage/archive/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). This DVD image can be validated using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md new file mode 100644 index 0000000000..1fc32112ce --- /dev/null +++ b/doc/shared-libraries.md @@ -0,0 +1,42 @@ +Shared Libraries +================ + +## bitcoinconsensus + +The purpose of this library is to make the verification functionality that is critical to Bitcoin's consensus available to other applications, e.g. to language bindings. + +### API + +The interface is defined in the C header `bitcoinconsensus.h` located in `src/script/bitcoinconsensus.h`. + +#### Version + +`bitcoinconsensus_version` returns an `unsigned int` with the the API version *(currently at an experimental `0`)*. + +#### Script Validation + +`bitcoinconsensus_verify_script` returns an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`. + +##### Parameters +- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending. +- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`. +- `const unsigned char *txTo` - The transaction with the input that is spending the previous output. +- `unsigned int txToLen` - The number of bytes for the `txTo`. +- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`. +- `unsigned int flags` - The script validation flags *(see below)*. +- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*. + +##### Script Flags +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE` +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance + +##### Errors +- `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)* +- `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo` +- `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo` +- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo` + +### Example Implementations +- [NBitcoin](https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Script.cs#L814) (.NET Bindings) +- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings) diff --git a/src/Makefile.am b/src/Makefile.am index b82c6dc37a..cc8dded413 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ BITCOIN_CORE_H = \ consensus/params.h \ consensus/validation.h \ core_io.h \ + core_memusage.h \ eccryptoverify.h \ ecwrapper.h \ hash.h \ diff --git a/src/coins.cpp b/src/coins.cpp index a41d5a310d..f02949de53 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -83,7 +83,7 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const // version as fresh. ret->second.flags = CCoinsCacheEntry::FRESH; } - cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins); + cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage(); return ret; } @@ -110,7 +110,7 @@ CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) { ret.first->second.flags = CCoinsCacheEntry::FRESH; } } else { - cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins); + cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage(); } // Assume that whenever ModifyCoins is called, the entry will be modified. ret.first->second.flags |= CCoinsCacheEntry::DIRTY; @@ -159,7 +159,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn assert(it->second.flags & CCoinsCacheEntry::FRESH); CCoinsCacheEntry& entry = cacheCoins[it->first]; entry.coins.swap(it->second.coins); - cachedCoinsUsage += memusage::DynamicUsage(entry.coins); + cachedCoinsUsage += entry.coins.DynamicMemoryUsage(); entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH; } } else { @@ -167,13 +167,13 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn // The grandparent does not have an entry, and the child is // modified and being pruned. This means we can just delete // it from the parent. - cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage(); cacheCoins.erase(itUs); } else { // A normal modification. - cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage(); itUs->second.coins.swap(it->second.coins); - cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins); + cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage(); itUs->second.flags |= CCoinsCacheEntry::DIRTY; } } @@ -261,6 +261,6 @@ CCoinsModifier::~CCoinsModifier() cache.cacheCoins.erase(it); } else { // If the coin still exists after the modification, add the new usage - cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins); + cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage(); } } diff --git a/src/coins.h b/src/coins.h index a4671645df..bf4a777b8a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -7,6 +7,7 @@ #define BITCOIN_COINS_H #include "compressor.h" +#include "core_memusage.h" #include "memusage.h" #include "serialize.h" #include "uint256.h" @@ -257,8 +258,7 @@ public: size_t DynamicMemoryUsage() const { size_t ret = memusage::DynamicUsage(vout); BOOST_FOREACH(const CTxOut &out, vout) { - const std::vector<unsigned char> *script = &out.scriptPubKey; - ret += memusage::DynamicUsage(*script); + ret += RecursiveDynamicUsage(out.scriptPubKey); } return ret; } diff --git a/src/compat.h b/src/compat.h index 7a5438a11e..5378c2c761 100644 --- a/src/compat.h +++ b/src/compat.h @@ -92,4 +92,12 @@ typedef u_int SOCKET; size_t strnlen( const char *start, size_t max_len); #endif // HAVE_DECL_STRNLEN +bool static inline IsSelectableSocket(SOCKET s) { +#ifdef WIN32 + return true; +#else + return (s < FD_SETSIZE); +#endif +} + #endif // BITCOIN_COMPAT_H diff --git a/src/core_memusage.h b/src/core_memusage.h new file mode 100644 index 0000000000..711135bb44 --- /dev/null +++ b/src/core_memusage.h @@ -0,0 +1,62 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CORE_MEMUSAGE_H +#define BITCOIN_CORE_MEMUSAGE_H + +#include "primitives/transaction.h" +#include "primitives/block.h" +#include "memusage.h" + +static inline size_t RecursiveDynamicUsage(const CScript& script) { + return memusage::DynamicUsage(*static_cast<const std::vector<unsigned char>*>(&script)); +} + +static inline size_t RecursiveDynamicUsage(const COutPoint& out) { + return 0; +} + +static inline size_t RecursiveDynamicUsage(const CTxIn& in) { + return RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout); +} + +static inline size_t RecursiveDynamicUsage(const CTxOut& out) { + return RecursiveDynamicUsage(out.scriptPubKey); +} + +static inline size_t RecursiveDynamicUsage(const CTransaction& tx) { + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) { + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + for (std::vector<CTxIn>::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + for (std::vector<CTxOut>::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CBlock& block) { + size_t mem = memusage::DynamicUsage(block.vtx) + memusage::DynamicUsage(block.vMerkleTree); + for (std::vector<CTransaction>::const_iterator it = block.vtx.begin(); it != block.vtx.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CBlockLocator& locator) { + return memusage::DynamicUsage(locator.vHave); +} + +#endif // BITCOIN_CORE_MEMUSAGE_H diff --git a/src/main.cpp b/src/main.cpp index 03c09f0a27..fb90d7578c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2059,7 +2059,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - CInv inv(MSG_BLOCK, pindexNew->GetBlockHash()); bool rv = ConnectBlock(*pblock, state, pindexNew, view); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { @@ -2067,7 +2066,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * InvalidBlockFound(pindexNew, state); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } - mapBlockSource.erase(inv.hash); + mapBlockSource.erase(pindexNew->GetBlockHash()); nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); assert(view.Flush()); diff --git a/src/memusage.h b/src/memusage.h index 7a831e6d33..be3964df1b 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -34,28 +34,14 @@ static inline size_t DynamicUsage(const float& v) { return 0; } static inline size_t DynamicUsage(const double& v) { return 0; } template<typename X> static inline size_t DynamicUsage(X * const &v) { return 0; } template<typename X> static inline size_t DynamicUsage(const X * const &v) { return 0; } -template<typename X, typename Y> static inline size_t DynamicUsage(std::pair<X, Y> &p) { return 0; } /** Compute the memory used for dynamically allocated but owned data structures. * For generic data types, this is *not* recursive. DynamicUsage(vector<vector<int> >) * will compute the memory used for the vector<int>'s, but not for the ints inside. * This is for efficiency reasons, as these functions are intended to be fast. If * application data structures require more accurate inner accounting, they should - * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching + - * updating on modification. + * iterate themselves, or use more efficient caching + updating on modification. */ -template<typename X> static size_t DynamicUsage(const std::vector<X>& v); -template<typename X> static size_t DynamicUsage(const std::set<X>& s); -template<typename X, typename Y> static size_t DynamicUsage(const std::map<X, Y>& m); -template<typename X, typename Y> static size_t DynamicUsage(const boost::unordered_set<X, Y>& s); -template<typename X, typename Y, typename Z> static size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& s); -template<typename X> static size_t DynamicUsage(const X& x); - -template<typename X> static size_t RecursiveDynamicUsage(const std::vector<X>& v); -template<typename X> static size_t RecursiveDynamicUsage(const std::set<X>& v); -template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::map<X, Y>& v); -template<typename X, typename Y> static size_t RecursiveDynamicUsage(const std::pair<X, Y>& v); -template<typename X> static size_t RecursiveDynamicUsage(const X& v); static inline size_t MallocUsage(size_t alloc) { @@ -89,53 +75,17 @@ static inline size_t DynamicUsage(const std::vector<X>& v) } template<typename X> -static inline size_t RecursiveDynamicUsage(const std::vector<X>& v) -{ - size_t usage = DynamicUsage(v); - BOOST_FOREACH(const X& x, v) { - usage += RecursiveDynamicUsage(x); - } - return usage; -} - -template<typename X> static inline size_t DynamicUsage(const std::set<X>& s) { return MallocUsage(sizeof(stl_tree_node<X>)) * s.size(); } -template<typename X> -static inline size_t RecursiveDynamicUsage(const std::set<X>& v) -{ - size_t usage = DynamicUsage(v); - BOOST_FOREACH(const X& x, v) { - usage += RecursiveDynamicUsage(x); - } - return usage; -} - template<typename X, typename Y> static inline size_t DynamicUsage(const std::map<X, Y>& m) { return MallocUsage(sizeof(stl_tree_node<std::pair<const X, Y> >)) * m.size(); } -template<typename X, typename Y> -static inline size_t RecursiveDynamicUsage(const std::map<X, Y>& v) -{ - size_t usage = DynamicUsage(v); - for (typename std::map<X, Y>::const_iterator it = v.begin(); it != v.end(); it++) { - usage += RecursiveDynamicUsage(*it); - } - return usage; -} - -template<typename X, typename Y> -static inline size_t RecursiveDynamicUsage(const std::pair<X, Y>& v) -{ - return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second); -} - // Boost data structures template<typename X> @@ -157,20 +107,6 @@ static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m) return MallocUsage(sizeof(boost_unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); } -// Dispatch to class method as fallback - -template<typename X> -static inline size_t DynamicUsage(const X& x) -{ - return x.DynamicMemoryUsage(); -} - -template<typename X> -static inline size_t RecursiveDynamicUsage(const X& x) -{ - return DynamicUsage(x); -} - } #endif diff --git a/src/net.cpp b/src/net.cpp index 2c7ba0ca79..3d369c7dd1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -386,6 +386,12 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) : ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed)) { + if (!IsSelectableSocket(hSocket)) { + LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); + CloseSocket(hSocket); + return NULL; + } + addrman.Attempt(addrConnect); // Add node @@ -949,6 +955,11 @@ void ThreadSocketHandler() if (nErr != WSAEWOULDBLOCK) LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); } + else if (!IsSelectableSocket(hSocket)) + { + LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString()); + CloseSocket(hSocket); + } else if (nInbound >= nMaxInbound) { LogPrint("net", "connection from %s dropped (full)\n", addr.ToString()); @@ -1597,6 +1608,13 @@ bool BindListenPort(const CService &addrBind, string& strError, bool fWhiteliste LogPrintf("%s\n", strError); return false; } + if (!IsSelectableSocket(hListenSocket)) + { + strError = "Error: Couldn't create a listenable socket for incoming connections"; + LogPrintf("%s\n", strError); + return false; + } + #ifndef WIN32 #ifdef SO_NOSIGPIPE diff --git a/src/netbase.cpp b/src/netbase.cpp index c9fc7d67f7..b7e2e57917 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -266,6 +266,9 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock } else { // Other error or blocking int nErr = WSAGetLastError(); if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { + if (!IsSelectableSocket(hSocket)) { + return false; + } struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait)); fd_set fdset; FD_ZERO(&fdset); diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 7ed2d45973..606dbea798 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -72,11 +72,6 @@ void CTransaction::UpdateHash() const *const_cast<uint256*>(&hash) = SerializeHash(*this); } -size_t CTransaction::DynamicMemoryUsage() const -{ - return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout); -} - CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 84f7adddd1..2a457cdae7 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,7 +7,6 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" -#include "memusage.h" #include "script/script.h" #include "serialize.h" #include "uint256.h" @@ -49,8 +48,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return 0; } }; /** An input of a transaction. It contains the location of the previous @@ -99,8 +96,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); } }; /** An output of a transaction. It contains the public key that the next input @@ -174,8 +169,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); } }; struct CMutableTransaction; @@ -259,8 +252,6 @@ public: } std::string ToString() const; - - size_t DynamicMemoryUsage() const; }; /** A mutable version of CTransaction. */ diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index cb888a07c4..778dbcb1ca 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -30,7 +30,6 @@ #include <QTreeWidget> #include <QTreeWidgetItem> -using namespace std; QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); bool CoinControlDialog::fSubtractFeeFromAmount = false; @@ -442,7 +441,7 @@ QString CoinControlDialog::getPriorityLabel(double dPriority, double mempoolEsti // shows count of locked unspent outputs void CoinControlDialog::updateLabelLocked() { - vector<COutPoint> vOutpts; + std::vector<COutPoint> vOutpts; model->listLockedCoins(vOutpts); if (vOutpts.size() > 0) { @@ -467,7 +466,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (amount > 0) { - CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0)); + CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0)); txDummy.vout.push_back(txout); if (txout.IsDust(::minRelayTxFee)) fDust = true; @@ -487,8 +486,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) int nQuantityUncompressed = 0; bool fAllowFree = false; - vector<COutPoint> vCoinControl; - vector<COutput> vOutputs; + std::vector<COutPoint> vCoinControl; + std::vector<COutput> vOutputs; coinControl->ListSelected(vCoinControl); model->getOutputs(vCoinControl, vOutputs); @@ -568,7 +567,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Never create dust outputs; if we would, just add the dust to the fee. if (nChange > 0 && nChange < CENT) { - CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0)); + CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0)); if (txout.IsDust(::minRelayTxFee)) { if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust @@ -687,10 +686,10 @@ void CoinControlDialog::updateView() int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget); - map<QString, vector<COutput> > mapCoins; + std::map<QString, std::vector<COutput> > mapCoins; model->listCoins(mapCoins); - BOOST_FOREACH(const PAIRTYPE(QString, vector<COutput>)& coins, mapCoins) { + BOOST_FOREACH(const PAIRTYPE(QString, std::vector<COutput>)& coins, mapCoins) { QTreeWidgetItem *itemWalletAddress = new QTreeWidgetItem(); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); QString sWalletAddress = coins.first; diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 7e9729eeb9..78a783dea4 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -19,8 +19,6 @@ #include <QDebug> #include <QSslCertificate> -using namespace std; - class SSLVerifyError : public std::runtime_error { public: @@ -49,7 +47,7 @@ bool PaymentRequestPlus::parse(const QByteArray& data) return true; } -bool PaymentRequestPlus::SerializeToString(string* output) const +bool PaymentRequestPlus::SerializeToString(std::string* output) const { return paymentRequest.SerializeToString(output); } diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 654292903b..6481b0046e 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -46,8 +46,6 @@ #include <QUrlQuery> #endif -using namespace std; - const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds const QString BITCOIN_IPC_PREFIX("bitcoin:"); // BIP70 payment protocol messages @@ -647,7 +645,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien // Create a new refund address, or re-use: QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant); std::string strAccount = account.toStdString(); - set<CTxDestination> refundAddresses = wallet->GetAccountAddresses(strAccount); + std::set<CTxDestination> refundAddresses = wallet->GetAccountAddresses(strAccount); if (!refundAddresses.empty()) { CScript s = GetScriptForDestination(*refundAddresses.begin()); payments::Output* refund_to = payment.add_refund_to(); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index d7ee3d4c78..af78a51d0f 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -21,8 +21,6 @@ #include <stdint.h> #include <string> -using namespace std; - QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { AssertLockHeld(cs_main); @@ -243,14 +241,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) - Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) if (r.first == "Message") strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>"; // // PaymentRequest info: // - Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) { if (r.first == "PaymentRequest") { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2691fa9309..168a0255ff 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -25,8 +25,6 @@ #include <QSet> #include <QTimer> -using namespace std; - WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), transactionTableModel(0), diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index c2de6cb244..f1c5ffe050 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -594,6 +594,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) heighest block available\n" " \"softforks\": [ (array) status of softforks in progress\n" " {\n" " \"id\": \"xxxx\", (string) name of softfork\n" diff --git a/src/script/script.cpp b/src/script/script.cpp index b1d2ceeb9f..fd33924732 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -260,8 +260,3 @@ std::string CScript::ToString() const } return str; } - -size_t CScript::DynamicMemoryUsage() const -{ - return memusage::DynamicUsage(*(static_cast<const std::vector<unsigned char>*>(this))); -} diff --git a/src/script/script.h b/src/script/script.h index aea34d05f4..e39ca57f4f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H -#include "memusage.h" #include "crypto/common.h" #include <assert.h> @@ -608,8 +607,6 @@ public: // The default std::vector::clear() does not release memory. std::vector<unsigned char>().swap(*this); } - - size_t DynamicMemoryUsage() const; }; class CReserveScript diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 34b311b804..13d848311a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -70,9 +70,9 @@ public: // Manually recompute the dynamic usage of the whole data, and compare it. size_t ret = memusage::DynamicUsage(cacheCoins); for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { - ret += memusage::DynamicUsage(it->second.coins); + ret += it->second.coins.DynamicMemoryUsage(); } - BOOST_CHECK_EQUAL(memusage::DynamicUsage(*this), ret); + BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret); } }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 4caa5fc821..5bc06e5056 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -31,7 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, { nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); nModSize = tx.CalculateModifiedSize(nTxSize); - nUsageSize = tx.DynamicMemoryUsage(); + nUsageSize = RecursiveDynamicUsage(tx); } CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) |