Get the shared secret from a transaction
This commit is contained in:
parent
0f185c693f
commit
b5f3c82192
@ -1,5 +1,6 @@
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Mutex, OnceLock, PoisonError};
|
||||
|
||||
@ -11,6 +12,7 @@ use sdk_common::crypto::AnkSharedSecret;
|
||||
use serde_json::Error as SerdeJsonError;
|
||||
use shamir::SecretData;
|
||||
use sp_client::bitcoin::consensus::{deserialize, serialize};
|
||||
use sp_client::silentpayments::bitcoin_hashes::{HashEngine, sha256, Hash};
|
||||
use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError};
|
||||
use sp_client::bitcoin::secp256k1::ecdh::SharedSecret;
|
||||
use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey};
|
||||
@ -355,9 +357,9 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> {
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_outpoints_for_user(pre_id: String) -> ApiResult<outputs_list> {
|
||||
pub fn get_outpoints_for_user() -> ApiResult<outputs_list> {
|
||||
let connected_users = lock_connected_users()?;
|
||||
let user = connected_users.get(&pre_id).ok_or(ApiError {
|
||||
let (_, user) = connected_users.iter().last().ok_or(ApiError {
|
||||
message: "Can't find user".to_owned(),
|
||||
})?;
|
||||
Ok(outputs_list(user.get_all_outputs()))
|
||||
@ -395,26 +397,24 @@ pub struct createNotificationTransactionReturn {
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_notification_transaction(
|
||||
user_pre_id: String,
|
||||
recipient: String,
|
||||
message: String,
|
||||
) -> ApiResult<createNotificationTransactionReturn> {
|
||||
let sp_address: SilentPaymentAddress = recipient.try_into()?;
|
||||
|
||||
let (transaction, notification_information) =
|
||||
create_transaction_for_address(user_pre_id, sp_address, message)?;
|
||||
let (transaction, shared_point) =
|
||||
create_transaction_for_address_with_shared_secret(sp_address, message)?;
|
||||
|
||||
// The secret is an ecc point and *must* be hashed to produce a proper ecdh secret
|
||||
// The shared_point *must* be hashed to produce a proper ecdh secret
|
||||
// For now we propose to implement a tagged hash for it
|
||||
// It could be interesting to add some piece of data to allow for the derivation of multiple secrets
|
||||
let mut eng = sha256::HashEngine::default();
|
||||
eng.write_all(&shared_point);
|
||||
let shared_secret = sha256::Hash::from_engine(eng);
|
||||
|
||||
let spaddress2secret = notification_information
|
||||
.into_iter()
|
||||
.map(|(address, shared_pubkey)| {
|
||||
let shared_secret = AnkSharedSecret::new_from_public_key(shared_pubkey);
|
||||
(address.into(), shared_secret.to_string())
|
||||
})
|
||||
.collect();
|
||||
let mut spaddress2secret: HashMap<String, String> = HashMap::new();
|
||||
|
||||
spaddress2secret.insert(sp_address.into(), shared_secret.as_byte_array().to_lower_hex_string());
|
||||
|
||||
Ok(createNotificationTransactionReturn {
|
||||
transaction: serialize(&transaction).to_lower_hex_string(),
|
||||
|
@ -4,11 +4,11 @@ use anyhow::{Error, Result};
|
||||
|
||||
use rand::Rng;
|
||||
use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE;
|
||||
use sp_client::bitcoin::secp256k1::ecdh::SharedSecret;
|
||||
use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point;
|
||||
use sp_client::bitcoin::{block, Amount, OutPoint};
|
||||
use sp_client::silentpayments::sending::SilentPaymentAddress;
|
||||
use sp_client::silentpayments::utils::receiving::calculate_shared_secret;
|
||||
use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient};
|
||||
use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient, SpWallet};
|
||||
use sp_client::{
|
||||
bitcoin::{
|
||||
secp256k1::{PublicKey, Scalar, XOnlyPublicKey},
|
||||
@ -21,30 +21,30 @@ use crate::user::{lock_connected_users, CONNECTED_USERS};
|
||||
|
||||
type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>;
|
||||
|
||||
type NotificationInformation = (Transaction, Vec<(SilentPaymentAddress, PublicKey)>);
|
||||
type SharedPoint = [u8;64];
|
||||
|
||||
pub fn create_transaction_for_address(
|
||||
send_as: String,
|
||||
pub fn create_transaction_for_address_with_shared_secret(
|
||||
sp_address: SilentPaymentAddress,
|
||||
message: String,
|
||||
) -> Result<NotificationInformation> {
|
||||
) -> Result<(Transaction, SharedPoint)> {
|
||||
let connected_users = lock_connected_users()?;
|
||||
|
||||
let sender = connected_users
|
||||
.get(&send_as)
|
||||
let (_, wallets) = connected_users
|
||||
.iter()
|
||||
.last()
|
||||
.ok_or(Error::msg("Unknown sender"))?;
|
||||
|
||||
let sp_wallet = if sp_address.is_testnet() {
|
||||
&sender.recover
|
||||
&wallets.recover
|
||||
} else {
|
||||
if let Some(main) = &sender.main {
|
||||
if let Some(main) = &wallets.main {
|
||||
main
|
||||
} else {
|
||||
return Err(Error::msg("Can't spend on mainnet"));
|
||||
}
|
||||
};
|
||||
|
||||
let available_outpoints = sender.recover.get_outputs().to_spendable_list();
|
||||
let available_outpoints = wallets.recover.get_outputs().to_spendable_list();
|
||||
|
||||
// Here we need to add more heuristics about which outpoint we spend
|
||||
// For now let's keep it simple
|
||||
@ -80,8 +80,8 @@ pub fn create_transaction_for_address(
|
||||
.create_new_psbt(inputs, vec![recipient], None)?;
|
||||
log::debug!("Created psbt: {}", new_psbt);
|
||||
SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?;
|
||||
let shared_secrets: Vec<(SilentPaymentAddress, PublicKey)> =
|
||||
sp_wallet.get_client().fill_sp_outputs(&mut new_psbt)?;
|
||||
let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&new_psbt)?;
|
||||
sp_wallet.get_client().fill_sp_outputs(&mut new_psbt, partial_secret)?;
|
||||
log::debug!("Definitive psbt: {}", new_psbt);
|
||||
let mut aux_rand = [0u8; 32];
|
||||
rand::thread_rng().fill(&mut aux_rand);
|
||||
@ -91,7 +91,10 @@ pub fn create_transaction_for_address(
|
||||
|
||||
let final_tx = signed.extract_tx()?;
|
||||
|
||||
Ok((final_tx, shared_secrets))
|
||||
// This should not be directly used without hashing
|
||||
let shared_point = shared_secret_point(&sp_address.get_scan_key(), &partial_secret);
|
||||
|
||||
Ok((final_tx, shared_point))
|
||||
}
|
||||
|
||||
pub fn check_transaction(
|
||||
|
Loading…
x
Reference in New Issue
Block a user