Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ton lib #82

Merged
merged 2 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions libs/ur-registry-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ pub mod cardano;
mod util_internal;
pub mod utils;
pub mod sui;
pub mod ton;

ffi_support::define_string_destructor!(keystone_sdk_destroy_string);
2 changes: 2 additions & 0 deletions libs/ur-registry-ffi/src/ton/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod ton_sign_request;
pub mod ton_signature;
159 changes: 159 additions & 0 deletions libs/ur-registry-ffi/src/ton/ton_sign_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
use hex;
use serde_json::json;
use ur_registry::crypto_key_path::CryptoKeyPath;
use ur_registry::registry_types::TON_SIGN_REQUEST;
use ur_registry::ton::ton_sign_request::{DataType, TonSignRequest};
use uuid::Uuid;

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

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_generateTonSignRequest
fn generate_ton_sign_request(
request_id: &str, //optional
sign_data: &str,
data_type: u32,
address: &str,
derivation_path: &str, //optional
xfp: &str, //optional
origin: &str //optional
) -> String {
let address = match address {
"" => return json!({"error": "address is required"}).to_string(),
_x => _x.to_string()
};

let sign_data = match sign_data {
"" => return json!({"error": "sign data is required"}).to_string(),
_x => _x
};


let request_id = match request_id {
"" => None,
_ => match Uuid::parse_str(request_id) {
Ok(v) => Some(v.as_bytes().to_vec()),
Err(_) => return json!({"error": "uuid is invalid"}).to_string(),
},
};

let derivation_path = match (derivation_path, xfp) {
("", _) | (_, "") => None,
(_path, _xfp) => {
let xfp = match hex::decode(_xfp) {
Ok(v) => Some(v),
Err(_) => {
return json!({"error": "xfp is invalid"}).to_string()
},
};
match CryptoKeyPath::from_path(_path.to_string(), xfp.map(|v| v.as_slice().try_into().ok()).flatten()) {
Ok(v) => Some(v),
Err(_) => return json!({"error": "path is invalid"}).to_string(),
}
},
};

let origin = match origin {
"" => None,
_ => Some(origin.to_string()),
};

let sign_data_bytes = match hex::decode(remove_prefix_0x(sign_data)) {
Ok(v) => v,
Err(_) => return json!({"error": "intent message is invalid"}).to_string(),
};

let data_type = match DataType::from_u32(data_type) {
Ok(v) => v,
Err(_) => return json!({"error": "data type is invalid"}).to_string(),
};

let cbor_bytes: Vec<u8> = match TonSignRequest::new(
request_id,
sign_data_bytes,
data_type,
derivation_path,
address,
origin,
).try_into() {
Ok(v) => v,
Err(_) => return json!({"error": "sign data is invalid"}).to_string(),
};
let cbor_hex = hex::encode(cbor_bytes);
let ur_type = TON_SIGN_REQUEST.get_type();
let ur = json!({
"type": ur_type,
"cbor": cbor_hex,
});
ur.to_string()
}
}

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

#[test]
fn test_generate_ton_sign_request() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "b5ee9c7241010201004700011c29a9a317663b3ea500000008000301006842002b16732f1c05fdb4e8d3a78fd10dddef3f6067f311be539313b8a44a504d4da2a1dcd65000000000000000000000000000007072e06f";
let address = "UQC1IywyQwixSOU8pezOZDC9rv2xCV4CGJzOWH6RX8BTsGJx";
let data_type = 1;
let origin = "TonKeeper";
let expect_result = "{\"cbor\":\"a501d825509b1deb4d3b7d4bad9bdd2b0d7b3dcb6d025856b5ee9c7241010201004700011c29a9a317663b3ea500000008000301006842002b16732f1c05fdb4e8d3a78fd10dddef3f6067f311be539313b8a44a504d4da2a1dcd65000000000000000000000000000007072e06f0301057830555143314979777951776978534f553870657a4f5a4443397276327843563443474a7a4f574836525838425473474a780669546f6e4b6565706572\",\"type\":\"ton-sign-request\"}";

assert_eq!(
expect_result,
generate_ton_sign_request(request_id, sign_data, data_type, address, "", "", origin)
);
}

#[test]
fn test_generate_ton_sign_request_data_type_error() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "b5ee9c7241010201004700011c29a9a317663b3ea500000008000301006842002b16732f1c05fdb4e8d3a78fd10dddef3f6067f311be539313b8a44a504d4da2a1dcd65000000000000000000000000000007072e06f";
let address = "UQC1IywyQwixSOU8pezOZDC9rv2xCV4CGJzOWH6RX8BTsGJx";
let data_type = 0;
let origin = "TonKeeper";

let expect_result = "{\"error\":\"data type is invalid\"}";

assert_eq!(
expect_result,
generate_ton_sign_request(request_id, sign_data, data_type, address, "", "", origin)
);
}

#[test]
fn test_generate_ton_sign_request_err_address() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "b5ee9c7241010201004700011c29a9a317663b3ea500000008000301006842002b16732f1c05fdb4e8d3a78fd10dddef3f6067f311be539313b8a44a504d4da2a1dcd65000000000000000000000000000007072e06f";
let address = "";
let data_type = 0;
let origin = "TonKeeper";

let expect_result = "{\"error\":\"address is required\"}";

assert_eq!(
expect_result,
generate_ton_sign_request(request_id, sign_data, data_type, address, "", "", origin)
);
}

