From 97c749b0d2ee9a80133a56b7c7b3b3243bc86d49 Mon Sep 17 00:00:00 2001 From: cygnet <131168104+cygnet3@users.noreply.github.com> Date: Wed, 23 Aug 2023 00:32:34 +0200 Subject: [PATCH] Add sending and receiving features (#21) * Add sending and receiving features and enable them by default * Add feature attributes in code and tests * Add serde as dev-dependency * Small improvements to sending docs --- Cargo.toml | 15 ++++++++++----- src/lib.rs | 2 ++ src/sending.rs | 19 +++++++++++++++++-- src/utils.rs | 9 +++++---- tests/vector_tests.rs | 14 ++++++++++---- 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bd775ea..3045218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "silentpayments" version = "0.1.0" -authors = "cygnet " +authors = ["cygnet "] edition = "2021" license = "MIT OR Apache-2.0" description = "A library to add silent payments support to wallets" @@ -14,11 +14,16 @@ readme = "README.md" name = "silentpayments" crate-type = ["lib"] +[features] +default = ["sending", "receiving"] +sending = [] +receiving = [] + [dependencies] -# bdk = {version = "0.20.0", features= ["all-keys"] } secp256k1 = {version = "0.24", features = ["bitcoin-hashes-std"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" hex = "0.4" bech32 = "0.9" -# bip32 = { version = "0.5", features = ["alloc"] } + +[dev-dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 2be57b5..ca240e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ #![allow(dead_code, non_snake_case)] mod error; +#[cfg(feature = "receiving")] pub mod receiving; +#[cfg(feature = "sending")] pub mod sending; mod utils; diff --git a/src/sending.rs b/src/sending.rs index 41272c7..a9b7f1b 100644 --- a/src/sending.rs +++ b/src/sending.rs @@ -103,7 +103,7 @@ impl Into for SilentPaymentAddress { /// # Arguments /// /// * `recipients` - A `Vec` of silent payment addresses to be paid. -/// * `ecdh_shared_secrets` - A HashMap that maps every scan key to a shared secret created with this scan key. +/// * `ecdh_shared_secrets` - A HashMap that maps every scan key (representing a recipient) to a shared secret. This shared secret is created using the scan key, along with the private keys of the outputs to spend. This library has no access to these private keys, so we expect the computed shared secret instead. /// /// # Returns /// @@ -115,7 +115,7 @@ impl Into for SilentPaymentAddress { /// This function will return an error if: /// /// * The recipients Vec contains a silent payment address with an incorrect format. -/// * The ecdh_shared_secrets does not contain a secret for every B_scan that are being paid to. +/// * The ecdh_shared_secrets does not contain a secret for every B_scan that is being paid to. /// * Edge cases are hit during elliptic curve computation (extremely unlikely). pub fn generate_recipient_pubkeys( recipients: Vec, @@ -167,6 +167,21 @@ pub fn generate_recipient_pubkeys( Ok(result) } +/// Helper function to retrieve the scanning public key from a bech32m-encoded silent payment address. +/// +/// # Arguments +/// +/// * `silent_payment_address` - The bech32m-encoded silent payment address to be decoded. +/// +/// # Returns +/// +/// If successful, the function returns a `Result` wrapping a `PublicKey`, the scanning public key. +/// +/// # Errors +/// +/// This function will return an error if: +/// +/// * The silent payment address has an incorrent format. pub fn decode_scan_pubkey(silent_payment_address: String) -> Result { let address: SilentPaymentAddress = silent_payment_address.try_into()?; Ok(address.scan_pubkey) diff --git a/src/utils.rs b/src/utils.rs index d51d354..b74fee1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,9 @@ use std::collections::{HashMap, HashSet}; -use crate::{ - receiving::{Label, NULL_LABEL}, - Error, Result, -}; +#[cfg(feature = "receiving")] +use crate::receiving::{Label, NULL_LABEL}; + +use crate::{Error, Result}; use secp256k1::{ hashes::{sha256, Hash}, PublicKey, Scalar, Secp256k1, SecretKey, @@ -33,6 +33,7 @@ pub(crate) fn calculate_t_n(ecdh_shared_secret: &[u8; 33], n: u32) -> Result>, diff --git a/tests/vector_tests.rs b/tests/vector_tests.rs index 02b27c1..5598859 100644 --- a/tests/vector_tests.rs +++ b/tests/vector_tests.rs @@ -9,10 +9,12 @@ mod tests { }; use secp256k1::{PublicKey, SecretKey}; - use silentpayments::{ - receiving::SilentPayment, - sending::{decode_scan_pubkey, generate_recipient_pubkeys}, - }; + + #[cfg(feature = "receiving")] + use silentpayments::receiving::SilentPayment; + + #[cfg(feature = "sending")] + use silentpayments::sending::{decode_scan_pubkey, generate_recipient_pubkeys}; use crate::common::{ structs::TestData, @@ -37,6 +39,8 @@ mod tests { fn process_test_case(test_case: TestData) { let mut sending_outputs: HashSet = HashSet::new(); eprintln!("test.comment = {:?}", test_case.comment); + + #[cfg(feature = "sending")] for sendingtest in test_case.sending { let given = sendingtest.given; @@ -75,12 +79,14 @@ mod tests { assert_eq!(sending_outputs, expected_output_addresses); } + #[cfg(feature = "receiving")] for receivingtest in test_case.receiving { let given = receivingtest.given; let mut expected = receivingtest.expected; let receiving_outputs: HashSet = given.outputs.iter().cloned().collect(); + #[cfg(feature = "sending")] // assert that the generated sending outputs are a subset // of the expected receiving outputs // i.e. all the generated outputs are present