Update api
This commit is contained in:
parent
b2cab53188
commit
361a8aa409
143
src/api.rs
143
src/api.rs
@ -23,6 +23,7 @@ use sdk_common::sp_client::bitcoin::hex::{
|
||||
};
|
||||
use sdk_common::sp_client::bitcoin::key::{Parity, Secp256k1};
|
||||
use sdk_common::sp_client::bitcoin::network::ParseNetworkError;
|
||||
use sdk_common::sp_client::bitcoin::p2p::message::NetworkMessage;
|
||||
use sdk_common::sp_client::bitcoin::psbt::raw;
|
||||
use sdk_common::sp_client::bitcoin::secp256k1::ecdh::shared_secret_point;
|
||||
use sdk_common::sp_client::bitcoin::secp256k1::{PublicKey, Scalar, SecretKey};
|
||||
@ -46,8 +47,7 @@ use wasm_bindgen::convert::FromWasmAbi;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use sdk_common::network::{
|
||||
self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, CipherMessage, FaucetMessage,
|
||||
NewTxMessage,
|
||||
self, AnkFlag, CachedMessage, CachedMessageStatus, Envelope, FaucetMessage, NewTxMessage, Pcd, Prd
|
||||
};
|
||||
use sdk_common::silentpayments::{create_transaction, map_outputs_to_sp_address};
|
||||
|
||||
@ -570,7 +570,7 @@ fn handle_transaction(
|
||||
}) {
|
||||
let (outpoint, output) = utxo_created.into_iter().next().unwrap();
|
||||
|
||||
let cipher_msg: CipherMessage = serde_json::from_slice(&plaintext)?;
|
||||
let cipher_msg: Prd = serde_json::from_slice(&plaintext)?;
|
||||
message.commited_in = Some(outpoint.clone());
|
||||
// freeze the commitment utxo
|
||||
let mut freezed_utxos = lock_freezed_utxos()?;
|
||||
@ -578,8 +578,6 @@ fn handle_transaction(
|
||||
|
||||
message.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
message.commitment = Some(commitment_str);
|
||||
message.plaintext.push(cipher_msg.message);
|
||||
message.ciphertext = None;
|
||||
message.sender = Some(cipher_msg.sender);
|
||||
message.recipient = Some(sp_wallet.get_client().get_receiving_address());
|
||||
message.status = CachedMessageStatus::ReceivedMustConfirm;
|
||||
@ -600,7 +598,7 @@ fn handle_transaction(
|
||||
new_msg.commitment = Some(commitment.to_lower_hex_string());
|
||||
new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address());
|
||||
new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.status = CachedMessageStatus::TxWaitingCipher;
|
||||
new_msg.status = CachedMessageStatus::TxWaitingPrd;
|
||||
messages.push(new_msg.clone());
|
||||
return Ok(new_msg.clone());
|
||||
}
|
||||
@ -711,46 +709,62 @@ pub fn parse_cipher(cipher_msg: String, fee_rate: u32) -> ApiResult<CachedMessag
|
||||
let mut messages = lock_messages()?;
|
||||
let cipher = Vec::from_hex(&cipher_msg.trim_matches('\"'))?;
|
||||
if let Some(message) = messages.iter_mut().find(|m| match m.status {
|
||||
CachedMessageStatus::TxWaitingCipher | CachedMessageStatus::Trusted => {
|
||||
m.try_decrypt_cipher(cipher.clone()).is_ok()
|
||||
CachedMessageStatus::TxWaitingPrd => {
|
||||
m.try_decrypt_prd(cipher.clone()).is_ok()
|
||||
}
|
||||
CachedMessageStatus::GotPrdWaitingPcd => {
|
||||
m.try_decrypt_pcd(cipher.clone()).is_ok()
|
||||
}
|
||||
_ => return false,
|
||||
}) {
|
||||
let plain = message.try_decrypt_cipher(cipher).unwrap();
|
||||
// debug!("Found message {}", String::from_utf8(plain.clone())?);
|
||||
if message.status == CachedMessageStatus::TxWaitingCipher {
|
||||
let cipher_msg: CipherMessage = serde_json::from_slice(&plain)?;
|
||||
if message.status == CachedMessageStatus::TxWaitingPrd {
|
||||
let plain = message.try_decrypt_prd(cipher).unwrap();
|
||||
debug!("Found message {}", String::from_utf8(plain.clone())?);
|
||||
let prd: Prd = serde_json::from_slice(&plain)?;
|
||||
// does the retrieved message match with the commited hash?
|
||||
let hash = create_commitment(serde_json::to_string(&cipher_msg)?);
|
||||
let hash = create_commitment(serde_json::to_string(&prd)?);
|
||||
if Some(hash) != message.commitment {
|
||||
return Err(ApiError {
|
||||
message: "Message doesn't match commitment".to_owned(),
|
||||
message: "Prd doesn't match commitment".to_owned(),
|
||||
});
|
||||
}
|
||||
message.sender = Some(cipher_msg.sender);
|
||||
message.ciphertext = None;
|
||||
if cipher_msg.message.starts_with("PAIRING") {
|
||||
message.sender = Some(prd.sender.clone());
|
||||
message.pcd_commitment = Some(prd.pcd_commitment.to_string());
|
||||
message.prd_cipher = None;
|
||||
message.prd = Some(prd);
|
||||
message.status = CachedMessageStatus::GotPrdWaitingPcd;
|
||||
} else {
|
||||
let plain = message.try_decrypt_pcd(cipher).unwrap();
|
||||
debug!("Found message {}", String::from_utf8(plain.clone())?);
|
||||
// we're receiving a pcd for a prd we already have
|
||||
let pcd: Pcd = serde_json::from_slice(&plain)?;
|
||||
// check that the hash of the pcd is the same than commited in the prd
|
||||
let pcd_commitment = create_commitment(pcd.to_string());
|
||||
if Some(&pcd_commitment) != message.pcd_commitment.as_ref() {
|
||||
return Err(ApiError {
|
||||
message: format!("Pcd doesn't match commitment: expected {:?}\ngot {}", message.pcd_commitment.as_ref(), pcd_commitment),
|
||||
});
|
||||
}
|
||||
|
||||
if pcd.message.starts_with("PAIRING") {
|
||||
// we don't follow the classic confirmation pattern
|
||||
// if we agree, we must send another notification to remote
|
||||
// the notification output here will be spent as our first session
|
||||
message.status = CachedMessageStatus::Pairing;
|
||||
} else if cipher_msg.message.starts_with("LOGIN") {
|
||||
} else if pcd.message.starts_with("LOGIN") {
|
||||
message.status = CachedMessageStatus::Login;
|
||||
} else {
|
||||
message.status = CachedMessageStatus::ReceivedMustConfirm;
|
||||
}
|
||||
message.plaintext.push(cipher_msg.message);
|
||||
} else {
|
||||
// We're receiving a message for some action already engaged
|
||||
// Let's update the message by pushing what we just found out
|
||||
message.plaintext.push(String::from_utf8(plain)?);
|
||||
message.pcd = Some(pcd);
|
||||
message.pcd_cipher = None;
|
||||
}
|
||||
return Ok(message.clone());
|
||||
} else {
|
||||
// let's keep it in case we receive the transaction later
|
||||
let mut new_msg = CachedMessage::new();
|
||||
new_msg.status = CachedMessageStatus::CipherWaitingTx;
|
||||
new_msg.ciphertext = Some(cipher_msg);
|
||||
new_msg.prd_cipher = Some(cipher_msg);
|
||||
messages.push(new_msg.clone());
|
||||
return Ok(new_msg);
|
||||
}
|
||||
@ -851,7 +865,7 @@ pub fn create_confirmation_transaction(
|
||||
let mut messages = lock_messages()?;
|
||||
let message: &mut CachedMessage;
|
||||
if let Some(m) = messages.iter_mut().find(|m| m.id == message_id) {
|
||||
if m.sender.is_none() || m.commited_in.is_none() || m.plaintext.is_empty() {
|
||||
if m.sender.is_none() || m.commited_in.is_none() || m.prd.is_none() {
|
||||
return Err(ApiError {
|
||||
message: "Invalid network message".to_owned(),
|
||||
});
|
||||
@ -938,19 +952,25 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
|
||||
);
|
||||
}
|
||||
|
||||
debug!("outpoint_to_spend: {}", outpoint_to_spend);
|
||||
let pcd = Pcd::new("LOGIN".to_owned());
|
||||
let pcd_commitment = sha256sum(pcd.to_string().as_bytes());
|
||||
|
||||
debug!("outputs: {:?}", sp_wallet.get_outputs().to_outpoints_list());
|
||||
let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into();
|
||||
|
||||
let cipher_msg = CipherMessage::new(
|
||||
let prd = Prd::new(
|
||||
local_device
|
||||
.get_wallet()
|
||||
.get_client()
|
||||
.get_receiving_address(),
|
||||
"LOGIN".to_owned(),
|
||||
.get_receiving_address()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
key,
|
||||
pcd_commitment,
|
||||
);
|
||||
|
||||
let commitment = create_commitment(serde_json::to_string(&cipher_msg)?);
|
||||
let pcd_cipher = prd.encrypt_pcd(&pcd)?;
|
||||
|
||||
let commitment = sha256sum(prd.to_string().as_bytes());
|
||||
|
||||
let recipient_address = SilentPaymentAddress::try_from(paired_device.address.as_str()).unwrap();
|
||||
|
||||
@ -970,7 +990,7 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
|
||||
&freezed_utxos,
|
||||
sp_wallet,
|
||||
vec![recipient],
|
||||
Some(Vec::from_hex(&commitment)?),
|
||||
Some(commitment.as_byte_array().to_vec()),
|
||||
Amount::from_sat(fee_rate.into()),
|
||||
None,
|
||||
)?;
|
||||
@ -987,7 +1007,7 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
|
||||
let shared_secret = AnkSharedSecret::new(shared_point);
|
||||
|
||||
let cipher = encrypt_with_key(
|
||||
serde_json::to_string(&cipher_msg)?,
|
||||
prd.to_string(),
|
||||
shared_secret.to_byte_array().to_lower_hex_string(),
|
||||
)?;
|
||||
|
||||
@ -1001,16 +1021,18 @@ pub fn create_login_transaction(fee_rate: u32) -> ApiResult<createTransactionRet
|
||||
let final_tx = signed_psbt.extract_tx()?;
|
||||
|
||||
let mut new_msg = CachedMessage::new();
|
||||
new_msg.plaintext.push(cipher_msg.message);
|
||||
new_msg.ciphertext = Some(cipher);
|
||||
new_msg.commitment = Some(commitment);
|
||||
new_msg.sender = Some(prd.sender.clone());
|
||||
new_msg.pcd = Some(pcd);
|
||||
new_msg.pcd_cipher = Some(pcd_cipher.to_lower_hex_string());
|
||||
new_msg.prd = Some(prd);
|
||||
new_msg.prd_cipher = Some(cipher);
|
||||
new_msg.commitment = Some(commitment.to_string());
|
||||
new_msg.commited_in = Some(OutPoint {
|
||||
txid: final_tx.txid(),
|
||||
vout: recipients_vouts[0] as u32,
|
||||
});
|
||||
new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.recipient = Some(recipient_address.into());
|
||||
new_msg.sender = Some(cipher_msg.sender);
|
||||
new_msg.tied_by = Some(1); // for now we just assume that's the second utxo, first being the notification itself
|
||||
new_msg.status = CachedMessageStatus::Login;
|
||||
lock_messages()?.push(new_msg.clone());
|
||||
@ -1032,9 +1054,9 @@ pub fn create_pairing_transaction(
|
||||
.get_client()
|
||||
.get_receiving_address();
|
||||
|
||||
let cipher_message = CipherMessage::new(my_address, "PAIRING".to_owned());
|
||||
let pcd = Pcd::new("PAIRING".to_owned());
|
||||
|
||||
let mut res = create_notification_transaction(address, cipher_message, fee_rate)?;
|
||||
let mut res = create_notification_transaction(address, pcd, fee_rate)?;
|
||||
|
||||
let mut messages = lock_messages()?;
|
||||
|
||||
@ -1051,7 +1073,7 @@ pub fn create_pairing_transaction(
|
||||
#[wasm_bindgen]
|
||||
pub fn create_notification_transaction(
|
||||
address: String,
|
||||
cipher_message: CipherMessage,
|
||||
pcd: Pcd,
|
||||
fee_rate: u32,
|
||||
) -> ApiResult<createTransactionReturn> {
|
||||
let sp_address: SilentPaymentAddress = address.as_str().try_into()?;
|
||||
@ -1066,7 +1088,19 @@ pub fn create_notification_transaction(
|
||||
nb_outputs: 1,
|
||||
};
|
||||
|
||||
let commitment = create_commitment(serde_json::to_string(&cipher_message)?);
|
||||
let pcd_commitment = sha256sum(pcd.to_string().as_bytes());
|
||||
|
||||
let key: [u8; 32] = Aes256Gcm::generate_key(thread_rng()).into();
|
||||
|
||||
let prd = Prd::new(
|
||||
sp_wallet.get_client().get_receiving_address().try_into().unwrap(),
|
||||
key,
|
||||
pcd_commitment
|
||||
);
|
||||
|
||||
let prd_commitment = sha256sum(prd.to_string().as_bytes());
|
||||
|
||||
let pcd_cipher = prd.encrypt_pcd(&pcd)?;
|
||||
|
||||
let freezed_utxos = lock_freezed_utxos()?;
|
||||
|
||||
@ -1075,7 +1109,7 @@ pub fn create_notification_transaction(
|
||||
&freezed_utxos,
|
||||
sp_wallet,
|
||||
vec![recipient],
|
||||
Some(Vec::from_hex(&commitment)?),
|
||||
Some(prd_commitment.as_byte_array().to_vec()),
|
||||
Amount::from_sat(fee_rate.into()),
|
||||
None,
|
||||
)?;
|
||||
@ -1092,7 +1126,7 @@ pub fn create_notification_transaction(
|
||||
let shared_secret = AnkSharedSecret::new(shared_point);
|
||||
|
||||
let cipher = encrypt_with_key(
|
||||
serde_json::to_string(&cipher_message)?,
|
||||
serde_json::to_string(&prd)?,
|
||||
shared_secret.to_byte_array().to_lower_hex_string(),
|
||||
)?;
|
||||
|
||||
@ -1105,16 +1139,19 @@ pub fn create_notification_transaction(
|
||||
// for now let's just take the smallest vout that belongs to the recipient
|
||||
let final_tx = signed_psbt.extract_tx()?;
|
||||
let mut new_msg = CachedMessage::new();
|
||||
new_msg.plaintext.push(cipher_message.message);
|
||||
new_msg.ciphertext = Some(cipher);
|
||||
new_msg.commitment = Some(commitment);
|
||||
new_msg.sender = Some(prd.sender.clone());
|
||||
new_msg.prd = Some(prd);
|
||||
new_msg.prd_cipher = Some(cipher);
|
||||
new_msg.pcd = Some(pcd);
|
||||
new_msg.pcd_cipher = Some(pcd_cipher.to_lower_hex_string());
|
||||
|
||||
new_msg.commitment = Some(prd_commitment.as_byte_array().to_lower_hex_string());
|
||||
new_msg.commited_in = Some(OutPoint {
|
||||
txid: final_tx.txid(),
|
||||
vout: recipients_vouts[0] as u32,
|
||||
});
|
||||
new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string());
|
||||
new_msg.recipient = Some(address);
|
||||
new_msg.sender = Some(cipher_message.sender);
|
||||
new_msg.tied_by = Some(1); // for now we just assume that's the second utxo, first being the notification itself
|
||||
new_msg.status = CachedMessageStatus::SentWaitingConfirmation;
|
||||
lock_messages()?.push(new_msg.clone());
|
||||
@ -1209,15 +1246,19 @@ pub fn create_faucet_msg() -> ApiResult<String> {
|
||||
cached_msg.status = CachedMessageStatus::FaucetWaiting;
|
||||
lock_messages()?.push(cached_msg.clone());
|
||||
|
||||
let network_msg = AnkNetworkMsg::new(AnkFlag::Faucet, &faucet_msg.to_string());
|
||||
let network_msg = Envelope::new(AnkFlag::Faucet, &faucet_msg.to_string());
|
||||
|
||||
Ok(network_msg.to_string())
|
||||
}
|
||||
|
||||
fn sha256sum(input: &[u8]) -> sha256::Hash {
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&input);
|
||||
sha256::Hash::from_engine(engine)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_commitment(payload_to_hash: String) -> String {
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&payload_to_hash.as_bytes());
|
||||
let hash = sha256::Hash::from_engine(engine);
|
||||
let hash = sha256sum(payload_to_hash.as_bytes());
|
||||
hash.to_byte_array().to_lower_hex_string()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user