mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
use the static secp instance everywhere (except the wallet) (#250)
This commit is contained in:
parent
a0c0d6f382
commit
c1656f7660
10 changed files with 102 additions and 78 deletions
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use util::secp;
|
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
use core::consensus;
|
use core::consensus;
|
||||||
|
@ -209,8 +208,7 @@ fn validate_block(
|
||||||
}
|
}
|
||||||
|
|
||||||
// main isolated block validation, checks all commitment sums and sigs
|
// main isolated block validation, checks all commitment sums and sigs
|
||||||
let curve = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
try!(b.validate().map_err(&Error::InvalidBlockProof));
|
||||||
try!(b.validate(&curve).map_err(&Error::InvalidBlockProof));
|
|
||||||
|
|
||||||
// apply the new block to the MMR trees and check the new root hashes
|
// apply the new block to the MMR trees and check the new root hashes
|
||||||
if b.header.previous == ctx.head.last_block_h {
|
if b.header.previous == ctx.head.last_block_h {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
use time;
|
use time;
|
||||||
use util;
|
use util;
|
||||||
use util::secp::{self, Secp256k1};
|
use util::{secp, static_secp_instance};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use core::Committed;
|
use core::Committed;
|
||||||
|
@ -299,8 +299,6 @@ impl Block {
|
||||||
reward_out: Output,
|
reward_out: Output,
|
||||||
reward_kern: TxKernel,
|
reward_kern: TxKernel,
|
||||||
) -> Result<Block, Error> {
|
) -> Result<Block, Error> {
|
||||||
let secp = Secp256k1::with_caps(secp::ContextFlag::Commit);
|
|
||||||
|
|
||||||
let mut kernels = vec![];
|
let mut kernels = vec![];
|
||||||
let mut inputs = vec![];
|
let mut inputs = vec![];
|
||||||
let mut outputs = vec![];
|
let mut outputs = vec![];
|
||||||
|
@ -311,7 +309,7 @@ impl Block {
|
||||||
// to build the block (which we can sort of think of as one big tx?)
|
// to build the block (which we can sort of think of as one big tx?)
|
||||||
for tx in txs {
|
for tx in txs {
|
||||||
// validate each transaction and gather their kernels
|
// validate each transaction and gather their kernels
|
||||||
let excess = tx.validate(&secp)?;
|
let excess = tx.validate()?;
|
||||||
let kernel = tx.build_kernel(excess);
|
let kernel = tx.build_kernel(excess);
|
||||||
kernels.push(kernel);
|
kernels.push(kernel);
|
||||||
|
|
||||||
|
@ -333,7 +331,7 @@ impl Block {
|
||||||
outputs.sort();
|
outputs.sort();
|
||||||
kernels.sort();
|
kernels.sort();
|
||||||
|
|
||||||
// calculate the overall Merkle tree and fees
|
// calculate the overall Merkle tree and fees (todo?)
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
Block {
|
Block {
|
||||||
|
@ -447,19 +445,19 @@ impl Block {
|
||||||
///
|
///
|
||||||
/// TODO - performs various verification steps - discuss renaming this to "verify"
|
/// TODO - performs various verification steps - discuss renaming this to "verify"
|
||||||
///
|
///
|
||||||
pub fn validate(&self, secp: &Secp256k1) -> Result<(), Error> {
|
pub fn validate(&self) -> Result<(), Error> {
|
||||||
if exceeds_weight(self.inputs.len(), self.outputs.len(), self.kernels.len()) {
|
if exceeds_weight(self.inputs.len(), self.outputs.len(), self.kernels.len()) {
|
||||||
return Err(Error::WeightExceeded);
|
return Err(Error::WeightExceeded);
|
||||||
}
|
}
|
||||||
self.verify_coinbase(secp)?;
|
self.verify_coinbase()?;
|
||||||
self.verify_kernels(secp, false)?;
|
self.verify_kernels(false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies the sum of input/output commitments match the sum in kernels
|
/// Verifies the sum of input/output commitments match the sum in kernels
|
||||||
/// and that all kernel signatures are valid.
|
/// and that all kernel signatures are valid.
|
||||||
/// TODO - when would we skip_sig? Is this needed or used anywhere?
|
/// TODO - when would we skip_sig? Is this needed or used anywhere?
|
||||||
fn verify_kernels(&self, secp: &Secp256k1, skip_sig: bool) -> Result<(), Error> {
|
fn verify_kernels(&self, skip_sig: bool) -> Result<(), Error> {
|
||||||
for k in &self.kernels {
|
for k in &self.kernels {
|
||||||
if k.fee & 1 != 0 {
|
if k.fee & 1 != 0 {
|
||||||
return Err(Error::OddKernelFee);
|
return Err(Error::OddKernelFee);
|
||||||
|
@ -471,11 +469,16 @@ impl Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sum all inputs and outs commitments
|
// sum all inputs and outs commitments
|
||||||
let io_sum = self.sum_commitments(secp)?;
|
let io_sum = self.sum_commitments()?;
|
||||||
|
|
||||||
// sum all kernels commitments
|
// sum all kernels commitments
|
||||||
let proof_commits = map_vec!(self.kernels, |proof| proof.excess);
|
let proof_commits = map_vec!(self.kernels, |proof| proof.excess);
|
||||||
let proof_sum = secp.commit_sum(proof_commits, vec![])?;
|
|
||||||
|
let proof_sum = {
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
secp.commit_sum(proof_commits, vec![])?
|
||||||
|
};
|
||||||
|
|
||||||
// both should be the same
|
// both should be the same
|
||||||
if proof_sum != io_sum {
|
if proof_sum != io_sum {
|
||||||
|
@ -485,7 +488,7 @@ impl Block {
|
||||||
// verify all signatures with the commitment as pk
|
// verify all signatures with the commitment as pk
|
||||||
if !skip_sig {
|
if !skip_sig {
|
||||||
for proof in &self.kernels {
|
for proof in &self.kernels {
|
||||||
proof.verify(secp)?;
|
proof.verify()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -496,7 +499,7 @@ impl Block {
|
||||||
// * That the sum of all coinbase-marked outputs equal the supply.
|
// * That the sum of all coinbase-marked outputs equal the supply.
|
||||||
// * That the sum of blinding factors for all coinbase-marked outputs match
|
// * That the sum of blinding factors for all coinbase-marked outputs match
|
||||||
// the coinbase-marked kernels.
|
// the coinbase-marked kernels.
|
||||||
fn verify_coinbase(&self, secp: &Secp256k1) -> Result<(), Error> {
|
fn verify_coinbase(&self) -> Result<(), Error> {
|
||||||
let cb_outs = filter_map_vec!(self.outputs, |out| if out.features.contains(
|
let cb_outs = filter_map_vec!(self.outputs, |out| if out.features.contains(
|
||||||
COINBASE_OUTPUT,
|
COINBASE_OUTPUT,
|
||||||
)
|
)
|
||||||
|
@ -511,10 +514,17 @@ impl Block {
|
||||||
None
|
None
|
||||||
});
|
});
|
||||||
|
|
||||||
let over_commit = secp.commit_value(reward(self.total_fees()))?;
|
let over_commit;
|
||||||
let out_adjust_sum = secp.commit_sum(cb_outs, vec![over_commit])?;
|
let out_adjust_sum;
|
||||||
|
let kerns_sum;
|
||||||
|
{
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
over_commit = secp.commit_value(reward(self.total_fees()))?;
|
||||||
|
out_adjust_sum = secp.commit_sum(cb_outs, vec![over_commit])?;
|
||||||
|
kerns_sum = secp.commit_sum(cb_kerns, vec![])?;
|
||||||
|
}
|
||||||
|
|
||||||
let kerns_sum = secp.commit_sum(cb_kerns, vec![])?;
|
|
||||||
if kerns_sum != out_adjust_sum {
|
if kerns_sum != out_adjust_sum {
|
||||||
return Err(Error::CoinbaseSumMismatch);
|
return Err(Error::CoinbaseSumMismatch);
|
||||||
}
|
}
|
||||||
|
@ -527,8 +537,6 @@ impl Block {
|
||||||
key_id: &keychain::Identifier,
|
key_id: &keychain::Identifier,
|
||||||
fees: u64,
|
fees: u64,
|
||||||
) -> Result<(Output, TxKernel), keychain::Error> {
|
) -> Result<(Output, TxKernel), keychain::Error> {
|
||||||
let secp = keychain.secp();
|
|
||||||
|
|
||||||
let commit = keychain.commit(reward(fees), key_id)?;
|
let commit = keychain.commit(reward(fees), key_id)?;
|
||||||
let switch_commit = keychain.switch_commit(key_id)?;
|
let switch_commit = keychain.switch_commit(key_id)?;
|
||||||
let switch_commit_hash = SwitchCommitHash::from_switch_commit(switch_commit);
|
let switch_commit_hash = SwitchCommitHash::from_switch_commit(switch_commit);
|
||||||
|
@ -553,6 +561,8 @@ impl Block {
|
||||||
proof: rproof,
|
proof: rproof,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
let over_commit = secp.commit_value(reward(fees))?;
|
let over_commit = secp.commit_value(reward(fees))?;
|
||||||
let out_commit = output.commitment();
|
let out_commit = output.commitment();
|
||||||
let excess = secp.commit_sum(vec![out_commit], vec![over_commit])?;
|
let excess = secp.commit_sum(vec![out_commit], vec![over_commit])?;
|
||||||
|
@ -560,10 +570,12 @@ impl Block {
|
||||||
let msg = util::secp::Message::from_slice(&[0; secp::constants::MESSAGE_SIZE])?;
|
let msg = util::secp::Message::from_slice(&[0; secp::constants::MESSAGE_SIZE])?;
|
||||||
let sig = keychain.sign(&msg, &key_id)?;
|
let sig = keychain.sign(&msg, &key_id)?;
|
||||||
|
|
||||||
|
let excess_sig = sig.serialize_der(&secp);
|
||||||
|
|
||||||
let proof = TxKernel {
|
let proof = TxKernel {
|
||||||
features: COINBASE_KERNEL,
|
features: COINBASE_KERNEL,
|
||||||
excess: excess,
|
excess: excess,
|
||||||
excess_sig: sig.serialize_der(&secp),
|
excess_sig: excess_sig,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
lock_height: 0,
|
lock_height: 0,
|
||||||
};
|
};
|
||||||
|
@ -628,7 +640,7 @@ mod test {
|
||||||
println!("Build tx: {}", now.elapsed().as_secs());
|
println!("Build tx: {}", now.elapsed().as_secs());
|
||||||
|
|
||||||
let b = new_block(vec![&mut tx], &keychain);
|
let b = new_block(vec![&mut tx], &keychain);
|
||||||
assert!(b.validate(&keychain.secp()).is_err());
|
assert!(b.validate().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -652,7 +664,7 @@ mod test {
|
||||||
|
|
||||||
// block should have been automatically compacted (including reward
|
// block should have been automatically compacted (including reward
|
||||||
// output) and should still be valid
|
// output) and should still be valid
|
||||||
b.validate(&keychain.secp()).unwrap();
|
b.validate().unwrap();
|
||||||
assert_eq!(b.inputs.len(), 3);
|
assert_eq!(b.inputs.len(), 3);
|
||||||
assert_eq!(b.outputs.len(), 3);
|
assert_eq!(b.outputs.len(), 3);
|
||||||
}
|
}
|
||||||
|
@ -677,10 +689,10 @@ mod test {
|
||||||
let mut btx3 = txspend1i1o(5, &keychain, key_id2.clone(), key_id3);
|
let mut btx3 = txspend1i1o(5, &keychain, key_id2.clone(), key_id3);
|
||||||
|
|
||||||
let b1 = new_block(vec![&mut btx1, &mut btx2], &keychain);
|
let b1 = new_block(vec![&mut btx1, &mut btx2], &keychain);
|
||||||
b1.validate(&keychain.secp()).unwrap();
|
b1.validate().unwrap();
|
||||||
|
|
||||||
let b2 = new_block(vec![&mut btx3], &keychain);
|
let b2 = new_block(vec![&mut btx3], &keychain);
|
||||||
b2.validate(&keychain.secp()).unwrap();
|
b2.validate().unwrap();
|
||||||
|
|
||||||
// block should have been automatically compacted and should still be valid
|
// block should have been automatically compacted and should still be valid
|
||||||
let b3 = b1.merge(b2);
|
let b3 = b1.merge(b2);
|
||||||
|
@ -713,7 +725,7 @@ mod test {
|
||||||
|
|
||||||
// the block should be valid here (single coinbase output with corresponding
|
// the block should be valid here (single coinbase output with corresponding
|
||||||
// txn kernel)
|
// txn kernel)
|
||||||
assert_eq!(b.validate(&keychain.secp()), Ok(()));
|
assert_eq!(b.validate(), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -728,13 +740,13 @@ mod test {
|
||||||
b.outputs[0].features.remove(COINBASE_OUTPUT);
|
b.outputs[0].features.remove(COINBASE_OUTPUT);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b.verify_coinbase(&keychain.secp()),
|
b.verify_coinbase(),
|
||||||
Err(Error::CoinbaseSumMismatch)
|
Err(Error::CoinbaseSumMismatch)
|
||||||
);
|
);
|
||||||
assert_eq!(b.verify_kernels(&keychain.secp(), false), Ok(()));
|
assert_eq!(b.verify_kernels(false), Ok(()));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b.validate(&keychain.secp()),
|
b.validate(),
|
||||||
Err(Error::CoinbaseSumMismatch)
|
Err(Error::CoinbaseSumMismatch)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -750,13 +762,13 @@ mod test {
|
||||||
b.kernels[0].features.remove(COINBASE_KERNEL);
|
b.kernels[0].features.remove(COINBASE_KERNEL);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b.verify_coinbase(&keychain.secp()),
|
b.verify_coinbase(),
|
||||||
Err(Error::Secp(secp::Error::IncorrectCommitSum))
|
Err(Error::Secp(secp::Error::IncorrectCommitSum))
|
||||||
);
|
);
|
||||||
assert_eq!(b.verify_kernels(&keychain.secp(), true), Ok(()));
|
assert_eq!(b.verify_kernels(true), Ok(()));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b.validate(&keychain.secp()),
|
b.validate(),
|
||||||
Err(Error::Secp(secp::Error::IncorrectCommitSum))
|
Err(Error::Secp(secp::Error::IncorrectCommitSum))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
//! build::transaction(vec![input_rand(75), output_rand(42), output_rand(32),
|
//! build::transaction(vec![input_rand(75), output_rand(42), output_rand(32),
|
||||||
//! with_fee(1)])
|
//! with_fee(1)])
|
||||||
|
|
||||||
use util::secp;
|
use util::{secp, static_secp_instance};
|
||||||
|
|
||||||
use core::{Input, Output, SwitchCommitHash, Transaction, DEFAULT_OUTPUT};
|
use core::{Input, Output, SwitchCommitHash, Transaction, DEFAULT_OUTPUT};
|
||||||
use core::transaction::kernel_sig_msg;
|
use core::transaction::kernel_sig_msg;
|
||||||
|
@ -139,7 +139,11 @@ pub fn transaction(
|
||||||
let blind_sum = ctx.keychain.blind_sum(&sum)?;
|
let blind_sum = ctx.keychain.blind_sum(&sum)?;
|
||||||
let msg = secp::Message::from_slice(&kernel_sig_msg(tx.fee, tx.lock_height))?;
|
let msg = secp::Message::from_slice(&kernel_sig_msg(tx.fee, tx.lock_height))?;
|
||||||
let sig = ctx.keychain.sign_with_blinding(&msg, &blind_sum)?;
|
let sig = ctx.keychain.sign_with_blinding(&msg, &blind_sum)?;
|
||||||
tx.excess_sig = sig.serialize_der(&ctx.keychain.secp());
|
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
tx.excess_sig = sig.serialize_der(&secp);
|
||||||
|
|
||||||
Ok((tx, blind_sum))
|
Ok((tx, blind_sum))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +169,7 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
tx.verify_sig(&keychain.secp()).unwrap();
|
tx.verify_sig().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -179,6 +183,6 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
tx.verify_sig(&keychain.secp()).unwrap();
|
tx.verify_sig().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ use std::cmp::Ordering;
|
||||||
use std::num::ParseFloatError;
|
use std::num::ParseFloatError;
|
||||||
use consensus::GRIN_BASE;
|
use consensus::GRIN_BASE;
|
||||||
|
|
||||||
use util::secp::{self, Secp256k1};
|
use util::{secp, static_secp_instance};
|
||||||
use util::secp::pedersen::*;
|
use util::secp::pedersen::*;
|
||||||
|
|
||||||
pub use self::block::*;
|
pub use self::block::*;
|
||||||
|
@ -36,18 +36,17 @@ pub use self::transaction::*;
|
||||||
use self::hash::Hashed;
|
use self::hash::Hashed;
|
||||||
use ser::{Error, Readable, Reader, Writeable, Writer};
|
use ser::{Error, Readable, Reader, Writeable, Writer};
|
||||||
use global;
|
use global;
|
||||||
// use keychain;
|
|
||||||
|
|
||||||
/// Implemented by types that hold inputs and outputs including Pedersen
|
/// Implemented by types that hold inputs and outputs including Pedersen
|
||||||
/// commitments. Handles the collection of the commitments as well as their
|
/// commitments. Handles the collection of the commitments as well as their
|
||||||
/// summing, taking potential explicit overages of fees into account.
|
/// summing, taking potential explicit overages of fees into account.
|
||||||
pub trait Committed {
|
pub trait Committed {
|
||||||
/// Gathers commitments and sum them.
|
/// Gathers commitments and sum them.
|
||||||
fn sum_commitments(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
|
fn sum_commitments(&self) -> Result<Commitment, secp::Error> {
|
||||||
// first, verify each range proof
|
// first, verify each range proof
|
||||||
let ref outputs = self.outputs_committed();
|
let ref outputs = self.outputs_committed();
|
||||||
for output in *outputs {
|
for output in *outputs {
|
||||||
try!(output.verify_proof(secp))
|
try!(output.verify_proof())
|
||||||
}
|
}
|
||||||
|
|
||||||
// then gather the commitments
|
// then gather the commitments
|
||||||
|
@ -58,7 +57,11 @@ pub trait Committed {
|
||||||
// negative
|
// negative
|
||||||
let overage = self.overage();
|
let overage = self.overage();
|
||||||
if overage != 0 {
|
if overage != 0 {
|
||||||
let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
|
let over_commit = {
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
secp.commit_value(overage.abs() as u64).unwrap()
|
||||||
|
};
|
||||||
if overage < 0 {
|
if overage < 0 {
|
||||||
input_commits.push(over_commit);
|
input_commits.push(over_commit);
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,7 +70,11 @@ pub trait Committed {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sum all that stuff
|
// sum all that stuff
|
||||||
secp.commit_sum(output_commits, input_commits)
|
{
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
secp.commit_sum(output_commits, input_commits)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vector of committed inputs to verify
|
/// Vector of committed inputs to verify
|
||||||
|
@ -310,14 +317,16 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn blind_tx() {
|
fn blind_tx() {
|
||||||
let keychain = Keychain::from_random_seed().unwrap();
|
|
||||||
|
|
||||||
let btx = tx2i1o();
|
let btx = tx2i1o();
|
||||||
btx.verify_sig(&keychain.secp()).unwrap(); // unwrap will panic if invalid
|
btx.verify_sig().unwrap(); // unwrap will panic if invalid
|
||||||
|
|
||||||
// checks that the range proof on our blind output is sufficiently hiding
|
// checks that the range proof on our blind output is sufficiently hiding
|
||||||
let Output { proof, .. } = btx.outputs[0];
|
let Output { proof, .. } = btx.outputs[0];
|
||||||
let info = &keychain.secp().range_proof_info(proof);
|
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
let info = secp.range_proof_info(proof);
|
||||||
|
|
||||||
assert!(info.min == 0);
|
assert!(info.min == 0);
|
||||||
assert!(info.max == u64::max_value());
|
assert!(info.max == u64::max_value());
|
||||||
}
|
}
|
||||||
|
@ -371,7 +380,7 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
tx_final.validate(&keychain.secp()).unwrap();
|
tx_final.validate().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -380,7 +389,7 @@ mod test {
|
||||||
let key_id = keychain.derive_key_id(1).unwrap();
|
let key_id = keychain.derive_key_id(1).unwrap();
|
||||||
|
|
||||||
let b = Block::new(&BlockHeader::default(), vec![], &keychain, &key_id).unwrap();
|
let b = Block::new(&BlockHeader::default(), vec![], &keychain, &key_id).unwrap();
|
||||||
b.compact().validate(&keychain.secp()).unwrap();
|
b.compact().validate().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -389,10 +398,10 @@ mod test {
|
||||||
let key_id = keychain.derive_key_id(1).unwrap();
|
let key_id = keychain.derive_key_id(1).unwrap();
|
||||||
|
|
||||||
let mut tx1 = tx2i1o();
|
let mut tx1 = tx2i1o();
|
||||||
tx1.verify_sig(keychain.secp()).unwrap();
|
tx1.verify_sig().unwrap();
|
||||||
|
|
||||||
let b = Block::new(&BlockHeader::default(), vec![&mut tx1], &keychain, &key_id).unwrap();
|
let b = Block::new(&BlockHeader::default(), vec![&mut tx1], &keychain, &key_id).unwrap();
|
||||||
b.compact().validate(keychain.secp()).unwrap();
|
b.compact().validate().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -409,7 +418,7 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
&key_id,
|
&key_id,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
b.validate(keychain.secp()).unwrap();
|
b.validate().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -439,7 +448,7 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
&key_id3.clone(),
|
&key_id3.clone(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
b.validate(keychain.secp()).unwrap();
|
b.validate().unwrap();
|
||||||
|
|
||||||
// now try adding a timelocked tx where lock height is greater than current block height
|
// now try adding a timelocked tx where lock height is greater than current block height
|
||||||
let tx1 = build::transaction(
|
let tx1 = build::transaction(
|
||||||
|
@ -459,7 +468,7 @@ mod test {
|
||||||
&keychain,
|
&keychain,
|
||||||
&key_id3.clone(),
|
&key_id3.clone(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
match b.validate(keychain.secp()) {
|
match b.validate() {
|
||||||
Err(KernelLockHeight { lock_height: height }) => {
|
Err(KernelLockHeight { lock_height: height }) => {
|
||||||
assert_eq!(height, 2);
|
assert_eq!(height, 2);
|
||||||
}
|
}
|
||||||
|
@ -469,16 +478,14 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_verify_1i1o_sig() {
|
pub fn test_verify_1i1o_sig() {
|
||||||
let keychain = keychain::Keychain::from_random_seed().unwrap();
|
|
||||||
let tx = tx1i1o();
|
let tx = tx1i1o();
|
||||||
tx.verify_sig(keychain.secp()).unwrap();
|
tx.verify_sig().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_verify_2i1o_sig() {
|
pub fn test_verify_2i1o_sig() {
|
||||||
let keychain = keychain::Keychain::from_random_seed().unwrap();
|
|
||||||
let tx = tx2i1o();
|
let tx = tx2i1o();
|
||||||
tx.verify_sig(keychain.secp()).unwrap();
|
tx.verify_sig().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// utility producing a transaction with 2 inputs and a single outputs
|
// utility producing a transaction with 2 inputs and a single outputs
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use blake2::blake2b::blake2b;
|
use blake2::blake2b::blake2b;
|
||||||
use util::secp::{self, Message, Secp256k1, Signature};
|
use util::secp::{self, Message, Signature};
|
||||||
use util::static_secp_instance;
|
use util::static_secp_instance;
|
||||||
use util::secp::pedersen::{Commitment, RangeProof};
|
use util::secp::pedersen::{Commitment, RangeProof};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -147,11 +147,13 @@ impl TxKernel {
|
||||||
/// Verify the transaction proof validity. Entails handling the commitment
|
/// Verify the transaction proof validity. Entails handling the commitment
|
||||||
/// as a public key and checking the signature verifies with the fee as
|
/// as a public key and checking the signature verifies with the fee as
|
||||||
/// message.
|
/// message.
|
||||||
pub fn verify(&self, secp: &Secp256k1) -> Result<(), secp::Error> {
|
pub fn verify(&self) -> Result<(), secp::Error> {
|
||||||
let msg = try!(Message::from_slice(
|
let msg = try!(Message::from_slice(
|
||||||
&kernel_sig_msg(self.fee, self.lock_height),
|
&kernel_sig_msg(self.fee, self.lock_height),
|
||||||
));
|
));
|
||||||
let sig = try!(Signature::from_der(secp, &self.excess_sig));
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
let sig = try!(Signature::from_der(&secp, &self.excess_sig));
|
||||||
secp.verify_from_commit(&msg, &sig, &self.excess)
|
secp.verify_from_commit(&msg, &sig, &self.excess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,11 +308,14 @@ impl Transaction {
|
||||||
/// sum to zero as they should in r.G + v.H then only k.G the excess
|
/// sum to zero as they should in r.G + v.H then only k.G the excess
|
||||||
/// of the sum of r.G should be left. And r.G is the definition of a
|
/// of the sum of r.G should be left. And r.G is the definition of a
|
||||||
/// public key generated using r as a private key.
|
/// public key generated using r as a private key.
|
||||||
pub fn verify_sig(&self, secp: &Secp256k1) -> Result<Commitment, secp::Error> {
|
pub fn verify_sig(&self) -> Result<Commitment, secp::Error> {
|
||||||
let rsum = self.sum_commitments(secp)?;
|
let rsum = self.sum_commitments()?;
|
||||||
|
|
||||||
let msg = Message::from_slice(&kernel_sig_msg(self.fee, self.lock_height))?;
|
let msg = Message::from_slice(&kernel_sig_msg(self.fee, self.lock_height))?;
|
||||||
let sig = Signature::from_der(secp, &self.excess_sig)?;
|
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
|
let sig = Signature::from_der(&secp, &self.excess_sig)?;
|
||||||
|
|
||||||
// pretend the sum is a public key (which it is, being of the form r.G) and
|
// pretend the sum is a public key (which it is, being of the form r.G) and
|
||||||
// verify the transaction sig with it
|
// verify the transaction sig with it
|
||||||
|
@ -338,14 +343,14 @@ impl Transaction {
|
||||||
/// Validates all relevant parts of a fully built transaction. Checks the
|
/// Validates all relevant parts of a fully built transaction. Checks the
|
||||||
/// excess value against the signature as well as range proofs for each
|
/// excess value against the signature as well as range proofs for each
|
||||||
/// output.
|
/// output.
|
||||||
pub fn validate(&self, secp: &Secp256k1) -> Result<Commitment, Error> {
|
pub fn validate(&self) -> Result<Commitment, Error> {
|
||||||
if self.fee & 1 != 0 {
|
if self.fee & 1 != 0 {
|
||||||
return Err(Error::OddFee);
|
return Err(Error::OddFee);
|
||||||
}
|
}
|
||||||
for out in &self.outputs {
|
for out in &self.outputs {
|
||||||
out.verify_proof(secp)?;
|
out.verify_proof()?;
|
||||||
}
|
}
|
||||||
let excess = self.verify_sig(secp)?;
|
let excess = self.verify_sig()?;
|
||||||
Ok(excess)
|
Ok(excess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,7 +519,9 @@ impl Output {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates the range proof using the commitment
|
/// Validates the range proof using the commitment
|
||||||
pub fn verify_proof(&self, secp: &Secp256k1) -> Result<(), secp::Error> {
|
pub fn verify_proof(&self) -> Result<(), secp::Error> {
|
||||||
|
let secp = static_secp_instance();
|
||||||
|
let secp = secp.lock().unwrap();
|
||||||
secp.verify_range_proof(self.commit, self.proof).map(|_| ())
|
secp.verify_range_proof(self.commit, self.proof).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ use util::LOGGER;
|
||||||
use types::Error;
|
use types::Error;
|
||||||
|
|
||||||
use chain;
|
use chain;
|
||||||
use util::secp;
|
|
||||||
use pool;
|
use pool;
|
||||||
use util;
|
use util;
|
||||||
use keychain::{Identifier, Keychain};
|
use keychain::{Identifier, Keychain};
|
||||||
|
@ -574,8 +573,7 @@ impl Miner {
|
||||||
);
|
);
|
||||||
|
|
||||||
// making sure we're not spending time mining a useless block
|
// making sure we're not spending time mining a useless block
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
b.validate().expect("Built an invalid block!");
|
||||||
b.validate(&secp).expect("Built an invalid block!");
|
|
||||||
|
|
||||||
let mut rng = rand::OsRng::new().unwrap();
|
let mut rng = rand::OsRng::new().unwrap();
|
||||||
b.header.nonce = rng.gen();
|
b.header.nonce = rng.gen();
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl Keychain {
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(LOGGER, "Derived Key key_id: {}", key_id);
|
trace!(LOGGER, "Derived Key key_id: {}", key_id);
|
||||||
|
|
||||||
if let Some(n) = n_child{
|
if let Some(n) = n_child{
|
||||||
let extkey = self.extkey.derive(&self.secp, n)?;
|
let extkey = self.extkey.derive(&self.secp, n)?;
|
||||||
return Ok(extkey.key);
|
return Ok(extkey.key);
|
||||||
|
@ -222,8 +222,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_derivation() {
|
fn test_key_derivation() {
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
|
||||||
let keychain = Keychain::from_random_seed().unwrap();
|
let keychain = Keychain::from_random_seed().unwrap();
|
||||||
|
let secp = keychain.secp();
|
||||||
|
|
||||||
// use the keychain to derive a "key_id" based on the underlying seed
|
// use the keychain to derive a "key_id" based on the underlying seed
|
||||||
let key_id = keychain.derive_key_id(1).unwrap();
|
let key_id = keychain.derive_key_id(1).unwrap();
|
||||||
|
|
|
@ -22,7 +22,6 @@ use core::core::block;
|
||||||
use core::core::hash;
|
use core::core::hash;
|
||||||
use core::global;
|
use core::global;
|
||||||
|
|
||||||
use util::secp;
|
|
||||||
use util::secp::pedersen::Commitment;
|
use util::secp::pedersen::Commitment;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -145,8 +144,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Making sure the transaction is valid before anything else.
|
// Making sure the transaction is valid before anything else.
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
tx.validate().map_err(|_e| PoolError::Invalid)?;
|
||||||
tx.validate(&secp).map_err(|_e| PoolError::Invalid)?;
|
|
||||||
|
|
||||||
// The first check involves ensuring that an identical transaction is
|
// The first check involves ensuring that an identical transaction is
|
||||||
// not already in the pool's transaction set.
|
// not already in the pool's transaction set.
|
||||||
|
|
|
@ -205,7 +205,7 @@ fn receive_transaction(
|
||||||
|
|
||||||
// make sure the resulting transaction is valid (could have been lied to on
|
// make sure the resulting transaction is valid (could have been lied to on
|
||||||
// excess).
|
// excess).
|
||||||
tx_final.validate(&keychain.secp())?;
|
tx_final.validate()?;
|
||||||
|
|
||||||
// operate within a lock on wallet data
|
// operate within a lock on wallet data
|
||||||
WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
|
WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
|
||||||
|
|
|
@ -135,7 +135,7 @@ pub fn issue_burn_tx(
|
||||||
|
|
||||||
// finalize the burn transaction and send
|
// finalize the burn transaction and send
|
||||||
let (tx_burn, _) = build::transaction(parts, &keychain)?;
|
let (tx_burn, _) = build::transaction(parts, &keychain)?;
|
||||||
tx_burn.validate(&keychain.secp())?;
|
tx_burn.validate()?;
|
||||||
|
|
||||||
let tx_hex = util::to_hex(ser::ser_vec(&tx_burn).unwrap());
|
let tx_hex = util::to_hex(ser::ser_vec(&tx_burn).unwrap());
|
||||||
let url = format!("{}/v1/pool/push", config.check_node_api_http_addr.as_str());
|
let url = format!("{}/v1/pool/push", config.check_node_api_http_addr.as_str());
|
||||||
|
|
Loading…
Reference in a new issue