Work in progress: One-time Shielding Addresses

Problem Statement

Shielding is the process of locking an amount of a public token to acquire the same amount of the corresponding private token inside the Incognito network. It is the mechanism for users who want to achieve the Incognito privacy level for their public tokens. Since the introduction of Privacy V2, Incognito users have been experiencing a fairly higher level of privacy, with the ability to hide transaction amounts, senders, recipients, as well as asset types. However, at the moment, shielding encounters a problem of address re-using. That is, the locking address for all shielding requests from the same user is the same. This is undesirable because it is easy to determine whether two shielding requests belong to the same user or not. Fortunately, this problem can be addressed by employing one-time addresses.

Before we get into the details of the solution, let’s take a look at the properties that each Incognito transaction type achieves, and then see how employing one-time addresses might increase the shielding process’s privacy.

Table. A summary of each transaction type in Incognito
(* depends on the interacting network)

Property Transfer Trade Shield Unshield
Hide amount YES NO NO NO
Hide sender YES YES YES/NO* YES
Hide receiver YES YES NO YES/NO*
Hide asset type YES NO NO NO

From the table, one can easily observe the following.

  • A normal transfer satisfies all of these properties, so we are good to go.
  • A trade cannot be processed unless the trading amount and trading assets are known. As a result, these values must be transparent. Therefore, hiding amounts and assets is not possible at the moment for a trade.
  • Unshielding (i.e., sending assets out of Incognito) necessitates knowledge of the destination blockchain, as well as knowledge of the asset type. Hiding receivers differs depending on whether the destination blockchain is public (e.g., BTC, ETH) or private (e.g., XMR). Unshielding also requires burning corresponding amounts inside the Incognito network. So, hiding amounts is impossible. Therefore, at this time, we can say that unshielding transactions achieve the highest level of privacy.
  • What’s left to be improved is the shielding process. Like unshielding, hiding amounts and asset types is not possible. Hiding senders depends on the interacting blockchain. So nothing we can do about these three properties. However, because the receivers are part of the Incognito network, we can improve this by employing one-time addresses.

Current Design

Next, we will quickly recap the current design. To shield a token from a Public Chain into Incognito, a User must proceed with the following steps.

  1. Generate the depositing address (depositAddr, a multisig address) using his payment address (incAddr). Each incAddr will have a uniquely corresponding depositAddr. Details of this can be found in this post.
  2. Send an amount of the public token to the generated depositing address.
  3. Query the Public Chain to get the depositProof.
  4. Send the depositProof to Incognito.
  5. Incognito mints the corresponding amount for User using his incAddr.

Figure 1. Current shielding design.

As we can see in Step 1, the incAddr is used every time the User wants to shield an asset. Therefore, for two separate shielding requests, the same depositAddr is generated. Therefore, one can tell that these requests belong to the same User.

To address this problem, we take advantage of one-time addresses to generate newly depositAddr every time the User wants to perform a shield. In the next section, we explain in detail the solution.


The idea is simple: let the User generate a one-time depositing address each time he deposits money into the Incognito network. The new flow is described in Figure 2 with the following steps.

Figure 2. New shielding flow. Colored in red indicates differences from the old design.

  1. Generate a one-time key pair (OTPrivKey, OTPubKey) to initiate the shielding request.
  2. Generate a one-time Incognito address (otaReceiver) for receiving the corresponding token.
  3. Sign this otaReceiver using the generated OTPrivKey in Step 1. This step is needed to ensure the authenticity of the shield (explained below).
  4. Generate a depositing address using the OTPubKey instead of his payment address incAddr.
  5. Send an amount of the public token to the generated depositing address.
  6. Query the Public Chain to get the depositProof.
  7. Send the depositProof and corresponding data (OTPubKey, otaReceiver, sig) to Incognito.
  8. Incognito mints the corresponding amount for User via the otaReceiver.

In this new design, we introduce the following new terms:

  • OTPrivKey, OTPubKey. A one-time key pair for the shield request.

    • The OTPubKey is used to replace the current incAddr. As a new OTPubKey is generated every time the User wants to shield, the corresponding depositAddr is also newly generated. Note that the User can re-use the OTPubKey in other shielding requests. However, this is NOT RECOMMENDED because it will lower the privacy level and allow an observer to link his shields.
    • The OTPrivKey is used to sign the shielding request on data including the otaReceiver.
  • otaReceiver. A one-time Incognito address that is used to receive the minted token. Unlike the previous design where incAddr is used and the Incognito knows how to mint the corresponding token for this address, this otaReceiver is needed as the payment address is not supplied.

  • sig. The signature for this shield request, which is signed on data including otaReceiver. This signature is needed to validate the authenticity of the shield request to make sure an attacker cannot use the depositAddr to shield the token to the address that he favors.

