mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
script/verify_flags: make script_verify_flags type safe
`using script_verify_flags = uint32_t` allows implicit conversion to and from int, so replace it with a class to have the compiler ensure we use the correct type. Provide from_int and as_int to allow for explicit conversions when desired. Introduces the type `script_verify_flag_name` for the individual flag name enumeration.
This commit is contained in:
@@ -2164,7 +2164,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
|
||||
}
|
||||
|
||||
#define FLAG_NAME(flag) {std::string(#flag), SCRIPT_VERIFY_##flag}
|
||||
const std::map<std::string, uint32_t> g_verify_flag_names{
|
||||
const std::map<std::string, script_verify_flag_name> g_verify_flag_names{
|
||||
FLAG_NAME(P2SH),
|
||||
FLAG_NAME(STRICTENC),
|
||||
FLAG_NAME(DERSIG),
|
||||
@@ -2203,7 +2203,7 @@ std::vector<std::string> GetScriptFlagNames(script_verify_flags flags)
|
||||
}
|
||||
}
|
||||
if (leftover != 0) {
|
||||
res.push_back(strprintf("0x%08x", leftover));
|
||||
res.push_back(strprintf("0x%08x", leftover.as_int()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <span.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
@@ -43,9 +44,10 @@ enum
|
||||
* All flags are intended to be soft forks: the set of acceptable scripts under
|
||||
* flags (A | B) is a subset of the acceptable scripts under flag (A).
|
||||
*/
|
||||
enum : uint32_t {
|
||||
SCRIPT_VERIFY_NONE = 0,
|
||||
|
||||
static constexpr script_verify_flags SCRIPT_VERIFY_NONE{0};
|
||||
|
||||
enum class script_verify_flag_name : uint32_t {
|
||||
// Evaluate P2SH subscripts (BIP16).
|
||||
SCRIPT_VERIFY_P2SH = (1U << 0),
|
||||
|
||||
@@ -148,6 +150,13 @@ enum : uint32_t {
|
||||
//
|
||||
SCRIPT_VERIFY_END_MARKER
|
||||
};
|
||||
using enum script_verify_flag_name;
|
||||
|
||||
// assert there is still a spare bit
|
||||
static_assert(static_cast<script_verify_flags::value_type>(SCRIPT_VERIFY_END_MARKER) < (1u << 31));
|
||||
|
||||
static constexpr script_verify_flags::value_type MAX_SCRIPT_VERIFY_FLAGS = ((static_cast<script_verify_flags::value_type>(SCRIPT_VERIFY_END_MARKER) - 1) << 1) - 1;
|
||||
static constexpr int MAX_SCRIPT_VERIFY_FLAGS_BITS = std::bit_width(MAX_SCRIPT_VERIFY_FLAGS);
|
||||
|
||||
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, script_verify_flags flags, ScriptError* serror);
|
||||
|
||||
@@ -372,7 +381,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
|
||||
|
||||
int FindAndDelete(CScript& script, const CScript& b);
|
||||
|
||||
extern const std::map<std::string, uint32_t> g_verify_flag_names;
|
||||
extern const std::map<std::string, script_verify_flag_name> g_verify_flag_names;
|
||||
|
||||
std::vector<std::string> GetScriptFlagNames(script_verify_flags flags);
|
||||
|
||||
|
||||
@@ -6,8 +6,66 @@
|
||||
#ifndef BITCOIN_SCRIPT_VERIFY_FLAGS_H
|
||||
#define BITCOIN_SCRIPT_VERIFY_FLAGS_H
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
|
||||
using script_verify_flags = uint32_t;
|
||||
enum class script_verify_flag_name : uint32_t;
|
||||
|
||||
class script_verify_flags
|
||||
{
|
||||
public:
|
||||
using value_type = uint32_t;
|
||||
|
||||
consteval script_verify_flags() = default;
|
||||
|
||||
// also allow construction with hard-coded 0 (but not other integers)
|
||||
consteval explicit(false) script_verify_flags(value_type f) : m_value{f} { if (f != 0) throw 0; }
|
||||
|
||||
// implicit construction from a hard-coded SCRIPT_VERIFY_* constant is also okay
|
||||
constexpr explicit(false) script_verify_flags(script_verify_flag_name f) : m_value{static_cast<value_type>(f)} { }
|
||||
|
||||
// rule of 5
|
||||
constexpr script_verify_flags(const script_verify_flags&) = default;
|
||||
constexpr script_verify_flags(script_verify_flags&&) = default;
|
||||
constexpr script_verify_flags& operator=(const script_verify_flags&) = default;
|
||||
constexpr script_verify_flags& operator=(script_verify_flags&&) = default;
|
||||
constexpr ~script_verify_flags() = default;
|
||||
|
||||
// integer conversion needs to be very explicit
|
||||
static constexpr script_verify_flags from_int(value_type f) { script_verify_flags r; r.m_value = f; return r; }
|
||||
constexpr value_type as_int() const { return m_value; }
|
||||
|
||||
// bitwise operations
|
||||
constexpr script_verify_flags operator~() const { return from_int(~m_value); }
|
||||
friend constexpr script_verify_flags operator|(script_verify_flags a, script_verify_flags b) { return from_int(a.m_value | b.m_value); }
|
||||
friend constexpr script_verify_flags operator&(script_verify_flags a, script_verify_flags b) { return from_int(a.m_value & b.m_value); }
|
||||
|
||||
// in-place bitwise operations
|
||||
constexpr script_verify_flags& operator|=(script_verify_flags vf) { m_value |= vf.m_value; return *this; }
|
||||
constexpr script_verify_flags& operator&=(script_verify_flags vf) { m_value &= vf.m_value; return *this; }
|
||||
|
||||
// tests
|
||||
constexpr explicit operator bool() const { return m_value != 0; }
|
||||
constexpr bool operator==(script_verify_flags other) const { return m_value == other.m_value; }
|
||||
|
||||
/** Compare two script_verify_flags. <, >, <=, and >= are auto-generated from this. */
|
||||
friend constexpr std::strong_ordering operator<=>(const script_verify_flags& a, const script_verify_flags& b) noexcept
|
||||
{
|
||||
return a.m_value <=> b.m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_value{0}; // default value is SCRIPT_VERIFY_NONE
|
||||
};
|
||||
|
||||
inline constexpr script_verify_flags operator~(script_verify_flag_name f)
|
||||
{
|
||||
return ~script_verify_flags{f};
|
||||
}
|
||||
|
||||
inline constexpr script_verify_flags operator|(script_verify_flag_name f1, script_verify_flag_name f2)
|
||||
{
|
||||
return script_verify_flags{f1} | f2;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_SCRIPT_VERIFY_FLAGS_H
|
||||
|
||||
Reference in New Issue
Block a user