forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat!: BLS scheme upgrade #5021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
PastaPastaPasta
merged 49 commits into
dashpay:develop
from
ogabrielides:bls_scheme_upgrade
Dec 30, 2022
Merged
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
a0d692d
BIP9 BLS hard fork
ogabrielides 0d59c87
Basic BLS scheme implementation
ogabrielides 18e2a2b
Adaptation for basic BLS
ogabrielides 17d607d
Basic BLS for CoinJoin objects
ogabrielides 87f31ca
Various refactoring
ogabrielides 8211869
Moved activation of BLS HF
ogabrielides bc7a9a9
build(bls): bump bls-dash depends to latest develop (4da22c2557e39d85…
kwvg c95f95d
Legacy version of protx register/update/revoke series
ogabrielides e12ad66
Fix for legacy protx version
ogabrielides e8a2805
Refactor
ogabrielides a1ec8fc
BLS Unerialisation fix
ogabrielides 60d8cf0
Correct serialisation of protx objects
ogabrielides 8f0df8a
getVersion helper method for CFinalCommitment
ogabrielides 834182d
Updated unit tests
ogabrielides 8672b18
Removed extra space
ogabrielides b8a17b3
Renamed CBLSPublicKeyVersionWrapper
ogabrielides f9ae65c
Serialisation support for CSimplifiedMNListEntry
ogabrielides 4408ce1
Various fixes and refactoring
ogabrielides 350bd17
Updated evo_deterministicmns_tests
ogabrielides 2bda2eb
Deleted old comment
ogabrielides fc1091f
Correct deployment checks
ogabrielides 2de2366
Correct serialisation of MNAUTH messages
ogabrielides c131c66
Correct include
ogabrielides d66e77f
Correct BIP9 checking
ogabrielides 614fedd
Fix for interface_zmq_dash.py
ogabrielides 844072b
use `return`s for protxes
UdjinM6 8b85bb9
secret key doesn't care about schemes
UdjinM6 3b13131
let `bls fromsecret` use specific scheme
UdjinM6 db43d7e
make `mnauth` rpc respect v19
UdjinM6 00ce0dd
some cleanup
UdjinM6 fc759d1
SigShares IsValid method
ogabrielides ba1cd61
some WIP changes
PastaPastaPasta 21f51fa
some fixes to WIP changes
PastaPastaPasta afe2553
Applied suggestions
ogabrielides 1502892
fix dmstate
UdjinM6 b97986b
Fix for LazyBLS + corrections
ogabrielides 8577b9c
fix
ogabrielides a675be6
Migration lazy BLS case
ogabrielides e1d99c6
Rebase fix
ogabrielides ebb4063
Linter fixes
ogabrielides 156fcb7
experimental linter, linking fix
ogabrielides 68e2a3d
cleanup
UdjinM6 d573ecb
chore: wrap bitwise AND in `()`
UdjinM6 37b66a8
legacy/basic for governance
UdjinM6 eabbe24
do not allow BASIC_BLS_VERSION protx version before the v19 fork
UdjinM6 7517277
Add legacy/basic bls versioning to MNHFTx
UdjinM6 7dd3bec
add bls sig serialization test
UdjinM6 e65f93a
don't throw exception, serialise all-zero buffer
ogabrielides 16b6bdd
Update src/bls/bls.h
ogabrielides File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,7 +99,6 @@ class CBLSWrapper | |
| *(static_cast<C*>(this)) = C(); | ||
| } | ||
|
|
||
| //TODO: Overwrite function with default value of specificLegacyScheme | ||
| void SetByteVector(const std::vector<uint8_t>& vecBytes, const bool specificLegacyScheme) | ||
| { | ||
| if (vecBytes.size() != SerSize) { | ||
|
|
@@ -125,7 +124,6 @@ class CBLSWrapper | |
| SetByteVector(vecBytes, bls::bls_legacy_scheme.load()); | ||
| } | ||
|
|
||
| //TODO: Overwrite function with default value of specificLegacyScheme | ||
| std::vector<uint8_t> ToByteVector(const bool specificLegacyScheme) const | ||
| { | ||
| if (!fValid) { | ||
|
|
@@ -147,8 +145,7 @@ class CBLSWrapper | |
| return cachedHash; | ||
| } | ||
|
|
||
| //TODO: Add version with argument (bool specificLegacyScheme) | ||
| bool SetHexStr(const std::string& str) | ||
| bool SetHexStr(const std::string& str, const bool specificLegacyScheme) | ||
| { | ||
| if (!IsHex(str)) { | ||
| Reset(); | ||
|
|
@@ -159,16 +156,20 @@ class CBLSWrapper | |
| Reset(); | ||
| return false; | ||
| } | ||
| SetByteVector(b); | ||
| SetByteVector(b, specificLegacyScheme); | ||
| return IsValid(); | ||
| } | ||
|
|
||
| bool SetHexStr(const std::string& str) | ||
| { | ||
| return SetHexStr(str, bls::bls_legacy_scheme.load()); | ||
| } | ||
|
|
||
| inline void Serialize(CSizeComputer& s) const | ||
| { | ||
| s.seek(SerSize); | ||
| } | ||
|
|
||
| //TODO: Overwrite function with default value of specificLegacyScheme | ||
| template <typename Stream> | ||
| inline void Serialize(Stream& s, const bool specificLegacyScheme) const | ||
| { | ||
|
|
@@ -181,15 +182,14 @@ class CBLSWrapper | |
| Serialize(s, bls::bls_legacy_scheme.load()); | ||
| } | ||
|
|
||
| //TODO: Overwrite function with default value of specificLegacyScheme | ||
| template <typename Stream> | ||
| inline void Unserialize(Stream& s, const bool specificLegacyScheme, bool checkMalleable = true) | ||
| { | ||
| std::vector<uint8_t> vecBytes(SerSize, 0); | ||
| s.read(reinterpret_cast<char*>(vecBytes.data()), SerSize); | ||
| SetByteVector(vecBytes, specificLegacyScheme); | ||
|
|
||
| if (checkMalleable && !CheckMalleable(vecBytes)) { | ||
| if (checkMalleable && !CheckMalleable(vecBytes, specificLegacyScheme)) { | ||
| throw std::ios_base::failure("malleable BLS object"); | ||
| } | ||
| } | ||
|
|
@@ -200,7 +200,6 @@ class CBLSWrapper | |
| Unserialize(s, bls::bls_legacy_scheme.load(), checkMalleable); | ||
| } | ||
|
|
||
| //TODO: Overwrite function with default value of specificLegacyScheme | ||
| inline bool CheckMalleable(const std::vector<uint8_t>& vecBytes, const bool specificLegacyScheme) const | ||
| { | ||
| if (memcmp(vecBytes.data(), ToByteVector(specificLegacyScheme).data(), SerSize)) { | ||
|
|
@@ -305,6 +304,44 @@ class CBLSPublicKey : public CBLSWrapper<bls::G1Element, BLS_CURVE_PUBKEY_SIZE, | |
|
|
||
| }; | ||
|
|
||
| class ConstCBLSPublicKeyVersionWrapper { | ||
| private: | ||
| bool legacy; | ||
| bool checkMalleable; | ||
| const CBLSPublicKey& obj; | ||
| public: | ||
| ConstCBLSPublicKeyVersionWrapper(const CBLSPublicKey& obj, bool legacy, bool checkMalleable = true) | ||
| : obj(obj) | ||
| , legacy(legacy) | ||
| , checkMalleable(checkMalleable) | ||
| {} | ||
| template <typename Stream> | ||
| inline void Serialize(Stream& s) const { | ||
| obj.Serialize(s, legacy); | ||
| } | ||
| }; | ||
|
|
||
| class CBLSPublicKeyVersionWrapper { | ||
| private: | ||
| bool legacy; | ||
| bool checkMalleable; | ||
| CBLSPublicKey& obj; | ||
| public: | ||
| CBLSPublicKeyVersionWrapper(CBLSPublicKey& obj, bool legacy, bool checkMalleable = true) | ||
| : obj(obj) | ||
| , legacy(legacy) | ||
| , checkMalleable(checkMalleable) | ||
| {} | ||
| template <typename Stream> | ||
| inline void Serialize(Stream& s) const { | ||
| obj.Serialize(s, legacy); | ||
| } | ||
| template <typename Stream> | ||
| inline void Unserialize(Stream& s) { | ||
| obj.Unserialize(s, legacy, checkMalleable); | ||
| } | ||
| }; | ||
|
|
||
| class CBLSSignature : public CBLSWrapper<bls::G2Element, BLS_CURVE_SIG_SIZE, CBLSSignature> | ||
| { | ||
| friend class CBLSSecretKey; | ||
|
|
@@ -332,6 +369,27 @@ class CBLSSignature : public CBLSWrapper<bls::G2Element, BLS_CURVE_SIG_SIZE, CBL | |
| bool Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids); | ||
| }; | ||
|
|
||
| class CBLSSignatureVersionWrapper { | ||
| private: | ||
| bool legacy; | ||
| bool checkMalleable; | ||
| CBLSSignature& obj; | ||
| public: | ||
| CBLSSignatureVersionWrapper(CBLSSignature& obj, bool legacy, bool checkMalleable = true) | ||
| : obj(obj) | ||
| , legacy(legacy) | ||
| , checkMalleable(checkMalleable) | ||
| {} | ||
| template <typename Stream> | ||
| inline void Serialize(Stream& s) const { | ||
| obj.Serialize(s, legacy); | ||
| } | ||
| template <typename Stream> | ||
| inline void Unserialize(Stream& s, bool checkMalleable = true) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like a bug for me due to shadowing class's member |
||
| obj.Unserialize(s, legacy, checkMalleable); | ||
| } | ||
| }; | ||
|
|
||
| #ifndef BUILD_BITCOIN_INTERNAL | ||
| template<typename BLSObject> | ||
| class CBLSLazyWrapper | ||
|
|
@@ -341,6 +399,7 @@ class CBLSLazyWrapper | |
|
|
||
| mutable std::vector<uint8_t> vecBytes; | ||
| mutable bool bufValid{false}; | ||
| mutable bool bufLegacyScheme{true}; | ||
|
|
||
| mutable BLSObject obj; | ||
| mutable bool objInitialized{false}; | ||
|
|
@@ -349,7 +408,8 @@ class CBLSLazyWrapper | |
|
|
||
| public: | ||
| CBLSLazyWrapper() : | ||
| vecBytes(BLSObject::SerSize, 0) | ||
| vecBytes(BLSObject::SerSize, 0), | ||
| bufLegacyScheme(bls::bls_legacy_scheme.load()) | ||
| { | ||
| // the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid | ||
| bufValid = true; | ||
|
|
@@ -365,6 +425,7 @@ class CBLSLazyWrapper | |
| { | ||
| std::unique_lock<std::mutex> l(r.mutex); | ||
| bufValid = r.bufValid; | ||
| bufLegacyScheme = r.bufLegacyScheme; | ||
| if (r.bufValid) { | ||
| vecBytes = r.vecBytes; | ||
| } else { | ||
|
|
@@ -386,30 +447,47 @@ class CBLSLazyWrapper | |
| } | ||
|
|
||
| template<typename Stream> | ||
| inline void Serialize(Stream& s) const | ||
| inline void Serialize(Stream& s, const bool specificLegacyScheme) const | ||
| { | ||
| std::unique_lock<std::mutex> l(mutex); | ||
| if (!objInitialized && !bufValid) { | ||
| throw std::ios_base::failure("obj and buf not initialized"); | ||
| // the all-zero buf is considered a valid buf | ||
| std::fill(vecBytes.begin(), vecBytes.end(), 0); | ||
| bufLegacyScheme = specificLegacyScheme; | ||
| bufValid = true; | ||
| } | ||
| if (!bufValid) { | ||
| vecBytes = obj.ToByteVector(); | ||
| if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) { | ||
| vecBytes = obj.ToByteVector(specificLegacyScheme); | ||
| bufValid = true; | ||
| bufLegacyScheme = specificLegacyScheme; | ||
| hash.SetNull(); | ||
| } | ||
| s.write(reinterpret_cast<const char*>(vecBytes.data()), vecBytes.size()); | ||
| } | ||
|
|
||
| template<typename Stream> | ||
| inline void Unserialize(Stream& s) | ||
| inline void Serialize(Stream& s) const | ||
| { | ||
| Serialize(s, bls::bls_legacy_scheme.load()); | ||
| } | ||
|
|
||
| template<typename Stream> | ||
| inline void Unserialize(Stream& s, const bool specificLegacyScheme) const | ||
| { | ||
| std::unique_lock<std::mutex> l(mutex); | ||
| s.read(reinterpret_cast<char*>(vecBytes.data()), BLSObject::SerSize); | ||
| bufValid = true; | ||
| bufLegacyScheme = specificLegacyScheme; | ||
| objInitialized = false; | ||
| hash.SetNull(); | ||
| } | ||
|
|
||
| template<typename Stream> | ||
| inline void Unserialize(Stream& s) const | ||
| { | ||
| Unserialize(s, bls::bls_legacy_scheme.load()); | ||
| } | ||
|
|
||
| void Set(const BLSObject& _obj) | ||
| { | ||
| std::unique_lock<std::mutex> l(mutex); | ||
|
|
@@ -426,8 +504,17 @@ class CBLSLazyWrapper | |
| return invalidObj; | ||
| } | ||
| if (!objInitialized) { | ||
| obj.SetByteVector(vecBytes); | ||
| if (!obj.CheckMalleable(vecBytes)) { | ||
| obj.SetByteVector(vecBytes, bufLegacyScheme); | ||
| if (!obj.IsValid()) { | ||
| // If setting of BLS object using one scheme failed, then we need to attempt again with the opposite scheme. | ||
| // This is due to the fact that LazyBLSWrapper receives a serialised buffer but attempts to create actual BLS object when needed. | ||
| // That could happen when the fork has been activated and the enforced scheme has switched. | ||
| obj.SetByteVector(vecBytes, !bufLegacyScheme); | ||
| if (obj.IsValid()) { | ||
| bufLegacyScheme = !bufLegacyScheme; | ||
| } | ||
| } | ||
| if (!obj.CheckMalleable(vecBytes, bufLegacyScheme)) { | ||
| bufValid = false; | ||
| objInitialized = false; | ||
| obj = invalidObj; | ||
|
|
@@ -440,7 +527,7 @@ class CBLSLazyWrapper | |
|
|
||
| bool operator==(const CBLSLazyWrapper& r) const | ||
| { | ||
| if (bufValid && r.bufValid) { | ||
| if (bufValid && r.bufValid && bufLegacyScheme == r.bufLegacyScheme) { | ||
| return vecBytes == r.vecBytes; | ||
| } | ||
| if (objInitialized && r.objInitialized) { | ||
|
|
@@ -454,12 +541,13 @@ class CBLSLazyWrapper | |
| return !(*this == r); | ||
| } | ||
|
|
||
| uint256 GetHash() const | ||
| uint256 GetHash(const bool specificLegacyScheme = bls::bls_legacy_scheme.load()) const | ||
| { | ||
| std::unique_lock<std::mutex> l(mutex); | ||
| if (!bufValid) { | ||
| vecBytes = obj.ToByteVector(); | ||
| if (!bufValid || bufLegacyScheme != specificLegacyScheme) { | ||
| vecBytes = obj.ToByteVector(specificLegacyScheme); | ||
| bufValid = true; | ||
| bufLegacyScheme = specificLegacyScheme; | ||
| hash.SetNull(); | ||
| } | ||
| if (hash.IsNull()) { | ||
|
|
@@ -472,6 +560,25 @@ class CBLSLazyWrapper | |
| }; | ||
| using CBLSLazySignature = CBLSLazyWrapper<CBLSSignature>; | ||
| using CBLSLazyPublicKey = CBLSLazyWrapper<CBLSPublicKey>; | ||
|
|
||
| class CBLSLazyPublicKeyVersionWrapper { | ||
| private: | ||
| bool legacy; | ||
| CBLSLazyPublicKey& obj; | ||
| public: | ||
| CBLSLazyPublicKeyVersionWrapper(CBLSLazyPublicKey& obj, bool legacy) | ||
| : obj(obj) | ||
| , legacy(legacy) | ||
| {} | ||
| template <typename Stream> | ||
| inline void Serialize(Stream& s) const { | ||
| obj.Serialize(s, legacy); | ||
| } | ||
| template <typename Stream> | ||
| inline void Unserialize(Stream& s) { | ||
| obj.Unserialize(s, legacy); | ||
| } | ||
| }; | ||
| #endif | ||
|
|
||
| using BLSIdVector = std::vector<CBLSId>; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to use
enum classinstead bool for better code reability.Otherwise it is more difficult to read code such as "SetHexStr(str, true)" without using IDE's hints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this bool can be extra pain in case if it would be once 3rd version of BLS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, there are two other schemes in the BLS library.