Skip to content
This repository has been archived by the owner on Aug 8, 2018. It is now read-only.

Account Management

howardpmarks edited this page Nov 16, 2015 · 11 revisions

Account management

Warning: Every account is encrypted with a password. If you forget this password, there is no way to access the account anymore. Consider using a password manager.

Warning: Likewise, don't lose your keystore files. If you do, you won't be able to restore your accounts, even if you still remember your passwords. Make frequent backups!

Theory

Accounts in Ethereum are identified by an address (usually displayed as 40 hex characters, sometimes prefixed with 0x). The address is derived from a private key which is used to sign transactions from this address. For persistent storage, the private keys are being encrypted and saved, along with some meta information, in keystore files (see this document for a technical description). Thus, for each account a password must be chosen and everytime an account is used, it must be decrypted.

Note that it is not possible to derive the address from an encrypted private key without knowing the password. Therefore, the address is usually stored in the keystore file as well, but this is optional (for privacy reasons, some users may prefer to keep their addresses hidden).

Keystore directory

By default, private keys are stored in the directory <data_dir>/keystore. This can be configured via the accounts.keystore_dir config entry, either as an absolute path or relative to <data_dir>. Every file in this directory (and any subdirectory) is considered to be a keystore file.

Export Accounts to Go-Client

To import your Ethereum Python-Client accounts, stored in the directroy <data_dir>/keystore, to the Ethereum Go-Client (geth) simply copy and paste the file of the desired account inside the Python <data_dir>/keystore directory to the Go <data_dir>/keystore. This second on is usual stored in '/home/.ethereum/keystore' or '/home/.ethereum/testnet/keystore', depending on the desired network.

Import Accounts from Go-Client

Same as above, just change the direction of the files, i.e. this time from Geth Keystore to Pyethapp Keystore.

Account management via the command line

Accounts are created with pyethapp account new. The private key is generated randomly, but you will be prompted for a password to encrypt it. If desired, a (most likely) unique id can be added to the account with the --uuid (-i) flag. The account will be stored in the keystore directory, with its address as filename.

$ pyethapp account new  # omitting log messages
Password to encrypt private key: 
Repeat for confirmation: 
Account creation successful
  Address: d6aaae06717f25095eab8250369a437e549160a4
       Id: None
$ pyethapp account new --uuid
Password to encrypt private key: 
Repeat for confirmation: 
Account creation successful
  Address: 8aa3a4f9d58950738a12ed2e19e977ffb350a806
       Id: 18dc18ed-8a25-4961-8e7f-50a9b18ec4f7

