@@ -35,6 +35,7 @@ class CDeterministicMNState
3535 int nPoSeBanHeight{-1 };
3636
3737 friend class CDeterministicMNStateDiff ;
38+ friend class CDeterministicMNStateDiffLegacy ;
3839
3940public:
4041 int nVersion{ProTxVersion::LegacyBLS};
@@ -284,4 +285,139 @@ class CDeterministicMNStateDiff
284285 }
285286};
286287
288+ // Legacy deserializer class
289+ class CDeterministicMNStateDiffLegacy
290+ {
291+ private:
292+ // Legacy field enum with original bit positions
293+ enum LegacyField : uint32_t {
294+ LegacyField_nRegisteredHeight = 0x0001 ,
295+ LegacyField_nLastPaidHeight = 0x0002 ,
296+ LegacyField_nPoSePenalty = 0x0004 ,
297+ LegacyField_nPoSeRevivedHeight = 0x0008 ,
298+ LegacyField_nPoSeBanHeight = 0x0010 ,
299+ LegacyField_nRevocationReason = 0x0020 ,
300+ LegacyField_confirmedHash = 0x0040 ,
301+ LegacyField_confirmedHashWithProRegTxHash = 0x0080 ,
302+ LegacyField_keyIDOwner = 0x0100 ,
303+ LegacyField_pubKeyOperator = 0x0200 ,
304+ LegacyField_keyIDVoting = 0x0400 ,
305+ LegacyField_netInfo = 0x0800 ,
306+ LegacyField_scriptPayout = 0x1000 ,
307+ LegacyField_scriptOperatorPayout = 0x2000 ,
308+ LegacyField_nConsecutivePayments = 0x4000 ,
309+ LegacyField_platformNodeID = 0x8000 ,
310+ LegacyField_platformP2PPort = 0x10000 ,
311+ LegacyField_platformHTTPPort = 0x20000 ,
312+ LegacyField_nVersion = 0x40000 ,
313+ };
314+
315+ // Legacy member template with old bit positions
316+ template <auto CDeterministicMNState::*Field, uint32_t Mask>
317+ struct LegacyMember {
318+ static constexpr uint32_t mask = Mask;
319+ static auto & get (CDeterministicMNState& state) { return state.*Field; }
320+ static const auto & get (const CDeterministicMNState& state) { return state.*Field; }
321+ };
322+
323+ #define LEGACY_DMN_STATE_MEMBER (name ) \
324+ LegacyMember<&CDeterministicMNState::name, LegacyField_##name> {}
325+ static constexpr auto legacy_members = boost::hana::make_tuple(
326+ LEGACY_DMN_STATE_MEMBER (nRegisteredHeight),
327+ LEGACY_DMN_STATE_MEMBER(nLastPaidHeight),
328+ LEGACY_DMN_STATE_MEMBER(nPoSePenalty),
329+ LEGACY_DMN_STATE_MEMBER(nPoSeRevivedHeight),
330+ LEGACY_DMN_STATE_MEMBER(nPoSeBanHeight),
331+ LEGACY_DMN_STATE_MEMBER(nRevocationReason),
332+ LEGACY_DMN_STATE_MEMBER(confirmedHash),
333+ LEGACY_DMN_STATE_MEMBER(confirmedHashWithProRegTxHash),
334+ LEGACY_DMN_STATE_MEMBER(keyIDOwner),
335+ LEGACY_DMN_STATE_MEMBER(pubKeyOperator),
336+ LEGACY_DMN_STATE_MEMBER(keyIDVoting),
337+ LEGACY_DMN_STATE_MEMBER(netInfo),
338+ LEGACY_DMN_STATE_MEMBER(scriptPayout),
339+ LEGACY_DMN_STATE_MEMBER(scriptOperatorPayout),
340+ LEGACY_DMN_STATE_MEMBER(nConsecutivePayments),
341+ LEGACY_DMN_STATE_MEMBER(platformNodeID),
342+ LEGACY_DMN_STATE_MEMBER(platformP2PPort),
343+ LEGACY_DMN_STATE_MEMBER(platformHTTPPort),
344+ LEGACY_DMN_STATE_MEMBER(nVersion)
345+ );
346+ #undef LEGACY_DMN_STATE_MEMBER
347+
348+ public:
349+ uint32_t fields{0 };
350+ CDeterministicMNState state;
351+
352+ CDeterministicMNStateDiffLegacy () = default ;
353+
354+ template <typename Stream>
355+ CDeterministicMNStateDiffLegacy (deserialize_type, Stream& s) { s >> *this ; }
356+
357+ // Deserialize using legacy format
358+ SERIALIZE_METHODS (CDeterministicMNStateDiffLegacy, obj)
359+ {
360+ READWRITE (VARINT (obj.fields ));
361+
362+ bool read_pubkey{false };
363+ boost::hana::for_each (legacy_members, [&](auto && member) {
364+ using BaseType = std::decay_t <decltype (member)>;
365+ if constexpr (BaseType::mask == LegacyField_pubKeyOperator) {
366+ if (obj.fields & member.mask ) {
367+ SER_READ (obj, read_pubkey = true );
368+ READWRITE (CBLSLazyPublicKeyVersionWrapper (const_cast <CBLSLazyPublicKey&>(obj.state .pubKeyOperator ),
369+ obj.state .nVersion == ProTxVersion::LegacyBLS));
370+ }
371+ } else if constexpr (BaseType::mask == LegacyField_netInfo) {
372+ if (obj.fields & member.mask ) {
373+ // Legacy format supports non-extended addresses only
374+ READWRITE (NetInfoSerWrapper (const_cast <std::shared_ptr<NetInfoInterface>&>(obj.state .netInfo ), false ));
375+ }
376+ } else {
377+ if (obj.fields & member.mask ) {
378+ READWRITE (member.get (obj.state ));
379+ }
380+ }
381+ });
382+
383+ if (read_pubkey) {
384+ SER_READ (obj, obj.fields |= LegacyField_nVersion);
385+ SER_READ (obj, obj.state .pubKeyOperator .SetLegacy (obj.state .nVersion == ProTxVersion::LegacyBLS));
386+ }
387+ }
388+
389+ // Convert to new format
390+ CDeterministicMNStateDiff ToNewFormat () const
391+ {
392+ CDeterministicMNStateDiff newDiff;
393+ newDiff.state = state;
394+
395+ // Convert field bits to new positions
396+ #define LEGACY_DMN_STATE_BITS (name ) \
397+ if (fields & LegacyField_##name) newDiff.fields |= CDeterministicMNStateDiff::Field_##name;
398+ LEGACY_DMN_STATE_BITS (nVersion)
399+ LEGACY_DMN_STATE_BITS (nRegisteredHeight)
400+ LEGACY_DMN_STATE_BITS (nLastPaidHeight)
401+ LEGACY_DMN_STATE_BITS (nPoSePenalty)
402+ LEGACY_DMN_STATE_BITS (nPoSeRevivedHeight)
403+ LEGACY_DMN_STATE_BITS (nPoSeBanHeight)
404+ LEGACY_DMN_STATE_BITS (nRevocationReason)
405+ LEGACY_DMN_STATE_BITS (confirmedHash)
406+ LEGACY_DMN_STATE_BITS (confirmedHashWithProRegTxHash)
407+ LEGACY_DMN_STATE_BITS (keyIDOwner)
408+ LEGACY_DMN_STATE_BITS (pubKeyOperator)
409+ LEGACY_DMN_STATE_BITS (keyIDVoting)
410+ LEGACY_DMN_STATE_BITS (netInfo)
411+ LEGACY_DMN_STATE_BITS (scriptPayout)
412+ LEGACY_DMN_STATE_BITS (scriptOperatorPayout)
413+ LEGACY_DMN_STATE_BITS (nConsecutivePayments)
414+ LEGACY_DMN_STATE_BITS (platformNodeID)
415+ LEGACY_DMN_STATE_BITS (platformP2PPort)
416+ LEGACY_DMN_STATE_BITS (platformHTTPPort)
417+ #undef LEGACY_DMN_STATE_BITS
418+
419+ return newDiff;
420+ }
421+ };
422+
287423#endif // BITCOIN_EVO_DMNSTATE_H
0 commit comments