When fuzzing the base58 functions I noticed that `DecodeBase58(const std::string& str, …)` is perhaps a bit too liberal in what input it accepts when decoding.

I naïvely assumed that `DecodeBase58(const std::string& str, …)` would return `false` when passing it a `str` which contains at least one character that is not any of the base58 characters (all alphanumeric characters except for "0", "I", "O", and "l") or the whitespace characters.

That is not the case:
* `str` contains `good` → `DecodeBase58(const std::string& str, …) == true` (as expected)
* `str` contains `bad0IOl` → `DecodeBase58(const std::string& str, …) == false` (as expected)
* `str` contains `good\x00bad0IOl` → `DecodeBase58(const std::string& str, …) == true`(!)

The reason is that `DecodeBase58(const std::string& str, …)` calls `DecodeBase58(const char* psz, …)` which will only consider the string up to the first `\x00`.
#ifndef BITCOIN_UTIL_STRING_H
#define BITCOIN_UTIL_STRING_H
#include <string>
#include <vector>
/**
 * Join a list of items
 *
 * @param list       The list to join
 * @param separator  The separator
 * @param unary_op   Apply this operator to each item in the list
 */
template <typename T, typename UnaryOp>
std::string Join(const std::vector<T>& list, const std::string& separator, UnaryOp unary_op)
{
    std::string ret;
    for (size_t i = 0; i < list.size(); ++i) {
        if (i > 0) ret += separator;
        ret += unary_op(list.at(i));
    }
    return ret;
}
inline std::string Join(const std::vector<std::string>& list, const std::string& separator)
{
    return Join(list, separator, [](const std::string& i) { return i; });
}
#endif