Skip to content
This repository was archived by the owner on Dec 28, 2023. It is now read-only.

Commit

Permalink
Support new Bulletproof rewind scheme (mimblewimble#50)
Browse files Browse the repository at this point in the history
* Bulletproofs: change message to 20 bytes, allow 2 nonces in generation

* Updated syntax of rewind function

* Update to latest libsecp

* Update tests

* Fix borrow after move

* Update tests
  • Loading branch information
jaspervdm authored and garyyu committed Sep 10, 2019
1 parent dea1d97 commit 2a44899
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub const SINGLE_BULLET_PROOF_SIZE: usize = 675;
pub const MAX_PROOF_SIZE: usize = SINGLE_BULLET_PROOF_SIZE;

/// The maximum size of an optional message embedded in a bullet proof
pub const BULLET_PROOF_MSG_SIZE: usize = 16;
pub const BULLET_PROOF_MSG_SIZE: usize = 20;

/// The maximum size of a message embedded in a range proof
pub const PROOF_MSG_SIZE: usize = BULLET_PROOF_MSG_SIZE;
Expand Down
1 change: 0 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,6 @@ extern "C" {

pub fn secp256k1_bulletproof_rangeproof_rewind(
ctx: *const Context,
gens: *const BulletproofGenerators,
value: *mut u64,
blind: *mut c_uchar,
proof: *const c_uchar,
Expand Down
129 changes: 104 additions & 25 deletions src/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,8 @@ impl Secp256k1 {
&self,
value: u64,
blind: SecretKey,
nonce: SecretKey,
rewind_nonce: SecretKey,
private_nonce: SecretKey,
extra_data_in: Option<Vec<u8>>,
message: Option<ProofMessage>,
) -> RangeProof {
Expand Down Expand Up @@ -738,12 +739,11 @@ impl Secp256k1 {
None => ptr::null(),
};

// This api is not for multi-party range proof, so all null for these 5 parameters.
// This api is not for multi-party range proof, so all null for these 4 parameters.
let tau_x = ptr::null_mut();
let t_one = ptr::null_mut();
let t_two = ptr::null_mut();
let commits = ptr::null_mut();
let private_nonce = ptr::null();

let _success = unsafe {
let scratch = ffi::secp256k1_scratch_space_create(self.ctx, SCRATCH_SPACE_SIZE);
Expand All @@ -763,8 +763,8 @@ impl Secp256k1 {
1,
constants::GENERATOR_H.as_ptr(),
n_bits as size_t,
nonce.as_ptr(),
private_nonce,
rewind_nonce.as_ptr(),
private_nonce.as_ptr(),
extra_data,
extra_data_len as size_t,
message_ptr,
Expand Down Expand Up @@ -1050,14 +1050,13 @@ impl Secp256k1 {

let mut blind_out = [0u8; constants::SECRET_KEY_SIZE];
let mut value_out = 0;
let mut message_out = [0u8; 16];
let mut message_out = [0u8; 20];
let commit = self.commit_parse(commit.0)?;

let success = unsafe {
let scratch = ffi::secp256k1_scratch_space_create(self.ctx, SCRATCH_SPACE_SIZE);
let result = ffi::secp256k1_bulletproof_rangeproof_rewind(
self.ctx,
shared_generators(self.ctx),
&mut value_out,
blind_out.as_mut_ptr(),
proof.proof.as_ptr(),
Expand Down Expand Up @@ -1343,7 +1342,14 @@ mod tests {
let blinding = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;
let commit = secp.commit(value, blinding.clone()).unwrap();
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
blinding.clone(),
blinding.clone(),
None,
None,
);

// correct verification
println!("Bullet proof len: {}", bullet_proof.plen);
Expand All @@ -1355,7 +1361,14 @@ mod tests {
// wrong value committed to
let value = 12345678;
let wrong_commit = secp.commit(87654321, blinding.clone()).unwrap();
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
blinding.clone(),
blinding.clone(),
None,
None,
);
if !secp
.verify_bullet_proof(wrong_commit, bullet_proof, None)
.is_err()
Expand All @@ -1367,7 +1380,14 @@ mod tests {
let value = 12345678;
let commit = secp.commit(value, blinding).unwrap();
let blinding = SecretKey::new(&secp, &mut thread_rng());
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
blinding.clone(),
blinding.clone(),
None,
None,
);
if !secp
.verify_bullet_proof(commit, bullet_proof, None)
.is_err()
Expand All @@ -1384,6 +1404,7 @@ mod tests {
value,
blinding.clone(),
blinding.clone(),
blinding.clone(),
Some(extra_data.clone()),
None,
);
Expand All @@ -1408,22 +1429,24 @@ mod tests {
// Ensure rewinding works

let blinding = SecretKey::new(&secp, &mut thread_rng());
let nonce = SecretKey::new(&secp, &mut thread_rng());
let rewind_nonce = SecretKey::new(&secp, &mut thread_rng());
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;
let commit = secp.commit(value, blinding.clone()).unwrap();

let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
nonce.clone(),
private_nonce.clone(),
private_nonce.clone(),
Some(extra_data.clone()),
None,
);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(
commit,
nonce.clone(),
private_nonce.clone(),
Some(extra_data.clone()),
bullet_proof,
)
Expand All @@ -1443,26 +1466,31 @@ mod tests {
}

// unwinding with wrong extra data should puke
let proof_info = secp.rewind_bullet_proof(commit, nonce.clone(), None, bullet_proof);
let proof_info =
secp.rewind_bullet_proof(commit, private_nonce.clone(), None, bullet_proof);
if !proof_info.is_err() {
panic!("Bullet proof verify with message should have errored.");
}

// Ensure including a message also works
let message_bytes: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let message_bytes: [u8; 20] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
];
let message = ProofMessage::from_bytes(&message_bytes);

let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
nonce.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data.clone()),
Some(message.clone()),
);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce, Some(extra_data.clone()), bullet_proof)
.rewind_bullet_proof(commit, rewind_nonce, Some(extra_data.clone()), bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_eq!(proof_info.message, message);
}

Expand Down Expand Up @@ -1769,6 +1797,7 @@ mod tests {
value,
blinding.clone(),
nonce.clone(),
nonce.clone(),
None,
Some(pm.clone()),
);
Expand All @@ -1790,13 +1819,36 @@ mod tests {
let value = <u64>::max_value() - 1;
let commit = secp.commit(value, blinding.clone()).unwrap();

let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), None, None);
let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
nonce.clone(),
nonce.clone(),
None,
None,
);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce, None, bullet_proof)
.rewind_bullet_proof(commit, nonce.clone(), None, bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_eq!(blinding, proof_info.blinding);

// Using a different private nonce should prevent rewind of blinding factor
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
nonce.clone(),
private_nonce.clone(),
None,
None,
);
let proof_info = secp
.rewind_bullet_proof(commit, nonce, None, bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_ne!(blinding, proof_info.blinding);
}

#[ignore]
Expand All @@ -1819,6 +1871,7 @@ mod tests {
value + i as u64,
blinding.clone(),
blinding.clone(),
blinding.clone(),
None,
None,
));
Expand Down Expand Up @@ -1852,13 +1905,22 @@ mod tests {

let secp = Secp256k1::with_caps(ContextFlag::Commit);
let blinding = SecretKey::new(&secp, &mut thread_rng());
let rewind_nonce = SecretKey::new(&secp, &mut thread_rng());
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let wrong_blinding = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;

let wrong_commit = secp.commit(value, wrong_blinding).unwrap();

commits.push(secp.commit(value, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(
value,
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
None,
None,
));
let proof_range = secp
.verify_bullet_proof(commits[0].clone(), proofs[0].clone(), None)
.unwrap();
Expand All @@ -1884,8 +1946,22 @@ mod tests {
proofs = vec![];
commits.push(secp.commit(value + 1, blinding.clone()).unwrap());
commits.push(secp.commit(value - 1, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value + 1, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value - 1, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(
value + 1,
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
None,
None,
));
proofs.push(secp.bullet_proof(
value - 1,
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
None,
None,
));
let proof_range = secp
.verify_bullet_proof_multi(commits.clone(), proofs.clone(), None)
.unwrap();
Expand All @@ -1901,14 +1977,16 @@ mod tests {
proofs.push(secp.bullet_proof(
value + 1,
blinding.clone(),
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data1.clone()),
None,
));
proofs.push(secp.bullet_proof(
value - 1,
blinding.clone(),
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data2.clone()),
None,
));
Expand Down Expand Up @@ -1943,7 +2021,8 @@ mod tests {
proofs.push(secp.bullet_proof(
value + i as u64,
blinding.clone(),
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
None,
None,
));
Expand Down

0 comments on commit 2a44899

Please sign in to comment.