Skip to content

Commit

Permalink
Merge pull request #84 from KeystoneHQ/add-stellar
Browse files Browse the repository at this point in the history
Add stellar integration
  • Loading branch information
soralit authored May 31, 2024
2 parents d8f14b6 + 986adef commit 3d98980
Show file tree
Hide file tree
Showing 10 changed files with 668 additions and 0 deletions.
2 changes: 2 additions & 0 deletions libs/ur-registry-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ mod util_internal;
pub mod utils;
pub mod sui;
pub mod ton;
pub mod stellar;


ffi_support::define_string_destructor!(keystone_sdk_destroy_string);
2 changes: 2 additions & 0 deletions libs/ur-registry-ffi/src/stellar/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod stellar_sign_request;
pub mod stellar_signature;
129 changes: 129 additions & 0 deletions libs/ur-registry-ffi/src/stellar/stellar_sign_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use hex;
use serde_json::json;
use ur_registry::crypto_key_path::CryptoKeyPath;
use ur_registry::stellar::stellar_sign_request::{SignType, StellarSignRequest};
use ur_registry::traits::To;
use uuid::Uuid;

use crate::export;
use crate::util_internal::string_helper::remove_prefix_0x;

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_generateStellarSignRequest
fn generate_stellar_sign_request(
request_id: &str,
sign_data: &str,
path: &str,
xfp: &str,
address: &str,
origin: &str,
sign_type: u32
) -> String {
let xfp_bytes = match hex::decode(xfp) {
Ok(v) => v,
Err(_) => return json!({"error": "xfp is invalid"}).to_string(),
};
let xfp_slice: [u8; 4] = match xfp_bytes.as_slice().try_into() {
Ok(v) => v,
Err(_) => return json!({"error": "length of xfp must be exactly 8"}).to_string(),
};
let derivation_path = match CryptoKeyPath::from_path(path.to_string(), Some(xfp_slice)) {
Ok(v) => v,
Err(_) => return json!({"error": "path is invalid"}).to_string(),
};
let sign_type = match SignType::from_u32(sign_type) {
Ok(v) => v,
Err(_) => return json!({"error": "sign_type is invalid"}).to_string(),
};
let request_id = match Uuid::parse_str(request_id) {
Ok(v) => v,
Err(_) => return json!({"error": "uuid is invalid"}).to_string(),
}.as_bytes().to_vec();
let sign_date_bytes = match hex::decode(remove_prefix_0x(sign_data)) {
Ok(v) => v,
Err(_) => return json!({"error": "sign data is invalid"}).to_string(),
};
let address = if address.len() == 0 { None } else { Some(address.as_bytes().to_vec()) };
let origin = if origin.len() == 0 { None } else { Some(origin.to_string()) };

let result = StellarSignRequest::new(
Some(request_id),
sign_date_bytes,
derivation_path,
address,
origin,
sign_type
);

let cbor = match result.to_bytes() {
Ok(v) => v,
Err(_) => return json!({"error": "cbor serialization failed"}).to_string(),
};
let cbor = hex::encode(cbor);
let ur_type = "stellar-sign-request";
let ur = json!({
"type": ur_type,
"cbor": cbor,
});
ur.to_string()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_generate_stellar_sign_request() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "01000103c8d842a2f17fd7aab608ce2ea535a6e958dffa20caf669b347b911c4171965530f957620b228bae2b94c82ddd4c093983a67365555b737ec7ddc1117e61c72e0000000000000000000000000000000000000000000000000000000000000000010295cc2f1f39f3604718496ea00676d6a72ec66ad09d926e3ece34f565f18d201020200010c0200000000e1f50500000000";
let path = "m/44'/501'/0'/0'";
let xfp = "12121212";
let address = "";
let sign_type = 1;
let origin = "";

let expect_result = "{\"cbor\":\"a401d825509b1deb4d3b7d4bad9bdd2b0d7b3dcb6d02589601000103c8d842a2f17fd7aab608ce2ea535a6e958dffa20caf669b347b911c4171965530f957620b228bae2b94c82ddd4c093983a67365555b737ec7ddc1117e61c72e0000000000000000000000000000000000000000000000000000000000000000010295cc2f1f39f3604718496ea00676d6a72ec66ad09d926e3ece34f565f18d201020200010c0200000000e1f5050000000003d90130a20188182cf51901f5f500f500f5021a121212120601\",\"type\":\"stellar-sign-request\"}";

assert_eq!(
expect_result,
generate_stellar_sign_request(request_id, sign_data, path, xfp, address, origin, sign_type)
);
}

