-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from KeystoneHQ/evm
support evm
- Loading branch information
Showing
7 changed files
with
242 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod evm_sign_request; | ||
pub mod evm_signature; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
nightly | ||
nightly-2023-06-26 |