mirror of
https://github.com/Xahau/xahaud.git
synced 2026-07-28 17:40:10 +00:00
fix(protocol): require validated validator bitsets
This commit is contained in:
@@ -30,9 +30,44 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
struct ValidatorBitsetInfo
|
||||
class ValidatedValidatorBitset
|
||||
{
|
||||
std::size_t selected = 0;
|
||||
Slice bitset_;
|
||||
std::size_t memberCount_ = 0;
|
||||
std::size_t selected_ = 0;
|
||||
|
||||
ValidatedValidatorBitset(
|
||||
Slice bitset,
|
||||
std::size_t memberCount,
|
||||
std::size_t selected)
|
||||
: bitset_(bitset), memberCount_(memberCount), selected_(selected)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/** Construct a validated, non-owning view over a validator bitset.
|
||||
|
||||
The caller must keep the bitset storage alive while using the view.
|
||||
*/
|
||||
static std::optional<ValidatedValidatorBitset>
|
||||
make(Slice bitset, std::size_t memberCount);
|
||||
|
||||
std::size_t
|
||||
selected() const
|
||||
{
|
||||
return selected_;
|
||||
}
|
||||
|
||||
bool
|
||||
contains(std::size_t position) const
|
||||
{
|
||||
if (position >= memberCount_)
|
||||
return false;
|
||||
|
||||
auto const byte = position / 8;
|
||||
return (bitset_[byte] &
|
||||
static_cast<std::uint8_t>(1u << (position % 8))) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr std::size_t
|
||||
@@ -47,8 +82,14 @@ validatorBitsetBytes(std::size_t memberCount)
|
||||
unused high bit in the final byte clear. The returned population can be
|
||||
used by a caller's profile-specific admission and quorum rules.
|
||||
*/
|
||||
inline std::optional<ValidatorBitsetInfo>
|
||||
inline std::optional<ValidatedValidatorBitset>
|
||||
validateValidatorBitset(Slice bitset, std::size_t memberCount)
|
||||
{
|
||||
return ValidatedValidatorBitset::make(bitset, memberCount);
|
||||
}
|
||||
|
||||
inline std::optional<ValidatedValidatorBitset>
|
||||
ValidatedValidatorBitset::make(Slice bitset, std::size_t memberCount)
|
||||
{
|
||||
if (bitset.size() != validatorBitsetBytes(memberCount))
|
||||
return std::nullopt;
|
||||
@@ -66,22 +107,7 @@ validateValidatorBitset(Slice bitset, std::size_t memberCount)
|
||||
for (auto const byte : bitset)
|
||||
selected += std::popcount(byte);
|
||||
|
||||
return ValidatorBitsetInfo{selected};
|
||||
}
|
||||
|
||||
inline bool
|
||||
validatorBitsetContains(
|
||||
Slice bitset,
|
||||
std::size_t memberCount,
|
||||
std::size_t position)
|
||||
{
|
||||
if (position >= memberCount ||
|
||||
bitset.size() != validatorBitsetBytes(memberCount))
|
||||
return false;
|
||||
|
||||
auto const byte = position / 8;
|
||||
return (bitset[byte] & static_cast<std::uint8_t>(1u << (position % 8))) !=
|
||||
0;
|
||||
return ValidatedValidatorBitset{bitset, memberCount, selected};
|
||||
}
|
||||
|
||||
template <class Predicate>
|
||||
|
||||
@@ -49,17 +49,15 @@ public:
|
||||
auto const info = validateValidatorBitset(makeSlice(bitset), 10);
|
||||
BEAST_EXPECT(info);
|
||||
if (info)
|
||||
BEAST_EXPECT(info->selected == 3);
|
||||
|
||||
BEAST_EXPECT(validatorBitsetContains(makeSlice(bitset), 10, 0));
|
||||
BEAST_EXPECT(validatorBitsetContains(makeSlice(bitset), 10, 7));
|
||||
BEAST_EXPECT(!validatorBitsetContains(makeSlice(bitset), 10, 8));
|
||||
BEAST_EXPECT(validatorBitsetContains(makeSlice(bitset), 10, 9));
|
||||
BEAST_EXPECT(!validatorBitsetContains(makeSlice(bitset), 10, 10));
|
||||
BEAST_EXPECT(!validatorBitsetContains(makeSlice(bitset), 10, 80));
|
||||
|
||||
Blob const wrongSize{0x81};
|
||||
BEAST_EXPECT(!validatorBitsetContains(makeSlice(wrongSize), 10, 0));
|
||||
{
|
||||
BEAST_EXPECT(info->selected() == 3);
|
||||
BEAST_EXPECT(info->contains(0));
|
||||
BEAST_EXPECT(info->contains(7));
|
||||
BEAST_EXPECT(!info->contains(8));
|
||||
BEAST_EXPECT(info->contains(9));
|
||||
BEAST_EXPECT(!info->contains(10));
|
||||
BEAST_EXPECT(!info->contains(80));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -78,7 +76,7 @@ public:
|
||||
auto const info = validateValidatorBitset(makeSlice(exact), 10);
|
||||
BEAST_EXPECT(info);
|
||||
if (info)
|
||||
BEAST_EXPECT(info->selected == 10);
|
||||
BEAST_EXPECT(info->selected() == 10);
|
||||
BEAST_EXPECT(!validateValidatorBitset(makeSlice(highBitSet), 10));
|
||||
BEAST_EXPECT(!validateValidatorBitset(makeSlice(tooLong), 10));
|
||||
|
||||
@@ -86,7 +84,7 @@ public:
|
||||
auto const full = validateValidatorBitset(makeSlice(fullByte), 8);
|
||||
BEAST_EXPECT(full);
|
||||
if (full)
|
||||
BEAST_EXPECT(full->selected == 8);
|
||||
BEAST_EXPECT(full->selected() == 8);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/ValidatorBitset.h>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
|
||||
@@ -46,21 +47,6 @@ namespace ripple {
|
||||
|
||||
namespace {
|
||||
|
||||
std::size_t
|
||||
countSetBits(Blob const& bytes)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for (auto byte : bytes)
|
||||
{
|
||||
while (byte != 0)
|
||||
{
|
||||
byte &= static_cast<std::uint8_t>(byte - 1);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
validEntropyContributorMask(
|
||||
std::uint8_t tier,
|
||||
@@ -77,19 +63,9 @@ validEntropyContributorMask(
|
||||
if (tier < entropyTierParticipantAligned || tier > entropyTierValidatorFull)
|
||||
return false;
|
||||
|
||||
auto const expectedSize = (denominator + 7) / 8;
|
||||
if (contributors.size() != expectedSize)
|
||||
return false;
|
||||
|
||||
if (auto const usedBits = denominator % 8;
|
||||
usedBits != 0 && !contributors.empty())
|
||||
{
|
||||
auto const validBits = static_cast<std::uint8_t>((1u << usedBits) - 1u);
|
||||
if ((contributors.back() & ~validBits) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return countSetBits(contributors) == count;
|
||||
auto const bitset =
|
||||
validateValidatorBitset(makeSlice(contributors), denominator);
|
||||
return bitset && bitset->selected() == count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user