To list all accounts known to pyethapp use pyethapp account list. This will show addresses and ids as well as a flag indicating if the account is locked (i.e. if the private key is still encrypted.

$ pyethapp account list
     Address (if known)                       Id (if any)                          Locked
  #1 8aa3a4f9d58950738a12ed2e19e977ffb350a806 18dc18ed-8a25-4961-8e7f-50a9b18ec4f7 yes
  #2 a9544551461d01e632b0bfb2ef70c8bf8ea5f06d                                      yes
  #3 d6aaae06717f25095eab8250369a437e549160a4                                      yes

Importing an unencrypted private key is possible with the pyethapp account import command. It expects a file containing the private key in hex encoded form as argument. Similar to creating a new account, you'll have to choose a password and can add an id.

$ pyethapp account import my_privkey.hex --uuid
Password to encrypt private key: 
Repeat for confirmation: 
Account creation successful
  Address: 87c018ef78005f118c53fa9cadf0a4fd367a77a9
       Id: f2432c7f-e293-4015-b53c-8df686017bf6

pyethapp account update changes the password of an account. As the only argument an account identifier needs to be provided, similar to the one expected by the --unlock option (an address, a uuid, or an integer). Updating an account can be dangerous, as the keystore file is replaced, so double-check your backups. Here is an example of a successful password change:

$ pyethapp account update b98aa6a13256ae98d470abf507141dd6415c3f99
Password for account b98aa6a13256ae98d470abf507141dd6415c3f99 (attempt 1/3): 
Updating account
Address: b98aa6a13256ae98d470abf507141dd6415c3f99
     Id: None
New password: 
Repeat for confirmation: 
Account update successful

Unlocking accounts

If you are going to use an account, for example to transfer ether or call contracts, you'll have to unlock it with the --unlock command line option. It is passed directly to pyethapp (thus, it works the same for all subcommands). As argument, it expects an account identifier. This can either be the account address (with or without 0x prefix), its uuid, or a number corresponding to the entry in pyethapp account list. If the account can be identified, you will be asked for its password. If you fail to provide it, pyethapp will quit.

$ pyethapp --unlock 1 account list
Password for account 1 (attempt 1/3): 
Wrong password. Please try again (attempt 2/3): 
     Address (if known)                       Id (if any)                          Locked
  #1 87c018ef78005f118c53fa9cadf0a4fd367a77a9 f2432c7f-e293-4015-b53c-8df686017bf6 no
  #2 8aa3a4f9d58950738a12ed2e19e977ffb350a806 18dc18ed-8a25-4961-8e7f-50a9b18ec4f7 yes
  #3 a9544551461d01e632b0bfb2ef70c8bf8ea5f06d                                      yes
$ pyethapp --unlock 0x8aa3a4f9d58950738a12ed2e19e977ffb350a806 account list
Password for account 8aa3a4f9d58950738a12ed2e19e977ffb350a806 (attempt 1/3): 
     Address (if known)                       Id (if any)                          Locked
  #1 87c018ef78005f118c53fa9cadf0a4fd367a77a9 f2432c7f-e293-4015-b53c-8df686017bf6 yes
  #2 8aa3a4f9d58950738a12ed2e19e977ffb350a806 18dc18ed-8a25-4961-8e7f-50a9b18ec4f7 no
  #3 a9544551461d01e632b0bfb2ef70c8bf8ea5f06d                                      yes

Password file

Instead of being prompted for a password when calling, e.g., pyethapp account new or pyethapp --unlock <account> you can provide the password by file. Note that all whitespace from the right is removed, so in order to avoid confusion do not put spaces at the end of your password.

Warning: Storing passwords in plain text is dangerous. Use it only for testing if no real loss is possible (i.e. on a testnet).

$ pyethapp --password path/to/password_file account new
Account creation successful
  Address: 4fecff17f25e38919f73791a8c8559c4afc2c7e3
       Id: None
$ pyethapp --password path/to/password_file --unlock 4fecff17f25e38919f73791a8c8559c4afc2c7e3 account list
     Address (if known)                       Id (if any)                          Locked
  #1 4fecff17f25e38919f73791a8c8559c4afc2c7e3                                      no
  #2 87c018ef78005f118c53fa9cadf0a4fd367a77a9 f2432c7f-e293-4015-b53c-8df686017bf6 yes

Getting Ether

One way to get Ether is by using the Ethereum wei faucet. Just type in your account address and enjoy some free ether.

Account management from the inside

Internally, accounts are managed by the accounts service. In the following section its interface will be outlined, so that you can work with accounts from the console or your own custom services. For more detailed information refer to the code.

To make the following examples easy to replicate, they are executed in a console session. In most cases, however, it is straightforward to translate them for use from a custom service.

Accounts

All available accounts can be accessed through the accounts service:

In [1]: acct_service = eth.services.accounts
In [2]: acct_service.accounts
[<Account(address=8aa3a4f9d58950738a12ed2e19e977ffb350a806, id=18dc18ed-8a25-4961-8e7f-50a9b18ec4f7)>,
 <Account(address=d6aaae06717f25095eab8250369a437e549160a4, id=None)>,
 <Account(address=b98aa6a13256ae98d470abf507141dd6415c3f99, id=None)>]

For each account, address, id, public key and private key are accessible if they are known. If not, they are None:

In [3]: acct1 = acct_service.accounts[0]
In [4]: acct1.address.encode('hex')
Out[4]: '8aa3a4f9d58950738a12ed2e19e977ffb350a806'
In [5]: acct1.uuid
Out[5]: u'18dc18ed-8a25-4961-8e7f-50a9b18ec4f7'
In [6]: assert acct1.privkey is None
In [7]: assert acct1.pubkey is None

Note, that privkey and pubkey are not known, because we didn't unlock the account via the --unlock command line option:

In [8]: acct1.locked
Out[8]: True

However, unlocking is just as simple from here:

In [9]: from getpass import getpass
In [10]: pw = getpass()  # avoid typing the password in directly, as it may appear in the iPython history
    Password: 
In [11]: acct1.unlock(pw)
In [12]: assert not acct1.locked
In [13]: acct1.privkey is not None and acct1.pubkey is not None  # again, don't print the private key to not compromise it
Out[13]: True

Once unlocked, we are able to sign transactions:

In [14]: from ethereum.transactions import Transaction
In [15]: tx = Transaction(
   ....:        nonce=eth.pending.get_nonce(acct1.address),
   ....:        gasprice=10 * 10**12,
   ....:        startgas=25000,
   ....:        to='\x00' * 20,
   ....:        value=0,
   ....:        data='')
In [16]: acct1.sign_tx(tx)
In [17]: tx.sender == acct1.address
Out[17]: True

Note that if you are working from the console, creating transactions via eth.transact or eth.call is usually easier.

Finding accounts

The accounts service has a couple of methods making it easier to find a specific account:

  • accounts.get_by_address and accounts.get_by_id return the account with a given address or id, respectively.
  • accounts.unlocked_accounts gives a list of all accounts which have been unlocked.
  • accounts.with_address filters for accounts with visible addresses (remember that addresses of locked accounts might be hidden).

Creating new accounts

To create a new account, there is Account.new. Both using an existing private key and generating a random new one is supported. Of course, encryption with a password is required.

In [18]: pw = getpass()
Password: 
In [19]: acct2 = Account.new(pw)  # use random private key
In [20]: acct2.locked
Out[20]: False  # new accounts are unlocked

However, the new account only exists in memory right now; it is not persistently stored on disk. Furthermore, the account manager does not know about it. Both problems are solved by setting the path attribute and subsequently calling AccountService.add_account:

In [21]: import os
In [22]: acct2.path = os.path.join(acct_service.keystore_dir, acct2.address.encode('hex'))
In [23]: acct_service.add_account(acct2)
In [24]: acct2 in acct_service.accounts
Out[24]: True

Updating accounts

Changing passwords is done by the update_accounts method of the account manager:

In [23]: new_pw = getpass()
Password: 
In [24]: acct_service.update_account(acct2, new_pw)

As can be seen from the fact that there is no old_password parameter, the account needs to be unlocked already for this command to work.