@@ -48,6 +48,16 @@ class CCheckQueue
48
48
49
49
BatchSchnorrVerifier m_batch;
50
50
51
+ static constexpr size_t SIGNATURE_BUCKETS = 15 ; // Same as MAX_SCRIPTCHECK_THREADS
52
+ std::array<std::vector<SchnorrSignatureToVerify>, SIGNATURE_BUCKETS + 1 /* Add one for master thread */ > m_signature_buckets;
53
+
54
+ void AddSignaturesToBucket (const std::vector<SchnorrSignatureToVerify>& signatures, size_t thread_idx) {
55
+ assert (thread_idx >= 0 && thread_idx < m_signature_buckets.size ());
56
+
57
+ auto & bucket = m_signature_buckets[thread_idx];
58
+ bucket.insert (bucket.end (), signatures.begin (), signatures.end ());
59
+ }
60
+
51
61
// ! Mutex to protect the inner state
52
62
Mutex m_mutex;
53
63
@@ -84,7 +94,7 @@ class CCheckQueue
84
94
bool m_request_stop GUARDED_BY (m_mutex){false };
85
95
86
96
/* * Internal function that does bulk of the verification work. If fMaster, return the final result. */
87
- std::optional<R> Loop (bool fMaster ) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
97
+ std::optional<R> Loop (bool fMaster , size_t thread_idx ) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
88
98
{
89
99
std::condition_variable& cond = fMaster ? m_master_cv : m_worker_cv;
90
100
std::vector<T> vChecks;
@@ -114,6 +124,12 @@ class CCheckQueue
114
124
if (fMaster && nTodo == 0 ) {
115
125
// All checks are done; master performs batch verification
116
126
if constexpr (std::is_same_v<R, ScriptFailureResult>) {
127
+ for (auto & bucket : m_signature_buckets) {
128
+ for (const auto & sig : bucket) {
129
+ m_batch.Add (sig.sig , sig.pubkey , sig.sighash );
130
+ }
131
+ bucket.clear ();
132
+ }
117
133
if (!m_batch.Verify ()) {
118
134
m_result = ScriptFailureResult (SCRIPT_ERR_BATCH_VALIDATION_FAILED, " Schnorr batch validation failed" );
119
135
}
@@ -159,9 +175,7 @@ class CCheckQueue
159
175
}
160
176
// Check succeeded; add signatures to shared batch
161
177
const auto & signatures = std::get<std::vector<SchnorrSignatureToVerify>>(check_result);
162
- for (const auto & sig : signatures) {
163
- m_batch.Add (sig.sig , sig.pubkey , sig.sighash );
164
- }
178
+ AddSignaturesToBucket (signatures, thread_idx);
165
179
} else {
166
180
local_result = check_result;
167
181
if (local_result.has_value ()) break ;
@@ -185,7 +199,7 @@ class CCheckQueue
185
199
for (int n = 0 ; n < worker_threads_num; ++n) {
186
200
m_worker_threads.emplace_back ([this , n]() {
187
201
util::ThreadRename (strprintf (" scriptch.%i" , n));
188
- Loop (false /* worker thread */ );
202
+ Loop (false /* worker thread */ , n /* index */ );
189
203
});
190
204
}
191
205
}
@@ -201,7 +215,7 @@ class CCheckQueue
201
215
// ! its error.
202
216
std::optional<R> Complete () EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
203
217
{
204
- return Loop (true /* master thread */ );
218
+ return Loop (true /* master thread */ , SIGNATURE_BUCKETS /* take the last bucket */ );
205
219
}
206
220
207
221
// ! Add a batch of checks to the queue
0 commit comments