Markdown didn't work out for ZIPs, try HTML.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2019-08-06 01:05:27 +01:00
parent 1e0a45b9ba
commit 4ee74f4322
35 changed files with 3747 additions and 6157 deletions

View File

@ -1,4 +1,7 @@
%.md: %.rst
pandoc -s -o $@ $<
default: $(addsuffix .md,$(basename $(wildcard *.rst)))
%.html: %.rst
pandoc -s -o $@ $<
default: $(addsuffix .html,$(basename $(wildcard *.rst)))

224
zip-0000.html Normal file
View File

@ -0,0 +1,224 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0000</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 0
Title: ZIP Process
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Josh Cincinnati &lt;josh@zfnd.org&gt;
Status: Active
Category: Process
Created: 2019-02-16
License: BSD-2-Clause</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;MAY&quot;, &quot;RECOMMENDED&quot;, &quot;OPTIONAL&quot;, and &quot;REQUIRED&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The term &quot;network upgrade&quot; in this document is to be interpreted as described in ZIP 200.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<h1 id="abstract">Abstract</h1>
<p>A Zcash Improvement Proposal (ZIP) is a design document providing information to the Zcash community, or describing a new feature for Zcash or its processes or environment. The ZIP should provide a concise technical specification of the feature and a rationale for the feature.</p>
<p>We intend ZIPs to be the primary mechanism for proposing new features, for collecting community input on an issue, and for documenting the design decisions that have gone into Zcash. The Owner(s) of the ZIP (usually the authors(s)) are responsible for building consensus within the community and documenting dissenting opinions.</p>
<p>Because the ZIPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal.</p>
<p>This document is based on the work done by Luke Dashjr with <a href="https://github.com/bitcoin/bips">BIP 2</a> and Daira Hopwood with <a href="https://github.com/daira/zips/tree/master/drafts/daira-zip-process">Draft ZIP 0</a>.</p>
<h1 id="zip-workflow">ZIP Workflow</h1>
<p>The ZIP process begins with a new idea for Zcash. Each potential ZIP must have a Owner -- someone who writes the ZIP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. The ZIP Owner should first attempt to ascertain whether the idea is ZIP-able. Small enhancements or patches to a particular piece of software often don't require standardisation between multiple projects; these don't need a ZIP and should be injected into the relevant project-specific development workflow with a patch submission to the applicable issue tracker. Additionally, many ideas have been brought forward for changing Zcash that have been rejected for various reasons. The first step should be to search past discussions to see if an idea has been considered before, and if so, what issues arose in its progression. After investigating past work, the best way to proceed is by posting about the new idea to the <a href="https://forum.zcashcommunity.com/">Zcash Community Forum</a>.</p>
<p>Vetting an idea publicly before going as far as writing a ZIP is meant to save both the potential Owner and the wider community time. Asking the Zcash community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the Owner. Just because an idea sounds good to the Owner does not mean it will work for most people in most areas where Zcash is used.</p>
<p>Once the Owner has asked the Zcash community as to whether an idea has any chance of acceptance, a draft ZIP should be presented to the <a href="https://forum.zcashcommunity.com/">Zcash Community Forum</a>. This gives the Owner a chance to flesh out the draft ZIP to make it properly formatted, of high quality, and to address additional concerns about the proposal. Following a discussion, the proposal should be submitted to the <a href="https://github.com/zcash/zips">ZIPs git repository</a> as a pull request. This draft must be written in ZIP style as described below, and named with an alias such as <code>zip-zatoshizakamoto-42millionzec</code> until the ZIP Editors have assigned it a ZIP number (Owners MUST NOT self-assign ZIP numbers).</p>
<p>ZIP Owners are responsible for collecting community feedback on both the initial idea and the ZIP before submitting it for review. However, wherever possible, long open-ended discussions on forums should be avoided.</p>
<p>It is highly recommended that a single ZIP contain a single key proposal or new idea. The more focused the ZIP, the more successful it tends to be. If in doubt, split your ZIP into several well-focused ones.</p>
<p>When the ZIP draft is complete, the ZIP Editors will assign the ZIP a number, label it as Standards Track, Informational, or Process, and merge the pull request to the ZIPs git repository. The ZIP Editors will not unreasonably reject a ZIP. Reasons for rejecting ZIPs include duplication of effort, disregard for formatting rules, being too unfocused or too broad, being technically unsound, not providing proper motivation or not in keeping with the Zcash philosophy. For a ZIP to be accepted it must meet certain minimum criteria. It must be a clear and complete description of the proposed enhancement. The enhancement must represent a net improvement. The proposed implementation, if applicable, must be solid and must not complicate the protocol unduly.</p>
<p>The ZIP Owner may update the draft as necessary in the git repository. Updates to drafts should also be submitted by the Owner as pull requests.</p>
<h2 id="transferring-zip-ownership">Transferring ZIP Ownership</h2>
<p>It occasionally becomes necessary to transfer ownership of ZIPs to a new Owner. In general, we'd like to retain the original Owner as a co-Owner of the transferred ZIP, but that's really up to the original Owner. A good reason to transfer ownership is because the original Owner no longer has the time or interest in updating it or following through with the ZIP process, or has fallen off the face of the 'net (i.e. is unreachable or not responding to email). A bad reason to transfer ownership is because you don't agree with the direction of the ZIP. We try to build consensus around a ZIP, but if that's not possible, you can always submit a competing ZIP.</p>
<p>If you are interested in assuming ownership of a ZIP, send a message asking to take over, addressed to both the original Owner and the ZIP Editors. If the original Owner doesn't respond to email in a timely manner, the ZIP Editors will make a unilateral decision (it's not like such decisions can't be reversed :).</p>
<p>If an author of a ZIP is no longer an Owner, an Original-Authors field SHOULD be added to the ZIP metadata indicating the original authorship, unless the original author(s) request otherwise.</p>
<h2 id="zip-editors">ZIP Editors</h2>
<p>The current ZIP Editors are Daira Hopwood, representing the Electric Coin Company, and Josh Cincinnati, representing the Zcash Foundation. Both can be reached at <a href="mailto:zips@z.cash">zips@z.cash</a> . The current design of the ZIP Process dictates that there are always at least two ZIP Editors: one from the Electric Coin Company and one from the Zcash Foundation. Additional Editors may be selected by consensus among the current Editors.</p>
<h2 id="zip-editor-responsibilities-workflow">ZIP Editor Responsibilities &amp; Workflow</h2>
<p>The ZIP Editors subscribe to the <a href="https://forum.zcashcommunity.com/">Zcash Community Forum.</a></p>
<p>For each new ZIP that comes in an Editor confirms the following:</p>
<ul>
<li>Read the ZIP to check if it is ready: sound and complete. The ideas must make technical sense, even if they don't seem likely to be accepted.</li>
<li>The title should accurately describe the content.</li>
<li>The ZIP draft must have been sent to the Zcash Community Forum or as a PR to the <a href="https://github.com/zcash/zips">ZIPs git repository</a></li>
<li>Motivation and backward compatibility (when applicable) must be addressed.</li>
<li>The licensing terms are acceptable for ZIPs.</li>
</ul>
<p>If the ZIP isn't ready, the editor will send it back to the Owner for revision, with specific instructions.</p>
<p>Once the ZIP is ready for the repository it should be submitted as a &quot;pull request&quot; to the <a href="https://github.com/zcash/zips">ZIPs git repository</a> where it may get further feedback. It should not contain a ZIP number, and should be labelled &quot;WIP&quot; in the pull request.</p>
<p>The ZIP Editors will:</p>
<ul>
<li>Assign a ZIP number in the pull request.</li>
<li>Merge the pull request when it is ready and remove the &quot;WIP&quot; label.</li>
</ul>
<p>The ZIP editors monitor ZIP changes and update ZIP headers as appropriate.</p>
<p>The ZIP Editors MAY reject a proposed ZIP or update to an existing ZIP for any of the following reasons:</p>
<ul>
<li>it violates the Zcash Code of Conduct<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a> ;</li>
<li>it appears too unfocused or broad;</li>
<li>it duplicates effort in other ZIPs without sufficient technical justification (however, alternative proposals to address similar or overlapping problems are not excluded for this reason);</li>
<li>it has manifest security flaws (including being unrealistically dependent on user vigilance to avoid security weaknesses);</li>
<li>it disregards compatibility with the existing Zcash blockchain or ecosystem;</li>
<li>it is manifestly unimplementable;</li>
<li>it includes buggy code, pseudocode, or algorithms;</li>
<li>it manifestly violates common expectations of a significant portion of the Zcash community;</li>
<li>it updates a Draft ZIP to Released when there is significant community opposition to its content (however, Draft ZIPs explicitly may describe proposals to which there is, or could be expected, significant community opposition);</li>
<li>in the case of a Released ZIP, the update makes a substantive change to which there is significant community opposition;</li>
<li>it is dependent on a patent that could potentially be an obstacle to adoption of the ZIP;</li>
<li>it includes commercial advertising or spam;</li>
<li>it disregards formatting rules;</li>
<li>it makes non-editorial edits to previous entries in a ZIP's Change history;</li>
<li>an update to an existing ZIP extends or changes its scope to an extent that would be better handled as a separate ZIP;</li>
<li>a new ZIP has been proposed for a category that does not reflect its content, or an update would change a ZIP to an inappropriate category;</li>
<li>it updates a Released ZIP to Draft when the specification is already implemented and has been in common use;</li>
<li>it violates any specific &quot;MUST&quot; or &quot;MUST NOT&quot; rule in this document;</li>
<li>the expressed political views of a Owner of the document are inimical to the Zcash Code of Conduct<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> (except in the case of an update removing that Owner);</li>
<li>it is not authorized by the stated ZIP Owners;</li>
<li>it removes an Owner without their consent (unless the reason for removal is directly related to a breach of the Code of Conduct by that Owner).</li>
</ul>
<p>The ZIP Editors MUST NOT unreasonably deny publication of a ZIP proposal or update that does not violate any of these criteria. If they refuse a proposal or update, they MUST give an explanation of which of the criteria were violated, with the exception that spam may be deleted without an explanation.</p>
<p>Note that it is not the primary responsibility of the ZIP Editors to review proposals for security, correctness, or implementability.</p>
<p>Please send all ZIP-related communications either by email to &lt;<a href="mailto:zips@z.cash">zips@z.cash</a>&gt;, or by opening an issue on the <a href="https://github.com/zcash/zips/issues">ZIPs issue tracker</a>. All communications should abide by the Zcash Code of Conduct<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a> and follow <a href="https://www.gnu.org/philosophy/kind-communication.en.html">the GNU Kind Communication Guidelines</a></p>
<h1 id="zip-format-and-structure">ZIP format and structure</h1>
<p>ZIPs SHOULD be written either in reStructuredText<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a> or LaTeX<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a>. In the latter case, a Makefile MUST be provided to build (at least) a PDF version of the document.</p>
<p>Each ZIP SHOULD have the following parts:</p>
<ul>
<li>Preamble -- Headers containing metadata about the ZIP (<a href="#zip-header-preamble">see below</a>). The License field of the preamble indicates the licensing terms, which MUST be acceptable according to <a href="#zip-licensing">the ZIP licensing requirements</a>.</li>
<li>Terminology -- Definitions of technical or non-obvious terms used in the document.</li>
<li>Abstract -- A short (~200 word) description of the technical issue being addressed.</li>
<li>Motivation -- The motivation is critical for ZIPs that want to change the Zcash protocol. It should clearly explain why the existing protocol is inadequate to address the problem that the ZIP solves.</li>
<li>Specification -- The technical specification should describe the interface and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Zcash platforms.</li>
<li>Rationale -- The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion.</li>
<li>Security and privacy considerations -- If applicable, security and privacy considerations should be explicitly described, particularly if the ZIP makes explicit trade-offs or assumptions. For guidance on this section consider <a href="https://tools.ietf.org/html/rfc3552">RFC 3552</a>. as a starting point.</li>
<li>Reference implementation -- Literal code implementing the ZIP's specification, and/or a link to the reference implementation of the ZIP's specification. The reference implementation must be completed before any ZIP is given status “Implemented” or “Final”, but it generally need not be completed before the ZIP is accepted into “Proposed”.</li>
</ul>
<h2 id="zip-header-preamble">ZIP header preamble</h2>
<p>Each ZIP must begin with an RFC 822-style header preamble. The following header fields are REQUIRED:</p>
<pre><code> ZIP:
 Title:
 Owners:
 Status:
 Category:
Created:
 License:</code></pre>
<p>The following additional header fields are OPTIONAL:</p>
<pre><code>Credits:
Original-Authors:</code></pre>
<blockquote>
<p> Discussions-To:  Network Upgrade: Obsoleted by: Updated by: Obsoletes: Updates:</p>
</blockquote>
<p>The Owners header lists the names and email addresses of all the Owners of the ZIP. The format of the Owners header value SHOULD be:</p>
<pre><code>Random J. User &lt;address@dom.ain&gt;</code></pre>
<p>If there are multiple Owners, each should be on a separate line.</p>
<p>While a ZIP is in private discussions (usually during the initial Draft phase), a Discussions-To header will indicate the URL where the ZIP is being discussed. No Discussions-To header is necessary if the ZIP is being discussed privately with the Owner.</p>
<p>The Category header specifies the type of ZIP: Consensus, Standards Track, Informational, or Process.</p>
<p>The Created header records the date that the ZIP was submitted. Dates should be in yyyy-mm-dd format, e.g. 2001-08-14.</p>
<h2 id="auxiliary-files">Auxiliary Files</h2>
<p>ZIPs may include auxiliary files such as diagrams. Auxiliary files should be included in a subdirectory for that ZIP; that is, for any ZIP that requires more than one file, all of the files SHOULD be in a subdirectory named zip-XXXX.</p>
<h1 id="zip-categories">ZIP categories</h1>
<p>There are several kinds of ZIP:</p>
<ul>
<li>A Consensus ZIP describes a change that affects the consensus protocol followed by all Zcash implementations.</li>
<li>A Standards Track ZIP describes any non-consensus change that affects most or all Zcash implementations, such as a change to the network protocol, or any change or addition that affects the interoperability of applications using Zcash.</li>
</ul>
<p>Consensus and Standards Track ZIPs consist of two parts: a design document and a reference implementation.</p>
<ul>
<li>An Informational ZIP describes Zcash design issues, or general guidelines or information for the Zcash community, that do not fall into either of the above categories. Informational ZIPs do not necessarily represent a Zcash community consensus or recommendation, so users and implementers are free to ignore Informational ZIPs or follow their advice.</li>
<li>A Process ZIP describes a process surrounding Zcash, or proposes a change to (or an event in) a process. Process ZIPs are like Standards Track ZIPs but apply to areas other than the Zcash protocol itself. They may propose an implementation, but not to Zcash's codebase; they often require community consensus; unlike Informational ZIPs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Zcash development.</li>
</ul>
<p>New categories may be added by consensus among the ZIP Editors.</p>
<h1 id="zip-status-field">ZIP Status Field</h1>
<ul>
<li>Draft: All initial ZIP submissions have this status.</li>
<li>Withdrawn: If the Owner decides to remove the ZIP from consideration by the community, they may set the status to Withdrawn.</li>
<li>Active: Typically only used for Process/Informational ZIPs, achieved once rough consensus is reached in PR/forum posts from Draft Process ZIP.</li>
<li>Proposed: Typically the stage after Draft, added to a ZIP after consideration, feedback, and rough consensus from the community. The ZIP Editors must validate this change before it is approved.</li>
<li>Rejected: The status when progress hasn't been made on the ZIP in one year. Can revert back to Draft/Proposed if the Owner resumes work or resolves issues preventing consensus.</li>
<li>Implemented: When a Consensus or Standards Track ZIP has a working reference implementation but before activation on the Zcash network.</li>
<li>Final: When a Consensus or Standards Track ZIP is both implemented and activated on the Zcash network.</li>
<li>Obsolete: The status when a ZIP is no longer relevant (typically when superseded by another ZIP).</li>
</ul>
<p>More details on the status workflow in the section below.</p>
<h2 id="specification">Specification</h2>
<p>Owners of a ZIP may decide on their own to change the status between Draft or Withdrawn.</p>
<p>A ZIP may only change status from Draft (or Rejected) to Proposed, when the Owner deems it is complete and there is rough consensus on the forums, validated by both the Electric Coin Company and Zcash Foundation Editors. One Editor will not suffice -- there needs to be consensus among the Editors. If it's a Standards Track ZIP, upon changing status to Proposed the Editors will add the optional <code>Network Upgrade</code> header to the preamble, indicating the intent for the ZIP to be implemented in the specified network upgrade. (All <code>Network Upgrade</code> schedules will be distributed via the Zcash Community Forum by the Editors.)</p>
<p>A Standards Track ZIP may only change status from Proposed to Implemented once the Owner provides an associated reference implementation, typically in the period after the network upgrade's specification freeze but before the implementation audit. If the Owner misses this deadline, the Editors or Owner(s) may choose to update the <code>Network Upgrade</code> header to target another upgrade, at their discretion.</p>
<p>ZIPs should be changed from Draft or Proposed status, to Rejected status, upon request by any person, if they have not made progress in one year. Such a ZIP may be changed to Draft status if the Owner provides revisions that meaningfully address public criticism of the proposal, or to Proposed status if it meets the criteria required as described in the previous paragraph.</p>
<p>A Consensus or Standards Track ZIP becomes Final when its associated network upgrade or other protocol change is activated on Zcash's mainnet.</p>
<p>A Process or Informational ZIP may change status from Draft to Active when it achieves rough consensus on the forum or PR. Such a proposal is said to have rough consensus if it has been open to discussion on the forum or GitHub PR for at least one month, and no person maintains any unaddressed substantiated objections to it. Addressed or obstructive objections may be ignored/overruled by general agreement that they have been sufficiently addressed, but clear reasoning must be given in such circumstances.</p>
<p>When an Active or Final ZIP is no longer relevant, its status may be changed to Obsolete. This change must also be objectively verifiable and/or discussed. Final ZIPs may be updated; the specification is still in force but modified by another specified ZIP or ZIPs (check the optional Updated-by header).</p>
<h1 id="zip-comments">ZIP Comments</h1>
<p>Comments from the community on the ZIP should occur on the Zcash Community Forum and the comment fields of the pull requests in any open ZIPs. Editors will use these sources to judge rough consensus.</p>
<h1 id="zip-licensing">ZIP licensing</h1>
<p>New ZIPs may be accepted with the following licenses. Each new ZIP MUST identify at least one acceptable license in its preamble. Each license MUST be referenced by their respective abbreviation given below.</p>
<p>For example, a preamble might include the following License header:</p>
<pre><code>License: BSD-2-Clause
   GNU-All-Permissive</code></pre>
<p>In this case, the ZIP text is fully licensed under both the OSI-approved BSD 2-clause license as well as the GNU All-Permissive License, and anyone may modify and redistribute the text provided they comply with the terms of <em>either</em> license. In other words, the license list is an &quot;OR choice&quot;, not an &quot;AND also&quot; requirement.</p>
<p>It is also possible to license source code differently from the ZIP text. This case SHOULD be indicated in the Reference Implementation section of the ZIP. Again, each license MUST be referenced by its respective abbreviation given below.</p>
<p>Statements of code licenses in ZIPs are only advisory; anyone intending to use the code should look for license statements in the code itself.</p>
<p>ZIPs are not required to be <em>exclusively</em> licensed under approved terms, and MAY also be licensed under unacceptable licenses <em>in addition to</em> at least one acceptable license. In this case, only the acceptable license(s) should be listed in the License header.</p>
<h2 id="recommended-licenses">Recommended licenses</h2>
<ul>
<li>MIT: <a href="https://opensource.org/licenses/MIT">Expat/MIT/X11 license</a></li>
<li>BSD-2-Clause: <a href="https://opensource.org/licenses/BSD-2-Clause">OSI-approved BSD 2-clause license</a></li>
<li>BSD-3-Clause: <a href="https://opensource.org/licenses/BSD-3-Clause">OSI-approved BSD 3-clause license</a></li>
<li>CC0-1.0: <a href="https://creativecommons.org/publicdomain/zero/1.0/">Creative Commons CC0 1.0 Universal</a></li>
<li>GNU-All-Permissive: <a href="http://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html">GNU All-Permissive License</a></li>
<li>Apache-2.0: <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, version 2.0</a></li>
</ul>
<p>In addition, it is RECOMMENDED that literal code included in the ZIP be dual-licensed under the same license terms as the project it modifies. For example, literal code intended for zcashd would ideally be dual-licensed under the MIT license terms as well as one of the above with the rest of the ZIP text.</p>
<h2 id="not-recommended-but-acceptable-licenses">Not recommended, but acceptable licenses</h2>
<ul>
<li>BSL-1.0: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License, version 1.0</a></li>
<li>CC-BY-4.0: <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International</a></li>
<li>CC-BY-SA-4.0: <a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International</a></li>
<li>AGPL-3.0+: <a href="http://www.gnu.org/licenses/agpl-3.0.en.html">GNU Affero General Public License (AGPL), version 3 or newer</a></li>
<li>FDL-1.3: <a href="http://www.gnu.org/licenses/fdl-1.3.en.html">GNU Free Documentation License, version 1.3</a></li>
<li>GPL-2.0+: <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU General Public License (GPL), version 2 or newer</a></li>
<li>LGPL-2.1+: <a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html">GNU Lesser General Public License (LGPL), version 2.1 or newer</a></li>
</ul>
<h2 id="not-acceptable-licenses">Not acceptable licenses</h2>
<p>All licenses not explicitly included in the above lists are not acceptable terms for a Zcash Improvement Proposal.</p>
<h2 id="rationale">Rationale</h2>
<p>Bitcoin's BIP 1 allowed the Open Publication License or releasing into the public domain; was this insufficient?</p>
<ul>
<li>The OPL is generally regarded as obsolete, and not a license suitable for new publications.</li>
<li>The OPL license terms allowed for the author to prevent publication and derived works, which was widely considered inappropriate.</li>
<li>In some jurisdictions, releasing a work to the public domain is not recognised as a legitimate legal action, leaving the ZIP simply copyrighted with no redistribution or modification allowed at all.</li>
</ul>
<p>Why are there software licenses included?</p>
<ul>
<li>Some ZIPs, especially in the Consensus category, may include literal code in the ZIP itself which may not be available under the exact license terms of the ZIP.</li>
<li>Despite this, not all software licenses would be acceptable for content included in ZIPs.</li>
</ul>
<h1 id="see-also">See Also</h1>
<ul>
<li><a href="https://www.gnu.org/philosophy/kind-communication.en.html">The GNU Kind Communication Guidelines</a></li>
<li><a href="https://tools.ietf.org/html/rfc7282">RFC 7282: On Consensus and Humming in the IETF</a></li>
<li><a href="https://electriccoin.co/blog/the-zcash-network-upgrade-pipeline/">Zcash Network Upgrade Pipeline</a></li>
</ul>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zcash/blob/master/code_of_conduct.md">Zcash Code of Conduct</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zcash/blob/master/code_of_conduct.md">Zcash Code of Conduct</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zcash/blob/master/code_of_conduct.md">Zcash Code of Conduct</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="http://docutils.sourceforge.net/rst.html">reStructuredText documentation</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://www.latex-project.org/">LaTeX -- a document preparation system</a><a href="#fnref7" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,569 +0,0 @@
ZIP: 0
Title: ZIP Process
Owners: Daira Hopwood <daira@electriccoin.co>
Josh Cincinnati <josh@zfnd.org>
Status: Active
Category: Process
Created: 2019-02-16
License: BSD-2-Clause
Terminology
===========
The key words \"MUST\", \"SHOULD\", \"SHOULD NOT\", \"MAY\",
\"RECOMMENDED\", \"OPTIONAL\", and \"REQUIRED\" in this document are to
be interpreted as described in RFC 2119.[^1]
The term \"network upgrade\" in this document is to be interpreted as
described in ZIP 200.[^2]
Abstract
========
A Zcash Improvement Proposal (ZIP) is a design document providing
information to the Zcash community, or describing a new feature for
Zcash or its processes or environment. The ZIP should provide a concise
technical specification of the feature and a rationale for the feature.
We intend ZIPs to be the primary mechanism for proposing new features,
for collecting community input on an issue, and for documenting the
design decisions that have gone into Zcash. The Owner(s) of the ZIP
(usually the authors(s)) are responsible for building consensus within
the community and documenting dissenting opinions.
Because the ZIPs are maintained as text files in a versioned repository,
their revision history is the historical record of the feature proposal.
This document is based on the work done by Luke Dashjr with [BIP
2](https://github.com/bitcoin/bips) and Daira Hopwood with [Draft ZIP
0](https://github.com/daira/zips/tree/master/drafts/daira-zip-process).
ZIP Workflow
============
The ZIP process begins with a new idea for Zcash. Each potential ZIP
must have a Owner \-- someone who writes the ZIP using the style and
format described below, shepherds the discussions in the appropriate
forums, and attempts to build community consensus around the idea. The
ZIP Owner should first attempt to ascertain whether the idea is
ZIP-able. Small enhancements or patches to a particular piece of
software often don\'t require standardisation between multiple projects;
these don\'t need a ZIP and should be injected into the relevant
project-specific development workflow with a patch submission to the
applicable issue tracker. Additionally, many ideas have been brought
forward for changing Zcash that have been rejected for various reasons.
The first step should be to search past discussions to see if an idea
has been considered before, and if so, what issues arose in its
progression. After investigating past work, the best way to proceed is
by posting about the new idea to the [Zcash Community
Forum](https://forum.zcashcommunity.com/).
Vetting an idea publicly before going as far as writing a ZIP is meant
to save both the potential Owner and the wider community time. Asking
the Zcash community first if an idea is original helps prevent too much
time being spent on something that is guaranteed to be rejected based on
prior discussions (searching the internet does not always do the trick).
It also helps to make sure the idea is applicable to the entire
community and not just the Owner. Just because an idea sounds good to
the Owner does not mean it will work for most people in most areas where
Zcash is used.
Once the Owner has asked the Zcash community as to whether an idea has
any chance of acceptance, a draft ZIP should be presented to the [Zcash
Community Forum](https://forum.zcashcommunity.com/). This gives the
Owner a chance to flesh out the draft ZIP to make it properly formatted,
of high quality, and to address additional concerns about the proposal.
Following a discussion, the proposal should be submitted to the [ZIPs
git repository](https://github.com/zcash/zips) as a pull request. This
draft must be written in ZIP style as described below, and named with an
alias such as `zip-zatoshizakamoto-42millionzec` until the ZIP Editors
have assigned it a ZIP number (Owners MUST NOT self-assign ZIP numbers).
ZIP Owners are responsible for collecting community feedback on both the
initial idea and the ZIP before submitting it for review. However,
wherever possible, long open-ended discussions on forums should be
avoided.
It is highly recommended that a single ZIP contain a single key proposal
or new idea. The more focused the ZIP, the more successful it tends to
be. If in doubt, split your ZIP into several well-focused ones.
When the ZIP draft is complete, the ZIP Editors will assign the ZIP a
number, label it as Standards Track, Informational, or Process, and
merge the pull request to the ZIPs git repository. The ZIP Editors will
not unreasonably reject a ZIP. Reasons for rejecting ZIPs include
duplication of effort, disregard for formatting rules, being too
unfocused or too broad, being technically unsound, not providing proper
motivation or not in keeping with the Zcash philosophy. For a ZIP to be
accepted it must meet certain minimum criteria. It must be a clear and
complete description of the proposed enhancement. The enhancement must
represent a net improvement. The proposed implementation, if applicable,
must be solid and must not complicate the protocol unduly.
The ZIP Owner may update the draft as necessary in the git repository.
Updates to drafts should also be submitted by the Owner as pull
requests.
Transferring ZIP Ownership
--------------------------
It occasionally becomes necessary to transfer ownership of ZIPs to a new
Owner. In general, we\'d like to retain the original Owner as a co-Owner
of the transferred ZIP, but that\'s really up to the original Owner. A
good reason to transfer ownership is because the original Owner no
longer has the time or interest in updating it or following through with
the ZIP process, or has fallen off the face of the \'net (i.e. is
unreachable or not responding to email). A bad reason to transfer
ownership is because you don\'t agree with the direction of the ZIP. We
try to build consensus around a ZIP, but if that\'s not possible, you
can always submit a competing ZIP.
If you are interested in assuming ownership of a ZIP, send a message
asking to take over, addressed to both the original Owner and the ZIP
Editors. If the original Owner doesn\'t respond to email in a timely
manner, the ZIP Editors will make a unilateral decision (it\'s not like
such decisions can\'t be reversed :).
If an author of a ZIP is no longer an Owner, an Original-Authors field
SHOULD be added to the ZIP metadata indicating the original authorship,
unless the original author(s) request otherwise.
ZIP Editors
-----------
The current ZIP Editors are Daira Hopwood, representing the Electric
Coin Company, and Josh Cincinnati, representing the Zcash Foundation.
Both can be reached at <zips@z.cash> . The current design of the ZIP
Process dictates that there are always at least two ZIP Editors: one
from the Electric Coin Company and one from the Zcash Foundation.
Additional Editors may be selected by consensus among the current
Editors.
ZIP Editor Responsibilities & Workflow
--------------------------------------
The ZIP Editors subscribe to the [Zcash Community
Forum.](https://forum.zcashcommunity.com/)
For each new ZIP that comes in an Editor confirms the following:
- Read the ZIP to check if it is ready: sound and complete. The ideas
must make technical sense, even if they don\'t seem likely to be
accepted.
- The title should accurately describe the content.
- The ZIP draft must have been sent to the Zcash Community Forum or as
a PR to the [ZIPs git repository](https://github.com/zcash/zips)
- Motivation and backward compatibility (when applicable) must be
addressed.
- The licensing terms are acceptable for ZIPs.
If the ZIP isn\'t ready, the editor will send it back to the Owner for
revision, with specific instructions.
Once the ZIP is ready for the repository it should be submitted as a
\"pull request\" to the [ZIPs git
repository](https://github.com/zcash/zips) where it may get further
feedback. It should not contain a ZIP number, and should be labelled
\"WIP\" in the pull request.
The ZIP Editors will:
- Assign a ZIP number in the pull request.
- Merge the pull request when it is ready and remove the \"WIP\"
label.
The ZIP editors monitor ZIP changes and update ZIP headers as
appropriate.
The ZIP Editors MAY reject a proposed ZIP or update to an existing ZIP
for any of the following reasons:
- it violates the Zcash Code of Conduct[^3] ;
- it appears too unfocused or broad;
- it duplicates effort in other ZIPs without sufficient technical justification
(however, alternative proposals to address similar or overlapping problems
are not excluded for this reason);
- it has manifest security flaws (including being unrealistically dependent
on user vigilance to avoid security weaknesses);
- it disregards compatibility with the existing Zcash blockchain or ecosystem;
- it is manifestly unimplementable;
- it includes buggy code, pseudocode, or algorithms;
- it manifestly violates common expectations of a significant portion of the
Zcash community;
- it updates a Draft ZIP to Released when there is significant community
opposition to its content (however, Draft ZIPs explicitly may describe
proposals to which there is, or could be expected, significant community
opposition);
- in the case of a Released ZIP, the update makes a substantive change to
which there is significant community opposition;
- it is dependent on a patent that could potentially be an obstacle to
adoption of the ZIP;
- it includes commercial advertising or spam;
- it disregards formatting rules;
- it makes non-editorial edits to previous entries in a ZIP\'s Change history;
- an update to an existing ZIP extends or changes its scope to an extent
that would be better handled as a separate ZIP;
- a new ZIP has been proposed for a category that does not reflect its content,
or an update would change a ZIP to an inappropriate category;
- it updates a Released ZIP to Draft when the specification is already
implemented and has been in common use;
- it violates any specific \"MUST\" or \"MUST NOT\" rule in this
document;
- the expressed political views of a Owner of the document are inimical
to the Zcash Code of Conduct[^4] (except in the case of an update
removing that Owner);
- it is not authorized by the stated ZIP Owners;
- it removes an Owner without their consent (unless the reason for removal
is directly related to a breach of the Code of Conduct by that Owner).
The ZIP Editors MUST NOT unreasonably deny publication of a ZIP proposal
or update that does not violate any of these criteria. If they refuse a
proposal or update, they MUST give an explanation of which of the
criteria were violated, with the exception that spam may be deleted
without an explanation.
Note that it is not the primary responsibility of the ZIP Editors to
review proposals for security, correctness, or implementability.
Please send all ZIP-related communications either by email to
\<<zips@z.cash>\>, or by opening an issue on the [ZIPs issue
tracker](https://github.com/zcash/zips/issues). All communications
should abide by the Zcash Code of Conduct[^5] and follow [the GNU Kind
Communication
Guidelines](https://www.gnu.org/philosophy/kind-communication.en.html)
ZIP format and structure
========================
ZIPs SHOULD be written either in reStructuredText[^6] or LaTeX[^7]. In
the latter case, a Makefile MUST be provided to build (at least) a PDF
version of the document.
Each ZIP SHOULD have the following parts:
- Preamble \-- Headers containing metadata about the ZIP ([see
below](#zip-header-preamble)). The License field of the preamble
indicates the licensing terms, which MUST be acceptable according to
[the ZIP licensing requirements](#zip-licensing).
- Terminology \-- Definitions of technical or non-obvious terms used
in the document.
- Abstract \-- A short (\~200 word) description of the technical issue
being addressed.
- Motivation \-- The motivation is critical for ZIPs that want to
change the Zcash protocol. It should clearly explain why the
existing protocol is inadequate to address the problem that the ZIP
solves.
- Specification \-- The technical specification should describe the
interface and semantics of any new feature. The specification should
be detailed enough to allow competing, interoperable implementations
for any of the current Zcash platforms.
- Rationale \-- The rationale fleshes out the specification by
describing what motivated the design and why particular design
decisions were made. It should describe alternate designs that were
considered and related work. The rationale should provide evidence
of consensus within the community and discuss important objections
or concerns raised during discussion.
- Security and privacy considerations \-- If applicable, security and
privacy considerations should be explicitly described, particularly
if the ZIP makes explicit trade-offs or assumptions. For guidance on
this section consider [RFC
3552](https://tools.ietf.org/html/rfc3552). as a starting point.
- Reference implementation \-- Literal code implementing the ZIP\'s
specification, and/or a link to the reference implementation of the
ZIP\'s specification. The reference implementation must be completed
before any ZIP is given status "Implemented" or "Final", but it
generally need not be completed before the ZIP is accepted into
"Proposed".
ZIP header preamble
-------------------
Each ZIP must begin with an RFC 822-style header preamble. The following
header fields are REQUIRED:
 ZIP:
 Title:
 Owners:
 Status:
 Category:
Created:
 License:
The following additional header fields are OPTIONAL:
Credits:
Original-Authors:
>  Discussions-To:  Network Upgrade: Obsoleted by: Updated by:
> Obsoletes: Updates:
The Owners header lists the names and email addresses of all the Owners
of the ZIP. The format of the Owners header value SHOULD be:
Random J. User <address@dom.ain>
If there are multiple Owners, each should be on a separate line.
While a ZIP is in private discussions (usually during the initial Draft
phase), a Discussions-To header will indicate the URL where the ZIP is
being discussed. No Discussions-To header is necessary if the ZIP is
being discussed privately with the Owner.
The Category header specifies the type of ZIP: Consensus, Standards
Track, Informational, or Process.
The Created header records the date that the ZIP was submitted. Dates
should be in yyyy-mm-dd format, e.g. 2001-08-14.
Auxiliary Files
---------------
ZIPs may include auxiliary files such as diagrams. Auxiliary files
should be included in a subdirectory for that ZIP; that is, for any ZIP
that requires more than one file, all of the files SHOULD be in a
subdirectory named zip-XXXX.
ZIP categories
==============
There are several kinds of ZIP:
- A Consensus ZIP describes a change that affects the consensus
protocol followed by all Zcash implementations.
- A Standards Track ZIP describes any non-consensus change that
affects most or all Zcash implementations, such as a change to the
network protocol, or any change or addition that affects the
interoperability of applications using Zcash.
Consensus and Standards Track ZIPs consist of two parts: a design
document and a reference implementation.
- An Informational ZIP describes Zcash design issues, or general
guidelines or information for the Zcash community, that do not fall
into either of the above categories. Informational ZIPs do not
necessarily represent a Zcash community consensus or recommendation,
so users and implementers are free to ignore Informational ZIPs or
follow their advice.
- A Process ZIP describes a process surrounding Zcash, or proposes a
change to (or an event in) a process. Process ZIPs are like
Standards Track ZIPs but apply to areas other than the Zcash
protocol itself. They may propose an implementation, but not to
Zcash\'s codebase; they often require community consensus; unlike
Informational ZIPs, they are more than recommendations, and users
are typically not free to ignore them. Examples include procedures,
guidelines, changes to the decision-making process, and changes to
the tools or environment used in Zcash development.
New categories may be added by consensus among the ZIP Editors.
ZIP Status Field
================
- Draft: All initial ZIP submissions have this status.
- Withdrawn: If the Owner decides to remove the ZIP from consideration
by the community, they may set the status to Withdrawn.
- Active: Typically only used for Process/Informational ZIPs, achieved
once rough consensus is reached in PR/forum posts from Draft Process
ZIP.
- Proposed: Typically the stage after Draft, added to a ZIP after
consideration, feedback, and rough consensus from the community. The
ZIP Editors must validate this change before it is approved.
- Rejected: The status when progress hasn\'t been made on the ZIP in
one year. Can revert back to Draft/Proposed if the Owner resumes
work or resolves issues preventing consensus.
- Implemented: When a Consensus or Standards Track ZIP has a working
reference implementation but before activation on the Zcash network.
- Final: When a Consensus or Standards Track ZIP is both implemented
and activated on the Zcash network.
- Obsolete: The status when a ZIP is no longer relevant (typically
when superseded by another ZIP).
More details on the status workflow in the section below.
Specification
-------------
Owners of a ZIP may decide on their own to change the status between
Draft or Withdrawn.
A ZIP may only change status from Draft (or Rejected) to Proposed, when
the Owner deems it is complete and there is rough consensus on the
forums, validated by both the Electric Coin Company and Zcash Foundation
Editors. One Editor will not suffice \-- there needs to be consensus
among the Editors. If it\'s a Standards Track ZIP, upon changing status
to Proposed the Editors will add the optional `Network Upgrade` header
to the preamble, indicating the intent for the ZIP to be implemented in
the specified network upgrade. (All `Network Upgrade` schedules will be
distributed via the Zcash Community Forum by the Editors.)
A Standards Track ZIP may only change status from Proposed to
Implemented once the Owner provides an associated reference
implementation, typically in the period after the network upgrade\'s
specification freeze but before the implementation audit. If the Owner
misses this deadline, the Editors or Owner(s) may choose to update the
`Network Upgrade` header to target another upgrade, at their discretion.
ZIPs should be changed from Draft or Proposed status, to Rejected
status, upon request by any person, if they have not made progress in
one year. Such a ZIP may be changed to Draft status if the Owner
provides revisions that meaningfully address public criticism of the
proposal, or to Proposed status if it meets the criteria required as
described in the previous paragraph.
A Consensus or Standards Track ZIP becomes Final when its associated
network upgrade or other protocol change is activated on Zcash\'s
mainnet.
A Process or Informational ZIP may change status from Draft to Active
when it achieves rough consensus on the forum or PR. Such a proposal is
said to have rough consensus if it has been open to discussion on the
forum or GitHub PR for at least one month, and no person maintains any
unaddressed substantiated objections to it. Addressed or obstructive
objections may be ignored/overruled by general agreement that they have
been sufficiently addressed, but clear reasoning must be given in such
circumstances.
When an Active or Final ZIP is no longer relevant, its status may be
changed to Obsolete. This change must also be objectively verifiable
and/or discussed. Final ZIPs may be updated; the specification is still
in force but modified by another specified ZIP or ZIPs (check the
optional Updated-by header).
ZIP Comments
============
Comments from the community on the ZIP should occur on the Zcash
Community Forum and the comment fields of the pull requests in any open
ZIPs. Editors will use these sources to judge rough consensus.
ZIP licensing
=============
New ZIPs may be accepted with the following licenses. Each new ZIP MUST
identify at least one acceptable license in its preamble. Each license
MUST be referenced by their respective abbreviation given below.
For example, a preamble might include the following License header:
License: BSD-2-Clause
   GNU-All-Permissive
In this case, the ZIP text is fully licensed under both the OSI-approved
BSD 2-clause license as well as the GNU All-Permissive License, and
anyone may modify and redistribute the text provided they comply with
the terms of *either* license. In other words, the license list is an
\"OR choice\", not an \"AND also\" requirement.
It is also possible to license source code differently from the ZIP
text. This case SHOULD be indicated in the Reference Implementation
section of the ZIP. Again, each license MUST be referenced by its
respective abbreviation given below.
Statements of code licenses in ZIPs are only advisory; anyone intending
to use the code should look for license statements in the code itself.
ZIPs are not required to be *exclusively* licensed under approved terms,
and MAY also be licensed under unacceptable licenses *in addition to* at
least one acceptable license. In this case, only the acceptable
license(s) should be listed in the License header.
Recommended licenses
--------------------
- MIT: [Expat/MIT/X11 license](https://opensource.org/licenses/MIT)
- BSD-2-Clause: [OSI-approved BSD 2-clause
license](https://opensource.org/licenses/BSD-2-Clause)
- BSD-3-Clause: [OSI-approved BSD 3-clause
license](https://opensource.org/licenses/BSD-3-Clause)
- CC0-1.0: [Creative Commons CC0 1.0
Universal](https://creativecommons.org/publicdomain/zero/1.0/)
- GNU-All-Permissive: [GNU All-Permissive
License](http://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html)
- Apache-2.0: [Apache License, version
2.0](http://www.apache.org/licenses/LICENSE-2.0)
In addition, it is RECOMMENDED that literal code included in the ZIP be
dual-licensed under the same license terms as the project it modifies.
For example, literal code intended for zcashd would ideally be
dual-licensed under the MIT license terms as well as one of the above
with the rest of the ZIP text.
Not recommended, but acceptable licenses
----------------------------------------
- BSL-1.0: [Boost Software License, version
1.0](http://www.boost.org/LICENSE_1_0.txt)
- CC-BY-4.0: [Creative Commons Attribution 4.0
International](https://creativecommons.org/licenses/by/4.0/)
- CC-BY-SA-4.0: [Creative Commons Attribution-ShareAlike 4.0
International](https://creativecommons.org/licenses/by-sa/4.0/)
- AGPL-3.0+: [GNU Affero General Public License (AGPL), version 3 or
newer](http://www.gnu.org/licenses/agpl-3.0.en.html)
- FDL-1.3: [GNU Free Documentation License, version
1.3](http://www.gnu.org/licenses/fdl-1.3.en.html)
- GPL-2.0+: [GNU General Public License (GPL), version 2 or
newer](http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
- LGPL-2.1+: [GNU Lesser General Public License (LGPL), version 2.1 or
newer](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
Not acceptable licenses
-----------------------
All licenses not explicitly included in the above lists are not
acceptable terms for a Zcash Improvement Proposal.
Rationale
---------
Bitcoin\'s BIP 1 allowed the Open Publication License or releasing into
the public domain; was this insufficient?
- The OPL is generally regarded as obsolete, and not a license
suitable for new publications.
- The OPL license terms allowed for the author to prevent publication
and derived works, which was widely considered inappropriate.
- In some jurisdictions, releasing a work to the public domain is not
recognised as a legitimate legal action, leaving the ZIP simply
copyrighted with no redistribution or modification allowed at all.
Why are there software licenses included?
- Some ZIPs, especially in the Consensus category, may include literal
code in the ZIP itself which may not be available under the exact
license terms of the ZIP.
- Despite this, not all software licenses would be acceptable for
content included in ZIPs.
See Also
========
- [The GNU Kind Communication
Guidelines](https://www.gnu.org/philosophy/kind-communication.en.html)
- [RFC 7282: On Consensus and Humming in the
IETF](https://tools.ietf.org/html/rfc7282)
- [Zcash Network Upgrade
Pipeline](https://electriccoin.co/blog/the-zcash-network-upgrade-pipeline/)
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [Zcash Code of
Conduct](https://github.com/zcash/zcash/blob/master/code_of_conduct.md)
[^4]: [Zcash Code of
Conduct](https://github.com/zcash/zcash/blob/master/code_of_conduct.md)
[^5]: [Zcash Code of
Conduct](https://github.com/zcash/zcash/blob/master/code_of_conduct.md)
[^6]: [reStructuredText
documentation](http://docutils.sourceforge.net/rst.html)
[^7]: [LaTeX \-- a document preparation
system](https://www.latex-project.org/)

289
zip-0032.html Normal file
View File

@ -0,0 +1,289 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0032</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 32
Title: Shielded Hierarchical Deterministic Wallets
Owners: Jack Grigg &lt;str4d@electriccoin.co&gt;
Daira Hopwood &lt;daira@electriccoin.co&gt;
Credits: Pieter Wuille &lt;pieter.wuille@gmail.com&gt;
Marek Palatinus &lt;slush@satoshilabs.com&gt;
Pavol Rusnak &lt;stick@satoshilabs.com&gt;
Status: Final
Category: Standards Track
Created: 2018-05-22
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119. <a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>&quot;Jubjub&quot; refers to the elliptic curve defined in<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> section 5.4.8.3.</p>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines a mechanism for extending hierarchical deterministic wallets, as decribed in BIP 32 <a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>, to support Zcash's shielded addresses.</p>
<p>The specification has three parts. The first part defines a system for deriving a tree of Sapling key components from a single seed. The second part defines an equivalent, but independent, system for Sprout key components (which have a different internal construction). The third part shows how to use these trees in the context of existing BIP 44<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> wallets.</p>
<p>This specification complements the existing use by some Zcash wallets of BIP 32 and BIP 44 for transparent Zcash addresses, and is not intended to deprecate that usage (privacy risks of using transparent addresses notwithstanding).</p>
<h1 id="motivation">Motivation</h1>
<p>BIP 32<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a> is the standard mechanism by which wallets for Bitcoin and its derivatives (including Zcash's transparent addresses<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a>) generate keys and addresses deterministically. This has several advantages over random generation:</p>
<ul>
<li>Wallets only need to store a single seed (particularly useful for hardware wallets).</li>
<li>A one-time backup of the seed (usually stored as a word phrase<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a>) can be used to recover funds from all future addresses.</li>
<li>Keys are arranged into a tree of chains, enabling wallets to represent &quot;accounts&quot; or other high-level structures.</li>
<li>View authority or spend authority can be delegated independently for sub-trees without compromising the master seed.</li>
</ul>
<p>At present, no such equivalent exists for Zcash's shielded addresses. This is of particular concern for hardware wallets; all currently-marketed devices only store a seed internally, and have trained their users to only backup that seed. Given that the Sapling upgrade will make it feasible to use hardware wallets with shielded addresses, it is desirable to have a standard mechanism for deriving them.</p>
<h1 id="conventions">Conventions</h1>
<p>Most of the notation and functions used in this ZIP are defined in the Sapling protocol specification <a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a>. They are reproduced here for convenience:</p>
<ul>
<li>truncate<sub>k</sub>(<em>S</em>) means the sequence formed from the first <em>k</em> elements of <em>S</em>.</li>
<li><em>a</em> || <em>b</em> means the concatenation of sequences <em>a</em> then <em>b</em>.</li>
<li>[<em>k</em>] <em>P</em> means scalar multiplication of the elliptic curve point <em>P</em> by the scalar <em>k</em>.</li>
<li>LEOS2IP<sub>l</sub>(<em>S</em>) is the integer in range {0..2<sup>l</sup>-1} represented in little-endian order by the byte sequence <em>S</em> of length <em>l</em>/8.</li>
<li>I2LEBSP<sub>l</sub>(<em>k</em>) is the sequence of <em>l</em> bits representing <em>k</em> in little-endian order.</li>
<li>LEBS2OSP<sub>l</sub>(<em>B</em>) is defined as follows when <em>l</em> is a multiple of 8: convert each group of 8 bits in <em>B</em> to a byte value with the least significant bit first, and concatenate the resulting bytes in the same order as the groups.</li>
<li>repr<sub>𝕁</sub>(<em>P</em>) is the representation of the Jubjub elliptic curve point <em>P</em> as a bit sequence, defined in<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a> section 5.4.8.3.</li>
<li>BLAKE2b-256(<em>p</em>, <em>x</em>) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string <em>p</em>, and input <em>x</em>.</li>
<li>BLAKE2b-512(<em>p</em>, <em>x</em>) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string <em>p</em>, and input <em>x</em>.</li>
<li>PRF<sup>expand</sup>(<em>sk</em>, <em>t</em>) := BLAKE2b-512(&quot;Zcash_ExpandSeed&quot;, <em>sk</em> || <em>t</em>)</li>
<li>ToScalar(<em>x</em>) := LEOS2IP<sub>512</sub>(<em>x</em>) (mod <em>r</em><sub>𝕁</sub>), where <em>r</em><sub>𝕁</sub> is the order of the Jubjub large prime subgroup.</li>
<li>DiversifyHash(<em>d</em>) maps a diversifier <em>d</em> to a base point on the Jubjub elliptic curve, or to ⊥ if the diversifier is invalid. It is instantiated in<a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a> section 5.4.1.6.</li>
</ul>
<p>The following algorithm standardized in<a href="#fn11" class="footnote-ref" id="fnref11"><sup>11</sup></a> is used:</p>
<ul>
<li>FF1-AES256.Encrypt(<em>key</em>, <em>tweak</em>, <em>x</em>) refers to the FF1 encryption algorithm using AES with a 256-bit <em>key</em>, and parameters <em>radix</em> = 2, <em>minlen</em> = 88, <em>maxlen</em> = 88. It will be used only with the empty string &quot;&quot; as the <em>tweak</em>. <em>x</em> is a sequence of 88 bits, as is the output.</li>
</ul>
<p>We also define the following conversion function:</p>
<ul>
<li>I2LEOSP<sub>l</sub>(<em>k</em>) is the byte sequence <em>S</em> of length <em>l</em>/8 representing in little-endian order the integer <em>k</em> in range {0..2<sup>l</sup>-1}. It is the reverse operation of LEOS2IP<sub>l</sub>(<em>S</em>).</li>
</ul>
<p>Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling specification), which is the opposite of BIP 32.</p>
<p>We adapt the path notation of BIP 32<a href="#fn12" class="footnote-ref" id="fnref12"><sup>12</sup></a> to describe shielded HD paths, using apostrophes to indicate hardened derivation (i' = i + 2<sup>31</sup>) as in BIP 44<a href="#fn13" class="footnote-ref" id="fnref13"><sup>13</sup></a>:</p>
<ul>
<li>CDKsk(CDKsk(CDKsk(m<sub>Sprout</sub>, a'), b), c) is written as m<sub>Sprout</sub> / a' / b / c</li>
<li>CDKfvk(CDKfvk(CDKfvk(M<sub>Sapling</sub>, a), b), c) is written as M<sub>Sapling</sub> / a / b / c</li>
</ul>
<h1 id="specification-sapling-key-derivation">Specification: Sapling key derivation</h1>
<h2 id="sapling-extended-keys">Sapling extended keys</h2>
<p>BIP 32 defines a method to derive a number of child keys from a parent key. In order to prevent these from depending solely on the parent key itself, both the private and public keys are extended with a 32-byte chain code. We similarly extend Sapling keys with a chain code here. However, the concepts of &quot;private&quot; and &quot;public&quot; keys in BIP 32 do not map cleanly to Sapling's key components. We take the following approach:</p>
<ul>
<li>We derive child Sapling expanded spending keys, rather than Sapling spending keys. This enables us to implement both hardened and non-hardened derivation modes (the latter being incompatible with Sapling spending keys).</li>
<li>We do not derive Sapling public keys directly, as this would prevent the use of diversified addresses. Instead, we derive Sapling full viewing keys, from which payment addresses can be generated. This maintains the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all transactions involving that address, which a Sapling full viewing key also enables.</li>
</ul>
<p>We represent a Sapling extended spending key as (<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), where (<em>ask</em>, <em>nsk</em>, <em>ovk</em>) is the normal Sapling expanded spending key, <em>dk</em> is a diversifier key, and <em>c</em> is the chain code.</p>
<p>We represent a Sapling extended full viewing key as (<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), where (<em>ak</em>, <em>nk</em>, <em>ovk</em>) is the normal Sapling full viewing key, <em>dk</em> is the same diversifier key as above, and <em>c</em> is the chain code.</p>
<h2 id="helper-functions">Helper functions</h2>
<p>Define EncodeExtSKParts(<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>) := I2LEOSP<sub>256</sub>(<em>ask</em>) || I2LEOSP<sub>256</sub>(<em>nsk</em>) || <em>ovk</em> || <em>dk</em>.</p>
<p>Define EncodeExtFVKParts(<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>) := LEBS2OSP<sub>256</sub>(repr<sub>𝕁</sub>(<em>ak</em>)) || LEBS2OSP<sub>256</sub>(repr<sub>𝕁</sub>(<em>nk</em>)) || <em>ovk</em> || <em>dk</em>.</p>
<h2 id="master-key-generation">Master key generation</h2>
<p>Let <em>S</em> be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<ul>
<li>Calculate <em>I</em> = BLAKE2b-512(&quot;ZcashIP32Sapling&quot;, <em>S</em>).</li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Use <em>I</em><sub>L</sub> as the master spending key <em>sk</em><sub>m</sub>, and <em>I</em><sub>R</sub> as the master chain code <em>c</em><sub>m</sub>.</li>
<li>Calculate <em>ask</em><sub>m</sub>, <em>nsk</em><sub>m</sub>, and <em>ovk</em><sub>m</sub> via the standard Sapling derivation <a href="#fn14" class="footnote-ref" id="fnref14"><sup>14</sup></a>:
<ul>
<li><em>ask</em><sub>m</sub> = ToScalar(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x00]))</li>
<li><em>nsk</em><sub>m</sub> = ToScalar(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x01]))</li>
<li><em>ovk</em><sub>m</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x02]))</li>
</ul></li>
<li>Calculate <em>dk</em><sub>m</sub> similarly:
<ul>
<li><em>dk</em><sub>m</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x10]))</li>
</ul></li>
<li>Return (<em>ask</em><sub>m</sub>, <em>nsk</em><sub>m</sub>, <em>ovk</em><sub>m</sub>, <em>dk</em><sub>m</sub>, <em>c</em><sub>m</sub>) as the master extended spending key <em>m</em><sub>Sapling</sub>.</li>
</ul>
<h2 id="child-key-derivation">Child key derivation</h2>
<p>As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index <em>i</em>, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.</p>
<h3 id="deriving-a-child-extended-spending-key">Deriving a child extended spending key</h3>
<p>CDKsk((<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>ask</em><sub>i</sub>, <em>nsk</em><sub>i</sub>, <em>ovk</em><sub>i</sub>, <em>dk</em><sub>i</sub>, <em>c</em><sub>i</sub>)</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<ul>
<li>If so (hardened child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x11] || EncodeExtSKParts(<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
<li>If not (normal child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x12] || EncodeExtFVKParts(<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>)) where (<em>nk</em><sub>par</sub>, <em>ak</em><sub>par</sub>, <em>ovk</em><sub>par</sub>) is the full viewing key derived from (<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>) as described in<a href="#fn15" class="footnote-ref" id="fnref15"><sup>15</sup></a>.</li>
</ul></li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Let <em>I</em><sub>ask</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x13]))</li>
<li>Let <em>I</em><sub>nsk</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x14]))</li>
<li>Return:
<ul>
<li><em>ask</em><sub>i</sub> = <em>I</em><sub>ask</sub> + <em>ask</em><sub>par</sub></li>
<li><em>nsk</em><sub>i</sub> = <em>I</em><sub>nsk</sub> + <em>nsk</em><sub>par</sub></li>
<li><em>ovk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x15] || <em>ovk</em><sub>par</sub>))</li>
<li><em>dk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x16] || <em>dk</em><sub>par</sub>))</li>
<li><em>c</em><sub>i</sub> = <em>I</em><sub>R</sub></li>
</ul></li>
</ul>
<h3 id="deriving-a-child-extended-full-viewing-key">Deriving a child extended full viewing key</h3>
<p>Let 𝓖 be as defined in<a href="#fn16" class="footnote-ref" id="fnref16"><sup>16</sup></a> section 5.4.6.1 and let 𝓗 be as defined in<a href="#fn17" class="footnote-ref" id="fnref17"><sup>17</sup></a>.</p>
<p>CDKfvk((<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>ak</em><sub>i</sub>, <em>nk</em><sub>i</sub>, <em>ovk</em><sub>i</sub>, <em>dk</em><sub>i</sub>, <em>c</em><sub>i</sub>)</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<ul>
<li>If so (hardened child): return failure</li>
<li>If not (normal child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x12] || EncodeExtFVKParts(<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
</ul></li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Let <em>I</em><sub>ask</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x13]))</li>
<li>Let <em>I</em><sub>nsk</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x14]))</li>
<li>Return:
<ul>
<li><em>ak</em><sub>i</sub> = [<em>I</em><sub>ask</sub>] 𝓖 + <em>ak</em><sub>par</sub></li>
<li><em>nk</em><sub>i</sub> = [<em>I</em><sub>nsk</sub>] 𝓗 + <em>nk</em><sub>par</sub></li>
<li><em>ovk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x15] || <em>ovk</em><sub>par</sub>))</li>
<li><em>dk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x16] || <em>dk</em><sub>par</sub>))</li>
<li><em>c</em><sub>i</sub> = <em>I</em><sub>R</sub></li>
</ul></li>
</ul>
<h2 id="diversifier-derivation">Diversifier derivation</h2>
<p>The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key <em>dk</em>. To prevent the diversifier leaking how many diversified addresses have already been generated for an account, we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows:</p>
<ul>
<li>Let <em>j</em> be the index of the desired diversifier, in the range 0 .. 2<sup>88</sup>-1.</li>
<li><em>d</em><sub>j</sub> = FF1-AES256.Encrypt(<em>dk</em>, &quot;&quot;, I2LEBSP<sub>88</sub>(<em>j</em>)).</li>
</ul>
<p>A valid diversifier <em>d</em><sub>j</sub> is one for which DiversifyHash(<em>d</em><sub>j</sub>) ≠ ⊥. For a given <em>dk</em>, approximately half of the possible values of <em>j</em> yield valid diversifiers.</p>
<p>The default diversifier for a Sapling extended key is defined to be <em>d</em><sub>j</sub>, where <em>j</em> is the least nonnegative integer yielding a valid diversifier.</p>
<h1 id="specification-sprout-key-derivation">Specification: Sprout key derivation</h1>
<p>For completeness, we define a system for deriving a tree of Sprout key components. It is unlikely that this will garner much usage once Sapling activates, but is presented for those users who may require it.</p>
<h2 id="sprout-extended-keys">Sprout extended keys</h2>
<p>Due to the way Sprout keys are constructed and used, it is not possible to derive incoming viewing keys or payment addresses in parallel with spending keys. Nor is it possible to implement non-hardened derivation. We therefore only define and derive Sprout extended spending keys.</p>
<p>We represent a Sprout extended spending key as (<em>a</em><sub>sk</sub>, <em>c</em>), where <em>a</em><sub>sk</sub> is the normal Sprout spending key, and <em>c</em> is the chain code.</p>
<h2 id="helper-functions-1">Helper functions</h2>
<p>Let EncodeASK(<em>a</em><sub>sk</sub>) be the 32-byte encoding of <em>a</em><sub>sk</sub> in the raw encoding of a Sprout spending key (excluding lead bytes) as specified in<a href="#fn18" class="footnote-ref" id="fnref18"><sup>18</sup></a> section 5.6.8.</p>
<p>Let DecodeASK(<em>ASK</em>) be the result of clearing the 4 most significant bits of the first byte of <em>ASK</em>, and decoding the 32-byte result according to the inverse of EncodeASK.</p>
<h2 id="master-key-generation-1">Master key generation</h2>
<p>Let <em>S</em> be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<ul>
<li>Calculate <em>I</em> = BLAKE2b-512(&quot;ZcashIP32_Sprout&quot;, <em>S</em>).</li>
<li>Split <em>I</em> into two 32-byte sequences, I<sub>L</sub> and I<sub>R</sub>.</li>
<li>Use DecodeASK(<em>I</em><sub>L</sub>) as the master spending key a<sub>sk,m</sub>.</li>
<li>Use <em>I</em><sub>R</sub> as the master chain code <em>c</em><sub>m</sub>.</li>
</ul>
<h2 id="child-key-derivation-1">Child key derivation</h2>
<p>CDKsk((<em>a</em><sub>sk,par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>a</em><sub>sk,i</sub>, <em>c</em><sub>i</sub>)</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<ul>
<li>If so (hardened child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x80] || EncodeASK(<em>a</em><sub>sk,par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
<li>If not (normal child): return failure</li>
</ul></li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Use DecodeASK(<em>I</em><sub>L</sub>) as the child spending key a<sub>sk,i</sub>.</li>
<li>Use <em>I</em><sub>R</sub> as the child chain code <em>c</em><sub>i</sub>.</li>
</ul>
<h1 id="specification-wallet-usage">Specification: Wallet usage</h1>
<p>Existing Zcash-supporting HD wallets all use BIP 44<a href="#fn19" class="footnote-ref" id="fnref19"><sup>19</sup></a> to organize their derived keys. In order to more easily mesh with existing user experiences, we broadly follow BIP 44's design here. However, we have altered the design where it makes sense to leverage features of shielded addresses.</p>
<h2 id="key-path-levels">Key path levels</h2>
<p>Both Sprout and Sapling key paths have the following three path levels at the top, all of which use hardened derivation:</p>
<ul>
<li><code>purpose</code>: a constant set to 32' (or 0x80000020) following the BIP 43 recommendation. It indicates that the subtree of this node is used according to this specification.</li>
<li><code>coin_type</code>: a constant identifying the cybercoin that this subtree's keys are used with. For compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 <a href="#fn20" class="footnote-ref" id="fnref20"><sup>20</sup></a>. Note that in keeping with that document, all cybercoin testnets share <code>coin_type</code> index 1.</li>
<li><code>account</code>: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44<a href="#fn21" class="footnote-ref" id="fnref21"><sup>21</sup></a>.</li>
</ul>
<p>Unlike BIP 44, neither Sprout nor Sapling have a change path level. The use of change addresses in Bitcoin is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by segregating external and internal address usage. Shielded addresses are never publicly visible in transactions, which means that sending change back to the originating address is indistinguishable from using a change address.</p>
<h2 id="sapling-key-path">Sapling key path</h2>
<p>Sapling provides a mechanism to allow the efficient creation of diversified payment addresses with the same spending authority. A group of such addresses shares the same full viewing key and incoming viewing key, and so creating as many unlinkable addresses as needed does not increase the cost of scanning the block chain for relevant transactions.</p>
<p>The above key path levels include an account identifier, which in all user interfaces is represented as a &quot;bucket of funds&quot; under the control of a single spending authority. Therefore, wallets implementing Sapling ZIP 32 derivation MUST support the following path for any account in range {0..2<sup>31</sup>-1}:</p>
<pre><code>m_Sapling / purpose&#39; / coin_type&#39; / account&#39;</code></pre>
<p>Furthermore, wallets MUST support generating the default payment address (corresponding to the default diversifier as defined above) for any account they support. They MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the user experience of giving a unique address to each recipient.</p>
<p>Note that a given account can have a maximum of approximately 2<sup>87</sup> payment addresses, because each diversifier has around a 50% chance of being invalid.</p>
<p>If in certain circumstances a wallet needs to derive independent spend authorities within a single account, they MAY additionally support a non-hardened <code>address_index</code> path level as in<a href="#fn22" class="footnote-ref" id="fnref22"><sup>22</sup></a>:</p>
<pre><code>m_Sapling / purpose&#39; / coin_type&#39; / account&#39; / address_index</code></pre>
<h2 id="sprout-key-path">Sprout key path</h2>
<p>Wallets implementing Sprout ZIP 32 derivation MUST support the following path:</p>
<pre><code>m_Sprout / purpose&#39; / coin_type&#39; / account&#39; / address_index</code></pre>
<h1 id="specification-fingerprints-and-tags">Specification: Fingerprints and Tags</h1>
<h2 id="sapling-full-viewing-key-fingerprints-and-tags">Sapling Full Viewing Key Fingerprints and Tags</h2>
<p>A &quot;Sapling full viewing key fingerprint&quot; of a full viewing key with raw encoding <em>FVK</em> (as specified in<a href="#fn23" class="footnote-ref" id="fnref23"><sup>23</sup></a> section 5.6.7) is given by:</p>
<blockquote>
<p>BLAKE2b-256(&quot;ZcashSaplingFVFP&quot;, <em>FVK</em>)</p>
</blockquote>
<p>It MAY be used to uniquely identify a particular Sapling full viewing key.</p>
<p>A &quot;Sapling full viewing key tag&quot; is the first 4 bytes of the corresponding Sapling full viewing key fingerprint. It is intended for optimizing performance of key lookups, and MUST NOT be assumed to uniquely identify a particular key.</p>
<h2 id="sprout-address-fingerprints-and-tags">Sprout Address Fingerprints and Tags</h2>
<p>A &quot;Sprout address fingerprint&quot; of a Sprout payment address with raw encoding <em>ADDR</em> (as specified in <a href="#fn24" class="footnote-ref" id="fnref24"><sup>24</sup></a> section 5.6.3, including the lead bytes) is given by:</p>
<blockquote>
<p>BLAKE2b-256(&quot;Zcash_Sprout_AFP&quot;, <em>ADDR</em>)</p>
</blockquote>
<p>It MAY be used to uniquely identify a particular Sprout payment address.</p>
<p>A &quot;Sprout address tag&quot; is the first 4 bytes of the corresponding Sprout address fingerprint. It is intended for optimizing performance of address lookups, and MUST NOT be assumed to uniquely identify a particular address.</p>
<h2 id="seed-fingerprints">Seed Fingerprints</h2>
<p>A &quot;seed fingerprint&quot; for the master seed <em>S</em> of a hierarchical deterministic wallet is given by:</p>
<blockquote>
<p>BLAKE2b-256(&quot;Zcash_HD_Seed_FP&quot;, <em>S</em>)</p>
</blockquote>
<p>It MAY be used to uniquely identify a particular hierarchical deterministic wallet.</p>
<p>No corresponding short tag is defined.</p>
<h1 id="specification-key-encodings">Specification: Key Encodings</h1>
<p>The following encodings are analogous to the <code>xprv</code> and <code>xpub</code> encodings defined in BIP 32 for transparent keys and addresses. Each key type has a raw representation and a Bech32<a href="#fn25" class="footnote-ref" id="fnref25"><sup>25</sup></a> encoding.</p>
<h2 id="sapling-extended-spending-keys">Sapling extended spending keys</h2>
<p>A Sapling extended spending key (<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), at depth <em>depth</em>, with parent full viewing key tag <em>parent_fvk_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_fvk_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeExtSKParts(<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>)</p>
</blockquote>
<p>For the master extended spending key, <em>depth</em> is 0, <em>parent_fvk_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>secret-extended-key-main</code> for the production network, or <code>secret-extended-key-test</code> for the test network.</p>
<h2 id="sapling-extended-full-viewing-keys">Sapling extended full viewing keys</h2>
<p>A Sapling extended full viewing key (<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), at depth <em>depth</em>, with parent full viewing key tag <em>parent_fvk_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_fvk_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeExtFVKParts(<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>)</p>
</blockquote>
<p>For the master extended full viewing key, <em>depth</em> is 0, <em>parent_fvk_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>zxviews</code> for the production network, or <code>zxviewtestsapling</code> for the test network.</p>
<h2 id="sprout-extended-spending-keys">Sprout extended spending keys</h2>
<p>A Sprout extended spending key (<em>a</em><sub>sk</sub>, <em>c</em>), at depth <em>depth</em>, with parent address tag <em>parent_addr_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_addr_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeASK(<em>a</em><sub>sk</sub>)</p>
</blockquote>
<p>For the master extended spending key, <em>depth</em> is 0, <em>parent_addr_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>zxsprout</code> for the production network, or <code>zxtestsprout</code> for the test network. Sprout extended spending keys are encoded using Bech32 even though other Sprout keys and addresses are encoded using Base58Check.</p>
<h1 id="test-vectors">Test Vectors</h1>
<p>TBC</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<ul>
<li><a href="https://github.com/zcash-hackworks/zip32" class="uri">https://github.com/zcash-hackworks/zip32</a></li>
<li><a href="https://github.com/zcash/librustzcash/pull/29" class="uri">https://github.com/zcash/librustzcash/pull/29</a></li>
<li><a href="https://github.com/zcash/zcash/pull/3447" class="uri">https://github.com/zcash/zcash/pull/3447</a></li>
<li><a href="https://github.com/zcash/zcash/pull/3492" class="uri">https://github.com/zcash/zcash/pull/3492</a></li>
</ul>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki">BIP 32: Hierarchical Deterministic Wallets</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki">BIP 32: Hierarchical Deterministic Wallets</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/satoshilabs/slips/blob/master/slip-0044.md">SLIP 44: Registered coin types for BIP-0044</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki">BIP 39: Mnemonic code for generating deterministic keys</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref10" class="footnote-back"></a></p></li>
<li id="fn11"><p><a href="https://dx.doi.org/10.6028/NIST.SP.800-38G">NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption</a><a href="#fnref11" class="footnote-back"></a></p></li>
<li id="fn12"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki">BIP 32: Hierarchical Deterministic Wallets</a><a href="#fnref12" class="footnote-back"></a></p></li>
<li id="fn13"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a><a href="#fnref13" class="footnote-back"></a></p></li>
<li id="fn14"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref14" class="footnote-back"></a></p></li>
<li id="fn15"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref15" class="footnote-back"></a></p></li>
<li id="fn16"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref16" class="footnote-back"></a></p></li>
<li id="fn17"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref17" class="footnote-back"></a></p></li>
<li id="fn18"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref18" class="footnote-back"></a></p></li>
<li id="fn19"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a><a href="#fnref19" class="footnote-back"></a></p></li>
<li id="fn20"><p><a href="https://github.com/satoshilabs/slips/blob/master/slip-0044.md">SLIP 44: Registered coin types for BIP-0044</a><a href="#fnref20" class="footnote-back"></a></p></li>
<li id="fn21"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a><a href="#fnref21" class="footnote-back"></a></p></li>
<li id="fn22"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP 44: Multi-Account Hierarchy for Deterministic Wallets</a><a href="#fnref22" class="footnote-back"></a></p></li>
<li id="fn23"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref23" class="footnote-back"></a></p></li>
<li id="fn24"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling]</a><a href="#fnref24" class="footnote-back"></a></p></li>
<li id="fn25"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki">BIP 173: Base32 address format for native v0-16 witness outputs</a><a href="#fnref25" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,601 +0,0 @@
ZIP: 32
Title: Shielded Hierarchical Deterministic Wallets
Owners: Jack Grigg <str4d@electriccoin.co>
Daira Hopwood <daira@electriccoin.co>
Credits: Pieter Wuille <pieter.wuille@gmail.com>
Marek Palatinus <slush@satoshilabs.com>
Pavol Rusnak <stick@satoshilabs.com>
Status: Final
Category: Standards Track
Created: 2018-05-22
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", and \"MAY\" in this document are
to be interpreted as described in RFC 2119. [^1]
\"Jubjub\" refers to the elliptic curve defined in[^2] section 5.4.8.3.
Abstract
========
This proposal defines a mechanism for extending hierarchical
deterministic wallets, as decribed in BIP 32 [^3], to support Zcash\'s
shielded addresses.
The specification has three parts. The first part defines a system for
deriving a tree of Sapling key components from a single seed. The second
part defines an equivalent, but independent, system for Sprout key
components (which have a different internal construction). The third
part shows how to use these trees in the context of existing BIP 44[^4]
wallets.
This specification complements the existing use by some Zcash wallets of
BIP 32 and BIP 44 for transparent Zcash addresses, and is not intended
to deprecate that usage (privacy risks of using transparent addresses
notwithstanding).
Motivation
==========
BIP 32[^5] is the standard mechanism by which wallets for Bitcoin and
its derivatives (including Zcash\'s transparent addresses[^6]) generate
keys and addresses deterministically. This has several advantages over
random generation:
- Wallets only need to store a single seed (particularly useful for
hardware wallets).
- A one-time backup of the seed (usually stored as a word phrase[^7])
can be used to recover funds from all future addresses.
- Keys are arranged into a tree of chains, enabling wallets to
represent \"accounts\" or other high-level structures.
- View authority or spend authority can be delegated independently for
sub-trees without compromising the master seed.
At present, no such equivalent exists for Zcash\'s shielded addresses.
This is of particular concern for hardware wallets; all
currently-marketed devices only store a seed internally, and have
trained their users to only backup that seed. Given that the Sapling
upgrade will make it feasible to use hardware wallets with shielded
addresses, it is desirable to have a standard mechanism for deriving
them.
Conventions
===========
Most of the notation and functions used in this ZIP are defined in the
Sapling protocol specification [^8]. They are reproduced here for
convenience:
- truncate~k~(*S*) means the sequence formed from the first *k*
elements of *S*.
- *a* \|\| *b* means the concatenation of sequences *a* then *b*.
- \[*k*\] *P* means scalar multiplication of the elliptic curve point
*P* by the scalar *k*.
- LEOS2IP~l~(*S*) is the integer in range {0..2^l^-1} represented in
little-endian order by the byte sequence *S* of length *l*/8.
- I2LEBSP~l~(*k*) is the sequence of *l* bits representing *k* in
little-endian order.
- LEBS2OSP~l~(*B*) is defined as follows when *l* is a multiple of 8:
convert each group of 8 bits in *B* to a byte value with the least
significant bit first, and concatenate the resulting bytes in the
same order as the groups.
- repr~𝕁~(*P*) is the representation of the Jubjub elliptic curve
point *P* as a bit sequence, defined in[^9] section 5.4.8.3.
- BLAKE2b-256(*p*, *x*) refers to unkeyed BLAKE2b-256 in sequential
mode, with an output digest length of 32 bytes, 16-byte
personalization string *p*, and input *x*.
- BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential
mode, with an output digest length of 64 bytes, 16-byte
personalization string *p*, and input *x*.
- PRF^expand^(*sk*, *t*) := BLAKE2b-512(\"Zcash\_ExpandSeed\", *sk*
\|\| *t*)
- ToScalar(*x*) := LEOS2IP~512~(*x*) (mod *r*~𝕁~), where *r*~𝕁~ is the
order of the Jubjub large prime subgroup.
- DiversifyHash(*d*) maps a diversifier *d* to a base point on the
Jubjub elliptic curve, or to ⊥ if the diversifier is invalid. It is
instantiated in[^10] section 5.4.1.6.
The following algorithm standardized in[^11] is used:
- FF1-AES256.Encrypt(*key*, *tweak*, *x*) refers to the FF1 encryption
algorithm using AES with a 256-bit *key*, and parameters *radix* =
2, *minlen* = 88, *maxlen* = 88. It will be used only with the empty
string \"\" as the *tweak*. *x* is a sequence of 88 bits, as is the
output.
We also define the following conversion function:
- I2LEOSP~l~(*k*) is the byte sequence *S* of length *l*/8
representing in little-endian order the integer *k* in range
{0..2^l^-1}. It is the reverse operation of LEOS2IP~l~(*S*).
Implementors should note that this ZIP is consistently little-endian (in
keeping with the Sapling specification), which is the opposite of BIP
32.
We adapt the path notation of BIP 32[^12] to describe shielded HD paths,
using apostrophes to indicate hardened derivation (i\' = i + 2^31^) as
in BIP 44[^13]:
- CDKsk(CDKsk(CDKsk(m~Sprout~, a\'), b), c) is written as m~Sprout~ /
a\' / b / c
- CDKfvk(CDKfvk(CDKfvk(M~Sapling~, a), b), c) is written as M~Sapling~
/ a / b / c
Specification: Sapling key derivation
=====================================
Sapling extended keys
---------------------
BIP 32 defines a method to derive a number of child keys from a parent
key. In order to prevent these from depending solely on the parent key
itself, both the private and public keys are extended with a 32-byte
chain code. We similarly extend Sapling keys with a chain code here.
However, the concepts of \"private\" and \"public\" keys in BIP 32 do
not map cleanly to Sapling\'s key components. We take the following
approach:
- We derive child Sapling expanded spending keys, rather than Sapling
spending keys. This enables us to implement both hardened and
non-hardened derivation modes (the latter being incompatible with
Sapling spending keys).
- We do not derive Sapling public keys directly, as this would prevent
the use of diversified addresses. Instead, we derive Sapling full
viewing keys, from which payment addresses can be generated. This
maintains the trust semantics of BIP 32: someone with access to a
BIP 32 extended public key is able to view all transactions
involving that address, which a Sapling full viewing key also
enables.
We represent a Sapling extended spending key as (*ask*, *nsk*, *ovk*,
*dk*, *c*), where (*ask*, *nsk*, *ovk*) is the normal Sapling expanded
spending key, *dk* is a diversifier key, and *c* is the chain code.
We represent a Sapling extended full viewing key as (*ak*, *nk*, *ovk*,
*dk*, *c*), where (*ak*, *nk*, *ovk*) is the normal Sapling full viewing
key, *dk* is the same diversifier key as above, and *c* is the chain
code.
Helper functions
----------------
Define EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*) :=
I2LEOSP~256~(*ask*) \|\| I2LEOSP~256~(*nsk*) \|\| *ovk* \|\| *dk*.
Define EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*) :=
LEBS2OSP~256~(repr~𝕁~(*ak*)) \|\| LEBS2OSP~256~(repr~𝕁~(*nk*)) \|\|
*ovk* \|\| *dk*.
Master key generation
---------------------
Let *S* be a seed byte sequence of a chosen length, which MUST be at
least 32 bytes.
- Calculate *I* = BLAKE2b-512(\"ZcashIP32Sapling\", *S*).
- Split *I* into two 32-byte sequences, *I*~L~ and *I*~R~.
- Use *I*~L~ as the master spending key *sk*~m~, and *I*~R~ as the
master chain code *c*~m~.
- Calculate *ask*~m~, *nsk*~m~, and *ovk*~m~ via the standard Sapling
derivation [^14]:
- *ask*~m~ = ToScalar(PRF^expand^(*sk*~m~, \[0x00\]))
- *nsk*~m~ = ToScalar(PRF^expand^(*sk*~m~, \[0x01\]))
- *ovk*~m~ = truncate~32~(PRF^expand^(*sk*~m~, \[0x02\]))
- Calculate *dk*~m~ similarly:
- *dk*~m~ = truncate~32~(PRF^expand^(*sk*~m~, \[0x10\]))
- Return (*ask*~m~, *nsk*~m~, *ovk*~m~, *dk*~m~, *c*~m~) as the master
extended spending key *m*~Sapling~.
Child key derivation
--------------------
As in BIP 32, the method for deriving a child extended key, given a
parent extended key and an index *i*, depends on the type of key being
derived, and whether this is a hardened or non-hardened derivation.
### Deriving a child extended spending key
CDKsk((*ask*~par~, *nsk*~par~, *ovk*~par~, *dk*~par~, *c*~par~), *i*) →
(*ask*~i~, *nsk*~i~, *ovk*~i~, *dk*~i~, *c*~i~)
- Check whether *i* ≥ 2^31^ (whether the child is a hardened key).
- If so (hardened child): let *I* = PRF^expand^(*c*~par~, \[0x11\]
\|\| EncodeExtSKParts(*ask*~par~, *nsk*~par~, *ovk*~par~,
*dk*~par~) \|\| I2LEOSP~32~(*i*))
- If not (normal child): let *I* = PRF^expand^(*c*~par~, \[0x12\]
\|\| EncodeExtFVKParts(*ak*~par~, *nk*~par~, *ovk*~par~,
*dk*~par~) \|\| I2LEOSP~32~(*i*)) where (*nk*~par~, *ak*~par~,
*ovk*~par~) is the full viewing key derived from (*ask*~par~,
*nsk*~par~, *ovk*~par~) as described in[^15].
- Split *I* into two 32-byte sequences, *I*~L~ and *I*~R~.
- Let *I*~ask~ = ToScalar(PRF^expand^(*I*~L~, \[0x13\]))
- Let *I*~nsk~ = ToScalar(PRF^expand^(*I*~L~, \[0x14\]))
- Return:
- *ask*~i~ = *I*~ask~ + *ask*~par~
- *nsk*~i~ = *I*~nsk~ + *nsk*~par~
- *ovk*~i~ = truncate~32~(PRF^expand^(*I*~L~, \[0x15\] \|\|
*ovk*~par~))
- *dk*~i~ = truncate~32~(PRF^expand^(*I*~L~, \[0x16\] \|\|
*dk*~par~))
- *c*~i~ = *I*~R~
### Deriving a child extended full viewing key
Let 𝓖 be as defined in[^16] section 5.4.6.1 and let 𝓗 be as defined
in[^17].
CDKfvk((*ak*~par~, *nk*~par~, *ovk*~par~, *dk*~par~, *c*~par~), *i*) →
(*ak*~i~, *nk*~i~, *ovk*~i~, *dk*~i~, *c*~i~)
- Check whether *i* ≥ 2^31^ (whether the child is a hardened key).
- If so (hardened child): return failure
- If not (normal child): let *I* = PRF^expand^(*c*~par~, \[0x12\]
\|\| EncodeExtFVKParts(*ak*~par~, *nk*~par~, *ovk*~par~,
*dk*~par~) \|\| I2LEOSP~32~(*i*))
- Split *I* into two 32-byte sequences, *I*~L~ and *I*~R~.
- Let *I*~ask~ = ToScalar(PRF^expand^(*I*~L~, \[0x13\]))
- Let *I*~nsk~ = ToScalar(PRF^expand^(*I*~L~, \[0x14\]))
- Return:
- *ak*~i~ = \[*I*~ask~\] 𝓖 + *ak*~par~
- *nk*~i~ = \[*I*~nsk~\] 𝓗 + *nk*~par~
- *ovk*~i~ = truncate~32~(PRF^expand^(*I*~L~, \[0x15\] \|\|
*ovk*~par~))
- *dk*~i~ = truncate~32~(PRF^expand^(*I*~L~, \[0x16\] \|\|
*dk*~par~))
- *c*~i~ = *I*~R~
Diversifier derivation
----------------------
The 88-bit diversifiers for a Sapling extended key are derived from its
diversifier key *dk*. To prevent the diversifier leaking how many
diversified addresses have already been generated for an account, we
make the sequence of diversifiers pseudorandom and uncorrelated to that
of any other account. In order to reach the maximum possible diversifier
range without running into repetitions due to the birthday bound, we use
FF1-AES256 as a Pseudo-Random Permutation as follows:
- Let *j* be the index of the desired diversifier, in the range 0 ..
2^88^-1.
- *d*~j~ = FF1-AES256.Encrypt(*dk*, \"\", I2LEBSP~88~(*j*)).
A valid diversifier *d*~j~ is one for which DiversifyHash(*d*~j~) ≠ ⊥.
For a given *dk*, approximately half of the possible values of *j* yield
valid diversifiers.
The default diversifier for a Sapling extended key is defined to be
*d*~j~, where *j* is the least nonnegative integer yielding a valid
diversifier.
Specification: Sprout key derivation
====================================
For completeness, we define a system for deriving a tree of Sprout key
components. It is unlikely that this will garner much usage once Sapling
activates, but is presented for those users who may require it.
Sprout extended keys
--------------------
Due to the way Sprout keys are constructed and used, it is not possible
to derive incoming viewing keys or payment addresses in parallel with
spending keys. Nor is it possible to implement non-hardened derivation.
We therefore only define and derive Sprout extended spending keys.
We represent a Sprout extended spending key as (*a*~sk~, *c*), where
*a*~sk~ is the normal Sprout spending key, and *c* is the chain code.
Helper functions
----------------
Let EncodeASK(*a*~sk~) be the 32-byte encoding of *a*~sk~ in the raw
encoding of a Sprout spending key (excluding lead bytes) as specified
in[^18] section 5.6.8.
Let DecodeASK(*ASK*) be the result of clearing the 4 most significant
bits of the first byte of *ASK*, and decoding the 32-byte result
according to the inverse of EncodeASK.
Master key generation
---------------------
Let *S* be a seed byte sequence of a chosen length, which MUST be at
least 32 bytes.
- Calculate *I* = BLAKE2b-512(\"ZcashIP32\_Sprout\", *S*).
- Split *I* into two 32-byte sequences, I~L~ and I~R~.
- Use DecodeASK(*I*~L~) as the master spending key a~sk,m~.
- Use *I*~R~ as the master chain code *c*~m~.
Child key derivation
--------------------
CDKsk((*a*~sk,par~, *c*~par~), *i*) → (*a*~sk,i~, *c*~i~)
- Check whether *i* ≥ 2^31^ (whether the child is a hardened key).
- If so (hardened child): let *I* = PRF^expand^(*c*~par~, \[0x80\]
\|\| EncodeASK(*a*~sk,par~) \|\| I2LEOSP~32~(*i*))
- If not (normal child): return failure
- Split *I* into two 32-byte sequences, *I*~L~ and *I*~R~.
- Use DecodeASK(*I*~L~) as the child spending key a~sk,i~.
- Use *I*~R~ as the child chain code *c*~i~.
Specification: Wallet usage
===========================
Existing Zcash-supporting HD wallets all use BIP 44[^19] to organize
their derived keys. In order to more easily mesh with existing user
experiences, we broadly follow BIP 44\'s design here. However, we have
altered the design where it makes sense to leverage features of shielded
addresses.
Key path levels
---------------
Both Sprout and Sapling key paths have the following three path levels
at the top, all of which use hardened derivation:
- `purpose`: a constant set to 32\' (or 0x80000020) following the BIP
43 recommendation. It indicates that the subtree of this node is
used according to this specification.
- `coin_type`: a constant identifying the cybercoin that this
subtree\'s keys are used with. For compatibility with existing BIP
44 implementations, we use the same constants as defined in SLIP 44
[^20]. Note that in keeping with that document, all cybercoin
testnets share `coin_type` index 1.
- `account`: numbered from index 0 in sequentially increasing manner.
Defined as in BIP 44[^21].
Unlike BIP 44, neither Sprout nor Sapling have a change path level. The
use of change addresses in Bitcoin is a (failed) attempt to increase the
difficulty of tracking users on the transaction graph, by segregating
external and internal address usage. Shielded addresses are never
publicly visible in transactions, which means that sending change back
to the originating address is indistinguishable from using a change
address.
Sapling key path
----------------
Sapling provides a mechanism to allow the efficient creation of
diversified payment addresses with the same spending authority. A group
of such addresses shares the same full viewing key and incoming viewing
key, and so creating as many unlinkable addresses as needed does not
increase the cost of scanning the block chain for relevant transactions.
The above key path levels include an account identifier, which in all
user interfaces is represented as a \"bucket of funds\" under the
control of a single spending authority. Therefore, wallets implementing
Sapling ZIP 32 derivation MUST support the following path for any
account in range {0..2^31^-1}:
m_Sapling / purpose' / coin_type' / account'
Furthermore, wallets MUST support generating the default payment address
(corresponding to the default diversifier as defined above) for any
account they support. They MAY also support generating a stream of
payment addresses for a given account, if they wish to maintain the user
experience of giving a unique address to each recipient.
Note that a given account can have a maximum of approximately 2^87^
payment addresses, because each diversifier has around a 50% chance of
being invalid.
If in certain circumstances a wallet needs to derive independent spend
authorities within a single account, they MAY additionally support a
non-hardened `address_index` path level as in[^22]:
m_Sapling / purpose' / coin_type' / account' / address_index
Sprout key path
---------------
Wallets implementing Sprout ZIP 32 derivation MUST support the following
path:
m_Sprout / purpose' / coin_type' / account' / address_index
Specification: Fingerprints and Tags
====================================
Sapling Full Viewing Key Fingerprints and Tags
----------------------------------------------
A \"Sapling full viewing key fingerprint\" of a full viewing key with
raw encoding *FVK* (as specified in[^23] section 5.6.7) is given by:
> BLAKE2b-256(\"ZcashSaplingFVFP\", *FVK*)
It MAY be used to uniquely identify a particular Sapling full viewing
key.
A \"Sapling full viewing key tag\" is the first 4 bytes of the
corresponding Sapling full viewing key fingerprint. It is intended for
optimizing performance of key lookups, and MUST NOT be assumed to
uniquely identify a particular key.
Sprout Address Fingerprints and Tags
------------------------------------
A \"Sprout address fingerprint\" of a Sprout payment address with raw
encoding *ADDR* (as specified in [^24] section 5.6.3, including the lead
bytes) is given by:
> BLAKE2b-256(\"Zcash\_Sprout\_AFP\", *ADDR*)
It MAY be used to uniquely identify a particular Sprout payment address.
A \"Sprout address tag\" is the first 4 bytes of the corresponding
Sprout address fingerprint. It is intended for optimizing performance of
address lookups, and MUST NOT be assumed to uniquely identify a
particular address.
Seed Fingerprints
-----------------
A \"seed fingerprint\" for the master seed *S* of a hierarchical
deterministic wallet is given by:
> BLAKE2b-256(\"Zcash\_HD\_Seed\_FP\", *S*)
It MAY be used to uniquely identify a particular hierarchical
deterministic wallet.
No corresponding short tag is defined.
Specification: Key Encodings
============================
The following encodings are analogous to the `xprv` and `xpub` encodings
defined in BIP 32 for transparent keys and addresses. Each key type has
a raw representation and a Bech32[^25] encoding.
Sapling extended spending keys
------------------------------
A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at
depth *depth*, with parent full viewing key tag *parent\_fvk\_tag* and
child number *i*, is represented as a byte sequence:
> I2LEOSP~8~(*depth*) \|\| *parent\_fvk\_tag* \|\| I2LEOSP~32~(*i*) \|\|
> *c* \|\| EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*)
For the master extended spending key, *depth* is 0, *parent\_fvk\_tag*
is 4 zero bytes, and *i* is 0.
When encoded as Bech32, the Human-Readable Part is
`secret-extended-key-main` for the production network, or
`secret-extended-key-test` for the test network.
Sapling extended full viewing keys
----------------------------------
A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at
depth *depth*, with parent full viewing key tag *parent\_fvk\_tag* and
child number *i*, is represented as a byte sequence:
> I2LEOSP~8~(*depth*) \|\| *parent\_fvk\_tag* \|\| I2LEOSP~32~(*i*) \|\|
> *c* \|\| EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*)
For the master extended full viewing key, *depth* is 0,
*parent\_fvk\_tag* is 4 zero bytes, and *i* is 0.
When encoded as Bech32, the Human-Readable Part is `zxviews` for the
production network, or `zxviewtestsapling` for the test network.
Sprout extended spending keys
-----------------------------
A Sprout extended spending key (*a*~sk~, *c*), at depth *depth*, with
parent address tag *parent\_addr\_tag* and child number *i*, is
represented as a byte sequence:
> I2LEOSP~8~(*depth*) \|\| *parent\_addr\_tag* \|\| I2LEOSP~32~(*i*)
> \|\| *c* \|\| EncodeASK(*a*~sk~)
For the master extended spending key, *depth* is 0, *parent\_addr\_tag*
is 4 zero bytes, and *i* is 0.
When encoded as Bech32, the Human-Readable Part is `zxsprout` for the
production network, or `zxtestsprout` for the test network. Sprout
extended spending keys are encoded using Bech32 even though other Sprout
keys and addresses are encoded using Base58Check.
Test Vectors
============
TBC
Reference Implementation
========================
- <https://github.com/zcash-hackworks/zip32>
- <https://github.com/zcash/librustzcash/pull/29>
- <https://github.com/zcash/zcash/pull/3447>
- <https://github.com/zcash/zcash/pull/3492>
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^3]: [BIP 32: Hierarchical Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
[^4]: [BIP 44: Multi-Account Hierarchy for Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
[^5]: [BIP 32: Hierarchical Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
[^6]: [SLIP 44: Registered coin types for
BIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
[^7]: [BIP 39: Mnemonic code for generating deterministic
keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
[^8]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^9]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^10]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^11]: [NIST Special Publication 800-38G \-- Recommendation for Block
Cipher Modes of Operation: Methods for Format-Preserving
Encryption](https://dx.doi.org/10.6028/NIST.SP.800-38G)
[^12]: [BIP 32: Hierarchical Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
[^13]: [BIP 44: Multi-Account Hierarchy for Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
[^14]: [Section 4.2.2: Sapling Key Components. Zcash Protocol
Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^15]: [Section 4.2.2: Sapling Key Components. Zcash Protocol
Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^16]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^17]: [Section 4.2.2: Sapling Key Components. Zcash Protocol
Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^18]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^19]: [BIP 44: Multi-Account Hierarchy for Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
[^20]: [SLIP 44: Registered coin types for
BIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
[^21]: [BIP 44: Multi-Account Hierarchy for Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
[^22]: [BIP 44: Multi-Account Hierarchy for Deterministic
Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
[^23]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^24]: [Zcash Protocol Specification, Version 2018.0-beta-25 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^25]: [BIP 173: Base32 address format for native v0-16 witness
outputs](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)

View File

@ -1,265 +0,0 @@
<pre>
BIP: 68
Layer: Consensus (soft fork)
Title: Relative lock-time using consensus-enforced sequence numbers
Author: Mark Friedenbach <mark@friedenbach.org>
BtcDrak <btcdrak@gmail.com>
Nicolas Dorier <nicolas.dorier@gmail.com>
kinoshitajona <kinoshitajona@gmail.com>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0068
Status: Final
Type: Standards Track
Created: 2015-05-28
</pre>
==Abstract==
This BIP introduces relative lock-time (RLT) consensus-enforced semantics of the sequence number field to enable a signed transaction input to remain invalid for a defined period of time after confirmation of its corresponding outpoint.
==Motivation==
Bitcoin transactions have a sequence number field for each input. The original idea appears to have been that a transaction in the mempool would be replaced by using the same input with a higher sequence value. Although this was not properly implemented, it assumes miners would prefer higher sequence numbers even if the lower ones were more profitable to mine. However, a miner acting on profit motives alone would break that assumption completely. The change described by this BIP repurposes the sequence number for new use cases without breaking existing functionality. It also leaves room for future expansion and other use cases.
The transaction nLockTime is used to prevent the mining of a transaction until a certain date. nSequence will be repurposed to prevent mining of a transaction until a certain age of the spent output in blocks or timespan. This, among other uses, allows bi-directional payment channels as used in [https://github.com/ElementsProject/lightning/raw/master/doc/deployable-lightning.pdf Hashed Timelock Contracts (HTLCs)] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki#Bidirectional_Payment_Channels BIP112].
==Specification==
This specification defines the meaning of sequence numbers for transactions with an nVersion greater than or equal to 2 for which the rest of this specification relies on.
All references to median-time-past (MTP) are as defined by BIP113.
If bit (1 << 31) of the sequence number is set, then no consensus meaning is applied to the sequence number and can be included in any block under all currently possible circumstances.
If bit (1 << 31) of the sequence number is not set, then the sequence number is interpreted as an encoded relative lock-time.
The sequence number encoding is interpreted as follows:
Bit (1 << 22) determines if the relative lock-time is time-based or block based: If the bit is set, the relative lock-time specifies a timespan in units of 512 seconds granularity. The timespan starts from the median-time-past of the outputs previous block, and ends at the MTP of the previous block. If the bit is not set, the relative lock-time specifies a number of blocks.
The flag (1<<22) is the highest order bit in a 3-byte signed integer for use in bitcoin scripts as a 3-byte PUSHDATA with OP_CHECKSEQUENCEVERIFY (BIP 112).
This specification only interprets 16 bits of the sequence number as relative lock-time, so a mask of 0x0000ffff MUST be applied to the sequence field to extract the relative lock-time. The 16-bit specification allows for a year of relative lock-time and the remaining bits allow for future expansion.
<img src=bip-0068/encoding.png></img>
For time based relative lock-time, 512 second granularity was chosen because bitcoin blocks are generated every 600 seconds. So when using block-based or time-based, the same amount of time can be encoded with the available number of bits. Converting from a sequence number to seconds is performed by multiplying by 512 = 2^9, or equivalently shifting up by 9 bits.
When the relative lock-time is time-based, it is interpreted as a minimum block-time constraint over the input's age. A relative time-based lock-time of zero indicates an input which can be included in any block. More generally, a relative time-based lock-time n can be included into any block produced 512 * n seconds after the mining date of the output it is spending, or any block thereafter.
The mining date of the output is equal to the median-time-past of the previous block which mined it.
The block produced time is equal to the median-time-past of its previous block.
When the relative lock-time is block-based, it is interpreted as a minimum block-height constraint over the input's age. A relative block-based lock-time of zero indicates an input which can be included in any block. More generally, a relative block lock-time n can be included n blocks after the mining date of the output it is spending, or any block thereafter.
The new rules are not applied to the nSequence field of the input of the coinbase transaction.
==Implementation==
A reference implementation is provided by the following pull request
https://github.com/bitcoin/bitcoin/pull/7184
<pre>
enum {
/* Interpret sequence numbers as relative lock-time constraints. */
LOCKTIME_VERIFY_SEQUENCE = (1 << 0),
};
/* Setting nSequence to this value for every input in a transaction
* disables nLockTime. */
static const uint32_t SEQUENCE_FINAL = 0xffffffff;
/* Below flags apply in the context of BIP 68*/
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. */
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1. */
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
/* In order to use the same number of bits to encode roughly the
* same wall-clock duration, and because blocks are naturally
* limited to occur every 600s on average, the minimum granularity
* for time-based relative lock-time is fixed at 512 seconds.
* Converting from CTxIn::nSequence to seconds is performed by
* multiplying by 512 = 2^9, or equivalently shifting up by
* 9 bits. */
static const int SEQUENCE_LOCKTIME_GRANULARITY = 9;
/**
* Calculates the block height and previous block's median time past at
* which the transaction will be considered final in the context of BIP 68.
* Also removes from the vector of input heights any entries which did not
* correspond to sequence locked inputs as they do not affect the calculation.
*/
static std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
assert(prevHeights->size() == tx.vin.size());
// Will be set to the equivalent height- and time-based nLockTime
// values that would be necessary to satisfy all relative lock-
// time constraints given our view of block chain history.
// The semantics of nLockTime are the last invalid height/time, so
// use -1 to have the effect of any height or time being valid.
int nMinHeight = -1;
int64_t nMinTime = -1;
// tx.nVersion is signed integer so requires cast to unsigned otherwise
// we would be doing a signed comparison and half the range of nVersion
// wouldn't support BIP 68.
bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
&& flags & LOCKTIME_VERIFY_SEQUENCE;
// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to
if (!fEnforceBIP68) {
return std::make_pair(nMinHeight, nMinTime);
}
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
const CTxIn& txin = tx.vin[txinIndex];
// Sequence numbers with the most significant bit set are not
// treated as relative lock-times, nor are they given any
// consensus-enforced meaning at this point.
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
// The height of this input is not relevant for sequence locks
(*prevHeights)[txinIndex] = 0;
continue;
}
int nCoinHeight = (*prevHeights)[txinIndex];
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
// NOTE: Subtract 1 to maintain nLockTime semantics
// BIP 68 relative lock times have the semantics of calculating
// the first block or time at which the transaction would be
// valid. When calculating the effective block time or height
// for the entire transaction, we switch to using the
// semantics of nLockTime which is the last invalid block
// time or height. Thus we subtract 1 from the calculated
// time or height.
// Time-based relative lock-times are measured from the
// smallest allowed timestamp of the block containing the
// txout being spent, which is the median time past of the
// block prior.
nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
} else {
nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
}
}
return std::make_pair(nMinHeight, nMinTime);
}
static bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
assert(block.pprev);
int64_t nBlockTime = block.pprev->GetMedianTimePast();
if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
return false;
return true;
}
bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}
bool CheckSequenceLocks(const CTransaction &tx, int flags)
{
AssertLockHeld(cs_main);
AssertLockHeld(mempool.cs);
CBlockIndex* tip = chainActive.Tip();
CBlockIndex index;
index.pprev = tip;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
// height based locks because when SequenceLocks() is called within
// ConnectBlock(), the height of the block *being*
// evaluated is what is used.
// Thus if we want to know if a transaction can be part of the
// *next* block, we need to use one more than chainActive.Height()
index.nHeight = tip->nHeight + 1;
// pcoinsTip contains the UTXO set for chainActive.Tip()
CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
std::vector<int> prevheights;
prevheights.resize(tx.vin.size());
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
const CTxIn& txin = tx.vin[txinIndex];
CCoins coins;
if (!viewMemPool.GetCoins(txin.prevout.hash, coins)) {
return error("%s: Missing input", __func__);
}
if (coins.nHeight == MEMPOOL_HEIGHT) {
// Assume all mempool transaction confirm in the next block
prevheights[txinIndex] = tip->nHeight + 1;
} else {
prevheights[txinIndex] = coins.nHeight;
}
}
std::pair<int, int64_t> lockPair = CalculateSequenceLocks(tx, flags, &prevheights, index);
return EvaluateSequenceLocks(index, lockPair);
}
</pre>
==Acknowledgments==
Credit goes to Gregory Maxwell for providing a succinct and clear description of the behavior of this change, which became the basis of this BIP text.
This BIP was edited by BtcDrak, Nicolas Dorier and kinoshitajona.
==Deployment==
This BIP is to be deployed by "versionbits" BIP9 using bit 0.
For Bitcoin '''mainnet''', the BIP9 '''starttime''' will be midnight 1st May 2016 UTC (Epoch timestamp 1462060800) and BIP9 '''timeout''' will be midnight 1st May 2017 UTC (Epoch timestamp 1493596800).
For Bitcoin '''testnet''', the BIP9 '''starttime''' will be midnight 1st March 2016 UTC (Epoch timestamp 1456790400) and BIP9 '''timeout''' will be midnight 1st May 2017 UTC (Epoch timestamp 1493596800).
This BIP must be deployed simultaneously with BIP112 and BIP113 using the same deployment mechanism.
==Compatibility==
The only use of sequence numbers by the Bitcoin Core reference client software is to disable checking the nLockTime constraints in a transaction. The semantics of that application are preserved by this BIP.
As can be seen from the specification section, a number of bits are undefined by this BIP to allow for other use cases by setting bit (1 << 31) as the remaining 31 bits have no meaning under this BIP. Additionally, bits (1 << 23) through (1 << 30) inclusive have no meaning at all when bit (1 << 31) is unset.
Additionally, this BIP specifies only 16 bits to actually encode relative lock-time meaning a further 6 are unused (1 << 16 through 1 << 21 inclusive). This allows the possibility to increase granularity by soft-fork, or for increasing the maximum possible relative lock-time in the future.
The most efficient way to calculate sequence number from relative lock-time is with bit masks and shifts:
<pre>
// 0 <= nHeight < 65,535 blocks (1.25 years)
nSequence = nHeight;
nHeight = nSequence & 0x0000ffff;
// 0 <= nTime < 33,554,431 seconds (1.06 years)
nSequence = (1 << 22) | (nTime >> 9);
nTime = (nSequence & 0x0000ffff) << 9;
</pre>
==References==
Bitcoin mailing list discussion: https://www.mail-archive.com/bitcoin-development@lists.sourceforge.net/msg07864.html
BIP9: https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki
BIP112: https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
BIP113: https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
Hashed Timelock Contracts (HTLCs): https://github.com/ElementsProject/lightning/raw/master/doc/deployable-lightning.pdf

View File

@ -1,400 +0,0 @@
<pre>
BIP: 112
Layer: Consensus (soft fork)
Title: CHECKSEQUENCEVERIFY
Author: BtcDrak <btcdrak@gmail.com>
Mark Friedenbach <mark@friedenbach.org>
Eric Lombrozo <elombrozo@gmail.com>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0112
Status: Final
Type: Standards Track
Created: 2015-08-10
License: PD
</pre>
==Abstract==
This BIP describes a new opcode (CHECKSEQUENCEVERIFY) for the Bitcoin
scripting system that in combination with BIP 68 allows execution
pathways of a script to be restricted based on the age of the output
being spent.
==Summary==
CHECKSEQUENCEVERIFY redefines the existing NOP3 opcode.
When executed, if any of the following conditions are true, the script interpreter will terminate with an error:
* the stack is empty; or
* the top item on the stack is less than 0; or
* the top item on the stack has the disable flag (1 << 31) unset; and
** the transaction version is less than 2; or
** the transaction input sequence number disable flag (1 << 31) is set; or
** the relative lock-time type is not the same; or
** the top stack item is greater than the transaction input sequence (when masked according to the BIP68);
Otherwise, script execution will continue as if a NOP had been executed.
BIP 68 prevents a non-final transaction from being selected for inclusion in a block until the corresponding input has reached the specified age, as measured in block-height or block-time. By comparing the argument to CHECKSEQUENCEVERIFY against the nSequence field, we indirectly verify a desired minimum age of the
the output being spent; until that relative age has been reached any script execution pathway including the CHECKSEQUENCEVERIFY will fail to validate, causing the transaction not to be selected for inclusion in a block.
==Motivation==
BIP 68 repurposes the transaction nSequence field meaning by giving
sequence numbers new consensus-enforced semantics as a relative
lock-time. However, there is no way to build Bitcoin scripts to make
decisions based on this field.
By making the nSequence field accessible to script, it becomes
possible to construct code pathways that only become accessible some
minimum time after proof-of-publication. This enables a wide variety
of applications in phased protocols such as escrow, payment channels,
or bidirectional pegs.
===Contracts With Expiration Deadlines===
====Escrow with Timeout====
An escrow that times out automatically 30 days after being funded can be
established in the following way. Alice, Bob and Escrow create a 2-of-3
address with the following redeemscript.
IF
2 <Alice's pubkey> <Bob's pubkey> <Escrow's pubkey> 3 CHECKMULTISIG
ELSE
"30d" CHECKSEQUENCEVERIFY DROP
<Alice's pubkey> CHECKSIG
ENDIF
At any time funds can be spent using signatures from any two of Alice,
Bob or the Escrow.
After 30 days Alice can sign alone.
The clock does not start ticking until the payment to the escrow address
confirms.
===Retroactive Invalidation===
In many instances, we would like to create contracts that can be revoked in case
of some future event. However, given the immutable nature of the blockchain, it
is practically impossible to retroactively invalidate a previous commitment that
has already confirmed. The only mechanism we really have for retroactive
invalidation is blockchain reorganization which, for fundamental security
reasons, is designed to be very hard and very expensive to do.
Despite this limitation, we do have a way to provide something functionally similar to retroactive invalidation while preserving irreversibility of past commitments
using CHECKSEQUENCEVERIFY. By constructing scripts with multiple branches of
execution where one or more of the branches are delayed we provide
a time window in which someone can supply an invalidation condition that allows the
output to be spent, effectively invalidating the would-be delayed branch and potentially discouraging
another party from broadcasting the transaction in the first place. If the invalidation
condition does not occur before the timeout, the delayed branch becomes spendable,
honoring the original contract.
Some more specific applications of this idea:
====Hash Time-Locked Contracts====
Hash Time-Locked Contracts (HTLCs) provide a general mechanism for off-chain contract negotiation. An execution pathway can be made to require knowledge of a secret (a hash preimage) that can be presented within an invalidation time window. By sharing the secret it is possible to guarantee to the counterparty that the transaction will never be broadcast since this would allow the counterparty to claim the output immediately while one would have to wait for the time window to pass. If the secret has not been shared, the counterparty will be unable to use the instant pathway and the delayed pathway must be used instead.
====Bidirectional Payment Channels====
Scriptable relative locktime provides a predictable amount of time to respond in
the event a counterparty broadcasts a revoked transaction: Absolute locktime
necessitates closing the channel and reopen it when getting close to the timeout,
whereas with relative locktime, the clock starts ticking the moment the
transactions confirms in a block. It also provides a means to know exactly how
long to wait (in number of blocks) before funds can be pulled out of the channel
in the event of a noncooperative counterparty.
====Lightning Network====
The lightning network extends the bidirectional payment channel idea to allow for payments to be routed over multiple bidirectional payment channel hops.
These channels are based on an anchor transaction that requires a 2-of-2
multisig from Alice and Bob, and a series of revocable commitment
transactions that spend the anchor transaction. The commitment
transaction splits the funds from the anchor between Alice and Bob and
the latest commitment transaction may be published by either party at
any time, finalising the channel.
Ideally then, a revoked commitment transaction would never be able to
be successfully spent; and the latest commitment transaction would be
able to be spent very quickly.
To allow a commitment transaction to be effectively revoked, Alice
and Bob have slightly different versions of the latest commitment
transaction. In Alice's version, any outputs in the commitment
transaction that pay Alice also include a forced delay, and an
alternative branch that allows Bob to spend the output if he knows that
transaction's revocation code. In Bob's version, payments to Bob are
similarly encumbered. When Alice and Bob negotiate new balances and
new commitment transactions, they also reveal the old revocation code,
thus committing to not relaying the old transaction.
A simple output, paying to Alice might then look like:
HASH160 <revokehash> EQUAL
IF
<Bob's pubkey>
ELSE
"24h" CHECKSEQUENCEVERIFY DROP
<Alice's pubkey>
ENDIF
CHECKSIG
This allows Alice to publish the latest commitment transaction at any
time and spend the funds after 24 hours, but also ensures that if Alice
relays a revoked transaction, that Bob has 24 hours to claim the funds.
With CHECKLOCKTIMEVERIFY, this would look like:
HASH160 <revokehash> EQUAL
IF
<Bob's pubkey>
ELSE
"2015/12/15" CHECKLOCKTIMEVERIFY DROP
<Alice's pubkey>
ENDIF
CHECKSIG
This form of transaction would mean that if the anchor is unspent on
2015/12/16, Alice can use this commitment even if it has been revoked,
simply by spending it immediately, giving no time for Bob to claim it.
This means that the channel has a deadline that cannot be pushed
back without hitting the blockchain; and also that funds may not be
available until the deadline is hit. CHECKSEQUENCEVERIFY allows you
to avoid making such a tradeoff.
Hashed Time-Lock Contracts (HTLCs) make this slightly more complicated,
since in principle they may pay either Alice or Bob, depending on whether
Alice discovers a secret R, or a timeout is reached, but the same principle
applies -- the branch paying Alice in Alice's commitment transaction gets a
delay, and the entire output can be claimed by the other party if the
revocation secret is known. With CHECKSEQUENCEVERIFY, a HTLC payable to
Alice might look like the following in Alice's commitment transaction:
HASH160 DUP <R-HASH> EQUAL
IF
"24h" CHECKSEQUENCEVERIFY
2DROP
<Alice's pubkey>
ELSE
<Commit-Revocation-Hash> EQUAL
NOTIF
"2015/10/20 10:33" CHECKLOCKTIMEVERIFY DROP
ENDIF
<Bob's pubkey>
ENDIF
CHECKSIG
and correspondingly in Bob's commitment transaction:
HASH160 DUP <R-HASH> EQUAL
SWAP <Commit-Revocation-Hash> EQUAL ADD
IF
<Alice's pubkey>
ELSE
"2015/10/20 10:33" CHECKLOCKTIMEVERIFY
"24h" CHECKSEQUENCEVERIFY
2DROP
<Bob's pubkey>
ENDIF
CHECKSIG
Note that both CHECKSEQUENCEVERIFY and CHECKLOCKTIMEVERIFY are used in the
final branch of above to ensure Bob cannot spend the output until after both
the timeout is complete and Alice has had time to reveal the revocation
secret.
See the [https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf Deployable Lightning] paper.
====2-Way Pegged Sidechains====
The 2-way pegged sidechain requires a new REORGPROOFVERIFY opcode, the semantics of which are outside the scope of this BIP. CHECKSEQUENCEVERIFY is used to make sure that sufficient time has passed since the return peg was posted to publish a reorg proof:
IF
lockTxHeight <lockTxHash> nlocktxOut [<workAmount>] reorgBounty Hash160(<...>) <genesisHash> REORGPROOFVERIFY
ELSE
withdrawLockTime CHECKSEQUENCEVERIFY DROP HASH160 p2shWithdrawDest EQUAL
ENDIF
==Specification==
Refer to the reference implementation, reproduced below, for the precise
semantics and detailed rationale for those semantics.
<pre>
/* Below flags apply in the context of BIP 68 */
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. */
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1. */
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
case OP_NOP3:
{
if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
// not enabled; treat as a NOP3
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
}
break;
}
if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// Note that elsewhere numeric opcodes are limited to
// operands in the range -2**31+1 to 2**31-1, however it is
// legal for opcodes to produce results exceeding that
// range. This limitation is implemented by CScriptNum's
// default 4-byte limit.
//
// Thus as a special case we tell CScriptNum to accept up
// to 5-byte bignums, which are good until 2**39-1, well
// beyond the 2**32-1 limit of the nSequence field itself.
const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
// In the rare event that the argument may be < 0 due to
// some arithmetic being done first, you can always use
// 0 MAX CHECKSEQUENCEVERIFY.
if (nSequence < 0)
return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
// To provide for future soft-fork extensibility, if the
// operand has the disabled lock-time flag set,
// CHECKSEQUENCEVERIFY behaves as a NOP.
if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
break;
// Compare the specified sequence number with the input.
if (!checker.CheckSequence(nSequence))
return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
break;
}
bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
{
// Relative lock times are supported by comparing the passed
// in operand to the sequence number of the input.
const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
// Fail if the transaction's version number is not set high
// enough to trigger BIP 68 rules.
if (static_cast<uint32_t>(txTo->nVersion) < 2)
return false;
// Sequence numbers with their most significant bit set are not
// consensus constrained. Testing that the transaction's sequence
// number do not have this bit set prevents using this property
// to get around a CHECKSEQUENCEVERIFY check.
if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
return false;
// Mask off any bits that do not have consensus-enforced meaning
// before doing the integer comparisons
const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
// There are two kinds of nSequence: lock-by-blockheight
// and lock-by-blocktime, distinguished by whether
// nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
//
// We want to compare apples to apples, so fail the script
// unless the type of nSequenceMasked being tested is the same as
// the nSequenceMasked in the transaction.
if (!(
(txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
(txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
))
return false;
// Now that we know we're comparing apples-to-apples, the
// comparison is a simple numeric one.
if (nSequenceMasked > txToSequenceMasked)
return false;
return true;
}
</pre>
==Reference Implementation==
A reference implementation is provided by the following pull request:
https://github.com/bitcoin/bitcoin/pull/7524
==Deployment==
This BIP is to be deployed by "versionbits" BIP9 using bit 0.
For Bitcoin '''mainnet''', the BIP9 '''starttime''' will be midnight 1st May 2016 UTC (Epoch timestamp 1462060800) and BIP9 '''timeout''' will be midnight 1st May 2017 UTC (Epoch timestamp 1493596800).
For Bitcoin '''testnet''', the BIP9 '''starttime''' will be midnight 1st March 2016 UTC (Epoch timestamp 1456790400) and BIP9 '''timeout''' will be midnight 1st May 2017 UTC (Epoch timestamp 1493596800).
This BIP must be deployed simultaneously with BIP68 and BIP113 using the same deployment mechanism.
==Credits==
Mark Friedenbach invented the application of sequence numbers to
achieve relative lock-time, and wrote the reference implementation of
CHECKSEQUENCEVERIFY.
The reference implementation and this BIP was based heavily on work
done by Peter Todd for the closely related BIP 65.
BtcDrak authored this BIP document.
Thanks to Eric Lombrozo and Anthony Towns for contributing example use cases.
==References==
[https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki BIP 9] Versionbits
[https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki BIP 68] Relative lock-time through consensus-enforced sequence numbers
[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP 65] OP_CHECKLOCKTIMEVERIFY
[https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki BIP 113] Median past block time for time-lock constraints
[http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and revocation hashes]
[http://lightning.network/lightning-network-paper.pdf Lightning Network]
[https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf Deployable Lightning]
[http://diyhpl.us/diyhpluswiki/transcripts/sf-bitcoin-meetup/2015-02-23-scaling-bitcoin-to-billions-of-transactions-per-day/ Scaling Bitcoin to Billions of Transactions Per Day]
[http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html Softfork deployment considerations]
[https://gist.github.com/sipa/bf69659f43e763540550 Version bits]
[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2013-April/002433.html Jeremy Spilman Micropayment Channels]
==Copyright==
This document is placed in the public domain.

427
zip-0143.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

190
zip-0200.html Normal file
View File

@ -0,0 +1,190 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0200</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(title);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
</head>
<body>
<pre><code>ZIP: 200
Title: Network Upgrade Mechanism
Owners: Jack Grigg &lt;str4d@electriccoin.co&gt;
Status: Final
Category: Consensus
Created: 2018-01-08
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>Block chain</dt>
<dd><p>A sequence of blocks starting at the genesis block, where the header of each block refers to the previous block in the sequence.</p>
</dd>
<dt>Consensus rule set</dt>
<dd><p>A set of validation rules that determine which block chains are considered valid.</p>
</dd>
<dt>Consensus rule change</dt>
<dd><p>A change in the consensus rule set of the network, such that nodes that do not recognize the new rules will follow a different block chain.</p>
</dd>
<dt>Branch</dt>
<dd><p>A block chain with a common consensus rule set, where the first block in the chain is either the genesis block, or the child of a parent block created under an older set of consensus rules (i.e. the parent block is a member of a different branch). By definition, every block belongs to at most one branch.</p>
</dd>
<dt>Network upgrade</dt>
<dd><p>An intentional consensus rule change undertaken by the community in order to improve the network.</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines a mechanism for coordinating upgrades of the Zcash network, in order to remove ambiguity about when network upgrades will activate, provide defined periods in which users should upgrade their local software, and minimize the risks to both the upgrading network and any users opting out of the changes.</p>
<h1 id="motivation">Motivation</h1>
<p>Zcash is a <em>consensual currency</em>: nobody is ever going to force someone to use a specific software implementation or a specific branch of Zcash.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> As such, different sub-communities will always have the freedom to choose different variants or branches which offer different design trade-offs.</p>
<p>The current Zcash software includes an <em>auto-senescence</em> feature, causing nodes running a particular version to automatically shut down approximately 16 weeks after that version was released (specifically, at the block height <code>DEPRECATION_HEIGHT</code> defined in the source code for that version). This was implemented for several reasons:<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a></p>
<ul>
<li>It gives the same systemic advantage of removing old software as auto-upgrade behavior.</li>
<li>It requires users to individually choose one of the following options:
<ul>
<li>Upgrade to a more recent software release from the main network.</li>
<li>Upgrade to an alternative release.</li>
<li>Modify their node in order to keep running the older software.</li>
</ul></li>
</ul>
<p>Developers can rely on this cadence for coordinating network upgrades. Once the last pre-upgrade software version has been deprecated, they can reasonably assume that all node operators on the network either support the upgraded rules, or have explicitly chosen not to follow them.</p>
<p>However, this behaviour is not sufficient for performing network upgrades. A globally-understood on-chain activation mechanism is necessary so that nodes can unambiguously know at what point the changes from an upgrade come into effect (and can enforce consensus rule changes, for example).</p>
<h1 id="specification">Specification</h1>
<p>The following constants are defined for every network upgrade:</p>
<dl>
<dt>BRANCH_ID</dt>
<dd><p>A globally-unique non-zero 32-bit identifier.</p>
<p>Implementations MAY use a value of zero in branch ID fields to indicate the absence of any upgrade (i.e. that the Sprout consensus rules apply).</p>
</dd>
<dt>ACTIVATION_HEIGHT</dt>
<dd><p>The non-zero block height at which the network upgrade rules will come into effect, and be enforced as part of the block chain consensus.</p>
<p>For removal of ambiguity, the block at height <code>ACTIVATION_HEIGHT - 1</code> is subject to the pre-upgrade consensus rules, and would be the last common block in the event of a persistent pre-upgrade branch.</p>
<p>It MUST be greater than the value of <code>DEPRECATION_HEIGHT</code> in the last software version that will not contain support for the network upgrade. It SHOULD be chosen to be reached approximately three months after the first software version containing support for the network upgrade is released, for the following reason:</p>
<ul>
<li>As of the time of writing (the 1.0.15 release), the release cycle is six weeks long, and nodes undergo auto-senescence 16 weeks after release. Thus, if version <code>X</code> contains support for a network upgrade, version <code>X-1</code> will be deprecated 10 weeks after the release of version <code>X</code>, which is about 2.3 months. A three-month window provides ample time for users to upgrade their nodes after auto-senescence, and re-integrate into the network prior to activation of the network upgrade.</li>
</ul>
</dd>
</dl>
<p>The relationship between <code>BRANCH_ID</code> and <code>ACTIVATION_HEIGHT</code> is many-to-one: it is possible for many distinct branches to descend from the same parent block (and thus have the same <code>ACTIVATION_HEIGHT</code>), but a specific branch can only have one parent block. Concretely, this means that if the <code>ACTIVATION_HEIGHT</code> of a network upgrade is changed for any reason (e.g. security vulnerabilities or consensus bugs are discovered), the <code>BRANCH_ID</code> MUST also be changed.</p>
<h2 id="activation-mechanism">Activation mechanism</h2>
<p>The Zcash block chain is broken into &quot;epochs&quot; of block height intervals <code>[ACTIVATION_HEIGHT_N, ACTIVATION_HEIGHT_{N+1})</code> (i.e. including <code>ACTIVATION_HEIGHT_N</code> and excluding <code>ACTIVATION_HEIGHT_{N+1}</code>), on which consensus rule sets are defined.</p>
<p>When a consensus rule depends on activation of a particular upgrade, its implementation (and that of any network behavior or surrounding code that depends on it) MUST be gated by a block height check. For example:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb2-1" title="1"><span class="cf">if</span> (CurrentEpoch(chainActive.Height(), Params().GetConsensus()) == Consensus::UPGRADE_OVERWINTER) {</a>
<a class="sourceLine" id="cb2-2" title="2"> <span class="co">// Overwinter-specific logic</span></a>
<a class="sourceLine" id="cb2-3" title="3">} <span class="cf">else</span> {</a>
<a class="sourceLine" id="cb2-4" title="4"> <span class="co">// Non-Overwinter logic</span></a>
<a class="sourceLine" id="cb2-5" title="5">}</a>
<a class="sourceLine" id="cb2-6" title="6"></a>
<a class="sourceLine" id="cb2-7" title="7"><span class="co">// ...</span></a>
<a class="sourceLine" id="cb2-8" title="8"></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="cf">if</span> (NetworkUpgradeActive(pindex-&gt;nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {</a>
<a class="sourceLine" id="cb2-10" title="10"> <span class="co">// Overwinter consensus rules applied to block</span></a>
<a class="sourceLine" id="cb2-11" title="11">} <span class="cf">else</span> {</a>
<a class="sourceLine" id="cb2-12" title="12"> <span class="co">// Pre-Overwinter consensus rules applied to block</span></a>
<a class="sourceLine" id="cb2-13" title="13">}</a></code></pre></div>
<h3 id="block-validation">Block validation</h3>
<p>Incoming blocks known to have a particular height (due to their parent chain being entirely known) MUST be validated under the consensus rules corresponding to the expected branch ID for that height.</p>
<p>Incoming blocks with unknown heights (because at least one block header in their parent chain is unknown) MAY be cached, so that they can be reconsidered in the future after all their parents have been received.</p>
<h3 id="chain-reorganization">Chain reorganization</h3>
<p>It is possible for a reorganization to occur that rolls back from after the activation height, to before that height. This can handled in the same way as any regular chain orphaning or reorganization, as long as the new chain is valid.</p>
<h3 id="post-activation-upgrading">Post-activation upgrading</h3>
<p>If a user does not upgrade their node to a compatible software version before <code>ACTIVATION_HEIGHT</code> is reached, their node will follow any pre-upgrade branch that persists, and may download blocks that are incompatible with the post-upgrade branch. If the user subsequently upgrades their node to a compatible software version, the node will consider these blocks to be invalid, and if there are a significant number of invalid blocks it SHOULD shut down and alert the user of the issue.</p>
<h2 id="memory-pool">Memory pool</h2>
<p>While the current chain tip height is below <code>ACTIVATION_HEIGHT</code>, nodes SHOULD NOT accept transactions that will only be valid on the post-upgrade branch.</p>
<p>When the current chain tip height reaches <code>ACTIVATION_HEIGHT</code>, the node's local transaction memory pool SHOULD be cleared of transactions that will never be valid on the post-upgrade branch.</p>
<h2 id="two-way-replay-protection">Two-way replay protection</h2>
<p>Before the Overwinter network upgrade, two-way replay protection is ensured by enforcing post-upgrade that the most significant bit of the transaction version is set to 1.<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> From the perspective of old nodes, the transactions will have a negative version number, which is invalid under the old consensus rules. Enforcing this rule trivially makes old transactions invalid on the Overwinter branch.</p>
<p>After the Overwinter network upgrade, two-way replay protection is ensured by transaction signatures committing to a specific <code>BRANCH_ID</code>.<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a></p>
<h2 id="wipe-out-protection">Wipe-out protection</h2>
<p>Nodes running upgrade-aware software versions will enforce the upgraded consensus rules from <code>ACTIVATION_HEIGHT</code>. The chain from that height will not reorganize to a pre-upgrade branch if any block in that branch would violate the new consensus rules.</p>
<p>Care must be taken, however, to account for possible edge cases where the old and new consensus rules do not differ. For example, if the non-upgraded chain only contained empty blocks from <code>ACTIVATION_HEIGHT</code>, and the coinbase transactions were valid under both the old and new consensus rules, a wipe-out could occur. The Overwinter network upgrade is not susceptible to this because all previous transaction versions will become invalid, meaning that the coinbase transactions must use the newer transaction version. More generally, this issue could be addressed in a future network upgrade by modifying the block header to include a commitment to the <code>BRANCH_ID</code>.</p>
<h1 id="deployment">Deployment</h1>
<p>This proposal will be deployed with the Overwinter network upgrade.<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a></p>
<h1 id="backward-compatibility">Backward compatibility</h1>
<p>This proposal intentionally creates what is known as a &quot;bilateral consensus rule change&quot;. Use of this mechanism requires that all network participants upgrade their software to a compatible version within the upgrade window. Older software will treat post-upgrade blocks as invalid, and will follow any pre-upgrade branch that persists.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p><a href="https://github.com/zcash/zcash/pull/2898" class="uri">https://github.com/zcash/zcash/pull/2898</a></p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://electriccoin.co/blog/consensual-currency/" class="uri">https://electriccoin.co/blog/consensual-currency/</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p>- <a href="https://electriccoin.co/blog/release-cycle-and-lifetimes/" class="uri">https://electriccoin.co/blog/release-cycle-and-lifetimes/</a> - <a href="https://electriccoin.co/blog/release-cycle-update/" class="uri">https://electriccoin.co/blog/release-cycle-update/</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0202.rst">ZIP 202: Version 3 Transaction Format for Overwinter</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0143.rst">ZIP 143: Transaction Signature Verification for Overwinter</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref6" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,273 +0,0 @@
ZIP: 200
Title: Network Upgrade Mechanism
Owners: Jack Grigg <str4d@electriccoin.co>
Status: Final
Category: Consensus
Created: 2018-01-08
License: MIT
Terminology
===========
The key words \"MUST\", \"SHOULD\", \"SHOULD NOT\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The terms below are to be interpreted as follows:
Block chain
: A sequence of blocks starting at the genesis block, where the header
of each block refers to the previous block in the sequence.
Consensus rule set
: A set of validation rules that determine which block chains are
considered valid.
Consensus rule change
: A change in the consensus rule set of the network, such that nodes
that do not recognize the new rules will follow a different block
chain.
Branch
: A block chain with a common consensus rule set, where the first
block in the chain is either the genesis block, or the child of a
parent block created under an older set of consensus rules (i.e. the
parent block is a member of a different branch). By definition,
every block belongs to at most one branch.
Network upgrade
: An intentional consensus rule change undertaken by the community in
order to improve the network.
Abstract
========
This proposal defines a mechanism for coordinating upgrades of the Zcash
network, in order to remove ambiguity about when network upgrades will
activate, provide defined periods in which users should upgrade their
local software, and minimize the risks to both the upgrading network and
any users opting out of the changes.
Motivation
==========
Zcash is a *consensual currency*: nobody is ever going to force someone
to use a specific software implementation or a specific branch of
Zcash.[^2] As such, different sub-communities will always have the
freedom to choose different variants or branches which offer different
design trade-offs.
The current Zcash software includes an *auto-senescence* feature,
causing nodes running a particular version to automatically shut down
approximately 16 weeks after that version was released (specifically, at
the block height `DEPRECATION_HEIGHT` defined in the source code for
that version). This was implemented for several reasons:[^3]
- It gives the same systemic advantage of removing old software as
auto-upgrade behavior.
- It requires users to individually choose one of the following
options:
- Upgrade to a more recent software release from the main network.
- Upgrade to an alternative release.
- Modify their node in order to keep running the older software.
Developers can rely on this cadence for coordinating network upgrades.
Once the last pre-upgrade software version has been deprecated, they can
reasonably assume that all node operators on the network either support
the upgraded rules, or have explicitly chosen not to follow them.
However, this behaviour is not sufficient for performing network
upgrades. A globally-understood on-chain activation mechanism is
necessary so that nodes can unambiguously know at what point the changes
from an upgrade come into effect (and can enforce consensus rule
changes, for example).
Specification
=============
The following constants are defined for every network upgrade:
BRANCH\_ID
: A globally-unique non-zero 32-bit identifier.
Implementations MAY use a value of zero in branch ID fields to
indicate the absence of any upgrade (i.e. that the Sprout consensus
rules apply).
ACTIVATION\_HEIGHT
: The non-zero block height at which the network upgrade rules will
come into effect, and be enforced as part of the block chain
consensus.
For removal of ambiguity, the block at height
`ACTIVATION_HEIGHT - 1` is subject to the pre-upgrade consensus
rules, and would be the last common block in the event of a
persistent pre-upgrade branch.
It MUST be greater than the value of `DEPRECATION_HEIGHT` in the
last software version that will not contain support for the network
upgrade. It SHOULD be chosen to be reached approximately three
months after the first software version containing support for the
network upgrade is released, for the following reason:
- As of the time of writing (the 1.0.15 release), the release
cycle is six weeks long, and nodes undergo auto-senescence 16
weeks after release. Thus, if version `X` contains support for a
network upgrade, version `X-1` will be deprecated 10 weeks after
the release of version `X`, which is about 2.3 months. A
three-month window provides ample time for users to upgrade
their nodes after auto-senescence, and re-integrate into the
network prior to activation of the network upgrade.
The relationship between `BRANCH_ID` and `ACTIVATION_HEIGHT` is
many-to-one: it is possible for many distinct branches to descend from
the same parent block (and thus have the same `ACTIVATION_HEIGHT`), but
a specific branch can only have one parent block. Concretely, this means
that if the `ACTIVATION_HEIGHT` of a network upgrade is changed for any
reason (e.g. security vulnerabilities or consensus bugs are discovered),
the `BRANCH_ID` MUST also be changed.
Activation mechanism
--------------------
The Zcash block chain is broken into \"epochs\" of block height
intervals `[ACTIVATION_HEIGHT_N, ACTIVATION_HEIGHT_{N+1})` (i.e.
including `ACTIVATION_HEIGHT_N` and excluding
`ACTIVATION_HEIGHT_{N+1}`), on which consensus rule sets are defined.
When a consensus rule depends on activation of a particular upgrade, its
implementation (and that of any network behavior or surrounding code
that depends on it) MUST be gated by a block height check. For example:
``` {.sourceCode .cpp}
if (CurrentEpoch(chainActive.Height(), Params().GetConsensus()) == Consensus::UPGRADE_OVERWINTER) {
// Overwinter-specific logic
} else {
// Non-Overwinter logic
}
// ...
if (NetworkUpgradeActive(pindex->nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
// Overwinter consensus rules applied to block
} else {
// Pre-Overwinter consensus rules applied to block
}
```
### Block validation
Incoming blocks known to have a particular height (due to their parent
chain being entirely known) MUST be validated under the consensus rules
corresponding to the expected branch ID for that height.
Incoming blocks with unknown heights (because at least one block header
in their parent chain is unknown) MAY be cached, so that they can be
reconsidered in the future after all their parents have been received.
### Chain reorganization
It is possible for a reorganization to occur that rolls back from after
the activation height, to before that height. This can handled in the
same way as any regular chain orphaning or reorganization, as long as
the new chain is valid.
### Post-activation upgrading
If a user does not upgrade their node to a compatible software version
before `ACTIVATION_HEIGHT` is reached, their node will follow any
pre-upgrade branch that persists, and may download blocks that are
incompatible with the post-upgrade branch. If the user subsequently
upgrades their node to a compatible software version, the node will
consider these blocks to be invalid, and if there are a significant
number of invalid blocks it SHOULD shut down and alert the user of the
issue.
Memory pool
-----------
While the current chain tip height is below `ACTIVATION_HEIGHT`, nodes
SHOULD NOT accept transactions that will only be valid on the
post-upgrade branch.
When the current chain tip height reaches `ACTIVATION_HEIGHT`, the
node\'s local transaction memory pool SHOULD be cleared of transactions
that will never be valid on the post-upgrade branch.
Two-way replay protection
-------------------------
Before the Overwinter network upgrade, two-way replay protection is
ensured by enforcing post-upgrade that the most significant bit of the
transaction version is set to 1.[^4] From the perspective of old nodes,
the transactions will have a negative version number, which is invalid
under the old consensus rules. Enforcing this rule trivially makes old
transactions invalid on the Overwinter branch.
After the Overwinter network upgrade, two-way replay protection is
ensured by transaction signatures committing to a specific
`BRANCH_ID`.[^5]
Wipe-out protection
-------------------
Nodes running upgrade-aware software versions will enforce the upgraded
consensus rules from `ACTIVATION_HEIGHT`. The chain from that height
will not reorganize to a pre-upgrade branch if any block in that branch
would violate the new consensus rules.
Care must be taken, however, to account for possible edge cases where
the old and new consensus rules do not differ. For example, if the
non-upgraded chain only contained empty blocks from `ACTIVATION_HEIGHT`,
and the coinbase transactions were valid under both the old and new
consensus rules, a wipe-out could occur. The Overwinter network upgrade
is not susceptible to this because all previous transaction versions
will become invalid, meaning that the coinbase transactions must use the
newer transaction version. More generally, this issue could be addressed
in a future network upgrade by modifying the block header to include a
commitment to the `BRANCH_ID`.
Deployment
==========
This proposal will be deployed with the Overwinter network upgrade.[^6]
Backward compatibility
======================
This proposal intentionally creates what is known as a \"bilateral
consensus rule change\". Use of this mechanism requires that all network
participants upgrade their software to a compatible version within the
upgrade window. Older software will treat post-upgrade blocks as
invalid, and will follow any pre-upgrade branch that persists.
Reference Implementation
========================
<https://github.com/zcash/zcash/pull/2898>
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: <https://electriccoin.co/blog/consensual-currency/>
[^3]: \- <https://electriccoin.co/blog/release-cycle-and-lifetimes/> -
<https://electriccoin.co/blog/release-cycle-update/>
[^4]: [ZIP 202: Version 3 Transaction Format for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0202.rst)
[^5]: [ZIP 143: Transaction Signature Verification for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0143.rst)
[^6]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)

206
zip-0201.html Normal file
View File

@ -0,0 +1,206 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0201</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 201
Title: Network Peer Management for Overwinter
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Original-Authors: Simon Liu &lt;simon@bitcartel.com&gt;
Status: Final
Category: Network
Created: 2018-01-15
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms &quot;branch&quot; and &quot;network upgrade&quot; in this document are to be interpreted as described in ZIP 200.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>Overwinter</dt>
<dd><p>Code-name for the first Zcash network upgrade, also known as Network Upgrade Zero.</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines an upgrade to the network handshake and peer management required for network upgrades following the Network Upgrade Activation Mechanism<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</p>
<p>Related to:</p>
<ul>
<li>Transaction Signature Verification for Overwinter<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>.</li>
<li>Version 3 Transaction Format for Overwinter<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</li>
<li>Transaction Expiry<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a>.</li>
</ul>
<h1 id="motivation">Motivation</h1>
<p>With scheduled network upgrades, at the activation height, nodes on each branch should disconnect from nodes on other branches and only accept new incoming connections from nodes on the same branch.</p>
<h1 id="specification">Specification</h1>
<p>When a new inbound connection is received or an outbound connection created, a CNode object is instantiated with the version field set to INIT_PROTO_VERSION which has a value of 209. This value is not transmitted across the network, but for legacy reasons and technical debt beyond the scope of this ZIP, this value will not be changed.</p>
<p>Once the two nodes have connected and started the handshake to negotiate the protocol version, the version field of CNode will be updated. The handshake<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a> involves &quot;version&quot; and &quot;verack&quot; messages being exchanged.:</p>
<pre><code>L -&gt; R: Send version message with the local peer&#39;s version
R -&gt; L: Send version message back
R -&gt; L: Send verack message
R: Sets version to the minimum of the 2 versions
L -&gt; R: Send verack message after receiving version message from R
L: Sets version to the minimum of the 2 versions</code></pre>
<p>To send a version message, the node will invoke <code>PushVersion()</code>:</p>
<pre><code>void CNode::PushVersion() {
...
PushMessage(&quot;version&quot;, PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, ...);
...
}</code></pre>
<p>where <code>PROTOCOL_VERSION</code> is the highest protocol version supported by the node.</p>
<h2 id="rejecting-pre-overwinter-connections">Rejecting Pre-Overwinter Connections</h2>
<p>Currently, nodes will reject connections from peers with an advertised protocol version lower than the other node's minimum supported protocol version.</p>
<p>This value is defined as:</p>
<pre><code>//! disconnect from peers older than this proto version
static const int MIN_PEER_PROTO_VERSION = 170002;</code></pre>
<p>With rejection implemented as:</p>
<pre><code>if (pfrom-&gt;nVersion &lt; MIN_PEER_PROTO_VERSION)
{
// disconnect from old peers running protocol version we don&#39;t support.</code></pre>
<p>Activation of Overwinter will take place first on testnet, and if successful, followed by mainnet.</p>
<p>To prepare for testnet activation, Overwinter nodes will contain the following constants:</p>
<pre><code>static const int PROTOCOL_VERSION = 170003;
static const int MIN_PEER_PROTO_VERSION = 170002;</code></pre>
<p>Nodes running protocol version 170003 have a testnet activation height set, but do not have a mainnet activation height set.</p>
<p>On testnet, a pre-Overwinter node is defined to be a node for which the highest supported protocol version is &lt;= 170002.</p>
<p>These constants allow pre-Overwinter nodes that support protocol version 170002, and Overwinter nodes (which support both protocol versions 170002 and 170003 before Overwinter activation) to remain connected until the activation.</p>
<p>To prepare for mainnet activation, Overwinter nodes will contain the following constants:</p>
<pre><code>static const int PROTOCOL_VERSION = 170005;
static const int MIN_PEER_PROTO_VERSION = 170002;</code></pre>
<p>On mainnet, a pre-Overwinter node is defined to be a node for which the highest supported protocol version is &lt;= 170004. (Nodes running protocol version 170003 or 170004 do not have a mainnet activation height set. The intermediate protocol version 170004 is used to indicate support for the <code>NODE_BLOOM</code> service bit defined in<a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a>.)</p>
<p>These constants allow pre-Overwinter nodes that support protocol versions 170002 to 170004 inclusive, and Overwinter nodes (which support protocol versions 170002 to 170005 inclusive before Overwinter activation) to remain connected until the activation.</p>
<p>As these constants cannot be changed at run-time, once Overwinter activates on testnet or mainnet, Overwinter nodes should take steps to:</p>
<ul>
<li>reject new connections from pre-Overwinter nodes;</li>
<li>disconnect any existing connections to pre-Overwinter nodes.</li>
</ul>
<h2 id="network-coalescence">Network Coalescence</h2>
<p>Prior to the activation of Overwinter, nodes running a pre-Overwinter protocol version (e.g. 170002) and the Overwinter protocol version (170003 for testnet; 170005 for mainnet) remain connected with the same consensus rules, but it is desirable for nodes supporting Overwinter to connect preferentially to other nodes supporting Overwinter.</p>
<p>This is intended to help the network partition smoothly, since nodes should already be connected to (a majority of) peers running the same protocol version. Otherwise an Overwinter node may find their connections to Sprout nodes dropped suddenly at the activation height, potentially leaving them isolated and susceptible to eclipse attacks.<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a></p>
<p>To assist network coalescence before the activation height, we update the eviction process to place a higher priority on evicting Sprout nodes.</p>
<p>Currently, an eviction process takes place when new inbound connections arrive, but the node has already connected to the maximum number of inbound peers:</p>
<pre><code>if (nInbound &gt;= nMaxInbound)
{
if (!AttemptToEvictConnection(whitelisted)) {
// No connection to evict, disconnect the new connection
LogPrint(&quot;net&quot;, &quot;failed to find an eviction candidate - connection dropped (full)\n&quot;);
CloseSocket(hSocket);
return;
}
}</code></pre>
<p>We update this process by adding behaviour so that the set of eviction candidates will prefer pre-Overwinter nodes, when the chain tip is in a period N blocks before the activation block height, where N is defined as:</p>
<pre><code>/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;</code></pre>
<p>The eviction candidates can be modified as so:</p>
<pre><code>static bool AttemptToEvictConnection(bool fPreferNewConnection) {
...
// Protect connections with certain characteristics
...
// Check version of eviction candidates...
// If we are connected to any pre-Overwinter nodes, keep them in the eviction set and remove any Overwinter nodes
// If we are only connected to Overwinter nodes, continue with existing behaviour.
if (nActivationHeight &gt; 0 &amp;&amp;
height &lt; nActivationHeight &amp;&amp;
height &gt;= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD)
{
// Find any nodes which don&#39;t support Overwinter protocol version
BOOST_FOREACH(const CNodeRef &amp;node, vEvictionCandidates) {
if (node-&gt;nVersion &lt; params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion) {
vTmpEvictionCandidates.push_back(node);
}
}
// Prioritize these nodes by replacing eviction set with them
if (vTmpEvictionCandidates.size() &gt; 0) {
vEvictionCandidates = vTmpEvictionCandidates;
}
}</code></pre>
<p>The existing method of disconnecting a candidate remains:</p>
<blockquote>
<p>vEvictionCandidates[0]-&gt;fDisconnect = true;</p>
</blockquote>
<p>The existing eviction process will classify and divide eviction candidates into buckets called netgroups. If a netgroup only has one peer, it will not be evicted. This means at least one pre-Overwinter node will remain connected upto the activation block height, barring any network issues or a high ban score.</p>
<h2 id="disconnecting-existing-connections">Disconnecting Existing Connections</h2>
<p>At the activation block height, an Overwinter node may still remain connected to pre-Overwinter nodes. Currently, when connecting, a node can only perform the networking handshake once, where it sends the version message before any other messages are processed. To disconnect existing pre-Overwinter connections, <code>ProcessMessage</code> is modified so that once Overwinter activates, if necessary, the protocol version of an existing peer is validated when inbound messages arrive.</p>
<p>Example code:</p>
<pre><code>bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream&amp; vRecv, int64_t nTimeReceived)
...
else if (pfrom-&gt;nVersion == 0)
{
// Must have a version message before anything else
Misbehaving(pfrom-&gt;GetId(), 1);
return false;
}
else if (strCommand == &quot;verack&quot;)
{
...
}
// Disconnect existing peer connection when:
// 1. The version message has been received
// 2. Overwinter is active
// 3. Peer version is pre-Overwinter
else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER)
&amp;&amp; (pfrom-&gt;nVersion &lt; chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion))
{
LogPrintf(&quot;peer=%d using obsolete version %i; disconnecting\n&quot;, pfrom-&gt;id, pfrom-&gt;nVersion);
pfrom-&gt;PushMessage(&quot;reject&quot;, strCommand, REJECT_OBSOLETE,
strprintf(&quot;Version must be %d or greater&quot;,
chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
pfrom-&gt;fDisconnect = true;
return false;
}</code></pre>
<h1 id="deployment-of-overwinter">Deployment of Overwinter</h1>
<p>The Overwinter network upgrade defines the following network upgrade constants<a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a>:</p>
<dl>
<dt>BRANCH_ID</dt>
<dd><p><code>0x5ba81b19</code></p>
</dd>
<dt>ACTIVATION_HEIGHT</dt>
<dd><p>Testnet: 207500</p>
<p>Mainnet: 347500</p>
</dd>
</dl>
<p>The following ZIPs are deployed by Overwinter:</p>
<ul>
<li>ZIP 200<a href="#fn11" class="footnote-ref" id="fnref11"><sup>11</sup></a></li>
<li>ZIP 201 (this ZIP)</li>
<li>ZIP 202<a href="#fn12" class="footnote-ref" id="fnref12"><sup>12</sup></a></li>
<li>ZIP 203<a href="#fn13" class="footnote-ref" id="fnref13"><sup>13</sup></a></li>
<li>ZIP 143<a href="#fn14" class="footnote-ref" id="fnref14"><sup>14</sup></a></li>
</ul>
<h1 id="backward-compatibility">Backward compatibility</h1>
<p>Prior to the network upgrade activating, Overwinter and pre-Overwinter nodes are compatible and can connect to each other. However, Overwinter nodes will have a preference for connecting to other Overwinter nodes, so pre-Overwinter nodes will gradually be disconnected in the run up to activation.</p>
<p>Once the network upgrades, even though pre-Overwinter nodes can still accept the numerically larger protocol version used by Overwinter as being valid, Overwinter nodes will always disconnect peers using lower protocol versions.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p><a href="https://github.com/zcash/zcash/pull/2919" class="uri">https://github.com/zcash/zcash/pull/2919</a></p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0143.rst">ZIP 143: Transaction Signature Verification for Overwinter</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0202.rst">ZIP 202: Version 3 Transaction Format for Overwinter</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0203.rst">ZIP 203: Transaction Expiry</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://en.bitcoin.it/wiki/Version_Handshake" class="uri">https://en.bitcoin.it/wiki/Version_Handshake</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki">BIP 111: NODE_BLOOM service bit</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://eprint.iacr.org/2015/263">Eclipse Attacks on Bitcoins Peer-to-Peer Network</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref10" class="footnote-back"></a></p></li>
<li id="fn11"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref11" class="footnote-back"></a></p></li>
<li id="fn12"><p><a href="https://github.com/zcash/zips/blob/master/zip-0202.rst">ZIP 202: Version 3 Transaction Format for Overwinter</a><a href="#fnref12" class="footnote-back"></a></p></li>
<li id="fn13"><p><a href="https://github.com/zcash/zips/blob/master/zip-0203.rst">ZIP 203: Transaction Expiry</a><a href="#fnref13" class="footnote-back"></a></p></li>
<li id="fn14"><p><a href="https://github.com/zcash/zips/blob/master/zip-0143.rst">ZIP 143: Transaction Signature Verification for Overwinter</a><a href="#fnref14" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,343 +0,0 @@
ZIP: 201
Title: Network Peer Management for Overwinter
Owners: Daira Hopwood <daira@electriccoin.co>
Original-Authors: Simon Liu <simon@bitcartel.com>
Status: Final
Category: Network
Created: 2018-01-15
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", \"SHOULD\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The terms \"branch\" and \"network upgrade\" in this document are to be
interpreted as described in ZIP 200.[^2]
The terms below are to be interpreted as follows:
Overwinter
: Code-name for the first Zcash network upgrade, also known as Network
Upgrade Zero.
Abstract
========
This proposal defines an upgrade to the network handshake and peer
management required for network upgrades following the Network Upgrade
Activation Mechanism[^3].
Related to:
- Transaction Signature Verification for Overwinter[^4].
- Version 3 Transaction Format for Overwinter[^5].
- Transaction Expiry[^6].
Motivation
==========
With scheduled network upgrades, at the activation height, nodes on each
branch should disconnect from nodes on other branches and only accept
new incoming connections from nodes on the same branch.
Specification
=============
When a new inbound connection is received or an outbound connection
created, a CNode object is instantiated with the version field set to
INIT\_PROTO\_VERSION which has a value of 209. This value is not
transmitted across the network, but for legacy reasons and technical
debt beyond the scope of this ZIP, this value will not be changed.
Once the two nodes have connected and started the handshake to negotiate
the protocol version, the version field of CNode will be updated. The
handshake[^7] involves \"version\" and \"verack\" messages being
exchanged.:
L -> R: Send version message with the local peer's version
R -> L: Send version message back
R -> L: Send verack message
R: Sets version to the minimum of the 2 versions
L -> R: Send verack message after receiving version message from R
L: Sets version to the minimum of the 2 versions
To send a version message, the node will invoke `PushVersion()`:
void CNode::PushVersion() {
...
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, ...);
...
}
where `PROTOCOL_VERSION` is the highest protocol version supported by
the node.
Rejecting Pre-Overwinter Connections
------------------------------------
Currently, nodes will reject connections from peers with an advertised
protocol version lower than the other node\'s minimum supported protocol
version.
This value is defined as:
//! disconnect from peers older than this proto version
static const int MIN_PEER_PROTO_VERSION = 170002;
With rejection implemented as:
if (pfrom->nVersion < MIN_PEER_PROTO_VERSION)
{
// disconnect from old peers running protocol version we don't support.
Activation of Overwinter will take place first on testnet, and if
successful, followed by mainnet.
To prepare for testnet activation, Overwinter nodes will contain the
following constants:
static const int PROTOCOL_VERSION = 170003;
static const int MIN_PEER_PROTO_VERSION = 170002;
Nodes running protocol version 170003 have a testnet activation height
set, but do not have a mainnet activation height set.
On testnet, a pre-Overwinter node is defined to be a node for which the
highest supported protocol version is \<= 170002.
These constants allow pre-Overwinter nodes that support protocol version
170002, and Overwinter nodes (which support both protocol versions
170002 and 170003 before Overwinter activation) to remain connected
until the activation.
To prepare for mainnet activation, Overwinter nodes will contain the
following constants:
static const int PROTOCOL_VERSION = 170005;
static const int MIN_PEER_PROTO_VERSION = 170002;
On mainnet, a pre-Overwinter node is defined to be a node for which the
highest supported protocol version is \<= 170004. (Nodes running
protocol version 170003 or 170004 do not have a mainnet activation
height set. The intermediate protocol version 170004 is used to indicate
support for the `NODE_BLOOM` service bit defined in[^8].)
These constants allow pre-Overwinter nodes that support protocol
versions 170002 to 170004 inclusive, and Overwinter nodes (which support
protocol versions 170002 to 170005 inclusive before Overwinter
activation) to remain connected until the activation.
As these constants cannot be changed at run-time, once Overwinter
activates on testnet or mainnet, Overwinter nodes should take steps to:
- reject new connections from pre-Overwinter nodes;
- disconnect any existing connections to pre-Overwinter nodes.
Network Coalescence
-------------------
Prior to the activation of Overwinter, nodes running a pre-Overwinter
protocol version (e.g. 170002) and the Overwinter protocol version
(170003 for testnet; 170005 for mainnet) remain connected with the same
consensus rules, but it is desirable for nodes supporting Overwinter to
connect preferentially to other nodes supporting Overwinter.
This is intended to help the network partition smoothly, since nodes
should already be connected to (a majority of) peers running the same
protocol version. Otherwise an Overwinter node may find their
connections to Sprout nodes dropped suddenly at the activation height,
potentially leaving them isolated and susceptible to eclipse
attacks.[^9]
To assist network coalescence before the activation height, we update
the eviction process to place a higher priority on evicting Sprout
nodes.
Currently, an eviction process takes place when new inbound connections
arrive, but the node has already connected to the maximum number of
inbound peers:
if (nInbound >= nMaxInbound)
{
if (!AttemptToEvictConnection(whitelisted)) {
// No connection to evict, disconnect the new connection
LogPrint("net", "failed to find an eviction candidate - connection dropped (full)\n");
CloseSocket(hSocket);
return;
}
}
We update this process by adding behaviour so that the set of eviction
candidates will prefer pre-Overwinter nodes, when the chain tip is in a
period N blocks before the activation block height, where N is defined
as:
/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
The eviction candidates can be modified as so:
static bool AttemptToEvictConnection(bool fPreferNewConnection) {
...
// Protect connections with certain characteristics
...
// Check version of eviction candidates...
// If we are connected to any pre-Overwinter nodes, keep them in the eviction set and remove any Overwinter nodes
// If we are only connected to Overwinter nodes, continue with existing behaviour.
if (nActivationHeight > 0 &&
height < nActivationHeight &&
height >= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD)
{
// Find any nodes which don't support Overwinter protocol version
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
if (node->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion) {
vTmpEvictionCandidates.push_back(node);
}
}
// Prioritize these nodes by replacing eviction set with them
if (vTmpEvictionCandidates.size() > 0) {
vEvictionCandidates = vTmpEvictionCandidates;
}
}
The existing method of disconnecting a candidate remains:
> vEvictionCandidates\[0\]-\>fDisconnect = true;
The existing eviction process will classify and divide eviction
candidates into buckets called netgroups. If a netgroup only has one
peer, it will not be evicted. This means at least one pre-Overwinter
node will remain connected upto the activation block height, barring any
network issues or a high ban score.
Disconnecting Existing Connections
----------------------------------
At the activation block height, an Overwinter node may still remain
connected to pre-Overwinter nodes. Currently, when connecting, a node
can only perform the networking handshake once, where it sends the
version message before any other messages are processed. To disconnect
existing pre-Overwinter connections, `ProcessMessage` is modified so
that once Overwinter activates, if necessary, the protocol version of an
existing peer is validated when inbound messages arrive.
Example code:
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
...
else if (pfrom->nVersion == 0)
{
// Must have a version message before anything else
Misbehaving(pfrom->GetId(), 1);
return false;
}
else if (strCommand == "verack")
{
...
}
// Disconnect existing peer connection when:
// 1. The version message has been received
// 2. Overwinter is active
// 3. Peer version is pre-Overwinter
else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER)
&& (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion))
{
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater",
chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
pfrom->fDisconnect = true;
return false;
}
Deployment of Overwinter
========================
The Overwinter network upgrade defines the following network upgrade
constants[^10]:
BRANCH\_ID
: `0x5ba81b19`
ACTIVATION\_HEIGHT
: Testnet: 207500
Mainnet: 347500
The following ZIPs are deployed by Overwinter:
- ZIP 200[^11]
- ZIP 201 (this ZIP)
- ZIP 202[^12]
- ZIP 203[^13]
- ZIP 143[^14]
Backward compatibility
======================
Prior to the network upgrade activating, Overwinter and pre-Overwinter
nodes are compatible and can connect to each other. However, Overwinter
nodes will have a preference for connecting to other Overwinter nodes,
so pre-Overwinter nodes will gradually be disconnected in the run up to
activation.
Once the network upgrades, even though pre-Overwinter nodes can still
accept the numerically larger protocol version used by Overwinter as
being valid, Overwinter nodes will always disconnect peers using lower
protocol versions.
Reference Implementation
========================
<https://github.com/zcash/zcash/pull/2919>
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^4]: [ZIP 143: Transaction Signature Verification for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0143.rst)
[^5]: [ZIP 202: Version 3 Transaction Format for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0202.rst)
[^6]: [ZIP 203: Transaction
Expiry](https://github.com/zcash/zips/blob/master/zip-0203.rst)
[^7]: <https://en.bitcoin.it/wiki/Version_Handshake>
[^8]: [BIP 111: NODE\_BLOOM service
bit](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki)
[^9]: [Eclipse Attacks on Bitcoin's Peer-to-Peer
Network](https://eprint.iacr.org/2015/263)
[^10]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^11]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^12]: [ZIP 202: Version 3 Transaction Format for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0202.rst)
[^13]: [ZIP 203: Transaction
Expiry](https://github.com/zcash/zips/blob/master/zip-0203.rst)
[^14]: [ZIP 143: Transaction Signature Verification for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0143.rst)

339
zip-0202.html Normal file
View File

@ -0,0 +1,339 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0202</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 202
Title: Version 3 Transaction Format for Overwinter
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Original-Authors: Simon Liu &lt;simon@bitcartel.com&gt;
Status: Final
Category: Consensus
Created: 2018-01-10
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms &quot;branch&quot;, &quot;network upgrade&quot;, and &quot;consensus rule change&quot; in this document are to be interpreted as described in ZIP 200.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<p>The term &quot;Overwinter&quot; in this document is to be interpreted as described in ZIP 201.<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a></p>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines a new transaction format required for Network Upgrade Activation Mechanism<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> and Transaction Expiry<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</p>
<h1 id="motivation">Motivation</h1>
<p>Zcash launched with support for upstream Bitcoin version 1 transactions and defined a new version 2 transaction format which added fields required for shielded transactions.</p>
<table>
<thead>
<tr class="header">
<th>Version</th>
<th>Field</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>version</code></td>
<td>positive value</td>
<td><code>int32</code></td>
</tr>
<tr class="even">
<td>&gt;= 1</td>
<td><code>tx_in_count</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>tx_in</code></td>
<td>list of inputs</td>
<td><code>vector</code></td>
</tr>
<tr class="even">
<td>&gt;= 1</td>
<td><code>tx_out_count</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>tx_out</code></td>
<td>list of outputs</td>
<td><code>vector</code></td>
</tr>
<tr class="even">
<td>&gt;= 1</td>
<td><code>lock_time</code></td>
<td>block height or timestamp</td>
<td><code>uint32</code></td>
</tr>
<tr class="odd">
<td>&gt;= 2</td>
<td><code>nJoinSplit</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="even">
<td>&gt;= 2</td>
<td><code>vJoinSplit</code></td>
<td>list of joinsplits</td>
<td><code>vector</code></td>
</tr>
<tr class="odd">
<td>&gt;= 2</td>
<td><code>joinSplitPubKey</code></td>
<td>joinsplit_sig public key</td>
<td>32 bytes</td>
</tr>
<tr class="even">
<td>&gt;= 2</td>
<td><code>joinSplitSig</code></td>
<td>signature</td>
<td>64 bytes</td>
</tr>
</tbody>
</table>
<p>A new transaction format is required to:</p>
<ul>
<li>support safe network upgrades as specified in Network Upgrade Activation Mechanism<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a>;</li>
<li>provide replay protection between pre-Overwinter and Overwinter branches during upgrades;</li>
<li>provide replay protection between different branches post-Overwinter;</li>
<li>enable a branch to support multiple transaction version formats;</li>
<li>ensure transaction formats are parsed uniquely across parallel branches;</li>
<li>support transaction expiry<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a>.</li>
</ul>
<h1 id="specification">Specification</h1>
<h2 id="transaction-format-version-3">Transaction format version 3</h2>
<p>A new version 3 transaction format will be introduced for Overwinter.</p>
<p>The version 3 format differs from the version 2 format in the following ways:</p>
<ul>
<li>header (first four bytes, little-endian encoded)
<ul>
<li><code>fOverwintered</code> flag : bit 31, must be set</li>
<li><code>nVersion</code> : bits 30-0, positive integer</li>
</ul></li>
<li><code>nVersionGroupId</code></li>
<li><code>nExpiryHeight</code></li>
</ul>
<table>
<thead>
<tr class="header">
<th>Version</th>
<th>Field</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>&gt;= 3</p></td>
<td><p>header</p></td>
<td><p>contains:</p>
<ul>
<li><code>fOverwintered</code> flag (bit 31, always set)</li>
<li><code>nVersion</code> (bits 30-0)</li>
</ul></td>
<td><p><code>uint32</code></p></td>
</tr>
<tr class="even">
<td>&gt;= 3</td>
<td><code>nVersionGroupId</code></td>
<td>version group id (not zero)</td>
<td><code>uint32</code></td>
</tr>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>tx_in_count</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="even">
<td>&gt;= 1</td>
<td><code>tx_in</code></td>
<td>list of inputs</td>
<td><code>vector</code></td>
</tr>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>tx_out_count</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="even">
<td>&gt;= 1</td>
<td><code>tx_out</code></td>
<td>list of outputs</td>
<td><code>vector</code></td>
</tr>
<tr class="odd">
<td>&gt;= 1</td>
<td><code>lock_time</code></td>
<td>block height or timestamp</td>
<td><code>uint32</code></td>
</tr>
<tr class="even">
<td>&gt;= 3</td>
<td><code>expiryHeight</code></td>
<td>block height</td>
<td><code>uint32</code></td>
</tr>
<tr class="odd">
<td>&gt;= 2</td>
<td><code>nJoinSplit</code></td>
<td>variable-length integer</td>
<td><code>compactSize</code></td>
</tr>
<tr class="even">
<td>&gt;= 2</td>
<td><code>vJoinSplit</code></td>
<td>list of joinsplits</td>
<td><code>vector</code></td>
</tr>
<tr class="odd">
<td>&gt;= 2</td>
<td><code>joinSplitPubKey</code></td>
<td>joinsplit_sig public key</td>
<td>32 bytes</td>
</tr>
<tr class="even">
<td>&gt;= 2</td>
<td><code>joinSplitSig</code></td>
<td>signature</td>
<td>64 bytes</td>
</tr>
</tbody>
</table>
<h2 id="header-field">Header Field</h2>
<p>The first four bytes of pre-Overwinter and Overwinter transactions are little-endian encoded.</p>
<p>Version 1 transaction (txid 5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061 <a href="https://zcash.blockexplorer.com/tx/5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061" class="uri">https://zcash.blockexplorer.com/tx/5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061</a>)</p>
<ul>
<li>begins with little-endian byte sequence [0x01, 0x00, 0x00, 0x00];</li>
<li>deserialized as 32-bit signed integer with decimal value of 1.</li>
</ul>
<p>Version 2 transaction (txid 4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b <a href="https://zcash.blockexplorer.com/tx/4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b" class="uri">https://zcash.blockexplorer.com/tx/4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b</a>)</p>
<ul>
<li>begins with little-endian byte sequence [0x02, 0x00, 0x00, 0x00];</li>
<li>deserialized as 32-bit signed integer with decimal value of 2.</li>
</ul>
<p>Transaction parsers for versions of Zcash prior to Overwinter, and for most other Bitcoin forks, require the transaction version number to be positive.</p>
<p>With the version 3 transaction format, the first four bytes of a serialized transaction, the 32-bit header, are made up of two fields as shown in the table above:</p>
<ul>
<li>1-bit <code>fOverwintered</code> flag, must be set;</li>
<li>31-bit unsigned int for the version.</li>
</ul>
<p>Pre-Overwinter parsers will deserialize these four bytes as a 32-bit signed integer. With two's complement integers, the most significant bit indicates whether an integer is positive or negative. With the Overwinter flag set, the transaction version will be negative, resulting in pre-Overwinter parsers rejecting the transaction as invalid. This provides transaction replay protection between pre-Overwinter and Overwinter software.</p>
<p>Consider the following example of a serialized version 3 transaction.</p>
<p>Pre-Overwinter parser:</p>
<ul>
<li>data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80];</li>
<li>deserialized as 32-bit signed integer.
<ul>
<li>with hexadecimal value of 0x80000003 (most significant bit is set);</li>
<li>decimal value of -2147483645.</li>
</ul></li>
</ul>
<p>Legacy parsers will expect the version to be a positive value, such as 1 or 2, and will thus reject the Overwinter transaction as invalid.</p>
<p>Overwinter parser:</p>
<ul>
<li>data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80];</li>
<li>deserialized as 32-bit unsigned integer
<ul>
<li>with binary value of 0b10000000000000000000000000000011;</li>
</ul></li>
<li>the 32-bits are decomposed into two fields:
<ul>
<li><code>fOverwintered</code> flag (bit 31) as a boolean, expected to be set;</li>
<li>version (bits 30 - bit 0) as an unsigned integer, expected to have a decimal value of 3.</li>
</ul></li>
</ul>
<p>Overwinter parsers will accept the transaction as valid as the most significant bit of the header has been set. By masking off (unsetting) the most significant bit, the parser can retrieve the transaction version number:</p>
<pre><code>0x80000003 &amp; 0x7FFFFFFF = 0x00000003 = 3</code></pre>
<h2 id="version-group-id">Version Group Id</h2>
<p>The version group id is a non-zero, random and unique identifier, of type <code>uint32</code>, assigned to a transaction format version, or a group of soft-forking transaction format versions. The version group id helps nodes disambiguate between branches using the same version number.</p>
<p>That is, it prevents a client on one branch of the network from attempting to parse transactions intended for another branch, in the situation where the transactions share the same format version number but are actually specified differently. For example, Zcash and a clone of Zcash might both define their own custom v3 transaction formats, but each will have its own unique version group id, so that they can reject v3 transactions with unknown version group ids.</p>
<p>The combination of transaction version and version group id, <code>nVersion || nVersionGroupId</code>, uniquely defines the transaction format, thus enabling parsers to reject transactions from outside the client's chain which cannot be parsed.</p>
<p>By convention, it is expected that when introducing a new transaction version requiring a network upgrade, a new unique version group id will be assigned to that transaction version.</p>
<p>However, if a new transaction version can be correctly parsed according to the format of a preceding version (that is, it only restricts the format, or defines fields that were previously reserved and which old parsers can safely ignore), then the same version group id MAY be re-used.</p>
<h2 id="expiry-height">Expiry Height</h2>
<p>The expiry height field, as defined in the Transaction Expiry ZIP<a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a>, stores the block height after which a transaction can no longer be mined.</p>
<h1 id="transaction-validation">Transaction Validation</h1>
<p>A valid Overwinter transaction intended for Zcash MUST have:</p>
<ul>
<li>version number 3; and</li>
<li>version group id 0x03C48270<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a>; and</li>
<li><code>fOverwintered</code> flag set.</li>
</ul>
<p>Overwinter validators MUST reject transactions for violating consensus rules if:</p>
<ul>
<li>the <code>fOverwintered</code> flag is not set; or</li>
<li>the version group id is unknown; or</li>
<li>the version number is unknown.</li>
</ul>
<p>Validation of version 3 transactions MUST use the signature verification process detailed in the Transaction Signature Verification for Overwinter ZIP<a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a>.</p>
<h1 id="implementation">Implementation</h1>
<p>The comments and code samples in this section apply to the reference C++ implementation of Zcash. Other implementations may vary.</p>
<h2 id="transaction-version">Transaction Version</h2>
<p>Transaction version remains a positive value. The main Zcash chain will follow convention and continue to order transaction versions in an ascending order.</p>
<p>Tests can continue to check for the existence of forwards-compatible transaction fields by checking the transaction version using comparison operators:</p>
<pre><code>if (tx.nVersion &gt;= 2) {
for (int js = 0; js &lt; joinsplits; js++) {
...
}
}</code></pre>
<p>When (de)serializing v3 transactions, the version group id must also be checked in case the transaction is intended for a branch which has a different format for its version 3 transaction:</p>
<pre><code>if (tx.nVersion == 3 &amp;&amp; tx.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID) {
auto expiryHeight = tx.nExpiryHeight;
}</code></pre>
<p>Tests can continue to set the version to zero as an error condition:</p>
<pre><code>mtx.nVersion = 0</code></pre>
<h2 id="overwinter-validation">Overwinter Validation</h2>
<p>To test if the format of an Overwinter transaction is v3 or not:</p>
<pre><code>if (tx.fOverwintered &amp;&amp; tx.nVersion == 3) {
// Valid v3 format transaction
}</code></pre>
<p>This only tests that the format of the transaction matches the v3 specification described above.</p>
<p>To test if the format of an Overwinter transaction is both v3 and the transaction itself is intended for the client's chain:</p>
<pre><code>if (tx.fOverwintered &amp;&amp;
tx.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID) &amp;&amp;
tx.nVersion == 3) {
// Valid v3 format transaction intended for this client&#39;s chain
}</code></pre>
<p>It is expected that this test involving <code>nVersionGroupId</code> is only required when a transaction is being constructed or deserialized e.g. when an external transaction enters the system.</p>
<p>However, it's possible that a clone of Zcash is using the same version group id and passes the conditional.</p>
<p>Ultimately, a client can determine if a transaction is truly intended for the client's chain or not by following the signature verification process detailed in the Transaction Signature Verification for Overwinter ZIP<a href="#fn11" class="footnote-ref" id="fnref11"><sup>11</sup></a>.</p>
<h1 id="deployment">Deployment</h1>
<p>This proposal will be deployed with the Overwinter network upgrade. The activation block height proposal is in<a href="#fn12" class="footnote-ref" id="fnref12"><sup>12</sup></a>.</p>
<h1 id="backwards-compatibility">Backwards compatibility</h1>
<p>This proposal intentionally creates what is known as a &quot;bilateral consensus rule change&quot;<a href="#fn13" class="footnote-ref" id="fnref13"><sup>13</sup></a> between pre-Overwinter software and Overwinter-compatible software. Use of this new transaction format requires that all network participants upgrade their software to a compatible version within the upgrade window. Pre-Overwinter software will treat Overwinter transactions as invalid.</p>
<p>Once Overwinter has activated, Overwinter-compatible software will reject version 1 and version 2 transactions, and will only accept transactions based upon supported transaction version numbers and recognized version group ids.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p><a href="https://github.com/zcash/zcash/pull/2925" class="uri">https://github.com/zcash/zcash/pull/2925</a></p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Handshaking for Overwinter</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0203.rst">ZIP 203: Transaction Expiry</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://github.com/zcash/zips/blob/master/zip-0203.rst">ZIP 203: Transaction Expiry</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/zcash/zips/blob/master/zip-0203.rst">ZIP 203: Transaction Expiry</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://github.com/zcash/zcash/pull/2925/files#diff-5cb8d9decaa15620a8f98b0c6c44da9bR311">OVERWINTER_VERSION_GROUP_ID</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/zip-0143.rst">ZIP 143: Transaction Signature Verification for Overwinter</a><a href="#fnref10" class="footnote-back"></a></p></li>
<li id="fn11"><p><a href="https://github.com/zcash/zips/blob/master/zip-0143.rst">ZIP 143: Transaction Signature Verification for Overwinter</a><a href="#fnref11" class="footnote-back"></a></p></li>
<li id="fn12"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Handshaking for Overwinter</a><a href="#fnref12" class="footnote-back"></a></p></li>
<li id="fn13"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref13" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,383 +0,0 @@
ZIP: 202
Title: Version 3 Transaction Format for Overwinter
Owners: Daira Hopwood <daira@electriccoin.co>
Original-Authors: Simon Liu <simon@bitcartel.com>
Status: Final
Category: Consensus
Created: 2018-01-10
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", and \"MAY\" in this document are
to be interpreted as described in RFC 2119.[^1]
The terms \"branch\", \"network upgrade\", and \"consensus rule change\"
in this document are to be interpreted as described in ZIP 200.[^2]
The term \"Overwinter\" in this document is to be interpreted as
described in ZIP 201.[^3]
Abstract
========
This proposal defines a new transaction format required for Network
Upgrade Activation Mechanism[^4] and Transaction Expiry[^5].
Motivation
==========
Zcash launched with support for upstream Bitcoin version 1 transactions
and defined a new version 2 transaction format which added fields
required for shielded transactions.
Version Field Description Type
--------- ------------------- --------------------------- ---------------
\>= 1 `version` positive value `int32`
\>= 1 `tx_in_count` variable-length integer `compactSize`
\>= 1 `tx_in` list of inputs `vector`
\>= 1 `tx_out_count` variable-length integer `compactSize`
\>= 1 `tx_out` list of outputs `vector`
\>= 1 `lock_time` block height or timestamp `uint32`
\>= 2 `nJoinSplit` variable-length integer `compactSize`
\>= 2 `vJoinSplit` list of joinsplits `vector`
\>= 2 `joinSplitPubKey` joinsplit\_sig public key 32 bytes
\>= 2 `joinSplitSig` signature 64 bytes
A new transaction format is required to:
- support safe network upgrades as specified in Network Upgrade
Activation Mechanism[^6];
- provide replay protection between pre-Overwinter and Overwinter
branches during upgrades;
- provide replay protection between different branches
post-Overwinter;
- enable a branch to support multiple transaction version formats;
- ensure transaction formats are parsed uniquely across parallel
branches;
- support transaction expiry[^7].
Specification
=============
Transaction format version 3
----------------------------
A new version 3 transaction format will be introduced for Overwinter.
The version 3 format differs from the version 2 format in the following
ways:
- header (first four bytes, little-endian encoded)
- `fOverwintered` flag : bit 31, must be set
- `nVersion` : bits 30-0, positive integer
- `nVersionGroupId`
- `nExpiryHeight`
+-----------------+-----------------+-----------------+-----------------+
| Version | Field | Description | Type |
+=================+=================+=================+=================+
| \>= 3 | header | contains: | `uint32` |
| | | | |
| | | - `fOverwinte | |
| | | red` | |
| | | flag (bit | |
| | | 31, always | |
| | | set) | |
| | | - `nVersion` | |
| | | (bits 30-0) | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 3 | `nVersionGroupI | version group | `uint32` |
| | d` | id (not zero) | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 1 | `tx_in_count` | variable-length | `compactSize` |
| | | integer | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 1 | `tx_in` | list of inputs | `vector` |
+-----------------+-----------------+-----------------+-----------------+
| \>= 1 | `tx_out_count` | variable-length | `compactSize` |
| | | integer | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 1 | `tx_out` | list of outputs | `vector` |
+-----------------+-----------------+-----------------+-----------------+
| \>= 1 | `lock_time` | block height or | `uint32` |
| | | timestamp | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 3 | `expiryHeight` | block height | `uint32` |
+-----------------+-----------------+-----------------+-----------------+
| \>= 2 | `nJoinSplit` | variable-length | `compactSize` |
| | | integer | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 2 | `vJoinSplit` | list of | `vector` |
| | | joinsplits | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 2 | `joinSplitPubKe | joinsplit\_sig | 32 bytes |
| | y` | public key | |
+-----------------+-----------------+-----------------+-----------------+
| \>= 2 | `joinSplitSig` | signature | 64 bytes |
+-----------------+-----------------+-----------------+-----------------+
Header Field
------------
The first four bytes of pre-Overwinter and Overwinter transactions are
little-endian encoded.
Version 1 transaction (txid
5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061
<https://zcash.blockexplorer.com/tx/5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061>)
- begins with little-endian byte sequence \[0x01, 0x00, 0x00, 0x00\];
- deserialized as 32-bit signed integer with decimal value of 1.
Version 2 transaction (txid
4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b
<https://zcash.blockexplorer.com/tx/4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b>)
- begins with little-endian byte sequence \[0x02, 0x00, 0x00, 0x00\];
- deserialized as 32-bit signed integer with decimal value of 2.
Transaction parsers for versions of Zcash prior to Overwinter, and for
most other Bitcoin forks, require the transaction version number to be
positive.
With the version 3 transaction format, the first four bytes of a
serialized transaction, the 32-bit header, are made up of two fields as
shown in the table above:
- 1-bit `fOverwintered` flag, must be set;
- 31-bit unsigned int for the version.
Pre-Overwinter parsers will deserialize these four bytes as a 32-bit
signed integer. With two\'s complement integers, the most significant
bit indicates whether an integer is positive or negative. With the
Overwinter flag set, the transaction version will be negative, resulting
in pre-Overwinter parsers rejecting the transaction as invalid. This
provides transaction replay protection between pre-Overwinter and
Overwinter software.
Consider the following example of a serialized version 3 transaction.
Pre-Overwinter parser:
- data begins with little-endian byte sequence: \[0x03, 0x00, 0x00,
0x80\];
- deserialized as 32-bit signed integer.
- with hexadecimal value of 0x80000003 (most significant bit is
set);
- decimal value of -2147483645.
Legacy parsers will expect the version to be a positive value, such as 1
or 2, and will thus reject the Overwinter transaction as invalid.
Overwinter parser:
- data begins with little-endian byte sequence: \[0x03, 0x00, 0x00,
0x80\];
- deserialized as 32-bit unsigned integer
- with binary value of 0b10000000000000000000000000000011;
- the 32-bits are decomposed into two fields:
- `fOverwintered` flag (bit 31) as a boolean, expected to be set;
- version (bits 30 - bit 0) as an unsigned integer, expected to
have a decimal value of 3.
Overwinter parsers will accept the transaction as valid as the most
significant bit of the header has been set. By masking off (unsetting)
the most significant bit, the parser can retrieve the transaction
version number:
0x80000003 & 0x7FFFFFFF = 0x00000003 = 3
Version Group Id
----------------
The version group id is a non-zero, random and unique identifier, of
type `uint32`, assigned to a transaction format version, or a group of
soft-forking transaction format versions. The version group id helps
nodes disambiguate between branches using the same version number.
That is, it prevents a client on one branch of the network from
attempting to parse transactions intended for another branch, in the
situation where the transactions share the same format version number
but are actually specified differently. For example, Zcash and a clone
of Zcash might both define their own custom v3 transaction formats, but
each will have its own unique version group id, so that they can reject
v3 transactions with unknown version group ids.
The combination of transaction version and version group id,
`nVersion || nVersionGroupId`, uniquely defines the transaction format,
thus enabling parsers to reject transactions from outside the client\'s
chain which cannot be parsed.
By convention, it is expected that when introducing a new transaction
version requiring a network upgrade, a new unique version group id will
be assigned to that transaction version.
However, if a new transaction version can be correctly parsed according
to the format of a preceding version (that is, it only restricts the
format, or defines fields that were previously reserved and which old
parsers can safely ignore), then the same version group id MAY be
re-used.
Expiry Height
-------------
The expiry height field, as defined in the Transaction Expiry ZIP[^8],
stores the block height after which a transaction can no longer be
mined.
Transaction Validation
======================
A valid Overwinter transaction intended for Zcash MUST have:
- version number 3; and
- version group id 0x03C48270[^9]; and
- `fOverwintered` flag set.
Overwinter validators MUST reject transactions for violating consensus
rules if:
- the `fOverwintered` flag is not set; or
- the version group id is unknown; or
- the version number is unknown.
Validation of version 3 transactions MUST use the signature verification
process detailed in the Transaction Signature Verification for
Overwinter ZIP[^10].
Implementation
==============
The comments and code samples in this section apply to the reference C++
implementation of Zcash. Other implementations may vary.
Transaction Version
-------------------
Transaction version remains a positive value. The main Zcash chain will
follow convention and continue to order transaction versions in an
ascending order.
Tests can continue to check for the existence of forwards-compatible
transaction fields by checking the transaction version using comparison
operators:
if (tx.nVersion >= 2) {
for (int js = 0; js < joinsplits; js++) {
...
}
}
When (de)serializing v3 transactions, the version group id must also be
checked in case the transaction is intended for a branch which has a
different format for its version 3 transaction:
if (tx.nVersion == 3 && tx.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID) {
auto expiryHeight = tx.nExpiryHeight;
}
Tests can continue to set the version to zero as an error condition:
mtx.nVersion = 0
Overwinter Validation
---------------------
To test if the format of an Overwinter transaction is v3 or not:
if (tx.fOverwintered && tx.nVersion == 3) {
// Valid v3 format transaction
}
This only tests that the format of the transaction matches the v3
specification described above.
To test if the format of an Overwinter transaction is both v3 and the
transaction itself is intended for the client\'s chain:
if (tx.fOverwintered &&
tx.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID) &&
tx.nVersion == 3) {
// Valid v3 format transaction intended for this client's chain
}
It is expected that this test involving `nVersionGroupId` is only
required when a transaction is being constructed or deserialized e.g.
when an external transaction enters the system.
However, it\'s possible that a clone of Zcash is using the same version
group id and passes the conditional.
Ultimately, a client can determine if a transaction is truly intended
for the client\'s chain or not by following the signature verification
process detailed in the Transaction Signature Verification for
Overwinter ZIP[^11].
Deployment
==========
This proposal will be deployed with the Overwinter network upgrade. The
activation block height proposal is in[^12].
Backwards compatibility
=======================
This proposal intentionally creates what is known as a \"bilateral
consensus rule change\"[^13] between pre-Overwinter software and
Overwinter-compatible software. Use of this new transaction format
requires that all network participants upgrade their software to a
compatible version within the upgrade window. Pre-Overwinter software
will treat Overwinter transactions as invalid.
Once Overwinter has activated, Overwinter-compatible software will
reject version 1 and version 2 transactions, and will only accept
transactions based upon supported transaction version numbers and
recognized version group ids.
Reference Implementation
========================
<https://github.com/zcash/zcash/pull/2925>
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [ZIP 201: Network Handshaking for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)
[^4]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^5]: [ZIP 203: Transaction
Expiry](https://github.com/zcash/zips/blob/master/zip-0203.rst)
[^6]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^7]: [ZIP 203: Transaction
Expiry](https://github.com/zcash/zips/blob/master/zip-0203.rst)
[^8]: [ZIP 203: Transaction
Expiry](https://github.com/zcash/zips/blob/master/zip-0203.rst)
[^9]: [OVERWINTER\_VERSION\_GROUP\_ID](https://github.com/zcash/zcash/pull/2925/files#diff-5cb8d9decaa15620a8f98b0c6c44da9bR311)
[^10]: [ZIP 143: Transaction Signature Verification for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0143.rst)
[^11]: [ZIP 143: Transaction Signature Verification for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0143.rst)
[^12]: [ZIP 201: Network Handshaking for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)
[^13]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)

62
zip-0203.html Normal file
View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0203</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 203
Title: Transaction Expiry
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Original-Authors: Jay Graber
Status: Final
Category: Consensus
Created: 2018-01-09
License: MIT</code></pre>
<h1 id="abstract">Abstract</h1>
<p>This is a Standards ZIP describing a new consensus rule to set an expiration time after which a transaction cannot be mined. If it is not mined within that time, the transaction will be removed from nodes' mempools.</p>
<h1 id="motivation">Motivation</h1>
<p>Transactions that have insufficient fees are often not mined. This indeterminism is a source of confusion for users and wallets. Allowing a transaction to set a block height after which it cannot be mined would provide certainty around how long a transaction has to confirm before it is rejected by the network and must be re-sent.</p>
<p>Advantages include optimizing mempool performance by removing transactions that will not be mined, and potentially simplifying bidirectional payment channels by reducing the need to store and compress revocations for past states, since transactions not committed to the chain could expire and become invalid after a period of time.</p>
<p>If the expiry is at block height N, then the transaction must be included in block N or earlier. Block N+1 will be too late, and the transaction will be removed from the mempool.</p>
<p>The new consensus rule will enforce that the transaction will not be considered valid if included in block of height greater than N, and blocks that include expired transactions will not be considered valid.</p>
<h1 id="specification">Specification</h1>
<p>Transactions will have a new field, <code>nExpiryHeight</code>, which will set the block height after which transactions will be removed from the mempool if they have not been mined.</p>
<p>The data type for <code>nExpiryHeight</code> will be <code>uint32_t</code>. If used in combination with <code>nLockTime</code>, both <code>nLockTime</code> and <code>nExpiryHeight</code> must be block heights. <code>nExpiryHeight</code> will never be a UNIX timestamp, unlike <code>nLockTime</code> values, and thus the maximum expiry height will be 499999999.</p>
<p>For the example below, the last block that the transaction below could possibly be included in is 3539. After that, it will be removed from the mempool.</p>
<p><code>` &quot;txid&quot;: &quot;17561b98cc77cd5a984bb959203e073b5f33cf14cbce90eb32b95ae2c796723f&quot;, &quot;version&quot;: 3, &quot;locktime&quot;: 2089, &quot;expiryheight&quot;: 3539,</code>`</p>
<p>Default: 20 blocks, or about 1 hour assuming 2.5 minute block times. A configuration option can be used to set the user's default. Minimum: No minimum Maximum: 499999999, about 380 years No limit: To set no limit on transactions (so that they do not expire), <code>nExpiryHeight</code> should be set to 0. Coinbase: <code>nExpiryHeight</code> on coinbase transactions is ignored, and is set to 0 by convention.</p>
<p>Every time a transaction expires and should be removed from the mempool, so should all of its dependent transactions.</p>
<h2 id="wallet-behavior-and-ui">Wallet behavior and UI</h2>
<p>With the addition of this feature, zero-confirmation transactions with an expiration block height set will have even less guarantee of inclusion. This means that UIs and services must never rely on zero-confirmation transactions in Zcash.</p>
<p>Wallet should notify the user of expired transactions that must be re-sent.</p>
<h2 id="rpc">RPC</h2>
<p>To make changes to the sendtoaddress and z_sendmany commands backwards compatible for future changes, keyword arguments should be accepted by the RPC interface.</p>
<p>For Overwinter, tx expiry will be set to a default that can be overridden by a flag txexpirydelta set in the config file.</p>
<p>-txexpirydelta= set the number of blocks after which a transaction that has not been mined will become invalid</p>
<p>To view: listtransactions has a new filter attribute, showing expired transactions only: listtransactions &quot;*&quot; 10 0 &quot;expired&quot;</p>
<p>WalletTxToJSON shows a boolean expired true/false.</p>
<h2 id="config">Config</h2>
<p>The default will be user-configurable with the option txexpirydelta.</p>
<p>--txexpirydelta=100</p>
<h2 id="deployment">Deployment</h2>
<p>This feature will be deployed with Overwinter. The activation blockheight proposal is in<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p><a href="https://github.com/zcash/zcash/pull/2874" class="uri">https://github.com/zcash/zcash/pull/2874</a></p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref1" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,121 +0,0 @@
ZIP: 203
Title: Transaction Expiry
Owners: Daira Hopwood <daira@electriccoin.co>
Original-Authors: Jay Graber
Status: Final
Category: Consensus
Created: 2018-01-09
License: MIT
Abstract
========
This is a Standards ZIP describing a new consensus rule to set an
expiration time after which a transaction cannot be mined. If it is not
mined within that time, the transaction will be removed from nodes\'
mempools.
Motivation
==========
Transactions that have insufficient fees are often not mined. This
indeterminism is a source of confusion for users and wallets. Allowing a
transaction to set a block height after which it cannot be mined would
provide certainty around how long a transaction has to confirm before it
is rejected by the network and must be re-sent.
Advantages include optimizing mempool performance by removing
transactions that will not be mined, and potentially simplifying
bidirectional payment channels by reducing the need to store and
compress revocations for past states, since transactions not committed
to the chain could expire and become invalid after a period of time.
If the expiry is at block height N, then the transaction must be
included in block N or earlier. Block N+1 will be too late, and the
transaction will be removed from the mempool.
The new consensus rule will enforce that the transaction will not be
considered valid if included in block of height greater than N, and
blocks that include expired transactions will not be considered valid.
Specification
=============
Transactions will have a new field, `nExpiryHeight`, which will set the
block height after which transactions will be removed from the mempool
if they have not been mined.
The data type for `nExpiryHeight` will be `uint32_t`. If used in
combination with `nLockTime`, both `nLockTime` and `nExpiryHeight` must
be block heights. `nExpiryHeight` will never be a UNIX timestamp, unlike
`nLockTime` values, and thus the maximum expiry height will be
499999999.
For the example below, the last block that the transaction below could
possibly be included in is 3539. After that, it will be removed from the
mempool.
`` ` "txid": "17561b98cc77cd5a984bb959203e073b5f33cf14cbce90eb32b95ae2c796723f", "version": 3, "locktime": 2089, "expiryheight": 3539, ``\`
Default: 20 blocks, or about 1 hour assuming 2.5 minute block times. A
configuration option can be used to set the user\'s default. Minimum: No
minimum Maximum: 499999999, about 380 years No limit: To set no limit on
transactions (so that they do not expire), `nExpiryHeight` should be set
to 0. Coinbase: `nExpiryHeight` on coinbase transactions is ignored, and
is set to 0 by convention.
Every time a transaction expires and should be removed from the mempool,
so should all of its dependent transactions.
Wallet behavior and UI
----------------------
With the addition of this feature, zero-confirmation transactions with
an expiration block height set will have even less guarantee of
inclusion. This means that UIs and services must never rely on
zero-confirmation transactions in Zcash.
Wallet should notify the user of expired transactions that must be
re-sent.
RPC
---
To make changes to the sendtoaddress and z\_sendmany commands backwards
compatible for future changes, keyword arguments should be accepted by
the RPC interface.
For Overwinter, tx expiry will be set to a default that can be
overridden by a flag txexpirydelta set in the config file.
-txexpirydelta= set the number of blocks after which a transaction that
has not been mined will become invalid
To view: listtransactions has a new filter attribute, showing expired
transactions only: listtransactions \"\*\" 10 0 \"expired\"
WalletTxToJSON shows a boolean expired true/false.
Config
------
The default will be user-configurable with the option txexpirydelta.
\--txexpirydelta=100
Deployment
----------
This feature will be deployed with Overwinter. The activation
blockheight proposal is in[^1].
Reference Implementation
========================
<https://github.com/zcash/zcash/pull/2874>
References
==========
[^1]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)

94
zip-0205.html Normal file
View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0205</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 205
Title: Deployment of the Sapling Network Upgrade
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Credits: Simon Liu &lt;simon@bitcartel.com&gt;
Status: Final
Category: Consensus
Created: 2018-10-08
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms &quot;branch&quot; and &quot;network upgrade&quot; in this document are to be interpreted as described in ZIP 200.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>Sapling</dt>
<dd><p>Code-name for the second Zcash network upgrade, also known as Network Upgrade 1.</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines the deployment of the Sapling network upgrade. In addition, it describes a hard fork that occurred on testnet to allow &quot;minimum-difficulty&quot; blocks.</p>
<h1 id="specification">Specification</h1>
<h2 id="sapling-deployment">Sapling deployment</h2>
<p>The primary sources of information about Sapling consensus protocol changes are:</p>
<ul>
<li>The Zcash Protocol Specification<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</li>
<li>Transaction Signature Verification for Sapling<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>.</li>
<li>Network Upgrade Activation Mechanism<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</li>
</ul>
<p>The network handshake and peer management mechanisms defined in<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a> also apply to this upgrade.</p>
<p>The following network upgrade constants<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a> are defined for the Sapling upgrade:</p>
<dl>
<dt>BRANCH_ID</dt>
<dd><p><code>0x76b809bb</code></p>
</dd>
<dt>ACTIVATION_HEIGHT (Sapling)</dt>
<dd><p>Testnet: 280000</p>
<p>Mainnet: 419200</p>
</dd>
</dl>
<p>On testnet, Sapling had activated prior to this height, but that branch was rolled back. A subsequent hard fork occurred on testnet, changing the difficulty algorithm to accept &quot;minimum-difficulty&quot; blocks under certain conditions starting at block height 299188.</p>
<p>On both mainnet and testnet, Sapling-compatible nodes MUST advertise protocol version 170007 or later. The minimum peer protocol version that Sapling-compatible nodes will connect to, remains 170002.</p>
<p>Pre-Sapling nodes are defined as nodes advertising a protocol version less than 170007.</p>
<p>Approximately three days (defined in terms of block height) before the Sapling activation height, Sapling-compatible nodes will change the behaviour of their peer connection logic in order to prefer pre-Sapling peers for eviction from the set of peer connections.</p>
<blockquote>
<p>/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). <em>/ static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24</em> 24 * 3;</p>
</blockquote>
<p>The implementation is similar to that for Overwinter which was described in <a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a>.</p>
<p>Once Sapling activates on testnet or mainnet, Sapling nodes should take steps to:</p>
<ul>
<li>reject new connections from pre-Sapling nodes;</li>
<li>disconnect any existing connections to pre-Sapling nodes.</li>
</ul>
<h2 id="change-to-difficulty-adjustment-on-testnet">Change to difficulty adjustment on testnet</h2>
<p>Section 7.6.3 of<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a> describes the algorithm used to adjust the difficulty of a block (defined in terms of a &quot;target threshold&quot;) based on the <code>nTime</code> and <code>nBits</code> fields of preceding blocks.</p>
<p>This algorithm changed on testnet, starting from block 299188, to allow &quot;minimum-difficulty&quot; blocks. If the block time of a block from this height onward is at least 15 minutes after that of the preceding block, then the block is a minimum-difficulty block, and its target threshold is set to the value of PoWLimit for testnet (see<a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a> section 5.3). However, its <code>nBits</code> field is still computed according to the original difficulty adjustment algorithm.</p>
<p>This does not affect how the minimum-difficulty block is treated for subsequent difficulty adjustments. In particular, only the <code>nBits</code> field computed by the original algorithm is used for the purpose of computing the MeanTarget values from which subsequent difficulty changes are calculated.</p>
<p>This change does not affect mainnet.</p>
<h1 id="backward-compatibility">Backward compatibility</h1>
<p>Prior to the network upgrade activating, Sapling and pre-Sapling nodes are compatible and can connect to each other. However, Sapling nodes will have a preference for connecting to other Sapling nodes, so pre-Sapling nodes will gradually be disconnected in the run up to activation.</p>
<p>Once the network upgrades, even though pre-Sapling nodes can still accept the numerically larger protocol version used by Sapling as being valid, Sapling nodes will always disconnect peers using lower protocol versions.</p>
<h1 id="support-in-zcashd">Support in zcashd</h1>
<p>Support for Sapling consensus rules was implemented in zcashd version 2.0.0. The majority of support for RPC calls and persistence of Sapling z-addresses was implemented in version 2.0.1. Both of these versions advertise protocol version 170007.</p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0243.rst">ZIP 243: Transaction Signature Verification for Sapling</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref10" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,168 +0,0 @@
ZIP: 205
Title: Deployment of the Sapling Network Upgrade
Owners: Daira Hopwood <daira@electriccoin.co>
Credits: Simon Liu <simon@bitcartel.com>
Status: Final
Category: Consensus
Created: 2018-10-08
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", \"SHOULD\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The terms \"branch\" and \"network upgrade\" in this document are to be
interpreted as described in ZIP 200.[^2]
The terms below are to be interpreted as follows:
Sapling
: Code-name for the second Zcash network upgrade, also known as
Network Upgrade 1.
Abstract
========
This proposal defines the deployment of the Sapling network upgrade. In
addition, it describes a hard fork that occurred on testnet to allow
\"minimum-difficulty\" blocks.
Specification
=============
Sapling deployment
------------------
The primary sources of information about Sapling consensus protocol
changes are:
- The Zcash Protocol Specification[^3].
- Transaction Signature Verification for Sapling[^4].
- Network Upgrade Activation Mechanism[^5].
The network handshake and peer management mechanisms defined in[^6] also
apply to this upgrade.
The following network upgrade constants[^7] are defined for the Sapling
upgrade:
BRANCH\_ID
: `0x76b809bb`
ACTIVATION\_HEIGHT (Sapling)
: Testnet: 280000
Mainnet: 419200
On testnet, Sapling had activated prior to this height, but that branch
was rolled back. A subsequent hard fork occurred on testnet, changing
the difficulty algorithm to accept \"minimum-difficulty\" blocks under
certain conditions starting at block height 299188.
On both mainnet and testnet, Sapling-compatible nodes MUST advertise
protocol version 170007 or later. The minimum peer protocol version that
Sapling-compatible nodes will connect to, remains 170002.
Pre-Sapling nodes are defined as nodes advertising a protocol version
less than 170007.
Approximately three days (defined in terms of block height) before the
Sapling activation height, Sapling-compatible nodes will change the
behaviour of their peer connection logic in order to prefer pre-Sapling
peers for eviction from the set of peer connections.
> /\*\* The period before a network upgrade activates, where connections
> to upgrading peers are preferred (in blocks). */ static const int
> NETWORK\_UPGRADE\_PEER\_PREFERENCE\_BLOCK\_PERIOD = 24* 24 \* 3;
The implementation is similar to that for Overwinter which was described
in [^8].
Once Sapling activates on testnet or mainnet, Sapling nodes should take
steps to:
- reject new connections from pre-Sapling nodes;
- disconnect any existing connections to pre-Sapling nodes.
Change to difficulty adjustment on testnet
------------------------------------------
Section 7.6.3 of[^9] describes the algorithm used to adjust the
difficulty of a block (defined in terms of a \"target threshold\") based
on the `nTime` and `nBits` fields of preceding blocks.
This algorithm changed on testnet, starting from block 299188, to allow
\"minimum-difficulty\" blocks. If the block time of a block from this
height onward is at least 15 minutes after that of the preceding block,
then the block is a minimum-difficulty block, and its target threshold
is set to the value of PoWLimit for testnet (see[^10] section 5.3).
However, its `nBits` field is still computed according to the original
difficulty adjustment algorithm.
This does not affect how the minimum-difficulty block is treated for
subsequent difficulty adjustments. In particular, only the `nBits` field
computed by the original algorithm is used for the purpose of computing
the MeanTarget values from which subsequent difficulty changes are
calculated.
This change does not affect mainnet.
Backward compatibility
======================
Prior to the network upgrade activating, Sapling and pre-Sapling nodes
are compatible and can connect to each other. However, Sapling nodes
will have a preference for connecting to other Sapling nodes, so
pre-Sapling nodes will gradually be disconnected in the run up to
activation.
Once the network upgrades, even though pre-Sapling nodes can still
accept the numerically larger protocol version used by Sapling as being
valid, Sapling nodes will always disconnect peers using lower protocol
versions.
Support in zcashd
=================
Support for Sapling consensus rules was implemented in zcashd version
2.0.0. The majority of support for RPC calls and persistence of Sapling
z-addresses was implemented in version 2.0.1. Both of these versions
advertise protocol version 170007.
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [Zcash Protocol Specification, Version 2018.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^4]: [ZIP 243: Transaction Signature Verification for
Sapling](https://github.com/zcash/zips/blob/master/zip-0243.rst)
[^5]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^6]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)
[^7]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^8]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)
[^9]: [Zcash Protocol Specification, Version 2018.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^10]: [Zcash Protocol Specification, Version 2018.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)

93
zip-0206.html Normal file
View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0206</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 206
Title: Deployment of the Blossom Network Upgrade
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Credits: Simon Liu &lt;simon@bitcartel.com&gt;
Status: Draft
Category: Consensus
Created: 2019-07-29
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The term &quot;network upgrade&quot; in this document is to be interpreted as described in ZIP 200.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>Blossom</dt>
<dd><p>Code-name for the third Zcash network upgrade, also known as Network Upgrade 2.</p>
</dd>
<dt>Testnet</dt>
<dd><p>The Zcash test network, as defined in<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</p>
</dd>
<dt>Mainnet</dt>
<dd><p>The Zcash production network, as defined in<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>.</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines the deployment of the Blossom network upgrade.</p>
<h1 id="specification">Specification</h1>
<h2 id="blossom-deployment">Blossom deployment</h2>
<p>The primary sources of information about Blossom consensus protocol changes are:</p>
<ul>
<li>The Zcash Protocol Specification<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</li>
<li>Shorter Block Target Spacing<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a>.</li>
<li>Network Upgrade Activation Mechanism<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a>.</li>
</ul>
<p>The network handshake and peer management mechanisms defined in<a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a> also apply to this upgrade.</p>
<p>The following network upgrade constants<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a> are defined for the Blossom upgrade:</p>
<dl>
<dt>BRANCH_ID</dt>
<dd><p><code>0xXXXXXXXX</code></p>
</dd>
<dt>ACTIVATION_HEIGHT (Blossom)</dt>
<dd><p>Testnet: XXXXXX</p>
<p>Mainnet: XXXXXX</p>
</dd>
</dl>
<p>Nodes compatible with Blossom activation on testnet MUST advertise protocol version 170008 or later. Nodes compatible with Blossom activation on mainnet MUST advertise protocol version 170009 or later. The minimum peer protocol version that Blossom-compatible nodes will connect to will be 170007.</p>
<p>Pre-Blossom testnet nodes are defined as nodes on testnet advertising a protocol version less than 170008. Pre-Blossom mainnet nodes are defined as nodes on mainnet advertising a protocol version less than 170009.</p>
<p>For each network (testnet and mainnet), approximately three days (defined in terms of block height) before the corresponding Blossom activation height, nodes compatible with Blossom activation on that network will change the behaviour of their peer connection logic in order to prefer pre-Blossom peers on that network for eviction from the set of peer connections:</p>
<pre><code>/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;</code></pre>
<p>The implementation is similar to that for Overwinter which was described in <a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a>.</p>
<p>Once Blossom activates on testnet or mainnet, Blossom nodes should take steps to:</p>
<ul>
<li>reject new connections from pre-Blossom nodes on that network;</li>
<li>disconnect any existing connections to pre-Blossom nodes on that network.</li>
</ul>
<h1 id="backward-compatibility">Backward compatibility</h1>
<p>Prior to the network upgrade activating on each network, Blossom and pre-Blossom nodes are compatible and can connect to each other. However, Blossom nodes will have a preference for connecting to other Blossom nodes, so pre-Blossom nodes will gradually be disconnected in the run up to activation.</p>
<p>Once the network upgrades, even though pre-Blossom nodes can still accept the numerically larger protocol version used by Blossom as being valid, Blossom nodes will always disconnect peers using lower protocol versions.</p>
<h1 id="support-in-zcashd">Support in zcashd</h1>
<p>Support for Blossom on testnet will be implemented in <code>zcashd</code> version 2.0.7, which will advertise protocol version 170008. Support for Blossom on mainnet will be implemented in <code>zcashd</code> version 2.1.0, which will advertise protocol version 170009.</p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2019.0.4 or later [Overwinter+Sapling+Blossom]</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2019.0.4 or later [Overwinter+Sapling+Blossom]</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2019.0.4 or later [Overwinter+Sapling+Blossom]</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0208.rst">ZIP 208: Shorter Block Target Spacing</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/zip-0201.rst">ZIP 201: Network Peer Management for Overwinter</a><a href="#fnref10" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,151 +0,0 @@
ZIP: 206
Title: Deployment of the Blossom Network Upgrade
Owners: Daira Hopwood <daira@electriccoin.co>
Credits: Simon Liu <simon@bitcartel.com>
Status: Draft
Category: Consensus
Created: 2019-07-29
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", \"SHOULD\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The term \"network upgrade\" in this document is to be interpreted as
described in ZIP 200.[^2]
The terms below are to be interpreted as follows:
Blossom
: Code-name for the third Zcash network upgrade, also known as Network
Upgrade 2.
Testnet
: The Zcash test network, as defined in[^3].
Mainnet
: The Zcash production network, as defined in[^4].
Abstract
========
This proposal defines the deployment of the Blossom network upgrade.
Specification
=============
Blossom deployment
------------------
The primary sources of information about Blossom consensus protocol
changes are:
- The Zcash Protocol Specification[^5].
- Shorter Block Target Spacing[^6].
- Network Upgrade Activation Mechanism[^7].
The network handshake and peer management mechanisms defined in[^8] also
apply to this upgrade.
The following network upgrade constants[^9] are defined for the Blossom
upgrade:
BRANCH\_ID
: `0xXXXXXXXX`
ACTIVATION\_HEIGHT (Blossom)
: Testnet: XXXXXX
Mainnet: XXXXXX
Nodes compatible with Blossom activation on testnet MUST advertise
protocol version 170008 or later. Nodes compatible with Blossom
activation on mainnet MUST advertise protocol version 170009 or later.
The minimum peer protocol version that Blossom-compatible nodes will
connect to will be 170007.
Pre-Blossom testnet nodes are defined as nodes on testnet advertising a
protocol version less than 170008. Pre-Blossom mainnet nodes are defined
as nodes on mainnet advertising a protocol version less than 170009.
For each network (testnet and mainnet), approximately three days
(defined in terms of block height) before the corresponding Blossom
activation height, nodes compatible with Blossom activation on that
network will change the behaviour of their peer connection logic in
order to prefer pre-Blossom peers on that network for eviction from the
set of peer connections:
/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
The implementation is similar to that for Overwinter which was described
in [^10].
Once Blossom activates on testnet or mainnet, Blossom nodes should take
steps to:
- reject new connections from pre-Blossom nodes on that network;
- disconnect any existing connections to pre-Blossom nodes on that
network.
Backward compatibility
======================
Prior to the network upgrade activating on each network, Blossom and
pre-Blossom nodes are compatible and can connect to each other. However,
Blossom nodes will have a preference for connecting to other Blossom
nodes, so pre-Blossom nodes will gradually be disconnected in the run up
to activation.
Once the network upgrades, even though pre-Blossom nodes can still
accept the numerically larger protocol version used by Blossom as being
valid, Blossom nodes will always disconnect peers using lower protocol
versions.
Support in zcashd
=================
Support for Blossom on testnet will be implemented in `zcashd` version
2.0.7, which will advertise protocol version 170008. Support for Blossom
on mainnet will be implemented in `zcashd` version 2.1.0, which will
advertise protocol version 170009.
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [Zcash Protocol Specification, Version 2019.0.4 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^4]: [Zcash Protocol Specification, Version 2019.0.4 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^5]: [Zcash Protocol Specification, Version 2019.0.4 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^6]: [ZIP 208: Shorter Block Target
Spacing](https://github.com/zcash/zips/blob/master/zip-0208.rst)
[^7]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^8]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)
[^9]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^10]: [ZIP 201: Network Peer Management for
Overwinter](https://github.com/zcash/zips/blob/master/zip-0201.rst)

652
zip-0207.html Normal file
View File

@ -0,0 +1,652 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0207</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(title);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
</head>
<body>
<pre><code>ZIP: 207
Title: Split Founders&#39; Reward
Owners: Jack Grigg &lt;str4d@electriccoin.co&gt;
Category: Consensus
Status: Withdrawn
Created: 2019-01-04
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<h1 id="abstract">Abstract</h1>
<p>This Withdrawn proposal would have altered consensus rules to split the original Founders' Reward across several recipient addresses per block instead of one, corresponding to the several funding streams contained within it.</p>
<h1 id="motivation">Motivation</h1>
<p>Since the launch of the Zcash network, the consensus rules have required that until the first block reward halving (at block 850,000), each block must send 20% of the block subsidy to a hard-coded transparent address. <a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> This funding stream is referred to as the Founders' Reward.</p>
<p>This stream of 2.5-ZEC outputs (the value after the mining slow-start was completed) can be split into several logical funding streams (for background, see<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>). Modifying the consensus rules to allocate the 2.5 ZEC across separate recipient addresses decouples these funding streams organizationally, legally, and operationally. It further reinforces transparency as to the structure of the original Founders' Reward.</p>
<h1 id="specification">Specification</h1>
<h2 id="definitions">Definitions</h2>
<p>We use the following constants and functions defined in<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>:</p>
<ul>
<li><code>BlossomActivationHeight</code></li>
<li><code>PostBlossomHalvingInterval</code></li>
<li><code>Halving(height)</code></li>
</ul>
<p>We also define the following constants and functions:</p>
<ul>
<li><code>SlowStartShift</code> as-defined in<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</li>
<li><code>HeightForHalving(halving)</code>: Smallest <code>height</code> such that <code>Halving(height) = halving</code></li>
</ul>
<h2 id="funding-streams">Funding streams</h2>
<p>A funding stream is defined by a block reward fraction (represented as a numerator and a denominator), a start height (inclusive), and an end height (exclusive).</p>
<p>By defining the issuance as a proportion of the total block issuance, rather than absolute zatoshis, this ZIP dovetails with any changes to both block target times and issuance-per-block rates while maintaining an unchanged target-time-based issuance schedule. We anticipate such target-time / issuance rate changes in other ZIPs (for example,<a href="#fn6" class="footnote-ref" id="fnref6"><sup>6</sup></a>).</p>
<p>The value of a funding stream at a given block height is defined as:</p>
<pre><code>FundingStream[FUND].Value(height) =
floor((
BlockReward(height) * FundingStream[FUND].ValueNumerator
) / FundingStream[FUND].ValueDenominator)</code></pre>
<p>An active funding stream at a given block height is defined as a funding stream for which the block height is less than its end height, but not less than its start height.</p>
<p>Each funding stream has an associated set of recipient addresses. Each address is used for at most 1/48th of a halving interval, creating a roughly-monthly sequence of funding periods. The address to be used for a given block height is defined as follows:</p>
<pre><code>AddressChangeInterval = PostBlossomHalvingInterval / 48
AddressPeriod(height) =
floor((
height + PostBlossomHalvingInterval - HeightForHalving(1)
) / AddressChangeInterval)
FundingStream[FUND].AddressIndex(height) =
AddressPeriod(height) - AddressPeriod(FundingStream[FUND].StartHeight)
Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex(height)]</code></pre>
<p>This has the property that all active funding streams change the address they are using on the same block height schedule, aligned to the height of the first halving so that 48 funding periods fit cleanly within a halving interval. This can be leveraged to simplify implementations, by batching the necessary outputs for each funding period.</p>
<p>Below is a visual representation of how stream addresses align with funding periods:</p>
<table>
<thead>
<tr class="header">
<th>Example height</th>
<th>Stream A</th>
<th>Stream B</th>
<th>Stream C</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><blockquote>
<p><code>AddressChangeInterval - 2</code> <code>AddressChangeInterval - 1</code></p>
</blockquote></td>
<td><blockquote>
<p>A0 A0</p>
</blockquote></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td><blockquote>
<p><code>AddressChangeInterval</code></p>
</blockquote></td>
<td><blockquote>
<p>A1</p>
</blockquote></td>
<td><blockquote>
<p>B0</p>
</blockquote></td>
<td><blockquote>
<p>C0</p>
</blockquote></td>
</tr>
<tr class="odd">
<td><blockquote>
<dl>
<dt><code>AddressChangeInterval + 1</code></dt>
<dd><p>...</p>
</dd>
</dl>
</blockquote></td>
<td><blockquote>
<p>A1</p>
</blockquote></td>
<td><blockquote>
<p>B0</p>
</blockquote></td>
<td><blockquote>
<p>C0</p>
</blockquote></td>
</tr>
<tr class="even">
<td><blockquote>
<p><code>2*AddressChangeInterval - 2</code></p>
</blockquote></td>
<td><blockquote>
<p>A1</p>
</blockquote></td>
<td><blockquote>
<p>B0</p>
</blockquote></td>
<td><blockquote>
<p>C0</p>
</blockquote></td>
</tr>
<tr class="odd">
<td><blockquote>
<p><code>2*AddressChangeInterval - 1</code> <code>2*AddressChangeInterval</code> <code>2*AddressChangeInterval + 1</code> ...</p>
</blockquote>
<p><code>PostBlossomHalvingInterval - 2</code> <code>PostBlossomHalvingInterval - 1</code> <code>PostBlossomHalvingInterval</code> <code>PostBlossomHalvingInterval + 1</code></p></td>
<td><blockquote>
<p>A1 A2 A2</p>
<p>A2 A2</p>
</blockquote></td>
<td><blockquote>
<p>B0</p>
</blockquote></td>
<td><blockquote>
<p>C0 C1 C1</p>
<p>C1 C1 C2 C2</p>
</blockquote></td>
</tr>
</tbody>
</table>
<p>Note that this is not intended to align with the end of a pre-Blossom Founders' Reward address period (as defined by <code>FounderAddressChangeInterval</code> in<a href="#fn7" class="footnote-ref" id="fnref7"><sup>7</sup></a>). There will be a shortened Founders' Reward address period prior to Blossom activation.</p>
<h2 id="consensus-rules">Consensus rules</h2>
<p>Prior to activation of the Blossom network upgrade, the existing consensus rule for payment of the original Founders' Reward is enforced.<a href="#fn8" class="footnote-ref" id="fnref8"><sup>8</sup></a></p>
<p>Once the Blossom network upgrade activates:</p>
<ul>
<li>The existing consensus rule<a href="#fn9" class="footnote-ref" id="fnref9"><sup>9</sup></a> is no longer active.</li>
<li>The coinbase transaction in each block MUST contain at least one output per active funding stream that pays the stream's value to the stream's recipient address for the block's height.</li>
</ul>
<h2 id="stream-definitions">Stream definitions</h2>
<p>The consensus-defined funding streams described above each start at the Blossom activation height, and end at the first block reward halving. They are defined as follows:</p>
<table>
<thead>
<tr class="header">
<th>Stream</th>
<th>Value numerator</th>
<th>Value denominator</th>
<th>Start height</th>
<th>End height</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><blockquote>
<p>FS 1</p>
</blockquote></td>
<td><blockquote>
<p>3</p>
</blockquote></td>
<td><blockquote>
<p>40</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="even">
<td><blockquote>
<p>FS 2</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>25</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="odd">
<td><blockquote>
<p>FS 3</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>40</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="even">
<td><blockquote>
<p>FS 4</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>50</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="odd">
<td><blockquote>
<p>FS 5</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>80</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="even">
<td><blockquote>
<p>FS 6</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>80</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="odd">
<td><blockquote>
<p>FS 7</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>100</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr class="even">
<td><blockquote>
<p>FS 8</p>
</blockquote></td>
<td><blockquote>
<p>1</p>
</blockquote></td>
<td><blockquote>
<p>200</p>
</blockquote></td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
</tbody>
</table>
<ul>
<li>To-do: specify the correct values.</li>
</ul>
<p>The sum of the block reward fractions for the above funding streams is <code>1/5</code>, equal to the original Founders' Reward (as-defined by <code>FoundersFraction</code> in<a href="#fn10" class="footnote-ref" id="fnref10"><sup>10</sup></a>).</p>
<p>The sets of recipient addresses are defined as follows:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb4-1" title="1"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_1_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-2" title="2"> <span class="st">&quot;tFS1INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-3" title="3"> <span class="st">&quot;tFS1INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-4" title="4"> <span class="st">&quot;tFS1INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-5" title="5"> <span class="st">&quot;tFS1INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-6" title="6"> <span class="st">&quot;tFS1INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-7" title="7"> <span class="st">&quot;tFS1INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-8" title="8"> <span class="st">&quot;tFS1INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-9" title="9"> <span class="st">&quot;tFS1INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-10" title="10"> <span class="st">&quot;tFS1INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-11" title="11"> <span class="st">&quot;tFS1INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-12" title="12"> <span class="st">&quot;tFS1INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-13" title="13"> <span class="st">&quot;tFS1INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-14" title="14">];</a>
<a class="sourceLine" id="cb4-15" title="15"></a>
<a class="sourceLine" id="cb4-16" title="16"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_2_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-17" title="17"> <span class="st">&quot;tFS2INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-18" title="18"> <span class="st">&quot;tFS2INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-19" title="19"> <span class="st">&quot;tFS2INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-20" title="20"> <span class="st">&quot;tFS2INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-21" title="21"> <span class="st">&quot;tFS2INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-22" title="22"> <span class="st">&quot;tFS2INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-23" title="23"> <span class="st">&quot;tFS2INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-24" title="24"> <span class="st">&quot;tFS2INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-25" title="25"> <span class="st">&quot;tFS2INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-26" title="26"> <span class="st">&quot;tFS2INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-27" title="27"> <span class="st">&quot;tFS2INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-28" title="28"> <span class="st">&quot;tFS2INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-29" title="29">];</a>
<a class="sourceLine" id="cb4-30" title="30"></a>
<a class="sourceLine" id="cb4-31" title="31"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_3_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-32" title="32"> <span class="st">&quot;tFS3INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-33" title="33"> <span class="st">&quot;tFS3INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-34" title="34"> <span class="st">&quot;tFS3INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-35" title="35"> <span class="st">&quot;tFS3INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-36" title="36"> <span class="st">&quot;tFS3INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-37" title="37"> <span class="st">&quot;tFS3INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-38" title="38"> <span class="st">&quot;tFS3INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-39" title="39"> <span class="st">&quot;tFS3INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-40" title="40"> <span class="st">&quot;tFS3INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-41" title="41"> <span class="st">&quot;tFS3INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-42" title="42"> <span class="st">&quot;tFS3INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-43" title="43"> <span class="st">&quot;tFS3INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-44" title="44">];</a>
<a class="sourceLine" id="cb4-45" title="45"></a>
<a class="sourceLine" id="cb4-46" title="46"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_4_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-47" title="47"> <span class="st">&quot;tFS4INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-48" title="48"> <span class="st">&quot;tFS4INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-49" title="49"> <span class="st">&quot;tFS4INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-50" title="50"> <span class="st">&quot;tFS4INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-51" title="51"> <span class="st">&quot;tFS4INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-52" title="52"> <span class="st">&quot;tFS4INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-53" title="53"> <span class="st">&quot;tFS4INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-54" title="54"> <span class="st">&quot;tFS4INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-55" title="55"> <span class="st">&quot;tFS4INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-56" title="56"> <span class="st">&quot;tFS4INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-57" title="57"> <span class="st">&quot;tFS4INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-58" title="58"> <span class="st">&quot;tFS4INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-59" title="59">];</a>
<a class="sourceLine" id="cb4-60" title="60"></a>
<a class="sourceLine" id="cb4-61" title="61"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_5_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-62" title="62"> <span class="st">&quot;tFS5INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-63" title="63"> <span class="st">&quot;tFS5INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-64" title="64"> <span class="st">&quot;tFS5INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-65" title="65"> <span class="st">&quot;tFS5INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-66" title="66"> <span class="st">&quot;tFS5INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-67" title="67"> <span class="st">&quot;tFS5INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-68" title="68"> <span class="st">&quot;tFS5INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-69" title="69"> <span class="st">&quot;tFS5INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-70" title="70"> <span class="st">&quot;tFS5INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-71" title="71"> <span class="st">&quot;tFS5INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-72" title="72"> <span class="st">&quot;tFS5INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-73" title="73"> <span class="st">&quot;tFS5INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-74" title="74">];</a>
<a class="sourceLine" id="cb4-75" title="75"></a>
<a class="sourceLine" id="cb4-76" title="76"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_6_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-77" title="77"> <span class="st">&quot;tFS6INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-78" title="78"> <span class="st">&quot;tFS6INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-79" title="79"> <span class="st">&quot;tFS6INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-80" title="80"> <span class="st">&quot;tFS6INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-81" title="81"> <span class="st">&quot;tFS6INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-82" title="82"> <span class="st">&quot;tFS6INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-83" title="83"> <span class="st">&quot;tFS6INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-84" title="84"> <span class="st">&quot;tFS6INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-85" title="85"> <span class="st">&quot;tFS6INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-86" title="86"> <span class="st">&quot;tFS6INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-87" title="87"> <span class="st">&quot;tFS6INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-88" title="88"> <span class="st">&quot;tFS6INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-89" title="89">];</a>
<a class="sourceLine" id="cb4-90" title="90"></a>
<a class="sourceLine" id="cb4-91" title="91"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_7_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-92" title="92"> <span class="st">&quot;tFS7INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-93" title="93"> <span class="st">&quot;tFS7INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-94" title="94"> <span class="st">&quot;tFS7INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-95" title="95"> <span class="st">&quot;tFS7INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-96" title="96"> <span class="st">&quot;tFS7INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-97" title="97"> <span class="st">&quot;tFS7INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-98" title="98"> <span class="st">&quot;tFS7INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-99" title="99"> <span class="st">&quot;tFS7INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-100" title="100"> <span class="st">&quot;tFS7INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-101" title="101"> <span class="st">&quot;tFS7INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-102" title="102"> <span class="st">&quot;tFS7INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-103" title="103"> <span class="st">&quot;tFS7INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-104" title="104">];</a>
<a class="sourceLine" id="cb4-105" title="105"></a>
<a class="sourceLine" id="cb4-106" title="106"><span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; FS_8_ADDRESSES = [</a>
<a class="sourceLine" id="cb4-107" title="107"> <span class="st">&quot;tFS8INVALIDADDRESS00&quot;</span>,</a>
<a class="sourceLine" id="cb4-108" title="108"> <span class="st">&quot;tFS8INVALIDADDRESS01&quot;</span>,</a>
<a class="sourceLine" id="cb4-109" title="109"> <span class="st">&quot;tFS8INVALIDADDRESS02&quot;</span>,</a>
<a class="sourceLine" id="cb4-110" title="110"> <span class="st">&quot;tFS8INVALIDADDRESS03&quot;</span>,</a>
<a class="sourceLine" id="cb4-111" title="111"> <span class="st">&quot;tFS8INVALIDADDRESS04&quot;</span>,</a>
<a class="sourceLine" id="cb4-112" title="112"> <span class="st">&quot;tFS8INVALIDADDRESS05&quot;</span>,</a>
<a class="sourceLine" id="cb4-113" title="113"> <span class="st">&quot;tFS8INVALIDADDRESS06&quot;</span>,</a>
<a class="sourceLine" id="cb4-114" title="114"> <span class="st">&quot;tFS8INVALIDADDRESS07&quot;</span>,</a>
<a class="sourceLine" id="cb4-115" title="115"> <span class="st">&quot;tFS8INVALIDADDRESS08&quot;</span>,</a>
<a class="sourceLine" id="cb4-116" title="116"> <span class="st">&quot;tFS8INVALIDADDRESS09&quot;</span>,</a>
<a class="sourceLine" id="cb4-117" title="117"> <span class="st">&quot;tFS8INVALIDADDRESS10&quot;</span>,</a>
<a class="sourceLine" id="cb4-118" title="118"> <span class="st">&quot;tFS8INVALIDADDRESS11&quot;</span>,</a>
<a class="sourceLine" id="cb4-119" title="119">];</a></code></pre></div>
<ul>
<li>To-do: specify the correct sets of FR addresses.</li>
<li>To-do: require that the FR address sets are PGP-signed with appropriate keys.</li>
</ul>
<h2 id="example-implementation">Example implementation</h2>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb5-1" title="1"><span class="kw">struct</span> FundingPeriod {</a>
<a class="sourceLine" id="cb5-2" title="2"> <span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; addresses,</a>
<a class="sourceLine" id="cb5-3" title="3"> <span class="dt">uint64_t</span> valueNumerator,</a>
<a class="sourceLine" id="cb5-4" title="4"> <span class="dt">uint64_t</span> valueDenominator,</a>
<a class="sourceLine" id="cb5-5" title="5"> <span class="dt">int</span> startHeight,</a>
<a class="sourceLine" id="cb5-6" title="6"> <span class="dt">int</span> endHeight,</a>
<a class="sourceLine" id="cb5-7" title="7">};</a>
<a class="sourceLine" id="cb5-8" title="8"></a>
<a class="sourceLine" id="cb5-9" title="9"><span class="kw">enum</span> FundingStream {</a>
<a class="sourceLine" id="cb5-10" title="10"> FS_1,</a>
<a class="sourceLine" id="cb5-11" title="11"> FS_2,</a>
<a class="sourceLine" id="cb5-12" title="12"> FS_3,</a>
<a class="sourceLine" id="cb5-13" title="13"> FS_4,</a>
<a class="sourceLine" id="cb5-14" title="14"> FS_5,</a>
<a class="sourceLine" id="cb5-15" title="15"> FS_6,</a>
<a class="sourceLine" id="cb5-16" title="16"> FS_7,</a>
<a class="sourceLine" id="cb5-17" title="17"> FS_8,</a>
<a class="sourceLine" id="cb5-18" title="18"> MAX_FUNDING_STREAMS,</a>
<a class="sourceLine" id="cb5-19" title="19">};</a>
<a class="sourceLine" id="cb5-20" title="20"></a>
<a class="sourceLine" id="cb5-21" title="21"><span class="kw">struct</span> Params {</a>
<a class="sourceLine" id="cb5-22" title="22"> ...</a>
<a class="sourceLine" id="cb5-23" title="23"> <span class="dt">int</span> nFundingPeriodLength;</a>
<a class="sourceLine" id="cb5-24" title="24"> FundingPeriod vFundingPeriods[MAX_FUNDING_STREAMS];</a>
<a class="sourceLine" id="cb5-25" title="25"> ...</a>
<a class="sourceLine" id="cb5-26" title="26">}</a>
<a class="sourceLine" id="cb5-27" title="27"></a>
<a class="sourceLine" id="cb5-28" title="28"><span class="dt">void</span> AddZIP207FundingStream(</a>
<a class="sourceLine" id="cb5-29" title="29"> Consensus::Params&amp; params,</a>
<a class="sourceLine" id="cb5-30" title="30"> Consensus::FundingStream idx,</a>
<a class="sourceLine" id="cb5-31" title="31"> <span class="bu">std::</span>vector&lt;<span class="bu">std::</span>string&gt; addresses,</a>
<a class="sourceLine" id="cb5-32" title="32"> <span class="dt">uint64_t</span> valueNumerator,</a>
<a class="sourceLine" id="cb5-33" title="33"> <span class="dt">uint64_t</span> valueDenominator)</a>
<a class="sourceLine" id="cb5-34" title="34">{</a>
<a class="sourceLine" id="cb5-35" title="35"> <span class="ot">assert</span>(valueNumerator &lt; valueDenominator);</a>
<a class="sourceLine" id="cb5-36" title="36"> params.vFundingPeriods[idx].addresses = addresses;</a>
<a class="sourceLine" id="cb5-37" title="37"> params.vFundingPeriods[idx].valueNumerator = valueNumerator;</a>
<a class="sourceLine" id="cb5-38" title="38"> params.vFundingPeriods[idx].valueDenominator = valueDenominator;</a>
<a class="sourceLine" id="cb5-39" title="39"> params.vFundingPeriods[idx].startHeight =</a>
<a class="sourceLine" id="cb5-40" title="40"> params.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight;</a>
<a class="sourceLine" id="cb5-41" title="41"> params.vFundingPeriods[idx].endHeight = HeightForHalving(params, <span class="dv">1</span>);</a>
<a class="sourceLine" id="cb5-42" title="42"> <span class="ot">assert</span>(params.vFundingPeriods[idx].startHeight &lt; params.vFundingPeriods[idx].endHeight);</a>
<a class="sourceLine" id="cb5-43" title="43">};</a>
<a class="sourceLine" id="cb5-44" title="44"></a>
<a class="sourceLine" id="cb5-45" title="45">CMainParams() {</a>
<a class="sourceLine" id="cb5-46" title="46"> ...</a>
<a class="sourceLine" id="cb5-47" title="47"></a>
<a class="sourceLine" id="cb5-48" title="48"> consensus.nFundingPeriodLength = consensus.nSubsidyPostBlossomHalvingInterval / <span class="dv">48</span>;</a>
<a class="sourceLine" id="cb5-49" title="49"></a>
<a class="sourceLine" id="cb5-50" title="50"> AddZIP207FundingStream(consensus, Consensus::FS_1, FS_1_ADDRESSES, <span class="dv">3</span>, <span class="dv">40</span>);</a>
<a class="sourceLine" id="cb5-51" title="51"> AddZIP207FundingStream(consensus, Consensus::FS_2, FS_2_ADDRESSES, <span class="dv">1</span>, <span class="dv">25</span>);</a>
<a class="sourceLine" id="cb5-52" title="52"> AddZIP207FundingStream(consensus, Consensus::FS_3, FS_3_ADDRESSES, <span class="dv">1</span>, <span class="dv">40</span>);</a>
<a class="sourceLine" id="cb5-53" title="53"> AddZIP207FundingStream(consensus, Consensus::FS_4, FS_4_ADDRESSES, <span class="dv">1</span>, <span class="dv">50</span>);</a>
<a class="sourceLine" id="cb5-54" title="54"> AddZIP207FundingStream(consensus, Consensus::FS_5, FS_5_ADDRESSES, <span class="dv">1</span>, <span class="dv">80</span>);</a>
<a class="sourceLine" id="cb5-55" title="55"> AddZIP207FundingStream(consensus, Consensus::FS_6, FS_6_ADDRESSES, <span class="dv">1</span>, <span class="dv">80</span>);</a>
<a class="sourceLine" id="cb5-56" title="56"> AddZIP207FundingStream(consensus, Consensus::FS_7, FS_7_ADDRESSES, <span class="dv">1</span>, <span class="dv">100</span>);</a>
<a class="sourceLine" id="cb5-57" title="57"> AddZIP207FundingStream(consensus, Consensus::FS_8, FS_8_ADDRESSES, <span class="dv">1</span>, <span class="dv">200</span>);</a>
<a class="sourceLine" id="cb5-58" title="58"></a>
<a class="sourceLine" id="cb5-59" title="59"> ...</a>
<a class="sourceLine" id="cb5-60" title="60">}</a>
<a class="sourceLine" id="cb5-61" title="61"></a>
<a class="sourceLine" id="cb5-62" title="62">CScript FundingStreamRecipientAddress(</a>
<a class="sourceLine" id="cb5-63" title="63"> <span class="dt">int</span> nHeight,</a>
<a class="sourceLine" id="cb5-64" title="64"> <span class="at">const</span> Consensus::Params&amp; params,</a>
<a class="sourceLine" id="cb5-65" title="65"> Consensus::FundingStream idx)</a>
<a class="sourceLine" id="cb5-66" title="66">{</a>
<a class="sourceLine" id="cb5-67" title="67"> <span class="co">// Integer division is floor division in C++</span></a>
<a class="sourceLine" id="cb5-68" title="68"> <span class="kw">auto</span> curPeriod = (</a>
<a class="sourceLine" id="cb5-69" title="69"> nHeight + params.nSubsidyPostBlossomHalvingInterval - HeightForHalving(params, <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb5-70" title="70"> ) / params.nFundingPeriodLength;</a>
<a class="sourceLine" id="cb5-71" title="71"> <span class="kw">auto</span> startPeriod = (</a>
<a class="sourceLine" id="cb5-72" title="72"> params.vFundingPeriods[idx].startHeight</a>
<a class="sourceLine" id="cb5-73" title="73"> + params.nSubsidyPostBlossomHalvingInterval</a>
<a class="sourceLine" id="cb5-74" title="74"> - HeightForHalving(params, <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb5-75" title="75"> ) / params.nFundingPeriodLength;</a>
<a class="sourceLine" id="cb5-76" title="76"> <span class="kw">auto</span> addressIndex = curPeriod - startPeriod;</a>
<a class="sourceLine" id="cb5-77" title="77"> <span class="cf">return</span> params.vFundingPeriods[idx].addresses[addressIndex];</a>
<a class="sourceLine" id="cb5-78" title="78">};</a>
<a class="sourceLine" id="cb5-79" title="79"></a>
<a class="sourceLine" id="cb5-80" title="80">CAmount FundingStreamValue(</a>
<a class="sourceLine" id="cb5-81" title="81"> <span class="dt">int</span> nHeight,</a>
<a class="sourceLine" id="cb5-82" title="82"> <span class="at">const</span> Consensus::Params&amp; params,</a>
<a class="sourceLine" id="cb5-83" title="83"> Consensus::FundingStream idx)</a>
<a class="sourceLine" id="cb5-84" title="84">{</a>
<a class="sourceLine" id="cb5-85" title="85"> <span class="co">// Integer division is floor division in C++</span></a>
<a class="sourceLine" id="cb5-86" title="86"> <span class="cf">return</span> CAmount((</a>
<a class="sourceLine" id="cb5-87" title="87"> GetBlockSubsidy(nHeight, params) * params.vFundingPeriods[idx].valueNumerator</a>
<a class="sourceLine" id="cb5-88" title="88"> ) / params.vFundingPeriods[idx].valueDenominator);</a>
<a class="sourceLine" id="cb5-89" title="89">}</a>
<a class="sourceLine" id="cb5-90" title="90"></a>
<a class="sourceLine" id="cb5-91" title="91"><span class="bu">std::</span>set&lt;<span class="bu">std::</span>pair&lt;CScript, CAmount&gt;&gt; GetActiveFundingStreams(</a>
<a class="sourceLine" id="cb5-92" title="92"> <span class="dt">int</span> nHeight,</a>
<a class="sourceLine" id="cb5-93" title="93"> <span class="at">const</span> Consensus::Params&amp; params)</a>
<a class="sourceLine" id="cb5-94" title="94">{</a>
<a class="sourceLine" id="cb5-95" title="95"> <span class="bu">std::</span>set&lt;<span class="bu">std::</span>pair&lt;CScript, CAmount&gt;&gt; requiredStreams;</a>
<a class="sourceLine" id="cb5-96" title="96"> <span class="cf">for</span> (<span class="dt">int</span> idx = Consensus::FS_ZECC_EF; idx &lt; Consensus::MAX_FUNDING_STREAMS; idx++) {</a>
<a class="sourceLine" id="cb5-97" title="97"> <span class="co">// Funding period is [startHeight, endHeight)</span></a>
<a class="sourceLine" id="cb5-98" title="98"> <span class="cf">if</span> (nHeight &gt;= params.vFundingPeriods[idx].startHeight &amp;&amp;</a>
<a class="sourceLine" id="cb5-99" title="99"> nHeight &lt; params.vFundingPeriods[idx].endHeight)</a>
<a class="sourceLine" id="cb5-100" title="100"> {</a>
<a class="sourceLine" id="cb5-101" title="101"> requiredStreams.insert(<span class="bu">std::</span>make_pair(</a>
<a class="sourceLine" id="cb5-102" title="102"> FundingStreamRecipientAddress(nHeight, params, idx),</a>
<a class="sourceLine" id="cb5-103" title="103"> FundingStreamValue(nHeight, params, idx));</a>
<a class="sourceLine" id="cb5-104" title="104"> }</a>
<a class="sourceLine" id="cb5-105" title="105"> }</a>
<a class="sourceLine" id="cb5-106" title="106"> <span class="cf">return</span> requiredStreams;</a>
<a class="sourceLine" id="cb5-107" title="107">};</a>
<a class="sourceLine" id="cb5-108" title="108"></a>
<a class="sourceLine" id="cb5-109" title="109"><span class="dt">bool</span> ContextualCheckBlock(...)</a>
<a class="sourceLine" id="cb5-110" title="110">{</a>
<a class="sourceLine" id="cb5-111" title="111"> ...</a>
<a class="sourceLine" id="cb5-112" title="112"></a>
<a class="sourceLine" id="cb5-113" title="113"> <span class="cf">if</span> (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_BLOSSOM)) {</a>
<a class="sourceLine" id="cb5-114" title="114"> <span class="co">// Coinbase transaction must include outputs corresponding to the consensus</span></a>
<a class="sourceLine" id="cb5-115" title="115"> <span class="co">// funding streams active at the current block height.</span></a>
<a class="sourceLine" id="cb5-116" title="116"> <span class="kw">auto</span> requiredStreams = GetActiveFundingStreams(nHeight, consensusParams);</a>
<a class="sourceLine" id="cb5-117" title="117"></a>
<a class="sourceLine" id="cb5-118" title="118"> <span class="cf">for</span> (<span class="at">const</span> CTxOut&amp; output : block.vtx[<span class="dv">0</span>].vout) {</a>
<a class="sourceLine" id="cb5-119" title="119"> <span class="cf">for</span> (<span class="kw">auto</span> it = requiredStreams.begin(); it != requiredStreams.end(); ++it) {</a>
<a class="sourceLine" id="cb5-120" title="120"> <span class="cf">if</span> (output.scriptPubKey == it-&gt;first &amp;&amp; output.nValue == it-&gt;second) {</a>
<a class="sourceLine" id="cb5-121" title="121"> requiredStreams.erase(it);</a>
<a class="sourceLine" id="cb5-122" title="122"> <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb5-123" title="123"> }</a>
<a class="sourceLine" id="cb5-124" title="124"> }</a>
<a class="sourceLine" id="cb5-125" title="125"> }</a>
<a class="sourceLine" id="cb5-126" title="126"></a>
<a class="sourceLine" id="cb5-127" title="127"> <span class="cf">if</span> (!requiredStreams.empty()) {</a>
<a class="sourceLine" id="cb5-128" title="128"> <span class="cf">return</span> state.DoS(<span class="dv">100</span>, error(<span class="st">&quot;</span><span class="sc">%s</span><span class="st">: funding stream missing&quot;</span>, <span class="ot">__func__</span>), REJECT_INVALID, <span class="st">&quot;cb-funding-stream-missing&quot;</span>);</a>
<a class="sourceLine" id="cb5-129" title="129"> }</a>
<a class="sourceLine" id="cb5-130" title="130"> } <span class="cf">else</span> {</a>
<a class="sourceLine" id="cb5-131" title="131"> <span class="co">// Coinbase transaction must include an output sending 20% of</span></a>
<a class="sourceLine" id="cb5-132" title="132"> <span class="co">// the block reward to a founders reward script, until the last founders</span></a>
<a class="sourceLine" id="cb5-133" title="133"> <span class="co">// reward block is reached, with exception of the genesis block.</span></a>
<a class="sourceLine" id="cb5-134" title="134"> <span class="co">// The last founders reward block is defined as the block just before the</span></a>
<a class="sourceLine" id="cb5-135" title="135"> <span class="co">// first subsidy halving block, which occurs at halving_interval + slow_start_shift</span></a>
<a class="sourceLine" id="cb5-136" title="136"> <span class="cf">if</span> ((nHeight &gt; <span class="dv">0</span>) &amp;&amp; (nHeight &lt;= consensusParams.GetLastFoundersRewardBlockHeight())) {</a>
<a class="sourceLine" id="cb5-137" title="137"> <span class="dt">bool</span> found = <span class="kw">false</span>;</a>
<a class="sourceLine" id="cb5-138" title="138"></a>
<a class="sourceLine" id="cb5-139" title="139"> <span class="cf">for</span> (<span class="at">const</span> CTxOut&amp; output : block.vtx[<span class="dv">0</span>].vout) {</a>
<a class="sourceLine" id="cb5-140" title="140"> <span class="cf">if</span> (output.scriptPubKey == Params().GetFoundersRewardScriptAtHeight(nHeight)) {</a>
<a class="sourceLine" id="cb5-141" title="141"> <span class="cf">if</span> (output.nValue == (GetBlockSubsidy(nHeight, consensusParams) / <span class="dv">5</span>)) {</a>
<a class="sourceLine" id="cb5-142" title="142"> found = <span class="kw">true</span>;</a>
<a class="sourceLine" id="cb5-143" title="143"> <span class="cf">break</span>;</a>
<a class="sourceLine" id="cb5-144" title="144"> }</a>
<a class="sourceLine" id="cb5-145" title="145"> }</a>
<a class="sourceLine" id="cb5-146" title="146"> }</a>
<a class="sourceLine" id="cb5-147" title="147"></a>
<a class="sourceLine" id="cb5-148" title="148"> <span class="cf">if</span> (!found) {</a>
<a class="sourceLine" id="cb5-149" title="149"> <span class="cf">return</span> state.DoS(<span class="dv">100</span>, error(<span class="st">&quot;</span><span class="sc">%s</span><span class="st">: founders reward missing&quot;</span>, <span class="ot">__func__</span>), REJECT_INVALID, <span class="st">&quot;cb-no-founders-reward&quot;</span>);</a>
<a class="sourceLine" id="cb5-150" title="150"> }</a>
<a class="sourceLine" id="cb5-151" title="151"> }</a>
<a class="sourceLine" id="cb5-152" title="152"> }</a>
<a class="sourceLine" id="cb5-153" title="153"></a>
<a class="sourceLine" id="cb5-154" title="154"> ...</a>
<a class="sourceLine" id="cb5-155" title="155">}</a></code></pre></div>
<h1 id="deployment">Deployment</h1>
<p>This proposal was originally intended to be deployed with the Blossom network upgrade.<a href="#fn11" class="footnote-ref" id="fnref11"><sup>11</sup></a></p>
<h1 id="backward-compatibility">Backward compatibility</h1>
<p>This proposal intentionally creates what is known as a &quot;bilateral consensus rule change&quot;. Use of this mechanism requires that all network participants upgrade their software to a compatible version within the upgrade window. Older software will treat post-upgrade blocks as invalid, and will follow any pre-upgrade branch that persists.</p>
<p>This proposal is designed with the explicit requirement of not altering the overall issuance schedule (based on time), nor does it alter the proportion or timeline of the overall Founders' Reward. As a result, no users outside of the Zerocoin Electric Coin Company and Zcash Foundation should experience any UX or economic change outside of the upgrade due to this proposal itself.</p>
<h2 id="interactions-with-other-zips">Interactions with other ZIPs</h2>
<p><a href="#fn12" class="footnote-ref" id="fnref12"><sup>12</sup></a> (Shorter Block Target Spacing) specifies a change to the block target spacing. It is planned to take effect in the Blossom network upgrade<a href="#fn13" class="footnote-ref" id="fnref13"><sup>13</sup></a>. This ZIP was originally written to take effect at the same time, but was Withdrawn from consideration for Blossom.</p>
<p>ZIP 208 modifies the payment of the original Founders' Reward to take account of the block target spacing change. It does this by specifying a FounderAddressAdjustedHeight function and related changes, which would need to be revisited to take into account funding streams.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p>TBC</p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.7: Calculation of Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://electriccoin.co/blog/continued-funding-and-transparency/">Continued Funding and Transparency</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0208.rst">ZIP 208: Shorter Block Target Spacing</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.7: Calculation of Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref5" class="footnote-back"></a></p></li>
<li id="fn6"><p><a href="https://github.com/zcash/zips/blob/master/zip-0208.rst">ZIP 208: Shorter Block Target Spacing</a><a href="#fnref6" class="footnote-back"></a></p></li>
<li id="fn7"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref7" class="footnote-back"></a></p></li>
<li id="fn8"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref8" class="footnote-back"></a></p></li>
<li id="fn9"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref9" class="footnote-back"></a></p></li>
<li id="fn10"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 5.3: Constants. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a><a href="#fnref10" class="footnote-back"></a></p></li>
<li id="fn11"><p><a href="https://github.com/zcash/zips/blob/master/zip-0206.rst">ZIP 206: Blossom Network Upgrade</a><a href="#fnref11" class="footnote-back"></a></p></li>
<li id="fn12"><p><a href="https://github.com/zcash/zips/blob/master/zip-0208.rst">ZIP 208: Shorter Block Target Spacing</a><a href="#fnref12" class="footnote-back"></a></p></li>
<li id="fn13"><p><a href="https://github.com/zcash/zips/blob/master/zip-0206.rst">ZIP 206: Blossom Network Upgrade</a><a href="#fnref13" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,590 +0,0 @@
ZIP: 207
Title: Split Founders' Reward
Owners: Jack Grigg <str4d@electriccoin.co>
Category: Consensus
Status: Withdrawn
Created: 2019-01-04
License: MIT
Terminology
===========
The key words \"MUST\", \"SHOULD\", \"SHOULD NOT\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
Abstract
========
This Withdrawn proposal would have altered consensus rules to split the
original Founders\' Reward across several recipient addresses per block
instead of one, corresponding to the several funding streams contained
within it.
Motivation
==========
Since the launch of the Zcash network, the consensus rules have required
that until the first block reward halving (at block 850,000), each block
must send 20% of the block subsidy to a hard-coded transparent address.
[^2] This funding stream is referred to as the Founders\' Reward.
This stream of 2.5-ZEC outputs (the value after the mining slow-start
was completed) can be split into several logical funding streams (for
background, see[^3]). Modifying the consensus rules to allocate the 2.5
ZEC across separate recipient addresses decouples these funding streams
organizationally, legally, and operationally. It further reinforces
transparency as to the structure of the original Founders\' Reward.
Specification
=============
Definitions
-----------
We use the following constants and functions defined in[^4]:
- `BlossomActivationHeight`
- `PostBlossomHalvingInterval`
- `Halving(height)`
We also define the following constants and functions:
- `SlowStartShift` as-defined in[^5].
- `HeightForHalving(halving)`: Smallest `height` such that
`Halving(height) = halving`
Funding streams
---------------
A funding stream is defined by a block reward fraction (represented as a
numerator and a denominator), a start height (inclusive), and an end
height (exclusive).
By defining the issuance as a proportion of the total block issuance,
rather than absolute zatoshis, this ZIP dovetails with any changes to
both block target times and issuance-per-block rates while maintaining
an unchanged target-time-based issuance schedule. We anticipate such
target-time / issuance rate changes in other ZIPs (for example,[^6]).
The value of a funding stream at a given block height is defined as:
FundingStream[FUND].Value(height) =
floor((
BlockReward(height) * FundingStream[FUND].ValueNumerator
) / FundingStream[FUND].ValueDenominator)
An active funding stream at a given block height is defined as a funding
stream for which the block height is less than its end height, but not
less than its start height.
Each funding stream has an associated set of recipient addresses. Each
address is used for at most 1/48th of a halving interval, creating a
roughly-monthly sequence of funding periods. The address to be used for
a given block height is defined as follows:
AddressChangeInterval = PostBlossomHalvingInterval / 48
AddressPeriod(height) =
floor((
height + PostBlossomHalvingInterval - HeightForHalving(1)
) / AddressChangeInterval)
FundingStream[FUND].AddressIndex(height) =
AddressPeriod(height) - AddressPeriod(FundingStream[FUND].StartHeight)
Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex(height)]
This has the property that all active funding streams change the address
they are using on the same block height schedule, aligned to the height
of the first halving so that 48 funding periods fit cleanly within a
halving interval. This can be leveraged to simplify implementations, by
batching the necessary outputs for each funding period.
Below is a visual representation of how stream addresses align with
funding periods:
+-----------------+-----------------+-----------------+-----------------+
| Example height | Stream A | Stream B | Stream C |
+=================+=================+=================+=================+
| > `AddressChang | > A0 A0 | | |
| eInterval - 2` | | | |
| > `AddressChang | | | |
| eInterval - 1` | | | |
+-----------------+-----------------+-----------------+-----------------+
| > `AddressChang | > A1 | > B0 | > C0 |
| eInterval` | | | |
+-----------------+-----------------+-----------------+-----------------+
| > `AddressChang | > A1 | > B0 | > C0 |
| eInterval + 1` | | | |
| > | | | |
| > : \... | | | |
+-----------------+-----------------+-----------------+-----------------+
| > `2*AddressCha | > A1 | > B0 | > C0 |
| ngeInterval - 2 | | | |
| ` | | | |
+-----------------+-----------------+-----------------+-----------------+
| > `2*AddressCha | > A1 A2 A2 | > B0 | > C0 C1 C1 |
| ngeInterval - 1 | > | | > |
| ` | > A2 A2 | | > C1 C1 C2 C2 |
| > `2*AddressCha | | | |
| ngeInterval` | | | |
| > `2*AddressCha | | | |
| ngeInterval + 1 | | | |
| ` | | | |
| > \... | | | |
| | | | |
| `PostBlossomHal | | | |
| vingInterval - | | | |
| 2` | | | |
| `PostBlossomHal | | | |
| vingInterval - | | | |
| 1` | | | |
| `PostBlossomHal | | | |
| vingInterval` | | | |
| `PostBlossomHal | | | |
| vingInterval + | | | |
| 1` | | | |
+-----------------+-----------------+-----------------+-----------------+
Note that this is not intended to align with the end of a pre-Blossom
Founders\' Reward address period (as defined by
`FounderAddressChangeInterval` in[^7]). There will be a shortened
Founders\' Reward address period prior to Blossom activation.
Consensus rules
---------------
Prior to activation of the Blossom network upgrade, the existing
consensus rule for payment of the original Founders\' Reward is
enforced.[^8]
Once the Blossom network upgrade activates:
- The existing consensus rule[^9] is no longer active.
- The coinbase transaction in each block MUST contain at least one
output per active funding stream that pays the stream\'s value to
the stream\'s recipient address for the block\'s height.
Stream definitions
------------------
The consensus-defined funding streams described above each start at the
Blossom activation height, and end at the first block reward halving.
They are defined as follows:
+-------------+-------------+-------------+-------------+-------------+
| Stream | Value | Value | Start | End height |
| | numerator | denominator | height | |
+=============+=============+=============+=============+=============+
| > FS 1 | > 3 | > 40 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 2 | > 1 | > 25 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 3 | > 1 | > 40 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 4 | > 1 | > 50 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 5 | > 1 | > 80 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 6 | > 1 | > 80 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 7 | > 1 | > 100 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
| > FS 8 | > 1 | > 200 | `BlossomAct | `HeightForH |
| | | | ivationHeig | alving(1)` |
| | | | ht` | |
+-------------+-------------+-------------+-------------+-------------+
- To-do: specify the correct values.
The sum of the block reward fractions for the above funding streams is
`1/5`, equal to the original Founders\' Reward (as-defined by
`FoundersFraction` in[^10]).
The sets of recipient addresses are defined as follows:
``` {.sourceCode .cpp}
std::vector<std::string> FS_1_ADDRESSES = [
"tFS1INVALIDADDRESS00",
"tFS1INVALIDADDRESS01",
"tFS1INVALIDADDRESS02",
"tFS1INVALIDADDRESS03",
"tFS1INVALIDADDRESS04",
"tFS1INVALIDADDRESS05",
"tFS1INVALIDADDRESS06",
"tFS1INVALIDADDRESS07",
"tFS1INVALIDADDRESS08",
"tFS1INVALIDADDRESS09",
"tFS1INVALIDADDRESS10",
"tFS1INVALIDADDRESS11",
];
std::vector<std::string> FS_2_ADDRESSES = [
"tFS2INVALIDADDRESS00",
"tFS2INVALIDADDRESS01",
"tFS2INVALIDADDRESS02",
"tFS2INVALIDADDRESS03",
"tFS2INVALIDADDRESS04",
"tFS2INVALIDADDRESS05",
"tFS2INVALIDADDRESS06",
"tFS2INVALIDADDRESS07",
"tFS2INVALIDADDRESS08",
"tFS2INVALIDADDRESS09",
"tFS2INVALIDADDRESS10",
"tFS2INVALIDADDRESS11",
];
std::vector<std::string> FS_3_ADDRESSES = [
"tFS3INVALIDADDRESS00",
"tFS3INVALIDADDRESS01",
"tFS3INVALIDADDRESS02",
"tFS3INVALIDADDRESS03",
"tFS3INVALIDADDRESS04",
"tFS3INVALIDADDRESS05",
"tFS3INVALIDADDRESS06",
"tFS3INVALIDADDRESS07",
"tFS3INVALIDADDRESS08",
"tFS3INVALIDADDRESS09",
"tFS3INVALIDADDRESS10",
"tFS3INVALIDADDRESS11",
];
std::vector<std::string> FS_4_ADDRESSES = [
"tFS4INVALIDADDRESS00",
"tFS4INVALIDADDRESS01",
"tFS4INVALIDADDRESS02",
"tFS4INVALIDADDRESS03",
"tFS4INVALIDADDRESS04",
"tFS4INVALIDADDRESS05",
"tFS4INVALIDADDRESS06",
"tFS4INVALIDADDRESS07",
"tFS4INVALIDADDRESS08",
"tFS4INVALIDADDRESS09",
"tFS4INVALIDADDRESS10",
"tFS4INVALIDADDRESS11",
];
std::vector<std::string> FS_5_ADDRESSES = [
"tFS5INVALIDADDRESS00",
"tFS5INVALIDADDRESS01",
"tFS5INVALIDADDRESS02",
"tFS5INVALIDADDRESS03",
"tFS5INVALIDADDRESS04",
"tFS5INVALIDADDRESS05",
"tFS5INVALIDADDRESS06",
"tFS5INVALIDADDRESS07",
"tFS5INVALIDADDRESS08",
"tFS5INVALIDADDRESS09",
"tFS5INVALIDADDRESS10",
"tFS5INVALIDADDRESS11",
];
std::vector<std::string> FS_6_ADDRESSES = [
"tFS6INVALIDADDRESS00",
"tFS6INVALIDADDRESS01",
"tFS6INVALIDADDRESS02",
"tFS6INVALIDADDRESS03",
"tFS6INVALIDADDRESS04",
"tFS6INVALIDADDRESS05",
"tFS6INVALIDADDRESS06",
"tFS6INVALIDADDRESS07",
"tFS6INVALIDADDRESS08",
"tFS6INVALIDADDRESS09",
"tFS6INVALIDADDRESS10",
"tFS6INVALIDADDRESS11",
];
std::vector<std::string> FS_7_ADDRESSES = [
"tFS7INVALIDADDRESS00",
"tFS7INVALIDADDRESS01",
"tFS7INVALIDADDRESS02",
"tFS7INVALIDADDRESS03",
"tFS7INVALIDADDRESS04",
"tFS7INVALIDADDRESS05",
"tFS7INVALIDADDRESS06",
"tFS7INVALIDADDRESS07",
"tFS7INVALIDADDRESS08",
"tFS7INVALIDADDRESS09",
"tFS7INVALIDADDRESS10",
"tFS7INVALIDADDRESS11",
];
std::vector<std::string> FS_8_ADDRESSES = [
"tFS8INVALIDADDRESS00",
"tFS8INVALIDADDRESS01",
"tFS8INVALIDADDRESS02",
"tFS8INVALIDADDRESS03",
"tFS8INVALIDADDRESS04",
"tFS8INVALIDADDRESS05",
"tFS8INVALIDADDRESS06",
"tFS8INVALIDADDRESS07",
"tFS8INVALIDADDRESS08",
"tFS8INVALIDADDRESS09",
"tFS8INVALIDADDRESS10",
"tFS8INVALIDADDRESS11",
];
```
- To-do: specify the correct sets of FR addresses.
- To-do: require that the FR address sets are PGP-signed with
appropriate keys.
Example implementation
----------------------
``` {.sourceCode .cpp}
struct FundingPeriod {
std::vector<std::string> addresses,
uint64_t valueNumerator,
uint64_t valueDenominator,
int startHeight,
int endHeight,
};
enum FundingStream {
FS_1,
FS_2,
FS_3,
FS_4,
FS_5,
FS_6,
FS_7,
FS_8,
MAX_FUNDING_STREAMS,
};
struct Params {
...
int nFundingPeriodLength;
FundingPeriod vFundingPeriods[MAX_FUNDING_STREAMS];
...
}
void AddZIP207FundingStream(
Consensus::Params& params,
Consensus::FundingStream idx,
std::vector<std::string> addresses,
uint64_t valueNumerator,
uint64_t valueDenominator)
{
assert(valueNumerator < valueDenominator);
params.vFundingPeriods[idx].addresses = addresses;
params.vFundingPeriods[idx].valueNumerator = valueNumerator;
params.vFundingPeriods[idx].valueDenominator = valueDenominator;
params.vFundingPeriods[idx].startHeight =
params.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight;
params.vFundingPeriods[idx].endHeight = HeightForHalving(params, 1);
assert(params.vFundingPeriods[idx].startHeight < params.vFundingPeriods[idx].endHeight);
};
CMainParams() {
...
consensus.nFundingPeriodLength = consensus.nSubsidyPostBlossomHalvingInterval / 48;
AddZIP207FundingStream(consensus, Consensus::FS_1, FS_1_ADDRESSES, 3, 40);
AddZIP207FundingStream(consensus, Consensus::FS_2, FS_2_ADDRESSES, 1, 25);
AddZIP207FundingStream(consensus, Consensus::FS_3, FS_3_ADDRESSES, 1, 40);
AddZIP207FundingStream(consensus, Consensus::FS_4, FS_4_ADDRESSES, 1, 50);
AddZIP207FundingStream(consensus, Consensus::FS_5, FS_5_ADDRESSES, 1, 80);
AddZIP207FundingStream(consensus, Consensus::FS_6, FS_6_ADDRESSES, 1, 80);
AddZIP207FundingStream(consensus, Consensus::FS_7, FS_7_ADDRESSES, 1, 100);
AddZIP207FundingStream(consensus, Consensus::FS_8, FS_8_ADDRESSES, 1, 200);
...
}
CScript FundingStreamRecipientAddress(
int nHeight,
const Consensus::Params& params,
Consensus::FundingStream idx)
{
// Integer division is floor division in C++
auto curPeriod = (
nHeight + params.nSubsidyPostBlossomHalvingInterval - HeightForHalving(params, 1)
) / params.nFundingPeriodLength;
auto startPeriod = (
params.vFundingPeriods[idx].startHeight
+ params.nSubsidyPostBlossomHalvingInterval
- HeightForHalving(params, 1)
) / params.nFundingPeriodLength;
auto addressIndex = curPeriod - startPeriod;
return params.vFundingPeriods[idx].addresses[addressIndex];
};
CAmount FundingStreamValue(
int nHeight,
const Consensus::Params& params,
Consensus::FundingStream idx)
{
// Integer division is floor division in C++
return CAmount((
GetBlockSubsidy(nHeight, params) * params.vFundingPeriods[idx].valueNumerator
) / params.vFundingPeriods[idx].valueDenominator);
}
std::set<std::pair<CScript, CAmount>> GetActiveFundingStreams(
int nHeight,
const Consensus::Params& params)
{
std::set<std::pair<CScript, CAmount>> requiredStreams;
for (int idx = Consensus::FS_ZECC_EF; idx < Consensus::MAX_FUNDING_STREAMS; idx++) {
// Funding period is [startHeight, endHeight)
if (nHeight >= params.vFundingPeriods[idx].startHeight &&
nHeight < params.vFundingPeriods[idx].endHeight)
{
requiredStreams.insert(std::make_pair(
FundingStreamRecipientAddress(nHeight, params, idx),
FundingStreamValue(nHeight, params, idx));
}
}
return requiredStreams;
};
bool ContextualCheckBlock(...)
{
...
if (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_BLOSSOM)) {
// Coinbase transaction must include outputs corresponding to the consensus
// funding streams active at the current block height.
auto requiredStreams = GetActiveFundingStreams(nHeight, consensusParams);
for (const CTxOut& output : block.vtx[0].vout) {
for (auto it = requiredStreams.begin(); it != requiredStreams.end(); ++it) {
if (output.scriptPubKey == it->first && output.nValue == it->second) {
requiredStreams.erase(it);
break;
}
}
}
if (!requiredStreams.empty()) {
return state.DoS(100, error("%s: funding stream missing", __func__), REJECT_INVALID, "cb-funding-stream-missing");
}
} else {
// Coinbase transaction must include an output sending 20% of
// the block reward to a founders reward script, until the last founders
// reward block is reached, with exception of the genesis block.
// The last founders reward block is defined as the block just before the
// first subsidy halving block, which occurs at halving_interval + slow_start_shift
if ((nHeight > 0) && (nHeight <= consensusParams.GetLastFoundersRewardBlockHeight())) {
bool found = false;
for (const CTxOut& output : block.vtx[0].vout) {
if (output.scriptPubKey == Params().GetFoundersRewardScriptAtHeight(nHeight)) {
if (output.nValue == (GetBlockSubsidy(nHeight, consensusParams) / 5)) {
found = true;
break;
}
}
}
if (!found) {
return state.DoS(100, error("%s: founders reward missing", __func__), REJECT_INVALID, "cb-no-founders-reward");
}
}
}
...
}
```
Deployment
==========
This proposal was originally intended to be deployed with the Blossom
network upgrade.[^11]
Backward compatibility
======================
This proposal intentionally creates what is known as a \"bilateral
consensus rule change\". Use of this mechanism requires that all network
participants upgrade their software to a compatible version within the
upgrade window. Older software will treat post-upgrade blocks as
invalid, and will follow any pre-upgrade branch that persists.
This proposal is designed with the explicit requirement of not altering
the overall issuance schedule (based on time), nor does it alter the
proportion or timeline of the overall Founders\' Reward. As a result, no
users outside of the Zerocoin Electric Coin Company and Zcash Foundation
should experience any UX or economic change outside of the upgrade due
to this proposal itself.
Interactions with other ZIPs
----------------------------
[^12] (Shorter Block Target Spacing) specifies a change to the block
target spacing. It is planned to take effect in the Blossom network
upgrade[^13]. This ZIP was originally written to take effect at the same
time, but was Withdrawn from consideration for Blossom.
ZIP 208 modifies the payment of the original Founders\' Reward to take
account of the block target spacing change. It does this by specifying a
FounderAddressAdjustedHeight function and related changes, which would
need to be revisited to take into account funding streams.
Reference Implementation
========================
TBC
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [Section 7.7: Calculation of Block Subsidy and Founders\' Reward.
Zcash Protocol Specification, Version 2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^3]: [Continued Funding and
Transparency](https://electriccoin.co/blog/continued-funding-and-transparency/)
[^4]: [ZIP 208: Shorter Block Target
Spacing](https://github.com/zcash/zips/blob/master/zip-0208.rst)
[^5]: [Section 7.7: Calculation of Block Subsidy and Founders\' Reward.
Zcash Protocol Specification, Version 2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^6]: [ZIP 208: Shorter Block Target
Spacing](https://github.com/zcash/zips/blob/master/zip-0208.rst)
[^7]: [Section 7.8: Payment of Founders\' Reward. Zcash Protocol
Specification, Version 2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^8]: [Section 7.8: Payment of Founders\' Reward. Zcash Protocol
Specification, Version 2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^9]: [Section 7.8: Payment of Founders\' Reward. Zcash Protocol
Specification, Version 2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^10]: [Section 5.3: Constants. Zcash Protocol Specification, Version
2018.0-beta-33 or later
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^11]: [ZIP 206: Blossom Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0206.rst)
[^12]: [ZIP 208: Shorter Block Target
Spacing](https://github.com/zcash/zips/blob/master/zip-0208.rst)
[^13]: [ZIP 206: Blossom Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0206.rst)

270
zip-0208.html Normal file
View File

@ -0,0 +1,270 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<pre>ZIP: 208
Title: Shorter Block Target Spacing
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Original-Authors: Daira Hopwood &lt;daira@electriccoin.co&gt;
Simon Liu &lt;simon@bitcartel.com&gt;
Status: Implemented
Category: Consensus
Created: 2019-01-10
License: MIT</pre>
<section id="terminology">
<h1>Terminology</h1>
<p>The key words "MUST", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. <a href="#rfc2119" id="id1" class="footnote_reference">3</a></p>
<p>The terms "block chain", "consensus rule change", "branch", and "network upgrade" are to be interpreted as defined in <a href="#zip-0200" id="id2" class="footnote_reference">4</a>.</p>
<p>The term "block target spacing" means the time interval between blocks targeted by the difficulty adjustment algorithm in a given branch. It is normally measured in seconds. (This is also sometimes called the "target block time", but "block target spacing" is the term used in <a href="#latest-protocol" id="id3" class="footnote_reference">1</a>.)</p>
</section>
<section id="abstract">
<h1>Abstract</h1>
<p>This proposal specifies a change in the block target spacing, to take effect in the Blossom network upgrade <a href="#zip-0206" id="id4" class="footnote_reference">6</a>.</p>
<p>The emission schedule of mined ZEC will be approximately the same in terms of time, but this requires the emission per block to be adjusted to take account of the changed block target spacing.</p>
</section>
<section id="motivation">
<h1>Motivation</h1>
<p>The motivations for decreasing the block target spacing are:</p>
<ul>
<li>Reduced latency for considering transactions to be sufficiently confirmed;</li>
<li>Greater throughput of transactions in unit time.</li>
</ul>
<p>The latter goal could alternatively be achieved by increasing the block size limit, but that would not also achieve the former goal.</p>
<p>Note that, for a given security requirement (in terms of the expected cost distribution of a rollback attack), the number of confirmations needed increases more slowly than the decrease in block time, and so, up to a point, decreasing the block target spacing can provide a better trade-off between latency and security. This argument assumes that the verification and propagation time for a block remain small compared to the block target spacing. See <a href="#slowfastblocks" id="id5" class="footnote_reference">7</a> for further analysis in various attack models.</p>
</section>
<section id="specification">
<h1>Specification</h1>
<p>The changes described in this section are to be made in <a href="#latest-protocol" id="id6" class="footnote_reference">1</a>, relative to the pre-Blossom specification in [#preblossom-protocol].</p>
<section id="consensus-changes">
<h2>Consensus changes</h2>
<p>Throughout the specification, rename HalvingInterval to PreBlossomHalvingInterval, and rename PoWTargetSpacing to PreBlossomTargetSpacing. These constants retain their values from <a href="#preblossom-protocol" id="id7" class="footnote_reference">2</a> of 840000 (blocks) and 150 (seconds) respectively.</p>
<p>In section 2 (Notation), add BlossomActivationHeight and PostBlossomPoWTargetSpacing to the list of integer constants.</p>
<p>In section 5.3 (Constants), define PostBlossomPoWTargetSpacing := 75 seconds.</p>
<p>For a given network (production or test), define BlossomActivationHeight as the height at which Blossom activates on that network, as specified in <a href="#zip-0206" id="id8" class="footnote_reference">6</a>.</p>
<p>In section 7.6.3 (Difficulty adjustment), make the following changes:</p>
<p>Define IsBlossomActivated(<em>height</em>) to return true if <em>height</em> ≥ BlossomActivationHeight, otherwise false.</p>
<p>This specification assumes that BlossomActivationHeight ≥ SlowStartInterval.</p>
<p>Define:</p>
<ul>
<li>BlossomPoWTargetSpacingRatio := PreBlossomPoWTargetSpacing / PostBlossomPoWTargetSpacing</li>
<li>PostBlossomHalvingInterval := floor(PreBlossomHalvingInterval · BlossomPoWTargetSpacingRatio).</li>
</ul>
<p>In the same section, redefine PoWTargetSpacing as a function taking a <em>height</em> parameter, as follows:</p>
<ul>
<li>PoWTargetSpacing(<em>height</em>) :=
<ul>
<li>PreBlossomPoWTargetSpacing, if not IsBlossomActivated(<em>height</em>)</li>
<li>PostBlossomPoWTargetSpacing, otherwise.</li>
</ul>
</li>
</ul>
<p>Also redefine AveragingWindowTimespan, MinActualTimespan, MaxActualTimespan, ActualTimespanDamped, ActualTimespanBounded, and Threshold as follows:</p>
<ul>
<li>add a <em>height</em> parameter to each of these functions that does not already have one;</li>
<li>ensure that each reference to any of these values, or to PoWTargetSpacing, are replaced with a function call passing the <em>height</em> parameter.</li>
</ul>
<p>In <a href="#latest-protocol" id="id9" class="footnote_reference">1</a> section 7.7 (Calculation of Block Subsidy and Founders Reward), redefine the Halving and BlockSubsidy functions as follows:</p>
<ul>
<li>Halving(<em>height</em>) :=
<ul>
<li>floor((<em>height</em> - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(<em>height</em>)</li>
<li>floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (<em>height</em> - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise</li>
</ul>
</li>
<li>BlockSubsidy(<em>height</em>) :=
<ul>
<li>SlowStartRate · <em>height</em>, if <em>height</em> &lt; SlowStartInterval / 2</li>
<li>SlowStartRate · (<em>height</em> + 1), if SlowStartInterval / 2 ≤ <em>height</em> and <em>height</em> &lt; SlowStartInterval</li>
<li>floor(MaxBlockSubsidy / 2<sup>Halving(*height*)</sup>), if SlowStartInterval ≤ <em>height</em> and not IsBlossomActivated(<em>height</em>)</li>
<li>floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2<sup>Halving(*height*)</sup>)), otherwise</li>
</ul>
</li>
</ul>
<p>TODO: ideally, BlossomActivationHeight, PostBlossomHalvingInterval, and PostBlossomTargetSpacing should be chosen so that:</p>
<ul>
<li>(BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (<em>height</em> - BlossomActivationHeight) / PostBlossomHalvingInterval) is exactly 1 for some integer <em>height</em>.</li>
<li>MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2<sup>Halving(*height*)</sup>) is an integer for the next few periods.</li>
</ul>
<p>In <a href="#latest-protocol" id="id10" class="footnote_reference">1</a> section 7.8 (Payment of Founders Reward), define:</p>
<ul>
<li>FounderAddressAdjustedHeight(<em>height</em>) :=
<ul>
<li><em>height</em>, if not IsBlossomActivated(<em>height</em>)</li>
<li>BlossomActivationHeight + floor((<em>height</em> - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise</li>
</ul>
</li>
</ul>
<p>and in the definition of FounderAddressIndex, replace the use of <em>height</em> with FounderAddressAdjustedHeight(<em>height</em>).</p>
<p>Also define:</p>
<ul>
<li>FoundersRewardLastBlockHeight := max({ <em>height</em> ⦂ N | Halving(<em>height</em>) &lt; 1 })</li>
</ul>
<p>Replace the first note in that section with:</p>
<ul>
<li>No Founders Reward is required to be paid for <em>height</em> &gt; FoundersRewardLastBlockHeight (i.e. after the first halving), or for <em>height</em> = 0 (i.e. the genesis block).</li>
</ul>
<p>and in the second note, replace SlowStartShift + PreBlossomHalvingInterval - 1 with FoundersRewardLastBlockHeight.</p>
</section>
<section id="effect-on-difficulty-adjustment">
<h2>Effect on difficulty adjustment</h2>
<p>The difficulty adjustment parameters PoWAveragingWindow and PoWMedianBlockSpan refer to numbers of blocks, but do <em>not</em> change at Blossom activation. This is because the amount of damping/averaging required is expected to be roughly the same, in terms of the number of blocks, after the change in block target spacing.</p>
<p>The change in the effective value of PoWTargetSpacing will cause the block spacing to adjust to the new target, at the normal rate for a difficulty adjustment. The results of simulations are consistent with this expected behaviour.</p>
<p>Note that the change in AveragingWindowTimespan(height) takes effect immediately when calculating the target difficulty starting from the block at the Blossom activation height, even though the difficulty of the preceding PoWAveragingWindow blocks will have been adjusted using the pre-Blossom target spacing. Therefore it is likely that the difficulty adjustment for the first few blocks after activation will be limited by PoWMaxAdjustDown. This is not anticipated to cause any problem.</p>
<section id="minimum-difficulty-blocks-on-the-test-network">
<h3>Minimum difficulty blocks on the test network</h3>
<p>On the test network from block height 299188 onward, the difficulty adjustment algorithm allows minimum-difficulty blocks, as described in <a href="#zip-0205" id="id11" class="footnote_reference">5</a>, when the block time exceeds a given threshold. This specification changes this threshold to be proportional to the block target spacing.</p>
<p>That is, if the block time of a block at height <em>height</em> ≥ 299188 is at least 6 · PoWTargetSpacing(<em>height</em>) seconds after that of the preceding block, then the block is a minimum-difficulty block, and its target threshold is set to the value of PoWLimit for testnet (see <a href="#latest-protocol" id="id12" class="footnote_reference">1</a> section 5.3).</p>
<p>As before, the <code>nBits</code> field of a minimum-difficulty block is still computed according to the original difficulty adjustment algorithm, and only this field is used for the purpose of computing the MeanTarget values from which subsequent difficulty changes are calculated.</p>
</section>
</section>
<section id="non-consensus-node-behaviour">
<h2>Non-consensus node behaviour</h2>
<section id="end-of-service-halt">
<h3>End-of-Service halt</h3>
<p><cite>zcashd</cite> implements an "End-of-Service halt" behaviour that halts the node at a block height that corresponds approximately to a given time after release. This interval SHOULD be adjusted in releases where the End-of-Service halt time will follow Blossom activation.</p>
</section>
<section id="default-expiry-delta">
<h3>Default expiry delta</h3>
<p>When not overridden by the <cite>-txexpirydelta</cite> option, <cite>zcashd</cite> RPC calls that create transactions use a default value for the number of blocks after which a transaction will expire. The default in recent versions of <cite>zcashd</cite> is 20 blocks, which at the pre-Blossom block target spacing corresponds to roughly 50 minutes.</p>
<p>This default SHOULD change to BlossomPoWTargetSpacingRatio · 20 blocks after Blossom activation, to maintain the approximate expiry time of 50 minutes.</p>
<p>If the <cite>-txexpirydelta</cite> option is set, then the set value SHOULD be used both before and after Blossom activation.</p>
</section>
<section id="fingerprinting-mitigation">
<h3>Fingerprinting mitigation</h3>
<p>A "fingerprinting attack" is a network analysis technique in which nodes are identified across network sessions, for example using information about which blocks they request or send.</p>
<p><code>zcashd</code> inherits from Bitcoin Core the following behaviour, described in a comment in <code>main.cpp</code>, intended as a fingerprinting mitigation:</p>
<pre>// To prevent fingerprinting attacks, only send blocks outside of the active
// chain if they are valid, and no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about.</pre>
<p>We make no assertion about the significance of fingerprinting for Zcash, and (despite the word "prevent" in the above comment) no claim about the effectiveness of this mitigation.</p>
<p>In any case, to estimate the "best equivalent proof of work" of a given block chain (measured in units of time), we take the total work of the chain as defined in <a href="#latest-protocol" id="id13" class="footnote_reference">1</a> section 7.6.5, divide by the work of the block at the active tip, and multiply by the target block spacing of that block.</p>
<p>It is not a requirement of the Zcash protocol that this fingerprinting mitigation is used; however, if it is used, then it SHOULD use the target block spacing at the same block height that is used for the current work estimate.</p>
</section>
<section id="monitoring-for-quicker-or-slower-than-expected-blocks">
<h3>Monitoring for quicker- or slower-than-expected blocks</h3>
<p><cite>zcashd</cite> previously did this monitoring every 150 seconds; it is now done every 60 seconds.</p>
</section>
<section id="block-timeout">
<h3>Block timeout</h3>
<p>The timeout for a requested block is calculated as the target block time, multiplied by 2 + (the number of queued validated headers)/2.</p>
</section>
<section id="latency-optimization-when-requesting-blocks">
<h3>Latency optimization when requesting blocks</h3>
<p>When <code>zcashd</code> sees an announced block that chains from headers that it does not already have, it will first ask for the headers, and then the block itself. A latency optimization is performed only if the chain is "nearly synced":</p>
<pre>// First request the headers preceding the announced block. In the normal fully-synced
// case where a new block is announced that succeeds the current tip (no reorganization),
// there are no such headers.
// Secondly, and only when we are close to being synced, we request the announced block directly,
// to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
// time the block arrives, the header chain leading up to it is already validated. Not
// doing this will result in the received block being rejected as an orphan in case it is
// not a direct successor.</pre>
<p>The heuristic for "nearly synced" is that the timestamp of the block at the active tip is no more than 20 block times before the current "adjusted time". In <code>zcashd</code> this calculation uses the block target spacing as of the best known header. Around Blossom activation when the block target spacing changes, this could cause the heuristic to be based on the pre-Blossom block target spacing until the node has synced headers past the activation block, but this is not anticipated to cause any problem.</p>
</section>
<section id="response-to-getblocks-message-when-pruning">
<h3>Response to getblocks message when pruning</h3>
<p>If pruning is enabled, when <code>zcashd</code> responds to an "getblocks" peer-to-peer message, it will only include blocks that it has on disk, and is likely to still have on disk an hour after responding to the message:</p>
<pre>// If pruning, don't inv blocks unless we have on disk and are likely to still have
// for some reasonable time window (1 hour) that block relay might require.</pre>
<p>For each block, when estimating whether it will still be on disk after an hour, we take MIN_BLOCKS_TO_KEEP = 288 blocks, minus approximately the number of blocks expected in one hour at the target block spacing as of that block. Around Blossom activation, this might underestimate the number of blocks in the next hour, but given the value of MIN_BLOCKS_TO_KEEP, this is not anticipated to cause any problem.</p>
</section>
<section id="estimation-of-fully-synced-chain-height">
<h3>Estimation of fully synced chain height</h3>
<p><code>zcashd</code> uses the <code>EstimateNetHeight</code> function to estimate the approximate height of the fully synced chain, so that the progress of block download can be displayed to the node operator. This function has been rewritten, simplified, and changed to take account of cases where the time period that needs to be estimated crosses Blossom activation.</p>
</section>
<section id="other-block-related-constants">
<h3>Other block-related constants</h3>
<p>The following constants, measured in number of blocks, were reviewed and a decision was made not to change them:</p>
<pre>/** The number of blocks within expiry height when a tx is considered to be expiring soon */
TX_EXPIRING_SOON_THRESHOLD = 3
/** Maximum reorg length we will accept before we shut down and alert the user. */
MAX_REORG_LENGTH = COINBASE_MATURITY - 1;
static const int COINBASE_MATURITY = 100;
/** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;</pre>
</section>
</section>
</section>
<section id="deployment">
<h1>Deployment</h1>
<p>This proposal will be deployed with the Blossom network upgrade. <a href="#zip-0206" id="id14" class="footnote_reference">6</a></p>
</section>
<section id="backward-compatibility">
<h1>Backward compatibility</h1>
<p>This proposal intentionally creates what is known as a "bilateral consensus rule change". Use of this mechanism requires that all network participants upgrade their software to a compatible version within the upgrade window. Older software will treat post-upgrade blocks as invalid, and will follow any pre-upgrade branch that persists.</p>
</section>
<section id="reference-implementation">
<h1>Reference Implementation</h1>
<p><a href="https://github.com/zcash/zcash/pull/4025">https://github.com/zcash/zcash/pull/4025</a></p>
</section>
<section id="references">
<h1>References</h1>
<table id="latest-protocol" class="footnote">
<tbody>
<tr>
<th>1</th>
<td><a href="https://github.com/zcash/zips/blob/master/protocol/blossom.pdf">Zcash Protocol Specification, Version 2019.0.1 or later [Overwinter+Sapling+Blossom]</a></td>
</tr>
</tbody>
</table>
<table id="preblossom-protocol" class="footnote">
<tbody>
<tr>
<th>2</th>
<td><a href="https://github.com/zcash/zips/blob/9515d73aac0aea3494f77bcd634e1e4fbd744b97/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-37 (exactly) [Overwinter+Sapling]</a></td>
</tr>
</tbody>
</table>
<table id="rfc2119" class="footnote">
<tbody>
<tr>
<th>3</th>
<td><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a></td>
</tr>
</tbody>
</table>
<table id="zip-0200" class="footnote">
<tbody>
<tr>
<th>4</th>
<td><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Mechanism</a></td>
</tr>
</tbody>
</table>
<table id="zip-0205" class="footnote">
<tbody>
<tr>
<th>5</th>
<td><a href="https://github.com/zcash/zips/blob/master/zip-0205.rst">ZIP 205: Deployment of the Sapling Network Upgrade</a></td>
</tr>
</tbody>
</table>
<table id="zip-0206" class="footnote">
<tbody>
<tr>
<th>6</th>
<td><a href="https://github.com/zcash/zips/blob/master/zip-0206.rst">ZIP 206: Deployment of the Blossom Network Upgrade</a></td>
</tr>
</tbody>
</table>
<table id="slowfastblocks" class="footnote">
<tbody>
<tr>
<th>7</th>
<td>On Slow and Fast Block Times &lt;<a href="https://blog.ethereum.org/2015/09/14/on-slow-and-fast-block-times/">https://blog.ethereum.org/2015/09/14/on-slow-and-fast-block-times/</a>&gt;_</td>
</tr>
</tbody>
</table>
</section>
</body>
</html>

View File

@ -1,404 +0,0 @@
ZIP: 208
Title: Shorter Block Target Spacing
Owners: Daira Hopwood <daira@electriccoin.co>
Original-Authors: Daira Hopwood <daira@electriccoin.co>
Simon Liu <simon@bitcartel.com>
Status: Implemented
Category: Consensus
Created: 2019-01-10
License: MIT
Terminology
===========
The key words \"MUST\", \"SHOULD\", \"SHOULD NOT\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The terms \"block chain\", \"consensus rule change\", \"branch\", and
\"network upgrade\" are to be interpreted as defined in[^2].
The term \"block target spacing\" means the time interval between blocks
targeted by the difficulty adjustment algorithm in a given branch. It is
normally measured in seconds. (This is also sometimes called the
\"target block time\", but \"block target spacing\" is the term used
in[^3].)
Abstract
========
This proposal specifies a change in the block target spacing, to take
effect in the Blossom network upgrade[^4].
The emission schedule of mined ZEC will be approximately the same in
terms of time, but this requires the emission per block to be adjusted
to take account of the changed block target spacing.
Motivation
==========
The motivations for decreasing the block target spacing are:
- Reduced latency for considering transactions to be sufficiently
confirmed;
- Greater throughput of transactions in unit time.
The latter goal could alternatively be achieved by increasing the block
size limit, but that would not also achieve the former goal.
Note that, for a given security requirement (in terms of the expected
cost distribution of a rollback attack), the number of confirmations
needed increases more slowly than the decrease in block time, and so, up
to a point, decreasing the block target spacing can provide a better
trade-off between latency and security. This argument assumes that the
verification and propagation time for a block remain small compared to
the block target spacing. See[^5] for further analysis in various attack
models.
Specification
=============
The changes described in this section are to be made in[^6], relative to
the pre-Blossom specification in \[\#preblossom-protocol\].
Consensus changes
-----------------
Throughout the specification, rename HalvingInterval to
PreBlossomHalvingInterval, and rename PoWTargetSpacing to
PreBlossomTargetSpacing. These constants retain their values from[^7] of
840000 (blocks) and 150 (seconds) respectively.
In section 2 (Notation), add BlossomActivationHeight and
PostBlossomPoWTargetSpacing to the list of integer constants.
In section 5.3 (Constants), define PostBlossomPoWTargetSpacing := 75
seconds.
For a given network (production or test), define BlossomActivationHeight
as the height at which Blossom activates on that network, as specified
in[^8].
In section 7.6.3 (Difficulty adjustment), make the following changes:
Define IsBlossomActivated(*height*) to return true if *height*
BlossomActivationHeight, otherwise false.
This specification assumes that BlossomActivationHeight ≥
SlowStartInterval.
Define:
- BlossomPoWTargetSpacingRatio := PreBlossomPoWTargetSpacing /
PostBlossomPoWTargetSpacing
- PostBlossomHalvingInterval := floor(PreBlossomHalvingInterval ·
BlossomPoWTargetSpacingRatio).
In the same section, redefine PoWTargetSpacing as a function taking a
*height* parameter, as follows:
- PoWTargetSpacing(*height*) :=
- PreBlossomPoWTargetSpacing, if not IsBlossomActivated(*height*)
- PostBlossomPoWTargetSpacing, otherwise.
Also redefine AveragingWindowTimespan, MinActualTimespan,
MaxActualTimespan, ActualTimespanDamped, ActualTimespanBounded, and
Threshold as follows:
- add a *height* parameter to each of these functions that does not
already have one;
- ensure that each reference to any of these values, or to
PoWTargetSpacing, are replaced with a function call passing the
*height* parameter.
In[^9] section 7.7 (Calculation of Block Subsidy and Founders' Reward),
redefine the Halving and BlockSubsidy functions as follows:
- Halving(*height*) :=
- floor((*height* - SlowStartShift) / PreBlossomHalvingInterval),
if not IsBlossomActivated(*height*)
- floor((BlossomActivationHeight - SlowStartShift) /
PreBlossomHalvingInterval + (*height* - BlossomActivationHeight)
/ PostBlossomHalvingInterval), otherwise
- BlockSubsidy(*height*) :=
- SlowStartRate · *height*, if *height* \< SlowStartInterval / 2
- SlowStartRate · (*height* + 1), if SlowStartInterval / 2 ≤
*height* and *height* \< SlowStartInterval
- floor(MaxBlockSubsidy / 2^Halving(\*height\*)^), if
SlowStartInterval ≤ *height* and not
IsBlossomActivated(*height*)
- floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio ·
2^Halving(\*height\*)^)), otherwise
TODO: ideally, BlossomActivationHeight, PostBlossomHalvingInterval, and
PostBlossomTargetSpacing should be chosen so that:
- (BlossomActivationHeight - SlowStartShift) /
PreBlossomHalvingInterval + (*height* - BlossomActivationHeight) /
PostBlossomHalvingInterval) is exactly 1 for some integer *height*.
- MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio ·
2^Halving(\*height\*)^) is an integer for the next few periods.
In[^10] section 7.8 (Payment of Founders' Reward), define:
- FounderAddressAdjustedHeight(*height*) :=
- *height*, if not IsBlossomActivated(*height*)
- BlossomActivationHeight + floor((*height* -
BlossomActivationHeight) / BlossomPoWTargetSpacingRatio),
otherwise
and in the definition of FounderAddressIndex, replace the use of
*height* with FounderAddressAdjustedHeight(*height*).
Also define:
- FoundersRewardLastBlockHeight := max({ *height* ⦂ N \|
Halving(*height*) \< 1 })
Replace the first note in that section with:
- No Founders' Reward is required to be paid for *height* \>
FoundersRewardLastBlockHeight (i.e. after the first halving), or for
*height* = 0 (i.e. the genesis block).
and in the second note, replace SlowStartShift +
PreBlossomHalvingInterval - 1 with FoundersRewardLastBlockHeight.
Effect on difficulty adjustment
-------------------------------
The difficulty adjustment parameters PoWAveragingWindow and
PoWMedianBlockSpan refer to numbers of blocks, but do *not* change at
Blossom activation. This is because the amount of damping/averaging
required is expected to be roughly the same, in terms of the number of
blocks, after the change in block target spacing.
The change in the effective value of PoWTargetSpacing will cause the
block spacing to adjust to the new target, at the normal rate for a
difficulty adjustment. The results of simulations are consistent with
this expected behaviour.
Note that the change in AveragingWindowTimespan(height) takes effect
immediately when calculating the target difficulty starting from the
block at the Blossom activation height, even though the difficulty of
the preceding PoWAveragingWindow blocks will have been adjusted using
the pre-Blossom target spacing. Therefore it is likely that the
difficulty adjustment for the first few blocks after activation will be
limited by PoWMaxAdjustDown. This is not anticipated to cause any
problem.
### Minimum difficulty blocks on the test network
On the test network from block height 299188 onward, the difficulty
adjustment algorithm allows minimum-difficulty blocks, as described
in[^11], when the block time exceeds a given threshold. This
specification changes this threshold to be proportional to the block
target spacing.
That is, if the block time of a block at height *height* ≥ 299188 is at
least 6 · PoWTargetSpacing(*height*) seconds after that of the preceding
block, then the block is a minimum-difficulty block, and its target
threshold is set to the value of PoWLimit for testnet (see[^12] section
5.3).
As before, the `nBits` field of a minimum-difficulty block is still
computed according to the original difficulty adjustment algorithm, and
only this field is used for the purpose of computing the MeanTarget
values from which subsequent difficulty changes are calculated.
Non-consensus node behaviour
----------------------------
### End-of-Service halt
zcashd implements an \"End-of-Service halt\" behaviour that halts the
node at a block height that corresponds approximately to a given time
after release. This interval SHOULD be adjusted in releases where the
End-of-Service halt time will follow Blossom activation.
### Default expiry delta
When not overridden by the -txexpirydelta option, zcashd RPC calls that
create transactions use a default value for the number of blocks after
which a transaction will expire. The default in recent versions of
zcashd is 20 blocks, which at the pre-Blossom block target spacing
corresponds to roughly 50 minutes.
This default SHOULD change to BlossomPoWTargetSpacingRatio · 20 blocks
after Blossom activation, to maintain the approximate expiry time of 50
minutes.
If the -txexpirydelta option is set, then the set value SHOULD be used
both before and after Blossom activation.
### Fingerprinting mitigation
A \"fingerprinting attack\" is a network analysis technique in which
nodes are identified across network sessions, for example using
information about which blocks they request or send.
`zcashd` inherits from Bitcoin Core the following behaviour, described
in a comment in `main.cpp`, intended as a fingerprinting mitigation:
// To prevent fingerprinting attacks, only send blocks outside of the active
// chain if they are valid, and no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about.
We make no assertion about the significance of fingerprinting for Zcash,
and (despite the word \"prevent\" in the above comment) no claim about
the effectiveness of this mitigation.
In any case, to estimate the \"best equivalent proof of work\" of a
given block chain (measured in units of time), we take the total work of
the chain as defined in[^13] section 7.6.5, divide by the work of the
block at the active tip, and multiply by the target block spacing of
that block.
It is not a requirement of the Zcash protocol that this fingerprinting
mitigation is used; however, if it is used, then it SHOULD use the
target block spacing at the same block height that is used for the
current work estimate.
### Monitoring for quicker- or slower-than-expected blocks
zcashd previously did this monitoring every 150 seconds; it is now done
every 60 seconds.
### Block timeout
The timeout for a requested block is calculated as the target block
time, multiplied by 2 + (the number of queued validated headers)/2.
### Latency optimization when requesting blocks
When `zcashd` sees an announced block that chains from headers that it
does not already have, it will first ask for the headers, and then the
block itself. A latency optimization is performed only if the chain is
\"nearly synced\":
// First request the headers preceding the announced block. In the normal fully-synced
// case where a new block is announced that succeeds the current tip (no reorganization),
// there are no such headers.
// Secondly, and only when we are close to being synced, we request the announced block directly,
// to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
// time the block arrives, the header chain leading up to it is already validated. Not
// doing this will result in the received block being rejected as an orphan in case it is
// not a direct successor.
The heuristic for \"nearly synced\" is that the timestamp of the block
at the active tip is no more than 20 block times before the current
\"adjusted time\". In `zcashd` this calculation uses the block target
spacing as of the best known header. Around Blossom activation when the
block target spacing changes, this could cause the heuristic to be based
on the pre-Blossom block target spacing until the node has synced
headers past the activation block, but this is not anticipated to cause
any problem.
### Response to getblocks message when pruning
If pruning is enabled, when `zcashd` responds to an \"getblocks\"
peer-to-peer message, it will only include blocks that it has on disk,
and is likely to still have on disk an hour after responding to the
message:
// If pruning, don't inv blocks unless we have on disk and are likely to still have
// for some reasonable time window (1 hour) that block relay might require.
For each block, when estimating whether it will still be on disk after
an hour, we take MIN\_BLOCKS\_TO\_KEEP = 288 blocks, minus approximately
the number of blocks expected in one hour at the target block spacing as
of that block. Around Blossom activation, this might underestimate the
number of blocks in the next hour, but given the value of
MIN\_BLOCKS\_TO\_KEEP, this is not anticipated to cause any problem.
### Estimation of fully synced chain height
`zcashd` uses the `EstimateNetHeight` function to estimate the
approximate height of the fully synced chain, so that the progress of
block download can be displayed to the node operator. This function has
been rewritten, simplified, and changed to take account of cases where
the time period that needs to be estimated crosses Blossom activation.
### Other block-related constants
The following constants, measured in number of blocks, were reviewed and
a decision was made not to change them:
/** The number of blocks within expiry height when a tx is considered to be expiring soon */
TX_EXPIRING_SOON_THRESHOLD = 3
/** Maximum reorg length we will accept before we shut down and alert the user. */
MAX_REORG_LENGTH = COINBASE_MATURITY - 1;
static const int COINBASE_MATURITY = 100;
/** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
Deployment
==========
This proposal will be deployed with the Blossom network upgrade.[^14]
Backward compatibility
======================
This proposal intentionally creates what is known as a \"bilateral
consensus rule change\". Use of this mechanism requires that all network
participants upgrade their software to a compatible version within the
upgrade window. Older software will treat post-upgrade blocks as
invalid, and will follow any pre-upgrade branch that persists.
Reference Implementation
========================
<https://github.com/zcash/zcash/pull/4025>
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^4]: [ZIP 206: Deployment of the Blossom Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0206.rst)
[^5]: On Slow and Fast Block Times
\<<https://blog.ethereum.org/2015/09/14/on-slow-and-fast-block-times/>\>\_
[^6]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^7]: [Zcash Protocol Specification, Version 2018.0-beta-37 (exactly)
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/9515d73aac0aea3494f77bcd634e1e4fbd744b97/protocol/protocol.pdf)
[^8]: [ZIP 206: Deployment of the Blossom Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0206.rst)
[^9]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^10]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^11]: [ZIP 205: Deployment of the Sapling Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0205.rst)
[^12]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^13]: [Zcash Protocol Specification, Version 2019.0.1 or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/blossom.pdf)
[^14]: [ZIP 206: Deployment of the Blossom Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0206.rst)

50
zip-0209.html Normal file
View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0209</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 209
Title: Prohibit Negative Shielded Value Pool
Owners: Sean Bowe &lt;sean@electriccoin.co&gt;
Status: Final
Category: Consensus
Created: 2019-02-25
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The term &quot;block chain&quot; and &quot;network upgrade&quot; are to be interpreted as defined in<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a>.</p>
<p>The &quot;Sprout value pool balance&quot; for a given block chain, as implied by section 4.11 of the Zcash Protocol Specification<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>, is the sum of all <code>vpub_old</code> fields for transactions in the block chain, minus the sum of all <code>vpub_new</code> fields for transactions in the block chain.</p>
<p>The &quot;Sapling value pool balance&quot; for a given block chain, as implied by section 4.12 of Zcash Protocol Specification<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>, is the negation of the sum of all <code>valueBalance</code> fields for transactions in the block chain.</p>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines how the consensus rules are altered such that blocks which produce negative shielded value pools are prohibited.</p>
<h1 id="motivation">Motivation</h1>
<p>It is possible for nodes to monitor the total value of notes that are shielded to, or unshielded from, each of the Sprout or Sapling value pools. If the total value that is unshielded exceeds the total value that was shielded for a given pool, a balance violation has occurred in the corresponding shielded transaction protocol.</p>
<p>It would be preferable for the network to reject blocks that result in the aforementioned balance violation. However, nodes do not currently react to such an event. Remediation may therefore require chain rollbacks and other disruption.</p>
<h1 id="specification">Specification</h1>
<p>If the &quot;Sprout value pool balance&quot; or &quot;Sapling value pool balance&quot; would become negative in the block chain created as a result of accepting a block, then all nodes MUST reject the block as invalid.</p>
<p>Nodes MAY relay transactions even if one or more of them cannot be mined due to the aforementioned restriction.</p>
<h1 id="deployment">Deployment</h1>
<p>This consensus rule is not deployed as part of a network upgrade as defined in ZIP-200<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a> and there is no mechanism by which the network will synchronize to enforce this rule. Rather, all nodes should begin enforcing this consensus rule upon acceptance of this proposal.</p>
<p>There is a risk that before all nodes on the network begin enforcing this consensus rule that block(s) will be produced that violate it, potentially leading to network fragmentation. This is considered sufficiently unlikely that the benefits of enforcing this consensus rule sooner are overwhelming.</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2019.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2019.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Mechanism</a><a href="#fnref5" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,85 +0,0 @@
ZIP: 209
Title: Prohibit Negative Shielded Value Pool
Owners: Sean Bowe <sean@electriccoin.co>
Status: Final
Category: Consensus
Created: 2019-02-25
License: MIT
Terminology
===========
The key words \"MUST\", \"SHOULD\", \"SHOULD NOT\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The term \"block chain\" and \"network upgrade\" are to be interpreted
as defined in[^2].
The \"Sprout value pool balance\" for a given block chain, as implied by
section 4.11 of the Zcash Protocol Specification[^3], is the sum of all
`vpub_old` fields for transactions in the block chain, minus the sum of
all `vpub_new` fields for transactions in the block chain.
The \"Sapling value pool balance\" for a given block chain, as implied
by section 4.12 of Zcash Protocol Specification[^4], is the negation of
the sum of all `valueBalance` fields for transactions in the block
chain.
Abstract
========
This proposal defines how the consensus rules are altered such that
blocks which produce negative shielded value pools are prohibited.
Motivation
==========
It is possible for nodes to monitor the total value of notes that are
shielded to, or unshielded from, each of the Sprout or Sapling value
pools. If the total value that is unshielded exceeds the total value
that was shielded for a given pool, a balance violation has occurred in
the corresponding shielded transaction protocol.
It would be preferable for the network to reject blocks that result in
the aforementioned balance violation. However, nodes do not currently
react to such an event. Remediation may therefore require chain
rollbacks and other disruption.
Specification
=============
If the \"Sprout value pool balance\" or \"Sapling value pool balance\"
would become negative in the block chain created as a result of
accepting a block, then all nodes MUST reject the block as invalid.
Nodes MAY relay transactions even if one or more of them cannot be mined
due to the aforementioned restriction.
Deployment
==========
This consensus rule is not deployed as part of a network upgrade as
defined in ZIP-200[^5] and there is no mechanism by which the network
will synchronize to enforce this rule. Rather, all nodes should begin
enforcing this consensus rule upon acceptance of this proposal.
There is a risk that before all nodes on the network begin enforcing
this consensus rule that block(s) will be produced that violate it,
potentially leading to network fragmentation. This is considered
sufficiently unlikely that the benefits of enforcing this consensus rule
sooner are overwhelming.
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [Zcash Protocol Specification, Version 2019.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^4]: [Zcash Protocol Specification, Version 2019.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^5]: [ZIP 200: Network Upgrade
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)

61
zip-0210.html Normal file
View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0210</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 210
Title: Sapling Anchor Deduplication within Transactions
Owners: Jack Grigg &lt;str4d@electriccoin.co&gt;
Status: Draft
Category: Consensus
Created: 2019-03-27
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot; and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The term &quot;network upgrade&quot; in this document is to be interpreted as described in ZIP 200 <a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a>.</p>
<p>The term &quot;Sapling&quot; in this document is to be interpreted as described in ZIP 205 <a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</p>
<h1 id="abstract">Abstract</h1>
<p>This proposal defines a modification to the transaction format whereby a single Sapling anchor is used for all Sapling spends. This change removes a potential implementation fingerprint, and reduces the size of Sapling transactions within the block chain.</p>
<h1 id="motivation">Motivation</h1>
<p>The Sapling network upgrade<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> introduced new shielded inputs (spends) and outputs. Each spend proves the existence of the note being spent by including the anchor of a Merkle tree that contains the note's commitment, and proving in zero knowledge the existence of a path from the commitment to the anchor (a witness). Valid anchors correspond to the state of the Sapling commitment tree after each block in the chain.</p>
<p>The choice of anchor leaks information about the note being spent, namely that the note was created no later than the anchor's block height. This is an unavoidable outcome of the Zcash design, and the least information it is possible to leak about a note being spent. However, the Sapling v4 transaction format<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a> includes a separate anchor for each Sapling spend, and thus it is possible to leak additional information by using different anchors for different notes. The anchor selection choices could also be used as a fingerprint to identify transactions created by particular wallet implementations, reducing the privacy set.</p>
<p>Modifying the transaction format to have a single Sapling anchor field, instead of one field per Sapling spend, removes the ability (within the new transaction format version) to create transactions with this fingerprint. It also reduces the size of the transaction, costing 32 bytes per transaction instead of 32 bytes per spend.</p>
<h1 id="specification">Specification</h1>
<p>A new transaction format is defined, identical to the Sapling v4 transaction format except for two changes:</p>
<ul>
<li>The <code>anchor</code> field in <code>SpendDescription</code> is removed.</li>
<li>A new field <code>saplingAnchor</code> is placed between <code>vShieldedOutput</code> and <code>vJoinSplit</code>, if and only if <code>vShieldedSpend</code> is not empty.</li>
</ul>
<p>Consensus rules that previously applied to individual <code>anchor</code> entries MUST be applied to <code>saplingAnchor</code>.</p>
<p>TODO: If this is the only ZIP updating the transaction format in a NU, specify the full transaction format here. Otherwise, reference the new transaction format when specified.</p>
<p>Implementations that support older transaction formats MAY copy <code>saplingAnchor</code> into each spend's in-memory representation during parsing to reduce code duplication, and MUST ensure that these per-spend in-memory anchors are all identical prior to serialization.</p>
<h1 id="rationale">Rationale</h1>
<p>Placing the <code>saplingAnchor</code> field after <code>vShieldedOutput</code> means that it can be conditionally included (saving space when there are no Sapling spends), while ensuring that the transaction can still be parsed unambiguously.</p>
<p>Requiring all Sapling spends to use the same anchor removes a possible performance optimisation in certain classes of (particularly light) wallets, where witnesses for older notes are only updated periodically instead of every block. This optimisation is exactly the kind of behaviour that can be used as a fingerprint in the v4 transaction format, and that we are choosing to prevent with this proposal.</p>
<h1 id="security-and-privacy-considerations">Security and Privacy Considerations</h1>
<p>This proposal eliminates a possible avenue for distinguishing transactions based on the client implementation that created them.</p>
<h1 id="reference-implementation">Reference Implementation</h1>
<p>TBD</p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0200.rst">ZIP 200: Network Upgrade Activation Mechanism</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/zip-0205.rst">ZIP 205: Deployment of the Sapling Network Upgrade</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/zcash/zips/blob/master/zip-0205.rst">ZIP 205: Deployment of the Sapling Network Upgrade</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Section 7.1: Encoding of Transactions. Zcash Protocol Specification, Version 2019.0-beta-37 [Overwinter+Sapling]</a><a href="#fnref5" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,121 +0,0 @@
ZIP: 210
Title: Sapling Anchor Deduplication within Transactions
Owners: Jack Grigg <str4d@electriccoin.co>
Status: Draft
Category: Consensus
Created: 2019-03-27
License: MIT
Terminology
===========
The key words \"MUST\" and \"MAY\" in this document are to be
interpreted as described in RFC 2119.[^1]
The term \"network upgrade\" in this document is to be interpreted as
described in ZIP 200 [^2].
The term \"Sapling\" in this document is to be interpreted as described
in ZIP 205 [^3].
Abstract
========
This proposal defines a modification to the transaction format whereby a
single Sapling anchor is used for all Sapling spends. This change
removes a potential implementation fingerprint, and reduces the size of
Sapling transactions within the block chain.
Motivation
==========
The Sapling network upgrade[^4] introduced new shielded inputs (spends)
and outputs. Each spend proves the existence of the note being spent by
including the anchor of a Merkle tree that contains the note\'s
commitment, and proving in zero knowledge the existence of a path from
the commitment to the anchor (a witness). Valid anchors correspond to
the state of the Sapling commitment tree after each block in the chain.
The choice of anchor leaks information about the note being spent,
namely that the note was created no later than the anchor\'s block
height. This is an unavoidable outcome of the Zcash design, and the
least information it is possible to leak about a note being spent.
However, the Sapling v4 transaction format[^5] includes a separate
anchor for each Sapling spend, and thus it is possible to leak
additional information by using different anchors for different notes.
The anchor selection choices could also be used as a fingerprint to
identify transactions created by particular wallet implementations,
reducing the privacy set.
Modifying the transaction format to have a single Sapling anchor field,
instead of one field per Sapling spend, removes the ability (within the
new transaction format version) to create transactions with this
fingerprint. It also reduces the size of the transaction, costing 32
bytes per transaction instead of 32 bytes per spend.
Specification
=============
A new transaction format is defined, identical to the Sapling v4
transaction format except for two changes:
- The `anchor` field in `SpendDescription` is removed.
- A new field `saplingAnchor` is placed between `vShieldedOutput` and
`vJoinSplit`, if and only if `vShieldedSpend` is not empty.
Consensus rules that previously applied to individual `anchor` entries
MUST be applied to `saplingAnchor`.
TODO: If this is the only ZIP updating the transaction format in a NU,
specify the full transaction format here. Otherwise, reference the new
transaction format when specified.
Implementations that support older transaction formats MAY copy
`saplingAnchor` into each spend\'s in-memory representation during
parsing to reduce code duplication, and MUST ensure that these per-spend
in-memory anchors are all identical prior to serialization.
Rationale
=========
Placing the `saplingAnchor` field after `vShieldedOutput` means that it
can be conditionally included (saving space when there are no Sapling
spends), while ensuring that the transaction can still be parsed
unambiguously.
Requiring all Sapling spends to use the same anchor removes a possible
performance optimisation in certain classes of (particularly light)
wallets, where witnesses for older notes are only updated periodically
instead of every block. This optimisation is exactly the kind of
behaviour that can be used as a fingerprint in the v4 transaction
format, and that we are choosing to prevent with this proposal.
Security and Privacy Considerations
===================================
This proposal eliminates a possible avenue for distinguishing
transactions based on the client implementation that created them.
Reference Implementation
========================
TBD
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 200: Network Upgrade Activation
Mechanism](https://github.com/zcash/zips/blob/master/zip-0200.rst)
[^3]: [ZIP 205: Deployment of the Sapling Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0205.rst)
[^4]: [ZIP 205: Deployment of the Sapling Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0205.rst)
[^5]: [Section 7.1: Encoding of Transactions. Zcash Protocol
Specification, Version 2019.0-beta-37
\[Overwinter+Sapling\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)

516
zip-0243.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

189
zip-0308.html Normal file
View File

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-0308</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: 308
Title: Sprout to Sapling Migration
Owners: Daira Hopwood &lt;daira@electriccoin.co&gt;
Eirik Ogilvie-Wigley &lt;eirik@electriccoin.co&gt;
Status: Final
Category: RPC/Wallet
Created: 2018-11-27
License: MIT</code></pre>
<h1 id="terminology">Terminology</h1>
<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>Sprout protocol</dt>
<dd><p>Code-name for the Zcash shielded protocol at launch.</p>
</dd>
<dt>Sapling protocol</dt>
<dd><p>Code-name for the Zcash shielded protocol added by the second Zcash network upgrade, also known as Network Upgrade 1.</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>This proposal describes privacy-preserving procedures to migrate funds from Sprout to Sapling z-addresses; and supporting RPC operations to enable, disable, and monitor the migration process.</p>
<h1 id="motivation">Motivation</h1>
<p>Zcash Sapling<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> introduces significant efficiency improvements relative to the previous iteration of the Zcash shielded protocol, Sprout. These improvements will pave the way for broad mobile, exchange and vendor adoption of shielded addresses.</p>
<p>Therefore, we anticipate that users will want to migrate all their shielded funds from Sprout to Sapling.</p>
<p>The Zcash consensus rules prohibit direct transfers from Sprout to Sapling z-addresses, unless the amount is revealed by sending it through the &quot;transparent value pool&quot;<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>. The primary motivation for this is to allow detection of any overall inflation of the Zcash monetary base, due to exploitation of possible vulnerabilities in the shielded protocols or their implementation, or a compromise of the Sprout multi-party computation. (It is not necessary for Sprout -&gt; Sapling transfers to go via a t-address.)</p>
<p>Since the exposure of the migrated amount potentially compromises the privacy of users, we wish to define a way to perform the migration that mitigates this privacy leak as far as possible. This can be done by hiding individual migration transactions among those of all users that are doing the migration at around the same time.</p>
<p>The security analysis of migration strategies is quite subtle; the more obvious potential strategies can leak a lot of information.</p>
<h1 id="requirements">Requirements</h1>
<p>Migration is performed &quot;in the background&quot; by a <code>zcashd</code> (or equivalent) node. It does not significantly interfere with concurrent usage of the node, other than possibly increasing the latency of some other shielded operations.</p>
<p>It is possible to enable or disable migration at any time.</p>
<p>All shielded funds in Sprout z-addresses will eventually be transferred to Sapling z-addresses, provided the node is working.</p>
<p>It should take a &quot;reasonable&quot; length of time to complete the transfer; less than a month for amounts up to 1000 ZEC.</p>
<p>The design should mitigate information leakage via timing information and transaction data, including</p>
<ul>
<li>linkage of particular z-addresses or users, and the amounts held;</li>
<li>information about the distribution of amounts of individual notes.</li>
</ul>
<p>The design and implementation is stateless, to the extent practical.</p>
<p>Visibility is provided for the wallet/node user into the progress of the migration.</p>
<p>There is sufficient information available to debug failed transactions that are part of the migration.</p>
<p>The design recovers from failed operations to the extent possible.</p>
<p>The total amount sent by each user is obscured, to the extent practical.</p>
<h1 id="non-requirements">Non-requirements</h1>
<p>There is no requirement or assumption of network layer anonymity. (Users may, but are not expected to, configure Tor.)</p>
<p>The migration procedure does not have to provably leak no information.</p>
<p>There is no need to preserve individual note values (i.e. notes can be consolidated).</p>
<p>Migration txns need only be hidden among themselves, rather than among all kinds of transaction.</p>
<p>A small amount (less than 0.01 ZEC) can be left unmigrated if this helps with privacy.</p>
<p>It is not required to support the case of single wallet being used by multiple users whose funds should be kept distinct.</p>
<h1 id="specification">Specification</h1>
<p>There are two main aspects to a strategy for selecting migration transactions:</p>
<ul>
<li>how many transactions are sent, and when;</li>
<li>the amount sent in each transaction.</li>
</ul>
<h2 id="transaction-schedule">Transaction schedule</h2>
<p>When migration is enabled, a node will send up to 5 transactions for inclusion in each block with height a multiple of 500 (that is, they are sent immediately after seeing a block with height 499, modulo 500). Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds (possibly with a remainder less than 0.01 ZEC left unmigrated).</p>
<p>Nodes SHOULD NOT send migration transactions during initial block download, or if the timestamp of the triggering block (with height 499, modulo 500) is more than three hours in the past according to the node's adjusted local clock.</p>
<p>TODO: if we change the target block interval, 500 might need to be changed.</p>
<p>The migration transactions to be sent in a particular batch can take significant time to generate, and this time depends on the speed of the user's computer. If they were generated only after a block is seen at the target height minus 1, then this could leak information. Therefore, for target height N, implementations SHOULD start generating the transactions at around height N-5 (provided that block's timestamp is not more than three hours in the past). Each migration transaction SHOULD specify an anchor at height N-10 for each Sprout JoinSplit description.</p>
<p>Open questions:</p>
<ul>
<li>does this reliably give sufficient time to generate the transactions?</li>
<li>what happens to a batch if the anchor is invalidated -- should it be regenerated, or cancelled?</li>
</ul>
<h3 id="rationale-for-transaction-schedule">Rationale for transaction schedule</h3>
<p>Privacy is increased when the times at which to send transactions are coordinated between nodes. We choose to send a batch of transactions at each coordinated time. Sending multiple transactions in each batch ensures that:</p>
<ul>
<li>less information about balances is leaked;</li>
<li>it is easier to finish in a reasonable length of time.</li>
</ul>
<p>The choice of 500 blocks as the batch interval ensures that each batch occurs at a different time of day, which may help to mitigate problems with the availability of nodes being correlated with the local time-of-day.</p>
<p>Simulation shows that the migration process will typically complete reasonably quickly even if the amount to be migrated is large:</p>
<p>+-----------+--------------------------------------------+ | | Time in days to complete migration | | Amount +-----------------+--------+-----------------+ | | 10th-percentile | median | 90th-percentile | +===========+=================+========+=================+ | 1 ZEC| 1.01 | 1.50 | 2.33 | +-----------+-----------------+--------+-----------------+ | 10 ZEC| 1.65 | 2.46 | 3.45 | +-----------+-----------------+--------+-----------------+ | 100 ZEC| 2.54 | 3.99 | 5.83 | +-----------+-----------------+--------+-----------------+ | 1000 ZEC| 9.86 | 12.52 | 15.54 | +-----------+-----------------+--------+-----------------+ | 10000 ZEC| 89.23 | 97.01 | 105.05 | +-----------+-----------------+--------+-----------------+</p>
<p>The simulation also depends on the amounts sent as specified in the next section. It includes the time spent waiting for the first batch to be sent.</p>
<p>The code used for this simulation is at<a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>.</p>
<h2 id="how-much-to-send-in-each-transaction">How much to send in each transaction</h2>
<p>If the remaining amount to be migrated is less than 0.01 ZEC, end the migration.</p>
<p>Otherwise, the amount to send in each transaction is chosen according to the following distribution:</p>
<ol type="1">
<li>Choose an integer exponent uniformly in the range 6 to 8 inclusive.</li>
<li>Choose an integer mantissa uniformly in the range 1 to 99 inclusive.</li>
<li>Calculate amount := (mantissa * 10<sup>exponent</sup>) zatoshi.</li>
<li>If amount is greater than the amount remaining to send, repeat from step 1.</li>
</ol>
<p>Implementations MAY optimize this procedure by selecting the exponent and mantissa based on the amount remaining to avoid repetition, but the resulting distribution MUST be identical.</p>
<p>The amount chosen <em>includes</em> the 0.0001 ZEC fee for this transaction, i.e. the value of the Sapling output will be 0.0001 ZEC less.</p>
<h3 id="rationale-for-how-much-to-send">Rationale for how much to send</h3>
<p>Suppose that a user has an amount to migrate that is a round number of ZEC. Then, a potential attack would be to find some subset of all the migration transactions that sum to a round number of ZEC, and infer that all of those transactions are from the same user. If amounts sent were a random multiple of 1 zatoshi, then the resulting knapsack problem would be likely to have a unique solution and be practically solvable for the number of transactions involved. The chosen distribution of transaction amounts mitigates this potential vulnerability by ensuring that there will be many solutions for sets of transactions, including &quot;incorrect&quot; solutions (that is, solutions that mix transactions from different users, contrary to the supposed adversary's inference).</p>
<p>Making the chosen amount inclusive of the fee avoids leaving any unmigrated funds at the end, in the case where the original amount to migrate was a multiple of 0.01 ZEC.</p>
<h2 id="other-design-decisions">Other design decisions</h2>
<p>We assume use of the normal wallet note selection algorithm and change handling. Change is sent back to the default address, which is the z-address of the first selected Sprout note. The number of JoinSplits will therefore be the same as for a normal transaction sending the same amount with the same wallet state. Only the <code>vpub_new</code> of the last JoinSplit will be nonzero. There will always be exactly one Sapling Output.</p>
<p>The expiry delta for migration transactions MUST be 450 blocks. Since these transactions are sent when the block height is 499 modulo 500, their expiry height will be 451 blocks later, i.e. <code>nExpiryHeight</code> will be 450 modulo 500.</p>
<p>The fee for each migration transaction MUST be 0.0001 ZEC. This fee is taken from the funds to be migrated.</p>
<p>Some wallets by default add a &quot;developer fee&quot; to each transaction, directed to the developer(s) of the wallet. This is typically implemented by adding the developer address as an explicit output, so if migration transactions are generated internally by <code>zcashd</code>, they will not include the developer fee. We strongly recommend <em>not</em> patching the <code>zcashd</code> code to add the developer fee output to migration transactions, because doing so partitions the anonymity set between users of that wallet and other users.</p>
<p>There MUST NOT be any transparent inputs or outputs, or Sapling Spends, in a migration transaction.</p>
<p>The <code>lock_time</code> field MUST be set to 0 (unused).</p>
<p>When creating Sapling shielded Outputs, the outgoing viewing key <code>ovk</code> SHOULD be chosen in the same way as for a transfer sent from a t-address.</p>
<p>A node SHOULD treat migration transactions in the same way as transactions submitted over the RPC interface.</p>
<h2 id="open-questions">Open questions</h2>
<p>The above strategy has several &quot;magic number&quot; parameters:</p>
<ul>
<li>the interval between batches (500 blocks)</li>
<li>the maximum number of transactions in a batch (5)</li>
<li>the distribution of exponents (uniform integer in 6..8)</li>
<li>the distribution of mantissae (uniform integer in 1..99).</li>
</ul>
<p>These have been chosen by guesswork. Should we change any of them?</p>
<p>In particular, if the amount to migrate is large, then this strategy can result in fairly large amounts (up to 99 ZEC, worth USD ~6700 at time of writing) transferred in each transaction. This leaks the fact that the transaction was sent by a user who has at least that amount.</p>
<p>The strategy does not migrate any remaining fractional amount less than 0.01 ZEC (worth USD ~0.68 at time of writing). Is this reasonable?</p>
<p>In deciding the amount to send in each transaction, the strategy does not take account of the values of individual Sprout notes, only the total amount remaining to migrate. Can a strategy that is sensitive to individual note values improve privacy?</p>
<p>An adversary may attempt to interfere with the view of the block chain seen by a subset of nodes that are performing migrations, in order to cause those nodes to send migration batches at a different time, so that they may be distinguished. Is there anything further we can do to mitigate this vulnerability?</p>
<h2 id="rpc-calls">RPC calls</h2>
<p>Nodes MUST maintain a boolean state variable during their execution, to determine whether migration is enabled. The default when a node starts, is set by a configuration option:</p>
<pre><code>-migration=0/1</code></pre>
<p>The destination z-address can optionally be set by another option:</p>
<pre><code>-migrationdestaddress=&lt;zaddr&gt;</code></pre>
<p>If this option is not present then the migration destination address is the address for Sapling account 0, with the default diversifier<a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</p>
<p>The state variable can also be set for a running node using the following RPC method:</p>
<pre><code>z_setmigration true/false</code></pre>
<p>It is intentional that the only option associated with the migration is the destination z-address. Other options could potentially distinguish users.</p>
<p>Nodes MUST also support the following RPC call to return the current status of the migration:</p>
<pre><code>z_getmigrationstatus</code></pre>
<p>Returns:</p>
<pre><code>{
&quot;enabled&quot;: true|false,
&quot;destination_address&quot;: &quot;zaddr&quot;,
&quot;unmigrated_amount&quot;: nnn.n,
&quot;unfinalized_migrated_amount&quot;: nnn.n,
&quot;finalized_migrated_amount&quot;: nnn.n,
&quot;finalized_migration_transactions&quot;: nnn,
&quot;time_started&quot;: ttt, // Unix timestamp
&quot;migration_txids&quot;: [txids]
}</code></pre>
<p>The <code>destination_address</code> field MAY be omitted if the <code>-migrationaddress</code> parameter is not set and no default address has yet been generated.</p>
<p>The values of <code>unmigrated_amount</code> and <code>migrated_amount</code> MUST take into account failed transactions, that were not mined within their expiration height.</p>
<p>The values of <code>unfinalized_migrated_amount</code> and <code>finalized_migrated_amount</code> are the total amounts sent to the Sapling destination address in migration transactions, excluding fees.</p>
<p><code>migration_txids</code> is a list of strings representing transaction IDs of all known migration transactions involving this wallet, as lowercase hexadecimal in RPC byte order. A given transaction is defined as a migration transaction iff it has:</p>
<ul>
<li>one or more Sprout JoinSplits with nonzero <code>vpub_new</code> field; and</li>
<li>no Sapling Spends, and;</li>
<li>one or more Sapling Outputs.</li>
</ul>
<p>Note: it is possible that manually created transactions involving this wallet will be recognized as migration transactions and included in <code>migration_txids</code>.</p>
<p>The value of <code>time_started</code> is the earliest Unix timestamp of any known migration transaction involving this wallet; if there is no such transaction, then the field is absent.</p>
<p>A transaction is <code>finalized</code> iff it has at least 10 confirmations. TODO: subject to change, if the recommended number of confirmations changes.</p>
<h1 id="support-in-zcashd">Support in zcashd</h1>
<p>The following PRs implement this specification:</p>
<ul>
<li><a href="https://github.com/zcash/zcash/pull/3848" class="uri">https://github.com/zcash/zcash/pull/3848</a> (TransactionBuilder support)</li>
<li><a href="https://github.com/zcash/zcash/pull/3888" class="uri">https://github.com/zcash/zcash/pull/3888</a> (main RPC)</li>
<li><a href="https://github.com/zcash/zcash/pull/3967" class="uri">https://github.com/zcash/zcash/pull/3967</a> (config options)</li>
<li><a href="https://github.com/zcash/zcash/pull/3973" class="uri">https://github.com/zcash/zcash/pull/3973</a> (getmigrationstatus RPC)</li>
<li><a href="https://github.com/zcash/zcash/pull/3977" class="uri">https://github.com/zcash/zcash/pull/3977</a> (bugfix)</li>
<li><a href="https://github.com/zcash/zcash/pull/3987" class="uri">https://github.com/zcash/zcash/pull/3987</a> (bugfix)</li>
<li><a href="https://github.com/zcash/zcash/pull/3990" class="uri">https://github.com/zcash/zcash/pull/3990</a> (bugfix)</li>
<li><a href="https://github.com/zcash/zcash/pull/3995" class="uri">https://github.com/zcash/zcash/pull/3995</a> (don't migrate in initial block download/after wakeup)</li>
<li><a href="https://github.com/zcash/zcash/pull/3997" class="uri">https://github.com/zcash/zcash/pull/3997</a> (bugfix)</li>
<li><a href="https://github.com/zcash/zcash/pull/4002" class="uri">https://github.com/zcash/zcash/pull/4002</a> (minor RPC improvements)</li>
<li><a href="https://github.com/zcash/zcash/pull/4005" class="uri">https://github.com/zcash/zcash/pull/4005</a> (change expiry for migration transactions)</li>
</ul>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/zip-0205.rst">ZIP 205: Deployment of the Sapling Network Upgrade</a><a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version 2018.0-beta-33 [Overwinter+Sapling]; sections 3.4, 4.11 and 4.12</a><a href="#fnref3" class="footnote-back"></a></p></li>
<li id="fn4"><p><a href="https://github.com/daira/zcash-migration">Sprout -&gt; Sapling migration simulation</a><a href="#fnref4" class="footnote-back"></a></p></li>
<li id="fn5"><p><a href="https://github.com/zcash/zips/blob/master/zip-0032.rst">ZIP 32: Shielded Hierarchical Deterministic Wallets</a><a href="#fnref5" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,424 +0,0 @@
ZIP: 308
Title: Sprout to Sapling Migration
Owners: Daira Hopwood <daira@electriccoin.co>
Eirik Ogilvie-Wigley <eirik@electriccoin.co>
Status: Final
Category: RPC/Wallet
Created: 2018-11-27
License: MIT
Terminology
===========
The key words \"MUST\", \"MUST NOT\", \"SHOULD\", and \"MAY\" in this
document are to be interpreted as described in RFC 2119.[^1]
The terms below are to be interpreted as follows:
Sprout protocol
: Code-name for the Zcash shielded protocol at launch.
Sapling protocol
: Code-name for the Zcash shielded protocol added by the second Zcash
network upgrade, also known as Network Upgrade 1.
Abstract
========
This proposal describes privacy-preserving procedures to migrate funds
from Sprout to Sapling z-addresses; and supporting RPC operations to
enable, disable, and monitor the migration process.
Motivation
==========
Zcash Sapling[^2] introduces significant efficiency improvements
relative to the previous iteration of the Zcash shielded protocol,
Sprout. These improvements will pave the way for broad mobile, exchange
and vendor adoption of shielded addresses.
Therefore, we anticipate that users will want to migrate all their
shielded funds from Sprout to Sapling.
The Zcash consensus rules prohibit direct transfers from Sprout to
Sapling z-addresses, unless the amount is revealed by sending it through
the \"transparent value pool\"[^3]. The primary motivation for this is
to allow detection of any overall inflation of the Zcash monetary base,
due to exploitation of possible vulnerabilities in the shielded
protocols or their implementation, or a compromise of the Sprout
multi-party computation. (It is not necessary for Sprout -\> Sapling
transfers to go via a t-address.)
Since the exposure of the migrated amount potentially compromises the
privacy of users, we wish to define a way to perform the migration that
mitigates this privacy leak as far as possible. This can be done by
hiding individual migration transactions among those of all users that
are doing the migration at around the same time.
The security analysis of migration strategies is quite subtle; the more
obvious potential strategies can leak a lot of information.
Requirements
============
Migration is performed \"in the background\" by a `zcashd` (or
equivalent) node. It does not significantly interfere with concurrent
usage of the node, other than possibly increasing the latency of some
other shielded operations.
It is possible to enable or disable migration at any time.
All shielded funds in Sprout z-addresses will eventually be transferred
to Sapling z-addresses, provided the node is working.
It should take a \"reasonable\" length of time to complete the transfer;
less than a month for amounts up to 1000 ZEC.
The design should mitigate information leakage via timing information
and transaction data, including
- linkage of particular z-addresses or users, and the amounts held;
- information about the distribution of amounts of individual notes.
The design and implementation is stateless, to the extent practical.
Visibility is provided for the wallet/node user into the progress of the
migration.
There is sufficient information available to debug failed transactions
that are part of the migration.
The design recovers from failed operations to the extent possible.
The total amount sent by each user is obscured, to the extent practical.
Non-requirements
================
There is no requirement or assumption of network layer anonymity. (Users
may, but are not expected to, configure Tor.)
The migration procedure does not have to provably leak no information.
There is no need to preserve individual note values (i.e. notes can be
consolidated).
Migration txns need only be hidden among themselves, rather than among
all kinds of transaction.
A small amount (less than 0.01 ZEC) can be left unmigrated if this helps
with privacy.
It is not required to support the case of single wallet being used by
multiple users whose funds should be kept distinct.
Specification
=============
There are two main aspects to a strategy for selecting migration
transactions:
- how many transactions are sent, and when;
- the amount sent in each transaction.
Transaction schedule
--------------------
When migration is enabled, a node will send up to 5 transactions for
inclusion in each block with height a multiple of 500 (that is, they are
sent immediately after seeing a block with height 499, modulo 500). Up
to the limit of 5, as many transactions are sent as are needed to
migrate the remaining funds (possibly with a remainder less than 0.01
ZEC left unmigrated).
Nodes SHOULD NOT send migration transactions during initial block
download, or if the timestamp of the triggering block (with height 499,
modulo 500) is more than three hours in the past according to the
node\'s adjusted local clock.
TODO: if we change the target block interval, 500 might need to be
changed.
The migration transactions to be sent in a particular batch can take
significant time to generate, and this time depends on the speed of the
user\'s computer. If they were generated only after a block is seen at
the target height minus 1, then this could leak information. Therefore,
for target height N, implementations SHOULD start generating the
transactions at around height N-5 (provided that block\'s timestamp is
not more than three hours in the past). Each migration transaction
SHOULD specify an anchor at height N-10 for each Sprout JoinSplit
description.
Open questions:
- does this reliably give sufficient time to generate the
transactions?
- what happens to a batch if the anchor is invalidated \-- should it
be regenerated, or cancelled?
### Rationale for transaction schedule
Privacy is increased when the times at which to send transactions are
coordinated between nodes. We choose to send a batch of transactions at
each coordinated time. Sending multiple transactions in each batch
ensures that:
- less information about balances is leaked;
- it is easier to finish in a reasonable length of time.
The choice of 500 blocks as the batch interval ensures that each batch
occurs at a different time of day, which may help to mitigate problems
with the availability of nodes being correlated with the local
time-of-day.
Simulation shows that the migration process will typically complete
reasonably quickly even if the amount to be migrated is large:
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| \| Time in days to complete migration \| \| Amount
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| \| 10th-percentile \| median \| 90th-percentile \|
+===========+=================+========+=================+ \| 1 ZEC\|
1.01 \| 1.50 \| 2.33 \|
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| 10 ZEC\| 1.65 \| 2.46 \| 3.45 \|
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| 100 ZEC\| 2.54 \| 3.99 \| 5.83 \|
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| 1000 ZEC\| 9.86 \| 12.52 \| 15.54 \|
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
\| 10000 ZEC\| 89.23 \| 97.01 \| 105.05 \|
+\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
The simulation also depends on the amounts sent as specified in the next
section. It includes the time spent waiting for the first batch to be
sent.
The code used for this simulation is at[^4].
How much to send in each transaction
------------------------------------
If the remaining amount to be migrated is less than 0.01 ZEC, end the
migration.
Otherwise, the amount to send in each transaction is chosen according to
the following distribution:
1. Choose an integer exponent uniformly in the range 6 to 8 inclusive.
2. Choose an integer mantissa uniformly in the range 1 to 99 inclusive.
3. Calculate amount := (mantissa \* 10^exponent^) zatoshi.
4. If amount is greater than the amount remaining to send, repeat from
step 1.
Implementations MAY optimize this procedure by selecting the exponent
and mantissa based on the amount remaining to avoid repetition, but the
resulting distribution MUST be identical.
The amount chosen *includes* the 0.0001 ZEC fee for this transaction,
i.e. the value of the Sapling output will be 0.0001 ZEC less.
### Rationale for how much to send
Suppose that a user has an amount to migrate that is a round number of
ZEC. Then, a potential attack would be to find some subset of all the
migration transactions that sum to a round number of ZEC, and infer that
all of those transactions are from the same user. If amounts sent were a
random multiple of 1 zatoshi, then the resulting knapsack problem would
be likely to have a unique solution and be practically solvable for the
number of transactions involved. The chosen distribution of transaction
amounts mitigates this potential vulnerability by ensuring that there
will be many solutions for sets of transactions, including \"incorrect\"
solutions (that is, solutions that mix transactions from different
users, contrary to the supposed adversary\'s inference).
Making the chosen amount inclusive of the fee avoids leaving any
unmigrated funds at the end, in the case where the original amount to
migrate was a multiple of 0.01 ZEC.
Other design decisions
----------------------
We assume use of the normal wallet note selection algorithm and change
handling. Change is sent back to the default address, which is the
z-address of the first selected Sprout note. The number of JoinSplits
will therefore be the same as for a normal transaction sending the same
amount with the same wallet state. Only the `vpub_new` of the last
JoinSplit will be nonzero. There will always be exactly one Sapling
Output.
The expiry delta for migration transactions MUST be 450 blocks. Since
these transactions are sent when the block height is 499 modulo 500,
their expiry height will be 451 blocks later, i.e. `nExpiryHeight` will
be 450 modulo 500.
The fee for each migration transaction MUST be 0.0001 ZEC. This fee is
taken from the funds to be migrated.
Some wallets by default add a \"developer fee\" to each transaction,
directed to the developer(s) of the wallet. This is typically
implemented by adding the developer address as an explicit output, so if
migration transactions are generated internally by `zcashd`, they will
not include the developer fee. We strongly recommend *not* patching the
`zcashd` code to add the developer fee output to migration transactions,
because doing so partitions the anonymity set between users of that
wallet and other users.
There MUST NOT be any transparent inputs or outputs, or Sapling Spends,
in a migration transaction.
The `lock_time` field MUST be set to 0 (unused).
When creating Sapling shielded Outputs, the outgoing viewing key `ovk`
SHOULD be chosen in the same way as for a transfer sent from a
t-address.
A node SHOULD treat migration transactions in the same way as
transactions submitted over the RPC interface.
Open questions
--------------
The above strategy has several \"magic number\" parameters:
- the interval between batches (500 blocks)
- the maximum number of transactions in a batch (5)
- the distribution of exponents (uniform integer in 6..8)
- the distribution of mantissae (uniform integer in 1..99).
These have been chosen by guesswork. Should we change any of them?
In particular, if the amount to migrate is large, then this strategy can
result in fairly large amounts (up to 99 ZEC, worth USD \~6700 at time
of writing) transferred in each transaction. This leaks the fact that
the transaction was sent by a user who has at least that amount.
The strategy does not migrate any remaining fractional amount less than
0.01 ZEC (worth USD \~0.68 at time of writing). Is this reasonable?
In deciding the amount to send in each transaction, the strategy does
not take account of the values of individual Sprout notes, only the
total amount remaining to migrate. Can a strategy that is sensitive to
individual note values improve privacy?
An adversary may attempt to interfere with the view of the block chain
seen by a subset of nodes that are performing migrations, in order to
cause those nodes to send migration batches at a different time, so that
they may be distinguished. Is there anything further we can do to
mitigate this vulnerability?
RPC calls
---------
Nodes MUST maintain a boolean state variable during their execution, to
determine whether migration is enabled. The default when a node starts,
is set by a configuration option:
-migration=0/1
The destination z-address can optionally be set by another option:
-migrationdestaddress=<zaddr>
If this option is not present then the migration destination address is
the address for Sapling account 0, with the default diversifier[^5].
The state variable can also be set for a running node using the
following RPC method:
z_setmigration true/false
It is intentional that the only option associated with the migration is
the destination z-address. Other options could potentially distinguish
users.
Nodes MUST also support the following RPC call to return the current
status of the migration:
z_getmigrationstatus
Returns:
{
"enabled": true|false,
"destination_address": "zaddr",
"unmigrated_amount": nnn.n,
"unfinalized_migrated_amount": nnn.n,
"finalized_migrated_amount": nnn.n,
"finalized_migration_transactions": nnn,
"time_started": ttt, // Unix timestamp
"migration_txids": [txids]
}
The `destination_address` field MAY be omitted if the
`-migrationaddress` parameter is not set and no default address has yet
been generated.
The values of `unmigrated_amount` and `migrated_amount` MUST take into
account failed transactions, that were not mined within their expiration
height.
The values of `unfinalized_migrated_amount` and
`finalized_migrated_amount` are the total amounts sent to the Sapling
destination address in migration transactions, excluding fees.
`migration_txids` is a list of strings representing transaction IDs of
all known migration transactions involving this wallet, as lowercase
hexadecimal in RPC byte order. A given transaction is defined as a
migration transaction iff it has:
- one or more Sprout JoinSplits with nonzero `vpub_new` field; and
- no Sapling Spends, and;
- one or more Sapling Outputs.
Note: it is possible that manually created transactions involving this
wallet will be recognized as migration transactions and included in
`migration_txids`.
The value of `time_started` is the earliest Unix timestamp of any known
migration transaction involving this wallet; if there is no such
transaction, then the field is absent.
A transaction is `finalized` iff it has at least 10 confirmations. TODO:
subject to change, if the recommended number of confirmations changes.
Support in zcashd
=================
The following PRs implement this specification:
- <https://github.com/zcash/zcash/pull/3848> (TransactionBuilder
support)
- <https://github.com/zcash/zcash/pull/3888> (main RPC)
- <https://github.com/zcash/zcash/pull/3967> (config options)
- <https://github.com/zcash/zcash/pull/3973> (getmigrationstatus RPC)
- <https://github.com/zcash/zcash/pull/3977> (bugfix)
- <https://github.com/zcash/zcash/pull/3987> (bugfix)
- <https://github.com/zcash/zcash/pull/3990> (bugfix)
- <https://github.com/zcash/zcash/pull/3995> (don\'t migrate in
initial block download/after wakeup)
- <https://github.com/zcash/zcash/pull/3997> (bugfix)
- <https://github.com/zcash/zcash/pull/4002> (minor RPC improvements)
- <https://github.com/zcash/zcash/pull/4005> (change expiry for
migration transactions)
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [ZIP 205: Deployment of the Sapling Network
Upgrade](https://github.com/zcash/zips/blob/master/zip-0205.rst)
[^3]: [Zcash Protocol Specification, Version 2018.0-beta-33
\[Overwinter+Sapling\]; sections 3.4, 4.11 and
4.12](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)
[^4]: [Sprout -\> Sapling migration
simulation](https://github.com/daira/zcash-migration)
[^5]: [ZIP 32: Shielded Hierarchical Deterministic
Wallets](https://github.com/zcash/zips/blob/master/zip-0032.rst)

81
zip-guide.html Normal file
View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zip-guide</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
</head>
<body>
<pre><code>ZIP: Unassigned {numbers are assigned by ZIP editors}
Title: {Something Short and To the Point}
Owners: First Owner &lt;email&gt;
...
Credits: First Credited &lt;optional email&gt;
...
Status: Draft
Category: {Consensus | Standards Track | Network | RPC | Wallet | Informational | Process}
Created: yyyy-mm-dd
License: {usually MIT}</code></pre>
<h1 id="dont-panic">Don't Panic</h1>
<p>If this is your first time writing a ZIP, the structure and format may look intimidating. But really, it's just meant to reflect common-sense practice and some technical conventions. Feel free to start with a simple initial draft that gets ideas across, even if it doesn't quite follow this format. The community and ZIP editors will help you figure things out and get it into shape later.</p>
<p>{Delete this section.}</p>
<h1 id="terminology">Terminology</h1>
<p>{Edit this to reflect the key words that are actually used.} The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>{Term to be defined}</dt>
<dd><p>{Definition.}</p>
</dd>
<dt>{Another term}</dt>
<dd><p>{Definition.}</p>
</dd>
</dl>
<h1 id="abstract">Abstract</h1>
<p>{Describe what this proposal does, typically in a few paragraphs.}</p>
<p>{Use links where applicable, e.g.<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a>.}</p>
<h1 id="motivation">Motivation</h1>
<p>{Why is this proposal needed?</p>
<p>This is one of the most important sections of the ZIP, and should be detailed and comprehensive. It shouldn't include any of the actual specification --don't put conformance requirements in this section.</p>
<p>Explain the status quo, why the status quo is in need of improvement, and if applicable, the history of how this area has changed. Then describe <em>at a high level</em> why this proposed solution addresses the perceived issues. It is ok if this is somewhat redundant with the abstract, but here you can go into a lot more detail.}</p>
<h1 id="requirements">Requirements</h1>
<p>{Describe design constraints on, or goals for the solution -- typically one paragraph for each constraint or goal. Again, don't actually specify anything here; this section is primarily for use as a consistency check that what is specified meets the requirements.}</p>
<h1 id="non-requirements">Non-requirements</h1>
<p>{This section is entirely optional. If it is present, it describes issues that the proposal is <em>not</em> attempting to address, that someone might otherwise think it does or should.}</p>
<h1 id="specification">Specification</h1>
<p>{This section describes what should change, using precise language and conformance key words. Anything that is <em>required in order to implement the ZIP</em> (or follow its process, in the case of a Process ZIP) should be in this section.</p>
<p>Avoid overspecification! Also avoid underspecification. Specification is hard. Don't be afraid to ask for help.</p>
<p>Unless the specification is particularly simple, you will need to organise it under subheadings.}</p>
<h2 id="example-subheading">Example subheading</h2>
<p>{At least while the ZIP is in Draft, we encourage writing open questions and TODOs.}</p>
<h3 id="open-questions">Open questions</h3>
<ul>
<li>What happens if a full node can't parse the fandangle as a doohicky?</li>
</ul>
<p>TODO: define byte encoding for the Jabberwock.</p>
<p>{Feel free to copy from other ZIPs doing similar things, e.g. defining RPC calls, consensus rules, etc.}</p>
<h2 id="valid-restructuredtext">Valid reStructuredText</h2>
<p>This is optional before publishing a PR, but to check whether a document is valid reStructuredText, first install rst2html5:</p>
<pre><code>sudo apt-get install python-pip
sudo pip install rst2html5</code></pre>
<p>and then run:</p>
<pre><code>rst2html5 -v zip-xxxx.rst &gt;zip-xxxx.html</code></pre>
<p>and view <code>zip-xxxx.html</code> in a web browser.</p>
<h1 id="reference-implementation">Reference implementation</h1>
<p>{This section is entirely optional; if present, it usually gives links to zcashd or zebrad PRs.}</p>
<h1 id="references">References</h1>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p><a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a><a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p><a href="https://github.com/zcash/zips/blob/master/protocol/protocol.pdf">Zcash Protocol Specification, Version {...} or later [Overwinter+Sapling+Blossom]</a><a href="#fnref2" class="footnote-back"></a></p></li>
</ol>
</section>
</body>
</html>

View File

@ -1,136 +0,0 @@
ZIP: Unassigned {numbers are assigned by ZIP editors}
Title: {Something Short and To the Point}
Owners: First Owner <email>
...
Credits: First Credited <optional email>
...
Status: Draft
Category: {Consensus | Standards Track | Network | RPC | Wallet | Informational | Process}
Created: yyyy-mm-dd
License: {usually MIT}
Don\'t Panic
============
If this is your first time writing a ZIP, the structure and format may
look intimidating. But really, it\'s just meant to reflect common-sense
practice and some technical conventions. Feel free to start with a
simple initial draft that gets ideas across, even if it doesn\'t quite
follow this format. The community and ZIP editors will help you figure
things out and get it into shape later.
{Delete this section.}
Terminology
===========
{Edit this to reflect the key words that are actually used.} The key
words \"MUST\", \"MUST NOT\", \"SHOULD\", and \"MAY\" in this document
are to be interpreted as described in RFC 2119.[^1]
The terms below are to be interpreted as follows:
{Term to be defined}
: {Definition.}
{Another term}
: {Definition.}
Abstract
========
{Describe what this proposal does, typically in a few paragraphs.}
{Use links where applicable, e.g.[^2].}
Motivation
==========
{Why is this proposal needed?
This is one of the most important sections of the ZIP, and should be
detailed and comprehensive. It shouldn\'t include any of the actual
specification \--don\'t put conformance requirements in this section.
Explain the status quo, why the status quo is in need of improvement,
and if applicable, the history of how this area has changed. Then
describe *at a high level* why this proposed solution addresses the
perceived issues. It is ok if this is somewhat redundant with the
abstract, but here you can go into a lot more detail.}
Requirements
============
{Describe design constraints on, or goals for the solution \-- typically
one paragraph for each constraint or goal. Again, don\'t actually
specify anything here; this section is primarily for use as a
consistency check that what is specified meets the requirements.}
Non-requirements
================
{This section is entirely optional. If it is present, it describes
issues that the proposal is *not* attempting to address, that someone
might otherwise think it does or should.}
Specification
=============
{This section describes what should change, using precise language and
conformance key words. Anything that is *required in order to implement
the ZIP* (or follow its process, in the case of a Process ZIP) should be
in this section.
Avoid overspecification! Also avoid underspecification. Specification is
hard. Don\'t be afraid to ask for help.
Unless the specification is particularly simple, you will need to
organise it under subheadings.}
Example subheading
------------------
{At least while the ZIP is in Draft, we encourage writing open questions
and TODOs.}
### Open questions
- What happens if a full node can\'t parse the fandangle as a
doohicky?
TODO: define byte encoding for the Jabberwock.
{Feel free to copy from other ZIPs doing similar things, e.g. defining
RPC calls, consensus rules, etc.}
Valid reStructuredText
----------------------
This is optional before publishing a PR, but to check whether a document
is valid reStructuredText, first install rst2html5:
sudo apt-get install python-pip
sudo pip install rst2html5
and then run:
rst2html5 -v zip-xxxx.rst >zip-xxxx.html
and view `zip-xxxx.html` in a web browser.
Reference implementation
========================
{This section is entirely optional; if present, it usually gives links
to zcashd or zebrad PRs.}
References
==========
[^1]: [Key words for use in RFCs to Indicate Requirement
Levels](https://tools.ietf.org/html/rfc2119)
[^2]: [Zcash Protocol Specification, Version {\...} or later
\[Overwinter+Sapling+Blossom\]](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf)