PIVX Core  5.6.99
P2P Digital Currency
bls.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 The Dash Core developers
2 // Copyright (c) 2021 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "bench.h"
7 #include "random.h"
8 #include "bls/bls_worker.h"
9 #include "utiltime.h"
10 
11 #include <iostream>
12 
14 
16 {
17  blsWorker.Start();
18 }
19 
21 {
22  blsWorker.Stop();
23 }
24 
25 static void BuildTestVectors(size_t count, size_t invalidCount,
27  std::vector<uint256>& msgHashes,
28  std::vector<bool>& invalid)
29 {
30  secKeys.resize(count);
31  pubKeys.resize(count);
32  sigs.resize(count);
33  msgHashes.resize(count);
34 
35  invalid.resize(count);
36  for (size_t i = 0; i < invalidCount; i++) {
37  invalid[i] = true;
38  }
39  Shuffle(invalid.begin(), invalid.end(), FastRandomContext());
40 
41  for (size_t i = 0; i < count; i++) {
42  secKeys[i].MakeNewKey();
43  pubKeys[i] = secKeys[i].GetPublicKey();
44  msgHashes[i] = GetRandHash();
45  sigs[i] = secKeys[i].Sign(msgHashes[i]);
46 
47  if (invalid[i]) {
48  CBLSSecretKey s;
49  s.MakeNewKey();
50  sigs[i] = s.Sign(msgHashes[i]);
51  }
52  }
53 }
54 
55 static void BLSPubKeyAggregate_Normal(benchmark::State& state)
56 {
57  CBLSSecretKey secKey1, secKey2;
58  secKey1.MakeNewKey();
59  secKey2.MakeNewKey();
60  CBLSPublicKey pubKey1 = secKey1.GetPublicKey();
61  CBLSPublicKey pubKey2 = secKey2.GetPublicKey();
62 
63  // Benchmark.
64  while (state.KeepRunning()) {
65  CBLSPublicKey k(pubKey1);
66  k.AggregateInsecure(pubKey2);
67  }
68 }
69 
70 static void BLSSecKeyAggregate_Normal(benchmark::State& state)
71 {
72  CBLSSecretKey secKey1, secKey2;
73  secKey1.MakeNewKey();
74  secKey2.MakeNewKey();
75 
76  // Benchmark.
77  while (state.KeepRunning()) {
78  CBLSSecretKey k(secKey1);
79  k.AggregateInsecure(secKey2);
80  }
81 }
82 
83 static void BLSSign_Normal(benchmark::State& state)
84 {
85  CBLSSecretKey secKey;
86  secKey.MakeNewKey();
87 
88  // Benchmark.
89  while (state.KeepRunning()) {
90  uint256 hash = GetRandHash();
91  secKey.Sign(hash);
92  }
93 }
94 
95 static void BLSVerify_Normal(benchmark::State& state)
96 {
97  BLSPublicKeyVector pubKeys;
98  BLSSecretKeyVector secKeys;
99  BLSSignatureVector sigs;
100  std::vector<uint256> msgHashes;
101  std::vector<bool> invalid;
102  BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
103 
104  // Benchmark.
105  size_t i = 0;
106  while (state.KeepRunning()) {
107  bool valid = sigs[i].VerifyInsecure(pubKeys[i], msgHashes[i]);
108  if (valid && invalid[i]) {
109  std::cout << "expected invalid but it is valid" << std::endl;
110  assert(false);
111  } else if (!valid && !invalid[i]) {
112  std::cout << "expected valid but it is invalid" << std::endl;
113  assert(false);
114  }
115  i = (i + 1) % pubKeys.size();
116  }
117 }
118 
119 
120 static void BLSVerify_LargeBlock(size_t txCount, benchmark::State& state)
121 {
122  BLSPublicKeyVector pubKeys;
123  BLSSecretKeyVector secKeys;
124  BLSSignatureVector sigs;
125  std::vector<uint256> msgHashes;
126  std::vector<bool> invalid;
127  BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
128 
129  // Benchmark.
130  while (state.KeepRunning()) {
131  for (size_t i = 0; i < pubKeys.size(); i++) {
132  sigs[i].VerifyInsecure(pubKeys[i], msgHashes[i]);
133  }
134  }
135 }
136 
137 static void BLSVerify_LargeBlock1000(benchmark::State& state)
138 {
139  BLSVerify_LargeBlock(1000, state);
140 }
141 
142 static void BLSVerify_LargeBlock10000(benchmark::State& state)
143 {
144  BLSVerify_LargeBlock(10000, state);
145 }
146 
147 static void BLSVerify_LargeBlockSelfAggregated(size_t txCount, benchmark::State& state)
148 {
149  BLSPublicKeyVector pubKeys;
150  BLSSecretKeyVector secKeys;
151  BLSSignatureVector sigs;
152  std::vector<uint256> msgHashes;
153  std::vector<bool> invalid;
154  BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
155 
156  // Benchmark.
157  while (state.KeepRunning()) {
159  aggSig.VerifyInsecureAggregated(pubKeys, msgHashes);
160  }
161 }
162 
163 static void BLSVerify_LargeBlockSelfAggregated1000(benchmark::State& state)
164 {
165  BLSVerify_LargeBlockSelfAggregated(1000, state);
166 }
167 
168 static void BLSVerify_LargeBlockSelfAggregated10000(benchmark::State& state)
169 {
170  BLSVerify_LargeBlockSelfAggregated(10000, state);
171 }
172 
173 static void BLSVerify_LargeAggregatedBlock(size_t txCount, benchmark::State& state)
174 {
175  BLSPublicKeyVector pubKeys;
176  BLSSecretKeyVector secKeys;
177  BLSSignatureVector sigs;
178  std::vector<uint256> msgHashes;
179  std::vector<bool> invalid;
180  BuildTestVectors(txCount, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
181 
183 
184  // Benchmark.
185  while (state.KeepRunning()) {
186  aggSig.VerifyInsecureAggregated(pubKeys, msgHashes);
187  }
188 }
189 
190 static void BLSVerify_LargeAggregatedBlock1000(benchmark::State& state)
191 {
192  BLSVerify_LargeAggregatedBlock(1000, state);
193 }
194 
195 static void BLSVerify_LargeAggregatedBlock10000(benchmark::State& state)
196 {
197  BLSVerify_LargeAggregatedBlock(10000, state);
198 }
199 
200 static void BLSVerify_LargeAggregatedBlock1000PreVerified(benchmark::State& state)
201 {
202  BLSPublicKeyVector pubKeys;
203  BLSSecretKeyVector secKeys;
204  BLSSignatureVector sigs;
205  std::vector<uint256> msgHashes;
206  std::vector<bool> invalid;
207  BuildTestVectors(1000, 0, pubKeys, secKeys, sigs, msgHashes, invalid);
208 
210 
211  std::set<size_t> prevalidated;
212 
213  while (prevalidated.size() < 900) {
214  int idx = GetRandInt((int)pubKeys.size());
215  if (prevalidated.count((size_t)idx)) {
216  continue;
217  }
218  prevalidated.emplace((size_t)idx);
219  }
220 
221  // Benchmark.
222  while (state.KeepRunning()) {
223  BLSPublicKeyVector nonvalidatedPubKeys;
224  std::vector<uint256> nonvalidatedHashes;
225  nonvalidatedPubKeys.reserve(pubKeys.size());
226  nonvalidatedHashes.reserve(msgHashes.size());
227 
228  for (size_t i = 0; i < sigs.size(); i++) {
229  if (prevalidated.count(i)) {
230  continue;
231  }
232  nonvalidatedPubKeys.emplace_back(pubKeys[i]);
233  nonvalidatedHashes.emplace_back(msgHashes[i]);
234  }
235 
236  CBLSSignature aggSigCopy = aggSig;
237  for (auto idx : prevalidated) {
238  aggSigCopy.SubInsecure(sigs[idx]);
239  }
240 
241  bool valid = aggSigCopy.VerifyInsecureAggregated(nonvalidatedPubKeys, nonvalidatedHashes);
242  assert(valid);
243  }
244 }
245 
246 static void BLSVerify_Batched(benchmark::State& state)
247 {
248  BLSPublicKeyVector pubKeys;
249  BLSSecretKeyVector secKeys;
250  BLSSignatureVector sigs;
251  std::vector<uint256> msgHashes;
252  std::vector<bool> invalid;
253  BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
254 
255  // Benchmark.
256  size_t i = 0;
257  size_t j = 0;
258  size_t batchSize = 16;
259  while (state.KeepRunning()) {
260  j++;
261  if ((j % batchSize) != 0) {
262  continue;
263  }
264 
265  BLSPublicKeyVector testPubKeys;
266  BLSSignatureVector testSigs;
267  std::vector<uint256> testMsgHashes;
268  testPubKeys.reserve(batchSize);
269  testSigs.reserve(batchSize);
270  testMsgHashes.reserve(batchSize);
271  size_t startI = i;
272  for (size_t k = 0; k < batchSize; k++) {
273  testPubKeys.emplace_back(pubKeys[i]);
274  testSigs.emplace_back(sigs[i]);
275  testMsgHashes.emplace_back(msgHashes[i]);
276  i = (i + 1) % pubKeys.size();
277  }
278 
279  CBLSSignature batchSig = CBLSSignature::AggregateInsecure(testSigs);
280  bool batchValid = batchSig.VerifyInsecureAggregated(testPubKeys, testMsgHashes);
281  std::vector<bool> valid;
282  if (batchValid) {
283  valid.assign(batchSize, true);
284  } else {
285  for (size_t k = 0; k < batchSize; k++) {
286  bool valid1 = testSigs[k].VerifyInsecure(testPubKeys[k], testMsgHashes[k]);
287  valid.emplace_back(valid1);
288  }
289  }
290  for (size_t k = 0; k < batchSize; k++) {
291  if (valid[k] && invalid[(startI + k) % pubKeys.size()]) {
292  std::cout << "expected invalid but it is valid" << std::endl;
293  assert(false);
294  } else if (!valid[k] && !invalid[(startI + k) % pubKeys.size()]) {
295  std::cout << "expected valid but it is invalid" << std::endl;
296  assert(false);
297  }
298  }
299  }
300 }
301 
302 static void BLSVerify_BatchedParallel(benchmark::State& state)
303 {
304  BLSPublicKeyVector pubKeys;
305  BLSSecretKeyVector secKeys;
306  BLSSignatureVector sigs;
307  std::vector<uint256> msgHashes;
308  std::vector<bool> invalid;
309  BuildTestVectors(1000, 10, pubKeys, secKeys, sigs, msgHashes, invalid);
310 
311  std::list<std::pair<size_t, std::future<bool>>> futures;
312 
313  volatile bool cancel = false;
314  auto cancelCond = [&]() {
315  return cancel;
316  };
317 
318  // Benchmark.
319  size_t i = 0;
320  while (state.KeepRunning()) {
321  if (futures.size() < 100) {
322  while (futures.size() < 10000) {
323  auto f = blsWorker.AsyncVerifySig(sigs[i], pubKeys[i], msgHashes[i], cancelCond);
324  futures.emplace_back(std::make_pair(i, std::move(f)));
325  i = (i + 1) % pubKeys.size();
326  }
327  }
328 
329  auto fp = std::move(futures.front());
330  futures.pop_front();
331 
332  size_t j = fp.first;
333  bool valid = fp.second.get();
334 
335  if (valid && invalid[j]) {
336  std::cout << "expected invalid but it is valid" << std::endl;
337  assert(false);
338  } else if (!valid && !invalid[j]) {
339  std::cout << "expected valid but it is invalid" << std::endl;
340  assert(false);
341  }
342  }
343  cancel = true;
345  MilliSleep(100);
346  }
347 }
348 
349 BENCHMARK(BLSPubKeyAggregate_Normal, 700 * 1000)
350 BENCHMARK(BLSSecKeyAggregate_Normal, 1300 * 1000)
351 BENCHMARK(BLSSign_Normal, 600)
352 BENCHMARK(BLSVerify_Normal, 350)
353 BENCHMARK(BLSVerify_LargeBlock1000, 1)
354 BENCHMARK(BLSVerify_LargeBlock10000, 1)
355 BENCHMARK(BLSVerify_LargeBlockSelfAggregated1000, 1)
356 BENCHMARK(BLSVerify_LargeBlockSelfAggregated10000, 1)
357 BENCHMARK(BLSVerify_LargeAggregatedBlock1000, 1)
358 BENCHMARK(BLSVerify_LargeAggregatedBlock10000, 1)
359 BENCHMARK(BLSVerify_LargeAggregatedBlock1000PreVerified, 7)
360 BENCHMARK(BLSVerify_Batched, 500)
361 BENCHMARK(BLSVerify_BatchedParallel, 1000)
#define BENCHMARK(n, num_iters_for_one_second)
Definition: bench.h:138
void InitBLSTests()
Definition: bls.cpp:15
CBLSWorker blsWorker
Definition: bls.cpp:13
void CleanupBLSTests()
Definition: bls.cpp:20
std::vector< CBLSPublicKey > BLSPublicKeyVector
Definition: bls_wrapper.h:410
std::vector< CBLSSecretKey > BLSSecretKeyVector
Definition: bls_wrapper.h:411
std::vector< CBLSSignature > BLSSignatureVector
Definition: bls_wrapper.h:412
void MakeNewKey()
Definition: bls_wrapper.cpp:54
CBLSPublicKey GetPublicKey() const
Definition: bls_wrapper.cpp:99
CBLSSignature Sign(const uint256 &hash) const
void AggregateInsecure(const CBLSSignature &o)
void SubInsecure(const CBLSSignature &o)
bool VerifyInsecureAggregated(const std::vector< CBLSPublicKey > &pubKeys, const std::vector< uint256 > &hashes) const
bool IsAsyncVerifyInProgress()
Definition: bls_worker.cpp:883
void Start()
Definition: bls_worker.cpp:63
void Stop()
Definition: bls_worker.cpp:71
void AsyncVerifySig(const CBLSSignature &sig, const CBLSPublicKey &pubKey, const uint256 &msgHash, SigVerifyDoneCallback doneCallback, CancelCond cancelCond=[] { return false;})
Definition: bls_worker.cpp:846
Fast randomness source.
Definition: random.h:107
bool KeepRunning()
Definition: bench.h:69
256-bit opaque blob.
Definition: uint256.h:138
uint256 GetRandHash() noexcept
Definition: random.cpp:596
int GetRandInt(int nMax) noexcept
Definition: random.cpp:591
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:217
void MilliSleep(int64_t n)
Definition: utiltime.cpp:82