From 1d9b86d584542fbc34bf49726badaba2ca764228 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 8 Oct 2014 14:27:07 -0400 Subject: [PATCH 1/6] boost: drop dependency on is_fundamental in serialization There's only one case where a vector containing a fundamental type is serialized all-at-once, unsigned char. Anything else would lead to strange results. Use a dummy argument to overload in that case. --- src/serialize.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index ff11edc06..8220fecb9 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -21,7 +21,6 @@ #include #include -#include class CAutoFile; class CDataStream; @@ -432,14 +431,15 @@ template void Serialize(Stream& os, const std::basi template void Unserialize(Stream& is, std::basic_string& str, int, int=0); // vector -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&); -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&); +// vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const unsigned char&); +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const V&); template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const unsigned char&); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const V&); template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const unsigned char&); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const V&); template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion); // others derived from vector @@ -536,13 +536,13 @@ void Unserialize(Stream& is, std::basic_string& str, int, int) // vector // template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&) +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const unsigned char&) { return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); } -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&) +template +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const V&) { unsigned int nSize = GetSizeOfCompactSize(v.size()); for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) @@ -553,20 +553,20 @@ unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nV template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion) { - return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental()); + return GetSerializeSize_impl(v, nType, nVersion, T()); } template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&) +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const unsigned char&) { WriteCompactSize(os, v.size()); if (!v.empty()) os.write((char*)&v[0], v.size() * sizeof(T)); } -template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&) +template +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const V&) { WriteCompactSize(os, v.size()); for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) @@ -576,12 +576,12 @@ void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVers template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion) { - Serialize_impl(os, v, nType, nVersion, boost::is_fundamental()); + Serialize_impl(os, v, nType, nVersion, T()); } template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&) +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const unsigned char&) { // Limit size per read so bogus size value won't cause out of memory v.clear(); @@ -596,8 +596,8 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, } } -template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&) +template +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const V&) { v.clear(); unsigned int nSize = ReadCompactSize(is); @@ -617,7 +617,7 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion) { - Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental()); + Unserialize_impl(is, v, nType, nVersion, T()); } From 52955068b70fdd4166ffe443e716b0b2f6fe9f6d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 8 Oct 2014 14:28:03 -0400 Subject: [PATCH 2/6] boost: drop dependency on tuple in serialization There's only one user of this form of serialization, so it can be easily dropped. It could be re-added if desired when we switch to c++11. --- src/serialize.h | 77 ------------------------------------------------ src/walletdb.cpp | 8 ++--- 2 files changed, 4 insertions(+), 81 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 8220fecb9..55b689139 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -20,8 +20,6 @@ #include #include -#include - class CAutoFile; class CDataStream; class CScript; @@ -452,16 +450,6 @@ template unsigned int GetSerializeSize(const std::pair void Serialize(Stream& os, const std::pair& item, int nType, int nVersion); template void Unserialize(Stream& is, std::pair& item, int nType, int nVersion); -// 3 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); - -// 4 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); - // map template unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion); template void Serialize(Stream& os, const std::map& m, int nType, int nVersion); @@ -669,71 +657,6 @@ void Unserialize(Stream& is, std::pair& item, int nType, int nVersion) -// -// 3 tuple -// -template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) -{ - unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) -{ - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); -} - -template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) -{ - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); -} - - - -// -// 4 tuple -// -template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) -{ - unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) -{ - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); - Serialize(os, boost::get<3>(item), nType, nVersion); -} - -template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) -{ - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); - Unserialize(is, boost::get<3>(item), nType, nVersion); -} - - - // // map // diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 783f766f6..ffddd8106 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -185,7 +185,7 @@ bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account) bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) { - return Write(boost::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry); + return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) @@ -218,7 +218,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list Date: Thu, 9 Oct 2014 16:38:38 -0400 Subject: [PATCH 3/6] boost: remove CPrivKey dependency from CECKey This allows CECKey to be used without directly depending on the secure allocators --- src/key.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index c2251b4f2..079e2c654 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -179,19 +179,17 @@ public: BN_clear_free(&bn); } - void GetPrivKey(CPrivKey &privkey, bool fCompressed) { + int GetPrivKeySize(bool fCompressed) { EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); - int nSize = i2d_ECPrivateKey(pkey, NULL); - assert(nSize); - privkey.resize(nSize); - unsigned char* pbegin = &privkey[0]; - int nSize2 = i2d_ECPrivateKey(pkey, &pbegin); - assert(nSize == nSize2); + return i2d_ECPrivateKey(pkey, NULL); + } + int GetPrivKey(unsigned char* privkey, bool fCompressed) { + EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); + return i2d_ECPrivateKey(pkey, &privkey); } - bool SetPrivKey(const CPrivKey &privkey, bool fSkipCheck=false) { - const unsigned char* pbegin = &privkey[0]; - if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) { + bool SetPrivKey(const unsigned char* privkey, size_t size, bool fSkipCheck=false) { + if (d2i_ECPrivateKey(&pkey, &privkey, size)) { if(fSkipCheck) return true; @@ -424,7 +422,7 @@ bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { return false; #else CECKey key; - if (!key.SetPrivKey(privkey)) + if (!key.SetPrivKey(&privkey[0], privkey.size())) return false; key.GetSecretBytes(vch); #endif @@ -436,16 +434,21 @@ bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { CPrivKey CKey::GetPrivKey() const { assert(fValid); CPrivKey privkey; + int privkeylen, ret; #ifdef USE_SECP256K1 privkey.resize(279); - int privkeylen = 279; - int ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); + privkeylen = 279; + ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); assert(ret); privkey.resize(privkeylen); #else CECKey key; key.SetSecretBytes(vch); - key.GetPrivKey(privkey, fCompressed); + privkeylen = key.GetPrivKeySize(fCompressed); + assert(privkeylen); + privkey.resize(privkeylen); + ret = key.GetPrivKey(&privkey[0], fCompressed); + assert(ret == (int)privkey.size()); #endif return privkey; } @@ -517,7 +520,7 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { return false; #else CECKey key; - if (!key.SetPrivKey(privkey, fSkipCheck)) + if (!key.SetPrivKey(&privkey[0], privkey.size(), fSkipCheck)) return false; key.GetSecretBytes(vch); #endif From e1c946776652a177e3b46db02391263cc24bfd5a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 10 Oct 2014 00:42:03 -0400 Subject: [PATCH 4/6] boost: drop boost dependency in core.cpp --- src/core.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 380b1c38e..6a7a9ff37 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -7,8 +7,6 @@ #include "tinyformat.h" -#include - std::string COutPoint::ToString() const { return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); @@ -113,10 +111,10 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { CAmount CTransaction::GetValueOut() const { CAmount nValueOut = 0; - BOOST_FOREACH(const CTxOut& txout, vout) + for (std::vector::const_iterator it(vout.begin()); it != vout.end(); ++it) { - nValueOut += txout.nValue; - if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) + nValueOut += it->nValue; + if (!MoneyRange(it->nValue) || !MoneyRange(nValueOut)) throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); } return nValueOut; @@ -139,10 +137,9 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const // risk encouraging people to create junk outputs to redeem later. if (nTxSize == 0) nTxSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); - - BOOST_FOREACH(const CTxIn& txin, vin) + for (std::vector::const_iterator it(vin.begin()); it != vin.end(); ++it) { - unsigned int offset = 41U + std::min(110U, (unsigned int)txin.scriptSig.size()); + unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size()); if (nTxSize > offset) nTxSize -= offset; } @@ -263,8 +260,8 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const */ vMerkleTree.clear(); vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. - BOOST_FOREACH(const CTransaction& tx, vtx) - vMerkleTree.push_back(tx.GetHash()); + for (std::vector::const_iterator it(vtx.begin()); it != vtx.end(); ++it) + vMerkleTree.push_back(it->GetHash()); int j = 0; bool mutated = false; for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) @@ -307,12 +304,12 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMer { if (nIndex == -1) return 0; - BOOST_FOREACH(const uint256& otherside, vMerkleBranch) + for (std::vector::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it) { if (nIndex & 1) - hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); + hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); else - hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); + hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); nIndex >>= 1; } return hash; From 352058e8b0da4ec37b2f1891716c53adc2957a02 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 10 Oct 2014 13:24:12 -0400 Subject: [PATCH 5/6] boost: drop boost dependency in utilstrencodings.cpp --- src/utilstrencodings.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index b9e64c5fe..81e156f43 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -9,8 +9,8 @@ #include #include - -#include +#include +#include using namespace std; @@ -53,9 +53,9 @@ signed char HexDigit(char c) bool IsHex(const string& str) { - BOOST_FOREACH(char c, str) + for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) { - if (HexDigit(c) < 0) + if (HexDigit(*it) < 0) return false; } return (str.size() > 0) && (str.size()%2 == 0); From 5f4bcf6b14eb45da408e19295332d2a8486d70df Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 13 Oct 2014 14:15:19 -0400 Subject: [PATCH 6/6] boost: drop boost dependency in version.cpp. Also add a test to verify. --- src/test/util_tests.cpp | 12 ++++++++++++ src/version.cpp | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 6378bd094..61daa0a3f 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -9,6 +9,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utilmoneystr.h" +#include "version.h" #include #include @@ -341,4 +342,15 @@ BOOST_AUTO_TEST_CASE(test_FormatParagraph) BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test"); } +BOOST_AUTO_TEST_CASE(test_FormatSubVersion) +{ + std::vector comments; + comments.push_back(std::string("comment1")); + std::vector comments2; + comments2.push_back(std::string("comment1")); + comments2.push_back(std::string("comment2")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector()),std::string("/Test:0.9.99/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/")); + BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/")); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/version.cpp b/src/version.cpp index 95632fdab..d12b681e5 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -8,8 +8,6 @@ #include -#include - // Name of client reported in the 'version' message. Report the same name // for both bitcoind and bitcoin-qt, to make it harder for attackers to // target servers or GUI users specifically. @@ -94,7 +92,13 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const ss << "/"; ss << name << ":" << FormatVersion(nClientVersion); if (!comments.empty()) - ss << "(" << boost::algorithm::join(comments, "; ") << ")"; + { + std::vector::const_iterator it(comments.begin()); + ss << "(" << *it; + for(++it; it != comments.end(); ++it) + ss << "; " << *it; + ss << ")"; + } ss << "/"; return ss.str(); }