diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9121278ad7815e..444488783642b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -274,6 +274,7 @@ add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL rpc/signmessage.cpp rpc/txoutproof.cpp script/sigcache.cpp + script/batchsigcache.cpp signet.cpp torcontrol.cpp txdb.cpp diff --git a/src/batchverify.cpp b/src/batchverify.cpp index 1f9d749b516336..55284ef6682667 100644 --- a/src/batchverify.cpp +++ b/src/batchverify.cpp @@ -29,6 +29,8 @@ BatchSchnorrVerifier::BatchSchnorrVerifier() { const size_t max_batch_size{106}; secp256k1_batch* batch{secp256k1_batch_create(secp256k1_context_static, max_batch_size, rnd)}; m_batch = new Batch(batch); + m_callbacks.reserve(max_batch_size); + m_batch_size = max_batch_size; } BatchSchnorrVerifier::~BatchSchnorrVerifier() { @@ -38,7 +40,15 @@ BatchSchnorrVerifier::~BatchSchnorrVerifier() { } } -bool BatchSchnorrVerifier::Add(const Span sig, const XOnlyPubKey& pubkey, const uint256& sighash) { +void BatchSchnorrVerifier::ExecuteCallbacks() { + AssertLockHeld(m_batch_mutex); + for (size_t i = 0; i < m_callbacks.size(); i++) { + m_callbacks[i](); + } + m_callbacks.clear(); +} + +bool BatchSchnorrVerifier::Add(const Span sig, const XOnlyPubKey& pubkey, const uint256& sighash, SigCacheCallback callback) { LOCK(m_batch_mutex); if (secp256k1_batch_usable(secp256k1_context_static, m_batch->get()) == 0) { LogPrintf("ERROR: BatchSchnorrVerifier m_batch unusable\n"); @@ -47,10 +57,25 @@ bool BatchSchnorrVerifier::Add(const Span sig, const XOnlyP secp256k1_xonly_pubkey pubkey_parsed; if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey_parsed, pubkey.data())) return false; - return secp256k1_batch_add_schnorrsig(secp256k1_context_static, m_batch->get(), sig.data(), sighash.begin(), 32, &pubkey_parsed); + if (secp256k1_batch_add_schnorrsig(secp256k1_context_static, m_batch->get(), sig.data(), sighash.begin(), 32, &pubkey_parsed)) { + if (m_callbacks.size() == m_batch_size) { + // Batch was verified and cleared, cache now + ExecuteCallbacks(); + } else { + m_callbacks.push_back(callback); + } + return true; + } + + return false; } bool BatchSchnorrVerifier::Verify() { LOCK(m_batch_mutex); - return secp256k1_batch_verify(secp256k1_context_static, m_batch->get()); + if (secp256k1_batch_verify(secp256k1_context_static, m_batch->get())) { + // cache sigs + ExecuteCallbacks(); + return true; + } + return false; } diff --git a/src/batchverify.h b/src/batchverify.h index 77d3f3d982cb86..b307e64b19498f 100644 --- a/src/batchverify.h +++ b/src/batchverify.h @@ -6,19 +6,39 @@ #define BITCOIN_BATCHVERIFY_H #include +#include