Soda Labs
Soda Labs Docs
Developer GuidesTypes and operations

Anonymous Tokens

Anonymous tokens let a user prove they are authorized to use a service without revealing who they are.

Understanding Anonymous Tokens

Anonymous tokens are a way for users to prove they are authorized to use a service without revealing who they are. The idea is simple: a user obtains a token once (where they may be identified), and later presents that token to access a service anonymously. The challenge is ensuring that:

  1. The user cannot forge tokens.
  2. The service provider cannot link a redeemed token back to the original user.
  3. Tokens cannot be reused (no double-spending).

A standard way to create such tokens is to use a Pseudorandom Function (PRF). The server has a secret key K, and a valid token is a pair (x, y) such that y = H(K, x). However, issuing (x, y) directly would reveal x and y to the server, which means the server could later recognize the token and deanonymize the user. This breaks anonymity.

To solve this, we need an Oblivious PRF (OPRF): the server evaluates the PRF without learning the input or output, meaning it issues a token without being able to recognize it later.


How Bubble Solves This

Bubble already provides the ability to compute H(x) securely without revealing x or H(x) to anyone. We use this to implement anonymous tokens functionalities.

  1. Token Issuance (identified stage)

    • A user requests a token using their known address.
    • The Bubble system privately generates a random value x.
    • It privately computes y = H(x) using MPC.
    • No one, not even the service, sees the actual values.

    This is done using the OPRF mint function.

  2. Anonymous Redemption

    • The user later interacts from a different, unrelated address.
    • The user submits the token (x, y) while x remains encrypted under a different key associated with the alternate address, so it remains hidden publicly. Y is given in the clear.
    • Bubble decrypts the token internally, verifies that:
      • y = H(x) (the token is valid)
      • y has not been used before (no replay using a nullifier list)
    • If valid, the user is granted access without linking to their original identity.
  3. Token splitting and merging

    Tokens can represent a value q. To change denominations, the user burns the existing token or tokens. They then mint replacement tokens with the required values.

    Replacement tokens receive fresh, private x values. They cannot be linked to the burned tokens by their public values.

    The application must enforce value conservation. The sum of replacement values must equal the sum of burned values. It should perform the burn and mint operations atomically. This prevents a user from spending an input token while its replacement is created.

    Example, split: A user burns one token with q = 100. The application mints two new tokens with q = 40 and q = 60. The user can redeem them separately from unrelated addresses.

    Example, merge: A user burns tokens with q = 25 and q = 75. The application mints one replacement token with q = 100. The original tokens remain unusable after the burn.


Bubble Anonymous token functionalities

oprfMint

function oprfMint(gtUint128 key, gtUint256 q) internal returns (gtUint128, gtUint128)

Purpose: Create a new token (X, Q, Y)

Inputs:

  • Key: OPRF key
  • Q: The requested token value

Outputs:

  • Q value of the token

oprfBurn

function oprfBurn(gtUint128 key, gtUint128 x, gtUint256 q, uint128 y) internal returns (gtUint256)

Purpose: Burn the token (X, Q, Y)

Inputs:

  • Key: OPRF key
  • X: The x value of the token, encrypted.
  • Q: The q value of the token, encrypted.
  • Y: The y value of the token, in the clear. Y value is not encrypted in order to check nullification.

Outputs:

  • X Handle
  • Y Handle

On this page