Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

Problem:(fix #827)no import/export for non-HD keys #1106

Merged
merged 1 commit into from
Feb 24, 2020

Conversation

linfeng-crypto
Copy link
Contributor

Solution:

  • add export method to backup a wallet, and import method to store the wallet again, both in client-rpc and client-cli
  • add unit test

parse(from_os_str),
help = "file to dump wallet"
)]
file: PathBuf,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to treat a special value "-" as stdout and make it the default value, so the command can work with pipes in shell.

parse(from_os_str),
help = "file stored the wallet info"
)]
file: PathBuf,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to treat a special value "-" as stdin and make it the default value, so the command can work with pipes in shell.

Copy link
Contributor Author

@linfeng-crypto linfeng-crypto Feb 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, I serialized the wallet info as multiline json string using the serde_json::to_string_pretty.

If the wallet info inputted from the terminal, I have to serialize the wallet info into one line json string. By the way, the output is colored and there is a waring messge like Warning! CRYPTO_CHAIN_ID environment variable is not set. Setting network to devnet and network-id to 0. I don't think the the pipes can work well.

Copy link
Collaborator

@yihuang yihuang Feb 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean something like this:

let output = if name == "-" {
  std::io::stdout
} else {
  File::open(name)...
};
output.write_all(...);

If warnings are going to stderr, then it's ok, otherwise, it's indeed problematic.

Copy link
Collaborator

@leejw51crypto leejw51crypto Feb 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- is too short , "console"?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- is too short , "console"?

- is like a conventional name for this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does the command work with -, like this?

cat wallet_file | ./client-cli wallet import -

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one way to use it, but only some developers know it.

Copy link
Collaborator

@yihuang yihuang Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does the command work with -, like this?

cat wallet_file | ./client-cli wallet import -

Yes, with pipes it can work with other tools together, for example, compression tool, assuming stdin/stdout is the default:

$ ./client-cli wallet export --all | gzip > wallets.export.gz
$ zcat wallets.export.gz | ./client-cli wallet import

@yihuang
Copy link
Collaborator

yihuang commented Feb 19, 2020

We had an issue before to import/export all wallets at once, which is closed for duplication of this one, so I presume this one should support import/export all wallets at once?

@tomtau
Copy link
Contributor

tomtau commented Feb 19, 2020

We had an issue before to import/export all wallets at once, which is closed for duplication of this one, so I presume this one should support import/export all wallets at once?

@leejw51crypto is this one ok as is, or should it take say several names of wallets, or a flag --all and ask for individual details (and then dump all in one file or ask for several ?)

@codecov
Copy link

codecov bot commented Feb 19, 2020

Codecov Report

Merging #1106 into master will decrease coverage by 1.07%.
The diff coverage is 36.78%.

@@            Coverage Diff            @@
##           master   #1106      +/-   ##
=========================================
- Coverage   65.57%   64.5%   -1.08%     
=========================================
  Files         145     149       +4     
  Lines       19041   19677     +636     
=========================================
+ Hits        12487   12692     +205     
- Misses       6554    6985     +431
Impacted Files Coverage Δ
client-rpc/src/rpc/sync_rpc.rs 0% <ø> (ø) ⬆️
client-rpc/src/rpc/multisig_rpc.rs 31.27% <ø> (ø) ⬆️
client-rpc/src/rpc/staking_rpc.rs 0% <ø> (ø) ⬆️
client-rpc/src/server.rs 6.36% <ø> (-4.85%) ⬇️
client-cli/src/command/wallet_command.rs 0% <0%> (ø) ⬆️
chain-tx-validation/src/lib.rs 70.3% <100%> (-0.13%) ⬇️
client-core/src/wallet.rs 100% <100%> (ø)
client-core/src/service/wallet_service.rs 78.5% <4.76%> (-8.1%) ⬇️
client-core/src/wallet/default_wallet_client.rs 42.51% <85.71%> (+4.24%) ⬆️
client-rpc/src/rpc/wallet_rpc.rs 65.09% <94.87%> (+4.37%) ⬆️
... and 26 more

@leejw51crypto
Copy link
Collaborator

leejw51crypto commented Feb 19, 2020

import and export all wallets would be better
dump all to one file also using one password?
if decoding fails, we can ask again

consider that wallets can be over 100 or thousands

@tomtau
Copy link
Contributor

tomtau commented Feb 19, 2020

import and export all wallets would be better
dump all to one file also using one password?
if decoding fails, we can ask again

consider that wallets can be over 100 or thousands

  1. will anyone have client-cli with that many wallets? there'll be other issues arising for that, so it can be left for now

  2. each wallet may a different passphrase

@leejw51crypto
Copy link
Collaborator

leejw51crypto commented Feb 19, 2020

yes, that's possible scenario for special use case
a few hundreds are common , i think

@yihuang
Copy link
Collaborator

yihuang commented Feb 20, 2020

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

@linfeng-crypto
Copy link
Contributor Author

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

I think it's user's response to encrypt data and keep the file safe, just like the mnemonics. It's not the client's business.

