Skip to content

Commit

Permalink
Cache batch signature validation result
Browse files Browse the repository at this point in the history
Output of connectblock benchmark
|            ns/block |             block/s |    err% |       ins/block |       cyc/block |    IPC |      bra/block |   miss% |     total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|       17,564,741.00 |               56.93 |    0.3% |  151,320,406.00 |   59,021,590.00 |  2.564 |  14,493,808.00 |    0.6% |      0.29 | `ConnectBlock`
  • Loading branch information
Eunovo committed Nov 11, 2024
1 parent 8133306 commit 2ed7828
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 28 additions & 3 deletions src/batchverify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -38,7 +40,15 @@ BatchSchnorrVerifier::~BatchSchnorrVerifier() {
}
}

bool BatchSchnorrVerifier::Add(const Span<const unsigned char> 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<const unsigned char> 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");
Expand All @@ -47,10 +57,25 @@ bool BatchSchnorrVerifier::Add(const Span<const unsigned char> 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;
}
22 changes: 21 additions & 1 deletion src/batchverify.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,39 @@
#define BITCOIN_BATCHVERIFY_H

#include <pubkey.h>
#include <script/sigcache.h>
#include <sync.h>
#include <uint256.h>

#include <vector>

class SigCacheCallback {
private:
SignatureCache& m_signature_cache;
uint256 m_entry;

public:
SigCacheCallback(SignatureCache& cache, uint256 entry): m_signature_cache(cache), m_entry(entry) {}

void operator()() { m_signature_cache.Set(m_entry); }
};

class Batch;
class BatchSchnorrVerifier {
private:
Batch* m_batch GUARDED_BY(m_batch_mutex);
std::vector<SigCacheCallback> m_callbacks GUARDED_BY(m_batch_mutex);
mutable Mutex m_batch_mutex;

size_t m_batch_size;

void ExecuteCallbacks() EXCLUSIVE_LOCKS_REQUIRED(m_batch_mutex);

public:
BatchSchnorrVerifier();
~BatchSchnorrVerifier();

bool Add(const Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) EXCLUSIVE_LOCKS_REQUIRED(!m_batch_mutex);
bool Add(const Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash, SigCacheCallback callback) EXCLUSIVE_LOCKS_REQUIRED(!m_batch_mutex);
bool Verify() EXCLUSIVE_LOCKS_REQUIRED(!m_batch_mutex);
};

Expand Down
1 change: 1 addition & 0 deletions src/kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_library(bitcoinkernel
../script/script.cpp
../script/script_error.cpp
../script/sigcache.cpp
../script/batchsigcache.cpp
../script/solver.cpp
../signet.cpp
../streams.cpp
Expand Down
16 changes: 16 additions & 0 deletions src/script/batchsigcache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <batchverify.h>
#include <script/batchsigcache.h>

bool BatchingCachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
{
uint256 entry;
m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
if (m_signature_cache.Get(entry, !GetStore())) return true;
SigCacheCallback callback(m_signature_cache, entry);
return m_batch->Add(sig, pubkey, sighash, callback);
}
23 changes: 23 additions & 0 deletions src/script/batchsigcache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2024 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_SCRIPT_BATCHSIGCACHE_H
#define BITCOIN_SCRIPT_BATCHSIGCACHE_H

#include <batchverify.h>
#include <script/sigcache.h>

class BatchingCachingTransactionSignatureChecker : public CachingTransactionSignatureChecker
{
private:
BatchSchnorrVerifier* m_batch;

public:
BatchingCachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, bool storeIn, SignatureCache& signature_cache, PrecomputedTransactionData& txdataIn, BatchSchnorrVerifier* batchIn) : CachingTransactionSignatureChecker(txToIn, nInIn, amountIn, storeIn, signature_cache, txdataIn), m_batch(batchIn) {}

bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const override;
};


#endif // BITCOIN_SCRIPT_BATCHSIGCACHE_H
10 changes: 0 additions & 10 deletions src/script/sigcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <script/sigcache.h>

#include <crypto/sha256.h>
#include <batchverify.h>
#include <common/system.h>
#include <logging.h>
#include <pubkey.h>
Expand Down Expand Up @@ -84,12 +83,3 @@ bool CachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsig
if (store) m_signature_cache.Set(entry);
return true;
}

bool BatchingCachingTransactionSignatureChecker::VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const
{
uint256 entry;
m_signature_cache.ComputeEntrySchnorr(entry, sighash, sig, pubkey);
if (m_signature_cache.Get(entry, !GetStore())) return true;

return m_batch->Add(sig, pubkey, sighash);
}
12 changes: 0 additions & 12 deletions src/script/sigcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <consensus/amount.h>
#include <crypto/sha256.h>
#include <cuckoocache.h>
#include <batchverify.h>
#include <script/interpreter.h>
#include <span.h>
#include <uint256.h>
Expand Down Expand Up @@ -79,15 +78,4 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker

[[nodiscard]] bool InitSignatureCache(size_t max_size_bytes);

class BatchingCachingTransactionSignatureChecker : public CachingTransactionSignatureChecker
{
private:
BatchSchnorrVerifier* m_batch;

public:
BatchingCachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, bool storeIn, SignatureCache& signature_cache, PrecomputedTransactionData& txdataIn, BatchSchnorrVerifier* batchIn) : CachingTransactionSignatureChecker(txToIn, nInIn, amountIn, storeIn, signature_cache, txdataIn), m_batch(batchIn) {}

bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const override;
};

#endif // BITCOIN_SCRIPT_SIGCACHE_H
1 change: 1 addition & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <primitives/transaction.h>
#include <random.h>
#include <script/script.h>
#include <script/batchsigcache.h>
#include <script/sigcache.h>
#include <signet.h>
#include <tinyformat.h>
Expand Down

0 comments on commit 2ed7828

Please sign in to comment.