Effective Key Management

The replacement of the incAddr results in a problem of key management. Since a fresh (OTPrivKey, OTPubKey) pair is generated for each shield, we need a wise method for generating, managing, and checking if the key pair has been used. Randomly generating this pair is not a good solution, because we do not have an effective way to retrieve which pairs we have used, and thus cannot rebuild the shielding history.

To address this problem, we can employ the idea of HD Wallets or the BIP32 proposal, in which we have the pairs generated using a master key (mKey) and an increasing index. The mKey can be dependent on or independent of the private key, the latter is a better choice in terms of key management. For example, mKey can be generated as follows (details will be updated soon):

mKey = Hash(privateKey, “onetimedepositingmasterkey”)

Figure 3. One-time key generation.

Starting at index = 0, we try to create a child key pair and check if this pair has been used. If yes, we increase the index by 1.


With this design, Incognito is now becoming more and more robust. Please tell us what you think about this design. Comments and recommendations are wholeheartedly welcomed.


One time shielding addresses = more privacy = robust

Not technically minded but I read the word robust so it must be good :stuck_out_tongue:


This is a huge improvement—happy to see one-time addresses returning to the Shielding process by leveraging asymmetric cryptography and proven BIP32/hierarchical deterministic wallet design. No need to reinvent the wheel! Also, can adoption of BIP32-style key management aid in the integration of hardware wallets into Incognito?

1 Like

I can’t say because there’s no plan for hardware wallets at the moment.

What about the Ledger work that was put on pause until Privacy v2 and pDEX v3 were completed?


Hi @Mike_Wagner, what @Daniel said is correct-ist, as we doesn’t have a solid plan for hardware wallet yet, nevertheless it’s on our todo list. pDEX v3 were already deployed but not completed yet, there are more things needed to be done to improve its current UX both on chain and the app (as you can see the app is slow), we doesn’t want to have half-done/near-completed feature lie around.


Sorry, I’m not a very technical person so a lot of this went over my head, however I do want to approach this topic from a completely different angle.

Don’t get me wrong, I’m first a foremost a privacy advocate, but for those of us that do not want to hide from the tax authorities and want to be a law abiding citizen that does not want to evade tax, we need to ensure there is a way in the app to export a CSV file with all taxable event details, below are some examples:

  • Incognito pDEX Trades - these will trigger capital gain tax events
  • Amount of interest earnt from Provide - this should be reported as interest on savings
  • Earning from running Validator Nodes - this needs to be treated like income

You get my drift, above is just a shortlist and there may be additional Tax events that require some level of reporting.

So, my concern/question is, will this new improvement and use of one-time addresses impact the Incognito’s reporting capabilities for Tax Reports to regulators?

1 Like

I’m glad to brought this up @Mike_Wagner

I too have been wondering when Ledger Hard Wallet integration will be put back on the roadmap. @Jared , could you please ask the Devs when you next meet with them?

Regarding ‘Growth Marketing’, by integrating with Ledger Hard Wallets, I feel this would catapult the Incognito brand to new heights as it builds upon this project’s focus of “Self custody” and “security”.

I feel it would bring a lot of attention to the project and would build more awareness thus attracting a NEW wave of users to the platform.

Can you imagine someday, being able to sign a contract via Ledger Nano hard wallet to add liquidity to a Provide pool?

I feel this feature alone would set this project far apart from SCRT and RAIL.

I do realize there would be a lot of work involved to make this happen, so it would be nice to see it on the roadmap.


@daniel @support
Any updates on this or a timeline/targeted Incognito app version for release?

Just got reminded of the value of one-time addresses today when a withdrawal to Incognito was blocked by a CEX (“We’ve noticed you’ve attempted to transfer funds directly to a prohibited service.”) This was my mistake–I almost always use an intermediate wallet with one-time addresses but copied the wrong address. smh


1 Like

Interesting. I will bring this up with the devs.

1 Like

We’ve have finished implementing the protocol at the chain-side and it’s being reviewed. For integrating with the App, we’ll update to the community soon.


Wonderful! Glad to hear it’s potentially so close to going live.

Cheers to @daniel & the other Incognito developers for all your work to continually improve the tools from which we all benefit.

1 Like

AFAIK, the protocol (+ go-SDK & CLI tool) might go live in Q1 but app integration is scheduled to Q2.

1 Like