Skip to content

Commit 0073e9a

Browse files
committed
refactor: replace CDeterministicMNStateDiff macros with boost::hana
1 parent e053c8b commit 0073e9a

File tree

2 files changed

+69
-37
lines changed

2 files changed

+69
-37
lines changed

src/evo/dmnstate.h

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include <memory>
1616
#include <utility>
1717

18+
#include <boost/hana/for_each.hpp>
19+
#include <boost/hana/tuple.hpp>
20+
1821
class CProRegTx;
1922
class UniValue;
2023

@@ -173,26 +176,38 @@ class CDeterministicMNStateDiff
173176
Field_nVersion = 0x40000,
174177
};
175178

176-
#define DMN_STATE_DIFF_ALL_FIELDS \
177-
DMN_STATE_DIFF_LINE(nRegisteredHeight) \
178-
DMN_STATE_DIFF_LINE(nLastPaidHeight) \
179-
DMN_STATE_DIFF_LINE(nPoSePenalty) \
180-
DMN_STATE_DIFF_LINE(nPoSeRevivedHeight) \
181-
DMN_STATE_DIFF_LINE(nPoSeBanHeight) \
182-
DMN_STATE_DIFF_LINE(nRevocationReason) \
183-
DMN_STATE_DIFF_LINE(confirmedHash) \
184-
DMN_STATE_DIFF_LINE(confirmedHashWithProRegTxHash) \
185-
DMN_STATE_DIFF_LINE(keyIDOwner) \
186-
DMN_STATE_DIFF_LINE(pubKeyOperator) \
187-
DMN_STATE_DIFF_LINE(keyIDVoting) \
188-
DMN_STATE_DIFF_LINE(addr) \
189-
DMN_STATE_DIFF_LINE(scriptPayout) \
190-
DMN_STATE_DIFF_LINE(scriptOperatorPayout) \
191-
DMN_STATE_DIFF_LINE(nConsecutivePayments) \
192-
DMN_STATE_DIFF_LINE(platformNodeID) \
193-
DMN_STATE_DIFF_LINE(platformP2PPort) \
194-
DMN_STATE_DIFF_LINE(platformHTTPPort) \
195-
DMN_STATE_DIFF_LINE(nVersion)
179+
private:
180+
template <auto CDeterministicMNState::*Field, uint32_t Mask>
181+
struct Member
182+
{
183+
static constexpr uint32_t mask = Mask;
184+
static auto& get(CDeterministicMNState& state) { return state.*Field; }
185+
static const auto& get(const CDeterministicMNState& state) { return state.*Field; }
186+
};
187+
188+
#define DMN_STATE_MEMBER(name) Member<&CDeterministicMNState::name, Field_##name>{}
189+
static constexpr auto members = boost::hana::make_tuple(
190+
DMN_STATE_MEMBER(nRegisteredHeight),
191+
DMN_STATE_MEMBER(nLastPaidHeight),
192+
DMN_STATE_MEMBER(nPoSePenalty),
193+
DMN_STATE_MEMBER(nPoSeRevivedHeight),
194+
DMN_STATE_MEMBER(nPoSeBanHeight),
195+
DMN_STATE_MEMBER(nRevocationReason),
196+
DMN_STATE_MEMBER(confirmedHash),
197+
DMN_STATE_MEMBER(confirmedHashWithProRegTxHash),
198+
DMN_STATE_MEMBER(keyIDOwner),
199+
DMN_STATE_MEMBER(pubKeyOperator),
200+
DMN_STATE_MEMBER(keyIDVoting),
201+
DMN_STATE_MEMBER(addr),
202+
DMN_STATE_MEMBER(scriptPayout),
203+
DMN_STATE_MEMBER(scriptOperatorPayout),
204+
DMN_STATE_MEMBER(nConsecutivePayments),
205+
DMN_STATE_MEMBER(platformNodeID),
206+
DMN_STATE_MEMBER(platformP2PPort),
207+
DMN_STATE_MEMBER(platformHTTPPort),
208+
DMN_STATE_MEMBER(nVersion)
209+
);
210+
#undef DMN_STATE_MEMBER
196211