#[test]
fn test_generate_stellar_sign_request_path_error() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "01000103c8d842a2f17fd7aab608ce2ea535a6e958dffa20caf669b347b911c4171965530f957620b228bae2b94c82ddd4c093983a67365555b737ec7ddc1117e61c72e0000000000000000000000000000000000000000000000000000000000000000010295cc2f1f39f3604718496ea00676d6a72ec66ad09d926e3ece34f565f18d201020200010c0200000000e1f50500000000";
let path = "";
let xfp = "1212120";
let address = "";
let sign_type = 1;
let origin = "keystone";

let err_result_derivation_path = "{\"error\":\"xfp is invalid\"}";

assert_eq!(
err_result_derivation_path,
generate_stellar_sign_request(request_id, sign_data, path, xfp, address, origin, sign_type)
);
}

#[test]
fn test_generate_stellar_sign_request_err_sign_data() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "0123h";
let path = "m/44'/501'/0'/0'";
let xfp = "12121212";
let address = "";
let sign_type = 1;
let origin = "keystone";

let err_result = "{\"error\":\"sign data is invalid\"}";

assert_eq!(
err_result,
generate_stellar_sign_request(request_id, sign_data, path, xfp, address, origin, sign_type)
);
}
}
74 changes: 74 additions & 0 deletions libs/ur-registry-ffi/src/stellar/stellar_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use anyhow::format_err;
use anyhow::Error;
use hex;
use serde_json::json;
use ur_registry::registry_types::STELLAR_SIGNATURE;
use ur_registry::stellar::stellar_signature::StellarSignature;
use ur_registry::traits::From;
use uuid::Uuid;

use crate::export;

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_parseStellarSignature
fn parse_stellar_signature(ur_type: &str, cbor_hex: &str) -> String {
if STELLAR_SIGNATURE.get_type() != ur_type {
return json!({"error": "type not match"}).to_string();
}

let parse_signature = || -> Result<(String, String), Error> {
let cbor = hex::decode(cbor_hex.to_string())?;
let stellar_signature = StellarSignature::from_cbor(cbor).map_err(|_| format_err!(""))?;
let uuid = stellar_signature.get_request_id().ok_or(format_err!(""))?;
let uuid_hex = hex::encode(uuid);
let request_id = Uuid::parse_str(&uuid_hex)?.to_string();
let signature = hex::encode(stellar_signature.get_signature());
Ok((request_id, signature))
};
match parse_signature() {
Ok((request_id, signature)) => json!({
"request_id": request_id,
"signature": signature,
}).to_string(),
Err(_) => json!({"error": "signature is invalid"}).to_string(),
}
}
}

#[cfg(test)]
mod tests {

use super::*;
#[test]
fn test_parse_stellar_signature() {
let stellar_signature_cbor = "a201d825509b1deb4d3b7d4bad9bdd2b0d7b3dcb6d025840d4f0a7bcd95bba1fbb1051885054730e3f47064288575aacc102fbbf6a9a14daa066991e360d3e3406c20c00a40973eff37c7d641e5b351ec4a99bfe86f335f7";
let expect_result = "{\"request_id\":\"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d\",\"signature\":\"d4f0a7bcd95bba1fbb1051885054730e3f47064288575aacc102fbbf6a9a14daa066991e360d3e3406c20c00a40973eff37c7d641e5b351ec4a99bfe86f335f7\"}";

assert_eq!(
expect_result,
parse_stellar_signature("stellar-signature", stellar_signature_cbor)
);
}

#[test]
fn test_parse_stellar_signature_type_error() {
let stellar_signature_cbor = "a301d825509b1deb4d3b7d4bad9bdd2b0d7b3dcb6d025841d4f0a7bcd95bba1fbb1051885054730e3f47064288575aacc102fbbf6a9a14daa066991e360d3e3406c20c00a40973eff37c7d641e5b351ec4a99bfe86f335f71303686b657973746f6e65";
let expect_result = "{\"error\":\"type not match\"}";

assert_eq!(
expect_result,
parse_stellar_signature("eth-signature", stellar_signature_cbor)
);
}

#[test]
fn test_parse_stellar_signature_error() {
let stellar_signature_cbor = "a201";
let expect_result = "{\"error\":\"signature is invalid\"}";

assert_eq!(
expect_result,
parse_stellar_signature("stellar-signature", stellar_signature_cbor)
);
}
}
1 change: 1 addition & 0 deletions libs/ur-registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod pb;
pub mod registry_types;
pub mod script_expression;
pub mod solana;
pub mod stellar;
pub mod sui;
pub mod ton;
pub mod traits;
Expand Down
3 changes: 3 additions & 0 deletions libs/ur-registry/src/macros_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::keystone::{
};
use crate::near::{near_sign_request::NearSignRequest, near_signature::NearSignature};
use crate::solana::{sol_sign_request::SolSignRequest, sol_signature::SolSignature};
use crate::stellar::{stellar_sign_request::StellarSignRequest, stellar_signature::StellarSignature};
use crate::sui::sui_sign_request::SuiSignRequest;
use crate::sui::sui_signature::SuiSignature;
use crate::ton::{ton_signature::TonSignature, ton_sign_request::TonSignRequest};
Expand Down Expand Up @@ -68,6 +69,8 @@ impl_cbor_bytes!(
NearSignature,
SolSignRequest,
SolSignature,
StellarSignRequest,
StellarSignature,
SuiSignRequest,
SuiSignature,
TonSignature,
Expand Down
6 changes: 6 additions & 0 deletions libs/ur-registry/src/registry_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub enum URType {
CryptoAccount(String),
EthSignRequest(String),
SolSignRequest(String),
StellarSignRequest(String),
NearSignRequest(String),
ArweaveSignRequest(String),
AptosSignRequest(String),
Expand All @@ -33,6 +34,7 @@ impl URType {
"keystone-sign-request" => Ok(URType::KeystoneSignRequest(type_str.to_string())),
"eth-sign-request" => Ok(URType::EthSignRequest(type_str.to_string())),
"sol-sign-request" => Ok(URType::SolSignRequest(type_str.to_string())),
"stellar-sign-request" => Ok(URType::StellarSignRequest(type_str.to_string())),
"arweave-sign-request" => Ok(URType::ArweaveSignRequest(type_str.to_string())),
"cosmos-sign-request" => Ok(URType::CosmosSignRequest(type_str.to_string())),
"evm-sign-request" => Ok(URType::EvmSignRequest(type_str.to_string())),
Expand All @@ -56,6 +58,7 @@ impl URType {
URType::KeystoneSignRequest(type_str) => type_str.to_string(),
URType::EthSignRequest(type_str) => type_str.to_string(),
URType::SolSignRequest(type_str) => type_str.to_string(),
URType::StellarSignRequest(type_str) => type_str.to_string(),
URType::NearSignRequest(type_str) => type_str.to_string(),
URType::ArweaveSignRequest(type_str) => type_str.to_string(),
URType::AptosSignRequest(type_str) => type_str.to_string(),
Expand Down Expand Up @@ -141,3 +144,6 @@ pub const TON_SIGNATURE: RegistryType = RegistryType("ton-signature", Some(7202)
// BTC
pub const BTC_SIGN_REQUEST: RegistryType = RegistryType("btc-sign-request", Some(8101));
pub const BTC_SIGNATURE: RegistryType = RegistryType("btc-signature", Some(8102));
// Stellar
pub const STELLAR_SIGN_REQUEST: RegistryType = RegistryType("stellar-sign-request", Some(8201));
pub const STELLAR_SIGNATURE: RegistryType = RegistryType("stellar-signature", Some(8202));
2 changes: 2 additions & 0 deletions libs/ur-registry/src/stellar/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod stellar_sign_request;
pub mod stellar_signature;
Loading

0 comments on commit 3d98980

Please sign in to comment.