#[test]
fn test_generate_ton_sign_request_err_sign_data() {
let request_id = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
let sign_data = "";
let address = "UQC1IywyQwixSOU8pezOZDC9rv2xCV4CGJzOWH6RX8BTsGJx";
let data_type = 0;
let origin = "TonKeeper";

let expect_result = "{\"error\":\"sign data is required\"}";

assert_eq!(
expect_result,
generate_ton_sign_request(request_id, sign_data, data_type, address, "", "", origin)
);
}
}
79 changes: 79 additions & 0 deletions libs/ur-registry-ffi/src/ton/ton_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use anyhow::Error;
use hex;
use serde_json::json;
use ur_registry::ton::ton_signature::TonSignature;
use ur_registry::registry_types::TON_SIGNATURE;
use uuid::Uuid;

use crate::export;

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

let parse_signature = || -> Result<(String, String, String), Error> {
let cbor = hex::decode(cbor_hex.to_string())?;
let sig = TonSignature::try_from(cbor)?;
let mut request_id = String::from("");
if let Some(uuid) = sig.get_request_id() {
let uuid_hex = hex::encode(uuid);
request_id = Uuid::parse_str(&uuid_hex)?.to_string();
}
let signature = hex::encode(sig.get_signature());
let mut origin = String::from("");
if let Some(ori) = sig.get_origin() {
origin = ori;
}
Ok((request_id, signature, origin))
};
match parse_signature() {
Ok((request_id, signature, origin)) => json!({
"request_id": request_id,
"signature": signature,
"origin": origin,
}).to_string(),
Err(_) => json!({"error": "signature is invalid"}).to_string(),
}
}
}

#[cfg(test)]
mod tests {

use super::*;
#[test]
fn test_parse_ton_signature() {
let signature_cbor = "a301d825509b1deb4d3b7d4bad9bdd2b0d7b3dcb6d025840f4b79835417490958c72492723409289b444f3af18274ba484a9eeaca9e760520e453776e5975df058b537476932a45239685f694fc6362fe5af6ba714da650503684b657973746f6e65";
let expect_result = "{\"origin\":\"Keystone\",\"request_id\":\"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d\",\"signature\":\"f4b79835417490958c72492723409289b444f3af18274ba484a9eeaca9e760520e453776e5975df058b537476932a45239685f694fc6362fe5af6ba714da6505\"}";

assert_eq!(
expect_result,
parse_ton_signature("ton-signature", signature_cbor)
);
}

#[test]
fn test_parse_ton_signature_type_error() {
let signature_cbor = "A301D825509B1DEB4D3B7D4BAD9BDD2B0D7B3DCB6D025840B93921DB17F2F1D50BDA37B510F543151DF222E80946FEFBACFADFB2D4A79FDA4FACF0AE5B41D71EA3A7EBEA6AA88DE9577A788AEAB195B99B6A633C20E055030358207BAC671050FCBA0DD54F3930601C42AD36CC11BC0589ED8D3CEF3EFF1C49EF6E";
let expect_result = "{\"error\":\"type not match\"}";

assert_eq!(
expect_result,
parse_ton_signature("eth-signature", signature_cbor)
);
}

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

assert_eq!(
expect_result,
parse_ton_signature("ton-signature", signature_cbor)
);
}
}
3 changes: 3 additions & 0 deletions libs/ur-registry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ paste = "1.0.12"

[build-dependencies]
prost-build = { version = "0.11.8" }

[dev-dependencies]
base64 = { version = "0.22.1"}
1 change: 1 addition & 0 deletions libs/ur-registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ pub mod registry_types;
pub mod script_expression;
pub mod solana;
pub mod sui;
pub mod ton;
pub mod traits;
mod types;
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 @@ -32,6 +32,7 @@ use crate::near::{near_sign_request::NearSignRequest, near_signature::NearSignat
use crate::solana::{sol_sign_request::SolSignRequest, sol_signature::SolSignature};
use crate::sui::sui_sign_request::SuiSignRequest;
use crate::sui::sui_signature::SuiSignature;
use crate::ton::{ton_signature::TonSignature, ton_sign_request::TonSignRequest};
use crate::{impl_cbor_bytes, impl_ur_try_from_cbor_bytes, impl_ur_try_into_cbor_bytes};
use alloc::string::ToString;
use alloc::vec::Vec;
Expand Down Expand Up @@ -69,6 +70,8 @@ impl_cbor_bytes!(
SolSignature,
SuiSignRequest,
SuiSignature,
TonSignature,
TonSignRequest,
KeyDerivationSchema,
KeyDerivationCall,
QRHardwareCall,
Expand Down
3 changes: 3 additions & 0 deletions libs/ur-registry/src/registry_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ pub const CARDANO_CERT_KEY: RegistryType = RegistryType("cardano-cert-key", Some
// Sui
pub const SUI_SIGN_REQUEST: RegistryType = RegistryType("sui-sign-request", Some(7101));
pub const SUI_SIGNATURE: RegistryType = RegistryType("sui-signature", Some(7102));
// Ton
pub const TON_SIGN_REQUEST: RegistryType = RegistryType("ton-sign-request", Some(7201));
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));
2 changes: 2 additions & 0 deletions libs/ur-registry/src/ton/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod ton_sign_request;
pub mod ton_signature;
Loading
Loading