Skip to content

Commit

Permalink
Merge pull request #82 from KeystoneHQ/support-ton
Browse files Browse the repository at this point in the history
feat: add ton lib
  • Loading branch information
soralit authored May 17, 2024
2 parents 378bf68 + fda4659 commit 94ace04
Show file tree
Hide file tree
Showing 12 changed files with 587 additions and 0 deletions.
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

0 comments on commit 94ace04

Please sign in to comment.