Add create_labeled_silent_payment_address function

This commit is contained in:
cygnet 2023-07-23 14:15:45 +02:00
parent fcb11d0208
commit 2d55f9fa49
5 changed files with 92 additions and 16 deletions

37
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bech32"
version = "0.9.1"
@ -41,6 +47,36 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a"
[[package]]
name = "num-bigint"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "proc-macro2"
version = "1.0.63"
@ -121,6 +157,7 @@ version = "0.1.0"
dependencies = [
"bech32",
"hex",
"num-bigint",
"secp256k1",
"serde",
"serde_json",

View File

@ -15,3 +15,4 @@ serde_json = "1.0"
hex = "0.4"
bech32 = "0.9"
# bip32 = { version = "0.5", features = ["alloc"] }
num-bigint = "0.4.0"

View File

@ -1,3 +1,4 @@
use num_bigint::BigUint;
use serde::Deserialize;
use serde_json::{from_str, Value};
use std::hash::{Hash, Hasher};
@ -22,11 +23,11 @@ pub struct ReceivingDataGiven {
pub input_pub_keys: Vec<String>,
pub bip32_seed: String,
#[serde(deserialize_with = "empty_array_as_map")]
pub labels: HashMap<String, u32>,
pub labels: HashMap<String, BigUint>,
pub outputs: Vec<String>,
}
fn empty_array_as_map<'de, D>(deserializer: D) -> Result<HashMap<String, u32>, D::Error>
fn empty_array_as_map<'de, D>(deserializer: D) -> Result<HashMap<String, BigUint>, D::Error>
where
D: serde::Deserializer<'de>,
{
@ -41,22 +42,25 @@ where
}
}
Value::Object(map) => {
let result: HashMap<String, u32> = map
// let len = map.len();
let result: HashMap<String, BigUint> = map
.into_iter()
.map(|(k, v)| {
.filter_map(|(k, v)| {
if let Value::Number(num) = v {
num.as_i64()
.and_then(|n| u32::from_str(&n.to_string()).ok())
.and_then(|n| BigUint::from_str(&n.to_string()).ok())
.map(|n| (k, n))
} else {
None
}
})
.collect::<Option<_>>()
.ok_or(serde::de::Error::custom(
"Failed to parse map values as u32",
))?;
.collect();
// if result.len() != len {
// return Err(serde::de::Error::custom(
// "Failed to parse map values as BigUint",
// ));
// }
Ok(result)
}
_ => Err(serde::de::Error::custom("Expected map or empty array")),

View File

@ -14,8 +14,9 @@ use std::{collections::HashSet, io::Write};
use crate::{
input::ComparableHashMap,
receiving::{
derive_silent_payment_key_pair, encode_silent_payment_address, get_A_sum_public_keys,
scanning, verify_and_calculate_signatures,
create_labeled_silent_payment_address, derive_silent_payment_key_pair,
encode_silent_payment_address, get_A_sum_public_keys, scanning,
verify_and_calculate_signatures,
},
sending::create_outputs,
};
@ -70,6 +71,7 @@ fn main() {
} else {
eprintln!("sending expected = {:#?}", expected_comparable);
eprintln!("sending outputs = {:#?}", outputs_comparable);
std::process::exit(0);
}
}
@ -88,8 +90,15 @@ fn main() {
let mut receiving_addresses: Vec<String> = vec![];
receiving_addresses.push(encode_silent_payment_address(B_scan, B_spend, None, None));
// todo label support
if !receiving_addresses.eq(&expected.addresses) {
for (_, label) in &given.labels {
receiving_addresses.push(create_labeled_silent_payment_address(
B_scan, B_spend, label, None, None,
));
}
let set1: HashSet<_> = receiving_addresses.iter().collect();
let set2: HashSet<_> = expected.addresses.iter().collect();
if !set1.eq(&set2) {
println!("receiving addressess failed");
eprintln!("receiving_addresses = {:#?}", receiving_addresses);
eprintln!("expected.addresses = {:#?}", expected.addresses);
@ -105,7 +114,6 @@ fn main() {
let outpoints_hash = hash_outpoints(&given.outpoints);
let A_sum = get_A_sum_public_keys(&given.input_pub_keys);
let labels = &given.labels;
let mut add_to_wallet = scanning(
b_scan,
B_spend,

View File

@ -1,5 +1,6 @@
use bech32::ToBase32;
use num_bigint::BigUint;
use secp256k1::{hashes::Hash, Message, PublicKey, Scalar, Secp256k1, SecretKey, XOnlyPublicKey};
use std::{collections::HashMap, str::FromStr};
@ -50,7 +51,7 @@ pub fn get_A_sum_public_keys(input: &Vec<String>) -> PublicKey {
.map(|x| match PublicKey::from_str(&x) {
Ok(key) => key,
Err(_) => {
println!("using x only public key with even pairing");
// println!("using x only public key with even pairing");
let x_only_public_key = XOnlyPublicKey::from_str(&x).unwrap();
PublicKey::from_x_only_public_key(x_only_public_key, secp256k1::Parity::Even)
}
@ -80,6 +81,31 @@ pub fn encode_silent_payment_address(
bech32::encode(hrp, data, bech32::Variant::Bech32m).unwrap()
}
pub fn create_labeled_silent_payment_address(
B_scan: PublicKey,
B_spend: PublicKey,
m: &BigUint,
hrp: Option<&str>,
version: Option<u8>,
) -> String {
let bytes = m.to_bytes_be();
let mut array = [0u8; 32];
let start = array.len() - bytes.len();
array[start..].copy_from_slice(&bytes);
let scalar = Scalar::from_be_bytes(array).unwrap();
let secp = Secp256k1::new();
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())
.unwrap()
.public_key(&secp);
let intermediate = G.mul_tweak(&secp, &scalar).unwrap();
let B_m = intermediate.combine(&B_spend).unwrap();
encode_silent_payment_address(B_scan, B_m, hrp, version)
}
fn calculate_P_n(B_spend: &PublicKey, t_n: [u8; 32]) -> XOnlyPublicKey {
let secp = Secp256k1::new();
@ -128,7 +154,7 @@ pub fn scanning(
A_sum: PublicKey,
outpoints_hash: [u8; 32],
outputs_to_check: Vec<XOnlyPublicKey>,
_labels: &HashMap<String, u32>,
_labels: &HashMap<String, BigUint>,
) -> Vec<WalletItem> {
let ecdh_shared_secret = calculate_ecdh_secret(&A_sum, b_scan, outpoints_hash);
let mut n = 0;