From 62e44fa9364584056cf4605b84e278186c0f3755 Mon Sep 17 00:00:00 2001 From: Antioch Peverell <30642645+antiochp@users.noreply.github.com> Date: Fri, 2 Feb 2018 09:51:55 -0500 Subject: [PATCH] [WIP] Kernel investigation (#679) * add some tests around building a tx_kernel from a tx and adding secret keys together (and checking commitments) * key addition tests --- core/src/core/mod.rs | 28 ++++++++++++++++++ keychain/src/blind.rs | 3 +- keychain/src/keychain.rs | 62 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/core/src/core/mod.rs b/core/src/core/mod.rs index 3d6a0d04..27bb827c 100644 --- a/core/src/core/mod.rs +++ b/core/src/core/mod.rs @@ -296,6 +296,34 @@ mod test { assert_eq!(dtx.hash(), dtx2.hash()); } + #[test] + fn build_tx_kernel() { + let keychain = Keychain::from_random_seed().unwrap(); + let key_id1 = keychain.derive_key_id(1).unwrap(); + let key_id2 = keychain.derive_key_id(2).unwrap(); + let key_id3 = keychain.derive_key_id(3).unwrap(); + + // first build a valid tx with corresponding blinding factor + let (tx, blind) = build::transaction( + vec![ + input(10, ZERO_HASH, key_id1), + output(5, key_id2), + output(3, key_id3), + with_fee(2), + ], + &keychain, + ).unwrap(); + + // confirm the tx validates and that we can construct a valid tx_kernel from it + let excess = tx.validate().unwrap(); + let tx_kernel = tx.build_kernel(excess); + let _ = tx_kernel.verify().unwrap(); + + assert_eq!(tx_kernel.features, DEFAULT_KERNEL); + assert_eq!(tx_kernel.fee, tx.fee); + assert_eq!(tx_kernel.excess, excess); + } + #[test] fn hash_output() { let keychain = Keychain::from_random_seed().unwrap(); diff --git a/keychain/src/blind.rs b/keychain/src/blind.rs index 5d6405ed..6c915eb8 100644 --- a/keychain/src/blind.rs +++ b/keychain/src/blind.rs @@ -18,7 +18,7 @@ use util::secp::{self, Secp256k1}; use extkey::Identifier; use keychain::Error; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct BlindingFactor(secp::key::SecretKey); impl BlindingFactor { @@ -39,6 +39,7 @@ impl BlindingFactor { /// Accumulator to compute the sum of blinding factors. Keeps track of each /// factor as well as the "sign" with which they should be combined. +#[derive(Clone, Debug, PartialEq)] pub struct BlindSum { pub positive_key_ids: Vec, pub negative_key_ids: Vec, diff --git a/keychain/src/keychain.rs b/keychain/src/keychain.rs index 075bd16c..af5a42e8 100644 --- a/keychain/src/keychain.rs +++ b/keychain/src/keychain.rs @@ -439,9 +439,11 @@ impl Keychain { #[cfg(test)] mod test { - use keychain::Keychain; + use keychain::{BlindSum, BlindingFactor, Keychain}; use util::secp; use util::secp::pedersen::ProofMessage; + use util::secp::key::SecretKey; + #[test] fn test_key_derivation() { @@ -508,4 +510,62 @@ mod test { assert_eq!(proof_info.success, false); assert_eq!(proof_info.value, 0); } + + // We plan to "offset" the key used in the kernel commitment + // so we are going to be doing some key addition/subtraction. + // This test is mainly to demonstrate that idea that summing commitments + // and summing the keys used to commit to 0 have the same result. + #[test] + fn secret_key_addition() { + let keychain = Keychain::from_random_seed().unwrap(); + + let skey1 = SecretKey::from_slice( + &keychain.secp, + &[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + ], + ).unwrap(); + + let skey2 = SecretKey::from_slice( + &keychain.secp, + &[ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + ], + ).unwrap(); + + // adding secret keys 1 and 2 to give secret key 3 + let mut skey3 = skey1.clone(); + let _ = skey3.add_assign(&keychain.secp, &skey2).unwrap(); + + // create commitments for secret keys 1, 2 and 3 + // all committing to the value 0 (which is what we do for tx_kernels) + let commit_1 = keychain.secp.commit(0, skey1).unwrap(); + let commit_2 = keychain.secp.commit(0, skey2).unwrap(); + let commit_3 = keychain.secp.commit(0, skey3).unwrap(); + + // now sum commitments for keys 1 and 2 + let sum = keychain.secp.commit_sum( + vec![commit_1.clone(), commit_2.clone()], + vec![], + ).unwrap(); + + // confirm the commitment for key 3 matches the sum of the commitments 1 and 2 + assert_eq!(sum, commit_3); + + // now check we can sum keys up using keychain.blind_sum() + // in the same way (convenience function) + assert_eq!( + keychain.blind_sum(&BlindSum::new() + .add_blinding_factor(BlindingFactor::new(skey1)) + .add_blinding_factor(BlindingFactor::new(skey2)) + ).unwrap(), + BlindingFactor::new(skey3), + ); + } }