agro.yaya.cash › Reference

GNU Taler primer

The parts of Taler this project depends on, and why this stack rather than another.

Orientation for readers who know agriculture but not Taler, and for readers who know Taler but want to see which specific mechanisms we lean on. Authoritative documentation lives at docs.taler.net.

GNU Taler
WhatElectronic payment system with blind-signed digital coins
ModelPayer-anonymous, merchant-accountable
PartiesExchange, merchant backend, wallet, auditor
SignaturesEdDSA
Contract hashSHA-512 over contract terms
BlockchainNone
LicenceFree software (GNU project)

1. The three parts

GNU Taler splits a payment into three roles that matter to us:

  • Exchange — holds the settlement float and issues digital coins as blind signatures. Because the signature is blind, the exchange cannot link a coin it later redeems to the withdrawal that produced it. This is what makes the payer anonymous.
  • Merchant backend — the seller's server. It creates orders, produces contract terms, and signs them. Each merchant runs instances, and each instance can hold its own signing keys.[1] That detail carries a lot of weight in our design.
  • Wallet — the payer's app. It receives contract terms, verifies the merchant's signature, shows the user what they are agreeing to, and signs the deposit.

The asymmetry is deliberate and it is the reason Taler is here: the buyer is anonymous, the seller is not. Every sale is bound to an identified merchant key and an auditable settlement account. For a certification scheme this is exactly the right way round — we want the producer accountable for the claim and the shopper unsurveilled for having bought.

2. Contract terms are the payload

A merchant creates an order by POSTing to /private/orders (or /instances/$INSTANCE/private/orders) on its backend. The backend fills in the missing details; the completed object is the contract terms.[1]

Fields we rely on:

FieldMeaningOur use
order_idUnique within the merchant instance Ties the sale to a producer's own numbering
summary, summary_i18n Human-readable description, localisable Must state the claim in Spanish and, where relevant, Quechua
products[]Line items with product detail One entry per lot, carrying weight and unit price
merchant_pubEdDSA public key of the instance The producer's key. The anchor of the whole scheme
merchant_sigEdDSA signature over the contract The producer signing the certified sale
h_contract_termsSHA-512 hash of the contract JSON Stable identifier for the sale; what the attestation binds against
extra Merchant-defined data, interpreted by the merchant frontend, carried on the contract without needing separate storage Where the attestation block lives. See spec
fulfillment_urlWhere the payer is sent after payment Receipt page with the full verification trace
timestamp, pay_deadlineContract timing Bounds replay of a signed lot claim

The wallet's verification is straightforward: compute the hash of the contract JSON, check merchant_sig against the instance's public key, and authenticate later requests with the contract hash.[1] Everything we add rides inside a structure that is already signed and already hashed; we are not inventing a signature envelope.

3. Contract format v1: choices, inputs, outputs

Taler's Contract Format v1 (design document 46) generalises a contract into a set of alternatives. Alongside the metadata fields above, a v1 contract carries a choices array; each choice has an amount, a max_fee, an inputs array of things the payer must supply, and an outputs array of things the merchant promises.[2]

Inputs may be coins or tokens (type: "token", with a token_family_slug, a valid_after timestamp and a number). Outputs may be coins, tokens, or a tax receipt. When the wallet pays, it commits to an h_outputs hash over the blinded outputs and signs over the selected choice_index as part of the deposit request.[2]

This is more machinery than a simple payment needs, and it is precisely the machinery a certification scheme needs, because it lets a contract say: this sale consumes N units of a bounded, authority-issued thing.

4. Token families

A contract's token_families map is keyed by slug, and each entry carries a name, a description, a set of issuing public keys, a details object describing the class (subscription or discount, with trusted or expected domains), and a critical flag.[2]

Tokens are issued by blind signature, like coins. That gives them three properties we want:

  • Bounded issuance. An authority can only sign as many as it decides to sign. A token cannot be forged and cannot be duplicated.
  • Unlinkability. The issuing authority cannot tell which of its tokens was spent where. A certifier learns that its quota was consumed, not who bought.
  • Spend-once. Redemption is checked against a double-spend database at the exchange, so the same unit cannot be sold twice.

Taler introduced this for subscriptions and discounts. We use it for a different thing entirely: a token family standing for "one kilogram certified under standard X, season Y". See kilo-tokens and mass balance. The critical flag matters — a wallet that does not understand a critical family must refuse rather than silently ignore it, which is the behaviour a certification claim requires.

This is a non-standard use of token families

Taler's design document frames details.class as subscription or discount. A certification quota is neither. Whether we can express this within the existing classes, or need to propose a third, is open question OQ-1 and the first thing to raise with upstream. We do not want a fork.

5. Why this stack fits the problem

What the problem needsWhat Taler already provides
The seller must be cryptographically identified Every contract is signed with merchant_sig under an instance's own key[1]
The buyer must not be surveilled for buying organic Blind-signed coins make the payer unlinkable by construction
The claim must be attached to the payment, not to a label Contract terms are the object being signed and paid against
Arbitrary structured data must ride along extra, plus products[] detail
Certified volume must be bounded Token families: blind-signed, bounded issuance, spend-once
Verification must work with bad connectivity Signature verification is local; only settlement needs the network
It has to be legal to operate Settlement is conventional banking, auditable, with a defined auditor role
Nobody should have to buy a speculative asset to sell potatoes Taler is denominated in ordinary currency — soles are soles

6. Why not a blockchain

The obvious objection: agricultural traceability on a distributed ledger is a well-populated field. We are not doing that, for reasons that are practical rather than ideological.

  • Consensus solves a problem we do not have. There is no dispute about who the certifying authority is — SENASA publishes the list. We need signatures under a known root, not agreement among strangers.
  • Public ledgers are the wrong privacy default. A permanent public record of every certified purchase is a surveillance artefact. Blind signatures give bounded issuance without a public transaction graph.
  • Volatility is not acceptable at a market stall. A vendor pricing papa nativa cannot absorb settlement-asset price movement.
  • Fees and latency. Per-kilo attestations at market volumes need to cost approximately nothing and confirm immediately.
  • Garbage in. The hardest part of produce traceability is the first assertion — that this sack really came from that parcel. No ledger fixes that. An SGP peer audit is a better answer to it than a consensus algorithm, which is why the institutional design here matters more than the cryptographic one.

7. Limits and things we still owe

  • Taler adoption in Peru is approximately zero. There is no deployed exchange, no wallet installed base, no bank integration. This is the largest risk in the project and no amount of protocol elegance touches it. See pilot risks.
  • Token families are not designed for this. See the note in § 4.
  • Offline payment is a different problem from offline verification. We get the second for free; the first is genuinely hard, and market stalls have patchy signal. OQ-2.
  • Key custody for producers is unsolved in a way that respects the reality of shared phones and lost devices. Discussed in the spec, not resolved.

See also: Protocol overview · Data model & spec

References

  1. GNU Taler, Merchant Backend RESTful API. docs.taler.net
  2. GNU Taler, DD 46: Contract Format v1. docs.taler.net
  3. GNU Taler, Merchant Point of Sale App Manual. docs.taler.net