Coder Social home page Coder Social logo

forc-wallet's Introduction

forc-wallet

A forc plugin for managing Fuel wallets.

Quickstart

Installation through fuelup (recommended)

forc-wallet is packaged alongside the default distributed toolchains when installed using fuelup. If you have the latest toolchain installed, you should already have forc-wallet available:

$ fuelup toolchain install latest
$ forc-wallet --version
forc-wallet 0.2.2

For usage in custom toolchains:

fuelup component add forc-wallet

Installation through cargo

Otherwise, you may use cargo:

cargo install forc-wallet

Create a wallet

Before creating accounts and signing transactions with them you need to create a wallet. To do so:

forc-wallet new

This will require a password for encrypting the wallet. After the wallet is created you will be shown the mnemonic phrase.

Note: You will need your password for signing and account derivation, and you will need your mnemonic phrase if you wish to recover your wallet in the future.

Import a wallet

To import a wallet from an existing mnemonic phrase, use:

forc-wallet import

Note: forc-wallet adheres to the Web3 Secret Storage Definition and accepts paths to wallet files that adhere to this standard.

Create an account

To create an account for the wallet, you can run:

forc-wallet account new

This will require your wallet password (the one that you chose during creation). This command will always derive the next account that has not yet been derived locally.

To list all accounts derived so far, use the following:

forc-wallet accounts

Note: When we "create" an account, we are really just revealing it. All accounts are derived deterministically based on the wallet's mnemonic phrase and derivation path. forc-wallet will cache the public addresses of derived accounts within ~/.fuel/wallets/accounts.

Sign a transaction

To sign a transaction, you can provide the transaction ID. You can generate a transaction and get its ID using forc-client. Signing the transaction once you have the ID is simple:

forc-wallet account <account_index> sign tx-id <transaction_id>

Sign arbitrary data

You may sign a string directly:

forc-wallet account <account_index> sign string "Blah blah blah"

Or the contents of a file:

forc-wallet account <account_index> sign file <path>

You may also sign a hex-encoded byte string:

forc-wallet account <account_index> sign hex 0x0123456789ABCDEF

You can also use the sign subcommand directly, e.g. the following is the same:

forc-wallet sign --account <account_index> hex 0x0123456789ABCDEF

Using the sign subcommand, you can choose to sign directly with a private key (rather than a wallet account):

forc-wallet sign --private-key hex 0x0123456789ABCDEF

Other useful commands

Get address of an account

To derive the address of a specific account, you can use:

forc-wallet account <account_index>

Get private key of an account

To retrieve the private key of a specific account, you can use:

forc-wallet account <account_index> private-key

Get public key of an account

To retrieve the public key of a specific account, you can use:

forc-wallet account <account_index> public-key

forc-wallet's People

Contributors

bingcicle avatar braqzen avatar crodas avatar crypdoughdoteth avatar dentosal avatar digorithm avatar hal3e avatar iqdecay avatar kayagokalp avatar levisyin avatar mitchmindtree avatar sarahschwartz avatar smuueth avatar voxelot avatar xgreenx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

forc-wallet's Issues

Improve wallet path handling

Currently in nearly each command handling function, we have something like

let wallet_path = match &path {
  Some(path) => PathBuf::from(path),
  None => home::home_dir().unwrap().join(DEFAULT_WALLETS_VAULT_PATH),
}

We can clean it by having a util function for this, more details can be found at #47 (comment)

Move `forc-wallet` to `sway` repo

As forc-wallet is another forc plugin, we discussed with @mitchmindtree a couple of days ago the possible pros of moving it to sway repo (under forc-plugins).

  1. fuelup can automatically pack forc-wallet with other plugins like forc-fmt so that it will be installed automatically
  2. Documentation for the forc-wallet will be automatically added in the appropriate section of the Sway Book
  3. We can call forc-wallet by executing forc wallet as forc will assume it is a plugin and try to run it like forc-wallet under the hood.

We can discuss here if anyone has some ideas or objections.

Add export and import to readme section

Export is widely missed and comes up as a question from discord. It would make sense to give examples and explanations for it (and maybe also for import too) in the readme.

Add support for signing transaction files and adding the generated signature as a witness

The new forc tx command allows for constructing transactions and outputting them to a file in a serialized form. Similarly, we anticipate adding support for writing transactions generated from forc deploy or forc run to file (see FuelLabs/sway#4130).

It would be great if we could use forc wallet to sign a potentially unsigned transaction and automatically add the generated signature as a witness. This would likely help a lot with shell-oriented workflows and testing.

This should look something like the following:

  1. Read and deserialize the transaction file into memory.
  2. Calculate the transaction ID (with cleared witnesses and necessary serialization format).
  3. Sign the transaction ID.
  4. Append the signature to the transaction's list of witnesses.
  5. Serialize the transaction to the same format it was deserialized from.
  6. Write the updated transaction to a new file <original-tx-path>-signed.<extension> (or overwrite the existing?).
  7. Output the new signature along with its index in the list of witnesses to stdout.

cc @nfurfaro @simonr0204 in case you have any other thoughts/ideas to add!

RUSTSEC-2020-0071: Potential segfault in the time crate

Potential segfault in the time crate

Details
Package time
Version 0.1.44
URL time-rs/time#293
Date 2020-11-18
Patched versions >=0.2.23
Unaffected versions =0.2.0,=0.2.1,=0.2.2,=0.2.3,=0.2.4,=0.2.5,=0.2.6

Impact

Unix-like operating systems may segfault due to dereferencing a dangling pointer in specific circumstances. This requires an environment variable to be set in a different thread than the affected functions. This may occur without the user's knowledge, notably in a third-party library.

The affected functions from time 0.2.7 through 0.2.22 are:

  • time::UtcOffset::local_offset_at
  • time::UtcOffset::try_local_offset_at
  • time::UtcOffset::current_local_offset
  • time::UtcOffset::try_current_local_offset
  • time::OffsetDateTime::now_local
  • time::OffsetDateTime::try_now_local

The affected functions in time 0.1 (all versions) are:

  • at
  • at_utc
  • now

Non-Unix targets (including Windows and wasm) are unaffected.

Patches

Pending a proper fix, the internal method that determines the local offset has been modified to always return None on the affected operating systems. This has the effect of returning an Err on the try_* methods and UTC on the non-try_* methods.

Users and library authors with time in their dependency tree should perform cargo update, which will pull in the updated, unaffected code.

Users of time 0.1 do not have a patch and should upgrade to an unaffected version: time 0.2.23 or greater or the 0.3 series.

Workarounds

No workarounds are known.

References

time-rs/time#293

See advisory page for additional details.

Commit lockfile

This is a binary crate, so the lockfile needs to be committed.

RUSTSEC-2021-0060: `aes-soft` has been merged into the `aes` crate

aes-soft has been merged into the aes crate

Details
Status unmaintained
Package aes-soft
Version 0.6.4
URL RustCrypto/block-ciphers#200
Date 2021-04-29

Please use the aes crate going forward. The new repository location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To force the use of a constant-time portable implementation on these platforms,
even if AES-NI is available, use the new force-soft feature of the aes
crate to disable autodetection.

See advisory page for additional details.

feat: `new` command

after randomly generating the wallet we are encrypting and storing it in the vault

That needs to be spec'd out first. Is the wallet going to use a mnemonic? Will forc-wallet new generate a new mnemonic?

Originally posted by @adlerjohn in #8 (comment)

Update sway book and developer quickstart with new command set

We have a section in the sway book under forc-client explaining how to use it with forc-wallet (since usage of forc-client generally means usage of forc-wallet).

We also have a developer quickstart that might need a little bit of love after the changed set of commands gets released. Since they are in different repos it might be possible to miss them but we should probably update them as soon as we release this new set of commands in the next release of forc-wallet

AlternateScreen dropping bug can cause losing discrete string

Because of this issue (more like a design decision I guess), we might run into situations where AlternateScreen is dropped and thus closes even before the users can see the information we were trying to show them. This is possible after #51 since we are using a function to call AlternateScreen and once the function is dropped the internal variables are also dropped.

Use a single wallet file for storing both the keystore and derived account tracking

It would be nice if a user could store their wallet within a single file in a portable way without having to zip up a directory.

It would also help with some of the ambiguity around "wallet paths" in the UI, as it's not always clear if a wallet path refers to a .wallet file (the keystore), or the directory containing both .wallet and .accounts files.

Currently, it looks like the main reason we store the .wallet keystore and .accounts data in separate files is because the eth_keystore crate only exposes functions that operate on the keystore as an independent file. We could easily work around this by serializing just the keystore to a temporary file, interacting with eth_keystore crate, then updating our original wallet file as necessary.

File Layout

A simple JSON file that basically joins our current files, e.g.

{
    "keystore": /* serialization of keystore (currently `.wallet`) */,
    "accounts": /* serialization of `Accounts` (currently `.accounts`) */
}

Full example:

{
  "keystore": {
    "crypto": {
      "cipher": "aes-128-ctr",
      "cipherparams": {
        "iv": "749e7fab374762912860986c2e08d48e"
      },
      "ciphertext": "032cd4033bf089c54f3c36947cc072b75bf936d3a1b74e351d7fba8531d41c3a60dbf68314f5d495426ffc15c214e57d06eca1be09a58527ad2efca1939cb4137dfe8b346b3c76a6287f8e4c58e6a7b5a7c8f3d4f32db984bafea521d7808f0aecff40d043106e72651ce2f33646653de62b9bc137dd6688af0d38572344e99b91d1599d4bb6d633b60de00aaf12c5b8",
      "kdf": "scrypt",
      "kdfparams": {
        "dklen": 32,
        "n": 8192,
        "p": 1,
        "r": 8,
        "salt": "398e5f2d3fb11f3aa009d209da9dd02c43568b343f7162499669c74957c9bb98"
      },
      "mac": "9885432bf3b6e914bdb312a37babcca19becfc4f7d86d913ebcc172bcd1a9f22"
    },
    "id": "dc8c6438-f953-4a1d-8abc-52cf403d9915",
    "version": 3
  },
  "accounts": {
    "addresses": [
      "fuel1htrldg7wpelrnhvad8lwcep57duhpxmj2h6a55nhr4md4839cy2q04p3tu"
    ]
  }
}

Note the accounts layout may be subject to change as of #77.


Edit: Please correct me if I'm missing some other motivation to using solely .wallet keystore files! E.g. Perhaps this is some standard file format that can be used with different ETH tooling?

Expand the README to include installation instructions and steps for usage

The README.md does not contain any installation instructions and it only shows the output of the --help.

It should be clear to the user how to install the plugin and how to perform an action - namely creating the wallet.
For a dev with experience or knowledge of the project / similar tools it is easy to follow the help but for a new user instructions are very helpful.

I suggest adding the gif from #3 as well.

RUSTSEC-2021-0059: `aesni` has been merged into the `aes` crate

aesni has been merged into the aes crate

Details
Status unmaintained
Package aesni
Version 0.10.0
URL RustCrypto/block-ciphers#200
Date 2021-04-29

Please use the aes crate going forward. The new repository location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To prevent this fallback (and have absence of AES-NI result in an illegal
instruction crash instead), continue to pass the same RUSTFLAGS which were
previously required for the aesni crate to compile:

RUSTFLAGS=-Ctarget-feature=+aes,+ssse3

See advisory page for additional details.

feat: add the `from` feature

# Add a wallet from a private key. Note that this should prompt a password input, so the private key
# won't live in the terminal's history.
forc wallet from

        Private key:
        [enter private key]

        Please enter a password to encrypt this private key:
        [enter once]
        
        Please re-enter:
        [enter again]

Allow wallet to sign bytes

cc @kayagokalp @mitchmindtree

Context

  • On the Indexer's beta-4 milestone we're trying to implement FuelLabs/fuel-indexer#240
  • We would prefer to implement any authentication via what's already available in the Fuel ecosystem -- i.e., use forc-wallet
  • As it stands (and this could change) we're expecting to implement a method where in which indexer users (those building and deploying indexers) authenticate against indexer operators (those running the actual indexer services) by simply signing some message, then sending that message to an indexer service so that the service can verify that the user signed the message (thus "authenticating" them).
  • โš ๏ธ Note that we would also need some way for the user to export their public key in a way that can easily be sent in an HTTP request
    • The indexer service would use that public key on the backend to assert that the message was signed by the proper usage

Implementation

  • This is just an idea doesn't have to look like this

Signatures

forc-wallet sign --raw 'my super secret message' --account-index 0

> 0xf86c0a8502540be400825208944bbeeb066ed09b7aed07bf39eee0460dfa261520880de0b6b3a7640000801ca0f3ae52c1ef3300f44df0bcfd1341c232ed6134672b16e35699ae3f5fe2493379a023d23d2955a239dd6f61c4e8b2678d174356ff424eac53da53e17706c43ef871
  • As discussed with @kayagokalp, we could also allow for signing a file (assuming it's not too much additional work)
forc-wallet sign --file /path/to/file.txt --account-index 0

> 0xf86c0a8502540be400825208944bbeeb066ed09b7aed07bf39eee0460dfa261520880de0b6b3a7640000801ca0f3ae52c1ef3300f44df0bcfd1341c232ed6134672b16e35699ae3f5fe2493379a023d23d2955a239dd6f61c4e8b2678d174356ff424eac53da53e17706c43ef871

Exporting pubkey

  • Assuming current export functionality doesn't include the public key with the exported private key
forc-wallet export --account-index <account_index> --pubkey

> 63FaC9201494f0bd17B9892B9fae4d52fe3BD377

Clarify support around multiple wallets. Remove ambiguous "vault" terminology.

Currently, there's some ambiguity around forc wallet's support for multiple wallets.

The default "vault" directory is .fuel/wallets.

However, in practice, all uses of this directory assume a single wallet with a single set of accounts. E.g. the default .wallet and .accounts files are dumped directly in .fuel/wallets.

I propose the following:

  1. For now, clarify that in order to use anything other than the default wallet, a full path to the custom wallet must be specified.
  2. Change the default wallet path to .fuel/wallets/default in anticipation of potentially supporting multiple wallets (e.g. by name) under .fuel/wallets in the future.
  3. Remove the "vault" terminology from the UI and code in favour of "wallet" when referring to the .wallet file. Currently, the two terms are used interchangeably throughout the code-base and help text and it can be confusing until realizing that there's no practical distinction.

Try to separate CLI and operation logic throughout `forc-wallet`

Currently in the forc-wallet, CLI operations such as taking input and the specific operation logic are tightly coupled. I think we should try to separate them as much as possible so that we can:

  1. Write more comprehensive tests
  2. If we decide to consume this later on from forc-client, we could also do that

Ambiguity between referring to wallet or account in commands (e.g. new, init, list)

Currently, the new command allows for deriving a new account, while init allows for initializing a wallet. This can be a little confusing for users, as forc wallet new looks a lot like creating a new wallet, when it actually just creates a new account for the default wallet.

Similarly, forc wallet list does not output a list of wallets, rather it outputs a list of accounts.

I propose we use account as a general subcommand for all account-related operations, and remove the init command altogether. This would look like the following:

Existing commands

  • forc wallet new
    • Previously: forc wallet init. Create a new wallet.
  • forc wallet import
    • No change. Imports a wallet from a seed phrase.
  • forc wallet accounts
    • Previously forc wallet list. List all previously derived accounts.
  • forc wallet account new
    • Previously forc wallet new. Create a new account.
  • forc wallet account <ix>
    • Previously forc account <ix>. Derive the acc at the given index.
  • forc wallet account <ix> export-private-key
    • Previously forc wallet export --account-index <ix>.
  • forc wallet account <ix> sign tx <tx-id>
    • Previously forc wallet sign --acount-index <ix> --id <tx-id>. Sign a transaction ID.

Upcoming commands

  • forc wallet account <ix> sign file <path>
    • Sign arbitrary data in the form of bytes read from a file.
  • forc wallet account <ix> sign data <string>
    • Sign arbitrary data in the form of a string.
  • forc wallet account <ix> send --gas-price <price> --gas-limit <lmt> --asset-id <id> <amount>
    • Send assets from the specified account.
  • forc wallet send --gas-price <price> --gas-limit <lmt> --asset-id <id> <amount>
    • Automatically aggregates UTXOs from all accounts to send an asset.

Beyond reducing ambiguity, putting account-specific commands behind a subcommand like this potentially opens up the options for "smart" versions of other commands. E.g. forc wallet sign [tx|file|data] <tx-id|path|string> could potentially automatically derive a new account and use it to sign some data?

We can also handle cases where the user tries to do something account related without creating or specifying a wallet in one place, rather than checking within each of the separate account-related sub-commands individually.

Consider not storing newly derived account addresses in plain text?

Currently, we write newly derived addresses to an .accounts file in order to keep track of what addresses have been used so far. This exposes all derived account addresses in plain-text to any user process, which might be unexpected to the user. E.g. the Trezor Suite requires using your hardware wallet to view account addresses, whether previously derived or not.

Proposed Alternative

Rather than storing full addresses, we may want to consider the following:

  1. Only store the index of each derived account so that we can keep track of which accounts have already been derived without revealing all derived addresses in plain text.
  2. Require the user enters a password for forc wallet list or forc wallet account <ix> so that they can be derived upon request.

Otherwise, at the very least we should warn the user that derived account addresses are stored in plain text.

This is a bit of a UX trade-off, as some users may not care about exposing their derived public addresses, and prefer to not require inputting a password to retrieve them.

I think it's likely better to assume that the user wants the more secure option, and leave it to the user to manage their own plain-text files of addresses if they wish to do so.

cc @nfurfaro @simonr0204 @adlerjohn thoughts?

feat: Get private key of a wallet created with forc wallet

Currently, you cannot get the private key of a wallet. This is useful when you want to use a single account to sign transactions in other applications without using the seed phrase, exposing the wallet.

Having a command like this would be helpful: forc wallet account 0 export

Without the private key, developers have to create a private key in a different wallet and manage the wallets manually. Currently, you can use the seed phrase, but we don't want to encourage users to expose their seed phrase.

Thank you @luizstacio for helping me figure this out

Add a command to sign with private key

Although this is not ideal, while testing signed transactions that goes to local node, it would be really nice to have a command that signs transactions with private key directly. Otherwise the initial accounts funded by the local node cannot be used to sign without a custom chain config file.

So for rapid development agains local node we may want to add a command that directly accepts a private key so that users can use initial account of local node.

Faucet integration?

Raised by @Braqzen, it would be great to have some sort of faucet for getting test funds on the CLI.

Currently our web faucet uses a captcha as a kind of rate-limit to stop folks programmatically rinsing the faucet. It might be tricky to achieve something as effective on a CLI that cannot be trivially worked around.

At the very least, we should provide a link to the web faucet for the user in the default help output or something along these lines.

Forc wallet management feature

Introduce a new command in forc to enable wallet management, this includes the creation of a wallet, signing and verification of hashes, and more. A couple of initial examples above:

outdated, do not read ``` # Generate a new Wallet. forc wallet new
    Please enter a password to encrypt this private key:
    [enter once]
    
    Please re-enter:
    [enter again]

Add a wallet from a private key. Note that this should prompt a password input, so the private key

won't live in the terminal's history.

forc wallet from

    Private key:
    [enter private key]

    Please enter a password to encrypt this private key:
    [enter once]
    
    Please re-enter:
    [enter again]

Verify a signature of a specific wallet

forc wallet verify

Sign a hash

forc wallet sign

Get the address of a wallet

forc wallet address

List the wallets available.

forc wallet list

   Num.      Address.
   [0].      0xabc...dbne

Clear a wallet from storage.

forc wallet clear

</details>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.