Skip to content

Commit

Permalink
Merge pull request #63 from KeystoneHQ/evm
Browse files Browse the repository at this point in the history
support evm
  • Loading branch information
renfengshi authored Jul 17, 2023
2 parents 1758b4a + ed007fa commit eb444d0
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 4 deletions.
4 changes: 4 additions & 0 deletions include/URRegistryFFI/lib_ur_registry_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const char* parse_sol_signature(struct ExternError*, const char* ur_type, const
const char* generate_cosmos_sign_request(struct ExternError*, const char* request_id, const char* sign_data, const int data_type, const char* accounts, const char* origin);
const char* parse_cosmos_signature(struct ExternError*, const char* ur_type, const char* cbor_hex);

// Cosmos
const char* generate_evm_sign_request(struct ExternError*, const char* request_id, const char* sign_data, const int data_type, const int custom_chain_identifier, const char* account, const char* origin);
const char* parse_evm_signature(struct ExternError*, const char* ur_type, const char* cbor_hex);

// Tron
const char* generate_tron_sign_request(struct ExternError*, const char* request_id, const char* sign_data, const char* path, const char* xfp, const char* token_info, const char* origin, const int64_t timestamp);
const char* parse_tron_signature(struct ExternError*, const char* ur_type, const char* cbor_hex);
Expand Down
160 changes: 160 additions & 0 deletions libs/ur-registry-ffi/src/evm/evm_sign_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use hex;
use serde::Deserialize;
use serde_json::json;
use ur_registry::crypto_key_path::CryptoKeyPath;
use uuid::Uuid;
use ur_registry::cosmos::evm_sign_request::{EvmSignRequest, SignDataType};
use ur_registry::registry_types::EVM_SIGN_REQUEST;

use crate::export;

#[derive(Deserialize)]
struct Account {
path: String,
xfp: String,
address: Option<String>,
}

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_generateEvmSignRequest
fn generate_evm_sign_request(
request_id: &str,
sign_data: &str,
data_type: u8,
custom_chain_identifier: u32,
account: &str,
origin: &str
) -> 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_data_bytes = match hex::decode(sign_data) {
Ok(v) => v,
Err(_) => return json!({"error": "sign data is invalid"}).to_string(),
};
let data_type = match SignDataType::from_u8(data_type) {
Ok(v) => v,
Err(_) => return json!({"error": "data type is invalid"}).to_string(),
};
let account = match serde_json::from_str::<Account>(account) {
Ok(v) => v,
Err(_) => return json!({"error": "account is invalid"}).to_string(),
};
let xfp = match hex::decode(account.xfp) {
Ok(v) => Some(v),
Err(_) => {
return json!({"error": "xfp is invalid"}).to_string();
}
};
if xfp.is_some() && xfp.as_ref().unwrap().len() != 4 {
return json!({"error": "xfp is invalid"}).to_string();
}
let path = match CryptoKeyPath::from_path(account.path.to_string(), xfp.map(|v| v.as_slice().try_into().ok()).flatten()) {
Ok(v) => v,
Err(_) => {
return json!({"error": "account is invalid"}).to_string();
},
};
let address = match account.address {
Some(v) => {
match hex::decode(if v.starts_with("0x") {v[2..].to_string()} else {v}) {
Ok(b) => Some(b),
Err(_) => {
return json!({"error": "address is invalid"}).to_string();
}
}
}
None => None
};
let origin = if origin.len() == 0 { None } else { Some(origin.to_string()) };

let cbor_bytes: Vec<u8> = match EvmSignRequest::new(
request_id,
sign_data_bytes,
data_type,
custom_chain_identifier,
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 = EVM_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_evm_sign_request() {
let request_id = "05752335-5d51-4a64-a481-ff2200000000";
let sign_data = "0A9D010A9A010A1C2F636F736D6F732E62616E6B2E763162657461312E4D736753656E64127A0A2C65766D6F73317363397975617230756E3736677235633871346A3736687572347179706A6B38336E786B7735122C65766D6F73317363397975617230756E3736677235633871346A3736687572347179706A6B38336E786B77351A1C0A07617465766D6F7312113130303030303030303030303030303030127E0A590A4F0A282F65746865726D696E742E63727970746F2E76312E657468736563703235366B312E5075624B657912230A21024F7A8D64E515CCF1E0A92A7C859262F425473CF09A50EBCAF3B06B156624145312040A020801181612210A1B0A07617465766D6F7312103236323530303030303030303030303010A8B4061A0C65766D6F735F393030302D342084C68E01";
let data_type = 3;
let custom_chain_identifier = 9000;
let account = r#"
{
"path": "m/44'/60'/0'/0/0",
"xfp": "f23f9fd2",
"address": "0x860A4E746FE4FDA40E98382B2F6AFC1D4040CAC7"
}
"#;
let origin = "Keplr Extension";

let expect_result = "{\"cbor\":\"a701d82550057523355d514a64a481ff2200000000025901330a9d010a9a010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64127a0a2c65766d6f73317363397975617230756e3736677235633871346a3736687572347179706a6b38336e786b7735122c65766d6f73317363397975617230756e3736677235633871346a3736687572347179706a6b38336e786b77351a1c0a07617465766d6f7312113130303030303030303030303030303030127e0a590a4f0a282f65746865726d696e742e63727970746f2e76312e657468736563703235366b312e5075624b657912230a21024f7a8d64e515ccf1e0a92a7c859262f425473cf09a50ebcaf3b06b156624145312040a020801181612210a1b0a07617465766d6f7312103236323530303030303030303030303010a8b4061a0c65766d6f735f393030302d342084c68e0103030419232805d90130a2018a182cf5183cf500f500f400f4021af23f9fd20654860a4e746fe4fda40e98382b2f6afc1d4040cac7076f4b65706c7220457874656e73696f6e\",\"type\":\"evm-sign-request\"}";

assert_eq!(
expect_result,
generate_evm_sign_request(request_id, sign_data, data_type, custom_chain_identifier, account, origin)
);
}

#[test]
fn test_generate_evm_sign_request_path_error() {
let request_id = "7AFD5E09-9267-43FB-A02E-08C4A09417EC";
let sign_data = "7B226163636F756E745F6E756D626572223A22323930353536222C22636861696E5F6964223A226F736D6F2D746573742D34222C22666565223A7B22616D6F756E74223A5B7B22616D6F756E74223A2231303032222C2264656E6F6D223A22756F736D6F227D5D2C22676173223A22313030313936227D2C226D656D6F223A22222C226D736773223A5B7B2274797065223A22636F736D6F732D73646B2F4D736753656E64222C2276616C7565223A7B22616D6F756E74223A5B7B22616D6F756E74223A223132303030303030222C2264656E6F6D223A22756F736D6F227D5D2C2266726F6D5F61646472657373223A226F736D6F31667334396A7867797A30306C78363436336534767A767838353667756C64756C6A7A6174366D222C22746F5F61646472657373223A226F736D6F31667334396A7867797A30306C78363436336534767A767838353667756C64756C6A7A6174366D227D7D5D2C2273657175656E6365223A2230227D";
let data_type = 1;
let custom_chain_identifier = 9000;
let account = "{}";
let origin = "Keplr";

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

assert_eq!(
expect_result,
generate_evm_sign_request(request_id, sign_data, data_type, custom_chain_identifier, account, origin)
);
}

#[test]
fn test_generate_evm_sign_request_err_sign_data() {
let request_id = "7AFD5E09-9267-43FB-A02E-08C4A09417EC";
let sign_data = "123412341";
let data_type = 1;
let custom_chain_identifier = 9000;
let account = r#"
{
"path": "m/44'/118'/0'/0/0",
"xfp": "f23f9fd2",
"address": "4c2a59190413dff36aba8e6ac130c7a691cfb79f"
}
"#;
let origin = "Keplr";

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

assert_eq!(
expect_result,
generate_evm_sign_request(request_id, sign_data, data_type, custom_chain_identifier, account, origin)
);
}
}
71 changes: 71 additions & 0 deletions libs/ur-registry-ffi/src/evm/evm_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use anyhow::Error;
use hex;
use serde_json::json;
use ur_registry::{registry_types::EVM_SIGNATURE, cosmos::evm_signature::EvmSignature};
use uuid::Uuid;

use crate::export;

export! {
@Java_com_keystone_sdk_KeystoneNativeSDK_parseEvmSignature
fn parse_evm_signature(ur_type: &str, cbor_hex: &str) -> String {
if EVM_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 sig = EvmSignature::try_from(cbor)?;
let uuid = sig.get_request_id();
let uuid_hex = hex::encode(uuid);
let request_id = Uuid::parse_str(&uuid_hex)?.to_string();
let signature = hex::encode(sig.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_evm_signature() {
let signature_cbor = "a201d82550057523355d514a64a481ff2200000000025840a0e2577ca16119a32f421c6a1c90fa2178a9382f30bf3575ff276fb820b32b3269d49d6bbfc82bae899f60c15de4b97f24a7ebb6d4712534829628ccfbef38bc";
let expect_result = "{\"request_id\":\"05752335-5d51-4a64-a481-ff2200000000\",\"signature\":\"a0e2577ca16119a32f421c6a1c90fa2178a9382f30bf3575ff276fb820b32b3269d49d6bbfc82bae899f60c15de4b97f24a7ebb6d4712534829628ccfbef38bc\"}";

assert_eq!(
expect_result,
parse_evm_signature("evm-signature", signature_cbor)
);
}

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

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

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

assert_eq!(
expect_result,
parse_evm_signature("evm-signature", signature_cbor)
);
}
}
2 changes: 2 additions & 0 deletions libs/ur-registry-ffi/src/evm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod evm_sign_request;
pub mod evm_signature;
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 @@ -2,6 +2,7 @@ pub mod aptos;
pub mod arweave;
pub mod bitcoin;
pub mod cosmos;
pub mod evm;
pub mod ethereum;
mod export;
pub mod sync;
Expand Down
6 changes: 3 additions & 3 deletions libs/ur-registry/src/cosmos/evm_sign_request.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::convert::From;
use minicbor::data::{Int, Tag};

use crate::cbor::{cbor_map};
use crate::cbor::cbor_map;
use crate::crypto_key_path::CryptoKeyPath;
use crate::impl_template_struct;
use crate::registry_types::{RegistryType, UUID, EVM_SIGN_REQUEST, CRYPTO_KEYPATH};
use crate::types::Bytes;
use crate::traits::{From as FromCbor, MapSize, RegistryItem, To};
use crate::traits::{MapSize, RegistryItem};

const REQUEST_ID: u8 = 1;
const SIGN_DATA: u8 = 2;
Expand Down Expand Up @@ -142,6 +141,7 @@ impl<'b, C> minicbor::Decode<'b, C> for EvmSignRequest {
#[cfg(test)]
mod tests {
use alloc::vec;
use alloc::vec::Vec;
use hex::FromHex;
use crate::crypto_key_path::PathComponent;
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly
nightly-2023-06-26

0 comments on commit eb444d0

Please sign in to comment.