diff --git a/core/src/core/block.rs b/core/src/core/block.rs index 5c497a009..7c8057532 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -1059,9 +1059,13 @@ mod test { let b = new_block(vec![], &keychain); let mut vec = Vec::new(); ser::serialize(&mut vec, &b).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 1_256, + false => 5_708, + }; assert_eq!( vec.len(), - 5_708, + target_len, ); } @@ -1072,9 +1076,13 @@ mod test { let b = new_block(vec![&tx1], &keychain); let mut vec = Vec::new(); ser::serialize(&mut vec, &b).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 2_900, + false => 16_256, + }; assert_eq!( vec.len(), - 16_256, + target_len, ); } @@ -1084,9 +1092,13 @@ mod test { let b = new_block(vec![], &keychain); let mut vec = Vec::new(); ser::serialize(&mut vec, &b.as_compact_block()).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 1_264, + false => 5_716, + }; assert_eq!( vec.len(), - 5_716, + target_len, ); } @@ -1097,9 +1109,13 @@ mod test { let b = new_block(vec![&tx1], &keychain); let mut vec = Vec::new(); ser::serialize(&mut vec, &b.as_compact_block()).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 1_270, + false => 5_722, + }; assert_eq!( vec.len(), - 5_722, + target_len, ); } @@ -1119,9 +1135,13 @@ mod test { ); let mut vec = Vec::new(); ser::serialize(&mut vec, &b).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 17696, + false => 111188, + }; assert_eq!( vec.len(), - 111_188, + target_len, ); } @@ -1141,9 +1161,13 @@ mod test { ); let mut vec = Vec::new(); ser::serialize(&mut vec, &b.as_compact_block()).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 1_324, + false => 5_776, + }; assert_eq!( vec.len(), - 5_776, + target_len, ); } diff --git a/core/src/core/mod.rs b/core/src/core/mod.rs index 7eeb5755e..8d1c72660 100644 --- a/core/src/core/mod.rs +++ b/core/src/core/mod.rs @@ -263,9 +263,13 @@ mod test { let tx = tx2i1o(); let mut vec = Vec::new(); ser::serialize(&mut vec, &tx).expect("serialization failed"); + let target_len = match Keychain::is_using_bullet_proofs() { + true => 986, + false => 5_438, + }; assert_eq!( vec.len(), - 5_438, + target_len, ); } @@ -390,6 +394,12 @@ mod test { let btx = tx2i1o(); assert!(btx.validate().is_ok()); + // Ignored for bullet proofs, info doesn't exist yet and calling range_proof_info + // with a bullet proof causes painful errors + if Keychain::is_using_bullet_proofs() { + return; + } + // checks that the range proof on our blind output is sufficiently hiding let Output { proof, .. } = btx.outputs[0]; diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 599c53a2b..0c24f1854 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -92,6 +92,8 @@ pub enum Error { LockHeight(u64), /// Error originating from an invalid switch commitment (coinbase lock_height related) SwitchCommitment, + /// Range proof validation error + RangeProof, } impl From for Error { @@ -749,8 +751,11 @@ impl Output { 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(|_| ()) - } + match Keychain::verify_range_proof(&secp, self.commit, self.proof){ + Ok(_) => Ok(()), + Err(e) => Err(e), + } +} /// Given the original blinding factor we can recover the /// value from the range proof and the commitment @@ -1089,8 +1094,14 @@ mod test { }; // check we can successfully recover the value with the original blinding factor - let recovered_value = output.recover_value(&keychain, &key_id).unwrap(); - assert_eq!(recovered_value, 1003); + let result = output.recover_value(&keychain, &key_id); + // TODO: Remove this check once value recovery is supported within bullet proofs + if let Some(v) = result { + assert_eq!(v, 1003); + } else { + return; + } + // check we cannot recover the value without the original blinding factor let key_id2 = keychain.derive_key_id(2).unwrap(); diff --git a/keychain/Cargo.toml b/keychain/Cargo.toml index 649be6cdb..b3eeefa19 100644 --- a/keychain/Cargo.toml +++ b/keychain/Cargo.toml @@ -3,6 +3,12 @@ name = "grin_keychain" version = "0.1.0" authors = ["Antioch Peverell"] +[features] +#remove this feature to use older-style rangeproofs +#(this flag will disappear in future releases) +default = ["use-bullet-proofs"] +use-bullet-proofs = [] + [dependencies] byteorder = "^1.0" blake2-rfc = "~0.2.17" diff --git a/keychain/src/keychain.rs b/keychain/src/keychain.rs index 0d4cd322c..27e9f210b 100644 --- a/keychain/src/keychain.rs +++ b/keychain/src/keychain.rs @@ -28,12 +28,18 @@ use uuid::Uuid; use blind::{BlindSum, BlindingFactor}; use extkey::{self, Identifier}; +#[cfg(feature = "use-bullet-proofs")] +const USE_BULLET_PROOFS:bool = true; +#[cfg(not(feature = "use-bullet-proofs"))] +const USE_BULLET_PROOFS:bool = false; + #[derive(PartialEq, Eq, Clone, Debug)] pub enum Error { ExtendedKey(extkey::Error), Secp(secp::Error), KeyDerivation(String), Transaction(String), + RangeProof(String), } impl From for Error { @@ -220,6 +226,10 @@ impl Keychain { Ok(child_key.switch_key) } + pub fn is_using_bullet_proofs() -> bool { + USE_BULLET_PROOFS + } + pub fn range_proof( &self, amount: u64, @@ -228,10 +238,27 @@ impl Keychain { msg: ProofMessage, ) -> Result { let skey = self.derived_key(key_id)?; - let range_proof = self.secp.range_proof(0, amount, skey, commit, msg); + let range_proof = match USE_BULLET_PROOFS { + true => self.secp.bullet_proof(amount, skey), + false => self.secp.range_proof(0, amount, skey, commit, msg), + }; Ok(range_proof) } + pub fn verify_range_proof( + secp: &Secp256k1, + commit: Commitment, + proof: RangeProof) -> Result<(), secp::Error> { + let result = match USE_BULLET_PROOFS { + true => secp.verify_bullet_proof(commit, proof), + false => secp.verify_range_proof(commit, proof), + }; + match result { + Ok(_) => Ok(()), + Err(e) => Err(e), + } + } + pub fn rewind_range_proof( &self, key_id: &Identifier, @@ -239,6 +266,10 @@ impl Keychain { proof: RangeProof, ) -> Result { let nonce = self.derived_key(key_id)?; + if USE_BULLET_PROOFS { + error!(LOGGER, "Rewinding Bullet proofs not yet supported"); + return Err(Error::RangeProof("Rewinding Bullet proofs not yet supported".to_string())); + } Ok(self.secp.rewind_range_proof(commit, proof, nonce)) } @@ -527,6 +558,11 @@ mod test { let commit = keychain.commit(5, &key_id).unwrap(); let msg = ProofMessage::empty(); + //TODO: Remove this check when bullet proofs can be rewound + if Keychain::is_using_bullet_proofs(){ + return; + } + let proof = keychain.range_proof(5, &key_id, commit, msg).unwrap(); let proof_info = keychain.rewind_range_proof(&key_id, commit, proof).unwrap(); diff --git a/util/Cargo.toml b/util/Cargo.toml index b53449a44..2e43840d2 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -14,7 +14,7 @@ byteorder = "^1.0" rand = "^0.3" serde = "~1.0.8" serde_derive = "~1.0.8" -secp256k1zkp = { git = "https://github.com/mimblewimble/rust-secp256k1-zkp", tag="grin_integration_7" } +secp256k1zkp = { git = "https://github.com/mimblewimble/rust-secp256k1-zkp", tag="grin_integration_8" } #secp256k1zkp = { path = "../../rust-secp256k1-zkp" } walkdir = "^2.0.1" zip = "^0.2.6"