Skip to content

Instantly share code, notes, and snippets.

@jamesob
Created January 27, 2025 20:55
Show Gist options
  • Save jamesob/50b60bdaab5734fff6c766187c44b52e to your computer and use it in GitHub Desktop.
Save jamesob/50b60bdaab5734fff6c766187c44b52e to your computer and use it in GitHub Desktop.
#include <iostream>
#include <format>
#include <cstring>
#include <vector>
#include <thread>
#include <random>
#include <chrono>
#include <secp256k1.h>
constexpr size_t NUM_KEYS = 6'500'000;
constexpr size_t NUM_THREADS = 30;
void generate_keys(std::vector<std::vector<unsigned char>>& keys, size_t start, size_t end) {
std::random_device rd;
std::mt19937_64 gen(rd()); // 64-bit generator
std::uniform_int_distribution<uint64_t> dist(0, UINT64_MAX);
for (size_t i = start; i < end; ++i) {
std::vector<unsigned char> key(32);
for (size_t j = 0; j < 4; ++j) { // Generate 4 blocks of 64 bits (8 bytes each)
uint64_t rand_block = dist(gen);
std::memcpy(key.data() + j * 8, &rand_block, 8);
}
keys[i] = std::move(key);
if (i % 10'000 == 0) {
std::cout << "Generated " << i << " keys" << std::endl;
}
}
}
void benchmark_sign(
const std::vector<std::vector<unsigned char>>& keys, size_t thread_id, size_t& sign_count) {
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
unsigned char msg[32] = {0};
unsigned char sig[64];
size_t count = 0;
size_t keys_per_thread = NUM_KEYS / NUM_THREADS;
size_t start = thread_id * keys_per_thread;
size_t end = (thread_id + 1) * keys_per_thread;
for (size_t i = start; i < end; ++i) {
secp256k1_ecdsa_signature signature;
if (secp256k1_ecdsa_sign(ctx, &signature, msg, keys[i].data(), nullptr, nullptr)) {
++count;
}
if (count % 10'000 == 0) {
std::cout << std::format("signer thread {} signed {}\n", thread_id, count);
}
}
secp256k1_context_destroy(ctx);
sign_count = count;
}
int main() {
std::vector<std::vector<unsigned char>> keys(NUM_KEYS);
generate_keys(keys, 0, NUM_KEYS);
std::vector<std::thread> threads;
std::vector<size_t> sign_counts(NUM_THREADS, 0);
auto start_time = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < NUM_THREADS; ++i) {
threads.emplace_back(benchmark_sign, std::cref(keys), i, std::ref(sign_counts[i]));
}
for (auto& thread : threads) {
thread.join();
}
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
size_t total_signs = 0;
for (const auto& count : sign_counts) {
total_signs += count;
}
std::cout << "Total signatures: " << total_signs << "\n";
std::cout << "Time taken: " << duration.count() << " ms\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment