darkfid: Implement wallet.decrypt_note RPC endpoint.

This commit is contained in:
parazyd
2022-08-09 18:27:59 +02:00
parent 1e109e3edc
commit 3aa0a04d7b
4 changed files with 50 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ pub enum RpcError {
NotYetSynced = -32112,
InvalidAddressParam = -32113,
InvalidAmountParam = -32114,
DecryptionFailed = -32115,
}
fn to_tuple(e: RpcError) -> (i64, String) {
@@ -35,6 +36,7 @@ fn to_tuple(e: RpcError) -> (i64, String) {
RpcError::NotYetSynced => "Blockchain not yet synced",
RpcError::InvalidAddressParam => "Invalid address parameter",
RpcError::InvalidAmountParam => "invalid amount parameter",
RpcError::DecryptionFailed => "Decryption failed",
};
(e as i64, msg.to_string())

View File

@@ -185,6 +185,7 @@ impl RequestHandler for Darkfid {
Some("wallet.get_balances") => return self.get_balances(req.id, params).await,
Some("wallet.get_coins_valtok") => return self.get_coins_valtok(req.id, params).await,
Some("wallet.get_merkle_path") => return self.get_merkle_path(req.id, params).await,
Some("wallet.decrypt_note") => return self.decrypt_note(req.id, params).await,
Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
}
}

View File

@@ -10,11 +10,12 @@ use darkfi::{
keypair::{Keypair, PublicKey, SecretKey},
token_id,
},
node::State,
rpc::jsonrpc::{
ErrorCode::{InternalError, InvalidParams, ParseError},
JsonError, JsonResponse, JsonResult,
},
util::serial::serialize,
util::serial::{deserialize, serialize},
};
use super::Darkfid;
@@ -283,4 +284,48 @@ impl Darkfid {
merkle_path.iter().map(|x| bs58::encode(serialize(x)).into_string()).collect();
JsonResponse::new(json!(ret), id).into()
}
// RPCAPI:
// Try to decrypt a given encrypted note with the secret keys
// found in the wallet.
// --> {"jsonrpc": "2.0", "method": "wallet.decrypt_note", params": [ciphertext], "id": 1}
// <-- {"jsonrpc": "2.0", "result": "base58_encoded_plain_note", "id": 1}
pub async fn decrypt_note(&self, id: Value, params: &[Value]) -> JsonResult {
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
let bytes = match bs58::decode(params[0].as_str().unwrap()).into_vec() {
Ok(v) => v,
Err(e) => {
error!("decrypt_note(): Failed decoding base58 string: {}", e);
return JsonError::new(ParseError, None, id).into()
}
};
let enc_note = match deserialize(&bytes) {
Ok(v) => v,
Err(e) => {
error!("decrypt_note(): Failed deserializing bytes into EncryptedNote: {}", e);
return JsonError::new(InternalError, None, id).into()
}
};
let keypairs = match self.client.get_keypairs().await {
Ok(v) => v,
Err(e) => {
error!("decrypt_note(): Failed fetching keypairs: {}", e);
return JsonError::new(InternalError, None, id).into()
}
};
for kp in keypairs {
if let Some(note) = State::try_decrypt_note(&enc_note, kp.secret) {
let s = bs58::encode(&serialize(&note)).into_string();
return JsonResponse::new(json!(s), id).into()
}
}
return server_error(RpcError::DecryptionFailed, id)
}
}

View File

@@ -195,7 +195,7 @@ impl State {
Ok(())
}
fn try_decrypt_note(ciphertext: &EncryptedNote, secret: SecretKey) -> Option<Note> {
pub fn try_decrypt_note(ciphertext: &EncryptedNote, secret: SecretKey) -> Option<Note> {
match ciphertext.decrypt(&secret) {
Ok(note) => Some(note),
Err(_) => None,