8 remove all unwrap (#9)
* Remove all unwraps from sending * Remove unwraps from receiving * Move Result type to utils
This commit is contained in:
parent
a7001e4a3d
commit
ad2c5b0e72
|
@ -1,4 +1,4 @@
|
||||||
#![allow(non_snake_case, dead_code)]
|
#![allow(non_snake_case)]
|
||||||
pub mod receiving;
|
pub mod receiving;
|
||||||
pub mod sending;
|
pub mod sending;
|
||||||
pub mod structs;
|
pub mod structs;
|
||||||
|
|
111
src/receiving.rs
111
src/receiving.rs
|
@ -5,40 +5,31 @@ use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
structs::{OutputWithSignature, ScannedOutput},
|
structs::{OutputWithSignature, ScannedOutput},
|
||||||
utils::ser_uint32,
|
utils::{ser_uint32, Result},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn get_receiving_addresses(
|
pub fn get_receiving_addresses(
|
||||||
B_scan: PublicKey,
|
B_scan: PublicKey,
|
||||||
B_spend: PublicKey,
|
B_spend: PublicKey,
|
||||||
labels: &HashMap<String, String>,
|
labels: &HashMap<String, String>,
|
||||||
) -> Vec<String> {
|
) -> Result<Vec<String>> {
|
||||||
let mut receiving_addresses: Vec<String> = vec![];
|
let mut receiving_addresses: Vec<String> = vec![];
|
||||||
receiving_addresses.push(encode_silent_payment_address(B_scan, B_spend, None, None));
|
receiving_addresses.push(encode_silent_payment_address(B_scan, B_spend, None, None)?);
|
||||||
for (_, label) in labels {
|
for (_, label) in labels {
|
||||||
receiving_addresses.push(create_labeled_silent_payment_address(
|
receiving_addresses.push(create_labeled_silent_payment_address(
|
||||||
B_scan, B_spend, label, None, None,
|
B_scan, B_spend, label, None, None,
|
||||||
));
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiving_addresses
|
Ok(receiving_addresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_A_sum_public_keys(input: &Vec<String>) -> PublicKey {
|
pub fn get_A_sum_public_keys(
|
||||||
let keys: Vec<PublicKey> = input
|
input: &Vec<PublicKey>,
|
||||||
.iter()
|
) -> std::result::Result<PublicKey, secp256k1::Error> {
|
||||||
.map(|x| match PublicKey::from_str(&x) {
|
let keys_refs: &Vec<&PublicKey> = &input.iter().collect();
|
||||||
Ok(key) => key,
|
|
||||||
Err(_) => {
|
|
||||||
// we always assume even pairing for input public keys if they are omitted
|
|
||||||
let x_only_public_key = XOnlyPublicKey::from_str(&x).unwrap();
|
|
||||||
PublicKey::from_x_only_public_key(x_only_public_key, secp256k1::Parity::Even)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let keys_refs: Vec<&PublicKey> = keys.iter().collect();
|
|
||||||
|
|
||||||
PublicKey::combine_keys(&keys_refs).unwrap()
|
PublicKey::combine_keys(keys_refs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_silent_payment_address(
|
fn encode_silent_payment_address(
|
||||||
|
@ -46,9 +37,9 @@ fn encode_silent_payment_address(
|
||||||
B_m: PublicKey,
|
B_m: PublicKey,
|
||||||
hrp: Option<&str>,
|
hrp: Option<&str>,
|
||||||
version: Option<u8>,
|
version: Option<u8>,
|
||||||
) -> String {
|
) -> Result<String> {
|
||||||
let hrp = hrp.unwrap_or("sp");
|
let hrp = hrp.unwrap_or("sp");
|
||||||
let version = bech32::u5::try_from_u8(version.unwrap_or(0)).unwrap();
|
let version = bech32::u5::try_from_u8(version.unwrap_or(0))?;
|
||||||
|
|
||||||
let B_scan_bytes = B_scan.serialize();
|
let B_scan_bytes = B_scan.serialize();
|
||||||
let B_m_bytes = B_m.serialize();
|
let B_m_bytes = B_m.serialize();
|
||||||
|
@ -57,7 +48,7 @@ fn encode_silent_payment_address(
|
||||||
|
|
||||||
data.insert(0, version);
|
data.insert(0, version);
|
||||||
|
|
||||||
bech32::encode(hrp, data, bech32::Variant::Bech32m).unwrap()
|
Ok(bech32::encode(hrp, data, bech32::Variant::Bech32m)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_labeled_silent_payment_address(
|
fn create_labeled_silent_payment_address(
|
||||||
|
@ -66,32 +57,26 @@ fn create_labeled_silent_payment_address(
|
||||||
m: &String,
|
m: &String,
|
||||||
hrp: Option<&str>,
|
hrp: Option<&str>,
|
||||||
version: Option<u8>,
|
version: Option<u8>,
|
||||||
) -> String {
|
) -> Result<String> {
|
||||||
let bytes = hex::decode(m).unwrap().try_into().unwrap();
|
let bytes: [u8; 32] = hex::decode(m)?.as_slice().try_into()?;
|
||||||
|
|
||||||
let scalar = Scalar::from_be_bytes(bytes).unwrap();
|
let scalar = Scalar::from_be_bytes(bytes)?;
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())
|
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())?.public_key(&secp);
|
||||||
.unwrap()
|
let intermediate = G.mul_tweak(&secp, &scalar)?;
|
||||||
.public_key(&secp);
|
let B_m = intermediate.combine(&B_spend)?;
|
||||||
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)
|
encode_silent_payment_address(B_scan, B_m, hrp, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_P_n(B_spend: &PublicKey, t_n: [u8; 32]) -> PublicKey {
|
fn calculate_P_n(B_spend: &PublicKey, t_n: [u8; 32]) -> Result<PublicKey> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())
|
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())?.public_key(&secp);
|
||||||
.unwrap()
|
let intermediate = G.mul_tweak(&secp, &Scalar::from_be_bytes(t_n)?)?;
|
||||||
.public_key(&secp);
|
let P_n = intermediate.combine(&B_spend)?;
|
||||||
let intermediate = G
|
|
||||||
.mul_tweak(&secp, &Scalar::from_be_bytes(t_n).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
let P_n = intermediate.combine(&B_spend).unwrap();
|
|
||||||
|
|
||||||
P_n
|
Ok(P_n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_t_n(ecdh_shared_secret: &[u8; 33], n: u32) -> [u8; 32] {
|
fn calculate_t_n(ecdh_shared_secret: &[u8; 33], n: u32) -> [u8; 32] {
|
||||||
|
@ -105,14 +90,14 @@ fn calculate_ecdh_secret(
|
||||||
A_sum: &PublicKey,
|
A_sum: &PublicKey,
|
||||||
b_scan: SecretKey,
|
b_scan: SecretKey,
|
||||||
outpoints_hash: [u8; 32],
|
outpoints_hash: [u8; 32],
|
||||||
) -> [u8; 33] {
|
) -> Result<[u8; 33]> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let intermediate = A_sum.mul_tweak(&secp, &b_scan.into()).unwrap();
|
let intermediate = A_sum.mul_tweak(&secp, &b_scan.into())?;
|
||||||
let scalar = Scalar::from_be_bytes(outpoints_hash).unwrap();
|
let scalar = Scalar::from_be_bytes(outpoints_hash)?;
|
||||||
let ecdh_shared_secret = intermediate.mul_tweak(&secp, &scalar).unwrap().serialize();
|
let ecdh_shared_secret = intermediate.mul_tweak(&secp, &scalar)?.serialize();
|
||||||
|
|
||||||
ecdh_shared_secret
|
Ok(ecdh_shared_secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scanning(
|
pub fn scanning(
|
||||||
|
@ -122,9 +107,9 @@ pub fn scanning(
|
||||||
outpoints_hash: [u8; 32],
|
outpoints_hash: [u8; 32],
|
||||||
outputs_to_check: Vec<XOnlyPublicKey>,
|
outputs_to_check: Vec<XOnlyPublicKey>,
|
||||||
labels: Option<&HashMap<String, String>>,
|
labels: Option<&HashMap<String, String>>,
|
||||||
) -> Vec<ScannedOutput> {
|
) -> Result<Vec<ScannedOutput>> {
|
||||||
let secp = secp256k1::Secp256k1::new();
|
let secp = secp256k1::Secp256k1::new();
|
||||||
let ecdh_shared_secret = calculate_ecdh_secret(&A_sum, b_scan, outpoints_hash);
|
let ecdh_shared_secret = calculate_ecdh_secret(&A_sum, b_scan, outpoints_hash)?;
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut wallet: Vec<ScannedOutput> = vec![];
|
let mut wallet: Vec<ScannedOutput> = vec![];
|
||||||
|
|
||||||
|
@ -132,7 +117,7 @@ pub fn scanning(
|
||||||
while found {
|
while found {
|
||||||
found = false;
|
found = false;
|
||||||
let t_n = calculate_t_n(&ecdh_shared_secret, n);
|
let t_n = calculate_t_n(&ecdh_shared_secret, n);
|
||||||
let P_n = calculate_P_n(&B_spend, t_n);
|
let P_n = calculate_P_n(&B_spend, t_n)?;
|
||||||
let (P_n_xonly, _) = P_n.x_only_public_key();
|
let (P_n_xonly, _) = P_n.x_only_public_key();
|
||||||
if outputs_to_check.iter().any(|&output| output.eq(&P_n_xonly)) {
|
if outputs_to_check.iter().any(|&output| output.eq(&P_n_xonly)) {
|
||||||
let pub_key = hex::encode(P_n_xonly.serialize());
|
let pub_key = hex::encode(P_n_xonly.serialize());
|
||||||
|
@ -149,23 +134,19 @@ pub fn scanning(
|
||||||
let output_even = output.public_key(secp256k1::Parity::Even);
|
let output_even = output.public_key(secp256k1::Parity::Even);
|
||||||
let output_odd = output.public_key(secp256k1::Parity::Odd);
|
let output_odd = output.public_key(secp256k1::Parity::Odd);
|
||||||
|
|
||||||
let m_G_sub_even = output_even.combine(&P_n_negated).unwrap();
|
let m_G_sub_even = output_even.combine(&P_n_negated)?;
|
||||||
let m_G_sub_odd = output_odd.combine(&P_n_negated).unwrap();
|
let m_G_sub_odd = output_odd.combine(&P_n_negated)?;
|
||||||
let keys: Vec<PublicKey> = vec![m_G_sub_even, m_G_sub_odd];
|
let keys: Vec<PublicKey> = vec![m_G_sub_even, m_G_sub_odd];
|
||||||
for labelkeystr in labels.keys() {
|
for labelkeystr in labels.keys() {
|
||||||
let labelkey = PublicKey::from_str(labelkeystr).unwrap();
|
let labelkey = PublicKey::from_str(labelkeystr)?;
|
||||||
if keys.iter().any(|x| x.eq(&labelkey)) {
|
if keys.iter().any(|x| x.eq(&labelkey)) {
|
||||||
let P_nm = hex::encode(output.serialize());
|
let P_nm = hex::encode(output.serialize());
|
||||||
let label = labels.get(labelkeystr).unwrap();
|
let label = labels.get(labelkeystr).unwrap();
|
||||||
let label_bytes = hex::decode(label).unwrap().try_into().unwrap();
|
let label_bytes = hex::decode(label)?.as_slice().try_into()?;
|
||||||
let label_scalar = Scalar::from_be_bytes(label_bytes).unwrap();
|
let label_scalar = Scalar::from_be_bytes(label_bytes)?;
|
||||||
let t_n_as_secret_key = SecretKey::from_slice(&t_n).unwrap();
|
let t_n_as_secret_key = SecretKey::from_slice(&t_n)?;
|
||||||
let priv_key_tweak = hex::encode(
|
let priv_key_tweak =
|
||||||
t_n_as_secret_key
|
hex::encode(t_n_as_secret_key.add_tweak(&label_scalar)?.secret_bytes());
|
||||||
.add_tweak(&label_scalar)
|
|
||||||
.unwrap()
|
|
||||||
.secret_bytes(),
|
|
||||||
);
|
|
||||||
wallet.push(ScannedOutput {
|
wallet.push(ScannedOutput {
|
||||||
pub_key: P_nm,
|
pub_key: P_nm,
|
||||||
priv_key_tweak,
|
priv_key_tweak,
|
||||||
|
@ -177,23 +158,23 @@ pub fn scanning(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wallet
|
Ok(wallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_and_calculate_signatures(
|
pub fn verify_and_calculate_signatures(
|
||||||
add_to_wallet: &mut Vec<ScannedOutput>,
|
add_to_wallet: &mut Vec<ScannedOutput>,
|
||||||
b_spend: SecretKey,
|
b_spend: SecretKey,
|
||||||
) -> Result<Vec<OutputWithSignature>, secp256k1::Error> {
|
) -> Result<Vec<OutputWithSignature>> {
|
||||||
let secp = secp256k1::Secp256k1::new();
|
let secp = secp256k1::Secp256k1::new();
|
||||||
let msg = Message::from_hashed_data::<secp256k1::hashes::sha256::Hash>(b"message");
|
let msg = Message::from_hashed_data::<secp256k1::hashes::sha256::Hash>(b"message");
|
||||||
let aux = secp256k1::hashes::sha256::Hash::hash(b"random auxiliary data").to_byte_array();
|
let aux = secp256k1::hashes::sha256::Hash::hash(b"random auxiliary data").to_byte_array();
|
||||||
|
|
||||||
let mut res: Vec<OutputWithSignature> = vec![];
|
let mut res: Vec<OutputWithSignature> = vec![];
|
||||||
for output in add_to_wallet {
|
for output in add_to_wallet {
|
||||||
let pubkey = XOnlyPublicKey::from_str(&output.pub_key).unwrap();
|
let pubkey = XOnlyPublicKey::from_str(&output.pub_key)?;
|
||||||
let tweak = hex::decode(&output.priv_key_tweak).unwrap();
|
let tweak: [u8; 32] = hex::decode(&output.priv_key_tweak)?.as_slice().try_into()?;
|
||||||
let scalar = Scalar::from_be_bytes(tweak.try_into().unwrap()).unwrap();
|
let scalar = Scalar::from_be_bytes(tweak)?;
|
||||||
let mut full_priv_key = b_spend.add_tweak(&scalar).unwrap();
|
let mut full_priv_key = b_spend.add_tweak(&scalar)?;
|
||||||
|
|
||||||
let (_, parity) = full_priv_key.x_only_public_key(&secp);
|
let (_, parity) = full_priv_key.x_only_public_key(&secp);
|
||||||
|
|
||||||
|
|
|
@ -1,66 +1,64 @@
|
||||||
use bech32::FromBase32;
|
use bech32::FromBase32;
|
||||||
|
|
||||||
use secp256k1::{Parity, PublicKey, Scalar, Secp256k1, SecretKey};
|
use secp256k1::{Parity, PublicKey, Scalar, Secp256k1, SecretKey};
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::utils::{hash_outpoints, ser_uint32, sha256};
|
use crate::utils::{hash_outpoints, ser_uint32, sha256, Result};
|
||||||
|
|
||||||
fn get_a_sum_secret_keys(input: &Vec<(String, bool)>) -> SecretKey {
|
fn get_a_sum_secret_keys(input: &Vec<(SecretKey, bool)>) -> Result<SecretKey> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let mut negated_keys: Vec<SecretKey> = vec![];
|
let mut negated_keys: Vec<SecretKey> = vec![];
|
||||||
|
|
||||||
for (keystr, is_xonly) in input {
|
for (key, x_only) in input {
|
||||||
let key = SecretKey::from_str(&keystr).unwrap();
|
|
||||||
let (_, parity) = key.x_only_public_key(&secp);
|
let (_, parity) = key.x_only_public_key(&secp);
|
||||||
|
|
||||||
if *is_xonly && parity == Parity::Odd {
|
if *x_only && parity == Parity::Odd {
|
||||||
negated_keys.push(key.negate());
|
negated_keys.push(key.negate());
|
||||||
} else {
|
} else {
|
||||||
negated_keys.push(key);
|
negated_keys.push(*key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (head, tail) = negated_keys.split_first().unwrap();
|
let (head, tail) = negated_keys.split_first().ok_or("Empty input list")?;
|
||||||
|
|
||||||
let result: SecretKey = tail
|
let result: Result<SecretKey> = tail
|
||||||
.iter()
|
.iter()
|
||||||
.fold(*head, |acc, &item| acc.add_tweak(&item.into()).unwrap());
|
.fold(Ok(*head), |acc: Result<SecretKey>, &item| {
|
||||||
|
Ok(acc?.add_tweak(&item.into())?)
|
||||||
|
});
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_silent_payment_address(addr: &str) -> (PublicKey, PublicKey) {
|
fn decode_silent_payment_address(addr: &str) -> Result<(PublicKey, PublicKey)> {
|
||||||
let (_hrp, data, _variant) = bech32::decode(&addr).unwrap();
|
let (_hrp, data, _variant) = bech32::decode(&addr)?;
|
||||||
|
|
||||||
let data = Vec::<u8>::from_base32(&data[1..]).unwrap();
|
let data = Vec::<u8>::from_base32(&data[1..])?;
|
||||||
|
|
||||||
let B_scan = PublicKey::from_slice(&data[..33]).unwrap();
|
let B_scan = PublicKey::from_slice(&data[..33])?;
|
||||||
let B_spend = PublicKey::from_slice(&data[33..]).unwrap();
|
let B_spend = PublicKey::from_slice(&data[33..])?;
|
||||||
|
|
||||||
(B_scan, B_spend)
|
Ok((B_scan, B_spend))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_outputs(
|
pub fn create_outputs(
|
||||||
outpoints: &Vec<(String, u32)>,
|
outpoints: &Vec<(String, u32)>,
|
||||||
input_priv_keys: &Vec<(String, bool)>,
|
input_priv_keys: &Vec<(SecretKey, bool)>,
|
||||||
recipients: &Vec<(String, f32)>,
|
recipients: &Vec<(String, f32)>,
|
||||||
) -> Vec<HashMap<String, f32>> {
|
) -> Result<Vec<HashMap<String, f32>>> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let outpoints_hash = hash_outpoints(outpoints);
|
let outpoints_hash = hash_outpoints(outpoints)?;
|
||||||
|
|
||||||
let a_sum = get_a_sum_secret_keys(input_priv_keys);
|
let a_sum = get_a_sum_secret_keys(input_priv_keys)?;
|
||||||
|
|
||||||
let mut silent_payment_groups: HashMap<PublicKey, Vec<(PublicKey, f32)>> = HashMap::new();
|
let mut silent_payment_groups: HashMap<PublicKey, Vec<(PublicKey, f32)>> = HashMap::new();
|
||||||
for (payment_address, amount) in recipients {
|
for (payment_address, amount) in recipients {
|
||||||
let (B_scan, B_m) = decode_silent_payment_address(&payment_address);
|
let (B_scan, B_m) = decode_silent_payment_address(&payment_address)?;
|
||||||
|
|
||||||
if silent_payment_groups.contains_key(&B_scan) {
|
if let Some(payments) = silent_payment_groups.get_mut(&B_scan) {
|
||||||
silent_payment_groups
|
payments.push((B_m, *amount));
|
||||||
.get_mut(&B_scan)
|
|
||||||
.unwrap()
|
|
||||||
.push((B_m, *amount));
|
|
||||||
} else {
|
} else {
|
||||||
silent_payment_groups.insert(B_scan, vec![(B_m, *amount)]);
|
silent_payment_groups.insert(B_scan, vec![(B_m, *amount)]);
|
||||||
}
|
}
|
||||||
|
@ -71,9 +69,9 @@ pub fn create_outputs(
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
|
|
||||||
//calculate shared secret
|
//calculate shared secret
|
||||||
let intermediate = B_scan.mul_tweak(&secp, &a_sum.into()).unwrap();
|
let intermediate = B_scan.mul_tweak(&secp, &a_sum.into())?;
|
||||||
let scalar = Scalar::from_be_bytes(outpoints_hash).unwrap();
|
let scalar = Scalar::from_be_bytes(outpoints_hash)?;
|
||||||
let ecdh_shared_secret = intermediate.mul_tweak(&secp, &scalar).unwrap().serialize();
|
let ecdh_shared_secret = intermediate.mul_tweak(&secp, &scalar)?.serialize();
|
||||||
|
|
||||||
for (B_m, amount) in B_m_values {
|
for (B_m, amount) in B_m_values {
|
||||||
let mut bytes: Vec<u8> = Vec::new();
|
let mut bytes: Vec<u8> = Vec::new();
|
||||||
|
@ -81,15 +79,10 @@ pub fn create_outputs(
|
||||||
bytes.extend_from_slice(&ser_uint32(n));
|
bytes.extend_from_slice(&ser_uint32(n));
|
||||||
|
|
||||||
let t_n = sha256(&bytes);
|
let t_n = sha256(&bytes);
|
||||||
// eprintln!("t_n = {:?}", hex::encode(t_n));
|
|
||||||
|
|
||||||
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())
|
let G: PublicKey = SecretKey::from_slice(&Scalar::ONE.to_be_bytes())?.public_key(&secp);
|
||||||
.unwrap()
|
let res = G.mul_tweak(&secp, &Scalar::from_be_bytes(t_n)?)?;
|
||||||
.public_key(&secp);
|
let reskey = res.combine(&B_m)?;
|
||||||
let res = G
|
|
||||||
.mul_tweak(&secp, &Scalar::from_be_bytes(t_n).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
let reskey = res.combine(&B_m).unwrap();
|
|
||||||
let (reskey_xonly, _) = reskey.x_only_public_key();
|
let (reskey_xonly, _) = reskey.x_only_public_key();
|
||||||
|
|
||||||
let mut toAdd: HashMap<String, f32> = HashMap::new();
|
let mut toAdd: HashMap<String, f32> = HashMap::new();
|
||||||
|
@ -100,5 +93,5 @@ pub fn create_outputs(
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
10
src/utils.rs
10
src/utils.rs
|
@ -3,6 +3,8 @@ use std::io::Write;
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
use secp256k1::hashes::{sha256, Hash};
|
use secp256k1::hashes::{sha256, Hash};
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
pub fn sha256(message: &[u8]) -> [u8; 32] {
|
pub fn sha256(message: &[u8]) -> [u8; 32] {
|
||||||
sha256::Hash::hash(message).to_byte_array()
|
sha256::Hash::hash(message).to_byte_array()
|
||||||
}
|
}
|
||||||
|
@ -11,11 +13,11 @@ pub fn ser_uint32(u: u32) -> Vec<u8> {
|
||||||
u.to_be_bytes().into()
|
u.to_be_bytes().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_outpoints(sending_data: &Vec<(String, u32)>) -> [u8; 32] {
|
pub fn hash_outpoints(sending_data: &Vec<(String, u32)>) -> Result<[u8; 32]> {
|
||||||
let mut outpoints: Vec<Vec<u8>> = vec![];
|
let mut outpoints: Vec<Vec<u8>> = vec![];
|
||||||
|
|
||||||
for (txid_str, vout) in sending_data {
|
for (txid_str, vout) in sending_data {
|
||||||
let mut txid = Vec::from_hex(txid_str).unwrap();
|
let mut txid = Vec::from_hex(txid_str)?;
|
||||||
txid.reverse();
|
txid.reverse();
|
||||||
let mut vout_bytes = vout.to_le_bytes().to_vec();
|
let mut vout_bytes = vout.to_le_bytes().to_vec();
|
||||||
txid.append(&mut vout_bytes);
|
txid.append(&mut vout_bytes);
|
||||||
|
@ -26,8 +28,8 @@ pub fn hash_outpoints(sending_data: &Vec<(String, u32)>) -> [u8; 32] {
|
||||||
let mut engine = sha256::HashEngine::default();
|
let mut engine = sha256::HashEngine::default();
|
||||||
|
|
||||||
for v in outpoints {
|
for v in outpoints {
|
||||||
engine.write_all(&v).unwrap();
|
engine.write_all(&v)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256::Hash::from_engine(engine).to_byte_array()
|
Ok(sha256::Hash::from_engine(engine).to_byte_array())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use silentpayments::utils;
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{collections::HashSet, str::FromStr};
|
use std::{collections::HashSet, str::FromStr};
|
||||||
|
|
||||||
use secp256k1::XOnlyPublicKey;
|
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::input::{self, get_testing_silent_payment_key_pair, ComparableHashMap, TestData},
|
common::input::{self, get_testing_silent_payment_key_pair, ComparableHashMap, TestData},
|
||||||
|
@ -40,8 +40,14 @@ mod tests {
|
||||||
let expected_comparable: HashSet<ComparableHashMap> =
|
let expected_comparable: HashSet<ComparableHashMap> =
|
||||||
expected.outputs.into_iter().map(|x| x.into()).collect();
|
expected.outputs.into_iter().map(|x| x.into()).collect();
|
||||||
|
|
||||||
|
let input_priv_keys: Vec<(SecretKey, bool)> = given
|
||||||
|
.input_priv_keys
|
||||||
|
.iter()
|
||||||
|
.map(|(keystr, x_only)| (SecretKey::from_str(&keystr).unwrap(), *x_only))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let outputs =
|
let outputs =
|
||||||
create_outputs(&given.outpoints, &given.input_priv_keys, &given.recipients);
|
create_outputs(&given.outpoints, &input_priv_keys, &given.recipients).unwrap();
|
||||||
|
|
||||||
for map in &outputs {
|
for map in &outputs {
|
||||||
for key in map.keys() {
|
for key in map.keys() {
|
||||||
|
@ -68,7 +74,8 @@ mod tests {
|
||||||
let (b_scan, b_spend, B_scan, B_spend) =
|
let (b_scan, b_spend, B_scan, B_spend) =
|
||||||
get_testing_silent_payment_key_pair(&given.bip32_seed);
|
get_testing_silent_payment_key_pair(&given.bip32_seed);
|
||||||
|
|
||||||
let receiving_addresses = get_receiving_addresses(B_scan, B_spend, &given.labels);
|
let receiving_addresses =
|
||||||
|
get_receiving_addresses(B_scan, B_spend, &given.labels).unwrap();
|
||||||
|
|
||||||
let set1: HashSet<_> = receiving_addresses.iter().collect();
|
let set1: HashSet<_> = receiving_addresses.iter().collect();
|
||||||
let set2: HashSet<_> = expected.addresses.iter().collect();
|
let set2: HashSet<_> = expected.addresses.iter().collect();
|
||||||
|
@ -82,8 +89,26 @@ mod tests {
|
||||||
.map(|x| XOnlyPublicKey::from_str(x).unwrap())
|
.map(|x| XOnlyPublicKey::from_str(x).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let outpoints_hash = hash_outpoints(&given.outpoints);
|
let outpoints_hash = hash_outpoints(&given.outpoints).unwrap();
|
||||||
let A_sum = get_A_sum_public_keys(&given.input_pub_keys);
|
|
||||||
|
let input_pub_keys: Vec<PublicKey> = given
|
||||||
|
.input_pub_keys
|
||||||
|
.iter()
|
||||||
|
.map(|x| match PublicKey::from_str(&x) {
|
||||||
|
Ok(key) => key,
|
||||||
|
Err(_) => {
|
||||||
|
// we always assume even pairing for input public keys if they are omitted
|
||||||
|
let x_only_public_key = XOnlyPublicKey::from_str(&x).unwrap();
|
||||||
|
PublicKey::from_x_only_public_key(
|
||||||
|
x_only_public_key,
|
||||||
|
secp256k1::Parity::Even,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let A_sum = get_A_sum_public_keys(&input_pub_keys).unwrap();
|
||||||
|
|
||||||
let labels = match &given.labels.len() {
|
let labels = match &given.labels.len() {
|
||||||
0 => None,
|
0 => None,
|
||||||
_ => Some(&given.labels),
|
_ => Some(&given.labels),
|
||||||
|
@ -96,7 +121,8 @@ mod tests {
|
||||||
outpoints_hash,
|
outpoints_hash,
|
||||||
outputs_to_check,
|
outputs_to_check,
|
||||||
labels,
|
labels,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let res = verify_and_calculate_signatures(&mut add_to_wallet, b_spend).unwrap();
|
let res = verify_and_calculate_signatures(&mut add_to_wallet, b_spend).unwrap();
|
||||||
assert_eq!(res, expected.outputs);
|
assert_eq!(res, expected.outputs);
|
||||||
|
|
Loading…
Reference in New Issue