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::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::io::Write;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Mutex, OnceLock, PoisonError};
|
use std::sync::{Mutex, OnceLock, PoisonError};
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ use sdk_common::crypto::AnkSharedSecret;
|
|||||||
use serde_json::Error as SerdeJsonError;
|
use serde_json::Error as SerdeJsonError;
|
||||||
use shamir::SecretData;
|
use shamir::SecretData;
|
||||||
use sp_client::bitcoin::consensus::{deserialize, serialize};
|
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::hex::{parse, DisplayHex, FromHex, HexToBytesError};
|
||||||
use sp_client::bitcoin::secp256k1::ecdh::SharedSecret;
|
use sp_client::bitcoin::secp256k1::ecdh::SharedSecret;
|
||||||
use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey};
|
use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey};
|
||||||
@ -355,9 +357,9 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[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 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(),
|
message: "Can't find user".to_owned(),
|
||||||
})?;
|
})?;
|
||||||
Ok(outputs_list(user.get_all_outputs()))
|
Ok(outputs_list(user.get_all_outputs()))
|
||||||
@ -395,26 +397,24 @@ pub struct createNotificationTransactionReturn {
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn create_notification_transaction(
|
pub fn create_notification_transaction(
|
||||||
user_pre_id: String,
|
|
||||||
recipient: String,
|
recipient: String,
|
||||||
message: String,
|
message: String,
|
||||||
) -> ApiResult<createNotificationTransactionReturn> {
|
) -> ApiResult<createNotificationTransactionReturn> {
|
||||||
let sp_address: SilentPaymentAddress = recipient.try_into()?;
|
let sp_address: SilentPaymentAddress = recipient.try_into()?;
|
||||||
|
|
||||||
let (transaction, notification_information) =
|
let (transaction, shared_point) =
|
||||||
create_transaction_for_address(user_pre_id, sp_address, message)?;
|
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
|
// 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
|
// 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
|
let mut spaddress2secret: HashMap<String, String> = HashMap::new();
|
||||||
.into_iter()
|
|
||||||
.map(|(address, shared_pubkey)| {
|
spaddress2secret.insert(sp_address.into(), shared_secret.as_byte_array().to_lower_hex_string());
|
||||||
let shared_secret = AnkSharedSecret::new_from_public_key(shared_pubkey);
|
|
||||||
(address.into(), shared_secret.to_string())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(createNotificationTransactionReturn {
|
Ok(createNotificationTransactionReturn {
|
||||||
transaction: serialize(&transaction).to_lower_hex_string(),
|
transaction: serialize(&transaction).to_lower_hex_string(),
|
||||||
|
@ -4,11 +4,11 @@ use anyhow::{Error, Result};
|
|||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE;
|
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::bitcoin::{block, Amount, OutPoint};
|
||||||
use sp_client::silentpayments::sending::SilentPaymentAddress;
|
use sp_client::silentpayments::sending::SilentPaymentAddress;
|
||||||
use sp_client::silentpayments::utils::receiving::calculate_shared_secret;
|
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::{
|
use sp_client::{
|
||||||
bitcoin::{
|
bitcoin::{
|
||||||
secp256k1::{PublicKey, Scalar, XOnlyPublicKey},
|
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 FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>;
|
||||||
|
|
||||||
type NotificationInformation = (Transaction, Vec<(SilentPaymentAddress, PublicKey)>);
|
type SharedPoint = [u8;64];
|
||||||
|
|
||||||
pub fn create_transaction_for_address(
|
pub fn create_transaction_for_address_with_shared_secret(
|
||||||
send_as: String,
|
|
||||||
sp_address: SilentPaymentAddress,
|
sp_address: SilentPaymentAddress,
|
||||||
message: String,
|
message: String,
|
||||||
) -> Result<NotificationInformation> {
|
) -> Result<(Transaction, SharedPoint)> {
|
||||||
let connected_users = lock_connected_users()?;
|
let connected_users = lock_connected_users()?;
|
||||||
|
|
||||||
let sender = connected_users
|
let (_, wallets) = connected_users
|
||||||
.get(&send_as)
|
.iter()
|
||||||
|
.last()
|
||||||
.ok_or(Error::msg("Unknown sender"))?;
|
.ok_or(Error::msg("Unknown sender"))?;
|
||||||
|
|
||||||
let sp_wallet = if sp_address.is_testnet() {
|
let sp_wallet = if sp_address.is_testnet() {
|
||||||
&sender.recover
|
&wallets.recover
|
||||||
} else {
|
} else {
|
||||||
if let Some(main) = &sender.main {
|
if let Some(main) = &wallets.main {
|
||||||
main
|
main
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::msg("Can't spend on mainnet"));
|
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
|
// Here we need to add more heuristics about which outpoint we spend
|
||||||
// For now let's keep it simple
|
// For now let's keep it simple
|
||||||
@ -80,8 +80,8 @@ pub fn create_transaction_for_address(
|
|||||||
.create_new_psbt(inputs, vec![recipient], None)?;
|
.create_new_psbt(inputs, vec![recipient], None)?;
|
||||||
log::debug!("Created psbt: {}", new_psbt);
|
log::debug!("Created psbt: {}", new_psbt);
|
||||||
SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?;
|
SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?;
|
||||||
let shared_secrets: Vec<(SilentPaymentAddress, PublicKey)> =
|
let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&new_psbt)?;
|
||||||
sp_wallet.get_client().fill_sp_outputs(&mut new_psbt)?;
|
sp_wallet.get_client().fill_sp_outputs(&mut new_psbt, partial_secret)?;
|
||||||
log::debug!("Definitive psbt: {}", new_psbt);
|
log::debug!("Definitive psbt: {}", new_psbt);
|
||||||
let mut aux_rand = [0u8; 32];
|
let mut aux_rand = [0u8; 32];
|
||||||
rand::thread_rng().fill(&mut aux_rand);
|
rand::thread_rng().fill(&mut aux_rand);
|
||||||
@ -91,7 +91,10 @@ pub fn create_transaction_for_address(
|
|||||||
|
|
||||||
let final_tx = signed.extract_tx()?;
|
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(
|
pub fn check_transaction(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user