diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/bech32.cpp | 8 | ||||
-rw-r--r-- | src/outputtype.cpp | 6 | ||||
-rw-r--r-- | src/script/descriptor.cpp | 36 | ||||
-rw-r--r-- | src/txdb.cpp | 3 | ||||
-rw-r--r-- | src/util/vector.h | 51 |
6 files changed, 73 insertions, 32 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index eec84122ae..d50524a8ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -220,6 +220,7 @@ BITCOIN_CORE_H = \ util/translation.h \ util/url.h \ util/validation.h \ + util/vector.h \ validation.h \ validationinterface.h \ versionbits.h \ diff --git a/src/bech32.cpp b/src/bech32.cpp index 4c966350b4..1e0471f110 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bech32.h> +#include <util/vector.h> #include <assert.h> @@ -26,13 +27,6 @@ const int8_t CHARSET_REV[128] = { 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 }; -/** Concatenate two byte arrays. */ -data Cat(data x, const data& y) -{ - x.insert(x.end(), y.begin(), y.end()); - return x; -} - /** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to * make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher * bits correspond to earlier values. */ diff --git a/src/outputtype.cpp b/src/outputtype.cpp index bcaa05f4b6..5cc43898a7 100644 --- a/src/outputtype.cpp +++ b/src/outputtype.cpp @@ -10,6 +10,7 @@ #include <script/sign.h> #include <script/signingprovider.h> #include <script/standard.h> +#include <util/vector.h> #include <assert.h> #include <string> @@ -65,12 +66,13 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key) { PKHash keyid(key); + CTxDestination p2pkh{keyid}; if (key.IsCompressed()) { CTxDestination segwit = WitnessV0KeyHash(keyid); CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit)); - return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)}; + return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit)); } else { - return std::vector<CTxDestination>{std::move(keyid)}; + return Vector(std::move(p2pkh)); } } diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index ed1bd4cda9..536807e1d8 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -14,6 +14,7 @@ #include <util/spanparsing.h> #include <util/system.h> #include <util/strencodings.h> +#include <util/vector.h> #include <memory> #include <string> @@ -501,22 +502,13 @@ public: } }; -/** Construct a vector with one element, which is moved into it. */ -template<typename T> -std::vector<T> Singleton(T elem) -{ - std::vector<T> ret; - ret.emplace_back(std::move(elem)); - return ret; -} - /** A parsed addr(A) descriptor. */ class AddressDescriptor final : public DescriptorImpl { const CTxDestination m_destination; protected: std::string ToStringExtra() const override { return EncodeDestination(m_destination); } - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(m_destination)); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); } public: AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {} bool IsSolvable() const final { return false; } @@ -528,7 +520,7 @@ class RawDescriptor final : public DescriptorImpl const CScript m_script; protected: std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); } - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(m_script); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(m_script); } public: RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {} bool IsSolvable() const final { return false; } @@ -538,9 +530,9 @@ public: class PKDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForRawPubKey(keys[0])); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); } public: - PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pk") {} + PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {} }; /** A parsed pkh(P) descriptor. */ @@ -551,10 +543,10 @@ protected: { CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); - return Singleton(GetScriptForDestination(PKHash(id))); + return Vector(GetScriptForDestination(PKHash(id))); } public: - PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pkh") {} + PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {} }; /** A parsed wpkh(P) descriptor. */ @@ -565,10 +557,10 @@ protected: { CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); - return Singleton(GetScriptForDestination(WitnessV0KeyHash(id))); + return Vector(GetScriptForDestination(WitnessV0KeyHash(id))); } public: - WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "wpkh") {} + WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {} }; /** A parsed combo(P) descriptor. */ @@ -591,7 +583,7 @@ protected: return ret; } public: - ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {} + ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {} }; /** A parsed multi(...) or sortedmulti(...) descriptor */ @@ -605,9 +597,9 @@ protected: if (m_sorted) { std::vector<CPubKey> sorted_keys(keys); std::sort(sorted_keys.begin(), sorted_keys.end()); - return Singleton(GetScriptForMultisig(m_threshold, sorted_keys)); + return Vector(GetScriptForMultisig(m_threshold, sorted_keys)); } - return Singleton(GetScriptForMultisig(m_threshold, keys)); + return Vector(GetScriptForMultisig(m_threshold, keys)); } public: MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {} @@ -617,7 +609,7 @@ public: class SHDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(ScriptHash(*script))); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(ScriptHash(*script))); } public: SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {} }; @@ -626,7 +618,7 @@ public: class WSHDescriptor final : public DescriptorImpl { protected: - std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(WitnessV0ScriptHash(*script))); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); } public: WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {} }; diff --git a/src/txdb.cpp b/src/txdb.cpp index 536bfee901..a7eb5f9f67 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -12,6 +12,7 @@ #include <uint256.h> #include <util/system.h> #include <util/translation.h> +#include <util/vector.h> #include <stdint.h> @@ -102,7 +103,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { // A vector is used for future extensibility, as we may want to support // interrupting after partial writes from multiple independent reorgs. batch.Erase(DB_BEST_BLOCK); - batch.Write(DB_HEAD_BLOCKS, std::vector<uint256>{hashBlock, old_tip}); + batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip)); for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { diff --git a/src/util/vector.h b/src/util/vector.h new file mode 100644 index 0000000000..dab65ded2a --- /dev/null +++ b/src/util/vector.h @@ -0,0 +1,51 @@ +// Copyright (c) 2019 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_UTIL_VECTOR_H +#define BITCOIN_UTIL_VECTOR_H + +#include <initializer_list> +#include <type_traits> +#include <vector> + +/** Construct a vector with the specified elements. + * + * This is preferable over the list initializing constructor of std::vector: + * - It automatically infers the element type from its arguments. + * - If any arguments are rvalue references, they will be moved into the vector + * (list initialization always copies). + */ +template<typename... Args> +inline std::vector<typename std::common_type<Args...>::type> Vector(Args&&... args) +{ + std::vector<typename std::common_type<Args...>::type> ret; + ret.reserve(sizeof...(args)); + // The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html + (void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...}; + return ret; +} + +/** Concatenate two vectors, moving elements. */ +template<typename V> +inline V Cat(V v1, V&& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (auto& arg : v2) { + v1.push_back(std::move(arg)); + } + return v1; +} + +/** Concatenate two vectors. */ +template<typename V> +inline V Cat(V v1, const V& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (const auto& arg : v2) { + v1.push_back(arg); + } + return v1; +} + +#endif // BITCOIN_UTIL_VECTOR_H |