Creating accounts
You can create or import accounts into the Octez client just like you do so in wallet applications.
Octez keeps a local list of aliases for addresses, including user accounts, smart contracts, and Smart Rollups.
You can list the aliases that the Octez client is aware of by running the command octez-client list known addresses
.
When you run transactions with Octez, you can use the alias in place of the account address.
Creating accounts
To create an account, run this command, replacing local_account
with a local name for the new account:
octez-client gen keys local_account
You can see the address of the account by running this command:
octez-client show address local_account
To print the private key for the address, add the --show-secret
argument.
The account address (technically the hash of the public key) starts with tz1
, tz2
, tz3
, or tz4
depending on the options that you use when you create the account.
For command reference, see Command Line Interface in the Octez and protocol documentation.
You can use this address to send tez to this account, such as from a faucet if you are using a testnet. See Testing on testnets.
Importing pre-existing accounts
If you already have a Tezos account, you can import your private key to use the account in Octez:
-
Export the private key from your wallet application, being careful not to expose it to anyone.
-
Run this command, replacing the placeholder
<ALIAS>
with a local alias for the account and the placeholder<PRIVATE_KEY>
with the private key:octez-client import secret key <ALIAS> unencrypted:<PRIVATE_KEY>
Now you can use the alias in place of the address when you send transactions with Octez.
Exporting accounts
To export an account and use it in another wallet, you can make the Octez client print its secret key by adding the -S
switch to the octez-client show address
command, as in this example:
octez-client show address local_account -S
There is no way to export all of the addresses in the Octez client at once, but you can print all of the accounts in the Octez client with the command octez-client list known addresses
.
You can also see the keys in the file ~/.tezos-client/secret_keys
.
Revealing accounts
User accounts are unrevealed until they make a transaction. To reveal an account, send any transaction from it, such as calling a smart contract or sending tez to any account, including itself. Unrevealed accounts can receive and store tez, but doing so does not reveal them. An account must have some tez to be revealed.
You can also use the dedicated reveal operation to reveal an account.
You can use the Octez client to create this reveal operation by passing the account alias to the reveal key for
command, as in this example:
octez-client reveal key for local_account
You can tell if an account is revealed by calling the /chains/main/blocks/<block_id>/context/contracts/<contract_id>
RPC endpoint, as in this example:
octez-client rpc get /chains/main/blocks/head/context/contracts/tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx
The response includes the balance, delegate, and counter for the account and a Boolean field named revealed
which is true if it has been revealed or false if it has not:
{ "balance": "9104058003",
"delegate": "tz1NNT9EERmcKekRq2vdv6e8TL3WQpY8AXSF",
"counter": "128420",
"revealed": true
}
Delegating accounts
An account can delegate to another account, usually a baker account. As described in Bakers, delegating your account to a baker account puts your tez toward the voting power of the baker account. Delegating is also a prerequisite for staking. For more information about staking, see Staking and Managing tez.
You can delegate using the staking site as described in Staking, or you can delegate your account by passing the account and the delegate account to the Octez client set delegate for
command, as in this example, which uses <ALIAS>
as the alias for your account and <BAKER>
as the address or alias to delegate to:
octez-client set delegate for <ALIAS> to <BAKER>
To delegate to an account, the target account must be registered as a delegate.
Registering as a delegate
To register as a delegate and allow other accounts to delegate to you, pass the account alias to the Octez client register key
command, as in this example:
octez-client register key <ALIAS> as delegate
For baking delegation scenarios, including registering with a consensus key, see Run a Tezos node in 5 steps.
Multi-signature accounts
As described in Multi-signature accounts, multi-signature accounts (multisigs) require multiple other accounts to authorize operations before running them.
When you create a multi-signature account, you determine how access is shared among the participant accounts. You can configure a multi-signature account to be split among any number of participant accounts and to require all or only some of their signatures to authorize an operation. In general, multisig accounts are referred to as using one of these schemes:
- Signature aggregation (aka N-of-N scheme): All N participants to the multisig account must sign every operation.
- Threshold signature (M-of-N scheme): A threshold number of M participants out of the total of N members is required to sign each operation.
In either case, there must be at least 2 participants (N >= 2) and at least 2 of them must be required to sign an operation (M >= 2).
Built-in multi-signature accounts were introduced in the Seoul protocol and require accounts that start with tz4
, which are created with the BLS signature scheme.
If you created a tz4
account prior to Seoul, you must re-reveal them after Seoul becomes active.
Multi-signature accounts require version 23 or later of the Octez client.
Creating multi-signature accounts
There are two ways to create a multi-signature account:
-
You can generate an account from multiple existing accounts. This method is convenient because you can use existing accounts, but it works only for multisigs in which every participant signs every transaction (N-of-N scheme).
-
You can create an account and split it into multiple other new accounts. This method requires you to distribute private keys to the participants for them to create new accounts, but it permits schemes where only a threshold number of participants are required to sign a transaction (M-of-N).
For a walkthrough, see Staking and baking with native multisig accounts.
Creating a multisig account from existing accounts
Creating a multisig account in this way requires 2 or more existing tz4
accounts.
You use the public keys for these accounts to generate the public key and tz4
address of the multisig account and the proof of possession, which allows participants to create operations on behalf of the multisig account.
Creating a multisig account in this way always results in an N-of-N scheme, in which every participant account must sign every operation. To create a multisig account with an M-of-N scheme, use the method described in Creating a multisig account and new participant accounts.
-
If you don't already have the participant accounts, create them with the
gen keys
command as usual, but pass the-s bls
argument to use the BLS scheme, which creates atz4
account:octez-client gen keys participant_1 -s bls
-
Generate a proof of possession (PoP) for each participant account with the
create bls proof for
command, as in this example:octez-client create bls proof for participant_1
The response is the PoP for the account. You can also see the PoP in the metadata for the reveal operation for the account.
-
Aggregate the accounts into a multisig account by passing the public keys and PoPs to the
aggregate bls public keys
, as in this example:octez-client aggregate bls public keys '[
{
"public_key": "<PARTICIPANT_1_PK>",
"proof": "<PARTICIPANT_1_POP>"
},
{
"public_key": "<PARTICIPANT_2_PK>",
"proof": "<PARTICIPANT_2_POP>"
},
{
"public_key": "<PARTICIPANT_3_PK>",
"proof": "<PARTICIPANT_3_POP>"
}
]'This example uses placeholders such as
<PARTICIPANT_1_PK>
and<PARTICIPANT_1_POP>
for the public key (not the address) and PoP of each of the participant accounts.The response includes the public key and public key hash (address) of the new multisig account.
-
Generate the combined PoP for the multisig account:
-
Generate a PoP fragment for each participant account by passing the public key to the
create bls proof for
command for each account. This example uses<MULTISIG_PK>
for the public key of the multisig account:octez-client create bls proof for participant_1 --override-public-key <MULTISIG_PK>
-
Combine the PoP fragments to the PoP for the multisig accounts by passing the PoP fragments to the
aggregate bls proofs
, as in this example:octez-client aggregate bls proofs '{
"public_key": "<MULTISIG_PK>",
"proofs": [
"<PARTICIPANT_1_POP_FRAGMENT>",
"<PARTICIPANT_2_POP_FRAGMENT>",
"<PARTICIPANT_3_POP_FRAGMENT>"
]
}'The response is the aggregated proof for the multisig account, which you will need for each operation from the account.
The order of the PoPs in this command is not important.
-
-
Reveal the public key of the multisig account by aggregating the signatures of the participant accounts and injecting a reveal operation:
-
Send some tez to the multisig account, because a user account with no tez can't be revealed.
-
Get the counter for the multisig account by passing its address to the
/counter
RPC endpoint, as in this example, which uses<MULTISIG_ADDRESS>
as a placeholder for the address of the multisig account:octez-client rpc get chains/main/blocks/head/context/contracts/<MULTISIG_ADDRESS>/counter
-
Get the hash of a recent block to use as the starting point for the operation:
octez-client rpc get chains/main/blocks/head~2/hash
-
Encode the reveal operation to binary by passing it to the
octez-codec
program. This example uses the placeholders<COUNTER_PLUS_1>
for the current counter plus one and uses<BRANCH>
as the hash of a recent block:octez-codec encode 023-PtSeouLo.operation.unsigned from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "reveal",
"source": "<MULTISIG_ADDRESS>", "fee": "1450",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3250", "storage_limit": "0",
"public_key": "<MULTISIG_PK>",
"proof": "<MULTISIG_PROOF>" } ] }'This command encodes the values for the operation with the
octez-codec
program, based on the Seoul protocol. You can replace023-PtSeouLo.operation.unsigned
with the schema for the protocol that you want to use; see Encodings in the Octez and protocol documentation.The response is the bytecode-encoded operation.
-
As the participant accounts, sign the encoded operation. This example signs the bytecode
<ENCODED_OPERATION>
as the account with the local aliasparticipant_1
:octez-client sign bytes "0x03<ENCODED_OPERATION>" for participant_1
Note that in this command, the encoded operation is prefixed with the code
0x03
.The response is the account's signature for the operation.
-
When you have signatures from all of the participant accounts, combine them into a single aggregated signature. This example uses placeholders such as
<SIGNATURE_1>
for the signatures from each account. The order of the signatures is not important.octez-client aggregate bls signatures '{
"public_key": "<MULTISIG_PK>",
"message": "03<ENCODED_OPERATION>",
"signature_shares": [
"<SIGNATURE_1>",
"<SIGNATURE_2>",
"<SIGNATURE_3>"
]
}'The response is the combined signature for the operation.
-
Sign the operation by running this command, which uses the same JSON parameter as the command to generate the operation with the addition of the
signature
field:octez-codec encode 023-PtSeouLo.operation from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "reveal",
"source": "<MULTISIG_ADDRESS>", "fee": "1450",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3250", "storage_limit": "0",
"public_key": "<MULTISIG_PK>",
"proof": "<MULTISIG_PROOF>" } ],
"signature": "<COMBINED_SIGNATURE>" }'The value of the
signature
field, represented by the placeholder<COMBINED_SIGNATURE>
, is the output of the previous command.The response is the bytecode of the signed operation.
-
Inject the signed operation from the previous step by passing it to the
/injection/operation
RPC endpoint, as in this example:octez-client rpc post /injection/operation with '"<SIGNED_OPERATION>"'
The response is the hash of the operation.
You can use the same process for signing and injecting other transactions from the multisig account, as described in Signing operations with multi-signature accounts.
-
Now the multisig account is active and the participants can co-sign transactions to submit transactions on its behalf.
Creating a multisig account and new participant accounts
When you create a multi-signature account with this method, you create the account and then split it into multiple other new accounts. Follow these steps:
-
Create the account with the
gen keys
command as usual, but pass the-s bls
argument to use the BLS scheme, which creates atz4
account:octez-client gen keys my_multisig -s bls
-
Get the secret key of the account with the
show address
command and the--show-secret
argument:octez-client show address my_multisig --show-secret
-
Pass the secret key of the account to the
share bls secret key
command and specify how many participant accounts to create and how many of these accounts must authorize operations. For example, this command creates 3 participant accounts, 2 of which must authorize each operation:octez-client share bls secret key <SECRET_KEY> between 3 shares with threshold 2
The response includes the proof for the multi-sig account and the secret keys and IDs for the participant accounts, as in this example:
{ "public_key":
"<MULTISIG_PK>",
"public_key_hash": "<MULTISIG_ADDRESS>",
"proof":
"<MULTISIG_PROOF>",
"secret_shares":
[ { "id": 1,
"secret_key":
"<SECRET_1>" },
{ "id": 2,
"secret_key":
"<SECRET_2>" },
{ "id": 3,
"secret_key":
"<SECRET_3>" } ] } -
Save the proof and information about the participant accounts.
noteBe sure to save the IDs of the participant accounts so you can link the IDs with the accounts themselves. In later transactions, you must link the participant signatures with their IDs.
-
Use the secret keys provided in the response to import new accounts with the Octez client. You can import the accounts yourself or distribute the keys to other people. For example, this command imports the account with the placeholder secret key
<SECRET_1>
and gives it the local aliasparticipant_1
:octez-client import secret key participant_1 unencrypted:<SECRET_1>
-
Destroy the secret key of the multisig account because it is no longer needed. For example, this Octez client command removes an account named
my_multisig
, including the-f
argument to delete the private key:octez-client forget address my_multisig -f
importantWhoever has the secret key of the multisig account can sign operations for it independently, getting around the authorization of the participants. For security, after you have imported the participant accounts, ensure that the secret key for the multisig account is destroyed.
-
Optional: To keep track of the account's address and public key, add it back as a local alias by running this command, where
<MULTISIG_PK>
is the public key of the multisig account:octez-client import public key my_multisig unencrypted:<MULTISIG_PK>
Now you can get the address of the account with the command
octez-client show address multisig_staker
and use its alias locally, but you don't have its private key. -
Reveal the public key of the multisig account by aggregating the signatures of the participant accounts and injecting a reveal operation:
-
Send some tez to the multisig account, because a user account with no tez can't be revealed.
-
Get the counter for the multisig account by passing its address to the
/counter
RPC endpoint, as in this example, which uses<MULTISIG_ADDRESS>
as a placeholder for the address of the multisig account:octez-client rpc get chains/main/blocks/head/context/contracts/<MULTISIG_ADDRESS>/counter
-
Get the hash of a recent block to use as the starting point for the operation:
octez-client rpc get chains/main/blocks/head~2/hash
-
Create the operation by passing the reveal operation to the
octez-codec
program. This example uses the placeholders<COUNTER_PLUS_1>
for the current counter plus one and uses<BRANCH>
as the hash of a recent block:octez-codec encode 023-PtSeouLo.operation.unsigned from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "reveal",
"source": "<MULTISIG_ADDRESS>", "fee": "1450",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3250", "storage_limit": "0",
"public_key": "<MULTISIG_PK>",
"proof": "<MULTISIG_PROOF>" } ] }'The response is the bytecode-encoded operation.
-
As the participant accounts, sign the encoded operation. This example signs the bytecode
<ENCODED_OPERATION>
as the account with the local aliasparticipant_1
:octez-client sign bytes "0x03<ENCODED_OPERATION>" for participant_1
Note that in this command, the encoded operation is prefixed with the code
0x03
.The response is the account's signature for the operation.
-
When you have signatures from enough of the participant accounts, combine them into a single threshold signature. This example uses placeholders such as
<SIGNATURE_1>
for the signatures from each account:octez-client threshold bls signatures '{
"public_key": "<MULTISIG_PK>",
"message": "03<ENCODED_OPERATION>",
"signature_shares": [
{ "id": 1, "signature": "<SIGNATURE_1>"},
{ "id": 2, "signature": "<SIGNATURE_2>"}
]
}'noteEach signature in this command is connected to the ID of the account when you created it with the
share bls secret key
command. The signature is not valid if these IDs don't match.The response is the combined signature for the operation.
-
Sign the operation by running this command, which uses the same JSON parameter as the command to generate the operation with the addition of the
signature
field:octez-codec encode 023-PtSeouLo.operation from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "reveal",
"source": "<MULTISIG_ADDRESS>", "fee": "1450",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3250", "storage_limit": "0",
"public_key": "<MULTISIG_PK>",
"proof": "<MULTISIG_PROOF>" } ],
"signature": "<COMBINED_SIGNATURE>" }'The response is the bytecode of the signed operation.
-
Inject the signed operation from the previous step by passing it to the
/injection/operation
RPC endpoint, as in this example:octez-client rpc post /injection/operation with '"<SIGNED_OPERATION>"'
The response is the hash of the operation.
You can use the same process for signing and injecting other transactions from the multisig account, as described in Signing operations with multi-signature accounts.
-
Now the multisig account is active and the participants can co-sign transactions to submit transactions on its behalf.
Whoever has the secret key of the multisig account can sign operations for it independently, getting around the authorization of the participants. For security, after you have imported the participant accounts, ensure that the secret key for the multisig account is destroyed.
Signing operations with multi-signature accounts
To sign operations for the multisig account (regardless of which method you used to create it), enough participants must sign the same operation and provide their signatures. Then anyone can aggregate those signatures and submit the operation.
Signing operations for multisig accounts requires multiple steps that must be done within a specified amount of time. In particular, the operation is based on a recent block (referred to as a branch). If this branch is too old when you submit the signed operation, the operation fails. Therefore, you may want to review the following instructions and plan the commands that you need to run so you can complete them in time. You can also automate the process with a program to save time and prevent errors.
-
Generate the bytes that the participants must sign:
-
Get the counter for the multisig account by passing its address to the
/counter
RPC endpoint, as in this example, which uses<MULTISIG_ADDRESS>
as a placeholder for the address of the multisig account:octez-client rpc get chains/main/blocks/head/context/contracts/<MULTISIG_ADDRESS>/counter
-
Get the hash of a recent block to use as the starting point (branch) for the operation:
octez-client rpc get chains/main/blocks/head~2/hash
-
Encode the operation to binary by passing it to the
octez-codec
program. For example, this operation transfers 1 tez from the multisig account<MULTISIG_ADDRESS>
to the target account<TARGET>
. It adds one to the value returned for the multisig account's counter from a previous step as<COUNTER_PLUS_1>
and uses<BRANCH>
as the hash of a recent block:octez-codec encode 023-PtSeouLo.operation.unsigned from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "transaction",
"source": "<MULTISIG_ADDRESS>", "fee": "1000",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3674", "storage_limit": "0",
"amount": "1000000",
"destination": "<TARGET>" } ] }'The response is the bytecode-encoded operation.
-
As the participant accounts, sign the encoded operation. This example signs the bytecode
<ENCODED_OPERATION>
as the account with the local aliasparticipant_1
:octez-client sign bytes "0x03<ENCODED_OPERATION>" for participant_1
Note that in this command, the encoded operation is prefixed with the code
0x03
.The response is the account's signature for the operation.
-
When you have the necessary number of signatures from the participant accounts, combine them into a single final signature. The process is different for N-of-N schemes and M-of-N schemes.
These examples use placeholders like
<SIGNATURE_1>
for the participant signatures and<MULTISIG_PK>
for the public key of the multisig account. Also note that in this command, the encoded operation is prefixed with the code03
, not0x03
as in the previous command.-
If you are using an N-of-N scheme (all participants must sign), pass the signatures to the
aggregate bls signatures
command:octez-client aggregate bls signatures '{
"public_key": "<MULTISIG_PK>",
"message": "03<ENCODED_OPERATION>",
"signature_shares": [
"<SIGNATURE_1>",
"<SIGNATURE_2>",
"<SIGNATURE_3>"
]
}' -
If you are using an M-of-N scheme (a threshold amount of participants must sign), pass the signatures to the
threshold bls signatures
command:octez-client threshold bls signatures '{
"public_key": "<MULTISIG_PK>",
"message": "03<ENCODED_OPERATION>",
"signature_shares": [
{ "id": 1, "signature": "<SIGNATURE_1>"},
{ "id": 2, "signature": "<SIGNATURE_2>"}
]
}'noteEach signature in this command is connected to the ID of the account when you created it with the
share bls secret key
command. The signature is not valid if these IDs don't match.
The response is the combined signature for the operation.
-
-
Sign the operation by running this command, which uses the same JSON parameter as the command to generate the operation with the addition of the
signature
field:octez-codec encode 023-PtSeouLo.operation from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "transaction",
"source": "<MULTISIG_ADDRESS>", "fee": "1000",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3674", "storage_limit": "0",
"amount": "1000000",
"destination": "<TARGET>" } ],
"signature": "<COMBINED_SIGNATURE>" }'The value of the
signature
field, represented by the placeholder<COMBINED_SIGNATURE>
, is the output of the previous command.The response is the bytecode of the signed operation.
-
Inject the signed operation by sending it to the
/injection/operation
RPC endpoint, as in this example, which uses<SIGNED_OPERATION>
as the signed operation:octez-client rpc post /injection/operation with '"<SIGNED_OPERATION>"'
If the injection is successful, the RPC endpoint returns the hash of the operation.
If the branch has expired, the endpoint returns an error saying that the operation is branched on a block that is too old or unknown.
-
Verify that the operation succeeded by looking it up on a block explorer or by passing the hash to the
octez-client get receipt for
command.
-
You can send many different kinds of operations in this way. For example, this command stakes 100 tez on behalf of the multisig accounts:
octez-codec encode 023-PtSeouLo.operation.unsigned from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "transaction",
"source": "<MULTISIG_ADDRESS>", "fee": "808",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "5134", "storage_limit": "0",
"amount": "100000000",
"destination": "<MULTISIG_ADDRESS>",
"parameters":
{ "entrypoint": "stake", "value": { "prim": "Unit" } } } ] }'
You can also bundle transactions within the contents
field of the JSON data.
For example, this command reveals the account and sets its delegation to the account represented by the placeholder <DELEGATE>
:
octez-codec encode 023-PtSeouLo.operation.unsigned from '{
"branch": "<BRANCH>",
"contents":
[ { "kind": "reveal",
"source": "<MULTISIG_ADDRESS>", "fee": "735",
"counter": "<COUNTER_PLUS_1>", "gas_limit": "3251", "storage_limit": "0",
"public_key": "<MULTISIG_PK>",
"proof": "<MULTISIG_PROOF>" },
{ "kind": "delegation",
"source": "<MULTISIG_ADDRESS>", "fee": "448",
"counter": "<COUNTER_PLUS_2>", "gas_limit": "1673", "storage_limit": "0",
"delegate": "<DELEGATE>" } ] }'