diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index fe969415b4..96da1f55e1 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -1373,9 +1373,11 @@ impl<'a> Extension<'a> { fn verify_kernel_signatures(&self, status: &dyn TxHashsetWriteStatus) -> Result<(), Error> { let now = Instant::now(); + const KERNEL_BATCH_SIZE: usize = 5_000; let mut kern_count = 0; let total_kernels = pmmr::n_leaves(self.kernel_pmmr.unpruned_size()); + let mut tx_kernels: Vec = Vec::with_capacity(KERNEL_BATCH_SIZE); for n in 1..self.kernel_pmmr.unpruned_size() + 1 { if pmmr::is_leaf(n) { let kernel = self @@ -1383,18 +1385,18 @@ impl<'a> Extension<'a> { .get_data(n) .ok_or::(ErrorKind::TxKernelNotFound.into())?; - kernel.verify()?; - kern_count += 1; + tx_kernels.push(kernel.kernel); + } - if kern_count % 20 == 0 { - status.on_validation(kern_count, total_kernels, 0, 0); - } - if kern_count % 1_000 == 0 { - debug!( - "txhashset: verify_kernel_signatures: verified {} signatures", - kern_count, - ); - } + if tx_kernels.len() >= KERNEL_BATCH_SIZE || n >= self.kernel_pmmr.unpruned_size() { + TxKernel::batch_sig_verify(&tx_kernels)?; + kern_count += tx_kernels.len() as u64; + tx_kernels.clear(); + status.on_validation(kern_count, total_kernels, 0, 0); + debug!( + "txhashset: verify_kernel_signatures: verified {} signatures", + kern_count, + ); } } @@ -1411,8 +1413,8 @@ impl<'a> Extension<'a> { fn verify_rangeproofs(&self, status: &dyn TxHashsetWriteStatus) -> Result<(), Error> { let now = Instant::now(); - let mut commits: Vec = vec![]; - let mut proofs: Vec = vec![]; + let mut commits: Vec = Vec::with_capacity(1_000); + let mut proofs: Vec = Vec::with_capacity(1_000); let mut proof_count = 0; let total_rproofs = pmmr::n_leaves(self.output_pmmr.unpruned_size()); @@ -1443,7 +1445,7 @@ impl<'a> Extension<'a> { ); } - if proof_count % 20 == 0 { + if proof_count % 1_000 == 0 { status.on_validation(0, 0, proof_count, total_rproofs); } } diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 426ed76d25..bfcf961a50 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -391,6 +391,29 @@ impl TxKernel { Ok(()) } + /// Batch signature verification. + pub fn batch_sig_verify(tx_kernels: &Vec) -> Result<(), Error> { + let len = tx_kernels.len(); + let mut sigs: Vec = Vec::with_capacity(len); + let mut pubkeys: Vec = Vec::with_capacity(len); + let mut msgs: Vec = Vec::with_capacity(len); + + let secp = static_secp_instance(); + let secp = secp.lock(); + + for tx_kernel in tx_kernels { + sigs.push(tx_kernel.excess_sig); + pubkeys.push(tx_kernel.excess.to_pubkey(&secp)?); + msgs.push(tx_kernel.msg_to_sign()?); + } + + if !secp::aggsig::verify_batch(&secp, &sigs, &msgs, &pubkeys) { + return Err(Error::IncorrectSignature); + } + + Ok(()) + } + /// Build an empty tx kernel with zero values. pub fn empty() -> TxKernel { TxKernel { @@ -861,11 +884,7 @@ impl TransactionBody { }; // Verify the unverified tx kernels. - // No ability to batch verify these right now - // so just do them individually. - for x in &kernels { - x.verify()?; - } + TxKernel::batch_sig_verify(&kernels)?; // Cache the successful verification results for the new outputs and kernels. {