197212
public:
198213
uint32_t fields{0};
@@ -203,27 +218,41 @@ class CDeterministicMNStateDiff
203218
CDeterministicMNStateDiff() = default;
204219
CDeterministicMNStateDiff(const CDeterministicMNState& a, const CDeterministicMNState& b)
205220
{
206-
#define DMN_STATE_DIFF_LINE(f) if (a.f != b.f) { state.f = b.f; fields |= Field_##f; }
207-
DMN_STATE_DIFF_ALL_FIELDS
208-
#undef DMN_STATE_DIFF_LINE
209-
if (fields & Field_pubKeyOperator) { state.nVersion = b.nVersion; fields |= Field_nVersion; }
221+
boost::hana::for_each(members, [&](auto&& member) {
222+
if (member.get(a) != member.get(b)) {
223+
member.get(state) = member.get(b);
224+
fields |= member.mask;
225+
}
226+
});
227+
if (fields & Field_pubKeyOperator) {
228+
// pubKeyOperator needs nVersion
229+
state.nVersion = b.nVersion;
230+
fields |= Field_nVersion;
231+
}
210232
}
211233

212234
[[nodiscard]] UniValue ToJson(MnType nType) const;
213235

214236
SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
215237
{
238+
READWRITE(VARINT(obj.fields));
239+
216240
// NOTE: reading pubKeyOperator requires nVersion
217241
bool read_pubkey{false};
218-
READWRITE(VARINT(obj.fields));
219-
#define DMN_STATE_DIFF_LINE(f) \
220-
if (strcmp(#f, "pubKeyOperator") == 0 && (obj.fields & Field_pubKeyOperator)) {\
221-
SER_READ(obj, read_pubkey = true); \
222-
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == ProTxVersion::LegacyBLS)); \
223-
} else if (obj.fields & Field_##f) READWRITE(obj.state.f);
224-
225-
DMN_STATE_DIFF_ALL_FIELDS
226-
#undef DMN_STATE_DIFF_LINE
242+
boost::hana::for_each(members, [&](auto&& member) {
243+
using BaseType = std::decay_t<decltype(member)>;
244+
if constexpr (BaseType::mask == Field_pubKeyOperator) {
245+
if (obj.fields & member.mask) {
246+
SER_READ(obj, read_pubkey = true);
247+
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == ProTxVersion::LegacyBLS));
248+
}
249+
} else {
250+
if (obj.fields & member.mask) {
251+
READWRITE(member.get(obj.state));
252+
}
253+
}
254+
});
255+
227256
if (read_pubkey) {
228257
SER_READ(obj, obj.fields |= Field_nVersion);
229258
SER_READ(obj, obj.state.pubKeyOperator.SetLegacy(obj.state.nVersion == ProTxVersion::LegacyBLS));
@@ -232,11 +261,12 @@ class CDeterministicMNStateDiff
232261

233262
void ApplyToState(CDeterministicMNState& target) const
234263
{
235-
#define DMN_STATE_DIFF_LINE(f) if (fields & Field_##f) target.f = state.f;
236-
DMN_STATE_DIFF_ALL_FIELDS
237-
#undef DMN_STATE_DIFF_LINE
264+
boost::hana::for_each(members, [&](auto&& member) {
265+
if (fields & member.mask) {
266+
member.get(target) = member.get(state);
267+
}
268+
});
238269
}
239270
};
240271

241-
242272
#endif // BITCOIN_EVO_DMNSTATE_H

test/lint/lint-includes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
"src/crypto/x11/"]
2626

2727
EXPECTED_BOOST_INCLUDES = ["boost/date_time/posix_time/posix_time.hpp",
28+
"boost/hana/for_each.hpp",
29+
"boost/hana/tuple.hpp",
2830
"boost/multi_index/hashed_index.hpp",
2931
"boost/multi_index/identity.hpp",
3032
"boost/multi_index/indexed_by.hpp",

0 commit comments

Comments
 (0)