14.6. Design Doc 006: Extensions for GNU Taler

14.6.1. Summary

This design document describes a generic framework for how extensions (i.e. optional features) to GNU Taler can be offered and used by the exchange, merchants and wallets.

14.6.2. Motivation

GNU Taler’s list of supported features evolves over time. For example, the following features are going to be designed and implemented during the course of 2021 and 2022:

  • Peer-to-peer payments
  • Anonymous age-restriction
  • Escrow service for anonymous auctions

We call a feature an extension when it is optional for either the exchange, wallet or merchant to enable and support it. (However, enabling a feature might require the other parties to support the feature, too)

For optional features we therefore need a mechanism to express the availability, version and configuration of a particular feature, f.e. p2p or age-restriction offered by an exchange, and make it verifiable by the other participants.

14.6.3. Requirements

14.6.4. Proposed Solution


The exchange will add two new optional fields in response to /keys:

  1. The field extensions which contains a dictionary of extension-names and their configuration, see below.
  2. The field extensions_sig that contains the EdDSA signature of the SHA256-hash of the normalized JSON-string of the extensions object.

The necessary changes to ExchangeKeysResponse are highlighted here:

interface ExchangeKeysResponse {

// Optional field with a dictionary of (name, object) pairs defining the
// supported and enabled extensions.
// The name MUST be non-empty and unique.
extensions?: { name: Extension };

// Signature by the exchange master key of the SHA-256 hash of the
// normalized JSON-object of field extensions, if it was set.
extensions_sig?: EddsaSignature;


Extension names

The names of extensions MUST be unique. The full name MUST be registered with GANA along with a full description of the extension.

(In the rare situation that the exchange might have to provide multiple versions of the “same” feature in parallel, multiple unique names MUST be used, f.e. age_restriction an age_restriction.v2.)

Extension object

The definition of Extension object itself is mostly up to the particular feature. However, it MUST have

  1. the boolean field critical that has the same semantics as as “critical” has for extensions in X.509: if true, the client must “understand” the extension before proceeding, if “false” clients can safely skip extensions they do not understand.
  2. the field version of type LibtoolVersion which contains the version information of the extension in Taler’s protocol version ranges notation.
interface Extension {
  // The criticality of the extension MUST be provided.  It has the same
  // semantics as "critical" has for extensions in X.509:
  // - if "true", the client must "understand" the extension before
  //   proceeding,
  // - if "false", clients can safely skip extensions they do not
  //   understand.
  // (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2)
  critical: boolean;

  // The version information MUST be provided in Taler's protocol version
  // ranges notation, see
  // https://docs.taler.net/core/api-common.html#protocol-version-ranges
  version: LibtoolVersion;

  // Optional configuration object, defined by the feature itself
  config?: object;


Extensions are disabled per default and must explicetly be enabled in the the TALER configuration manually. The configurations of all enabled extensions are signed with the master key and uploaded to the exchange with the tool taler-exchange-offline.

Each extension has its own section in the configuration, starting with the prefix exchange-extension-, like [exchange-extension-age_restriction]. The field ENABLED = YES|NO is used to enable or disable the corresponding extension. If the extension has its own configuration parameters, they MAY be optional, in which case the taler-exchange-offline tool MUST fill them with safe default values.

The taler-exchange-offline tool MUST offer the subcommand extensions for showing and signing extensions. For this purpose, the following sub-subcommands MUST be available:

  • extensions show: List all available extensions, their versions, criticality and whether they are enabled.
  • extensions sign: Sign the configuration of all enabled extensions with the master key and prepare a JSON-object for the upload command.

When extensions are offered and enabled by an exchange, the extensions object MUST be signed by the exchange’s master signing key. Whenever extensions are enabled or disabled, the offline tool MUST sign the SHA256 hash of the normalized JSON-string of the extensions object, if it is not empty.

In order to do so, the taler-exchange-offline tool MUST

  1. have the complete list of all available optional features/extensions and their versions builtin and
  2. understand them (including the version). For example, the extension for age-restriction will require the exchange to perform particular steps when this extension is enabled (i.e. signing denominations with support with age restriction together with the string of age groups).
  3. reject a configuration that refers to any extension that the tool does not know or understand.

Similarly, the exchange MUST reject a signed configuration with extensions it does not know or understand.


A configuration for age-restriction in the taler configuration would look like this:

ENABLED = true
# default:
AGE_GROUPS = "8:10:12:14:16:18:21"
  • TODO: Add examples for p2p.



  • Needs to express support for particular extensions, too. F.e. age-restriction.

14.6.5. Alternatives

TODO. None yet.

14.6.6. Drawbacks

  • We do not offer (yet) any lifetime cycle of a feature, that is: There are only two states that a feature can be in: “available” or “not-available”.
  • The existing design for peer-to-peer payments must be adapted to this.

14.6.7. Discussion / Q&A

The initial ideas presented here are based on discussions between Özgür Kesim and Christian Grothoff.