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
This commit is contained in:
cygnet 2023-08-23 00:32:34 +02:00 committed by GitHub
parent eaef44177a
commit 97c749b0d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 15 deletions

View File

@ -1,7 +1,7 @@
[package]
name = "silentpayments"
version = "0.1.0"
authors = "cygnet <cygnet3@proton.me>"
authors = ["cygnet <cygnet3@proton.me>"]
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"

View File

@ -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;

View File

@ -103,7 +103,7 @@ impl Into<String> 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<String> 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<String>,
@ -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<PublicKey> {
let address: SilentPaymentAddress = silent_payment_address.try_into()?;
Ok(address.scan_pubkey)

View File

@ -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<Sca
Ok(Scalar::from_be_bytes(sha256(&bytes))?)
}
#[cfg(feature = "receiving")]
pub(crate) fn insert_new_key(
mut new_privkey: SecretKey,
my_outputs: &mut HashMap<Label, HashSet<SecretKey>>,

View File

@ -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<String> = 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<String> = 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