added basic tests around range_proof (#121)

Pass nonce in to range_proof (we need it for rewind_range_proof, at least for testing)
This commit is contained in:
AntiochP 2017-09-10 14:31:41 -04:00 committed by Ignotus Peverell
parent 6056c16cfa
commit 87cd0e5c58
5 changed files with 87 additions and 15 deletions

View file

@ -458,7 +458,8 @@ impl Block {
let sig = try!(secp.sign(&msg, &skey));
let commit = secp.commit(REWARD, skey).unwrap();
//let switch_commit = secp.switch_commit(skey).unwrap();
let rproof = secp.range_proof(0, REWARD, skey, commit);
let nonce = secp.nonce();
let rproof = secp.range_proof(0, REWARD, skey, commit, nonce);
let output = Output {
features: COINBASE_OUTPUT,

View file

@ -110,7 +110,8 @@ pub fn input_rand(value: u64) -> Box<Append> {
pub fn output(value: u64, blinding: SecretKey) -> Box<Append> {
Box::new(move |build, (tx, sum)| -> (Transaction, BlindSum) {
let commit = build.secp.commit(value, blinding).unwrap();
let rproof = build.secp.range_proof(0, value, blinding, commit);
let nonce = build.secp.nonce();
let rproof = build.secp.range_proof(0, value, blinding, commit, nonce);
(tx.with_output(Output {
features: DEFAULT_OUTPUT,
commit: commit,
@ -127,7 +128,8 @@ pub fn output_rand(value: u64) -> Box<Append> {
Box::new(move |build, (tx, sum)| -> (Transaction, BlindSum) {
let blinding = SecretKey::new(&build.secp, &mut build.rng);
let commit = build.secp.commit(value, blinding).unwrap();
let rproof = build.secp.range_proof(0, value, blinding, commit);
let nonce = build.secp.nonce();
let rproof = build.secp.range_proof(0, value, blinding, commit, nonce);
(tx.with_output(Output {
features: DEFAULT_OUTPUT,
commit: commit,

View file

@ -233,7 +233,7 @@ mod tests {
let outputs = vec![core::transaction::Output{
features: core::transaction::DEFAULT_OUTPUT,
commit: output_commit,
proof: ec.range_proof(0, 100, key::ZERO_KEY, output_commit)}];
proof: ec.range_proof(0, 100, key::ZERO_KEY, output_commit, ec.nonce())}];
let test_transaction = core::transaction::Transaction::new(inputs,
outputs, 5);

View file

@ -892,7 +892,7 @@ mod tests {
transaction::Output{
features: transaction::DEFAULT_OUTPUT,
commit: output_commitment,
proof: ec.range_proof(0, value, output_key, output_commitment)}
proof: ec.range_proof(0, value, output_key, output_commitment, ec.nonce())}
}
/// Makes a SecretKey from a single u64

View file

@ -163,6 +163,7 @@ impl RangeProof {
}
/// The range that was proven
#[derive(Debug)]
pub struct ProofRange {
/// Min value that was proven
pub min: u64,
@ -306,20 +307,25 @@ impl Secp256k1 {
SecretKey::from_slice(self, &ret)
}
/// Convenience function for generating a random nonce for a range proof.
/// We will need the nonce later if we want to rewind the range proof.
pub fn nonce(&self) -> [u8; 32] {
let mut rng = OsRng::new().unwrap();
let mut nonce = [0u8; 32];
rng.fill_bytes(&mut nonce);
nonce
}
/// Produces a range proof for the provided value, using min and max
/// bounds, relying
/// on the blinding factor and commitment.
pub fn range_proof(&self,
min: u64,
value: u64,
blind: SecretKey,
commit: Commitment)
-> RangeProof {
let mut rng = OsRng::new().unwrap();
let mut nonce = [0u8; 32];
rng.fill_bytes(&mut nonce);
min: u64,
value: u64,
blind: SecretKey,
commit: Commitment,
nonce: [u8; 32])
-> RangeProof {
let mut retried = false;
let mut proof = [0; constants::MAX_PROOF_SIZE];
let mut plen = constants::MAX_PROOF_SIZE as i32;
@ -585,4 +591,67 @@ mod tests {
1001
));
}
#[test]
fn test_commit_sum() {
let secp = Secp256k1::with_caps(ContextFlag::Commit);
fn commit(value: u64, blinding: SecretKey) -> Commitment {
let secp = Secp256k1::with_caps(ContextFlag::Commit);
secp.commit(value, blinding).unwrap()
}
let blind_a = SecretKey::new(&secp, &mut OsRng::new().unwrap());
let blind_b = SecretKey::new(&secp, &mut OsRng::new().unwrap());
let commit_a = commit(3, blind_a);
let commit_b = commit(2, blind_b);
let blind_c = secp.blind_sum(vec![blind_a, blind_b], vec![]).unwrap();
let commit_c = commit(3 + 2, blind_c);
let commit_d = secp.commit_sum(vec![commit_a, commit_b], vec![]).unwrap();
assert_eq!(commit_c, commit_d);
}
#[test]
fn test_range_proof() {
let secp = Secp256k1::with_caps(ContextFlag::Commit);
let blinding = SecretKey::new(&secp, &mut OsRng::new().unwrap());
let commit = secp.commit(7, blinding).unwrap();
let nonce = secp.nonce();
let range_proof = secp.range_proof(0, 7, blinding, commit, nonce);
let proof_range = secp.verify_range_proof(commit, range_proof).unwrap();
assert_eq!(proof_range.min, 0);
let proof_info = secp.range_proof_info(range_proof);
assert!(proof_info.success);
assert_eq!(proof_info.min, 0);
// check we get no information back for the value here
assert_eq!(proof_info.value, 0);
let proof_info = secp.rewind_range_proof(commit, range_proof, nonce);
assert!(proof_info.success);
assert_eq!(proof_info.min, 0);
assert_eq!(proof_info.value, 7);
// check we cannot rewind a range proof without the original nonce
let bad_nonce = secp.nonce();
let bad_info = secp.rewind_range_proof(commit, range_proof, bad_nonce);
assert_eq!(bad_info.success, false);
assert_eq!(bad_info.value, 0);
// check we can construct and verify a range proof on value 0
let commit = secp.commit(0, blinding).unwrap();
let nonce = secp.nonce();
let range_proof = secp.range_proof(0, 0, blinding, commit, nonce);
let proof_range = secp.verify_range_proof(commit, range_proof).unwrap();
let proof_info = secp.rewind_range_proof(commit, range_proof, nonce);
assert!(proof_info.success);
assert_eq!(proof_info.min, 0);
assert_eq!(proof_info.value, 0);
}
}