Contents

POST /reveal-withdraw#

Reveal previously committed values to the exchange, except for the values corresponding to the noreveal_index returned by the /withdraw step.

The base URL for /reveal-withdraw-request may differ from the main base URL of the exchange. Clients SHOULD respect the reveal_base_url returned for the coin during melt operations. The exchange MUST return a 307 or 308 redirection to the correct base URL if the client failed to respect the reveal_base_url or if the allocation has changed.

The request body is a RevealWithdrawRequest.

This endpoint was introduced in this form in protocol v32.

200 OK:

The coin’s’ secret material matched the commitment and the original request was well-formed. The response body is a RevealResponse.

404 Not found:

The provided commitment $RCH is unknown.

409 Conflict:

There is a problem between the original commitment and the revealed secret data. The returned information is proof of the mismatch, and therefore rather verbose, as it includes most of the original /withdraw request, but of course expected to be primarily used for diagnostics.

The response body is a RevealConflictResponse.

The following specific error codes can be returned:

  • An age commitment for at least one of the coins did not fulfill the required maximum age requirement of the corresponding reserve. Error code: TALER_EC_EXCHANGE_GENERIC_COIN_AGE_REQUIREMENT_FAILURE.

  • The computation of the hash of the commitment with provided input does result in the value of field h_commitment. Error code: TALER_EC_EXCHANGE_AGE_WITHDRAW_REVEAL_INVALID_HASH

Details:

Request body for a reveal-withdraw request contains a JSON object with the following fields:

interface RevealWithdrawRequest {
  // The reserve's public key from the previous call to /withdraw.
  reserve_pub: string;

  // This is the h_planchets running hash of all blinded planchets
  // from the previous call to /withdraw.
  h_planchets: string;

  // Array of (kappa - 1) disclosed batch secrets,
  // from which for each of the n coins in a batch
  // their coin master secret is derived,
  // from which in turn their private key,
  // blinding, nonce (for Clause-Schnorr) and
  // age-restriction is calculated.
  disclosed_batch_seeds: AgeRestrictedPlanchetSeed[];

}
// The master seed material from which for n coins in a batch,
// each the coins' private key coin_priv,  blinding beta
// and nonce nonce (for Clause-Schnorr) itself are
// derived as usually in wallet-core.  Given a coin's master key material,
// the age commitment for the coin MUST be derived from this private key as
// follows:
//
// Let m ∈  {1,...,M} be the maximum age group as defined in the reserve
// that the wallet can commit to.
//
// For age group $AG ∈  {1,...m}, set
//     seed = HDKF(coin_secret, "age-commitment", $AG)
//   p[$AG] = Edx25519_generate_private(seed)
// and calculate the corresponding Edx25519PublicKey as
//   q[$AG] = Edx25519_public_from_private(p[$AG])
//
// For age groups $AG ∈  {m+1,...,M}, set
//   f[$AG] = HDKF(coin_secret, "age-factor", $AG)
// and calculate the corresponding Edx25519PublicKey as
//   q[$AG] = Edx25519_derive_public(PublishedAgeRestrictionBaseKey, f[$AG])
//
type AgeRestrictedPlanchetSeed = string;
// The value for PublishedAgeRestrictionBaseKey is a randomly chosen
// Edx25519PublicKey for which the private key is not known to the clients.  It is
// used during the age-withdraw protocol so that clients can prove that they
// derived all public keys to age groups higher than their allowed maximum
// from this particular value.
const PublishedAgeRestrictionBaseKey =
    new Edx25519PublicKey("CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG");