@@ -99,7 +99,6 @@ class CBLSWrapper
9999 *(static_cast <C*>(this )) = C ();
100100 }
101101
102- // TODO: Overwrite function with default value of specificLegacyScheme
103102 void SetByteVector (const std::vector<uint8_t >& vecBytes, const bool specificLegacyScheme)
104103 {
105104 if (vecBytes.size () != SerSize) {
@@ -125,7 +124,6 @@ class CBLSWrapper
125124 SetByteVector (vecBytes, bls::bls_legacy_scheme.load ());
126125 }
127126
128- // TODO: Overwrite function with default value of specificLegacyScheme
129127 std::vector<uint8_t > ToByteVector (const bool specificLegacyScheme) const
130128 {
131129 if (!fValid ) {
@@ -147,8 +145,7 @@ class CBLSWrapper
147145 return cachedHash;
148146 }
149147
150- // TODO: Add version with argument (bool specificLegacyScheme)
151- bool SetHexStr (const std::string& str)
148+ bool SetHexStr (const std::string& str, const bool specificLegacyScheme)
152149 {
153150 if (!IsHex (str)) {
154151 Reset ();
@@ -159,16 +156,20 @@ class CBLSWrapper
159156 Reset ();
160157 return false ;
161158 }
162- SetByteVector (b);
159+ SetByteVector (b, specificLegacyScheme );
163160 return IsValid ();
164161 }
165162
163+ bool SetHexStr (const std::string& str)
164+ {
165+ return SetHexStr (str, bls::bls_legacy_scheme.load ());
166+ }
167+
166168 inline void Serialize (CSizeComputer& s) const
167169 {
168170 s.seek (SerSize);
169171 }
170172
171- // TODO: Overwrite function with default value of specificLegacyScheme
172173 template <typename Stream>
173174 inline void Serialize (Stream& s, const bool specificLegacyScheme) const
174175 {
@@ -181,15 +182,14 @@ class CBLSWrapper
181182 Serialize (s, bls::bls_legacy_scheme.load ());
182183 }
183184
184- // TODO: Overwrite function with default value of specificLegacyScheme
185185 template <typename Stream>
186186 inline void Unserialize (Stream& s, const bool specificLegacyScheme, bool checkMalleable = true )
187187 {
188188 std::vector<uint8_t > vecBytes (SerSize, 0 );
189189 s.read (reinterpret_cast <char *>(vecBytes.data ()), SerSize);
190190 SetByteVector (vecBytes, specificLegacyScheme);
191191
192- if (checkMalleable && !CheckMalleable (vecBytes)) {
192+ if (checkMalleable && !CheckMalleable (vecBytes, specificLegacyScheme )) {
193193 throw std::ios_base::failure (" malleable BLS object" );
194194 }
195195 }
@@ -200,7 +200,6 @@ class CBLSWrapper
200200 Unserialize (s, bls::bls_legacy_scheme.load (), checkMalleable);
201201 }
202202
203- // TODO: Overwrite function with default value of specificLegacyScheme
204203 inline bool CheckMalleable (const std::vector<uint8_t >& vecBytes, const bool specificLegacyScheme) const
205204 {
206205 if (memcmp (vecBytes.data (), ToByteVector (specificLegacyScheme).data (), SerSize)) {
@@ -305,6 +304,44 @@ class CBLSPublicKey : public CBLSWrapper<bls::G1Element, BLS_CURVE_PUBKEY_SIZE,
305304
306305};
307306
307+ class ConstCBLSPublicKeyVersionWrapper {
308+ private:
309+ bool legacy;
310+ bool checkMalleable;
311+ const CBLSPublicKey& obj;
312+ public:
313+ ConstCBLSPublicKeyVersionWrapper (const CBLSPublicKey& obj, bool legacy, bool checkMalleable = true )
314+ : obj(obj)
315+ , legacy(legacy)
316+ , checkMalleable(checkMalleable)
317+ {}
318+ template <typename Stream>
319+ inline void Serialize (Stream& s) const {
320+ obj.Serialize (s, legacy);
321+ }
322+ };
323+
324+ class CBLSPublicKeyVersionWrapper {
325+ private:
326+ bool legacy;
327+ bool checkMalleable;
328+ CBLSPublicKey& obj;
329+ public:
330+ CBLSPublicKeyVersionWrapper (CBLSPublicKey& obj, bool legacy, bool checkMalleable = true )
331+ : obj(obj)
332+ , legacy(legacy)
333+ , checkMalleable(checkMalleable)
334+ {}
335+ template <typename Stream>
336+ inline void Serialize (Stream& s) const {
337+ obj.Serialize (s, legacy);
338+ }
339+ template <typename Stream>
340+ inline void Unserialize (Stream& s) {
341+ obj.Unserialize (s, legacy, checkMalleable);
342+ }
343+ };
344+
308345class CBLSSignature : public CBLSWrapper <bls::G2Element, BLS_CURVE_SIG_SIZE, CBLSSignature>
309346{
310347 friend class CBLSSecretKey ;
@@ -332,6 +369,27 @@ class CBLSSignature : public CBLSWrapper<bls::G2Element, BLS_CURVE_SIG_SIZE, CBL
332369 bool Recover (const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids);
333370};
334371
372+ class CBLSSignatureVersionWrapper {
373+ private:
374+ bool legacy;
375+ bool checkMalleable;
376+ CBLSSignature& obj;
377+ public:
378+ CBLSSignatureVersionWrapper (CBLSSignature& obj, bool legacy, bool checkMalleable = true )
379+ : obj(obj)
380+ , legacy(legacy)
381+ , checkMalleable(checkMalleable)
382+ {}
383+ template <typename Stream>
384+ inline void Serialize (Stream& s) const {
385+ obj.Serialize (s, legacy);
386+ }
387+ template <typename Stream>
388+ inline void Unserialize (Stream& s, bool checkMalleable = true ) {
389+ obj.Unserialize (s, legacy, checkMalleable);
390+ }
391+ };
392+
335393#ifndef BUILD_BITCOIN_INTERNAL
336394template <typename BLSObject>
337395class CBLSLazyWrapper
@@ -341,6 +399,7 @@ class CBLSLazyWrapper
341399
342400 mutable std::vector<uint8_t > vecBytes;
343401 mutable bool bufValid{false };
402+ mutable bool bufLegacyScheme{true };
344403
345404 mutable BLSObject obj;
346405 mutable bool objInitialized{false };
@@ -349,7 +408,8 @@ class CBLSLazyWrapper
349408
350409public:
351410 CBLSLazyWrapper () :
352- vecBytes (BLSObject::SerSize, 0 )
411+ vecBytes (BLSObject::SerSize, 0 ),
412+ bufLegacyScheme (bls::bls_legacy_scheme.load())
353413 {
354414 // the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid
355415 bufValid = true ;
@@ -365,6 +425,7 @@ class CBLSLazyWrapper
365425 {
366426 std::unique_lock<std::mutex> l (r.mutex );
367427 bufValid = r.bufValid ;
428+ bufLegacyScheme = r.bufLegacyScheme ;
368429 if (r.bufValid ) {
369430 vecBytes = r.vecBytes ;
370431 } else {
@@ -386,30 +447,47 @@ class CBLSLazyWrapper
386447 }
387448
388449 template <typename Stream>
389- inline void Serialize (Stream& s) const
450+ inline void Serialize (Stream& s, const bool specificLegacyScheme ) const
390451 {
391452 std::unique_lock<std::mutex> l (mutex);
392453 if (!objInitialized && !bufValid) {
393- throw std::ios_base::failure (" obj and buf not initialized" );
454+ // the all-zero buf is considered a valid buf
455+ std::fill (vecBytes.begin (), vecBytes.end (), 0 );
456+ bufLegacyScheme = specificLegacyScheme;
457+ bufValid = true ;
394458 }
395- if (!bufValid) {
396- vecBytes = obj.ToByteVector ();
459+ if (!bufValid || (bufLegacyScheme != specificLegacyScheme) ) {
460+ vecBytes = obj.ToByteVector (specificLegacyScheme );
397461 bufValid = true ;
462+ bufLegacyScheme = specificLegacyScheme;
398463 hash.SetNull ();
399464 }
400465 s.write (reinterpret_cast <const char *>(vecBytes.data ()), vecBytes.size ());
401466 }
402467
403468 template <typename Stream>
404- inline void Unserialize (Stream& s)
469+ inline void Serialize (Stream& s) const
470+ {
471+ Serialize (s, bls::bls_legacy_scheme.load ());
472+ }
473+
474+ template <typename Stream>
475+ inline void Unserialize (Stream& s, const bool specificLegacyScheme) const
405476 {
406477 std::unique_lock<std::mutex> l (mutex);
407478 s.read (reinterpret_cast <char *>(vecBytes.data ()), BLSObject::SerSize);
408479 bufValid = true ;
480+ bufLegacyScheme = specificLegacyScheme;
409481 objInitialized = false ;
410482 hash.SetNull ();
411483 }
412484
485+ template <typename Stream>
486+ inline void Unserialize (Stream& s) const
487+ {
488+ Unserialize (s, bls::bls_legacy_scheme.load ());
489+ }
490+
413491 void Set (const BLSObject& _obj)
414492 {
415493 std::unique_lock<std::mutex> l (mutex);
@@ -426,8 +504,17 @@ class CBLSLazyWrapper
426504 return invalidObj;
427505 }
428506 if (!objInitialized) {
429- obj.SetByteVector (vecBytes);
430- if (!obj.CheckMalleable (vecBytes)) {
507+ obj.SetByteVector (vecBytes, bufLegacyScheme);
508+ if (!obj.IsValid ()) {
509+ // If setting of BLS object using one scheme failed, then we need to attempt again with the opposite scheme.
510+ // This is due to the fact that LazyBLSWrapper receives a serialised buffer but attempts to create actual BLS object when needed.
511+ // That could happen when the fork has been activated and the enforced scheme has switched.
512+ obj.SetByteVector (vecBytes, !bufLegacyScheme);
513+ if (obj.IsValid ()) {
514+ bufLegacyScheme = !bufLegacyScheme;
515+ }
516+ }
517+ if (!obj.CheckMalleable (vecBytes, bufLegacyScheme)) {
431518 bufValid = false ;
432519 objInitialized = false ;
433520 obj = invalidObj;
@@ -440,7 +527,7 @@ class CBLSLazyWrapper
440527
441528 bool operator ==(const CBLSLazyWrapper& r) const
442529 {
443- if (bufValid && r.bufValid ) {
530+ if (bufValid && r.bufValid && bufLegacyScheme == r. bufLegacyScheme ) {
444531 return vecBytes == r.vecBytes ;
445532 }
446533 if (objInitialized && r.objInitialized ) {
@@ -454,12 +541,13 @@ class CBLSLazyWrapper
454541 return !(*this == r);
455542 }
456543
457- uint256 GetHash () const
544+ uint256 GetHash (const bool specificLegacyScheme = bls::bls_legacy_scheme.load() ) const
458545 {
459546 std::unique_lock<std::mutex> l (mutex);
460- if (!bufValid) {
461- vecBytes = obj.ToByteVector ();
547+ if (!bufValid || bufLegacyScheme != specificLegacyScheme ) {
548+ vecBytes = obj.ToByteVector (specificLegacyScheme );
462549 bufValid = true ;
550+ bufLegacyScheme = specificLegacyScheme;
463551 hash.SetNull ();
464552 }
465553 if (hash.IsNull ()) {
@@ -472,6 +560,25 @@ class CBLSLazyWrapper
472560};
473561using CBLSLazySignature = CBLSLazyWrapper<CBLSSignature>;
474562using CBLSLazyPublicKey = CBLSLazyWrapper<CBLSPublicKey>;
563+
564+ class CBLSLazyPublicKeyVersionWrapper {
565+ private:
566+ bool legacy;
567+ CBLSLazyPublicKey& obj;
568+ public:
569+ CBLSLazyPublicKeyVersionWrapper (CBLSLazyPublicKey& obj, bool legacy)
570+ : obj(obj)
571+ , legacy(legacy)
572+ {}
573+ template <typename Stream>
574+ inline void Serialize (Stream& s) const {
575+ obj.Serialize (s, legacy);
576+ }
577+ template <typename Stream>
578+ inline void Unserialize (Stream& s) {
579+ obj.Unserialize (s, legacy);
580+ }
581+ };
475582#endif
476583
477584using BLSIdVector = std::vector<CBLSId>;
0 commit comments