Skip to content

Commit

Permalink
schnorr signature batch verification (#2961)
Browse files Browse the repository at this point in the history
* schnorr signature batch verification

* Split the fee and lock_height verification out from the batch signature verification

* Remove the new added fee_height_verify to comply with #2859

* fix: the last n could not be leaf?
  • Loading branch information
garyyu authored and antiochp committed Sep 3, 2019
1 parent 2cebdc5 commit 928279a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 19 deletions.
30 changes: 16 additions & 14 deletions chain/src/txhashset/txhashset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1373,28 +1373,30 @@ 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<TxKernel> = Vec::with_capacity(KERNEL_BATCH_SIZE);
for n in 1..self.kernel_pmmr.unpruned_size() + 1 {
if pmmr::is_leaf(n) {
let kernel = self
.kernel_pmmr
.get_data(n)
.ok_or::<Error>(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,
);
}
}

Expand All @@ -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<Commitment> = vec![];
let mut proofs: Vec<RangeProof> = vec![];
let mut commits: Vec<Commitment> = Vec::with_capacity(1_000);
let mut proofs: Vec<RangeProof> = Vec::with_capacity(1_000);

let mut proof_count = 0;
let total_rproofs = pmmr::n_leaves(self.output_pmmr.unpruned_size());
Expand Down Expand Up @@ -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);
}
}
Expand Down
29 changes: 24 additions & 5 deletions core/src/core/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,29 @@ impl TxKernel {
Ok(())
}

/// Batch signature verification.
pub fn batch_sig_verify(tx_kernels: &Vec<TxKernel>) -> Result<(), Error> {
let len = tx_kernels.len();
let mut sigs: Vec<secp::Signature> = Vec::with_capacity(len);
let mut pubkeys: Vec<secp::key::PublicKey> = Vec::with_capacity(len);
let mut msgs: Vec<secp::Message> = 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 {
Expand Down Expand Up @@ -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.
{
Expand Down

0 comments on commit 928279a

Please sign in to comment.