commit 03ef78ac0243a3705c49f41e7edb78f039e957f2
parent 624a15a981cd3e1fd956a1cd3ac692aebab50346
Author: Mikolai Gütschow <mikolai.guetschow@tu-dresden.de>
Date: Mon, 6 Apr 2026 12:07:40 +0200
protocol: pass-through to fix notation
Diffstat:
2 files changed, 236 insertions(+), 226 deletions(-)
diff --git a/draft-guetschow-taler-protocol.md b/draft-guetschow-taler-protocol.md
@@ -387,22 +387,24 @@ Output:
out = uint32(len(msg)) | uint32(purpose) | msg
~~~
-// todo: explain persist, check, knows, sum, indexing (if left of equal sign, single entry; if not refers to whole list)
-
# The Taler Crypto Protocol
+// todo: explain persist, check, knows, sum, indexing/list notation
+
## Withdrawal {#withdrawal}
-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ᵢ`).
+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ᵢ⟩`.
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.
+// notation: ⟨⟩ᵢ
+
// todo: extend with extra roundtrip for CBS
~~~
wallet exchange
-knows denomᵢ.pub knows denomᵢ.priv
+knows ⟨denomᵢ⟩ knows ⟨denomᵢ.priv⟩
| |
+-----------------------------+ |
| (W1) reserve key generation | |
@@ -420,14 +422,14 @@ knows denomᵢ.pub knows denomᵢ.priv
+-----------------------------------+ |
| |
|-------------- /withdraw -------------->|
- | (reserve.pub, ~(coinᵢ.h_denom), |
- | ~blind_coin, sig0) |
+ | (reserve.pub, ⟨coinᵢ.h_denom⟩, |
+ | ⟨blind_coinᵢ⟩, sig) |
| |
| +--------------------------------+
| | (E1) coin issuance and signing |
| +--------------------------------+
| |
- |<----------- (~blind_sig) --------------|
+ |<---------- (⟨blind_sigᵢ⟩) -------------|
| |
+----------------------+ |
| (W3) coin unblinding | |
@@ -461,8 +463,8 @@ coinᵢ.pub = EdDSA-GetPub(coinᵢ.priv)
coinᵢ.h_denom = SHA-512(uint32(0) | uint32(1) | denomᵢ.pub)
blind_coinᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
- ( sum(denomᵢ.value) | sum(denomᵢ.fee_withdraw)
- | SHA-512( SHA-512(~(denomᵢ.pub)) | uint32(0x1) | blind_coinᵢ )
+ ( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
+ | SHA-512( SHA-512( ⟨denomᵢ.pub⟩ ) | uint32(0x1) | ⟨blind_coinᵢ⟩ )
| uint256(0x0) | uint32(0x0) | uint32(0x0) ))
sig = EdDSA-Sign(reserve.priv, msg)
~~~
@@ -474,32 +476,32 @@ denomᵢ = Denom-Lookup(coinᵢ.h_denom)
check denomᵢ.pub known and not withdrawal-expired
check EdDSA-Verify(reserve.pub, msg, sig)
check reserve KYC status ok or not needed
-total = sum(~(denomᵢ.value)) + sum(~(denomᵢ.fee_withdraw))
+total = sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
check reserve.balance >= total
reserve.balance -= total
blind_sigᵢ = RSA-FDH-Sign(blind_coinᵢ, denomᵢ.priv)
-persist withdrawal
+persist withdrawal // todo: what exactly? should be checked first?
~~~
~~~
-(W4) coin unblinding (wallet)
+(W3) coin unblinding (wallet)
coinᵢ.sig = RSA-FDH-Unblind(blind_sigᵢ, blind_secretᵢ, denomᵢ.pub)
check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
-persist (coinᵢ, blind_secretᵢ)
+persist (coinᵢ, blind_secretᵢ) // todo: why blind_secret, if master_secret already persisted?
~~~
## Payment {#payment}
The wallet obtains `contract` information for an `order` from the merchant
after claiming it with a `nonce`.
-Payment of the order is prepared by signing (partial) deposit authorizations (`depositᵢ`) of coins (`coinᵢ`),
+Payment of the order is prepared by signing (partial) deposit authorizations `⟨depositᵢ⟩` with coins `⟨coinᵢ⟩` of certain denominations `⟨denomᵢ⟩`,
where the sum of all contributions (`contributionᵢ <= denomᵢ.value`) must match the `contract.price` plus potential deposit fees.
The payment is complete as soon as the merchant successfully redeems the deposit authorizations at the exchange (cf. {{deposit}}).
~~~
wallet merchant
-knows valid coinᵢ knows merchant.priv
+knows ⟨coinᵢ⟩ knows merchant.priv
knows exchange, payto
| |
| +-----------------------+
@@ -520,14 +522,14 @@ knows valid coinᵢ knows merchant.priv
| | (M2) contract generation |
| +--------------------------+
| |
- |<---- (contract, merchant.pub, contract_sig) ----|
+ |<---- (contract, merchant.pub, sig) ----|
| |
+--------------------------+ |
| (W2) payment preparation | |
+--------------------------+ |
| |
|------- /orders/{order.id}/pay -------->|
- | (~deposit) |
+ | (⟨depositᵢ⟩) |
| |
| +--------------------+
| | (M3) deposit check |
@@ -547,6 +549,7 @@ where (without age restriction, policy and wallet data hash)
(M1) order generation (merchant)
wire_salt = random(128)
+determine id, price, info, token?
persist order = (id, price, info, token?, wire_salt)
~~~
@@ -565,15 +568,15 @@ or proving the payment without resorting to the individual coins.
~~~
(M2) contract generation (merchant)
+check order.token? == token?
h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
determine timestamp, refund_deadline, wire_deadline
contract = (order.{id,price,info,token?}, exchange, h_wire, timestamp, refund_deadline, wire_deadline)
-check contract.order.token == token
contract.nonce = nonce.pub
persist contract
h_contract = SHA-512(canonicalJSON(contract))
msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
-contract_sig = EdDSA-Sign(merchant.priv, msg)
+sig = EdDSA-Sign(merchant.priv, msg)
~~~
~~~
@@ -581,12 +584,11 @@ contract_sig = EdDSA-Sign(merchant.priv, msg)
h_contract = SHA-512(canonicalJSON(contract))
msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
-check EdDSA-Verify(merchant.pub, msg, contract_sig)
-check contract.nonce = nonce
-TODO: double-check extra hash check?
-~selection = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
+check EdDSA-Verify(merchant.pub, msg, sig)
+check contract.nonce == nonce
+// TODO: double-check extra hash check?
+⟨selectionᵢ⟩ = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
(coinᵢ, denomᵢ, contributionᵢ) = selectionᵢ
-h_contract = SHA-512(canonicalJSON(contract))
msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
( h_contract | uint256(0x0)
| uint512(0x0) | contract.h_wire | coinᵢ.h_denom
@@ -595,19 +597,18 @@ msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
| denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
sigᵢ = EdDSA-Sign(coinᵢ.priv, msgᵢ)
depositᵢ = (coinᵢ.{pub,sig,h_denom}, contributionᵢ, sigᵢ)
-persist (contract, ~sig, ~deposit)
+persist (contract, ⟨sigᵢ⟩, ⟨depositᵢ⟩)
~~~
// TODO: explain CoinSelection
-// TODO: maybe better {sigᵢ} instead of ~sig?
// TODO: maybe introduce symbol for pub/priv
// TODO: maybe rename Sign-Msg as name is currently a bit confusing
~~~
(M3) deposit check (merchant)
-check sum(depositᵢ.contribution) == contract.price
-check Deposit(~deposit)
+check sum( ⟨depositᵢ.contribution⟩ ) == contract.price
+check Deposit(⟨depositᵢ⟩)
msg = Sign-Msg(MERCHANT_PAYMENT_OK, h_contract)
sig = EdDSA-Sign(merchant.priv, msg)
~~~
@@ -623,20 +624,22 @@ check EdDSA-Verify(merchant.pub, msg, sig)
// todo: add introductory text
+Deposit could also be used directly by a wallet with its own payto and a minimal contract.
+
~~~
- merchant/wallet exchange
+ merchant exchange
knows exchange.pub knows exchange.priv
-knows contract_sig knows denomᵢ.pub
+knows merchant.priv knows ⟨denomᵢ⟩
knows payto, wire_salt |
-knows contract, ~deposit |
+knows contract, ⟨depositᵢ⟩ |
| |
+--------------------------+ |
| (M1) deposit preparation | |
+--------------------------+ |
| |
|----------- /batch-deposit ------------>|
- | (info, h_contract, ~deposit |
- | merchant.pub, contract_sig) |
+ | (info, h_contract, ⟨depositᵢ⟩ |
+ | merchant.pub, sig) |
| |
| +-------------------------+
| | (E1) deposit validation |
@@ -653,11 +656,13 @@ knows contract, ~deposit |
where (without age restriction, policy and wallet data hash)
~~~
-(M1) Deposit preparation (merchant/wallet)
+(M1) Deposit preparation (merchant)
-h_contract = SHA-512(canonicalJSON(contract))
info.time = contract.{timestamp, wire_deadline, refund_deadline}
info.wire = (payto, wire_salt)
+h_contract = SHA-512(canonicalJSON(contract))
+msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
+sig = EdDSA-Sign(merchant.priv, msg)
~~~
~~~
@@ -665,7 +670,7 @@ info.wire = (payto, wire_salt)
coinᵢ = depositᵢ.coin
denomᵢ = Denom-Lookup(coinᵢ.h_denom)
-check denomᵢ.pub known and not deposit-expired
+check denomᵢ.pub known and not deposit-expired // todo: check could be included in Denom-Lookup
h_wire = HKDF(info.wire.wire_salt, info.wire.payto, "merchant-wire-signature", 64)
msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
( h_contract | uint256(0x0)
@@ -683,21 +688,21 @@ msg = Sign-Msg(EXCHANGE_CONFIRM_DEPOSIT,
( h_contract | h_wire | uint512(0x0)
| timestamp | info.time.wire_deadline
| info.time.refund_deadline
- | sum(depositᵢ.contribution) - sum(denomᵢ.fee_deposit)
- | SHA-512(depositᵢ.sig) | merchant.pub ))
+ | sum( ⟨depositᵢ.contribution⟩ )
+ | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
sig = EdDSA-Sign(exchange.priv, msg)
~~~
~~~
-(M2) Deposit verification (merchant/wallet)
+(M2) Deposit verification (merchant)
h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
msg = Sign-Msg(EXCHANGE_CONFIRM_DEPOSIT,
( h_contract | h_wire | uint512(0x0)
| timestamp | contract.wire_deadline
| contract.refund_deadline
- | sum(depositᵢ.contribution) - sum(denomᵢ.fee_deposit)
- | SHA-512(depositᵢ.sig) | merchant.pub ))
+ | sum( ⟨depositᵢ.contribution⟩ )
+ | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
check EdDSA-Verify(exchange.pub, msg, sig)
~~~
diff --git a/draft-guetschow-taler-protocol.xml b/draft-guetschow-taler-protocol.xml
@@ -24,7 +24,7 @@
<email>mikolai.guetschow@tu-dresden.de</email>
</address>
</author>
- <date year="2026" month="April" day="02"/>
+ <date year="2026" month="April" day="06"/>
<workgroup>independent</workgroup>
<keyword>taler</keyword>
<keyword>cryptography</keyword>
@@ -376,21 +376,22 @@ Output:
<artwork><![CDATA[
out = uint32(len(msg)) | uint32(purpose) | msg
]]></artwork>
- <t>// todo: explain persist, check, knows, sum, indexing (if left of equal sign, single entry; if not refers to whole list)</t>
</section>
</section>
<section anchor="the-taler-crypto-protocol">
<name>The Taler Crypto Protocol</name>
+ <t>// todo: explain persist, check, knows, sum, indexing/list notation</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,
-attributing value to the coins according to <tt>n</tt> chosen denominations (<tt>denomᵢ</tt>).
+ <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>// notation: ⟨⟩ᵢ</t>
<t>// todo: extend with extra roundtrip for CBS</t>
<artwork><![CDATA[
wallet exchange
-knows denomᵢ.pub knows denomᵢ.priv
+knows ⟨denomᵢ⟩ knows ⟨denomᵢ.priv⟩
| |
+-----------------------------+ |
| (W1) reserve key generation | |
@@ -408,14 +409,14 @@ knows denomᵢ.pub knows denomᵢ.priv
+-----------------------------------+ |
| |
|-------------- /withdraw -------------->|
- | (reserve.pub, ~(coinᵢ.h_denom), |
- | ~blind_coin, sig0) |
+ | (reserve.pub, ⟨coinᵢ.h_denom⟩, |
+ | ⟨blind_coinᵢ⟩, sig) |
| |
| +--------------------------------+
| | (E1) coin issuance and signing |
| +--------------------------------+
| |
- |<----------- (~blind_sig) --------------|
+ |<---------- (⟨blind_sigᵢ⟩) -------------|
| |
+----------------------+ |
| (W3) coin unblinding | |
@@ -445,8 +446,8 @@ coinᵢ.pub = EdDSA-GetPub(coinᵢ.priv)
coinᵢ.h_denom = SHA-512(uint32(0) | uint32(1) | denomᵢ.pub)
blind_coinᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
msg = Sign-Msg(WALLET_RESERVE_WITHDRAW,
- ( sum(denomᵢ.value) | sum(denomᵢ.fee_withdraw)
- | SHA-512( SHA-512(~(denomᵢ.pub)) | uint32(0x1) | blind_coinᵢ )
+ ( sum( ⟨denomᵢ.value⟩ ) | sum( ⟨denomᵢ.fee_withdraw⟩ )
+ | SHA-512( SHA-512( ⟨denomᵢ.pub⟩ ) | uint32(0x1) | ⟨blind_coinᵢ⟩ )
| uint256(0x0) | uint32(0x0) | uint32(0x0) ))
sig = EdDSA-Sign(reserve.priv, msg)
]]></artwork>
@@ -457,30 +458,30 @@ denomᵢ = Denom-Lookup(coinᵢ.h_denom)
check denomᵢ.pub known and not withdrawal-expired
check EdDSA-Verify(reserve.pub, msg, sig)
check reserve KYC status ok or not needed
-total = sum(~(denomᵢ.value)) + sum(~(denomᵢ.fee_withdraw))
+total = sum( ⟨denomᵢ.value⟩ ) + sum( ⟨denomᵢ.fee_withdraw⟩ )
check reserve.balance >= total
reserve.balance -= total
blind_sigᵢ = RSA-FDH-Sign(blind_coinᵢ, denomᵢ.priv)
-persist withdrawal
+persist withdrawal // todo: what exactly? should be checked first?
]]></artwork>
<artwork><![CDATA[
-(W4) coin unblinding (wallet)
+(W3) coin unblinding (wallet)
coinᵢ.sig = RSA-FDH-Unblind(blind_sigᵢ, blind_secretᵢ, denomᵢ.pub)
check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
-persist (coinᵢ, blind_secretᵢ)
+persist (coinᵢ, blind_secretᵢ) // todo: why blind_secret, if master_secret already persisted?
]]></artwork>
</section>
<section anchor="payment">
<name>Payment</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>) of coins (<tt>coinᵢ</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[
wallet merchant
-knows valid coinᵢ knows merchant.priv
+knows ⟨coinᵢ⟩ knows merchant.priv
knows exchange, payto
| |
| +-----------------------+
@@ -501,14 +502,14 @@ knows valid coinᵢ knows merchant.priv
| | (M2) contract generation |
| +--------------------------+
| |
- |<---- (contract, merchant.pub, contract_sig) ----|
+ |<---- (contract, merchant.pub, sig) ----|
| |
+--------------------------+ |
| (W2) payment preparation | |
+--------------------------+ |
| |
|------- /orders/{order.id}/pay -------->|
- | (~deposit) |
+ | (⟨depositᵢ⟩) |
| |
| +--------------------+
| | (M3) deposit check |
@@ -526,6 +527,7 @@ knows valid coinᵢ knows merchant.priv
(M1) order generation (merchant)
wire_salt = random(128)
+determine id, price, info, token?
persist order = (id, price, info, token?, wire_salt)
]]></artwork>
<artwork><![CDATA[
@@ -541,27 +543,26 @@ or proving the payment without resorting to the individual coins.</t>
<artwork><![CDATA[
(M2) contract generation (merchant)
+check order.token? == token?
h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
determine timestamp, refund_deadline, wire_deadline
contract = (order.{id,price,info,token?}, exchange, h_wire, timestamp, refund_deadline, wire_deadline)
-check contract.order.token == token
contract.nonce = nonce.pub
persist contract
h_contract = SHA-512(canonicalJSON(contract))
msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
-contract_sig = EdDSA-Sign(merchant.priv, msg)
+sig = EdDSA-Sign(merchant.priv, msg)
]]></artwork>
<artwork><![CDATA[
(W2) payment preparation (wallet)
h_contract = SHA-512(canonicalJSON(contract))
msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
-check EdDSA-Verify(merchant.pub, msg, contract_sig)
-check contract.nonce = nonce
-TODO: double-check extra hash check?
-~selection = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
+check EdDSA-Verify(merchant.pub, msg, sig)
+check contract.nonce == nonce
+// TODO: double-check extra hash check?
+⟨selectionᵢ⟩ = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
(coinᵢ, denomᵢ, contributionᵢ) = selectionᵢ
-h_contract = SHA-512(canonicalJSON(contract))
msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
( h_contract | uint256(0x0)
| uint512(0x0) | contract.h_wire | coinᵢ.h_denom
@@ -570,17 +571,16 @@ msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
| denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
sigᵢ = EdDSA-Sign(coinᵢ.priv, msgᵢ)
depositᵢ = (coinᵢ.{pub,sig,h_denom}, contributionᵢ, sigᵢ)
-persist (contract, ~sig, ~deposit)
+persist (contract, ⟨sigᵢ⟩, ⟨depositᵢ⟩)
]]></artwork>
<t>// TODO: explain CoinSelection
-// TODO: maybe better {sigᵢ} instead of ~sig?
// TODO: maybe introduce symbol for pub/priv
// TODO: maybe rename Sign-Msg as name is currently a bit confusing</t>
<artwork><![CDATA[
(M3) deposit check (merchant)
-check sum(depositᵢ.contribution) == contract.price
-check Deposit(~deposit)
+check sum( ⟨depositᵢ.contribution⟩ ) == contract.price
+check Deposit(⟨depositᵢ⟩)
msg = Sign-Msg(MERCHANT_PAYMENT_OK, h_contract)
sig = EdDSA-Sign(merchant.priv, msg)
]]></artwork>
@@ -594,20 +594,21 @@ check EdDSA-Verify(merchant.pub, msg, sig)
<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[
- merchant/wallet exchange
+ merchant exchange
knows exchange.pub knows exchange.priv
-knows contract_sig knows denomᵢ.pub
+knows merchant.priv knows ⟨denomᵢ⟩
knows payto, wire_salt |
-knows contract, ~deposit |
+knows contract, ⟨depositᵢ⟩ |
| |
+--------------------------+ |
| (M1) deposit preparation | |
+--------------------------+ |
| |
|----------- /batch-deposit ------------>|
- | (info, h_contract, ~deposit |
- | merchant.pub, contract_sig) |
+ | (info, h_contract, ⟨depositᵢ⟩ |
+ | merchant.pub, sig) |
| |
| +-------------------------+
| | (E1) deposit validation |
@@ -622,18 +623,20 @@ knows contract, ~deposit |
]]></artwork>
<t>where (without age restriction, policy and wallet data hash)</t>
<artwork><![CDATA[
-(M1) Deposit preparation (merchant/wallet)
+(M1) Deposit preparation (merchant)
-h_contract = SHA-512(canonicalJSON(contract))
info.time = contract.{timestamp, wire_deadline, refund_deadline}
info.wire = (payto, wire_salt)
+h_contract = SHA-512(canonicalJSON(contract))
+msg = Sign-Msg(MERCHANT_CONTRACT, h_contract)
+sig = EdDSA-Sign(merchant.priv, msg)
]]></artwork>
<artwork><![CDATA[
(E1) Deposit validation (exchange)
coinᵢ = depositᵢ.coin
denomᵢ = Denom-Lookup(coinᵢ.h_denom)
-check denomᵢ.pub known and not deposit-expired
+check denomᵢ.pub known and not deposit-expired // todo: check could be included in Denom-Lookup
h_wire = HKDF(info.wire.wire_salt, info.wire.payto, "merchant-wire-signature", 64)
msgᵢ = Sign-Msg(WALLET_COIN_DEPOSIT,
( h_contract | uint256(0x0)
@@ -651,20 +654,20 @@ msg = Sign-Msg(EXCHANGE_CONFIRM_DEPOSIT,
( h_contract | h_wire | uint512(0x0)
| timestamp | info.time.wire_deadline
| info.time.refund_deadline
- | sum(depositᵢ.contribution) - sum(denomᵢ.fee_deposit)
- | SHA-512(depositᵢ.sig) | merchant.pub ))
+ | sum( ⟨depositᵢ.contribution⟩ )
+ | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
sig = EdDSA-Sign(exchange.priv, msg)
]]></artwork>
<artwork><![CDATA[
-(M2) Deposit verification (merchant/wallet)
+(M2) Deposit verification (merchant)
h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
msg = Sign-Msg(EXCHANGE_CONFIRM_DEPOSIT,
( h_contract | h_wire | uint512(0x0)
| timestamp | contract.wire_deadline
| contract.refund_deadline
- | sum(depositᵢ.contribution) - sum(denomᵢ.fee_deposit)
- | SHA-512(depositᵢ.sig) | merchant.pub ))
+ | sum( ⟨depositᵢ.contribution⟩ )
+ | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
check EdDSA-Verify(exchange.pub, msg, sig)
]]></artwork>
</section>
@@ -776,7 +779,7 @@ check EdDSA-Verify(exchange.pub, msg, sig)
<refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
</reference>
</references>
- <?line 732?>
+ <?line 737?>
<section anchor="change-log">
<name>Change log</name>
@@ -789,147 +792,149 @@ Education and Research (BMBF) within the project Concrete Contracts.</t>
</section>
</back>
<!-- ##markdown-source:
-H4sIAAAAAAAAA+U823bbSHLv+Ioe+QUcExRJyRqba3ki62IptiRHkte78Tpi
-E2iSiECAi4sljix9TP4hb3nLl+RPUlXdDTRAUJeR5Nmc8PhYQKO6u7ruVd2A
-4zjWtx5bsazUTwPRY0snY8HeHXxiJzwQMfsYR2nkRsGS5UVuyCcA4cV8mDqj
-TKSJO47OnRQBnakCtFyeilEUz3rMD4eRZfnTuMfSOEvSbrv9qt21zqP4bBRH
-2RQhPDEV8F+YWkkaCz4pt52JGUB7PYsxh9E8dOXGs2kajWI+Hc+oQbg8GdPV
-lM8m0DOxrGffRJiJnvWMsVhMox4bp+k06S0vj/y0NQqzUKStKB4tB4nXBsRa
-0LyMwAHgn6QFODyvAV+2LJ6l4ygG3ByYmTFJnH3/LAq4z979939J8tAz6Nhj
-J5+22FYsElgZ+xT630Sc+OmMRUN2ItxxGAXRaEbQfDCIxTfsoOGpGQkkALFd
-EUzGUZD+Bg0t1mnTQxeG6pXA3cgDfLacdqe99kq1ZGGKjHkn4gkP5WRiwv2g
-xyYS71bO1n9KM8eTw7U8YVlhBH1SwBqZcbSz2W3ri057VV2+eLn2Sl2udVeo
-dff91g5gcbjX6rThX/uX5Ve/vHRWnLXVrtNZBSjnl9OVVQA83j3O4dba3ZfL
-B3vHJ62dvY/Hrc7LtrMKggTilONgWY7jAKWABtxNLetvX9jJ28/sb1/lg4nv
-eQFg/YztwZIjL3NTPwpLYG/FOY8FS8c8hf/8hIGAZyg7DK6T1A8ChpLq+CHK
-9ghIkTAeemzCZ0DJMOV+yEQcR3HSsj4lgsEwsyiLWXQesthPzn7C2Q+ilMuZ
-HdZf4gN3qc+AohGIGEwqWOCnIuYB8tYPR6wPEH0mQuSdx3jCNo439/bYF6L3
-VxyDs+9sUB4DkEGdC2kiFCfOzv10zAYIH4jQ5o3KpCIcwXPAfzDDNuiCzXij
-EeHYd8q9fxVxZM+arDpECbbJfgMwB8AR6zQyJ4GxZ3IaHHHgp4l90egv96kJ
-L0vDTvzQnwA5wmwyAOMDnbHHskQzFC7wgMcznAJUGjiC3KJ+WZD600AwaHT9
-BOngh2CGYIwLnDeDO1xGdb7+rA+I8iRliT8K/aHvchgR59RE0cP0Lwq+AOHA
-GqBwSDqAhQIIe+CPAMTzedjQc3bW5GrxeqVbXK+tFtfdFwbQiw5BoQiKv2f+
-NzB5uMRILaGzRmuQsPZK17xbWzXvYFTzFsal2yYQLpkKF5UomCGaMch0NLFn
-BmU4k43BjI1ECPKZwqITwAcIIBRHgURSHH9mA2ZPIo8dwAjL1FJqKrFXsgmo
-TKK6zMTFNAphhX4uu4s5iXih/g2aDMbOgogdoIZtFr7Ad8Fd+RMfF4cOoPpw
-F5wE28lCsgUE8AzMzoYDtGKXz5Ixh4sry7q+vrZUsz1JRg3mvGFj9C/WXjjN
-0h6ZTXiAfwA5aGITFMwR0UbJ/Qf2mnX/ba3DIjcV6I4OszTvjKPRIKqb54/A
-5WDvoX8BtFZjIL4fwFmss5WuHgeRs/o4AAkJUjWikbG3XgwYjilI5LGQK2Wr
-rU6TvcD/1vA/pOJaq4s9vihT/bVVkANkRZIDLgxyoGg+kByd7ovHocfa6p3p
-gauZp0cX6dFFeqxoeqzeQA+iqg1BDFlaTzc3cjo59KxMrccQoEejWEWCTgo6
-KeK5UYymIQq9RJvwoR/DmHlPbRLn6euJoR9Kw3h5qQTnqieJkYrJFOY3Jcgi
-7NcZPvrS7q10vkqkwFma/jiaoulBC+D5wyEagGEcTfRIy0rQjbm/QAzxFS+k
-4QY7AK6E5gI7mglgKdqEfUWyDQjf0PQoY7QJpl3ZhN39jU3g7HjCNUexxUFi
-2hCRNgHxi5S4CqQAvkxxAMmXXcUXt2R4CIehMjzSOSsilvlUEhCYiQQkEW4s
-UrotpIOnym/pngiJaBUi5fGUUzQQg7FGrym7luUI0GDqr+JpBSOpX/CY1Mvl
-gZsFpAIV0qtA8Ksi8nvAdkvE4MBoyRWji0EhEvjMG15JWcTpYKQF3ZiNPRos
-S+RsMjXxMR6D2yTlpgf5ogLRrxYRGvy0kh/0pCVOgEBFMQnL9gWFkWQJti+m
-+CdJxRQXmWQjVC21TMTja8/q419H9eojXgnrk5CAdIJwgp89H/vgxTQgDlmF
-AwHuM9sdtkBpSNauGi0lbtDJTniQNtne+/0mJVJN9oFE7vD9vhKTRLIQ4YiF
-JIYYS2IDSTyzOQuj0FEiJL26fNT4E3Uufv4QQFNwu9E3H4IcmFQGwoLCD66D
-PSAwGF+M9yDsxX6AoGHHQEoRCqJ04CIPLPlkGJUQxOgZRRXJzKdFPICBCcZg
-LI/0o7CCpQ0BGhtAsC1DTiWsErcGwX5QkEX8qWS7ghqyU1nEyhSv11n3xYuf
-we6ts5edtXajrDKHasGLxrVhyg9q6MactcXec4o0jIIgOk+Uxfx49B5mNiWs
-kIWGtB670oBq+2ubnrFh4Rz5ACh5NgxpSFF1CHJupqtQaGtVdfYjD/IljtoX
-SetKGlwy+6TMV01punNbB2KXxSEpKmJFxh2lCoJ8VGG4D4GXIwjYwpuC+AND
-MRAb+6DJKvpRrxwHmquLBy8p0R+tRXdQox+gR/eT9xIzDwyRB+mA5zrMgHHI
-h3gCOk5IcPSln6AbDiDfGGgh47JagWZeOnL/N9SVlPBV0qAh1lnb8iIGN35A
-6L5mBxL3C6UHVWMKSbRKz9QYjaZMUu2DRiNf9ToB2ZS0HjQwfyrKKDDt83XW
-0YoCiX7ovA184MQxZJIcpF5HE9seWJPOK4Kqhzg63nB2tnbBI8YJd4be+Ira
-IfrMptMoTpHchgfFKVUXDKeabJoNgCmkANC5rAA6zFSBIrVJeIbz4jXIDUUX
-IE4JckLKJ+VYWQIahOKlwHS+xkRZRmBammWYBYED2oG1EXK1OBBgEH0Deslp
-WwcqpoA+1Zgi577WcxnxSePiAEZXV/Pmkvi5zpYkSTbYzsk0+fzTkkUKvK75
-LLmrUWg0CgkoPRGK/fBYwxaXwsJ1rufY5cNpY0TcIGNUKAFwGU0PFndoxUrx
-KJTBOBvDdj7iGMaA0IMq+a4fAd0Vc2B8azBjQD9/SHqn4mPBRrGgSiXwbTLB
-IBkSbdAlnkJMY49cr4HEl3MiB/saWSJ6p1WSI4eCLmEPzpKSOFF8a4oTABB5
-BijIiA4KjjKMZu5iJhxPI3I6cq0TOcSyTuRqwtgHidxbTQXomwtcqRXQJw8O
-PKGsArBZuk2KiAmGFJEp0IOW2Uat0gjcyro6S/CPx06d0BJGwBmM0JUa3M5D
-bUgVC7U1reEgJUfrrM6MWnHxoE4vrPhUAESMdS5tGGS5K7cuFq4GQADwZ5mH
-VZ4XfEVfMMdWbLSxH0wK82uWJv6ozFIaWv8FYwJ2BeuYGHfwIngq+Wc1HqgE
-8VHeST5S2iVuZ6SCyznplTkJGDD1V3o55AxhCHZMTah4CSA1aWWZUzjcuuyP
-BFfoe4qiejUmST+Fg1plUe02jHgHddHLoD7FYv5B1SYLtcIUmN6UupdpfLvE
-++E3gIH/RZxQlSquF3mk2s9Mwi+U+T9rZ1bmj2yWukg8uq81q5G8oaY5uQPo
-9MR8SONMNDELQFywQIF5gn8nrjyyFQNMNT9us1O2HGcdV2ekfpsBhyjFOca9
-yTjGWvsWwKWzqSqub0wwELYs+RfWGotiW8Ys1GD5NUqoLC/Lk840AuMkU6jE
-KpO9T6197IRRDiZeoRjRrl9u0aY8TvNdKyAbc7M4FqE7a1q0qzNElwvBcl9l
-loBJFqpNHWAfG2ehFwOGEz8IAAx01e4I52VjwZgUPunbHLMVp9NR+3PumOOM
-WKL0cd86D9WKUSDe+jwWoUAx1GUsfK63zZtyYojf4llBxWJLL2R9TnRGsbH0
-JpJsaslcVIW0K13drMmAT/ReHu4DqccatUafit3sxAdlSvlkCuzdGCRRkGE5
-Nm+c4y/QwdjMYudjAQC4T1YuJVtyY8+FXFe41Jb4uI/U77z6pe20O/CPtdu9
-dpttbh+f9JmN8J8O9v7CxDRyx40WhdGU00I2KTPyfvtip/LrF7glbIkIvdSy
-Xv/kONbyMqDhRT3gk3DPKEcXgjZYgbGErJtaRyKQQvZ7VgyanEuaudTfhTuE
-PAp7x3lDnDETxo0g0EYvKfn8Qt8Ae9APqvJwNhYcdyfVjrUSSx+AIKFGAlhc
-bRkkMhLJqwoQl8agtiBXsOxYjEBFBSoNePF3GwcbSoCtL+8OPoXg93Ic2UfZ
-L/lq5ycueMjNMxTy0smNYqJaTouW1jidBOB5aN541pJLc2IhjaXCLVFrhZSo
-0263VVKDqDj7yUivgBKzejeiIAyXoVvKi4YJcNF1rkcSDMyZLS7coKUI3ijx
-pt5ZQOI2DQQomR7JBsVYNELZb2Bdp86TS4OuzADu/ePKDcuQ8/Q7OUMaNFcP
-MP8BplFTPJmSQCZC+tJkZyFMAD45mzTpdM4FiontY6AzJDss/p5hxQwQRc8d
-jgKIDvGkyZ90PSwWtH8DCzofRwEee0jSBnoUVA8ptHKrNj9vRHL/GUTYi/k5
-DH757Dy/UXsG5xjWpvkWNehmyN6wNtofyKaZ3ce///Of/9FvkKLHuIGdpAjW
-L/iNcBQ6oexJYPK7aISAnxAyjwR4gDSN/UFGPkpqsdoik1NxF6wIBYK4Uw/D
-u2MgspGS02aD3ad7mkQahjRKc7OAKBZLZEMB4qALrKByJj60mWmO3bAmWZKS
-sKhYH7ImyRSFpzT5oC1RXPgexSo0PPE3VZLAfKtAo1WSDpByiaPMalkMY3pA
-mCn12nx7LGXQrDMqHt3600uzSNaYJlQLQpVFXaqQELZWipwg5Hf8fbeeOzf9
-nt/Q8zuzP3caORUxkFQiib57MQoPmfP3r7PaYEzI7AEPzyCE5WEyRPtjPHtT
-M6edZIN/B9fZ02tHbunooqcK5I+LbT3czXR0nt9xmO/a8DG7tCAdXf1YbGrw
-u0VgFouNFNJug8yVKZ10nkYnsXWIPGTO37/OakN5NrasDRQrP6gTUviVuXlt
-K7fQGp+S8Wg0b8f3WroI7Em5abvxRCuth7uVB3cXcXu7o8TAT5KMYyDOwyL4
-++EY1eA41/O1yXz7OnfXjQr/H8KIBQtabITznqhaK4qmWXijNj3anNWG23oU
-PSnik4mLjV776HijST4dI0eIQSHCxl1AmTdKf36Te7OlgwdIDbDOtr2t4w3n
-vZgBnN2wqkZVG9Rii0QFCR5VnhIdU5mmSdbWEghR6MCp3H6mOI3rKGbCMVTX
-VTiMkIxoKj9K1LTSaCQg+IlVflSUSSmyxbgMwms6AYxUCGaYvfEzmhZgMWCf
-5Im5JyCnClQ+S2luCQkfz6xiwo/5HAS5tOHDwxmLCAGsYqjqwsQfjSl+U4Gj
-jPzz2XCrVB9hCWYtzZbbDHrBHInXqcJrXe1h4yHRgj8lGAsHhmvhgaXUm6gq
-h/DBYpaAm2xJvgNQUNzB/o6XH+VZatLJBKW61EsObM7zZaXb+2pp84wBXRWg
-t9I1ACA21NL2TqQfs4Ft9m1YFUNvnEJTK2kbmVEHr824U2OrRjFKpHLXRY9l
-oIO7yOUVNitDYu64zvIE9fPGhw/bJ6dH28fbR3/ePv28d7K7dbTxuUkKbmPG
-Zef98yJPqRXyhFNNdrl1+T1fZX5xbZewMFbdvqB1l1eqx9Gnk9sX7VKXubtG
-Q5XpJTNo+yJ3usAKmYBLhSfRvdkJ2TobAMnViMPgW3jpfIiis2w658QtWdsp
-JQ6YIUiVwBzUEE5IdH3Ig1QfibSqPpdiBV2K1qNrG/f+r5tYeEizhEVnmGvh
-+LKmZMmcbp24dF3lXoM9rz4oMbAyUWvAA6LOm3WZK1rVB45+YOawhqgSK0rc
-bZZTpkL/C/oYjPq8Ou/ZCrOimSCZX91nMVG6VTHkuitbAfUqZsxaHSX3Nfli
-K9Pm5W32Ub4oxC6fqVeGylWFaIDlsoT1sbojT/kZp2ko4cWaLB397xclg4mI
-UXRTiw/REbgB9ydIMz+vx/XDCBjXb1kaAX2qll4iAJcxjQV4Bpn15xqBvsLn
-QQPWS6V0Jl8+8n8zagv0QJYwYMy5IkhTuX3K/LMJVZUDeYhI1jYiBV/coyy9
-XmdlIYbhqdoAlHDH8i0KTSOUKFgbm+K+yTRK6WR/kOMMoq4qoorktAOii2B4
-1jJCF5aUKAm4uvjeB+7zY2XcE2IiIRaQQh2PyIsl6oSlgi4OWZpx0V3LFDl7
-ZfFB7u1os1n/k5C6Y22ZYuFP9s3LUEi2NPrDso17JBn7YN+lQJulkB80fw1G
-C1MKZv/LkYNHv9kyO9jZhP8/He0ZecVNONu0wtal7zXT6EyEv149Vla4kAK3
-9lTFKLIxdytDPXzOasMtHW7oqZmyTJRNli8lhX3vapksqeLLgjwffjYtXDpv
-2VdyJmfMH5qr30eBKLaXVvUxdegp1Ai9rcS0adg5ZIFuL5L1p9CK24Q0r35p
-ryM97B0U4yFzVhvuuMz7aQWsKLdVi7VC/exr5QMbrAr4x2jFffRhpQh9ZKj4
-Q2auweXG6pRUh5rS1NOJ/o1ymFentOjTOVJ9TvwmBB4y5+9fp1mdMopSzChK
-QRQUBb47kxtmqnKE51fw8KeuWNXGH7Y2TgB1DvnfqTqwqYohne7LIoGQndeZ
-Dc6dUVSr35+QDgVrZmoEM6+t9b1FviQfLayQKeeFEeLc+3CidD4Pz8nIPIJC
-aDrIgbUqzENpG4+HM0nGyjGTlrUbnWNNit5McKMs8PLTyAp0mNE+eBrRWwwC
-32cH/Mb+VJ1DkaShXSJ5vKRpiZBjnjXCcRyX0758BskBhPJLWaiToCXMlPXu
-Uqwqamo0rIupqhhMhmPiuU98i0Kdo9ECrKUCJEKdjFc7nJicfvO9jN6LgNRH
-V8kWeVJTGsanyE1d5so5qwLuJlvSsA4+K84tqKpW/kZDcXYE37MeZpB5eoJ7
-QBqhBEbfWjlK62YcKSWNBE2FlE0j/JdoNu8+i06r8/zMiInwvBdd5Ki0tHjm
-QVQumRoEKGUgnqfnwLsQX+D45+PDgzwYaMxVu/a3jzZ3Nw5OTjcPD06ONjZP
-cEk5uGVGC+VaUil7mismLXLthd49KdbzNaRyEERFpFIkVOVKie7WyeHWYY95
-UTYIQJkIUm630+l2avjVuk5EIN9mhn6bIO/H+j5fSesylxwSK8hO5NB4yCSD
-jGefx2dbfpzOGFoKy54rEDVZpRjQwLqWngju709YWZ2q1j83D/cOTre2Px4e
-753o2qcxdLkSaRQncTZVjsxXrXT5O6tUCFW3HC5XIrOxok5mH6Mk8pyVqncq
-LlHAdY/wtI0hE1XsZflUksaQerOYTWJE9auizoOmQ8NcoqhhQUyt9mqOd1TI
-pBGMIpkO26+plpbHh/m5ICkw+lxQSc6KxxM+AxcyEClWvC7lLFf0Xi6QEZ0G
-jv5rFd5X32URLJlNBlGgT/ovk/+rAIN74xORyw06FmooOT+OX6XAZQ9pm0jb
-/7nI0bT8skVW1DVdWyblGmgny/Ut1WlLdiii6oWG4+PGX/e34e/h+7LpuK+d
-WxTHGfs898TgbsaLbJaum6pls8tnuqJmnBHinpczNo3wSy1gukrlNj388l1K
-bpVTQfp28amgKhyKkmwrOZcb+pr1ZNVVBQFFyHiHQLY8aaFat/esNtw+m+75
-oPwYI2aN4//N/Jhyr+UBVqUdvRITn0WnQ2RYX2hFDbMWYHtTseMJ1lkPt5gD
-9zwUohdNRe3HqjY9dqLNbCP4Ne2BtFJPWWO6PdHGVCOn4v+fRHurxmzYFTt/
-7yActZJiNGa430uD+aVEZy4RupIDqLTOrprw6l701rzsm5vQxRGAUpTgh4+4
-Pa1GzvemyzlpvpqWkZ0WjXfLU58y/r4l7M7ZWYq7i9b6wHtBTPYUAXhNJGTs
-Ouvwu2miZKRyD923lqOgGOB7agl+/hIjWB2pa9mIBZ4zx9M38ZmDUKmVQFcv
-C/CdJePsLlVvaLOwIDfml+f2XJS6/RcMEd9tY3q7s3e0f6Mc5Fw2yafoXs/Y
-ctWjKgz1bL8xHHfmz7/kAbjsrqlfYVVVBuoOrZQix7kAHO37Vp19r7V2Dyop
-/Qgm5Wa1jke3pMQ/jEU1ell2+/MZypEYghsb4+c05FWRoejnsCL5GC7mnrpR
-NqWneFF5+pn466SRI6/YxwxmKs6SnHfPnWk2N2VNtyCY6xYEpW74vbosxk/E
-buIbkp6qXCbqK6Zb9BXTZ2wPX8aqQhxEIX7vDCOmAXfP6EOJ8jhEEI3wbsNF
-9xMIbyQ/l3vZk9/cFN760pAHiVi6Ks1DxyLpk5fn9FEs+jCJLBrT25jqFRX5
-ZVm2Izz6rOk+fdslxoK1tQ05YXFI8UgkggOrmf12/+2O/CZRUavG1wpwTXhq
-R+AFyWLSsv4XcFI2TK9YAAA=
+H4sIAAAAAAAAA+U823bbSHLv+Ioe+QUcExQp2RqbMWci62JpbVGOJK9343XE
+JtAkEYEAg4sljqz5lT1nn5IPyFve8iXZL0lVdTfQAEFRHlmeyQmPjwU0qrur
+617VDTiOY33qsk3LSv00EF22djYR7FX/HTvjgYjZ2zhKIzcK1iwvckM+BQgv
+5qPUGWciTdxJdOmkCOjMFKDl8lSMo3jeZX44iizLn8VdlsZZkm6028/bG9Zl
+FF+M4yibIYQnZgL+C1MrSWPBp+W2CzEHaK9rMeYwmoeu3Hg+S6NxzGeTOTUI
+lycTuprx+RR6Jpb16JMIM9G1HjEWi1nUZZM0nSXd9fWxn7bGYRaKtBXF4/Ug
+8dqAWAua1xE4APyTtACH5zXg65bFs3QSxYCbAzMzJolz5F9EAffZq//+L0ke
+egYdu+zs3S7bjUUCK2PvQv+TiBM/nbNoxM6EOwmjIBrPCZoPh7H4hB00PDUj
+gQQgdiCC6SQK0p+hocU6bXrowlDdErgbeYDPrtPutLeeq5YsTJExr0Q85aGc
+TEy5H3TZVOLdytn6j2nmeHK4licsK4ygTwpYIzNO9nc22vqi036iLp8+23qu
+Lrc2Nqn14PXuPmBxfNjqtOFf+4f15z88czadrScbTucJQDk/nG8+AcDTg9Mc
+bqu98Wy9f3h61to/fHva6jxrO09AkECcchwsy3EcoBTQgLupZf3lAzt7+Z79
+5aN8MPU9LwCsH7FDWHLkZW7qR2EJ7KW45LFg6YSn8J+fMBDwDGWHwXWS+kHA
+UFIdP0TZHgMpEsZDj035HCgZptwPmYjjKE5a1rtEMBhmHmUxiy5DFvvJxXc4
+ez9KuZzZYYM1PnTXBgwoGoGIwaSCBX4qYh4gb/1wzAYAMWAiRN55jCds+3Tn
+8JB9IHp/xDE4+8yG5TEAGdS5kCZCceLs0k8nbIjwgQht3qhMKsIxPAf8h3Ns
+gy7YjDcaEY59Z9z7ZxFH9rzJqkOUYJvsZwBzAByxTiNzEhh7LqfBEYd+mthX
+jcH6gJrwsjTs1A/9KZAjzKZDMD7QGXusSzRD4QIPeDzHKUClgSPILeqXBak/
+CwSDRtdPkA5+CGYIxrjCeTO4w2VU5xvMB4AoT1KW+OPQH/kuhxFxTk0UPczg
+quALEA6sAQqHpANYKICwh/4YQDyfhw09Z2dLrhavNzeK660nxfXGUwPoaYeg
+UATFv2X+JzB5uMRILaGzRWuQsPbmhnm39cS8g1HNWxiXbptAuGQmXFSiYI5o
+xiDT0dSeG5ThTDYGczYWIchnCotOAB8ggFAcBRJJcfyeDZk9jTzWhxHWqaXU
+VGKvZBNQmUR1nYmrWRTCCv1cdpdzEvFC/Rs2GYydBRHro4btFL7Ad8Fd+VMf
+F4cOoPrwAJwE289CsgUE8AjMzrYDtGLXj5IJh4sby/rll18s1WxPk3GDOT+y
+CfoX6zCcZWmXzCY8wD+AHDSxKQrmmGij5P4Ne8E2/mWrwyI3FeiOjrM074yj
+0SCqm+ePweVg75F/BbRWYyC+b8BZ9Njmhh4HkbMGOAAJCVI1opGxt14MGI4Z
+SOSpkCtlT1qdJnuK/23hf0jFrdYG9vigTPXHVkEOkBVJDrgwyIGieU9ydDae
+fh16bD25Mz1wNYv02EB6bCA9NjU9ntxCD6KqDUEMWVpPNzdyOjn0rEytryFA
+X41iFQk6K+ikiOdGMZqGKPQSbcJHfgxj5j21SVykrydGfigN4/W1EpybriRG
+KqYzmN+UIIuw7zF89KHd3ex8lEiBszT9cTRD04MWwPNHIzQAozia6pHWlaAb
+c3+AGOIjXkjDDXYAXAnNBXY0E8BStAlHimTbEL6h6VHGaAdMu7IJB0fbO8DZ
+yZRrjmKLg8S0ISJtAuJXKXEVSAF8meEAki8Hii9uyfAQDiNleKRzVkQs86kk
+IDATCUgi3FikdFtIB0+V39I9ERLRKkTK4ymnaCAGY41eU3YtyxGgwdRfxdMK
+RlK/4DGpl8sDNwtIBSqkV4HgR0Xk14DtrojBgdGSK0YXg0Ik8IU3upGyiNPB
+SEu6MRt7NFiWyNlkauJjPAa3ScpND/JBBaIfLSI0+GklP+hJS5wAgYpiEpa9
+KwojyRLsXc3wT5KKGS4yycaoWmqZiMfHrjXAv47qNUC8EjYgIQHpBOEEP3s5
+8cGLaUAcsgoHAjxgtjtqgdKQrN00WkrcoJOd8CBtssPXR01KpJrsDYnc8esj
+JSaJZCHCEQtJDDGWxAaSeGZzFkaho0RIenX5qPEP1Ln4+SMATcHtRp98CHJg
+UhkICwo/uA72gMBgfDHeg7AX+wGChh0DKUUoiNKBizyw5JNRVEIQo2cUVSQz
+nxXxAAYmGIOxPNKPwgqWNgRobAjBtgw5lbBK3BoE+0ZBFvGnku0KashOZREr
+U7zosY2nT78Hu9djzzpb7UZZZY7VgpeNa8OUb9TQjQVri70XFGkUBUF0mSiL
++fbkNcxsSlghCw1pPQ6kAdX21zY9Y8PCOfIBUPJsGNKQouoQ5NxMV6HQ1qrq
+HEUe5EsctS+S1pU0uGT2SZlvmtJ057YOxC6LQ1JUxIqMO0oVBPmownAfAi/H
+ELCFtwXxfUMxEBu732QV/ahXjr7m6vLBS0r0W2vRHdToG+jRl8l7iZl9Q+RB
+OuC5DjNgHPIhnoCOUxIcfekn6IYDyDeGWsi4rFagmZeO3P8ZdSUlfJU0aIge
+a1texODGDwjdF6wvcb9SelA1ppBEq/RMjdFoyiTV7jca+ap7BGRT0tpvYP5U
+lFFg2sc91tGKAol+6LwMfODEKWSSHKReRxN7HliTznOCqoc4Od129ncPwCPG
+CXdG3uSG2iH6zGazKE6R3IYHxSlVFwynmmyWDYEppADQuawAOsxUgSK1SXiG
+8+I1yA1FFyBOCXJCyiflWFkCGoTipcB0vsZEWUZgWppllAWBA9qBtRFytTgQ
+YBB9AnrJaVt9FVNAn2pMkXNf67mM+KRxcQCjm5tFc0n87LE1SZJttn82S95/
+t2aRAvc0nyV3NQqNRiEBpSdCsR8ea9jiUli4zl6OXT6cNkbEDTJGhRIAl9H0
+YHGHVqwUj0IZjLMxbOdjjmEMCD2oku/6EdBdMQfGt4ZzBvTzR6R3Kj4WbBwL
+qlQC36ZTDJIh0QZd4inENPbY9RpIfDkncnCgkSWid1olOXIo6BL28CIpiRPF
+t6Y4AQCRZ4iCjOig4CjDaOYuZsLxMCKnI9c6kUMs60SuJoy9l8i91FSAvrnA
+lVoBffLgwBPKKgCbtVVSREwwpIhMgR60zDZqlUZgJevqLMHvj506oSWMgDMY
+oSs1WM1DbUgVC7U1reEgJUc9VmdGrbh4UKcXVnwuACLGOpc2DLLclVsXC1cD
+IAD4vczDKs8LvqIvWGArNtrYDyaF+TVLE39cZikNrf+CMQG7gnVMjDt4ETyV
+/LMaD1SC+CjvJB8p7RKrGangck56ZU4CBkz9lV4OOUMYgh1TEypeAkhNWlnm
+FA7Xk/2R4Ap9T1FUr8Yk6btwWKssqt2GEe+gLnoZ1KdYzO9UbbJQK0yB6W2p
+e5nGqyXeDz8BDPwv4oSqVHG9yCPVvmcSfqnM/1E7szJ/ZLPUReLRl1qzGskb
+aZqTO4BOD8yHNM5EE7MAxAULFJgn+Hfiyle2YoCp5scqO2XLcXq4OiP12wk4
+RCnOKe5NxjHW2ncBLp3PVHF9e4qBsGXJv7DWWBTbMmahBsuvUUJleVmedGYR
+GCeZQiVWmewDah1gJ4xyMPEKxZh2/XKLNuNxmu9aAdmYm8WxCN1506JdnRG6
+XAiWByqzBEyyUG3qAPvYJAu9GDCc+kEAYKCrdkc4zxpLxqTwSd/mmG06nY7a
+n3MnHGfEEqWP+9Z5qFaMAvHW+4kIBYqhLmPhc71t3pQTQ/wWzwsqFlt6IRtw
+ojOKjaU3kWRTS+aiKqTd3NDNmgz4RO/l4T6QeqxRawyo2M3OfFCmlE9nwN7t
+YRIFGZZj88YF/gIdjM0sdjkRAID7ZOVSsiU39lzIdYVLbYmP+0iDzvMf2k67
+A/9Yu91tt9nO3unZgNkI/65/+CcmZpE7abQojKacFrJJmZEP2lf7ld+gwC1h
+a0TotZb14jvHsdbXAQ0v6gKfhHtBOboQtMEKjCVk3dQ6EYEUsl+zYtDkXNLM
+pf4q3CHkUdg7zo/EGTNh3A4CbfSSks8v9A2wB/2gKg9nE8Fxd1LtWCux9AEI
+EmokgMXVlkEiI5G8qgBxaQxqC3IFy47FGFRUoNKAF3+13d9WAmx9eNV/F4Lf
+y3Fkb2W/5KOdn7jgITfPUMhLJzeKiWo5L1pak3QagOeheeN5Sy7NiYU0lgq3
+RK0VUqJOu91WSQ2i4hwlY70CSszq3YiCMFyGbikvGibARde5HkkwMGe2uHKD
+liJ4o8SbemcBidssEKBkeiQbFGPZCGW/gXWdOk8uDboyA7j3jys3LEPO08/k
+DKWtZyikUnTkhml+6scqdAd8Q4A51gyPrSSQppAyNdlFCLODw86mTTq6cwUy
+tB4ABBbC1NkHEOH3II1ezC9BDa4fXeY3qvx/iRFqmu82g5qF7EfWRlMCiTEb
+/P2v/45X//Off/v7X/9D5rMx7kcnKYIOCvZJWIqFUJh0B3KlaFeARRAFjwUY
+9TSN/WFGbkcqptr1klNyFwwDxXa4+Q5TuBOgm5Fl0/4BTkYtaiKp7yksXGs7
+olosl40EcFnXTUGTTJxoj9Icv2FNM6AjyoAK4SEZgmXDOApXaclBCaK4cClg
+XscBFR5E/ElVGjCNKtBoEV81f7oMVgHYwxpK/AahlrjLJJbFMJcHRJvRaDsv
+T6XImWVFxceVP71ki6SHlam4vNsCdAsTAOhSqW6CdN/x99l67Nz2e3xLz8/M
+ft9p5HTGCFIJMDrt5SjcZ85fv85qgzEhs4c8vIDYlYfJCA2P8ezHmjntJBv+
+K/jMrl57CyJKHVZ0VWX862JbD3c7HZ3HdxzmszZqzC4tSIdV3xabGvxWCMxy
+sZFCutEgo2ZKJx2k0dlrHSL3mfPXr7PaUJ6NrWsTxsoP6oQUfmVuFj6kNTkn
+AwKGo3kHnHOHUrggSlAbD7PmeriV3Li7sNt7HSUQfpJkHGNxHhbx3zfHqAbH
+hZ4vDCmwFz18oywQ92HHkmUtN8p5T1S1TUXZLLxVu77anNWGVT2KnhT6yQzG
+Rn9+crrdJG+PISQEoxBq43agTCClp7/N3dnS9QOkBuixPW/3dNt5LeYAZzes
+qpHVBrbYK1Hhg0clqERHYqapkkW2BIIaOnkq96EpuuM67plyjNl1OQ5jKiP+
+ys8UNa00GgsIl2KVKBX1UopiMZKDOJuOAiMVgjmmcfyCpgVYjNyneYbuCUiu
+ApXYUr5bQsLHw6uY+WNiB3E27fzwcM4iQgDLGarMMPXHE4r4VLgpU4B8Ntwz
+1WdZgnlLs2WVgS+YI/E6V3j11GY2nhYt+FOCsXBguBYeaJreTVXJhN9oloGb
+bE2+DFBQ3MH+jpef6Vlr0hEFpb/USw5szvNhc6P70dLWGmO8KkB3c8MAyIa5
+tL0S6dtsaJt9G1bF7hvH0dRK2kaK1MHrIsDMhhpbNYpRK5XbL3osAx3cTi6v
+sFkZEpPIHssz1ffbb97snZ2f7J3unfxx7/z94dnB7sn2+yYpuI3ZlV2Ke0lz
+MFZGZBeeQpZxrllAQJY0DhrT4qIUS2dDPaImyxURo8YB5kPqE8ztq3ap48Jd
+o6FK+ZJPtMWR+2fgkkzSpS0gqb7dS9k6hQCh1iuAwXfx0nkTRRfZzK6wHeSA
+6j/mgimlkNqC5zYMuYV814ekSvWRSKsKdSms0OVqPbo2f6//vIPFiTRLWHSB
+iRuOL+tOlkwQe7ey9fFd2FqasjXkAdHpx55MQa3qA0c/MN2nIc/ElBKrTbEl
+VdJGwrCpecp4iVvT4oqjtfyJJeBJAk/aMsASk1A8T/qTweI6d1nYKs0+KTbV
+XRxzCSu1TdKpstFQr7fGrNVRcgeWE6cybcOkxbz0lDYFytaXB7Hg3lwnH8L7
+KT9N8la+xcSuH6n3mcp1kmiItbyEDbD0JI8gGkd9KD3HgjG9l2AUP6YiRp1J
+LT5C5+QG3J8iyf28WDgII5CTQcvSCOgjv/SGA7ixWSzAW8naRa6K6L98HjSA
+XFTnZ/LNKP/nUpWEHumCDM1XX9yBKV0R0+s1txdbmip8oZpHNqUyeSBPRcnK
+DnayB+Y9ivuLHivr26DBqM4C1HMn8rUQTVcUeqAHm+FG0CxK6VWFIF8nKKQq
+8So20ZaOrurh4dEIXXFSoj7g6uKLLHhwAUv9nhBTCbGEfOq8R14mUkdGFXRx
+atSM7+5aiMlFIi+tGDZ++U9C685kGqqh6Iq+eSEOSZdGv1n+9AVp0xE4JKkI
+ZpnnG81fg9HSJInZ/3Ti4Hl2ts76+zvw/7uTQyNFug1nm1bYuva9ZhpdiPCn
+m4YJ+AA1jFVZTl5oI9t0txLb/eesNqzocEtPzZR1omyyfi0p7Hs362SBFV+W
+1DDgZ9PCZbQh+0rO5Iz5TasPX6JAlKdIy/o1degh1AidvMS0adg5ZAFVflap
+0ao5b1vK7T1VQU87HOmQ76AP95mz2nDHZX6ZMsCKchO1XBnkz65GFI0q+G+j
+El+iDJtFvCTD028ycw0utxXbJLfsXOZLvwdSgFulMS+zaQWgk7H65PttCNxn
+zl+/TrPMZlTXmFFdgxAoCnx3LvcKVQkMT+TgcVZdeqsNPmxtmQDqErLVc3UE
+VVV1OhvPGlZ+3J6BS2cUz+pXQaQbydMaOXyP2UsAsTyo5jDz9FrXXGRx8tHS
+YqDybRhALrwDKEpnEvFskExPKMqmwytYlsO8mvY4eTiXhK4crWlZB9Ellt/o
+bQxXZ6XmKZxRRnv/aURvbgh8hx/wm/gzdfZGkoY2yOSRmqYlQo753RjHcVxO
+ZxEyyB8g2l/LQp1brWHmrzfWYlU8VKNhCVAVAGEyHBPPuuKbI+rskBZxLTcg
+M+ptALX9iynzJ9/L6F0QyKV0QXCZozXlRdocM57AE2BKJCbnyGpd7svZroL1
+JlvTAzn4rDjIoap7hczlh2nwxfNRBumwBzkv0E0oadK3Vo5vz4xBpRiSFKpw
+tGmkDhLN5t1naeTTtLRc5sFVLpIaBKhgIJVXC4BpIb6t8ofT434eJDQWKnpH
+eyc7B9v9s/Od4/7ZyfbOGaKbgy/WwkrJ1EIxbJnLL/TsIZGtqYGVY6JqEaxK
+ZUVmPF1wdrx73GVelA0D0BuClscL6PA+NfxkgXtPRCBf11bJaI/tgIif6tZ8
+Ma3rXB5IWCBfkVPgWZoMcqAjHl/s+nE6Z2gcLHuhstVklRJBA0tzxvRILVko
+q9Zrd44P++e7e2+PTw/PdK3WYES5PGpUTJE3qkaar0Pp3GdWKVuqbjlcLuxm
+Y0XszT5G6eMxK9USVfihgOse4TEhg9FV7GVNV5LGEGWz+E6ygTS1ingNVVzD
+XKP8YK1NrfZmgRskWDSCUX/ToTkKit4EbLKFqFBqUC51+gxTSZKKx1M+H9Ih
+U/pgjGDJfDqMAv0Kwjo5qQow+CA+FblcoPWnhpKH4vi5DFzWiLattJFeCAAX
+zXNRAtarapnUkZXiXo+V61Wq867stBgrL9X+t9t/PtqDv8ev72esloVnxj7U
+F2LwBRZI11DV8tn1I10pM043cc/LGZ1G+EkZMEKWpfvIIIEHSZRHCp6Px0Tx
+FUVkqArTqIxJB4svQ+kb5cuY+YdscsYslujyeuCqX+WwlL4lhaz9VeFQbmsq
+drf0LVdaVWfl+4tA8w7hr+xZ0teSLK7qX21YPafuea8MG6NtrZv/NzNsytvW
+h1jSdvRKTHyWHZmRAX+hektZdivONRWTh1ltPdxyPnzhKRlNOXqJ42sVq752
+qs5sI/41rcPD16pWp+qYiuRU/P+Tqu/WGA/TvaOaUSTHDOd9bfCxlLYspDU3
+cgCVpNlVy9z4PaUuewY5DD0yN/CLkxWlQMcPv+LWvhpZ7+uzyksheVlApQ1U
+GjCnrOTEOf1bRnZcNN4tT37IvGJFOpELYCmfKFrrE4olcehDJBY1EZ+xUa/T
+iqaJkpGA3nerX46CcoMvDib4PVKM3HUGooUJQsIo9vAUVHzhIFRqJdDVywJ8
+icw4U02lJdroLMiNSfGlvaB9e39C5Xu1h9q3f3hydKsc5Fw2yafoXs/YctWl
+Kgz1bL9LGlI9YlQGBxLrs0UlvtedCioFrgvmBB3Kbp1DMc3rPetX34IjudWv
+Y8iKvP5B+VGjeOWgYjHVOhEjcJIT/ICJvCpSLf0cViEfw8XCUzC+M3qKF5Wn
+78nLOmnkyCv2NoOZigMylxuXzixbmLKmWxAsdAuCUjf8QmAW40d5d/CdVE/V
+TRP13dhd+m7sI3aIr79VIfpRiF+Yw3hsyN0L+jSlPK8RRGO823bRIQXCG8sP
+FF935VdOhddbG0GqKdZuSvPQ+VP6yOglfYaMPgUj/RK9/6reHpLf8mX7wqMP
+yR7R13RiLJdbe5DcFqdBT0QiOLCa2S+PXu7Lr0AVlXJ8nwPXhCeTBF6Q/CUt
+638BRvuUOiFaAAA=
-->