Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

bls.h
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Dash Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef DASH_CRYPTO_BLS_H
6 #define DASH_CRYPTO_BLS_H
7 
8 #include <hash.h>
9 #include <serialize.h>
10 #include <uint256.h>
11 #include <utilstrencodings.h>
12 
13 #undef ERROR // chia BLS uses relic, which defines ERROR, which in turn causes win32/win64 builds to print many warnings
14 #include <chiabls/bls.hpp>
15 #include <chiabls/privatekey.hpp>
16 #include <chiabls/publickey.hpp>
17 #include <chiabls/signature.hpp>
18 #undef DOUBLE
19 
20 #include <array>
21 #include <mutex>
22 #include <unistd.h>
23 
24 // reversed BLS12-381
25 #define BLS_CURVE_ID_SIZE 32
26 #define BLS_CURVE_SECKEY_SIZE 32
27 #define BLS_CURVE_PUBKEY_SIZE 48
28 #define BLS_CURVE_SIG_SIZE 96
29 
30 class CBLSSignature;
31 class CBLSPublicKey;
32 
33 template <typename ImplType, size_t _SerSize, typename C>
35 {
36  friend class CBLSSecretKey;
37  friend class CBLSPublicKey;
38  friend class CBLSSignature;
39 
40 protected:
41  ImplType impl;
42  bool fValid{false};
44 
45  inline constexpr size_t GetSerSize() const { return SerSize; }
46 
47  virtual bool InternalSetBuf(const void* buf) = 0;
48  virtual bool InternalGetBuf(void* buf) const = 0;
49 
50 public:
51  static const size_t SerSize = _SerSize;
52 
54  {
55  struct NullHash {
56  uint256 hash;
57  NullHash() {
58  char buf[_SerSize];
59  memset(buf, 0, _SerSize);
60  CHashWriter ss(SER_GETHASH, 0);
61  ss.write(buf, _SerSize);
62  hash = ss.GetHash();
63  }
64  };
65  static NullHash nullHash;
66  cachedHash = nullHash.hash;
67  }
68 
69  CBLSWrapper(const CBLSWrapper& ref) = default;
70  CBLSWrapper& operator=(const CBLSWrapper& ref) = default;
72  {
73  std::swap(impl, ref.impl);
74  std::swap(fValid, ref.fValid);
75  std::swap(cachedHash, ref.cachedHash);
76  }
78  {
79  std::swap(impl, ref.impl);
80  std::swap(fValid, ref.fValid);
81  std::swap(cachedHash, ref.cachedHash);
82  return *this;
83  }
84 
85  bool operator==(const C& r) const
86  {
87  return fValid == r.fValid && impl == r.impl;
88  }
89  bool operator!=(const C& r) const
90  {
91  return !((*this) == r);
92  }
93 
94  bool IsValid() const
95  {
96  return fValid;
97  }
98 
99  void SetBuf(const void* buf, size_t size)
100  {
101  if (size != SerSize) {
102  Reset();
103  return;
104  }
105 
106  if (std::all_of((const char*)buf, (const char*)buf + SerSize, [](char c) { return c == 0; })) {
107  Reset();
108  } else {
109  fValid = InternalSetBuf(buf);
110  if (!fValid) {
111  Reset();
112  }
113  }
114  UpdateHash();
115  }
116 
117  void Reset()
118  {
119  *((C*)this) = C();
120  }
121 
122  void GetBuf(void* buf, size_t size) const
123  {
124  assert(size == SerSize);
125 
126  if (!fValid) {
127  memset(buf, 0, SerSize);
128  } else {
129  bool ok = InternalGetBuf(buf);
130  assert(ok);
131  }
132  }
133 
134  template <typename T>
135  void SetBuf(const T& buf)
136  {
137  SetBuf(buf.data(), buf.size());
138  }
139 
140  template <typename T>
141  void GetBuf(T& buf) const
142  {
143  buf.resize(GetSerSize());
144  GetBuf(buf.data(), buf.size());
145  }
146 
147  const uint256& GetHash() const
148  {
149  return cachedHash;
150  }
151 
152  void UpdateHash() const
153  {
154  cachedHash = ::SerializeHash(*this);
155  }
156 
157  bool SetHexStr(const std::string& str)
158  {
159  if (!IsHex(str)) {
160  Reset();
161  return false;
162  }
163  auto b = ParseHex(str);
164  if (b.size() != SerSize) {
165  Reset();
166  return false;
167  }
168  SetBuf(b);
169  return IsValid();
170  }
171 
172 public:
173  inline void Serialize(CSizeComputer& s) const
174  {
175  s.seek(SerSize);
176  }
177 
178  template <typename Stream>
179  inline void Serialize(Stream& s) const
180  {
181  char buf[SerSize] = {0};
182  GetBuf(buf, SerSize);
183  s.write((const char*)buf, SerSize);
184  }
185  template <typename Stream>
186  inline void Unserialize(Stream& s, bool checkMalleable = true)
187  {
188  char buf[SerSize];
189  s.read((char*)buf, SerSize);
190  SetBuf(buf, SerSize);
191 
192  if (checkMalleable && !CheckMalleable(buf, SerSize)) {
193  throw std::ios_base::failure("malleable BLS object");
194  }
195  }
196 
197  inline bool CheckMalleable(void* buf, size_t size) const
198  {
199  char buf2[SerSize];
200  GetBuf(buf2, SerSize);
201  if (memcmp(buf, buf2, SerSize)) {
202  // TODO not sure if this is actually possible with the BLS libs. I'm assuming here that somewhere deep inside
203  // these libs masking might happen, so that 2 different binary representations could result in the same object
204  // representation
205  return false;
206  }
207  return true;
208  }
209 
210  inline std::string ToString() const
211  {
212  std::vector<unsigned char> buf;
213  GetBuf(buf);
214  return HexStr(buf.begin(), buf.end());
215  }
216 };
217 
218 class CBLSId : public CBLSWrapper<uint256, BLS_CURVE_ID_SIZE, CBLSId>
219 {
220 public:
221  using CBLSWrapper::operator=;
222  using CBLSWrapper::operator==;
223  using CBLSWrapper::operator!=;
224 
225  CBLSId() {}
226 
227  void SetInt(int x);
228  void SetHash(const uint256& hash);
229 
230  static CBLSId FromInt(int64_t i);
231  static CBLSId FromHash(const uint256& hash);
232 
233 protected:
234  bool InternalSetBuf(const void* buf);
235  bool InternalGetBuf(void* buf) const;
236 };
237 
238 class CBLSSecretKey : public CBLSWrapper<bls::PrivateKey, BLS_CURVE_SECKEY_SIZE, CBLSSecretKey>
239 {
240 public:
241  using CBLSWrapper::operator=;
242  using CBLSWrapper::operator==;
243  using CBLSWrapper::operator!=;
244 
246 
247  void AggregateInsecure(const CBLSSecretKey& o);
248  static CBLSSecretKey AggregateInsecure(const std::vector<CBLSSecretKey>& sks);
249 
250 #ifndef BUILD_BITCOIN_INTERNAL
251  void MakeNewKey();
252 #endif
253  bool SecretKeyShare(const std::vector<CBLSSecretKey>& msk, const CBLSId& id);
254 
255  CBLSPublicKey GetPublicKey() const;
256  CBLSSignature Sign(const uint256& hash) const;
257 
258 protected:
259  bool InternalSetBuf(const void* buf);
260  bool InternalGetBuf(void* buf) const;
261 };
262 
263 class CBLSPublicKey : public CBLSWrapper<bls::PublicKey, BLS_CURVE_PUBKEY_SIZE, CBLSPublicKey>
264 {
265  friend class CBLSSecretKey;
266  friend class CBLSSignature;
267 
268 public:
269  using CBLSWrapper::operator=;
270  using CBLSWrapper::operator==;
271  using CBLSWrapper::operator!=;
272 
274 
275  void AggregateInsecure(const CBLSPublicKey& o);
276  static CBLSPublicKey AggregateInsecure(const std::vector<CBLSPublicKey>& pks);
277 
278  bool PublicKeyShare(const std::vector<CBLSPublicKey>& mpk, const CBLSId& id);
279  bool DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk);
280 
281 protected:
282  bool InternalSetBuf(const void* buf);
283  bool InternalGetBuf(void* buf) const;
284 };
285 
286 class CBLSSignature : public CBLSWrapper<bls::InsecureSignature, BLS_CURVE_SIG_SIZE, CBLSSignature>
287 {
288  friend class CBLSSecretKey;
289 
290 public:
291  using CBLSWrapper::operator==;
292  using CBLSWrapper::operator!=;
294 
296  CBLSSignature(const CBLSSignature&) = default;
297  CBLSSignature& operator=(const CBLSSignature&) = default;
298 
299  void AggregateInsecure(const CBLSSignature& o);
300  static CBLSSignature AggregateInsecure(const std::vector<CBLSSignature>& sigs);
301  static CBLSSignature AggregateSecure(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSPublicKey>& pks, const uint256& hash);
302 
303  void SubInsecure(const CBLSSignature& o);
304 
305  bool VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const;
306  bool VerifyInsecureAggregated(const std::vector<CBLSPublicKey>& pubKeys, const std::vector<uint256>& hashes) const;
307 
308  bool VerifySecureAggregated(const std::vector<CBLSPublicKey>& pks, const uint256& hash) const;
309 
310  bool Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids);
311 
312 protected:
313  bool InternalSetBuf(const void* buf);
314  bool InternalGetBuf(void* buf) const;
315 };
316 
317 #ifndef BUILD_BITCOIN_INTERNAL
318 template<typename BLSObject>
320 {
321 private:
322  mutable std::mutex mutex;
323 
324  mutable char buf[BLSObject::SerSize];
325  mutable bool bufValid{false};
326 
327  mutable BLSObject obj;
328  mutable bool objInitialized{false};
329 
330  mutable uint256 hash;
331 
332 public:
334  {
335  memset(buf, 0, sizeof(buf));
336  // the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid
337  bufValid = true;
338  }
339 
341  {
342  *this = r;
343  }
344 
346  {
347  std::unique_lock<std::mutex> l(r.mutex);
348  bufValid = r.bufValid;
349  if (r.bufValid) {
350  memcpy(buf, r.buf, sizeof(buf));
351  } else {
352  memset(buf, 0, sizeof(buf));
353  }
355  if (r.objInitialized) {
356  obj = r.obj;
357  } else {
358  obj.Reset();
359  }
360  hash = r.hash;
361  return *this;
362  }
363 
364  inline void Serialize(CSizeComputer& s) const
365  {
366  s.seek(BLSObject::SerSize);
367  }
368 
369  template<typename Stream>
370  inline void Serialize(Stream& s) const
371  {
372  std::unique_lock<std::mutex> l(mutex);
373  if (!objInitialized && !bufValid) {
374  throw std::ios_base::failure("obj and buf not initialized");
375  }
376  if (!bufValid) {
377  obj.GetBuf(buf, sizeof(buf));
378  bufValid = true;
379  hash = uint256();
380  }
381  s.write(buf, sizeof(buf));
382  }
383 
384  template<typename Stream>
385  inline void Unserialize(Stream& s)
386  {
387  std::unique_lock<std::mutex> l(mutex);
388  s.read(buf, sizeof(buf));
389  bufValid = true;
390  objInitialized = false;
391  hash = uint256();
392  }
393 
394  void Set(const BLSObject& _obj)
395  {
396  std::unique_lock<std::mutex> l(mutex);
397  bufValid = false;
398  objInitialized = true;
399  obj = _obj;
400  hash = uint256();
401  }
402  const BLSObject& Get() const
403  {
404  std::unique_lock<std::mutex> l(mutex);
405  static BLSObject invalidObj;
406  if (!bufValid && !objInitialized) {
407  return invalidObj;
408  }
409  if (!objInitialized) {
410  obj.SetBuf(buf, sizeof(buf));
411  if (!obj.CheckMalleable(buf, sizeof(buf))) {
412  bufValid = false;
413  objInitialized = false;
414  obj = invalidObj;
415  } else {
416  objInitialized = true;
417  }
418  }
419  return obj;
420  }
421 
422  bool operator==(const CBLSLazyWrapper& r) const
423  {
424  if (bufValid && r.bufValid) {
425  return memcmp(buf, r.buf, sizeof(buf)) == 0;
426  }
427  if (objInitialized && r.objInitialized) {
428  return obj == r.obj;
429  }
430  return Get() == r.Get();
431  }
432 
433  bool operator!=(const CBLSLazyWrapper& r) const
434  {
435  return !(*this == r);
436  }
437 
438  uint256 GetHash() const
439  {
440  std::unique_lock<std::mutex> l(mutex);
441  if (!bufValid) {
442  obj.GetBuf(buf, sizeof(buf));
443  bufValid = true;
444  hash = uint256();
445  }
446  if (hash.IsNull()) {
447  UpdateHash();
448  }
449  return hash;
450  }
451 private:
452  void UpdateHash() const
453  {
455  ss.write(buf, sizeof(buf));
456  hash = ss.GetHash();
457  }
458 };
462 #endif
463 
464 typedef std::vector<CBLSId> BLSIdVector;
465 typedef std::vector<CBLSPublicKey> BLSVerificationVector;
466 typedef std::vector<CBLSPublicKey> BLSPublicKeyVector;
467 typedef std::vector<CBLSSecretKey> BLSSecretKeyVector;
468 typedef std::vector<CBLSSignature> BLSSignatureVector;
469 
470 typedef std::shared_ptr<BLSIdVector> BLSIdVectorPtr;
471 typedef std::shared_ptr<BLSVerificationVector> BLSVerificationVectorPtr;
472 typedef std::shared_ptr<BLSPublicKeyVector> BLSPublicKeyVectorPtr;
473 typedef std::shared_ptr<BLSSecretKeyVector> BLSSecretKeyVectorPtr;
474 typedef std::shared_ptr<BLSSignatureVector> BLSSignatureVectorPtr;
475 
476 bool BLSInit();
477 
478 #endif // DASH_CRYPTO_BLS_H
CBLSWrapper & operator=(const CBLSWrapper &ref)=default
bool all_of(Range &&r, Pred p)
Definition: algorithm.hpp:193
static const sph_u32 C[]
Definition: jh.c:370
bool InternalSetBuf(const void *buf)
Definition: bls.cpp:175
bool CheckMalleable(void *buf, size_t size) const
Definition: bls.h:197
bool SecretKeyShare(const std::vector< CBLSSecretKey > &msk, const CBLSId &id)
Definition: bls.cpp:118
void write(const char *pch, size_t size)
Definition: hash.h:198
std::vector< CBLSPublicKey > BLSPublicKeyVector
Definition: bls.h:466
const uint256 & GetHash() const
Definition: bls.h:147
static CBLSId FromInt(int64_t i)
Definition: bls.cpp:44
CBLSLazyWrapper & operator=(const CBLSLazyWrapper &r)
Definition: bls.h:345
bool InternalGetBuf(void *buf) const
Definition: bls.cpp:185
CBLSSignature & operator=(const CBLSSignature &)=default
virtual bool InternalGetBuf(void *buf) const =0
static CBLSSignature AggregateSecure(const std::vector< CBLSSignature > &sigs, const std::vector< CBLSPublicKey > &pks, const uint256 &hash)
Definition: bls.cpp:304
void GetBuf(T &buf) const
Definition: bls.h:141
void SetBuf(const void *buf, size_t size)
Definition: bls.h:99
uint256 GetHash() const
Definition: bls.h:438
void SubInsecure(const CBLSSignature &o)
Definition: bls.cpp:328
bool SetHexStr(const std::string &str)
Definition: bls.h:157
CBLSLazyWrapper< CBLSSecretKey > CBLSLazySecretKey
Definition: bls.h:461
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
std::vector< CBLSPublicKey > BLSVerificationVector
Definition: bls.h:465
bool VerifyInsecure(const CBLSPublicKey &pubKey, const uint256 &hash) const
Definition: bls.cpp:335
CBLSWrapper & operator=(CBLSWrapper &&ref)
Definition: bls.h:77
BLSObject obj
Definition: bls.h:327
virtual bool InternalSetBuf(const void *buf)=0
bool BLSInit()
Definition: bls.cpp:466
bool objInitialized
Definition: bls.h:328
bool operator!=(const C &r) const
Definition: bls.h:89
void AggregateInsecure(const CBLSSecretKey &o)
Definition: bls.cpp:74
void Serialize(Stream &s) const
Definition: bls.h:370
std::vector< CBLSSecretKey > BLSSecretKeyVector
Definition: bls.h:467
CBLSId()
Definition: bls.h:225
static CBLSId FromHash(const uint256 &hash)
Definition: bls.cpp:51
void MakeNewKey()
Definition: bls.cpp:102
bool IsNull() const
Definition: uint256.h:33
bool VerifyInsecureAggregated(const std::vector< CBLSPublicKey > &pubKeys, const std::vector< uint256 > &hashes) const
Definition: bls.cpp:348
bool operator==(const CBLSLazyWrapper &r) const
Definition: bls.h:422
void SetBuf(const T &buf)
Definition: bls.h:135
std::vector< CBLSSignature > BLSSignatureVector
Definition: bls.h:468
uint256 hash
Definition: bls.h:330
void GetBuf(void *buf, size_t size) const
Definition: bls.h:122
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object&#39;s serialization.
Definition: hash.h:254
Definition: bls.h:218
CBLSLazyWrapper()
Definition: bls.h:333
void SetHash(const uint256 &hash)
Definition: bls.cpp:37
std::shared_ptr< BLSVerificationVector > BLSVerificationVectorPtr
Definition: bls.h:471
void Unserialize(Stream &s)
Definition: bls.h:385
std::vector< CBLSId > BLSIdVector
Definition: bls.h:464
static const size_t SerSize
Definition: bls.h:51
CBLSSignature()
Definition: bls.h:295
bool fValid
Definition: bls.h:42
void Serialize(CSizeComputer &s) const
Definition: bls.h:173
constexpr size_t GetSerSize() const
Definition: bls.h:45
std::string ToString() const
Definition: bls.h:210
std::shared_ptr< BLSSignatureVector > BLSSignatureVectorPtr
Definition: bls.h:474
void Unserialize(Stream &s, bool checkMalleable=true)
Definition: bls.h:186
char buf[BLSObject::SerSize]
Definition: bls.h:324
const BLSObject & Get() const
Definition: bls.h:402
bool IsHex(const std::string &str)
std::shared_ptr< BLSSecretKeyVector > BLSSecretKeyVectorPtr
Definition: bls.h:473
CBLSSecretKey()
Definition: bls.h:245
void UpdateHash() const
Definition: bls.h:452
CBLSLazyWrapper< CBLSPublicKey > CBLSLazyPublicKey
Definition: bls.h:460
void Set(const BLSObject &_obj)
Definition: bls.h:394
bool InternalSetBuf(const void *buf)
Definition: bls.cpp:261
ImplType impl
Definition: bls.h:41
CBLSWrapper()
Definition: bls.h:53
uint256 GetHash()
Definition: hash.h:203
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1215
void Serialize(Stream &s) const
Definition: bls.h:179
CBLSLazyWrapper(const CBLSLazyWrapper &r)
Definition: bls.h:340
256-bit opaque blob.
Definition: uint256.h:123
void SetInt(int x)
Definition: bls.cpp:30
bool PublicKeyShare(const std::vector< CBLSPublicKey > &mpk, const CBLSId &id)
Definition: bls.cpp:218
bool InternalSetBuf(const void *buf)
Definition: bls.cpp:18
bool DHKeyExchange(const CBLSSecretKey &sk, const CBLSPublicKey &pk)
Definition: bls.cpp:247
void AggregateInsecure(const CBLSPublicKey &o)
Definition: bls.cpp:191
void AggregateInsecure(const CBLSSignature &o)
Definition: bls.cpp:277
void * memcpy(void *a, const void *b, size_t c)
std::mutex mutex
Definition: bls.h:322
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:14
bool bufValid
Definition: bls.h:325
bool operator!=(const CBLSLazyWrapper &r) const
Definition: bls.h:433
CBLSPublicKey GetPublicKey() const
Definition: bls.cpp:147
std::shared_ptr< BLSIdVector > BLSIdVectorPtr
Definition: bls.h:470
bool InternalGetBuf(void *buf) const
Definition: bls.cpp:68
bool InternalSetBuf(const void *buf)
Definition: bls.cpp:58
void Serialize(CSizeComputer &s) const
Definition: bls.h:364
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:184
bool InternalGetBuf(void *buf) const
Definition: bls.cpp:24
bool Recover(const std::vector< CBLSSignature > &sigs, const std::vector< CBLSId > &ids)
Definition: bls.cpp:393
bool InternalGetBuf(void *buf) const
Definition: bls.cpp:271
uint256 cachedHash
Definition: bls.h:43
void Reset()
Definition: bls.h:117
bool operator==(const C &r) const
Definition: bls.h:85
void UpdateHash() const
Definition: bls.h:152
bool IsValid() const
Definition: bls.h:94
bool VerifySecureAggregated(const std::vector< CBLSPublicKey > &pks, const uint256 &hash) const
Definition: bls.cpp:375
CBLSWrapper(CBLSWrapper &&ref)
Definition: bls.h:71
CBLSPublicKey()
Definition: bls.h:273
CBLSSignature Sign(const uint256 &hash) const
Definition: bls.cpp:160
std::vector< unsigned char > ParseHex(const char *psz)
std::shared_ptr< BLSPublicKeyVector > BLSPublicKeyVectorPtr
Definition: bls.h:472
CBLSLazyWrapper< CBLSSignature > CBLSLazySignature
Definition: bls.h:459
Released under the MIT license