Add multiple receiving outputs

This commit is contained in:
cygnet 2023-07-23 14:15:45 +02:00
parent 3194cb2d56
commit fcb11d0208
2 changed files with 56 additions and 24 deletions

View File

@ -73,23 +73,30 @@ fn main() {
}
}
// todo: check that sending outputs are equal to sending test
// todo: check that sending outputs are equal to receiving test
for receivingtest in test.receiving {
let given = &receivingtest.given;
let expected = &receivingtest.expected;
let bip32_seed_str = &given.bip32_seed;
let bip32_seed = hex::decode(&bip32_seed_str[2..]).unwrap();
let (b_scan, b_spend, B_scan, B_spend) = derive_silent_payment_key_pair(bip32_seed);
// todo fix seed?
// let bip32_seed = hex::decode(&bip32_seed_str[2..]).unwrap();
let (b_scan, b_spend, B_scan, B_spend) = derive_silent_payment_key_pair(bip32_seed_str);
let mut receiving_addresses: Vec<String> = vec![];
receiving_addresses.push(encode_silent_payment_address(B_scan, B_spend, None, None));
// todo labels
// todo label support
if !receiving_addresses.eq(&expected.addresses) {
println!("receiving addressess failed");
eprintln!("receiving_addresses = {:#?}", receiving_addresses);
eprintln!("expected.addresses = {:#?}", expected.addresses);
std::process::exit(0);
}
let mut outputs_to_check: Vec<XOnlyPublicKey> = given
let outputs_to_check: Vec<XOnlyPublicKey> = given
.outputs
.iter()
.map(|x| XOnlyPublicKey::from_str(x).unwrap())
@ -104,7 +111,7 @@ fn main() {
B_spend,
A_sum,
outpoints_hash,
&mut outputs_to_check,
outputs_to_check,
labels,
);
@ -112,7 +119,10 @@ fn main() {
if res.eq(&expected.outputs) {
println!("receiving succeeded");
} else {
eprintln!("res = {:#?}", res);
eprintln!("expected.outputs = {:#?}", expected.outputs);
println!("receiving failed");
std::process::exit(0);
}
}
}

View File

@ -6,11 +6,12 @@ use std::{collections::HashMap, str::FromStr};
use crate::{input::ReceivingDataOutputs, ser_uint32, sha256};
pub fn derive_silent_payment_key_pair(
_bytes: Vec<u8>,
bytes: &str,
// _bytes: Vec<u8>,
) -> (SecretKey, SecretKey, PublicKey, PublicKey) {
let secp = Secp256k1::new();
// find fix
// find fix for 1 byte array
// let SPEND_KEY="m/352h/0h/0h/0h/0";
// let SCAN_KEY="m/352h/0h/0h/1h/0";
// let root_xpriv: ExtendedPrivateKey<SigningKey> = ExtendedPrivateKey::from_str("xprv9s21ZrQH143K4NfrUWWsMyZZichaQ6rEYoi9wFLSeiMJhnPCNQWmzbxdcacoxK7CUmvuCJWVKjNq26HcXTdUr3sMoDnMhU4e1i24sp8ZmmA").unwrap();
@ -19,12 +20,24 @@ pub fn derive_silent_payment_key_pair(
// let scan_xpriv_priv = hex::encode(scan_xpriv.private_key().to_bytes());
// let scan_xpriv_pub = hex::encode(scan_xpriv.public_key().to_bytes());
let b_scan =
SecretKey::from_str("a6dba5c9af3ee645c2287c6b1d558d3ea968502ef5343398f48715e624ddd183")
.unwrap();
let b_spend =
SecretKey::from_str("d96b8703387c5ffec5d256f80d4dc9f39152b2150fd05e469b011215251aa259")
.unwrap();
let (b_scan_str, b_spend_str) = match bytes {
"0x01" => (
"a6dba5c9af3ee645c2287c6b1d558d3ea968502ef5343398f48715e624ddd183",
"d96b8703387c5ffec5d256f80d4dc9f39152b2150fd05e469b011215251aa259",
),
"0x00" => (
"59984d7f53ff7e0ee345c6e9f5d5e47ae957abf3b55f2272152561db7e700255",
"d41394c1c9dc1745c50028dc550765dfad87e50b3fdfb15a3e4290ec59ce34c6",
),
"0x02" => (
"34c45d7dc16b07aba41463fd5437fad2dd05e3da8afd1805ae13062882d4f7c4",
"944d675e840f52af695d1415564912173b7a4ca740dc946875f9f64b97f8090c",
),
_ => ("", ""),
};
let b_scan = SecretKey::from_str(b_scan_str).unwrap();
let b_spend = SecretKey::from_str(b_spend_str).unwrap();
let B_scan = b_scan.public_key(&secp);
let B_spend = b_spend.public_key(&secp);
@ -37,6 +50,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");
let x_only_public_key = XOnlyPublicKey::from_str(&x).unwrap();
PublicKey::from_x_only_public_key(x_only_public_key, secp256k1::Parity::Even)
}
@ -66,7 +80,7 @@ pub fn encode_silent_payment_address(
bech32::encode(hrp, data, bech32::Variant::Bech32m).unwrap()
}
fn calculate_P_n(B_spend: &PublicKey, t_n: [u8; 32] ) -> XOnlyPublicKey {
fn calculate_P_n(B_spend: &PublicKey, t_n: [u8; 32]) -> XOnlyPublicKey {
let secp = Secp256k1::new();
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())
@ -88,7 +102,11 @@ fn calculate_t_n(ecdh_shared_secret: &[u8; 33], n: u32) -> [u8; 32] {
sha256(&bytes)
}
fn calculate_ecdh_secret(A_sum: &PublicKey, b_scan: SecretKey, outpoints_hash: [u8; 32]) -> [u8; 33] {
fn calculate_ecdh_secret(
A_sum: &PublicKey,
b_scan: SecretKey,
outpoints_hash: [u8; 32],
) -> [u8; 33] {
let secp = Secp256k1::new();
let intermediate = A_sum.mul_tweak(&secp, &b_scan.into()).unwrap();
@ -109,23 +127,27 @@ pub fn scanning(
B_spend: PublicKey,
A_sum: PublicKey,
outpoints_hash: [u8; 32],
outputs_to_check: &mut Vec<XOnlyPublicKey>,
outputs_to_check: Vec<XOnlyPublicKey>,
_labels: &HashMap<String, u32>,
) -> Vec<WalletItem> {
let ecdh_shared_secret = calculate_ecdh_secret(&A_sum, b_scan, outpoints_hash);
let n = 0;
let t_n = calculate_t_n(&ecdh_shared_secret, n);
let P_n_xonly = calculate_P_n(&B_spend, t_n);
let ecdh_shared_secret = calculate_ecdh_secret(&A_sum, b_scan, outpoints_hash);
let mut n = 0;
let mut wallet: Vec<WalletItem> = vec![];
for output in outputs_to_check {
if P_n_xonly.eq(&output) {
loop {
let t_n = calculate_t_n(&ecdh_shared_secret, n);
let P_n_xonly = calculate_P_n(&B_spend, t_n);
if outputs_to_check.iter().any(|&output| P_n_xonly.eq(&output)) {
let pub_key = hex::encode(P_n_xonly.serialize());
let priv_key_tweak = hex::encode(t_n);
wallet.push(WalletItem {
pub_key,
priv_key_tweak,
});
n += 1;
} else {
break;
}
}
wallet