diff --git a/src/protocol.h b/src/protocol.h --- a/src/protocol.h +++ b/src/protocol.h @@ -358,7 +358,12 @@ NODE_AVALANCHE = (1 << 24), }; -std::string serviceFlagToStr(uint64_t mask, int bit); +/** + * Convert service flags (a bitmask of NODE_*) to human readable strings. + * It supports unknown service flags which will be returned as "UNKNOWN[...]". + * @param[in] flags multiple NODE_* bitwise-OR-ed together + */ +std::vector serviceFlagsToStr(const uint64_t flags); /** * Gets the set of service flags which are "desirable" for a given peer. diff --git a/src/protocol.cpp b/src/protocol.cpp --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -255,8 +255,14 @@ return allNetMessageTypesVec; } -std::string serviceFlagToStr(const uint64_t mask, const int bit) { - switch (ServiceFlags(mask)) { +/** + * Convert a service flag (NODE_*) to a human readable string. + * It supports unknown service flags which will be returned as "UNKNOWN[...]". + * @param[in] bit the service flag is calculated as (1 << bit) + */ +static std::string serviceFlagToStr(const size_t bit) { + const uint64_t service_flag = 1ULL << bit; + switch (ServiceFlags(service_flag)) { case NODE_NONE: // impossible abort(); @@ -285,3 +291,15 @@ return stream.str(); } } + +std::vector serviceFlagsToStr(const uint64_t flags) { + std::vector str_flags; + + for (size_t i = 0; i < sizeof(flags) * 8; ++i) { + if (flags & (1ULL << i)) { + str_flags.emplace_back(serviceFlagToStr(i)); + } + } + + return str_flags; +} diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -754,15 +754,10 @@ QString formatServicesStr(quint64 mask) { QStringList strList; - // Don't display experimental service bits - for (int i = 0; i < 64; i++) { - uint64_t check = 1ull << i; - if (check > NODE_LAST_NON_EXPERIMENTAL_SERVICE_BIT) { - break; - } - if (mask & check) { - strList.append(QString::fromStdString(serviceFlagToStr(check, i))); - } + constexpr uint64_t nonExperimentalMask = + (NODE_LAST_NON_EXPERIMENTAL_SERVICE_BIT << 1) - 1; + for (const auto &flag : serviceFlagsToStr(mask & nonExperimentalMask)) { + strList.append(QString::fromStdString(flag)); } if (strList.size()) { diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -866,14 +866,10 @@ } UniValue GetServicesNames(ServiceFlags services) { - const uint64_t services_n = services; UniValue servicesNames(UniValue::VARR); - for (int i = 0; i < 64; ++i) { - const uint64_t mask = 1ull << i; - if (services_n & mask) { - servicesNames.push_back(serviceFlagToStr(mask, i)); - } + for (const auto &flag : serviceFlagsToStr(services)) { + servicesNames.push_back(flag); } return servicesNames;