Skip to content

Commit

Permalink
Merge pull request consenlabs#77 from consenlabs/feature/import_polka…
Browse files Browse the repository at this point in the history
…dotjs_keystore

Add support to import/export PolkadotJS Keystore
  • Loading branch information
XuNeal authored Jul 28, 2020
2 parents 73ebd62 + 4eeed05 commit a19487e
Show file tree
Hide file tree
Showing 25 changed files with 967 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tools/android-token-v2-simulator-build.sh
tools/ios-token-v2-build.sh
tools/ios-token-v2-simulator-build.sh
tools/ios-token-v2-release-build.sh
tools/ios-release-build.sh
tools/ios-internal-release.sh

ios-release/**

Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ build-ios-rn-example: ##@build generate the iOS RN compiled file
build-android-rn-example: ##@build generate the Android RN compiled file
sh ./tools/android-rn-example-build.sh

internal-release-android:
./tools/android-token-v2-build.sh

internal-release-ios: ##@build generate the Android RN compiled file
sh ./tools/ios-framework-build.sh
sh ./tools/ios-internal-release.sh $(VER)

e2e: ##@test run e2e test
(cd examples/RN && yarn)
(cd examples/RN/ios && pod install)
Expand Down
Binary file not shown.
14 changes: 11 additions & 3 deletions tcx-chain/src/keystore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub enum Error {
KeystoreLocked,
#[fail(display = "invalid_version")]
InvalidVersion,
#[fail(display = "pkstore_can_not_add_other_curve_account")]
PkstoreCannotAddOtherCurveAccount,
}

fn transform_mnemonic_error(err: failure::Error) -> Error {
Expand Down Expand Up @@ -135,11 +137,11 @@ pub enum Keystore {
}

impl Keystore {
pub fn from_private_key(private_key: &str, password: &str) -> Keystore {
pub fn from_private_key(private_key: &str, password: &str, meta: Metadata) -> Keystore {
Keystore::PrivateKey(PrivateKeystore::from_private_key(
private_key,
password,
Source::Wif,
meta,
))
}

Expand Down Expand Up @@ -682,10 +684,16 @@ mod tests {
"512115eca3ae86646aeb06861d551e403b543509"
);

let meta = Metadata {
name: "test_create".to_string(),
password_hint: TEST_PASSWORD.to_string(),
source: Source::Private,
..Metadata::default()
};
let pk_store = PrivateKeystore::from_private_key(
"a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6",
TEST_PASSWORD,
Source::Private,
meta,
);
let keystore = PrivateKey(pk_store);
assert_eq!(0, keystore.accounts().len());
Expand Down
24 changes: 15 additions & 9 deletions tcx-chain/src/keystore/private.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::Account;
use super::{Address, Metadata, Source};
use super::{Address, Metadata};
use tcx_constants::CoinInfo;
use tcx_crypto::{Crypto, Key, Pbkdf2Params};

Expand Down Expand Up @@ -77,6 +77,12 @@ impl PrivateKeystore {
pub(crate) fn derive_coin<A: Address>(&mut self, coin_info: &CoinInfo) -> Result<Account> {
tcx_ensure!(self.private_key.is_some(), Error::KeystoreLocked);

if self.store.active_accounts.len() > 0
&& self.store.active_accounts[0].curve != coin_info.curve
{
return Err(Error::PkstoreCannotAddOtherCurveAccount.into());
}

let sk = self.private_key.as_ref().unwrap();

let account = Self::private_key_to_account::<A>(coin_info, sk)?;
Expand Down Expand Up @@ -105,17 +111,12 @@ impl PrivateKeystore {
self.store.crypto.verify_password(password)
}

pub fn from_private_key(private_key: &str, password: &str, source: Source) -> PrivateKeystore {
pub fn from_private_key(private_key: &str, password: &str, meta: Metadata) -> PrivateKeystore {
let key_data: Vec<u8> = hex::decode(private_key).expect("hex can't decode");
let key_hash = key_hash_from_private_key(&key_data);
// let pk_bytes = hex::decode(private_key).expect("valid private_key");
let crypto: Crypto<Pbkdf2Params> = Crypto::new(password, &key_data);

let meta = Metadata {
source,
..Metadata::default()
};

let store = Store {
key_hash,
crypto,
Expand Down Expand Up @@ -164,15 +165,20 @@ impl PrivateKeystore {

#[cfg(test)]
mod tests {
use crate::{PrivateKeystore, Source};
use crate::{Metadata, PrivateKeystore, Source};
use tcx_constants::TEST_PASSWORD;

#[test]
pub fn from_private_key_test() {
let meta = Metadata {
name: "from_private_key_test".to_string(),
source: Source::Private,
..Metadata::default()
};
let keystore = PrivateKeystore::from_private_key(
"a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6",
TEST_PASSWORD,
Source::Private,
meta,
);
assert_eq!(keystore.store.version, 11001);
assert_ne!(keystore.store.id, "");
Expand Down
1 change: 1 addition & 0 deletions tcx-ckb/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ mod tests {
let mut ks = Keystore::from_private_key(
"dcec27d0d975b0378471183a03f7071dea8532aaf968be796719ecd20af6988f",
"Password",
Metadata::default(),
);
ks.unlock_by_password("Password").unwrap();

Expand Down
2 changes: 1 addition & 1 deletion tcx-constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use btc_fork_network::{
coin_from_xpub_prefix, network_form_hrp, network_from_coin, pub_version_from_prv_version,
BtcForkNetwork,
};
pub use coin_info::CoinInfo;
pub use coin_info::{coin_info_from_param, CoinInfo};
pub use curve::CurveType;

pub type Result<T> = std::result::Result<T, failure::Error>;
Expand Down
2 changes: 2 additions & 0 deletions tcx-primitive/src/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub enum KeyError {
NotEnoughMemory,
#[fail(display = "invalid_curve_type")]
InvalidCurveType,
#[fail(display = "invalid_sr25519_key")]
InvalidSr25519Key,
}

pub trait PublicKey: Sized {
Expand Down
26 changes: 15 additions & 11 deletions tcx-primitive/src/sr25519.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ecc::{PrivateKey as TraitPrivateKey, PublicKey as TraitPublicKey};
use crate::ecc::{KeyError, PrivateKey as TraitPrivateKey, PublicKey as TraitPublicKey};
use crate::{FromHex, Result, ToHex};
use schnorrkel::{ExpansionMode, MiniSecretKey};
use schnorrkel::SecretKey;

use sp_core::sr25519::{Pair, Public};
use sp_core::{Pair as TraitPair, Public as TraitPublic};
Expand Down Expand Up @@ -29,11 +29,12 @@ impl TraitPrivateKey for Sr25519PrivateKey {
type PublicKey = Sr25519PublicKey;

fn from_slice(data: &[u8]) -> Result<Self> {
let mini_key: MiniSecretKey =
MiniSecretKey::from_bytes(data).expect("32 bytes can always build a key; qed");

let kp = mini_key.expand_to_keypair(ExpansionMode::Ed25519);
Ok(Sr25519PrivateKey(Pair::from(kp)))
// let mini_key: MiniSecretKey =
// MiniSecretKey::from_bytes(data).expect("32 bytes can always build a key; qed");
//
// let kp = mini_key.expand_to_keypair(ExpansionMode::Ed25519);
let pk = SecretKey::from_ed25519_bytes(data).map_err(|_| KeyError::InvalidSr25519Key)?;
Ok(Sr25519PrivateKey(Pair::from(pk)))
}

fn public_key(&self) -> Self::PublicKey {
Expand Down Expand Up @@ -91,17 +92,20 @@ mod tests {
#[test]
fn test_private_key_from_slice() {
let pk_bytes: Vec<u8> =
hex::decode("1111111111111111111111111111111111111111111111111111111111111111")
hex::decode("00ea01b0116da6ca425c477521fd49cc763988ac403ab560f4022936a18a4341016e7df1f5020068c9b150e0722fea65a264d5fbb342d4af4ddf2f1cdbddf1fd")
.unwrap();
let pk: Sr25519PrivateKey = Sr25519PrivateKey::from_slice(&pk_bytes).unwrap();
assert_eq!("704b72419b89bab3a4632685428901bf5715b44e40ec0df50f01fdc1553bf60b092539815e61663c7f9c4c9c377346f5d2936875bd760f0ac5c5f4f6e78a6d76", hex::encode(pk.to_bytes()));
assert_eq!(
&hex::encode(pk.to_bytes())[64..],
"016e7df1f5020068c9b150e0722fea65a264d5fbb342d4af4ddf2f1cdbddf1fd"
);
let public_key: Sr25519PublicKey = pk.public_key();
assert_eq!(
"50780547322a1ceba67ea8c552c9bc6c686f8698ac9a8cafab7cd15a1db19859",
"fc581c897af481b10cf846d88754f1d115e486e5b7bcc39c0588c01b0a9b7a11",
public_key.to_hex()
);
assert_eq!(
"5DtDLm5rQHShDqojQpsvcN8tRXHVFaecfDoRet1SU6BFD9Fi",
"5Hma6gDS9yY7gPTuAFvmMDNcxPf9JqMZdPsaihfXiyw5NRnQ",
format!("{}", public_key)
);
}
Expand Down
5 changes: 4 additions & 1 deletion tcx-proto/src/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,7 @@ message ExportPrivateKeyParam {
message WalletKeyParam {
string id = 1;
string password = 2;
}
}



5 changes: 4 additions & 1 deletion tcx-proto/src/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ enum KeyType {
message PrivateKeyStoreImportParam {
string privateKey = 1;
string password = 2;
bool overwrite = 3;
string name = 3;
string passwordHint = 4;
bool overwrite = 5;
}

// FUNCTION: private_key_store_export(PrivateKeyStoreExportParam): KeystoreCommonExportResult
Expand Down Expand Up @@ -181,3 +183,4 @@ message HdStoreExtendedPublicKeyParam {
message HdStoreExtendedPublicKeyResponse {
string extendedPublicKey = 1;
}

13 changes: 13 additions & 0 deletions tcx-proto/src/substrate.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
syntax = "proto3";
package transaction;


message SubstrateKeystoreParam {
string keystore = 1;
string password = 2;
string chainType = 3;
bool overwrite = 4;
}


message ExportSubstrateKeystoreResult {
string keystore = 1;
}

message SubstrateRawTxIn {
string rawData = 1;
}
Expand Down
5 changes: 5 additions & 0 deletions tcx-substrate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ prost-types = "0.6.1"
base58 = "0.1.0"
bs58 = "0.3.0"
codec = { package = "parity-scale-codec", branch = "v1.0", default-features = false, features = ["derive"] }
rand = "0.6"

failure = "0.1.5"
#tweetnacl = "0.2.1"
xsalsa20poly1305 = "0.4.2"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }

[dev-dependencies]
sp-runtime = "2.0.0-rc3"
Expand Down
Loading

0 comments on commit a19487e

Please sign in to comment.