Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

token-2022: limit incoming transfers for confidential transfer extension #3208

Merged

Conversation

samkim-crypto
Copy link
Contributor

@samkim-crypto samkim-crypto commented Jun 1, 2022

Decrypting ElGamal ciphertexts that encrypt large numbers (> 2^32) is computationally very expensive. When a confidential transfer extended account receives incoming transfers of large amounts that are accumulated into the pending_balance ciphertext, then it may become very expensive for users to decrypt and recover the exact amount of tokens that is held as pending_balance.

To cope with this, a confidential transfer instruction is structured such that the transfer amount (a 64-bit number) is encrypted as two ciphertexts: a lo ciphertext that encrypts the low 32-bits of the transfer amount and a hi ciphertext that encrypts the high 32-bits. Since each of the lo and hi ciphertexts encrypt 32-bit numbers, they can be efficiently decrypted. Then to recover an amount that is held in the pending_balance ciphertext in an account, users can look up the relevant incoming transactions data, decrypt the lo and hi ciphertexts, and then update the account data (i.e. decryptable_ciphertext). Although this solution could be made to work, searching for and decrypting each of the relevant incoming transfer data is cumbersome and difficult to work with on the client.

An alternative approach is to break up the pending_balance into two ciphertexts:

  • pending_balance_lo that encrypts the low 32-bits of the pending balance
  • pending_balance_hi that encrypts the high 32-bits of the pending balance
    As long as these pending balance ciphertexts are guaranteed to encrypt 32-bit values, users can easily look up and decrypt the pending balance from accounts.

The main problem with having two pending balance ciphertexts is that they can overflow. If an account receives a large number of incoming transactions, then the amount that pending_balance_lo encrypts could grow to be larger than a 32-bit number, in which case, the ciphertext becomes hard to decrypt.

One way to cope with the overflow problem is to introduce the following changes:

  1. Introduce a 2^48 upper bound on the transfer amount for a confidential transfer.
  2. Introduce an upper bound (e.g. 2^16) on the number of incoming transfers that a single account can accept. Any additional incoming transfers or deposits to an account are rejected before the owner of the account submits an ApplyPendingBalance.

With a 2^48 upper bound, a transfer amount must be encrypted as two ciphertexts in a transfer instruction such that:

  • the lo ciphertext encrypts the low 16-bits of the transfer amount
  • the hi ciphertext encrypts the high 32-bits of the transfer amount
    and similarly, pending_balance_lo and pending_balance_hi ciphertexts encrypt 16 and 32 bit amounts respectively.

With an upper bound of 2^16 incoming transfers to an account, the pending_balance_lo will overflow to at most 2^32, which is still efficiently decryptable. pending_balance_hi can also overflow to encrypt numbers larger up to 2^48. However, for overflows to occur in pending_balance_hi, an account must receive a high volume of large transactions. Users that expect large transactions can either submit ApplyPendingBalance more often to flush out pending balance ciphertexts or they can maintain multiple accounts to divide up the load in receiving large transactions. Furthermore, with enough time and/or hardware, moderate amounts of overflows (encrypted amount <2^42) in pending_balance_hi can still be decrypted. Users that typically deal with high volume of large transactions may have access to more advanced hardware.

@samkim-crypto samkim-crypto requested review from joncinque and removed request for joncinque June 2, 2022 02:42
@samkim-crypto
Copy link
Contributor Author

@mvines I updated the PR with more background on the changes. We did have a discussion thread on slack some time ago on this, but it seems like it is gone now. When you get a chance, it would be nice if you can skim over the changes to see if it looks reasonable.

mvines
mvines previously approved these changes Jun 2, 2022
Copy link
Contributor

@mvines mvines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm overall!

joncinque
joncinque previously approved these changes Jun 3, 2022
Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few nits and a question -- also, I second what Michael said

@mergify mergify bot dismissed stale reviews from joncinque and mvines June 4, 2022 00:18

Pull request has been modified.

joncinque
joncinque previously approved these changes Jun 6, 2022
Copy link
Contributor

@CriesofCarrots CriesofCarrots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nits. Code changes look correct to me.
Would be nice to have tests that cover the max-transfer error case, as well as pending_balance_hi population

@samkim-crypto samkim-crypto force-pushed the ct-limit-incoming-transfers branch from 839d87d to b2c72af Compare June 7, 2022 00:44
@mergify mergify bot dismissed joncinque’s stale review June 7, 2022 00:44

Pull request has been modified.

@samkim-crypto samkim-crypto force-pushed the ct-limit-incoming-transfers branch from d597273 to 27badd3 Compare June 7, 2022 10:27
@samkim-crypto
Copy link
Contributor Author

I pushed all the unpushed changes and the tests have also been updated to check that (1) deposit or transfer fails if max bound on pending credit is reached and (2) the pending_hi ciphertexts are populated on deposits.

@samkim-crypto samkim-crypto merged commit 677acf1 into solana-labs:master Jun 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants