commit bcaeb847d71c41768aa19c05fa8d05ffad5f805e
parent 19f871a71e034f89ba2502be08a4c12622a9fa82
Author: Mikolai Gütschow <mikolai.guetschow@tu-dresden.de>
Date: Wed, 29 Apr 2026 14:44:05 +0200
protocol: reorder sections logically
Diffstat:
2 files changed, 671 insertions(+), 586 deletions(-)
diff --git a/draft-guetschow-taler-protocol.md b/draft-guetschow-taler-protocol.md
@@ -576,7 +576,9 @@ Check-Subtract(value, subtrahend) =
// todo: capitalize wallet, exchange, merchant?
-## Withdrawal {#withdrawal}
+## Obtaining E-Cash
+
+### Withdrawal {#withdraw}
The wallet generates `n > 0` coins `⟨coinᵢ⟩` and requests `n` signatures `⟨blind_sigᵢ⟩` from the exchange,
attributing value to the coins according to `n` chosen denominations `⟨denomᵢ⟩`.
@@ -688,7 +690,13 @@ for i in 0..n:
Persist ⟨coinᵢ⟩
~~~
-## Payment {#payment}
+### Recoup {#withdraw-recoup}
+
+// todo
+
+## Payment with E-Cash {#payment}
+
+### Payment at a Merchant {#payment-merchant}
The wallet obtains `contract` information for an `order` from the merchant
after claiming it with a `nonce`.
@@ -817,7 +825,7 @@ msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
Check Ed25519-Verify(merchant.pub, msg, sig)
~~~
-## Deposit {#deposit}
+### Deposit performed by merchant {#deposit}
// todo: add introductory text
@@ -905,7 +913,151 @@ msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
Check Ed25519-Verify(exchange.pub, msg, sig)
~~~
-## Refresh {#refresh}
+### Refund {#refund}
+
+A wallet can request a refund for an order from the merchant after it has been completed successfully
+(cf. {{payment}}) and before the merchant has been paid out by the exchange (i.e., before `contract.wire_deadline`).
+The merchant needs to approve the refund via its business logic,
+and is free to decide the total amount of the refund
+as well as which coins' deposit operations (cf. {{deposit}}) are (potentially partly) invalidated.
+After the exchange has accepted the refund request,
+the coins obtain their (partial) value back.
+The wallet should proceed to refresh (cf. {{refresh}}) the coins before spending them again
+to obtain unlinkability.
+
+In case the wallet itself has used deposit to its own payto,
+it can act as the merchant in the protocol below.
+
+// todo: if proves practical, similar strucuture could be used for pay/deposit
+(interaction) between wallet, merchant and exchange
+
+~~~
+ wallet merchant exchange
+Knows order.id Knows merchant.priv Knows deposit_record
+Knows contract | for coinᵢ.pub
+ | | |
++---------------------+ | |
+| (W1) refund request | | |
++---------------------+ | |
+ | | |
+ |- /orders/{order.id}/refund ->| |
+ | (h_contract) | |
+ | | |
+ | +------------------------+ |
+ | | (M1) refund processing | |
+ | +------------------------+ |
+ | | |
+ | |- /coins/{coinᵢ.pub}/refund ->|
+ | | (valueᵢ, h_contract, id, |
+ | | merchant.pub, sigᵢ) |
+ | | |
+ | | +-------------------+
+ | | | (E1) refund check |
+ | | +-------------------+
+ | | |
+ | |<--- (exchange.pub, sigᵢ) ----|
+ | | |
+ | +--------------------------+ |
+ | | (M2) refund confirmation | |
+ | +--------------------------+ |
+ | | |
+ |<-----(value, ⟨refundᵢ⟩,------| |
+ | merchant.pub) | | // todo: why merchant.pub if no sig transmitted?
+ | | |
++-----------------------+ | |
+| (W2) refund reception | | |
++-----------------------+ | |
+ | | |
+~~~
+
+where (for RSA, without age-restriction)
+
+{::comment}
+
+⟨ᵧₖᵢ⟩
+{:/}
+
+~~~
+(W1) refund request (wallet)
+
+h_contract = SHA-512(canonicalJSON(contract))
+~~~
+
+{::comment}
+
+⟨ᵧₖᵢ⟩
+{:/}
+
+~~~
+(M1) refund processing (merchant)
+
+Check h_contract known and refund possible
+time = now()
+⟨coinᵢ⟩ = Lookup by h_contract
+id = ?
+for i in 0..n:
+ denomᵢ = Lookup by coinᵢ.h_denom
+ valueᵢ = refund amount // todo: split wisely
+ msgᵢ = Gen-Msg(MERCHANT_REFUND,
+ ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
+ sigᵢ = Ed25519-Sign(merchant.priv, msgᵢ)
+~~~
+
+{::comment}
+
+⟨ᵧₖᵢ⟩
+{:/}
+
+~~~
+(E1) refund check and confirmation (exchange)
+
+deposit_record = Lookup by h_contract // todo: needs to be persisted before with order.id and used coins!
+Check coinᵢ.pub part of deposit_record
+denomᵢ = Lookup by coinᵢ.pub
+msgᵢ = Gen-Msg(MERCHANT_REFUND,
+ ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
+Check Ed25519-Verify(merchant.pub, msgᵢ, sigᵢ)
+Check valueᵢ >= denomᵢ.fee_refund
+Check refund possible (prior to wire transfer deadline)
+remove/update scheduled wire transfer
+mark coin part as unspent
+msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
+sigᵢ = Ed25519-Sign(exchange.priv, msgᵢ)
+~~~
+
+{::comment}
+
+⟨ᵧₖᵢ⟩
+{:/}
+
+~~~
+(M2) refund confirmation (merchant)
+
+for i in 0..n:
+ msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
+ Check Ed25519-Verify(exchange.pub, msgᵢ, sigᵢ)
+ update business logic
+ refundᵢ = (valueᵢ, sigᵢ, id, coinᵢ.pub, time)
+value = sum ⟨valueᵢ⟩
+~~~
+
+{::comment}
+
+⟨ᵧₖᵢ⟩
+{:/}
+
+~~~
+(W2) refund reception (wallet)
+
+for i in 0..n:
+ (valueᵢ, sigᵢ, id, coinᵢ.pub, time) = refundᵢ
+update persistent transaction information
+refresh ⟨coinᵢ⟩
+~~~
+
+## Obtaining unlinkable change
+
+### Refresh {#refresh}
The wallet obtains `n` new coins `⟨coinᵢ⟩` of denominations `⟨denomᵢ⟩`
in exchange for one old `coin` of denomination `denom` from the exchange.
@@ -1224,157 +1376,19 @@ if ⟨blind_sigᵢ⟩ returned:
Persist ⟨coinᵧᵢ⟩
~~~
-## Refund {#refund}
-
-A wallet can request a refund for an order from the merchant after it has been completed successfully
-(cf. {{payment}}) and before the merchant has been paid out by the exchange (i.e., before `contract.wire_deadline`).
-The merchant needs to approve the refund via its business logic,
-and is free to decide the total amount of the refund
-as well as which coins' deposit operations (cf. {{deposit}}) are (potentially partly) invalidated.
-After the exchange has accepted the refund request,
-the coins obtain their (partial) value back.
-The wallet should proceed to refresh (cf. {{refresh}}) the coins before spending them again
-to obtain unlinkability.
-
-In case the wallet itself has used deposit to its own payto,
-it can act as the merchant in the protocol below.
-
-// todo: if proves practical, similar strucuture could be used for pay/deposit
-(interaction) between wallet, merchant and exchange
-
-~~~
- wallet merchant exchange
-Knows order.id Knows merchant.priv Knows deposit_record
-Knows contract | for coinᵢ.pub
- | | |
-+---------------------+ | |
-| (W1) refund request | | |
-+---------------------+ | |
- | | |
- |- /orders/{order.id}/refund ->| |
- | (h_contract) | |
- | | |
- | +------------------------+ |
- | | (M1) refund processing | |
- | +------------------------+ |
- | | |
- | |- /coins/{coinᵢ.pub}/refund ->|
- | | (valueᵢ, h_contract, id, |
- | | merchant.pub, sigᵢ) |
- | | |
- | | +-------------------+
- | | | (E1) refund check |
- | | +-------------------+
- | | |
- | |<--- (exchange.pub, sigᵢ) ----|
- | | |
- | +--------------------------+ |
- | | (M2) refund confirmation | |
- | +--------------------------+ |
- | | |
- |<-----(value, ⟨refundᵢ⟩,------| |
- | merchant.pub) | | // todo: why merchant.pub if no sig transmitted?
- | | |
-+-----------------------+ | |
-| (W2) refund reception | | |
-+-----------------------+ | |
- | | |
-~~~
-
-where (for RSA, without age-restriction)
-
-{::comment}
-
-⟨ᵧₖᵢ⟩
-{:/}
-
-~~~
-(W1) refund request (wallet)
-
-h_contract = SHA-512(canonicalJSON(contract))
-~~~
-
-{::comment}
-
-⟨ᵧₖᵢ⟩
-{:/}
-
-~~~
-(M1) refund processing (merchant)
-
-Check h_contract known and refund possible
-time = now()
-⟨coinᵢ⟩ = Lookup by h_contract
-id = ?
-for i in 0..n:
- denomᵢ = Lookup by coinᵢ.h_denom
- valueᵢ = refund amount // todo: split wisely
- msgᵢ = Gen-Msg(MERCHANT_REFUND,
- ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
- sigᵢ = Ed25519-Sign(merchant.priv, msgᵢ)
-~~~
-
-{::comment}
+### Recoup {#refresh-recoup}
-⟨ᵧₖᵢ⟩
-{:/}
-
-~~~
-(E1) refund check and confirmation (exchange)
-
-deposit_record = Lookup by h_contract // todo: needs to be persisted before with order.id and used coins!
-Check coinᵢ.pub part of deposit_record
-denomᵢ = Lookup by coinᵢ.pub
-msgᵢ = Gen-Msg(MERCHANT_REFUND,
- ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
-Check Ed25519-Verify(merchant.pub, msgᵢ, sigᵢ)
-Check valueᵢ >= denomᵢ.fee_refund
-Check refund possible (prior to wire transfer deadline)
-remove/update scheduled wire transfer
-mark coin part as unspent
-msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
-sigᵢ = Ed25519-Sign(exchange.priv, msgᵢ)
-~~~
-
-{::comment}
-
-⟨ᵧₖᵢ⟩
-{:/}
-
-~~~
-(M2) refund confirmation (merchant)
-
-for i in 0..n:
- msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
- Check Ed25519-Verify(exchange.pub, msgᵢ, sigᵢ)
- update business logic
- refundᵢ = (valueᵢ, sigᵢ, id, coinᵢ.pub, time)
-value = sum ⟨valueᵢ⟩
-~~~
-
-{::comment}
-
-⟨ᵧₖᵢ⟩
-{:/}
-
-~~~
-(W2) refund reception (wallet)
-
-for i in 0..n:
- (valueᵢ, sigᵢ, id, coinᵢ.pub, time) = refundᵢ
-update persistent transaction information
-refresh ⟨coinᵢ⟩
-~~~
+// todo
-## Recoup {#recoup}
+## Wallet-to-Wallet Payments {#w2w}
-// todo
+### Account Creation {#w2w-account}
-## Wallet-to-Wallet Push Payment {#w2w-push}
+### Push Payment {#w2w-push}
// todo
-## Wallet-to-Wallet Pull Payment {#w2w-pull}
+### Pull Payment {#w2w-pull}
// todo
@@ -1388,6 +1402,20 @@ None.
--- back
+# Test Vectors
+
+This appendix provides two sets of test vectors for testing Taler Protocol implementations.
+They are generated by going through the protocol operations in the following order:
+
+1. Withdraw two coins `coin₀` and `coin₁` from a single `reserve` (cf. {{withdraw}}).
+2. Pay for one `order` with the full value of `coin₀` and a partial value of `coin₁` (cf. {{payment}} and {{deposit}}).
+3. Refresh the now-dirty `coin₁` to two new coins `coin₂` and `coin₃` (cf. {{refresh}}).
+4. Regenerate `coin₂` and `coin₃` with the knowledge of `coin₁` (cf. {{link}}).
+5. Obtain a partial refund for `coin₀` used in `order` (cf. {{refund}}).
+6. Refresh the partially refunded `coin₀` into one new `coin₄` (cf. {{refresh}}). // todo: actually needed?
+
+// todo: still missing: recoup and w2w transfers
+
# Change log
# Acknowledgments
diff --git a/draft-guetschow-taler-protocol.xml b/draft-guetschow-taler-protocol.xml
@@ -549,15 +549,17 @@ Check-Subtract(value, subtrahend) =
<name>The Taler Crypto Protocol</name>
<t>// todo: briefly introduce the three components wallet, exchange, merchant; maybe with ASCII diagram version</t>
<t>// todo: capitalize wallet, exchange, merchant?</t>
- <section anchor="withdrawal">
- <name>Withdrawal</name>
- <t>The wallet generates <tt>n > 0</tt> coins <tt>⟨coinᵢ⟩</tt> and requests <tt>n</tt> signatures <tt>⟨blind_sigᵢ⟩</tt> from the exchange,
+ <section anchor="obtaining-e-cash">
+ <name>Obtaining E-Cash</name>
+ <section anchor="withdraw">
+ <name>Withdrawal</name>
+ <t>The wallet generates <tt>n > 0</tt> coins <tt>⟨coinᵢ⟩</tt> and requests <tt>n</tt> signatures <tt>⟨blind_sigᵢ⟩</tt> from the exchange,
attributing value to the coins according to <tt>n</tt> chosen denominations <tt>⟨denomᵢ⟩</tt>.
The total value and withdrawal fee (defined by the exchange per denomination)
must be smaller or equal to the amount stored in the single reserve used for withdrawal.</t>
- <t>// todo: document TALER_MAX_COINS = 64 per operation (due to CS-encoding)</t>
- <t>// todo: extend with extra roundtrip for CBS</t>
- <artwork><![CDATA[
+ <t>// todo: document TALER_MAX_COINS = 64 per operation (due to CS-encoding)</t>
+ <t>// todo: extend with extra roundtrip for CBS</t>
+ <artwork><![CDATA[
wallet exchange
Knows ⟨denomᵢ⟩ Knows ⟨denomᵢ.priv⟩
| |
@@ -590,19 +592,19 @@ Knows ⟨denomᵢ⟩ Knows ⟨denomᵢ.priv⟩
+----------------------+ |
| |
]]></artwork>
- <t>where (for RSA, without age-restriction)</t>
- <artwork><![CDATA[
+ <t>where (for RSA, without age-restriction)</t>
+ <artwork><![CDATA[
(W1) reserve key generation (wallet)
reserve = Ed25519-Keygen()
Persist (reserve, value)
]]></artwork>
- <t>The wallet derives coins and blinding secrets using a HKDF from a single seed per withdrawal operation,
+ <t>The wallet derives coins and blinding secrets using a HKDF from a single seed per withdrawal operation,
together with an integer index.
This is strictly speaking an implementation detail since the seed is never revealed to any other party,
and might be chosen to be implemented differently.</t>
- <t>// todo: blind_secret/coin.priv differently generated in TALER_EXCHANGE_post_withdraw_start/prepare_coins, double check with wallet-core (probably implementation detail here)</t>
- <artwork><![CDATA[
+ <t>// todo: blind_secret/coin.priv differently generated in TALER_EXCHANGE_post_withdraw_start/prepare_coins, double check with wallet-core (probably implementation detail here)</t>
+ <artwork><![CDATA[
(W2) coin generation and blinding (wallet)
batch_seed = random(256)
@@ -621,7 +623,7 @@ msg = Gen-Msg(WALLET_RESERVE_WITHDRAW,
| SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
sig = Ed25519-Sign(reserve.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(E1) coin issuance and signing (exchange)
(⟨h_denomᵢ⟩, ⟨planchetᵢ⟩) = planchets
@@ -640,7 +642,7 @@ for i in 0..n:
blind_sigᵢ = RSA-FDH-Sign(planchetᵢ, denomᵢ.priv)
Persist withdrawal // todo: what exactly? should be checked first for replay?
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W3) coin unblinding (wallet)
for i in 0..n:
@@ -650,15 +652,22 @@ for i in 0..n:
coinᵢ.blind_secret = blind_secretᵢ // todo: why save blind_secret, if batch_seed already persisted?
Persist ⟨coinᵢ⟩
]]></artwork>
+ </section>
+ <section anchor="withdraw-recoup">
+ <name>Recoup</name>
+ <t>// todo</t>
+ </section>
</section>
<section anchor="payment">
- <name>Payment</name>
- <t>The wallet obtains <tt>contract</tt> information for an <tt>order</tt> from the merchant
+ <name>Payment with E-Cash</name>
+ <section anchor="payment-merchant">
+ <name>Payment at a Merchant</name>
+ <t>The wallet obtains <tt>contract</tt> information for an <tt>order</tt> from the merchant
after claiming it with a <tt>nonce</tt>.
Payment of the order is prepared by signing (partial) deposit authorizations <tt>⟨depositᵢ⟩</tt> with coins <tt>⟨coinᵢ⟩</tt> of certain denominations <tt>⟨denomᵢ⟩</tt>,
where the sum of all contributions (<tt>contributionᵢ <= denomᵢ.value</tt>) must match the <tt>contract.price</tt> plus potential deposit fees.
The payment is complete as soon as the merchant successfully redeems the deposit authorizations at the exchange (cf. <xref target="deposit"/>).</t>
- <artwork><![CDATA[
+ <artwork><![CDATA[
wallet merchant
Knows ⟨coinᵢ⟩ Knows merchant.priv
Knows exchange, payto
@@ -701,25 +710,25 @@ Knows ⟨coinᵢ⟩ Knows merchant.priv
+---------------------------+ |
| |
]]></artwork>
- <t>where (without age restriction, policy and wallet data hash)</t>
- <artwork><![CDATA[
+ <t>where (without age restriction, policy and wallet data hash)</t>
+ <artwork><![CDATA[
(M1) order generation (merchant)
wire_salt = random(128)
determine id, price, info, token?
Persist order = (id, price, info, token?, wire_salt)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W1) nonce generation (wallet)
nonce = Ed25519-Keygen()
Persist nonce.priv
]]></artwork>
- <t>Note that the private key of <tt>nonce</tt> is currently not used anywhere in the protocol.
+ <t>Note that the private key of <tt>nonce</tt> is currently not used anywhere in the protocol.
However, it could be used in the future to prove ownership of an order transaction,
enabling use-cases such as "unclaiming" or transferring an order to another person,
or proving the payment without resorting to the individual coins.</t>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(M2) contract generation (merchant)
Check order.token? == token?
@@ -732,7 +741,7 @@ h_contract = SHA-512(canonicalJSON(contract))
msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
sig = Ed25519-Sign(merchant.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W2) payment preparation (wallet)
h_contract = SHA-512(canonicalJSON(contract))
@@ -754,8 +763,8 @@ for i in 0..n:
depositᵢ = (coinᵢ.{pub,sig,h_denom}, contributionᵢ, sigᵢ)
Persist (contract, ⟨sigᵢ⟩, ⟨depositᵢ⟩)
]]></artwork>
- <t>// TODO: explain CoinSelection</t>
- <artwork><![CDATA[
+ <t>// TODO: explain CoinSelection</t>
+ <artwork><![CDATA[
(M3) deposit check (merchant)
Check Sum ⟨depositᵢ.contribution⟩ == contract.price
@@ -763,18 +772,18 @@ Check Deposit(⟨depositᵢ⟩)
msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
sig = Ed25519-Sign(merchant.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W3) payment verification (wallet)
msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
Check Ed25519-Verify(merchant.pub, msg, sig)
]]></artwork>
- </section>
- <section anchor="deposit">
- <name>Deposit</name>
- <t>// todo: add introductory text</t>
- <t>Deposit could also be used directly by a wallet with its own payto and a minimal contract.</t>
- <artwork><![CDATA[
+ </section>
+ <section anchor="deposit">
+ <name>Deposit performed by merchant</name>
+ <t>// todo: add introductory text</t>
+ <t>Deposit could also be used directly by a wallet with its own payto and a minimal contract.</t>
+ <artwork><![CDATA[
merchant exchange
Knows exchange.pub Knows exchange.priv
Knows merchant.priv Knows ⟨denomᵢ⟩
@@ -800,8 +809,8 @@ Knows contract, ⟨depositᵢ⟩ |
+---------------------------+ |
| |
]]></artwork>
- <t>where (without age restriction, policy and wallet data hash)</t>
- <artwork><![CDATA[
+ <t>where (without age restriction, policy and wallet data hash)</t>
+ <artwork><![CDATA[
(M1) Deposit preparation (merchant)
info.time = contract.{timestamp, wire_deadline, refund_deadline}
@@ -810,7 +819,7 @@ h_contract = SHA-512(canonicalJSON(contract))
msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
sig = Ed25519-Sign(merchant.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(E1) Deposit validation (exchange)
h_wire = HKDF(info.wire.wire_salt, info.wire.payto, "merchant-wire-signature", 64)
@@ -839,7 +848,7 @@ msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
| SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
sig = Ed25519-Sign(exchange.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(M2) Deposit verification (merchant)
h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
@@ -851,31 +860,142 @@ msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
| SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
Check Ed25519-Verify(exchange.pub, msg, sig)
]]></artwork>
+ </section>
+ <section anchor="refund">
+ <name>Refund</name>
+ <t>A wallet can request a refund for an order from the merchant after it has been completed successfully
+(cf. <xref target="payment"/>) and before the merchant has been paid out by the exchange (i.e., before <tt>contract.wire_deadline</tt>).
+The merchant needs to approve the refund via its business logic,
+and is free to decide the total amount of the refund
+as well as which coins' deposit operations (cf. <xref target="deposit"/>) are (potentially partly) invalidated.
+After the exchange has accepted the refund request,
+the coins obtain their (partial) value back.
+The wallet should proceed to refresh (cf. <xref target="refresh"/>) the coins before spending them again
+to obtain unlinkability.</t>
+ <t>In case the wallet itself has used deposit to its own payto,
+it can act as the merchant in the protocol below.</t>
+ <t>// todo: if proves practical, similar strucuture could be used for pay/deposit
+(interaction) between wallet, merchant and exchange</t>
+ <artwork><![CDATA[
+ wallet merchant exchange
+Knows order.id Knows merchant.priv Knows deposit_record
+Knows contract | for coinᵢ.pub
+ | | |
++---------------------+ | |
+| (W1) refund request | | |
++---------------------+ | |
+ | | |
+ |- /orders/{order.id}/refund ->| |
+ | (h_contract) | |
+ | | |
+ | +------------------------+ |
+ | | (M1) refund processing | |
+ | +------------------------+ |
+ | | |
+ | |- /coins/{coinᵢ.pub}/refund ->|
+ | | (valueᵢ, h_contract, id, |
+ | | merchant.pub, sigᵢ) |
+ | | |
+ | | +-------------------+
+ | | | (E1) refund check |
+ | | +-------------------+
+ | | |
+ | |<--- (exchange.pub, sigᵢ) ----|
+ | | |
+ | +--------------------------+ |
+ | | (M2) refund confirmation | |
+ | +--------------------------+ |
+ | | |
+ |<-----(value, ⟨refundᵢ⟩,------| |
+ | merchant.pub) | | // todo: why merchant.pub if no sig transmitted?
+ | | |
++-----------------------+ | |
+| (W2) refund reception | | |
++-----------------------+ | |
+ | | |
+]]></artwork>
+ <t>where (for RSA, without age-restriction)</t>
+ <artwork><![CDATA[
+(W1) refund request (wallet)
+
+h_contract = SHA-512(canonicalJSON(contract))
+]]></artwork>
+ <artwork><![CDATA[
+(M1) refund processing (merchant)
+
+Check h_contract known and refund possible
+time = now()
+⟨coinᵢ⟩ = Lookup by h_contract
+id = ?
+for i in 0..n:
+ denomᵢ = Lookup by coinᵢ.h_denom
+ valueᵢ = refund amount // todo: split wisely
+ msgᵢ = Gen-Msg(MERCHANT_REFUND,
+ ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
+ sigᵢ = Ed25519-Sign(merchant.priv, msgᵢ)
+]]></artwork>
+ <artwork><![CDATA[
+(E1) refund check and confirmation (exchange)
+
+deposit_record = Lookup by h_contract // todo: needs to be persisted before with order.id and used coins!
+Check coinᵢ.pub part of deposit_record
+denomᵢ = Lookup by coinᵢ.pub
+msgᵢ = Gen-Msg(MERCHANT_REFUND,
+ ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
+Check Ed25519-Verify(merchant.pub, msgᵢ, sigᵢ)
+Check valueᵢ >= denomᵢ.fee_refund
+Check refund possible (prior to wire transfer deadline)
+remove/update scheduled wire transfer
+mark coin part as unspent
+msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
+sigᵢ = Ed25519-Sign(exchange.priv, msgᵢ)
+]]></artwork>
+ <artwork><![CDATA[
+(M2) refund confirmation (merchant)
+
+for i in 0..n:
+ msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
+ Check Ed25519-Verify(exchange.pub, msgᵢ, sigᵢ)
+ update business logic
+ refundᵢ = (valueᵢ, sigᵢ, id, coinᵢ.pub, time)
+value = sum ⟨valueᵢ⟩
+]]></artwork>
+ <artwork><![CDATA[
+(W2) refund reception (wallet)
+
+for i in 0..n:
+ (valueᵢ, sigᵢ, id, coinᵢ.pub, time) = refundᵢ
+update persistent transaction information
+refresh ⟨coinᵢ⟩
+]]></artwork>
+ </section>
</section>
- <section anchor="refresh">
- <name>Refresh</name>
- <t>The wallet obtains <tt>n</tt> new coins <tt>⟨coinᵢ⟩</tt> of denominations <tt>⟨denomᵢ⟩</tt>
+ <section anchor="obtaining-unlinkable-change">
+ <name>Obtaining unlinkable change</name>
+ <section anchor="refresh">
+ <name>Refresh</name>
+ <t>The wallet obtains <tt>n</tt> new coins <tt>⟨coinᵢ⟩</tt> of denominations <tt>⟨denomᵢ⟩</tt>
in exchange for one old <tt>coin</tt> of denomination <tt>denom</tt> from the exchange.
There are three reasons why a wallet needs to do this:</t>
- <ol spacing="normal" type="1"><li>
- <t>Obtaining unlinkable change after using only a part of the coin's value during a payment (cf. <xref target="payment"/>) or deposit (cf. <xref target="deposit"/>),
+ <ol spacing="normal" type="1"><li>
+ <t>Obtaining unlinkable change after using only a part of the coin's value during a payment (cf. <xref target="payment"/>) or deposit (cf. <xref target="deposit"/>),
i.e. where <tt>contribution <= denom.value</tt></t>
- </li>
- <li>
- <t>Obtaining unlinkable change after a successful refund (cf. <xref target="refund"/>)</t>
- </li>
- <li>
- <t>Renewing a coin before it deposit-expires</t>
- </li>
- </ol>
- <t>The sum of the refresh fee of <tt>denom</tt> and the new denominations' values and withdrawal fees (defined by the exchange)
+ </li>
+ <li>
+ <t>Obtaining unlinkable change after a successful refund (cf. <xref target="refund"/>)</t>
+ </li>
+ <li>
+ <t>Renewing a coin before it deposit-expires</t>
+ </li>
+ </ol>
+ <t>The sum of the refresh fee of <tt>denom</tt> and the new denominations' values and withdrawal fees (defined by the exchange)
must be smaller or equal to the residual value of the old <tt>coin</tt>.</t>
- <t>The private key of each new coin candidate <tt>⟨coinₖᵢ.priv⟩</tt> is transitively derived from the old coin's private key <tt>coin.priv</tt>
+ <t>The private key of each new coin candidate <tt>⟨coinₖᵢ.priv⟩</tt> is transitively derived from the old coin's private key <tt>coin.priv</tt>
via a 512-bit secret <tt>⟨sharedₖᵢ⟩</tt> according to <tt>Refresh-Derive</tt>.
The secret is regeneratable with the knowledge of <tt>coin.priv</tt> via the link protocol (cf. <xref target="link"/>).
The derivation ensures that ownership of coins (knowledge of the private key) is correctly transferred,
and thereby that value transfer among untrusted parties can only happen via payment and deposit, not via refresh.</t>
- <artwork><![CDATA[
+ <artwork><![CDATA[
Refresh-Derive(shared, denom) =
planchet_seed = HKDF(uint32(i), shared, "taler-coin-derivation", 64)
blind_secret = HKDF("bks", planchet_seed, "", 32)
@@ -885,18 +1005,18 @@ Refresh-Derive(shared, denom) =
h_planchet = Hash-Planchet(planchet, denomᵢ)
return (coin, blind_secret, planchet, h_planchet)
]]></artwork>
- <t>Taler uses a cut-and-choose protocol with the fixed parameter <tt>κ=3</tt> to enforce correct derivation
+ <t>Taler uses a cut-and-choose protocol with the fixed parameter <tt>κ=3</tt> to enforce correct derivation
of <tt>⟨sharedₖᵢ⟩</tt> from a single seed per batch of planchets <tt>⟨batch_seedₖ⟩</tt>
(in (κ-1)/κ of the cases, making income concealment for tax evasion purposes unpractical).</t>
- <t>Refreshing consists of two parts:</t>
- <ol spacing="normal" type="1"><li>
- <t>Melting of the old coin and commiting to κ batches of blinded planchet candidates</t>
- </li>
- <li>
- <t>Revelation of κ-1 secrets <tt>⟨revealed_seedₖ⟩</tt> to prove the proper construction of the (revealed) batches of blinded planchet candidates.</t>
- </li>
- </ol>
- <artwork><![CDATA[
+ <t>Refreshing consists of two parts:</t>
+ <ol spacing="normal" type="1"><li>
+ <t>Melting of the old coin and commiting to κ batches of blinded planchet candidates</t>
+ </li>
+ <li>
+ <t>Revelation of κ-1 secrets <tt>⟨revealed_seedₖ⟩</tt> to prove the proper construction of the (revealed) batches of blinded planchet candidates.</t>
+ </li>
+ </ol>
+ <artwork><![CDATA[
wallet exchange
Knows ⟨denomᵢ⟩ Knows ⟨denomᵢ.priv⟩
Knows coin |
@@ -933,8 +1053,8 @@ Knows coin |
+----------------------+ |
| |
]]></artwork>
- <t>where (for RSA, without age-restriction)</t>
- <artwork><![CDATA[
+ <t>where (for RSA, without age-restriction)</t>
+ <artwork><![CDATA[
(W1) coin melting (wallet)
refresh_seed = random(256)
@@ -958,7 +1078,7 @@ msg = Gen-Msg(WALLET_COIN_MELT,
sig = Ed25519-Sign(coin.priv, msg)
Persist (coin.denom.pub, ...) // todo: double-check
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(E1) gamma selection and coin signing (exchange)
denom = Lookup by coin.h_denom
@@ -994,7 +1114,7 @@ msg = Gen-Msg(EXCHANGE_CONFIRM_MELT,
( commitment | uint32(ɣ) ))
sig = Ed25519-Sign(exchange.priv, msg)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W2) secret revelation (wallet)
Check exchange.pub known
@@ -1005,7 +1125,7 @@ Persist refresh-challenge // what exactly?
for k in 0..κ and k != ɣ:
revealed_seedₖ = batch_seedₖ
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(E2) commitment validation (exchange)
refresh_record = Lookup by commitment
@@ -1024,7 +1144,7 @@ commitment' = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
Check commitment == commitment'
Persist refresh_record = (_, _, _, true, _)
]]></artwork>
- <artwork><![CDATA[
+ <artwork><![CDATA[
(W3) coin unblinding (wallet)
for i in 0..n:
@@ -1033,9 +1153,12 @@ for i in 0..n:
coinᵧᵢ.h_denom = h_denomᵢ
Persist ⟨coinᵧᵢ⟩
]]></artwork>
+ </section>
<section anchor="link">
<name>Link</name>
- <t>// todo: add introductory text</t>
+ <t>Coins ⟨coinᵧᵢ⟩ obtained via the refresh protocol (cf. <xref target="refresh"/>) can be regenerated
+with the knowledge of the old coin's private key <tt>coin.priv</tt> using the link protocol,
+integrated in the coin history endpoint.</t>
<artwork><![CDATA[
wallet exchange
Knows coin Knows refresh_record for coin.pub
@@ -1104,125 +1227,24 @@ if ⟨blind_sigᵢ⟩ returned:
Persist ⟨coinᵧᵢ⟩
]]></artwork>
</section>
+ <section anchor="refresh-recoup">
+ <name>Recoup</name>
+ <t>// todo</t>
+ </section>
</section>
- <section anchor="refund">
- <name>Refund</name>
- <t>A wallet can request a refund for an order after it has been completed successfully
-(cf. <xref target="payment"/>) and before the deadline for the wire transfer from the exchange
-to the merchant's bank account has passed.
-The merchant needs to approve the refund via its business logic,
-and is free to decide the total amount of the refund
-as well as which coins' deposit operations (cf. <xref target="deposit"/>) are (potentially partly) invalidated.
-After the exchange has accepted the refund request,
-the coins obtain their (partial) value back.
-The wallet should proceed to refresh (cf. <xref target="refresh"/>) the coins before spending them again
-to obtain unlinkability.</t>
- <t>// todo: if proves practical, similar strucuture could be used for pay/deposit
-(interaction) between wallet, merchant and exchange</t>
- <artwork><![CDATA[
- wallet merchant exchange
-Knows order.id Knows merchant.priv Knows deposit_record
-Knows contract | for coinᵢ.pub
- | | |
-+---------------------+ | |
-| (W1) refund request | | |
-+---------------------+ | |
- | | |
- |- /orders/{order.id}/refund ->| |
- | (h_contract) | |
- | | |
- | +------------------------+ |
- | | (M1) refund processing | |
- | +------------------------+ |
- | | |
- | |- /coins/{coinᵢ.pub}/refund ->|
- | | (valueᵢ, h_contract, id, |
- | | merchant.pub, sigᵢ) |
- | | |
- | | +-------------------+
- | | | (E1) refund check |
- | | +-------------------+
- | | |
- | |<--- (exchange.pub, sigᵢ) ----|
- | | |
- | +--------------------------+ |
- | | (M2) refund confirmation | |
- | +--------------------------+ |
- | | |
- |<-----(value, ⟨refundᵢ⟩,------| |
- | merchant.pub) | | // todo: why merchant.pub if no sig transmitted?
- | | |
-+-----------------------+ | |
-| (W2) refund reception | | |
-+-----------------------+ | |
- | | |
-]]></artwork>
- <t>where (for RSA, without age-restriction)</t>
- <artwork><![CDATA[
-(W1) refund request (wallet)
-
-h_contract = SHA-512(canonicalJSON(contract))
-]]></artwork>
- <artwork><![CDATA[
-(M1) refund processing (merchant)
-
-Check h_contract known and refund possible
-time = now()
-⟨coinᵢ⟩ = Lookup by h_contract
-id = ?
-for i in 0..n:
- denomᵢ = Lookup by coinᵢ.h_denom
- valueᵢ = refund amount // todo: split wisely
- msgᵢ = Gen-Msg(MERCHANT_REFUND,
- ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
- sigᵢ = Ed25519-Sign(merchant.priv, msgᵢ)
-]]></artwork>
- <artwork><![CDATA[
-(E1) refund check and confirmation (exchange)
-
-deposit_record = Lookup by h_contract // todo: needs to be persisted before with order.id and used coins!
-Check coinᵢ.pub part of deposit_record
-denomᵢ = Lookup by coinᵢ.pub
-msgᵢ = Gen-Msg(MERCHANT_REFUND,
- ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
-Check Ed25519-Verify(merchant.pub, msgᵢ, sigᵢ)
-Check valueᵢ >= denomᵢ.fee_refund
-Check refund possible (prior to wire transfer deadline)
-remove/update scheduled wire transfer
-mark coin part as unspent
-msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
-sigᵢ = Ed25519-Sign(exchange.priv, msgᵢ)
-]]></artwork>
- <artwork><![CDATA[
-(M2) refund confirmation (merchant)
-
-for i in 0..n:
- msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
- Check Ed25519-Verify(exchange.pub, msgᵢ, sigᵢ)
- update business logic
- refundᵢ = (valueᵢ, sigᵢ, id, coinᵢ.pub, time)
-value = sum ⟨valueᵢ⟩
-]]></artwork>
- <artwork><![CDATA[
-(W2) refund reception (wallet)
-
-for i in 0..n:
- (valueᵢ, sigᵢ, id, coinᵢ.pub, time) = refundᵢ
-update persistent state about transaction
-refresh ⟨coinᵢ⟩
-]]></artwork>
- </section>
- <section anchor="recoup">
- <name>Recoup</name>
- <t>// todo</t>
- </section>
- <section anchor="w2w-push">
- <name>Wallet-to-Wallet Push Payment</name>
- <t>// todo</t>
- </section>
- <section anchor="w2w-pull">
- <name>Wallet-to-Wallet Pull Payment</name>
- <t>// todo</t>
+ <section anchor="w2w">
+ <name>Wallet-to-Wallet Payments</name>
+ <section anchor="w2w-account">
+ <name>Account Creation</name>
+ </section>
+ <section anchor="w2w-push">
+ <name>Push Payment</name>
+ <t>// todo</t>
+ </section>
+ <section anchor="w2w-pull">
+ <name>Pull Payment</name>
+ <t>// todo</t>
+ </section>
</section>
</section>
<section anchor="security-considerations">
@@ -1339,9 +1361,34 @@ refresh ⟨coinᵢ⟩
<refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
</reference>
</references>
- <?line 1385?>
-
-<section anchor="change-log">
+ <?line 1403?>
+
+<section anchor="test-vectors">
+ <name>Test Vectors</name>
+ <t>This appendix provides two sets of test vectors for testing Taler Protocol implementations.
+They are generated by going through the protocol operations in the following order:</t>
+ <ol spacing="normal" type="1"><li>
+ <t>Withdraw two coins <tt>coin₀</tt> and <tt>coin₁</tt> from a single <tt>reserve</tt> (cf. <xref target="withdraw"/>).</t>
+ </li>
+ <li>
+ <t>Pay for one <tt>order</tt> with the full value of <tt>coin₀</tt> and a partial value of <tt>coin₁</tt> (cf. <xref target="payment"/> and <xref target="deposit"/>).</t>
+ </li>
+ <li>
+ <t>Refresh the now-dirty <tt>coin₁</tt> to two new coins <tt>coin₂</tt> and <tt>coin₃</tt> (cf. <xref target="refresh"/>).</t>
+ </li>
+ <li>
+ <t>Regenerate <tt>coin₂</tt> and <tt>coin₃</tt> with the knowledge of <tt>coin₁</tt> (cf. <xref target="link"/>).</t>
+ </li>
+ <li>
+ <t>Obtain a partial refund for <tt>coin₀</tt> used in <tt>order</tt> (cf. <xref target="refund"/>).</t>
+ </li>
+ <li>
+ <t>Refresh the partially refunded <tt>coin₀</tt> into one new <tt>coin₄</tt> (cf. <xref target="refresh"/>). // todo: actually needed?</t>
+ </li>
+ </ol>
+ <t>// todo: still missing: recoup and w2w transfers</t>
+ </section>
+ <section anchor="change-log">
<name>Change log</name>
</section>
<section numbered="false" anchor="acknowledgments">
@@ -1352,255 +1399,265 @@ Education and Research (BMBF) within the project Concrete Contracts.</t>
</section>
</back>
<!-- ##markdown-source:
-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
-BRwMyKZNZ8FXQEU/O2k1emXf0NGQDYQp9fbH8uxcW7nA5Lpx7hpvyiCcUCqQ
-bqsY2H8j7b7YFa4QD1qCEnNTJBhfxKHxigIF+AC9PccN9YJucInNOkHQ1X6j
-IhMVHug9JjzMnKK7lDvYB1hHeDcPltfhvnMo5ZRbNKBPbYaYvKJK66vW5Slm
-O0ZYNw1nWMIk1kpSLOnGrXVnUjvVcGZF3zKxDKgr0t8sBr9B6P0U3AEWBDvJ
-94Hmr4GoMdAW/j8cd/B+BdETRw/34f8vjh9bYfYymH1aYfdVFLaL9FwmX71p
-2Q3fQwZrVaRs0qykm9ZLsL77nNUHKzos6amJ0iPM5r1XjOEofNMjDazo0pDB
-gh+fFs4eDPdlyhjC/KYZrJsIEMWSrFlvU4behxiBllWQti09hyTgc4crxGjV
-nMuWsrynSudqg8MGeQ15eJc5qw/WXObNhAFWZFRUszDwj1/1KFrV5r+NSNxE
-GO6V/hLnaT7IzDWwLEvYMrV8w/POz3sSgKXcaFK1WgC4amS0WgLeZc63X6ed
-qrUytMLK0IILlMbR6Jo3l1USFUtL8NCFzsPVOh++1kzQ6hKi/r46KKGSb1vb
-n7U8c/2DAJMuyJ/VV5OwGTGhCA+/K/yGhphiVnPYWZJa01yGhfxqSUJZWTd0
-IRdupZJO7TyWqnKAQn421VJishSjddoWD5JrRnWl0rPrPUovMalL94OMdMxr
-F4WezakWja+8g3AuvYS15JNopkpBGTm0QcoVnm1PJgEGfWMcpzMKqDRujqVY
-udiYJzq62sB8gt5YzVQmWo2GiWWVVobJcEw8k4F3mahSVs3kmnOAa9SpNVUx
-gFH4RRTO6XYSiKa6ml0aTK3NMRxS2x4FViorppj0kdg6E2sIr9z1ttjQA3Xw
-XVlXqHKvJdeZ2k68WPFsDjFyCLEw4E0qftJ/egbeXdsLZUYkPlQOqV2VwmC2
-15+lZabpas407pVhSd0EsGABZbINQLQEK6b+/uTZkXETWtXc2dPDY0zYn/b3
-nx2dHu/tnyK0pnVdMtKJpxaykU1WvxS19whtbW7N9YuqybUqnhWicRvk9NnB
-sx21SdFh48cFJnTMjB58Vb2+coxXAUV0c8A+cPqJjNU5U+BKvSk0vC6TGpfS
-pF0wU6ozO/qGVDsl4IE3kevxVOy7685iENd9ZZiPOBPCI14Nl99J8TTIzg8i
-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
-JkywS/yFdG/e9f4/fQZjIeOzAAA=
+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
+VzdxrRtvxCB4aEoFXayAnB7MC87wGleYBPEE2SQ2B2aDNAOmH3Q9DZe++U6l
+YWKKpE8DdRJmZC1dvYJNAvSks27Blafin53IHb2yC4MsCDjClPrUZXkAsK2s
+bLIOOWSOBToIJxRtpCIZA/tvZI8vdoUrJwYtQbG/CfIE1//QeMU9C/gA1TDD
+c/ySCsckZp0gS9Qxp6IX5Tvooy28Q52hRVY42AdYQywJhFl9eNwdSTnhFgvQ
+p85gTOhSnSao1tXladsNWTfSZ1jCxO4qUizpxq11Z5JsdY9pRd8qng2oK7Nf
+zc2/gXf/BCwO3gh2HPE9zd8A0UJfXvh/d9zBsg6iJ44e7MP/nx8/sjz5ZTD7
+tMLuyzhql9m5TL963bIbvoMg2Spn3ERySTatF8N9+znrD1Z0WNJTE6VHmC16
+LxnDcfS6RxJY0WVBkAx+fFo4G0nclyljCPOrBslusoHIXWXJept76F1sI5Cy
+CtK2JeeQBHzdccU2WjXnsqUs76kixlrhsEJeYz+8zZz1B2su82abAVZkRNTi
+zcA/ft2iaNWb/zpb4iab4W5lL3Eo6L3M3ADLspgwU8s3PO/8vKMNsJQbTTRY
+bwBOVglX74C3mfPN12lHg60gsLCCwGACZUkcXvP5tYrTYkYL3vXQob5G48PX
+kglaXca57Kv7GSq+t7X9WcszVScEqHRB9qyuiMJqxHg7PPyu8Bc0xCi2msMO
+xDSq5srz5FdLYtZKu6EJOVcMSzop+5ghyw4K2dmUwonxWAwI0Ml7kF4zqmsJ
+pl3vYXaJcWMqSxJqt9rORT2bUQocV9oDjzG7hLUU43iqMlAZOXQGy4mlbU+m
+AfqVIxynEwaUkTfDDLBCbMxS7V1tYMhCn93mKtitRsPYtYpcw2Q4Jl4FwRIq
+KoN2armQGd31LtRlOZWUgI7+RRzNqCgKeFNdzS4LVK3NMey12xYFJkgrphj3
+kdg62GsIr8z1ttjQA3XwXZXOqMK7FdeZlFKs53g2Azc8Ancb8CYVP+k/PQPv
+rm2FMiMSHyqD1E6GYTDb68/SMtN0NWca88qwpG4CWLCAMgENIFqKiVp/e/L0
+yJgJrXp47snhMZ4JnPb3nx6dHu/tnyK0pnVTvNPxp+YCnou0frXV3iG0jeE7
+1y6qx+/qeFaIxhDJ6dODpzvqHKTDyo9zWOh2Gz34ql41c4QViGIqWLAPnH4i
+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
+D8LvvKM0QFEt8Rc6vINN+f8B6tCuZDi5AAA=
-->