Compare commits

...

33 Commits

Author SHA1 Message Date
bitcartel f47b9010b8
Merge 5d78218fda into 8124633a39 2024-04-26 22:49:48 +01:00
Daira-Emma Hopwood 8124633a39
Merge pull request #807 from daira/zip-253-stub
Add ZIP 253 stub
2024-04-23 19:23:08 +01:00
str4d affc145506
Merge pull request #817 from daira/zip-320-to-proposed
ZIP 320 to Proposed
2024-04-23 19:08:47 +01:00
Daira-Emma Hopwood 5d253b61d5 ZIP 320 to Proposed.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-04-18 23:09:43 +01:00
Daira-Emma Hopwood 5273fc9c99
Merge pull request #796 from zcash/dependabot/github_actions/actions/checkout-4.1.2
Bump actions/checkout from 4.1.1 to 4.1.2
2024-04-14 17:18:22 +01:00
dependabot[bot] bf6c166940
Bump actions/checkout from 4.1.1 to 4.1.2
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.2)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-14 16:17:28 +00:00
Daira-Emma Hopwood 7d790904cd Add stub for ZIP 253.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-04-14 15:50:15 +01:00
Daira-Emma Hopwood 2e9272e850
Merge pull request #711 from AArnott/workflow
Fix and rename GitHub Action workflow
2024-04-14 15:47:30 +01:00
Daira-Emma Hopwood 3b706de38b
Merge pull request #798 from daira/zip-320-choose-tex
ZIP 320: choose TEX Address alternative
2024-03-18 17:50:28 +00:00
Daira-Emma Hopwood 8cea84fcf3 ZIP 320: update Discussions-To and Pull-Request metadata.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-03-18 17:49:39 +00:00
Daira-Emma Hopwood 870d23056a ZIP 320: use the [#binance-address-expiry] reference.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-03-18 17:46:41 +00:00
Daira-Emma Hopwood e5a24b4d94 ZIP 320: address review comments and make additional clarifications.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-03-17 22:01:28 +00:00
Daira-Emma Hopwood 05d4c99a55 ZIP 320: choose TEX Address alternative.
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
2024-03-13 17:38:08 +00:00
github-actions 6a0a93c020 Commit from GitHub Actions (Build tex and rst) 2024-01-06 20:57:42 +00:00
Andrew Arnott 250425e54a
Drop PR trigger
The git push at the end didn't have permission to push back to the source repo, even if the PR author granted permission for contributors to push to the source branch.
2024-01-06 13:48:56 -07:00
Andrew Arnott b8ba2282c2
Fix and rename GitHub Action workflow
This gets the Dockerfile behind the render workflow to build again.

I also renamed the workflow because it described only building the PDF, but it also builds all the .html files.
2024-01-06 13:35:22 -07:00
Daira Hopwood 5d78218fda WIP DO NOT MERGE: Sapling payment disclosures 2021-08-24 16:23:55 +01:00
Deirdre Connolly acc4fda689 Add specific reference to decryption that verifies note commitments in Sprout 2021-08-24 16:23:55 +01:00
Deirdre Connolly f33b080d6c Remove duplicate copyright notice 2021-08-24 16:23:55 +01:00
Deirdre Connolly 08a9ef73dd remove payment disclosure duplicate section 2021-08-24 16:23:55 +01:00
Deirdre Connolly b648d3fddd Remove section in abstract on conventions 2021-08-24 16:23:55 +01:00
Deirdre Connolly a408dde58a Fix typos 2021-08-24 16:23:55 +01:00
Deirdre Connolly d270b40620 Organize protocol and zcash github issue links 2021-08-24 16:23:55 +01:00
Deirdre Connolly 71a4b8fd6e Fix typo 2021-08-24 16:23:55 +01:00
Deirdre Connolly a091f1dbb3 Remove the whole non-interactive solution bit 2021-08-24 16:23:55 +01:00
Deirdre Connolly 04ded3426d Add some detail around an interactive challenge 2021-08-24 16:23:55 +01:00
Deirdre Connolly 953484231e Update ZIP 303 header 2021-08-24 16:23:55 +01:00
bitcartel 96e0044f84 Update from review comments. 2021-08-24 16:23:55 +01:00
bitcartel facb7fe215 Update based on review comments (work in progress) 2021-08-24 16:23:55 +01:00
bitcartel dbc38eb2b3 Rename JSON field ephemeralSymmetricKey to onetimeSymmetricKey. 2021-08-24 16:23:55 +01:00
bitcartel 81014c4f24 Updating zip 2021-08-24 16:23:55 +01:00
Simon 31e5ce9847 Update payment disclosure draft ZIP based on comments. 2021-08-24 16:23:55 +01:00
Simon 83033099f5 ZIP: Payment Disclosure 2021-08-24 16:23:55 +01:00
15 changed files with 638 additions and 469 deletions

View File

@ -1 +0,0 @@
../../../Dockerfile

View File

@ -1,7 +0,0 @@
name: Render Zcash Protocol Specification
description: GitHub Action to compile Zcash Protocol Specification LaTeX documents
author: Deirdre Connolly
runs:
using: docker
# Runs `make all` or something like it
image: Dockerfile

7
.github/actions/render/action.yml vendored Normal file
View File

@ -0,0 +1,7 @@
name: Render ZIPs and Zcash Protocol Specification
description: GitHub Action to compile ZIPs and Zcash Protocol Specification LaTeX documents
author: Deirdre Connolly
runs:
using: docker
# Runs `make all` or something like it
image: ../../../Dockerfile

View File

@ -1,19 +1,23 @@
name: Render pdfs
name: Build tex and rst
on: workflow_dispatch
on:
workflow_dispatch:
push:
branches:
- main
jobs:
render:
runs-on: ubuntu-latest
steps:
- name: Set up Git repository
uses: actions/checkout@v4.1.1
- name: Checkout repository
uses: actions/checkout@v4.1.2
- name: Compile Zcash Protocol Specification
uses: ./.github/actions/render-protocol-pdf
- name: Compile ZIPs and Zcash Protocol Specification
uses: ./.github/actions/render
- uses: EndBug/add-and-commit@v9.1.3
with:
add: '**/*.pdf'
add: 'protocol/*.pdf *.html'
default_author: github_actions

View File

@ -1,7 +1,7 @@
FROM debian:latest
RUN apt-get update \
&& apt-get install -y \
RUN apt-get update
RUN apt-get install -y \
gawk \
perl \
sed \
@ -17,7 +17,10 @@ RUN apt-get update \
texlive-plain-generic \
texlive-bibtex-extra
RUN pip3 install rst2html5
RUN rm /usr/lib/python3.11/EXTERNALLY-MANAGED
RUN pip install rst2html5
ENV PATH=${PATH}:/root/.local/bin
WORKDIR "/zips"
ENTRYPOINT ["make", "all"]

View File

@ -0,0 +1,404 @@
::
ZIP: 303
Title: Payment Disclosure
Owners: Deirdre Connolly <deirdre@zfnd.org>
Original-Author: Simon Liu
Status: Implemented (zcashd)
Category: Informational
Created: 2017-02-22
License: MIT
Abstract
--------
This ZIP describes a method of proving that a payment was sent to a shielded address. In the typical case, this means enabling a sender to present a proof that they transferred funds to a recipient's shielded address. The method described will be compatible with the Zcash Protocol [#protocol]_ deployed at the launch of the Zcash network. See zcash issues `2036 <https://github.com/zcash/zcash/issues/2036>`_ and `737 <https://github.com/zcash/zcash/issues/737>`_ for context.
Motivation
----------
Payment disclosure is useful in a number of situations, for example:
* A sender may need to prove that their payment was sent and received by a recipient. For example, a customer paid too much for an item and would like to claim a refund from the vendor.
* A third party needs to verify that a payment between sender and recipient was executed successfully. For example, a regulator needs to confirm a transfer of funds between two parties.
When a transaction involves only transparent addresses, the sender and recipient can verify payment by examining the blockchain. A third party can also perform this verification if they know the transparent addresses of the involved parties.
However, if the transaction involves shielded addresses, the blockchain by itself does not contain enough information to allow a record of the payment to be reconstructed and verified.
Let us examine the types of transaction that might occur and when a method of payment disclosure would be useful:
transparent --> transparent
The source, destination and amount are visible on the public blockchain. Payment disclosure is not required.
transparent --> shielded
The destination address and amount sent to that address cannot be confirmed. Payment disclosure is required.
shielded --> transparent
The recipient can see the amount received at their destination address, but cannot identify the sender. Payment disclosure is required.
shielded --> shielded
The sender, recipient and amount are unknown. Payment disclosure required.
Requirements
------------
Allow the sender to automatically or optionally create a payment disclosure when creating a transaction involving shielded addresses.
The sender or a third party can present this payment disclosure to the recipient to prove that funds were sent to their address.
The mechanism should support both payments involving either the Sprout or Sapling protocols.
Example
'''''''
A group of coworkers go out for dinner and decide to split the bill. The restaurant only accepts physical cash. Alice ends up paying the entire bill as her coworkers have no cash on them.
The next day Bob sends 1 ZEC to Alice's shielded address for his share of the bill. Other coworkers do the same. A week later Alice remembers that she is owed money so she checks her shielded address. Alice sees that the balance is less than what it should be, so she asks her coworkers to confirm their payments.
Bob retrieves his payment disclosure and emails it to Alice. Alice is travelling and only has access to her smartphone. She visits a Zcash blockchain explorer and copies the payment disclosure into the search box. The explorer confirms that Bob paid his share.
Charlie attempts to retrieve the payment disclosure but can't find one. Charlie had used the command line to send his funds to Alice, but never checked the status of the z_sendmany operation. Checking the debug logs he discovers that the operation failed due to an incorrect parameter. Charlie tells Alice that he will re-send his payment.
Design Considerations
---------------------
The payment disclosure does not prove that the party presenting the payment disclosure is the sender.
To prevent a man-in-the-middle attack, the recipient could pose an interactive challenge involving some out-of-band secret which only the sender would pass successfully.
It's also possible, rather than an interactive challenge, to make the disclosure dependent on data such as a refund address. This would prevent an attack where the payment disclosure is replayed with a claim that the refund should be to another address.
Known Issues
------------
Both plaintext outputs of a Sprout JoinSplit are currently encrypted with symmetric keys derived from the same ephemeral secret key, as discussed here: https://github.com/zcash/zcash/issues/558#issuecomment-167819936
This means that a payment disclosure that includes the ephemeral secret key intended to decipher the note ciphertext belonging to a particular JoinSplit output, creates a privacy leak by also deciphering the other JoinSplit output and revealing its contents (amount, payment address and memo field).
Note the current implementation of the ``z_sendmany`` RPC call:
- When sending from a transparent address to shielded addresses, each shielded address will occupy one output of a JoinSplit. Thus a payment address to a different recipient could be revealed.
- When sending involves chained JoinSplits, for each JoinSplit, one output is for payment to a recipient's address, while the other output is used as change back to the sender. Thus the change address will be revealed, which is the sender's own shielded address.
A proposal to prevent information leakage of change addresses is currently under development [KDFT]. TODO: Does this block ZIP approval?
Note that an independent third party cannot know for sure that the sender and recipient are not colluding to hide value transfer. JoinSplits have two inputs and two outputs. The recipient may identify their receiving address for one output, but not disclose the fact that the other output also belongs to them. Also, the sender and recipient could collude to transfer value in a different JoinSplit without disclosing it.
When a shielded transaction is created successfully and accepted into the local mempool with ``z_sendmany`` or ``z_shieldcoinbase``, the payment disclosure database is updated with information necessary to create a payment disclosure. However, the transaction itself may never be mined and confirmed in the blockchain, rendering the database entry itself redundant and available for purging at a later date e.g. garbage collection.
.. [KDFT] https://github.com/zcash/zcash/issues/2102
Specification
-------------
When creating a transaction with one or more JoinSplit outputs, for each such output, a data structure is created to record the following fields:
- transaction id
- index [0..len-1] of the JoinSplit description in the ``vJoinSplit`` field of the transaction
- index [0..1] of the recipient output within that JoinSplit description
- recipient's payment address is a shielded address ``(a_pk, pk_enc)`` [#protocol]_ §3.1 Payment Addresses and Keys
- ephemeral private key ``esk`` used to encrypt the note [#protocol]_ §4.10.1 Generate a new KA (public, private) key pair ``(epk, esk)``.
- JoinSplitSig private key used to sign the JoinSplit transaction ``joinSplitPrivKey`` [#protocol]_ §4.4 Sending Notes
When creating a transaction with one or more Sapling outputs, for each such output, a data structure is created to record:
- transaction id
- list of Output description indices [0..outlen-1]:
- corresponding ocks
- list of Spend description indices [0..inlen-1]
- corresponding Spend descriptions:
- any (d, pk_d) s.t. pk_d = [ivk] GH(d) -> ivk -> (ak, nk)
- a ZIP 304 signature:
- nf
- (rk is implied)
- zkproof
- spendAuthSig
What the prover needs:
have ask, α
pick fresh nsk
\alpha from original tx
derive (ak, nk) from (ask, nsk)
derive ivk = CRH^ivk(ak, nk)
pick a fresh d
derive g_d = GH(d), pk_d = [ivk] g_d
create a proof like ZIP 304:
- Let :math:`cm = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(g_d), \mathsf{repr}_\mathbb{J}(pk_d), 1)`.
- Let :math:`rt` be the root of a Merkle tree with depth
:math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and hashing function
:math:`\mathsf{MerkleCRH}^\mathsf{Sapling}`, containing :math:`cm` at position 0, and
:math:`\mathsf{Uncommitted}^\mathsf{Sapling}` at all other positions.
- Let :math:`path` be the Merkle path from position 0 to :math:`rt`. [#merkle-path]_
- Let :math:`cv = \mathsf{ValueCommit}_0(1)`.
- This is a constant and may be pre-computed.
- Let :math:`nf = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(nk)}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(cm, 0)))`.
- Let :math:`zkproof` be a Sapling spend proof with primary input :math:`(rt, cv, nf, rk)`
and auxiliary input :math:`(path, 0, g_d, pk_d, 1, 0, cm, 0, α, ak, nsk)`.
[#spend-statement]_
- Let :math:`rsk = \mathsf{SpendAuthSig.RandomizePrivate}(α, ask)`.
- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index
form, not its hardened form (i.e. 133 for mainnet Zcash).
- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`.
- Let :math:`spendAuthSig = \mathsf{SpendAuthSig.Sign}(rsk, digest)`.
- Return :math:`(d, pk_d, nf, zkproof, spendAuthSig)`.
The payment disclosure data should be persisted to disk or a database so it can be retrieved later.
When persisting, third party applications should expect serialization of payment disclosure to follow Zcash and upstream convention.
::
ADD_SERIALIZE_METHODS;
...
READWRITE(marker);
READWRITE(version);
READWRITE(esk);
READWRITE(txid);
READWRITE(js);
READWRITE(n);
READWRITE(zaddr);
READWRITE(message);
A new RPC call will be introduced to allow the sender to retrieve the payment disclosure data for a given shielded output index.
``z_getpaymentdisclosure txid joinsplit_index output_index [message]``
- Returns the payment disclosure in case-insensitive hexadecimal format, with a prefix of ``zpd:``.
- Message is an optional parameter, a UTF-8 string. We may want to restrict/sanitize this user input, e.g. number of characters, allowed characters.
The sender wants the payment disclosure to be non-malleable, to prevent an attacker modifying details like the refund address. To achieve this, the sender will sign the payment disclosure with the JoinSplitSig private key and append the signature to the end of the payment disclosure data.
A new RPC call will be introduced to allow a third party to verify a payment disclosure.
``z_validatepaymentdisclosure paymentdisclosure``
Validates a payment disclosure and returns JSON output as follows:
::
{
"txid": "68519fe52f2f64aa64e2a601e470fcde1069ab5a39652d277b7d816aa57169d1",
"jsIndex": 0,
"outputIndex": 0,
"version": 0,
"onetimeSymmetricKey": "09d6a2e2e8523280e5f56e79c080e82c4fe228086c92ea10986ca6d9bcea1d17",
"message": "howdy",
"joinSplitPubKey": "4c8d8135dca734b2c4fda25b2c7db29731d28a5f421f09da284b110bc0d1df91",
"signatureVerified": true,
"paymentAddress": "ztr4Ef2m7CFTtTvs4UpDz8zJY4Swukr3NRKThfLE12sNdGdav7Yf55G9HMAzGM3baR1FD43u9jb5JsAN67BBvz1UsVdLxoi",
"memo": "f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"value": 10.00000000,
"commitmentMatch": true,
"valid": true
}
Valid field is true if all the following conditions hold:
- the payment disclosure is correctly encoded and has a recognized version
- txid is confirmed in the blockchain
- jsindex is valid for the txid
- outputindex is within range [0..1]
- paymentaddress is a valid shielded address for the network we are on
- value is within range [0..MAX_MONEY]
- message is within constraints (TODO: currently there are no constraints defined, such as number of characters, allowed characters)
- signature is valid for all of the above fields
- commitment derived from the deciphered note matches the commitment in the blockchain
Otherwise an error field is returned explaining why the payment disclosure is invalid:
::
{
valid : false,
...
error : "The payment disclosure is invalid because..."
}
Implementation
--------------
TODO: Link to commits in Github
A reference implementation will be added to zcashd as an experimental feature. To enable payment disclosure, set the following two options to true:
* `-paymentdisclosure=1`
* `-experimentalfeatures=1`
A third party trying to validate payment disclosure must track all transactions and thus enable the option:
* `-txindex=1`
In this implementation we will assume that once the feature is enabled, the node will create and store a payment disclosure for every transaction sent which involves a shielded address.
When the sender calls RPC call ``z_sendmany`` and creates a shielded transaction in ``asyncrpcoperation.cpp``:
#. retain the ephemeral joinSplitPrivKey used to sign the transaction
#. retain the ephemeral secret key used for symmetric encryption of the note plaintext
Record relevant data in a struct (or class) defined as follows:
::
struct PaymentDisclosureKey {
uint256 txid // primitives/transaction.h
size_t js; // Index into CTransaction.vjoinsplit
uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS
};
struct PaymentDisclosureInfo {
uint8_t version; // 0 = experimental, 1 = first production version, etc.
uint256 esk; // zcash/NoteEncryption.cpp
uint256 joinSplitPrivKey; // primitives/transaction.h
PaymentAddress zaddr; // zcash/Address.hpp
};
Persist the object in a LevelDB key-value store, saved in a subfolder of the configured datadir:
``DATADIR/paymentdisclosure/``
Where key-value entries are:
::
Key: PaymentDisclosureKey
Value: PaymentDisclosureInfo
Given the above, by default on Linux, the payment disclosure database will be saved under:
``$HOME/.zcash/paymentdisclosure/``
The sender may optionally:
- log records to ``debug.log`` using a new debug category ``paymentdisclosure``
- [Is this useful? Not implemented yet] have the records returned in result of RPC call ``z_getoperationresult``
If the sender needs to provide a payment disclosure to the recipient or a third party, the sender will use RPC call ``z_getpaymentdisclosure`` to generate a Payment Disclosure.
``z_getpaymentdisclosure txid joinsplit_index output_index [message]``
To create a valid Payment Disclosure an implementation must:
#. Check the txid was confirmed in the blockchain
#. Create a ``PaymentDisclosureKey`` from parameters to RPC call
#. Use the key to retrieve its value ``PaymentDisclosureInfo`` from storage
#. Create and populate a ``PaymentDisclosure``
::
struct PaymentDisclosurePayload {
int32_t marker = PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES; // to be disjoint from transaction encoding
uint8 version; // 0 = experimental, 1 = first production version, etc.
uint256 esk; // zcash/NoteEncryption.cpp
uint256 txid; // primitives/transaction.h
size_t js; // Index into CTransaction.vjoinsplit
uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS
PaymentAddress zaddr; // zcash/Address.hpp
std::string message // parameter to RPC call
};
TODO: Copy magic bytes info here from https://github.com/zcash/zcash/blob/master/src/paymentdisclosure.h
#. Serialize ``PaymentDisclosurePayload`` and sign the raw data using the ``joinSplitPrivKey`` to generate a signature ``payloadSig``. Sample C++ code to do this:
::
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
ss << payload << nHashType;
uint256 dataToBeSigned = ss.GetHash();
// Compute the payload signature
unsigned char[64] payloadSig;
if (!(crypto_sign_detached(&payloadSig[0], NULL,
dataToBeSigned.begin(), 32,
joinSplitPrivKey
) == 0))
{
throw std::runtime_error("crypto_sign_detached failed");
}
// Sanity check
if (!(crypto_sign_verify_detached(&payloadSig[0],
dataToBeSigned.begin(), 32,
joinSplitPubKey.begin()
) == 0))
{
throw std::runtime_error("crypto_sign_verify_detached failed");
}
#. Construct and serialize a PaymentDisclosure object using the data generated so far.
::
struct PaymentDisclosure {
PaymentDisclosurePayload payload;
unsigned char[64] payloadSig;
}
#. Return to the caller the hex string of the serialized PaymentDisclosure. If there were errors generating the payment disclosure, return a standard JSON-RPC error with an appropriate error message.
::
00171deabcd9a66c9810ea926c0828e24f2ce880c0796ef5e5803252e8e2a2d609d16971a56a817d7b272d65395aab6910defc70e401a6e264aa642f2fe59f5168000000000000000000f4fda3737075b8b7f00715a5fcf106c74b75150d8f5578b973417f529d3464e2df1d76d937887b8aad659a4a0bdedb34a2706759bd64fa923863094eba504d7b05686f776479c6855c4eee0e2601301bea503ad96d4216702baa8db2141530ae58875def42590afb9681c22948dd2affba1bddd81eeafef1579a760bf13e8afd849287d30800
This raw hex string can be given to the recipient or a third party to use with the new RPC call ``z_validatepaymentdisclosure``:
``z_validatepaymentdisclosure paymentdisclosure``
To validate a payment disclosure, perform the following steps:
1. Deserialize the raw hex string into a ``PaymentDisclosure`` object
2. Retrieve the ``joinSplitPubKey`` for the transaction and verify the payment disclosure signature ``payloadSig``.
3. Retrieve the note ciphertext from the blockchain for ``txid``, ``js``, ``n``.
4. Use the ``esk`` to decrypt the ciphertext into plain text, where `decrypt` is the same operation defined in [#protocol]_ §4.16.2 Decryption (Sprout).
5. Derive commitment from plain text and check it matches commitment in blockchain
6. Return JSON output as described above in the specification.
Possible error messages which could cause validation to fail include:
TODO: Add bad prefix error message here
- "Invalid parameter, expected payment disclosure data in hexadecimal format."
- "Invalid parameter, payment disclosure data is malformed."
- "No information available about transaction"
- "Transaction has not been confirmed yet"
- "Transaction is not a shielded transaction"
- "Payment disclosure refers to an invalid JoinSplit index"
- "Payment disclosure refers to an invalid output index"
- "Payment disclosure refers to an unknown version"
- "Payment disclosure signature does not match transaction signature"
- "Payment disclosure refers to an invalid payment address"
- "Payment disclosure derived commitment does not match blockchain commitment"
- "Payment disclosure error when deciphering note"
- ...
References
==========
.. [#protocol] `Zcash Protocol Specification, Version 2020.1.5 or later <protocol/protocol.pdf>`_

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

8
zip-0253.rst Normal file
View File

@ -0,0 +1,8 @@
::
ZIP: 253
Title: Deployment of the NU6 Network Upgrade
Owners: Daira-Emma Hopwood <daira-emma@electriccoin.co>
Status: Reserved
Category: Consensus / Network
Discussions-To: <https://github.com/zcash/zips/issues/806>

View File

@ -17,56 +17,70 @@ Category: Standards / Wallet
Created: 2024-01-12
License: MIT
Discussions-To: &lt;<a href="https://github.com/zcash/zips/issues/757">https://github.com/zcash/zips/issues/757</a>&gt;
&lt;<a href="https://github.com/zcash/zips/issues/795">https://github.com/zcash/zips/issues/795</a>&gt;
Pull-Request: &lt;<a href="https://github.com/zcash/zips/pull/760">https://github.com/zcash/zips/pull/760</a>&gt;
&lt;<a href="https://github.com/zcash/zips/pull/766">https://github.com/zcash/zips/pull/766</a>&gt;</pre>
&lt;<a href="https://github.com/zcash/zips/pull/766">https://github.com/zcash/zips/pull/766</a>&gt;
&lt;<a href="https://github.com/zcash/zips/pull/798">https://github.com/zcash/zips/pull/798</a>&gt;</pre>
<section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a rel="bookmark" href="#terminology"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The key words "MUST", "SHOULD", "NOT RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 14 <a id="footnote-reference-1" class="footnote_reference" href="#bcp14">1</a> when, and only when, they appear in all capitals.</p>
<p>The terms "Recipient", "Producer", "Consumer", "Sender", "Receiver", "Item", "Metadata Item", "Typecode", "Address", "Unified Address" (UA), "Unified Viewing Key" (UVK), "Unified Full Viewing Key" (UFVK), and "Unified Incoming Viewing Key" (UIVK) are to be interpreted as described in ZIP 316 <a id="footnote-reference-2" class="footnote_reference" href="#zip-0316-terminology">5</a>.</p>
<p>The terms "Testnet" and "Mainnet" are to be interpreted as described in section 3.12 of the Zcash Protocol Specification <a id="footnote-reference-3" class="footnote_reference" href="#protocol-networks">13</a>.</p>
<p>The terms "Recipient", "Producer", "Consumer", "Sender", "Receiver", "Address", and "Unified Address" are to be interpreted as described in ZIP 316 <a id="footnote-reference-2" class="footnote_reference" href="#zip-0316-terminology">7</a>.</p>
<p>The terms "Testnet" and "Mainnet" are to be interpreted as described in section 3.12 of the Zcash Protocol Specification <a id="footnote-reference-3" class="footnote_reference" href="#protocol-networks">10</a>.</p>
</section>
<section id="abstract"><h2><span class="section-heading">Abstract</span><span class="section-anchor"> <a rel="bookmark" href="#abstract"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>This ZIP defines a new encoding for transparent Zcash addresses. Wallets must ensure that no shielded notes are spent in transactions that send to a transparent address encoded in the specified fashion.</p>
<p>This ZIP is presently in Draft status, and defines two alternate encodings for consideration. Analysis of the benefits and drawbacks of each of the proposed alternatives is presented at the end of this document.</p>
</section>
<section id="background"><h2><span class="section-heading">Background</span><span class="section-anchor"> <a rel="bookmark" href="#background"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>In November of 2023, the Zcash community received notice from the Binance cryptocurrency exchange that Zcash was at risk of being delisted from the exchange unless the community could provide a mechanism by which Binance could refuse deposits from shielded addresses and return them to the depositor. This issue was raised and discussed at length in the Zcash Community forum <a id="footnote-reference-4" class="footnote_reference" href="#binance-delisting">2</a>.</p>
<p>In the course of that discussion thread, wallet developer and community member @hanh <a id="footnote-reference-5" class="footnote_reference" href="#hanh-profile">3</a> suggested a wallet-oriented approach <a id="footnote-reference-6" class="footnote_reference" href="#hanh-suggestion">4</a> that involved defining a new encoding for Zcash transparent P2PKH addresses. A Consumer of such an address, whether it be a wallet or an exchange, could recognize this encoding as a directive that the wallet should only spend transparent funds when creating an output to that address.</p>
<p>In November 2023, the Zcash community received notice from the Binance cryptocurrency exchange that Zcash was at risk of being delisted from the exchange unless the community could provide a mechanism by which Binance could refuse deposits from shielded addresses and return them to the depositor. This issue was raised and discussed at length in the Zcash Community forum <a id="footnote-reference-4" class="footnote_reference" href="#binance-delisting">2</a>.</p>
<p>In the course of that discussion thread, wallet developer and community member @hanh <a id="footnote-reference-5" class="footnote_reference" href="#hanh-profile">3</a> suggested a wallet-oriented approach <a id="footnote-reference-6" class="footnote_reference" href="#hanh-suggestion">4</a> that involved defining a new encoding for Zcash transparent P2PKH addresses. A Consumer of such an address, whether it be a wallet or an exchange, could recognize this encoding as a directive that the wallet should only spend transparent funds when creating an output to that address. This ZIP formalizes that proposal.</p>
</section>
<section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a rel="bookmark" href="#motivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The Binance cryptocurrency exchange requires that funds sent to their deposit addresses come from source addresses that are readily identifiable using on-chain information, such that if necessary funds may be rejected by sending them back to the source address(es). This ZIP is intended to standardize a transparent address encoding that is not yet understood by preexisting Consumers, in order to prevent inadvertent shielded spends when sending to such addresses. Then, Consumers that upgrade to support the new encoding will do so with the understanding that they must respect the restrictions on sources of funds described in this ZIP.</p>
<p>The Binance cryptocurrency exchange requires that funds sent to their deposit addresses come from source addresses that are readily identifiable using on-chain information, such that if necessary funds may be rejected by sending them back to one of the source addresses. This ZIP is intended to standardize a transparent address encoding that is not yet understood by preexisting Consumers, in order to prevent inadvertent shielded spends when sending to such addresses. Then, Consumers that upgrade to support the new encoding will do so with the understanding that they must respect the restrictions on sources of funds described in this ZIP.</p>
<p>It is not expected that other exchanges or Producers of Zcash addresses will generate Transparent-Source-Only Addresses unless they have a specific need to be able to identify the address or addresses from which a payment was funded. However, all Consumers of Zcash addresses should implement this specification, in order to promote interoperability across the Zcash ecosystem.</p>
</section>
<section id="requirements"><h2><span class="section-heading">Requirements</span><span class="section-anchor"> <a rel="bookmark" href="#requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<ol type="1">
<li>A Recipient wishing to receive funds from exclusively transparent sources must be able to generate a receiving address such that only transparent funds will be spent in transactions with an output to this address.</li>
<li>A Recipient wishing to receive funds from exclusively transparent sources must be able to generate a receiving address such that only transparent funds will be spent in transactions with an output to this address. The purpose of this is to ensure that it is reliably possible for the Recipient to send back funds received from a Sender that conforms to this ZIP.</li>
<li>Wallets and other Consumers that have not been upgraded to recognize the new address format cannot mistake the address for another address type or inadvertently send shielded funds to the address.</li>
<li>No changes to Recipient infrastructure beyond changes to address encoding and decoding should be required as a consequence of this ZIP.</li>
<li>No changes to Recipient infrastructure beyond changes to address encoding and decoding should be required as a consequence of this ZIP. In particular, conversion between a Transparent-Source-Only Address and the corresponding unrestricted transparent address should be possible using only dependencies that are available to Binance's front-end code.</li>
</ol>
</section>
<section id="alternative-1"><h2><span class="section-heading">Alternative 1</span><span class="section-anchor"> <a rel="bookmark" href="#alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>This alternative was suggested by @hanh in <a id="footnote-reference-7" class="footnote_reference" href="#hanh-suggestion">4</a>.</p>
<section id="tex-addresses"><h3><span class="section-heading">TEX Addresses</span><span class="section-anchor"> <a rel="bookmark" href="#tex-addresses"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A TEX Address is a Bech32m <a id="footnote-reference-8" class="footnote_reference" href="#bip-0350">18</a> reencoding of a transparent Zcash P2PKH address <a id="footnote-reference-9" class="footnote_reference" href="#protocol-transparentaddrencoding">14</a>.</p>
<section id="non-requirements"><h2><span class="section-heading">Non-requirements</span><span class="section-anchor"> <a rel="bookmark" href="#non-requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<ol type="1">
<li>It is only required to support a Transparent-Source-Only form of P2PKH addresses; P2SH address support is not necessary.</li>
<li>It is not required to limit the source of transparent funds sent to a Transparent-Source-Only Address to a single source address. This implies that if the Recipient chooses to send back the funds, it is acceptable for it to send them back to any of the source addresses if there is more than one.</li>
<li>It is not necessary for the restriction on the source of funds to be enforced as a consensus rule. If a Sender fails to adhere to the restriction, it risks loss of funds, which is acceptable in the case of a non-conforming Sender implementation.</li>
</ol>
</section>
<section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a rel="bookmark" href="#specification"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>A TEX Address, also called a Transparent-Source-Only Address, is a Bech32m <a id="footnote-reference-7" class="footnote_reference" href="#bip-0350">15</a> reencoding of a transparent Zcash P2PKH address <a id="footnote-reference-8" class="footnote_reference" href="#protocol-transparentaddrencoding">11</a>.</p>
<p>Wallets and other Senders sending to a TEX address (as any output) MUST ensure that only transparent (P2SH or P2PKH) UTXOs are spent in the creation of the transaction. For simplicity of parsing and interpreting such transactions, they also SHOULD only send to transparent outputs.</p>
<p>A TEX address can be produced from a Mainnet Zcash P2PKH Address by executing the following steps:</p>
<ol type="1">
<li>Decode the address to a byte sequence using the Base58Check decoding algorithm <a id="footnote-reference-9" class="footnote_reference" href="#base58check">13</a>.</li>
<li>If the length of the resulting byte sequence is not 22 bytes or if its two-byte address prefix is not
<span class="math">\([\mathtt{0x1C}, \mathtt{0xB8}]\)</span>
, return an error. Otherwise, let the <strong>validating key hash</strong> be the remaining 20 bytes of the sequence after removing the two-byte address prefix.</li>
<li>Reencode the 20-byte <strong>validating key hash</strong> using the Bech32m encoding defined in <a id="footnote-reference-10" class="footnote_reference" href="#bip-0350">15</a> with the human-readable prefix (HRP) <code>"tex"</code>.</li>
</ol>
<p>For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are
<span class="math">\([\mathtt{0x1D}, \mathtt{0x25}]\)</span>
, and the <code>"textest"</code> HRP is used when reencoding in step 3.</p>
<p>A TEX address can be parsed by reversing this encoding, i.e.:</p>
<ol type="1">
<li>Decode the address to a byte sequence using Bech32m <a id="footnote-reference-11" class="footnote_reference" href="#bip-0350">15</a>, checking that the HRP is <code>"tex"</code> for a Mainnet TEX Address and <code>"textest"</code> for a Testnet TEX Address.</li>
<li>If the length of the resulting byte sequence is not 20 bytes, return an error. Otherwise, the <strong>validating key hash</strong> is this byte sequence.</li>
</ol>
<section id="design-considerations-for-senders"><h3><span class="section-heading">Design considerations for Senders</span><span class="section-anchor"> <a rel="bookmark" href="#design-considerations-for-senders"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>For a transaction that spends only from transparent funds to a TEX Address, this specification imposes no additional requirements.</p>
<p>If, on the other hand, a user desires to spend shielded funds to a TEX Address, a Sender supporting this ZIP MUST create two transactions: one that unshields the funds to an ephemeral transparent address, and one that spends from that ephemeral address to the destination TEX Address. This does not defeat the intent of the ZIP, because it is still possible for a Recipient to return the funds to the Sender by sending them back to the ephemeral address.</p>
<p>Wallets MUST be able to recognize funds that have been returned in this way and spend them if desired. In order for this to be possible without use of TEX Addresses increasing the risk of loss of funds, wallets based on ZIP 32 <a id="footnote-reference-12" class="footnote_reference" href="#zip-0032">5</a> SHOULD choose ephemeral addresses in a way that allows the corresponding private keys to be recovered from a ZIP 32 master seed.</p>
<p>However, ephemeral addresses SHOULD NOT be chosen in a way that allows them to be linked between transactions, without knowledge of the wallet seed or the relevant transparent viewing keys. This also implies that they SHOULD be chosen in a way that avoids collisions with addresses for previously generated outputs (including change outputs), such as might have been created by a transparent-only wallet using Bitcoin-derived code based on BIP 44 <a id="footnote-reference-13" class="footnote_reference" href="#bip-0044">14</a>.</p>
<p>In order to show accurate transaction history to a user, wallets SHOULD remember when a particular transaction output was sent to a TEX Address, so that they can show that form rather than its P2PKH form. It is acceptable that this information may be lost on recovery from seed.</p>
</section>
<section id="motivations-for-alternative-1"><h3><span class="section-heading">Motivations for Alternative 1</span><span class="section-anchor"> <a rel="bookmark" href="#motivations-for-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>The TEX Address is the simplest possible approach to creating a new address type that indicates that only transparent sources of funds should be used.</p>
</section>
<section id="specification-alternative-1"><h3><span class="section-heading">Specification (Alternative 1)</span><span class="section-anchor"> <a rel="bookmark" href="#specification-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A TEX address is produced from a Mainnet Zcash P2PKH Address by executing the following steps:</p>
<ol type="1">
<li>Decode the address to a byte sequence using the Base58Check decoding algorithm <a id="footnote-reference-10" class="footnote_reference" href="#base58check">16</a>.</li>
<li>If the length of the resulting byte sequence is not 22 bytes or if its two-byte address prefix is not
<span class="math">\([\mathtt{0x1C}, \mathtt{0xB8}]\)</span>
, return an error. Otherwise, let the <strong>validating key hash</strong> be the remaining 20 bytes of the sequence after removing the two-byte address prefix.</li>
<li>Reencode the 20-byte <strong>validating key hash</strong> using the Bech32m encoding defined in <a id="footnote-reference-11" class="footnote_reference" href="#bip-0350">18</a> with the human-readable prefix (HRP) <code>"tex"</code>.</li>
</ol>
<p>For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are
<span class="math">\([\mathtt{0x1D}, \mathtt{0x25}]\)</span>
, and the <code>"textest"</code> HRP is used when reencoding in step 3.</p>
<p>Wallets and other Senders sending to a TEX address (as any output) MUST ensure that only transparent UTXOs are spent in the creation of a transaction.</p>
</section>
<section id="reference-implementation-alternative-1"><h3><span class="section-heading">Reference Implementation (Alternative 1)</span><span class="section-anchor"> <a rel="bookmark" href="#reference-implementation-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Javascript:</p>
<pre>import bs58check from 'bs58check'
</section>
<section id="reference-implementation"><h2><span class="section-heading">Reference Implementation</span><span class="section-anchor"> <a rel="bookmark" href="#reference-implementation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>Javascript:</p>
<pre>import bs58check from 'bs58check'
import {bech32m} from 'bech32'
// From t1 to tex
@ -84,123 +98,15 @@ var pkh2 = Uint8Array.from(bech32m.fromWords(bech32decoded.words))
console.assert(pkh2.length == 20, 'Invalid length');
var t1 = bs58check.encode(Buffer.concat([Uint8Array.from([0x1C, 0xB8]), pkh2]))
console.log(t1)</pre>
</section>
</section>
<section id="alternative-2"><h2><span class="section-heading">Alternative 2</span><span class="section-anchor"> <a rel="bookmark" href="#alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="traceable-unified-addresses"><h3><span class="section-heading">Traceable Unified Addresses</span><span class="section-anchor"> <a rel="bookmark" href="#traceable-unified-addresses"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A Traceable Unified Address is a reencoding of a transparent Zcash P2PKH address into a Unified Address <a id="footnote-reference-12" class="footnote_reference" href="#zip-0316-unified-addresses">8</a>.</p>
</section>
<section id="motivations-for-alternative-2"><h3><span class="section-heading">Motivations for Alternative 2</span><span class="section-anchor"> <a rel="bookmark" href="#motivations-for-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Traceable Unified Addresses fit into the Zcash Unified Address ecosystem defined by ZIP 316, Revision 1 <a id="footnote-reference-13" class="footnote_reference" href="#zip-0316-revision-1">7</a>. Existing Consumers of Unified Addresses will not be able to send to these address unless they update their code to understand the new MUST-understand Metadata Typecode defined in this ZIP.</p>
<p>By integrating with the Unified Address framework, it becomes possible for the addresses being generated to include extra metadata; in particular, metadata items such as an Address Expiry Height or Address Expiry Date <a id="footnote-reference-14" class="footnote_reference" href="#zip-0316-address-expiry">12</a> may be included. For exchange use cases such as Binance's, it is useful to ensure that an address provided to a user has a limited utility life, such that after expiration the user must obtain a new address in order to be able to continue to send funds <a id="footnote-reference-15" class="footnote_reference" href="#binance-address-expiry">15</a>.</p>
</section>
<section id="specification-alternative-2"><h3><span class="section-heading">Specification (Alternative 2)</span><span class="section-anchor"> <a rel="bookmark" href="#specification-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Upon activation of this ZIP, the section <cite>Metadata Items</cite> of ZIP 316 <a id="footnote-reference-16" class="footnote_reference" href="#zip-0316-metadata-items">11</a> will be modified to define a new MUST-understand Metadata Item type: Source Restriction Metadata, having Typecode
<span class="math">\(\mathtt{0xE2}\)</span>
, the value of which MUST be a single byte:</p>
<ul>
<li>
<span class="math">\(\mathtt{0x00}\)</span>
- Transparent Source Only</li>
</ul>
<p>Additional Source Restriction Metadata values can be defined in the future, but a Consumer that does not recognise the value MUST reject the entire UA/UVK as invalid.</p>
<p>Wallets and other Senders MUST ensure that only transparent UTXOs are spent in the creation of a transaction to any Unified Address containing a Source Restriction Metadata Item having value
<span class="math">\(\mathtt{0x00}\)</span>
.</p>
<p>A Traceable Unified Address is produced from a Mainnet Zcash P2PKH address by executing the following steps:</p>
<ol type="1">
<li>Decode the address to a byte sequence using the Base58Check decoding algorithm <a id="footnote-reference-17" class="footnote_reference" href="#base58check">16</a>.</li>
<li>If the length of the resulting byte sequence is not 22 bytes or if its two-byte address prefix is not
<span class="math">\([\mathtt{0x1C}, \mathtt{0xB8}]\)</span>
, return an error. Otherwise, let the <strong>validating key hash</strong> be the remaining 20 bytes of the array after removing the two-byte address prefix.</li>
<li>Construct a new Revision 1 Unified Address using a single P2PKH Receiver
<span class="math">\(\mathtt{0x04}\)</span>
with the 20-byte <strong>validating key hash</strong> as its value, and a Source Restriction Metadata Item (Typecode
<span class="math">\(\mathtt{0xE2}\)</span>
) having value
<span class="math">\(\mathtt{0x00}\)</span>
(Transparent Source Only). In addition, metadata items such as an Address Expiry Height or Address Expiry Date <a id="footnote-reference-18" class="footnote_reference" href="#zip-0316-address-expiry">12</a> MAY be included.</li>
<li>Encode the Unified Address using the “<code>ur</code>” Human Readable Part as specified for Revision 1 of ZIP 316 <a id="footnote-reference-19" class="footnote_reference" href="#zip-0316-revision-1">7</a>.</li>
</ol>
<p>For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are
<span class="math">\([\mathtt{0x1D}, \mathtt{0x25}]\)</span>
.</p>
<p>The HRP of the resulting Unified Address is the same as for any other Revision 1 Unified Address on the relevant network as specified in <a id="footnote-reference-20" class="footnote_reference" href="#zip-0316-revision-1">7</a>, i.e. <code>"ur"</code> for Mainnet and <code>"urtest"</code> for Testnet.</p>
<p>Any Source Restriction Metadata Item MUST be preserved with the same value when deriving a UIVK from a UFVK, or a UA from a UIVK. It has no other effect on the meaning of the UFVK or UIVK.</p>
<p>Note that it is possible for a Unified Address to include shielded Receivers and also Source Restriction Metadata with value Transparent Source Only. The semantics of such UAs are well defined: they allow a shielding transaction that only spends transparent UTXOs when sending to a shielded Receiver, and the priority order of Receivers defined by ZIP 316 is unaffected. However, this combination of requirements might result in wallet interoperability issues, and so producing such UAs is NOT RECOMMENDED.</p>
<section id="dependencies-on-revision-1-of-zip-316"><h4><span class="section-heading">Dependencies on Revision 1 of ZIP 316</span><span class="section-anchor"> <a rel="bookmark" href="#dependencies-on-revision-1-of-zip-316"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>This specification depends upon the following changes made for Revision 1 of ZIP 316 <a id="footnote-reference-21" class="footnote_reference" href="#zip-0316-revision-1">7</a>:</p>
<ul>
<li>A Revision 1 UA/UVK is <em>not</em> required to include a shielded Item. This is necessary for a Traceable Unified Address containing only a P2PKH Receiver to be valid. (It also has other independent motivations, as explained in <a id="footnote-reference-22" class="footnote_reference" href="#zip-0316-drop-shielded-restriction">10</a>.)</li>
<li>The change to the HRPs for Revision 1 UAs implies that a Sender implementing the Revision 0 specification will not recognize the UA as valid, which is necessary because it may not understand the Source Restriction Metadata.</li>
<li>A Consumer of a Revision 1 UIVK or UFVK is required to retain the Source Restriction Metadata when deriving a UA or UIVK respectively.</li>
</ul>
</section>
</section>
<section id="reference-implementation-alternative-2"><h3><span class="section-heading">Reference Implementation (Alternative 2)</span><span class="section-anchor"> <a rel="bookmark" href="#reference-implementation-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Javascript using <cite>zcash_address_wasm</cite> <a id="footnote-reference-23" class="footnote_reference" href="#zcash-address-wasm">19</a>:</p>
<pre>import init, { to_traceable_address, traceable_to_p2pkh, addr_expiry_time } from 'zcash_address_wasm';
init().then(() =&gt; {
var t_address = "t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC";
console.log("original P2PKH address: " + t_address);
var expiry_time = new Date();
// Add 30 days in UTC.
expiry_time.setUTCDate(expiry_time.getUTCDate() + 30);
// Date.getTime() returns UTC time since 1970-01-01T00:00:00Z in milliseconds.
var expiry_unix_seconds = BigInt(Math.floor(expiry_time.getTime() / 1000));
var traceable_address = to_traceable_address(t_address, expiry_unix_seconds);
console.log("Traceable Unified Address: " + traceable_address);
var p2pkh_addr = traceable_to_p2pkh(traceable_address);
console.log("decoded P2PKH address: " + p2pkh_addr);
var expiry = addr_expiry_time(traceable_address);
// Ignore far-future expiry times not representable as a Date.
if (expiry !== null &amp;&amp; expiry &lt;= 8_640_000_000_000n) {
console.log("expiry time: " + new Date(Number(expiry) * 1000).toUTCString());
}
});</pre>
<p>Example output:</p>
<pre>original P2PKH address: t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC
Traceable Unified Address: u1p3temdfuxr6vcfr2z3n5weh652rg0hv7q44c652y3su77d0pyktt47am3tng7uxxtk553hhka75r6cvfs5j
decoded P2PKH address: t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC
expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
</section>
</section>
<section id="analysis-of-alternative-1"><h2><span class="section-heading">Analysis of Alternative 1</span><span class="section-anchor"> <a rel="bookmark" href="#analysis-of-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="pros-to-alternative-1"><h3><span class="section-heading">Pros to Alternative 1</span><span class="section-anchor"> <a rel="bookmark" href="#pros-to-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<ul>
<li>The reencoding from Zcash P2PKH addresses is extremely straightforward and relies only upon widely available encoding libraries.</li>
</ul>
</section>
<section id="cons-to-alternative-1"><h3><span class="section-heading">Cons to Alternative 1</span><span class="section-anchor"> <a rel="bookmark" href="#cons-to-alternative-1"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<ul>
<li>Existing wallets and other Consumers will regard the new address type as entirely invalid, and will not automatically prompt their users that they need to upgrade in order to send to this type of address.</li>
<li>Creation of a new fully distinct address type further fragments the Zcash address ecosystem. Avoiding such fragmentation and providing smooth upgrade paths and good error messages to users is exactly the problem that Unified Addresses <a id="footnote-reference-24" class="footnote_reference" href="#zip-0316-motivation">6</a> were intended to avoid.</li>
<li>The TEX address type does not provide any mechanism for address expiration. One of the questions Binance has asked has been what to do about users who have stored their existing transparent deposit address in their wallets, or use them as a withdrawal address for other exchanges or services. This is a challenging problem to mitigate now because address expiration was not previously implemented. We should not further compound this problem by defining a new distinct address type that does not provide a mechanism for address expiry.</li>
</ul>
</section>
</section>
<section id="analysis-of-alternative-2"><h2><span class="section-heading">Analysis of Alternative 2</span><span class="section-anchor"> <a rel="bookmark" href="#analysis-of-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="pros-to-alternative-2"><h3><span class="section-heading">Pros To Alternative 2</span><span class="section-anchor"> <a rel="bookmark" href="#pros-to-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<ul>
<li>By integrating with the Unified Address framework, Consumers of Revision 1 Unified Addresses that have not yet been upgraded to recognize these addresses can automatically be prompted to upgrade their wallets or services to understand the unrecognized MUST-understand Metadata Typecode.</li>
<li>It is possible to include address expiration metadata in a Traceable Unified Address, which can help to mitigate problems related to stored addresses in the future.</li>
<li>The Source Restriction Metadata feature can easily be extended to express other kinds of source restriction, such as "Shielded Source Only" or "Fully Shielded with No Pool Crossing".</li>
<li>Traceable Unified Addresses benefit from the robustness to errors and protection against malleation of Unified Addresses <a id="footnote-reference-25" class="footnote_reference" href="#f4jumble">17</a>.</li>
<li>Regardless of which proposal is adopted, the Zcash Community will need to work with exchanges other than Binance to update their address parsing logic to understand the new address format. By encouraging Consumers such as exchanges to adopt parsing for Unified Addresses, this proposal furthers the original goal of Unified Addresses to reduce fragmentation in the address ecosystem.
<p>Whenever any new feature is added, wallets have a choice whether or not to support that new feature. The point of Unified Address parsing is that wallets dont have to upgrade to recognize a different address format as a valid Zcash address. Instead of returning a “Not a valid Zcash address” error, which could be confusing for users, they can return an error more like “This is a valid Zcash address, but this wallet does not support sending to it.” This can be used as a prompt to upgrade the wallet to a version (or alternative) that does support that feature.</p>
</li>
</ul>
</section>
<section id="cons-to-alternative-2"><h3><span class="section-heading">Cons to Alternative 2</span><span class="section-anchor"> <a rel="bookmark" href="#cons-to-alternative-2"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<ul>
<li>Existing wallets and other Consumers of Revision 0 Unified Addresses will regard the new address type as entirely invalid, and will not automatically prompt their users that they need to upgrade in order to send to this type of address.</li>
<li>Unified Address encoding is slightly more complex than the proposed TEX address encoding, and requires use of the F4Jumble encoding algorithm <a id="footnote-reference-26" class="footnote_reference" href="#f4jumble">17</a>. However, this can be readily mitigated by providing a purpose-built library for Traceable Unified Address encoding to Producers.</li>
<li>A Traceable Unified Address is somewhat longer than a TEX address, although not excessively so.</li>
</ul>
<section id="rationale"><h2><span class="section-heading">Rationale</span><span class="section-anchor"> <a rel="bookmark" href="#rationale"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>TEX addresses are the simplest possible approach to creating a new address type that indicates that only transparent sources of funds should be used.</p>
<p>As required by Binance, it will be possible to convert between a TEX address and an unrestricted transparent P2PKH address using extremely straightforward code that depends only on Base58Check and Bech32m encoding/decoding, as shown in the above <a href="#reference-implementation">Reference Implementation</a>.</p>
<p>An earlier version of this ZIP also described another alternative using metadata in Unified Addresses, as specified in ZIP 316 <a id="footnote-reference-14" class="footnote_reference" href="#zip-0316">6</a>. That alternative was designed to enable better integration with the Zcash Unified Address ecosystem, and had the advantage of being able to combine different types of metadata along with the Transparent-Source-Only indicator, such as an expiration block height or time <a id="footnote-reference-15" class="footnote_reference" href="#zip-0316-address-expiry">9</a> <a id="footnote-reference-16" class="footnote_reference" href="#binance-address-expiry">12</a>.</p>
<p>However, ultimately the Unified Address-based approach did not meet all of the requirements, since it would in practice have required dependencies on address handling libraries that Binance did not want to depend on in their front-end code.</p>
<p>Some design elements of that approach that apply to metadata in general have been incorporated into ZIP 316 Revision 1 <a id="footnote-reference-17" class="footnote_reference" href="#zip-0316-revision-1">8</a>. A more general form of Source Restriction Metadata is also under consideration.</p>
<section id="disadvantages"><h3><span class="section-heading">Disadvantages</span><span class="section-anchor"> <a rel="bookmark" href="#disadvantages"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A disadvantage of TEX Addresses (and also of the alternative approach using Unified Addresses) is that the information that a TEX Address was used does not appear on-chain, i.e. a transaction sending to a TEX Address is indistinguishable from one sending to the underlying P2PKH address. This is inevitable given the desire not to change the underlying consensus protocol to support this functionality.</p>
</section>
</section>
<section id="references"><h2><span class="section-heading">References</span><span class="section-anchor"> <a rel="bookmark" href="#references"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
@ -236,66 +142,42 @@ expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
</tr>
</tbody>
</table>
<table id="zip-0316-terminology" class="footnote">
<table id="zip-0032" class="footnote">
<tbody>
<tr>
<th>5</th>
<td><a href="zip-0316#terminology">ZIP 316: Unified Addresses and Unified Viewing Keys — Terminology</a></td>
<td><a href="zip-0032">ZIP 32: Shielded Hierarchical Deterministic Wallets</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-motivation" class="footnote">
<table id="zip-0316" class="footnote">
<tbody>
<tr>
<th>6</th>
<td><a href="zip-0316#motivation">ZIP 316: Unified Addresses and Unified Viewing Keys — Motivation</a></td>
<td><a href="zip-0316">ZIP 316: Unified Addresses and Unified Viewing Keys</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-terminology" class="footnote">
<tbody>
<tr>
<th>7</th>
<td><a href="zip-0316#terminology">ZIP 316: Unified Addresses and Unified Viewing Keys — Terminology</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-revision-1" class="footnote">
<tbody>
<tr>
<th>7</th>
<td><a href="zip-0316#revision-1">ZIP 316: Unified Addresses and Unified Viewing Keys — Revision 1</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-unified-addresses" class="footnote">
<tbody>
<tr>
<th>8</th>
<td><a href="zip-0316#encoding-of-unified-addresses">ZIP 316: Unified Addresses and Unified Viewing Keys — Encoding of Unified Addresses</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-unified-requirements" class="footnote">
<tbody>
<tr>
<th>9</th>
<td><a href="zip-0316#requirements-for-both-unified-addresses-and-unified-viewing-keys">ZIP 316: Unified Addresses and Unified Viewing Keys — Requirements for both Unified Addresses and Unified Viewing Keys</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-drop-shielded-restriction" class="footnote">
<tbody>
<tr>
<th>10</th>
<td><a href="zip-0316#rationale-for-dropping-the-at-least-one-shielded-item-restriction">ZIP 316: Unified Addresses and Unified Viewing Keys — Rationale for dropping the "at least one shielded Item" restriction</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-metadata-items" class="footnote">
<tbody>
<tr>
<th>11</th>
<td><a href="zip-0316#metadata-items">ZIP 316: Unified Addresses and Unified Viewing Keys — Metadata Items</a></td>
<td><a href="zip-0316#revision-1">ZIP 316: Unified Addresses and Unified Viewing Keys — Revision 1</a></td>
</tr>
</tbody>
</table>
<table id="zip-0316-address-expiry" class="footnote">
<tbody>
<tr>
<th>12</th>
<th>9</th>
<td><a href="zip-0316#address-expiration-metadata">ZIP 316: Unified Addresses and Unified Viewing Keys — Address Expiration Metadata</a></td>
</tr>
</tbody>
@ -303,7 +185,7 @@ expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
<table id="protocol-networks" class="footnote">
<tbody>
<tr>
<th>13</th>
<th>10</th>
<td><a href="protocol/protocol.pdf#networks">Zcash Protocol Specification, Version 2023.4.0. Section 3.12: Mainnet and Testnet</a></td>
</tr>
</tbody>
@ -311,7 +193,7 @@ expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
<table id="protocol-transparentaddrencoding" class="footnote">
<tbody>
<tr>
<th>14</th>
<th>11</th>
<td><a href="protocol/protocol.pdf#transparentaddrencoding">Zcash Protocol Specification, Version 2023.4.0. Section 5.6.1.1 Transparent Addresses</a></td>
</tr>
</tbody>
@ -319,7 +201,7 @@ expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
<table id="binance-address-expiry" class="footnote">
<tbody>
<tr>
<th>15</th>
<th>12</th>
<td><a href="https://forum.zcashcommunity.com/t/unified-address-expiration/46564/6">Zcash Community Forum post describing motivations for address expiry</a></td>
</tr>
</tbody>
@ -327,35 +209,27 @@ expiry time: Mon Feb 13 2024 01:14:18 GMT</pre>
<table id="base58check" class="footnote">
<tbody>
<tr>
<th>16</th>
<th>13</th>
<td><a href="https://en.bitcoin.it/wiki/Base58Check_encoding">Base58Check encoding — Bitcoin Wiki</a></td>
</tr>
</tbody>
</table>
<table id="f4jumble" class="footnote">
<table id="bip-0044" class="footnote">
<tbody>
<tr>
<th>17</th>
<td><a href="zip-0316#jumbling">ZIP 316: Unified Addresses and Unified Viewing Keys — Jumbling</a></td>
<th>14</th>
<td><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a></td>
</tr>
</tbody>
</table>
<table id="bip-0350" class="footnote">
<tbody>
<tr>
<th>18</th>
<th>15</th>
<td><a href="https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki">BIP 350: Bech32m format for v1+ witness addresses</a></td>
</tr>
</tbody>
</table>
<table id="zcash-address-wasm" class="footnote">
<tbody>
<tr>
<th>19</th>
<td><a href="https://github.com/nuttycom/zcash_address_wasm">zcash_address_wasm: Proof-of-concept library for Traceable Unified Address Encoding</a></td>
</tr>
</tbody>
</table>
</section>
</section>
</body>

View File

@ -5,13 +5,15 @@
Owners: Daira-Emma Hopwood <daira@electriccoin.co>
Kris Nuttycombe <kris@nutty.land>
Credits: Hanh
Status: Draft
Status: Proposed
Category: Standards / Wallet
Created: 2024-01-12
License: MIT
Discussions-To: <https://github.com/zcash/zips/issues/757>
<https://github.com/zcash/zips/issues/795>
Pull-Request: <https://github.com/zcash/zips/pull/760>
<https://github.com/zcash/zips/pull/766>
<https://github.com/zcash/zips/pull/798>
Terminology
@ -21,15 +23,14 @@ The key words "MUST", "SHOULD", "NOT RECOMMENDED", and "MAY" in this document
are to be interpreted as described in BCP 14 [#BCP14]_ when, and only when,
they appear in all capitals.
The terms "Recipient", "Producer", "Consumer", "Sender", "Receiver", "Item",
"Metadata Item", "Typecode", "Address", "Unified Address" (UA), "Unified
Viewing Key" (UVK), "Unified Full Viewing Key" (UFVK), and "Unified Incoming
Viewing Key" (UIVK) are to be interpreted as described in ZIP 316
The terms "Recipient", "Producer", "Consumer", "Sender", "Receiver", "Address",
and "Unified Address" are to be interpreted as described in ZIP 316
[#zip-0316-terminology]_.
The terms "Testnet" and "Mainnet" are to be interpreted as described in section
3.12 of the Zcash Protocol Specification [#protocol-networks]_.
Abstract
========
@ -37,14 +38,11 @@ This ZIP defines a new encoding for transparent Zcash addresses. Wallets must
ensure that no shielded notes are spent in transactions that send to a
transparent address encoded in the specified fashion.
This ZIP is presently in Draft status, and defines two alternate encodings for
consideration. Analysis of the benefits and drawbacks of each of the proposed
alternatives is presented at the end of this document.
Background
==========
In November of 2023, the Zcash community received notice from the Binance
In November 2023, the Zcash community received notice from the Binance
cryptocurrency exchange that Zcash was at risk of being delisted from the
exchange unless the community could provide a mechanism by which Binance could
refuse deposits from shielded addresses and return them to the depositor. This
@ -56,7 +54,9 @@ In the course of that discussion thread, wallet developer and community member
that involved defining a new encoding for Zcash transparent P2PKH addresses. A
Consumer of such an address, whether it be a wallet or an exchange, could
recognize this encoding as a directive that the wallet should only spend
transparent funds when creating an output to that address.
transparent funds when creating an output to that address. This ZIP formalizes
that proposal.
Motivation
==========
@ -64,54 +64,73 @@ Motivation
The Binance cryptocurrency exchange requires that funds sent to their deposit
addresses come from source addresses that are readily identifiable using
on-chain information, such that if necessary funds may be rejected by sending
them back to the source address(es). This ZIP is intended to standardize a
transparent address encoding that is not yet understood by preexisting
them back to one of the source addresses. This ZIP is intended to standardize
a transparent address encoding that is not yet understood by preexisting
Consumers, in order to prevent inadvertent shielded spends when sending to such
addresses. Then, Consumers that upgrade to support the new encoding will do so
with the understanding that they must respect the restrictions on sources of
funds described in this ZIP.
It is not expected that other exchanges or Producers of Zcash addresses will
generate Transparent-Source-Only Addresses unless they have a specific need to
be able to identify the address or addresses from which a payment was funded.
However, all Consumers of Zcash addresses should implement this specification,
in order to promote interoperability across the Zcash ecosystem.
Requirements
============
1. A Recipient wishing to receive funds from exclusively transparent sources
must be able to generate a receiving address such that only transparent
funds will be spent in transactions with an output to this address.
funds will be spent in transactions with an output to this address. The
purpose of this is to ensure that it is reliably possible for the Recipient
to send back funds received from a Sender that conforms to this ZIP.
2. Wallets and other Consumers that have not been upgraded to recognize the new
address format cannot mistake the address for another address type or
inadvertently send shielded funds to the address.
3. No changes to Recipient infrastructure beyond changes to address encoding
and decoding should be required as a consequence of this ZIP.
and decoding should be required as a consequence of this ZIP. In particular,
conversion between a Transparent-Source-Only Address and the corresponding
unrestricted transparent address should be possible using only dependencies
that are available to Binance's front-end code.
Alternative 1
Non-requirements
================
1. It is only required to support a Transparent-Source-Only form of P2PKH
addresses; P2SH address support is not necessary.
2. It is not required to limit the source of transparent funds sent to a
Transparent-Source-Only Address to a single source address. This implies that
if the Recipient chooses to send back the funds, it is acceptable for it to
send them back to any of the source addresses if there is more than one.
3. It is not necessary for the restriction on the source of funds to be enforced
as a consensus rule. If a Sender fails to adhere to the restriction, it risks
loss of funds, which is acceptable in the case of a non-conforming Sender
implementation.
Specification
=============
This alternative was suggested by @hanh in [#hanh-suggestion]_.
A TEX Address, also called a Transparent-Source-Only Address, is a Bech32m [#bip-0350]_
reencoding of a transparent Zcash P2PKH address [#protocol-transparentaddrencoding]_.
TEX Addresses
-------------
Wallets and other Senders sending to a TEX address (as any output) MUST ensure that
only transparent (P2SH or P2PKH) UTXOs are spent in the creation of the transaction.
For simplicity of parsing and interpreting such transactions, they also SHOULD only
send to transparent outputs.
A TEX Address is a Bech32m [#bip-0350]_ reencoding of a transparent Zcash
P2PKH address [#protocol-transparentaddrencoding]_.
Motivations for Alternative 1
-----------------------------
The TEX Address is the simplest possible approach to creating a new address
type that indicates that only transparent sources of funds should be used.
Specification (Alternative 1)
-----------------------------
A TEX address is produced from a Mainnet Zcash P2PKH Address by executing the
A TEX address can be produced from a Mainnet Zcash P2PKH Address by executing the
following steps:
1. Decode the address to a byte sequence using the Base58Check decoding
algorithm [#Base58Check]_.
2. If the length of the resulting byte sequence is not 22 bytes or if its two-byte
address prefix is not :math:`[\mathtt{0x1C}, \mathtt{0xB8}]`, return an error. Otherwise,
let the **validating key hash** be the remaining 20 bytes of the sequence after
removing the two-byte address prefix.
address prefix is not :math:`[\mathtt{0x1C}, \mathtt{0xB8}]`, return an error.
Otherwise, let the **validating key hash** be the remaining 20 bytes of the
sequence after removing the two-byte address prefix.
3. Reencode the 20-byte **validating key hash** using the Bech32m encoding
defined in [#bip-0350]_ with the human-readable prefix (HRP) ``"tex"``.
@ -119,12 +138,48 @@ For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are
:math:`[\mathtt{0x1D}, \mathtt{0x25}]`, and the ``"textest"`` HRP is used when
reencoding in step 3.
Wallets and other Senders sending to a TEX address (as any output) MUST
ensure that only transparent UTXOs are spent in the creation of a
transaction.
A TEX address can be parsed by reversing this encoding, i.e.:
Reference Implementation (Alternative 1)
----------------------------------------
1. Decode the address to a byte sequence using Bech32m [#bip-0350]_, checking
that the HRP is ``"tex"`` for a Mainnet TEX Address and ``"textest"`` for a
Testnet TEX Address.
2. If the length of the resulting byte sequence is not 20 bytes, return an error.
Otherwise, the **validating key hash** is this byte sequence.
Design considerations for Senders
---------------------------------
For a transaction that spends only from transparent funds to a TEX Address,
this specification imposes no additional requirements.
If, on the other hand, a user desires to spend shielded funds to a TEX Address,
a Sender supporting this ZIP MUST create two transactions: one that unshields
the funds to an ephemeral transparent address, and one that spends from that
ephemeral address to the destination TEX Address. This does not defeat the
intent of the ZIP, because it is still possible for a Recipient to return the
funds to the Sender by sending them back to the ephemeral address.
Wallets MUST be able to recognize funds that have been returned in this way
and spend them if desired. In order for this to be possible without use of
TEX Addresses increasing the risk of loss of funds, wallets based on ZIP 32
[#zip-0032]_ SHOULD choose ephemeral addresses in a way that allows the
corresponding private keys to be recovered from a ZIP 32 master seed.
However, ephemeral addresses SHOULD NOT be chosen in a way that allows them
to be linked between transactions, without knowledge of the wallet seed or
the relevant transparent viewing keys. This also implies that they SHOULD be
chosen in a way that avoids collisions with addresses for previously generated
outputs (including change outputs), such as might have been created by a
transparent-only wallet using Bitcoin-derived code based on BIP 44 [#bip-0044]_.
In order to show accurate transaction history to a user, wallets SHOULD
remember when a particular transaction output was sent to a TEX Address, so
that they can show that form rather than its P2PKH form. It is acceptable that
this information may be lost on recovery from seed.
Reference Implementation
========================
Javascript::
@ -147,215 +202,41 @@ Javascript::
var t1 = bs58check.encode(Buffer.concat([Uint8Array.from([0x1C, 0xB8]), pkh2]))
console.log(t1)
Alternative 2
=============
Rationale
=========
Traceable Unified Addresses
---------------------------
TEX addresses are the simplest possible approach to creating a new address type that
indicates that only transparent sources of funds should be used.
A Traceable Unified Address is a reencoding of a transparent Zcash P2PKH
address into a Unified Address [#zip-0316-unified-addresses]_.
As required by Binance, it will be possible to convert between a TEX address and an
unrestricted transparent P2PKH address using extremely straightforward code that
depends only on Base58Check and Bech32m encoding/decoding, as shown in the above
`Reference Implementation`_.
Motivations for Alternative 2
-----------------------------
An earlier version of this ZIP also described another alternative using metadata
in Unified Addresses, as specified in ZIP 316 [#zip-0316]_. That alternative was
designed to enable better integration with the Zcash Unified Address ecosystem, and
had the advantage of being able to combine different types of metadata along with
the Transparent-Source-Only indicator, such as an expiration block height or time
[#zip-0316-address-expiry]_ [#binance-address-expiry]_.
Traceable Unified Addresses fit into the Zcash Unified Address ecosystem
defined by ZIP 316, Revision 1 [#zip-0316-revision-1]_. Existing Consumers of
Unified Addresses will not be able to send to these address unless they update
their code to understand the new MUST-understand Metadata Typecode defined in
this ZIP.
However, ultimately the Unified Address-based approach did not meet all of the
requirements, since it would in practice have required dependencies on address
handling libraries that Binance did not want to depend on in their front-end code.
By integrating with the Unified Address framework, it becomes possible for the
addresses being generated to include extra metadata; in particular, metadata
items such as an Address Expiry Height or Address Expiry Date
[#zip-0316-address-expiry]_ may be included. For exchange use cases such as
Binance's, it is useful to ensure that an address provided to a user has a
limited utility life, such that after expiration the user must obtain a new
address in order to be able to continue to send funds
[#binance-address-expiry]_.
Some design elements of that approach that apply to metadata in general have
been incorporated into ZIP 316 Revision 1 [#zip-0316-revision-1]_. A more general
form of Source Restriction Metadata is also under consideration.
Specification (Alternative 2)
-----------------------------
Disadvantages
-------------
Upon activation of this ZIP, the section `Metadata Items` of ZIP 316
[#zip-0316-metadata-items]_ will be modified to define a new MUST-understand
Metadata Item type: Source Restriction Metadata, having Typecode
:math:`\mathtt{0xE2}`, the value of which MUST be a single byte:
A disadvantage of TEX Addresses (and also of the alternative approach using
Unified Addresses) is that the information that a TEX Address was used does not
appear on-chain, i.e. a transaction sending to a TEX Address is indistinguishable
from one sending to the underlying P2PKH address. This is inevitable given the
desire not to change the underlying consensus protocol to support this functionality.
* :math:`\mathtt{0x00}` - Transparent Source Only
Additional Source Restriction Metadata values can be defined in the future,
but a Consumer that does not recognise the value MUST reject the entire
UA/UVK as invalid.
Wallets and other Senders MUST ensure that only transparent UTXOs are spent in
the creation of a transaction to any Unified Address containing a Source
Restriction Metadata Item having value :math:`\mathtt{0x00}`.
A Traceable Unified Address is produced from a Mainnet Zcash P2PKH address by
executing the following steps:
1. Decode the address to a byte sequence using the Base58Check decoding
algorithm [#Base58Check]_.
2. If the length of the resulting byte sequence is not 22 bytes or if its
two-byte address prefix is not :math:`[\mathtt{0x1C}, \mathtt{0xB8}]`,
return an error. Otherwise, let the **validating key hash** be the remaining
20 bytes of the array after removing the two-byte address prefix.
3. Construct a new Revision 1 Unified Address using a single P2PKH Receiver
:math:`\mathtt{0x04}` with the 20-byte **validating key hash** as its value,
and a Source Restriction Metadata Item (Typecode :math:`\mathtt{0xE2}`)
having value :math:`\mathtt{0x00}` (Transparent Source Only). In addition,
metadata items such as an Address Expiry Height or Address Expiry Date
[#zip-0316-address-expiry]_ MAY be included.
4. Encode the Unified Address using the “``ur``” Human Readable Part as
specified for Revision 1 of ZIP 316 [#zip-0316-revision-1]_.
For Testnet addresses, the required lead bytes of a P2PKH address in step 2
are :math:`[\mathtt{0x1D}, \mathtt{0x25}]`.
The HRP of the resulting Unified Address is the same as for any other Revision 1
Unified Address on the relevant network as specified in [#zip-0316-revision-1]_,
i.e. ``"ur"`` for Mainnet and ``"urtest"`` for Testnet.
Any Source Restriction Metadata Item MUST be preserved with the same value
when deriving a UIVK from a UFVK, or a UA from a UIVK. It has no other effect
on the meaning of the UFVK or UIVK.
Note that it is possible for a Unified Address to include shielded Receivers
and also Source Restriction Metadata with value Transparent Source Only. The
semantics of such UAs are well defined: they allow a shielding transaction
that only spends transparent UTXOs when sending to a shielded Receiver, and
the priority order of Receivers defined by ZIP 316 is unaffected. However,
this combination of requirements might result in wallet interoperability
issues, and so producing such UAs is NOT RECOMMENDED.
Dependencies on Revision 1 of ZIP 316
'''''''''''''''''''''''''''''''''''''
This specification depends upon the following changes made for Revision 1 of
ZIP 316 [#zip-0316-revision-1]_:
* A Revision 1 UA/UVK is *not* required to include a shielded Item. This is
necessary for a Traceable Unified Address containing only a P2PKH Receiver
to be valid. (It also has other independent motivations, as explained in
[#zip-0316-drop-shielded-restriction]_.)
* The change to the HRPs for Revision 1 UAs implies that a Sender implementing
the Revision 0 specification will not recognize the UA as valid, which is
necessary because it may not understand the Source Restriction Metadata.
* A Consumer of a Revision 1 UIVK or UFVK is required to retain the Source
Restriction Metadata when deriving a UA or UIVK respectively.
Reference Implementation (Alternative 2)
----------------------------------------
Javascript using `zcash_address_wasm` [#zcash_address_wasm]_::
import init, { to_traceable_address, traceable_to_p2pkh, addr_expiry_time } from 'zcash_address_wasm';
init().then(() => {
var t_address = "t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC";
console.log("original P2PKH address: " + t_address);
var expiry_time = new Date();
// Add 30 days in UTC.
expiry_time.setUTCDate(expiry_time.getUTCDate() + 30);
// Date.getTime() returns UTC time since 1970-01-01T00:00:00Z in milliseconds.
var expiry_unix_seconds = BigInt(Math.floor(expiry_time.getTime() / 1000));
var traceable_address = to_traceable_address(t_address, expiry_unix_seconds);
console.log("Traceable Unified Address: " + traceable_address);
var p2pkh_addr = traceable_to_p2pkh(traceable_address);
console.log("decoded P2PKH address: " + p2pkh_addr);
var expiry = addr_expiry_time(traceable_address);
// Ignore far-future expiry times not representable as a Date.
if (expiry !== null && expiry <= 8_640_000_000_000n) {
console.log("expiry time: " + new Date(Number(expiry) * 1000).toUTCString());
}
});
Example output::
original P2PKH address: t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC
Traceable Unified Address: u1p3temdfuxr6vcfr2z3n5weh652rg0hv7q44c652y3su77d0pyktt47am3tng7uxxtk553hhka75r6cvfs5j
decoded P2PKH address: t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC
expiry time: Mon Feb 13 2024 01:14:18 GMT
Analysis of Alternative 1
=========================
Pros to Alternative 1
---------------------
- The reencoding from Zcash P2PKH addresses is extremely straightforward and
relies only upon widely available encoding libraries.
Cons to Alternative 1
---------------------
- Existing wallets and other Consumers will regard the new address type as
entirely invalid, and will not automatically prompt their users that they
need to upgrade in order to send to this type of address.
- Creation of a new fully distinct address type further fragments the Zcash
address ecosystem. Avoiding such fragmentation and providing smooth upgrade
paths and good error messages to users is exactly the problem that Unified
Addresses [#zip-0316-motivation]_ were intended to avoid.
- The TEX address type does not provide any mechanism for address expiration.
One of the questions Binance has asked has been what to do about users who
have stored their existing transparent deposit address in their wallets, or
use them as a withdrawal address for other exchanges or services. This is a
challenging problem to mitigate now because address expiration was not
previously implemented. We should not further compound this problem by
defining a new distinct address type that does not provide a mechanism for
address expiry.
Analysis of Alternative 2
=========================
Pros To Alternative 2
---------------------
- By integrating with the Unified Address framework, Consumers of Revision 1
Unified Addresses that have not yet been upgraded to recognize these
addresses can automatically be prompted to upgrade their wallets or services
to understand the unrecognized MUST-understand Metadata Typecode.
- It is possible to include address expiration metadata in a Traceable Unified
Address, which can help to mitigate problems related to stored addresses in
the future.
- The Source Restriction Metadata feature can easily be extended to express
other kinds of source restriction, such as "Shielded Source Only" or
"Fully Shielded with No Pool Crossing".
- Traceable Unified Addresses benefit from the robustness to errors and
protection against malleation of Unified Addresses [#F4Jumble]_.
- Regardless of which proposal is adopted, the Zcash Community will need to
work with exchanges other than Binance to update their address parsing logic
to understand the new address format. By encouraging Consumers such as
exchanges to adopt parsing for Unified Addresses, this proposal furthers the
original goal of Unified Addresses to reduce fragmentation in the address
ecosystem.
Whenever any new feature is added, wallets have a choice whether or not to
support that new feature. The point of Unified Address parsing is that
wallets dont have to upgrade to recognize a different address format as a
valid Zcash address. Instead of returning a “Not a valid Zcash address”
error, which could be confusing for users, they can return an error more like
“This is a valid Zcash address, but this wallet does not support sending to
it.” This can be used as a prompt to upgrade the wallet to a version (or
alternative) that does support that feature.
Cons to Alternative 2
---------------------
- Existing wallets and other Consumers of Revision 0 Unified Addresses will
regard the new address type as entirely invalid, and will not automatically
prompt their users that they need to upgrade in order to send to this type of
address.
- Unified Address encoding is slightly more complex than the proposed TEX
address encoding, and requires use of the F4Jumble encoding algorithm
[#F4Jumble]_. However, this can be readily mitigated by providing a
purpose-built library for Traceable Unified Address encoding to Producers.
- A Traceable Unified Address is somewhat longer than a TEX address, although
not excessively so.
References
==========
@ -364,18 +245,14 @@ References
.. [#binance-delisting] `Zcash Community Forum thread "Important: Potential Binance Delisting" <https://forum.zcashcommunity.com/t/important-potential-binance-delisting/45954>`_
.. [#hanh-profile] `Zcash Community Forum user @hanh <https://forum.zcashcommunity.com/u/hanh/summary>`_
.. [#hanh-suggestion] `Ywallet developer @hanh's proposal <https://forum.zcashcommunity.com/t/important-potential-binance-delisting/45954/112>`_
.. [#zip-0032] `ZIP 32: Shielded Hierarchical Deterministic Wallets <zip-0032.rst>`_
.. [#zip-0316] `ZIP 316: Unified Addresses and Unified Viewing Keys <zip-0316.rst>`_
.. [#zip-0316-terminology] `ZIP 316: Unified Addresses and Unified Viewing Keys — Terminology <zip-0316#terminology>`_
.. [#zip-0316-motivation] `ZIP 316: Unified Addresses and Unified Viewing Keys — Motivation <zip-0316#motivation>`_
.. [#zip-0316-revision-1] `ZIP 316: Unified Addresses and Unified Viewing Keys — Revision 1 <zip-0316#revision-1>`_
.. [#zip-0316-unified-addresses] `ZIP 316: Unified Addresses and Unified Viewing Keys — Encoding of Unified Addresses <zip-0316#encoding-of-unified-addresses>`_
.. [#zip-0316-unified-requirements] `ZIP 316: Unified Addresses and Unified Viewing Keys — Requirements for both Unified Addresses and Unified Viewing Keys <zip-0316#requirements-for-both-unified-addresses-and-unified-viewing-keys>`_
.. [#zip-0316-drop-shielded-restriction] `ZIP 316: Unified Addresses and Unified Viewing Keys — Rationale for dropping the "at least one shielded Item" restriction <zip-0316#rationale-for-dropping-the-at-least-one-shielded-item-restriction>`_
.. [#zip-0316-metadata-items] `ZIP 316: Unified Addresses and Unified Viewing Keys — Metadata Items <zip-0316#metadata-items>`_
.. [#zip-0316-address-expiry] `ZIP 316: Unified Addresses and Unified Viewing Keys — Address Expiration Metadata <zip-0316#address-expiration-metadata>`_
.. [#protocol-networks] `Zcash Protocol Specification, Version 2023.4.0. Section 3.12: Mainnet and Testnet <protocol/protocol.pdf#networks>`_
.. [#protocol-transparentaddrencoding] `Zcash Protocol Specification, Version 2023.4.0. Section 5.6.1.1 Transparent Addresses <protocol/protocol.pdf#transparentaddrencoding>`_
.. [#binance-address-expiry] `Zcash Community Forum post describing motivations for address expiry <https://forum.zcashcommunity.com/t/unified-address-expiration/46564/6>`_
.. [#Base58Check] `Base58Check encoding — Bitcoin Wiki <https://en.bitcoin.it/wiki/Base58Check_encoding>`_
.. [#F4Jumble] `ZIP 316: Unified Addresses and Unified Viewing Keys — Jumbling <zip-0316#jumbling>`_
.. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki>`_
.. [#bip-0350] `BIP 350: Bech32m format for v1+ witness addresses <https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki>`_
.. [#zcash_address_wasm] `zcash_address_wasm: Proof-of-concept library for Traceable Unified Address Encoding <https://github.com/nuttycom/zcash_address_wasm>`_