From 37d9eaaa2bebfb8fd0fcb8f2d5a236160eaa658f Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Mon, 13 Jul 2026 19:05:22 +0700 Subject: [PATCH] fix(protocol): reset moved validator bitsets --- include/xrpl/protocol/ValidatorBitset.h | 31 +++++++++++++++++++ src/test/protocol/ValidatorBitset_test.cpp | 35 ++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/include/xrpl/protocol/ValidatorBitset.h b/include/xrpl/protocol/ValidatorBitset.h index b702a0697..44ad6bf51 100644 --- a/include/xrpl/protocol/ValidatorBitset.h +++ b/include/xrpl/protocol/ValidatorBitset.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace ripple { @@ -47,6 +48,36 @@ class ValidatedValidatorBitset } public: + ValidatedValidatorBitset(ValidatedValidatorBitset const&) = default; + ValidatedValidatorBitset& + operator=(ValidatedValidatorBitset const&) = default; + + ValidatedValidatorBitset(ValidatedValidatorBitset&& other) noexcept + : bitset_(std::move(other.bitset_)) + , memberCount_(other.memberCount_) + , selected_(other.selected_) + { + other.bitset_.clear(); + other.memberCount_ = 0; + other.selected_ = 0; + } + + ValidatedValidatorBitset& + operator=(ValidatedValidatorBitset&& other) noexcept + { + if (this != &other) + { + bitset_ = std::move(other.bitset_); + memberCount_ = other.memberCount_; + selected_ = other.selected_; + + other.bitset_.clear(); + other.memberCount_ = 0; + other.selected_ = 0; + } + return *this; + } + /** Construct an owning, validated validator bitset. */ static std::optional make(Slice bitset, std::size_t memberCount); diff --git a/src/test/protocol/ValidatorBitset_test.cpp b/src/test/protocol/ValidatorBitset_test.cpp index 00238f9d1..ff4a5780d 100644 --- a/src/test/protocol/ValidatorBitset_test.cpp +++ b/src/test/protocol/ValidatorBitset_test.cpp @@ -19,6 +19,8 @@ #include #include +#include + namespace ripple { namespace test { @@ -117,6 +119,38 @@ public: } } + void + testValueSemantics() + { + testcase("value semantics"); + + Blob const bits{0x01, 0x02}; + auto source = validateValidatorBitset(makeSlice(bits), 10); + BEAST_EXPECT(source); + if (!source) + return; + + auto copy = *source; + BEAST_EXPECT(copy.selected() == 2); + BEAST_EXPECT(copy.contains(0)); + BEAST_EXPECT(copy.contains(9)); + + auto moved = std::move(*source); + BEAST_EXPECT(moved.selected() == 2); + BEAST_EXPECT(moved.contains(0)); + BEAST_EXPECT(moved.contains(9)); + BEAST_EXPECT(source->selected() == 0); + BEAST_EXPECT(!source->contains(0)); + + auto assigned = copy; + assigned = std::move(moved); + BEAST_EXPECT(assigned.selected() == 2); + BEAST_EXPECT(assigned.contains(0)); + BEAST_EXPECT(assigned.contains(9)); + BEAST_EXPECT(moved.selected() == 0); + BEAST_EXPECT(!moved.contains(0)); + } + void run() override { @@ -124,6 +158,7 @@ public: testConstructionAndPopulation(); testCanonicalShape(); testValidatedOwnership(); + testValueSemantics(); } };