1515#include < memory>
1616#include < utility>
1717
18+ #include < boost/hana/for_each.hpp>
19+ #include < boost/hana/tuple.hpp>
20+
1821class CProRegTx ;
1922class 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
197212public:
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
0 commit comments