🤫 How to send Tez privately

Like Zcash, the Tezos blockchain allows to transact using the native tez token without revealing information about the sender, recipient or amount sent. In this guide, we explain how to privately send tez to a friend.

To follow this guide, you need to be comfortable with the following:

Types of addresses

Tezos has several types of addresses:

Sending tez to your friend is a multi-step process:

  1. tz => zet: first, you will transfer your tokens from a public address into a shielded address, also known as shielding your tokens,
  2. zet => zet: then send them from your shielded address to your friend’s shielded address,
  3. zet => tz: finally, your friend unshields their tokens back into a public address.

If you were directly sending the tokens from your public address to your friend’s public address, the transaction amount, sender and recipient would be visible to anyone using a block explorer.

By going through shielded addresses, step 2 is hidden to an outside observer. When you perform step 2, they will only be able to see that you are interacting with a privacy contract, but they will not be able to tell how much you are sending, or to whom.

Important: step 2 is private, but steps 1 and 3 are not. While outside observers are unable to tell which shielded transfers are going on, they see money going in and out of the shielded pool. This can potentially reduce your privacy. More on this below.

Install the octez-client CLI

Octez is the software running Tezos. To install on your Windows, Linux or Mac OS X computer, it is recommended to use Tezos-packaging.

After adding the repository, install the octez-client utility. For example, on Mac OS X, do:

$ brew tap serokell/tezos-packaging-stable https://github.com/serokell/tezos-packaging-stable.git
$ brew install tezos-client

You may find online instructions about “running a node”. You do not need to run a node in order to follow this guide.

Get some Tez

You may acquire some Tez through an exchange. See for example: How to get Tezos on Coinbase.

Once you have some Tez on Coinbase or another exchange, transfer it to one tz address that you control.

Generate a tz address using the Tezos CLI. When prompted for a password, just press Enter:

$ octez-client --endpoint https://rpc.tzbeta.net gen keys public-address
Enter password to encrypt your key: 
Confirm password:
$ octez-client --endpoint https://rpc.tzbeta.net show address public-address
Hash: tz1cL3dCuDM19TSSeAR8AUqkDw93CPxBauQg
Public Key: edpkuzLBGDNJzFktSJyBXJK6C64LfJEqwp1cCxu8hfu42SQj1cAUJj

The Hash shown in your terminal is your public address. In our example, it is tz1cL3dCuDM19TSSeAR8AUqkDw93CPxBauQg.

Exchanges do not support directly sending tez to your shielded address. Send tez to your public address, using your exchange’s “Send” functionality.

You may then check your balance:

$ octez-client --endpoint https://rpc.tzbeta.net show balance for public-address
100ęś©

Create a shielded key and address

In order to transact privately, both you and your friend need to create shielded keys attached to the SaplingShield.tez privacy smart contract.

To record the contract address locally, issue the following command:

$ octez-client --endpoint https://rpc.tzbeta.net remember contract SaplingShield.tez text:KT1KzAPQdpziH3bxxJXQNmNQA46oo8tnDQfj

To create a shielded key, issue the following command. When prompted for a password, just press Enter:

$ octez-client --endpoint https://rpc.tzbeta.net sapling gen key shielded-key
It is important to save this mnemonic in a secure place:

choice wool later bike burst verify general universe patient point scatter
then category kidney client foam pact become organ cushion dwarf flavor
despair
oxygen

The mnemonic can be used to recover your spending key.

Enter password to encrypt your key: 
Confirm password: 

A mnemonic will appear on-screen. Make sure to copy and paste it somewhere safe, as anyone with the mnemonic can see your balance and take your money.

Next, associate your shielded address with the SaplingShield.tez contract on Tezos mainnet:

$ octez-client --endpoint https://rpc.tzbeta.net sapling use key shielded-key for contract SaplingShield.tez --memo-size 8
Enter password to decrypt your key:

Your shielded key shielded-key has its own balance within SaplingShield.tez. To receive tez privately, you can create as many shielded addresses as you like, associated with the shielded key.

Let’s generate one shielded address for shielded-key:

$ octez-client --endpoint https://rpc.tzbeta.net sapling gen address shielded-key
Enter password to decrypt your key: 
Generated address:
zet149goMF91acMerkaqLouVFJU4xJkSeaJuicvtjTXAeWz9nsXXHXUQugzntY8xAUXjg
at index 1

Your shielded address is zet149goMF91acMerkaqLouVFJU4xJkSeaJuicvtjTXAeWz9nsXXHXUQugzntY8xAUXjg.

You are now ready to perform a shielded transfer.

What is Sapling?
Sapling is a cryptographic library that allows shielded cryptocurrency transfers, developed for the Zcash blockchain and added to Tezos as part of the Jakarta protocol upgrade.


Transfer Tez privately

Step 1: tz=>zet: shield your tez

The first step is to shield your tokens, which means, transfer them from your public address to your shielded address:

$ octez-client --endpoint https://rpc.tzbeta.net sapling shield 100 from public-address to zet149goMF91acMerkaqLouVFJU4xJkSeaJuicvtjTXAeWz9nsXXHXUQugzntY8xAUXjg using SaplingShield.tez --burn-cap 2
Shielding 100 from tz1cL3dCuDM19TSSeAR8AUqkDw93CPxBauQg to zet149goMF91acMerkaqLouVFJU4xJkSeaJuicvtjTXAeWz9nsXXHXUQugzntY8xAUXjg
entails a loss of privacy

no message provided, adding a zeroes filled message of the required length: 8
Waiting for the node to be bootstrapped...
Current head: BLjdzHqVxUkm (timestamp: 2023-01-03T00:13:10.000-00:00, validation: 2023-01-03T00:13:25.151-00:00)
Node is bootstrapped.
Estimated storage: no bytes added
Estimated gas: 24789.351 units (will add 100 for safety)
Estimated storage: 339 bytes added (will add 20 for safety)
Enter password for encrypted key:
Operation successfully injected in the node.

Now verify that your shielded balance has increased by 100 tez:

$ octez-client --endpoint https://rpc.tzbeta.net sapling get balance for shielded-key in contract SaplingShield.tez
Enter password to decrypt your key: 
Total Sapling funds 100ęś©

What is SaplingShield.tez?
Using the privacy feature of Tezos requires interacting with a smart contract containing special instructions to interact with the Sapling code of the Tezos protocol. The first such smart contract was deployed on Tezos mainnet at the address KT1KzAPQdpziH3bxxJXQNmNQA46oo8tnDQfj, and for convenience, the Tezos Domain address SaplingShield.tez was created to designate this contract using a human-friendly name.
If you go look at this contract on an explorer after performing the steps above, you can see a 100 tez transfer from your public address to the contract. This is why the command line warned you of a “loss of privacy”.

Step 2: zet=>zet: shielded transfer

Your friend must also follow instructions above to “Create a shielded key and address”. Let’s assume they generated a shielded key shielded-key-2 and provided the shielded address zet14AQqNXu4gH5tk4Se8rfJnPYv6nrdX91aCofjFrc1DLhpSxdAkQa7T4V97ziHULxQ6 to you.

Then, transferring tez to them involve two steps: forging a transaction, and submitting it.

First, we forge a transaction sending 50 tez to your friend. This operation will be recorded in a file sapling_transaction:

$ octez-client --endpoint https://rpc.tzbeta.net sapling forge transaction 50 from shielded-key to zet14AQqNXu4gH5tk4Se8rfJnPYv6nrdX91aCofjFrc1DLhpSxdAkQa7T4V97ziHULxQ6 using SaplingShield.tez
Enter password to decrypt your key: 
no message provided, adding a zeroes filled message of the required length: 8 
Writing transaction to sapling_transaction

Then we submit:

$ octez-client --endpoint https://rpc.tzbeta.net sapling submit sapling_transaction from public-address using SaplingShield.tez --burn-cap 1
Reading forge transaction from file sapling_transaction -- sending it to KT1KzAPQdpziH3bxxJXQNmNQA46oo8tnDQfj

Waiting for the node to be bootstrapped...
Current head: BLgCiwodrJwK (timestamp: 2023-01-03T00:49:45.000-00:00, validation: 2023-01-03T00:49:46.712-00:00)
Node is bootstrapped.
Estimated gas: 37908.045 units (will add 100 for safety)
Estimated storage: 710 bytes added (will add 20 for safety)
Enter password for encrypted key: 
Operation successfully injected in the node.

Your friend can now verify that their shielded balance has increased by 50 tez:

$ octez-client --endpoint https://rpc.tzbeta.net sapling get balance for shielded-key-2 in contract SaplingShield.tez
Enter password to decrypt your key: 
Total Sapling funds 50ęś©

Who pays the fees?
In Tezos, only a public address (tz...) can pay for network fees. When looking at the shielded transfer from a block explorer, the account paying the fees is visible. In our example above, the address public-address is paying for fees, just like in step 1.
This is less a problem than you may think, because nothing else transpires: the origin account, destination account and amount are shielded.
You may elect to pay the fee. Alternatively, you can send the file sapling_transaction to your friend or a third party and ask them to submit it themselves using the submission command above.
You may also do step 1 and 2 together and directly send tez from your public address to your friend’s shielded address, but we do not recommend it: shielding tez on a per-transfer basis is bad practice, it is recommended to have shielded tez in reserve for future transfers.

Step 3: zet => tz: unshielding

Your friend may now unshield their tez. For that, they need access to their shielded key shielded-key-2.

They also need an unshielded tz... account public-account-2 with some tez already in it, to pay for fees.

The command to unshield 25 tez is:

$ octez-client --endpoint https://rpc.tzbeta.net sapling unshield 25 from shielded-key-2 to public-account-2 using SaplingShield.tez --burn-cap 1
Warning: Unshielding 25 from shielded-key2 to tz1Z5pKXWmtZyXuPm3H8JoH6dKPB25WxToie entails a loss of privacy

Enter password to decrypt your key:
Waiting for the node to be bootstrapped...

Then your friend’s public account balance will increase by 25.

Privacy tips

There are various ways in which steps 1 and 3 can give hints about your private transaction:

To mitigate these problems, it is recommended to:

Resources