#[structopt(
name = "from_file",
short = "f",
long = "from_file",
Copy link
Collaborator

@leejw51crypto leejw51crypto Feb 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about just from

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok -- if it's too long, one can just use -f ... -t ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

#[structopt(
name = "to_file",
short = "t",
long = "to_file",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just 'to'?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leejw51crypto
Copy link
Collaborator

also addresses, roothashes(mutlsig addresses) need to export, import

@yihuang
Copy link
Collaborator

yihuang commented Feb 20, 2020

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

I think it's user's response to encrypt data and keep the file safe, just like the mnemonics. It's not the client's business.

I mean if we don't decrypt the information, we can simply:

client-cli export --all

No need to worry about different passphrases of different wallets.

@linfeng-crypto
Copy link
Contributor Author

linfeng-crypto commented Feb 21, 2020

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

I think it's user's response to encrypt data and keep the file safe, just like the mnemonics. It's not the client's business.

I mean if we don't decrypt the information, we can simply:

client-cli export --all

No need to worry about different passphrases of different wallets.

sure, to get the private key, the workflow is wallet_name -> public key -> private key, but we should give a enckey to get the public key, or we have to store the un-encrypted mapwallet_name->pubkey, is it safe?

@yihuang
Copy link
Collaborator

yihuang commented Feb 21, 2020

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

I think it's user's response to encrypt data and keep the file safe, just like the mnemonics. It's not the client's business.

I mean if we don't decrypt the information, we can simply:

client-cli export --all

No need to worry about different passphrases of different wallets.

sure, to get the private key, the workflow is wallet_name -> public key -> private key, but we should give a enckey to get the public key, or we have to store the un-encrypted mapwallet_name->pubkey, is it safe?

Yeah, that's a block, the structure of the key service is to be changed in #914, after that it probably will be changed to wallet_name -> key_pairs.
Before that, I guess we just have to stick to the current solution?

@linfeng-crypto
Copy link
Contributor Author

Is it better to let export/import the encrypted data as is, not to decrypt and re-encrypt? This will work for multiple wallets with different passphrases.
And it's safer because the information is not decrypted?

I think it's user's response to encrypt data and keep the file safe, just like the mnemonics. It's not the client's business.

I mean if we don't decrypt the information, we can simply:

client-cli export --all

No need to worry about different passphrases of different wallets.

sure, to get the private key, the workflow is wallet_name -> public key -> private key, but we should give a enckey to get the public key, or we have to store the un-encrypted mapwallet_name->pubkey, is it safe?

Yeah, that's a block, the structure of the key service is to be changed in #914, after that it probably will be changed to wallet_name -> key_pairs.
Before that, I guess we just have to stick to the current solution?

sure

Copy link
Contributor

@tomtau tomtau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a small clippy suggestion:

error: single-character string constant used as pattern
1564   --> client-cli/src/command/wallet_command.rs:196:41
1565    |
1566196 |                 for name in names.split(",") {
1567    |                                         ^^^ help: try using a char instead: `','`
1568    |
1569    = note: `-D clippy::single-char-pattern` implied by `-D warnings`
1570    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
1571
1572error: aborting due to previous error
  • could you squash the commits?

#[serde(deserialize_with = "deserde_from_str", serialize_with = "serde_to_str")]
pub private_key: PrivateKey,
/// passphrase used when import wallet
pub passphrase: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String -> SecUtf8?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or Option, as it's optional (the client would ask for it if not provided?)?

Copy link
Contributor

@tomtau tomtau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two small comments:

  1. type of passphrase would be better Option<SecUtf8> rather than String to make it more concrete
  2. export json settings can be extracted out into a struct / data type

Comment on lines 209 to 226
let wallet_settings: Value = serde_json::from_str(&settings)
.chain(|| (ErrorKind::InvalidInput, "Invalid wallet info"))?;
let wallet_settings = wallet_settings.as_array().chain(|| {
(
ErrorKind::InvalidInput,
"from_file should contains a list of setting",
)
})?;
for setting in wallet_settings {
let name = setting["name"]
.as_str()
.chain(|| (ErrorKind::InvalidInput, "expect name"))?;
let key = setting["auth_token"]
.as_str()
.chain(|| (ErrorKind::InvalidInput, "Expect auth_token"))?;
let enckey = parse_hex_enckey(&key).map_err(|_e| {
error(&format!("error auth_token of wallet {}", name));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably giving it a data type "Vec" with serde implementations would be less error-prone ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

parse(from_os_str),
help = "file stored the wallet info"
)]
file: PathBuf,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does the command work with -, like this?

cat wallet_file | ./client-cli wallet import -

Solution:
* add export/import wallet, the dumpped info include private key, wallet name, and all information in `Wallet` struct
* in client-cli, can dump many wallets at onece by a setting file which include wallet name and auth-token
* the dumpped wallet information is not encrypted, so carefule backup it.
@tomtau
Copy link
Contributor

tomtau commented Feb 24, 2020

bors r+

@bors
Copy link
Contributor

bors bot commented Feb 24, 2020

@bors bors bot merged commit 5608759 into crypto-com:master Feb 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants