Reintroduce ZIP 207.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2020-03-10 21:49:18 +00:00
parent 3fc7a9a2b8
commit 811fb7e0ce
5 changed files with 348 additions and 612 deletions

View File

@ -57,7 +57,7 @@ Index of ZIPs
<tr> <td>203</td> <td class="left"><a href="zip-0203.rst">Transaction Expiry</a></td> <td>Final</td> <tr> <td>203</td> <td class="left"><a href="zip-0203.rst">Transaction Expiry</a></td> <td>Final</td>
<tr> <td>205</td> <td class="left"><a href="zip-0205.rst">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td> <tr> <td>205</td> <td class="left"><a href="zip-0205.rst">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td>
<tr> <td>206</td> <td class="left"><a href="zip-0206.rst">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td> <tr> <td>206</td> <td class="left"><a href="zip-0206.rst">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td>
<tr> <td><strike>207</strike></td> <td class="left"><strike><a href="zip-0207.rst">Split Founders' Reward</a></strike></td> <td>Withdrawn</td> <tr> <td>207</td> <td class="left"><a href="zip-0207.rst">Funding Streams</a></td> <td>Draft</td>
<tr> <td>208</td> <td class="left"><a href="zip-0208.rst">Shorter Block Target Spacing</a></td> <td>Final</td> <tr> <td>208</td> <td class="left"><a href="zip-0208.rst">Shorter Block Target Spacing</a></td> <td>Final</td>
<tr> <td>209</td> <td class="left"><a href="zip-0209.rst">Prohibit Negative Shielded Value Pool</a></td> <td>Final</td> <tr> <td>209</td> <td class="left"><a href="zip-0209.rst">Prohibit Negative Shielded Value Pool</a></td> <td>Final</td>
<tr> <td>210</td> <td class="left"><a href="zip-0210.rst">Sapling Anchor Deduplication within Transactions</a></td> <td>Draft</td> <tr> <td>210</td> <td class="left"><a href="zip-0210.rst">Sapling Anchor Deduplication within Transactions</a></td> <td>Draft</td>

View File

@ -255,7 +255,7 @@ td:first-child {
width: 920px; width: 920px;
} }
pre, div.math, table { pre, div.math, table {
font-size: 0.9375rem; font-size: 0.85rem;
} }
} }

View File

@ -36,7 +36,7 @@
<tr> <td>203</td> <td class="left"><a href="zip-0203">Transaction Expiry</a></td> <td>Final</td> <tr> <td>203</td> <td class="left"><a href="zip-0203">Transaction Expiry</a></td> <td>Final</td>
<tr> <td>205</td> <td class="left"><a href="zip-0205">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td> <tr> <td>205</td> <td class="left"><a href="zip-0205">Deployment of the Sapling Network Upgrade</a></td> <td>Final</td>
<tr> <td>206</td> <td class="left"><a href="zip-0206">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td> <tr> <td>206</td> <td class="left"><a href="zip-0206">Deployment of the Blossom Network Upgrade</a></td> <td>Final</td>
<tr> <td><strike>207</strike></td> <td class="left"><strike><a href="zip-0207">Split Founders' Reward</a></strike></td> <td>Withdrawn</td> <tr> <td>207</td> <td class="left"><a href="zip-0207">Funding Streams</a></td> <td>Draft</td>
<tr> <td>208</td> <td class="left"><a href="zip-0208">Shorter Block Target Spacing</a></td> <td>Final</td> <tr> <td>208</td> <td class="left"><a href="zip-0208">Shorter Block Target Spacing</a></td> <td>Final</td>
<tr> <td>209</td> <td class="left"><a href="zip-0209">Prohibit Negative Shielded Value Pool</a></td> <td>Final</td> <tr> <td>209</td> <td class="left"><a href="zip-0209">Prohibit Negative Shielded Value Pool</a></td> <td>Final</td>
<tr> <td>210</td> <td class="left"><a href="zip-0210">Sapling Anchor Deduplication within Transactions</a></td> <td>Draft</td> <tr> <td>210</td> <td class="left"><a href="zip-0210">Sapling Anchor Deduplication within Transactions</a></td> <td>Draft</td>

View File

@ -1,52 +1,70 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>ZIP 207: Split Founders' Reward</title> <title>ZIP 207: Funding Streams</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head> <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head>
<body> <body>
<section> <section>
<pre>ZIP: 207 <pre>ZIP: 207
Title: Split Founders' Reward Title: Funding Streams
Owners: Jack Grigg &lt;str4d@electriccoin.co&gt; Owners: Jack Grigg &lt;str4d@electriccoin.co&gt;
Daira Hopwood &lt;daira@electriccoin.co&gt;
Category: Consensus Category: Consensus
Status: Withdrawn Status: Draft
Created: 2019-01-04 Created: 2019-01-04
License: MIT</pre> License: MIT</pre>
<section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a href="#terminology"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a href="#terminology"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The key words "MUST", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. <a id="id1" class="footnote_reference" href="#rfc2119">1</a></p> <p>The key words "MUST", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. <a id="id1" class="footnote_reference" href="#rfc2119">1</a></p>
<p>The terms "block subsidy" and "halving" in this document are to be interpreted as described in sections 3.9 and 7.7 of the Zcash Protocol Specification. <a id="id2" class="footnote_reference" href="#protocol-subsidyconcepts">3</a> <a id="id3" class="footnote_reference" href="#protocol-subsidies">5</a></p>
<p>The terms below are to be interpreted as follows:</p>
<dl>
<dt>${NU4}</dt>
<dd>Code-name for the fifth Zcash network upgrade, also known as Network Upgrade 4.</dd>
<dt>Testnet</dt>
<dd>The Zcash test network, as defined in the Zcash Protocol Specification. <a id="id4" class="footnote_reference" href="#protocol">2</a></dd>
<dt>Mainnet</dt>
<dd>The Zcash production network, as defined in the Zcash Protocol Specification. <a id="id5" class="footnote_reference" href="#protocol">2</a></dd>
</dl>
</section> </section>
<section id="abstract"><h2><span class="section-heading">Abstract</span><span class="section-anchor"> <a href="#abstract"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="abstract"><h2><span class="section-heading">Abstract</span><span class="section-anchor"> <a href="#abstract"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<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> <p>This proposal specifies a mechanism to support funding streams, distributed from a portion of the block subsidy for a specified range of block heights.</p>
<p>This is intended as a means of implementing the Zcash Development Fund, using the funding stream definitions specified in ZIP 214 <a id="id6" class="footnote_reference" href="#zip-0214">10</a>. It should be read in conjunction with ZIP 1014 <a id="id7" class="footnote_reference" href="#zip-1014">12</a>, which describes the high-level requirements for that fund.</p>
</section> </section>
<section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a href="#motivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a href="#motivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<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 id="id2" class="footnote_reference" href="#block-subsidy">2</a> This funding stream is referred to as the Founders' Reward.</p> <p>Motivation for the Zcash Development Fund is considered in ZIP 1014 <a id="id8" class="footnote_reference" href="#zip-1014">12</a>.</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 id="id3" class="footnote_reference" href="#continued-funding">3</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> <p>This ZIP 207 was originally proposed for the Blossom network upgrade, as a means of splitting the original Founders' Reward into several streams. It was then withdrawn when such splitting was judged to be unnecessary at the consensus level. Since the capabilities of the funding stream mechanism match the requirements for the Zcash Development Fund, the ZIP is being reintroduced for that purpose in order to reuse specification, analysis, and implementation effort.</p>
</section>
<section id="requirements"><h2><span class="section-heading">Requirements</span><span class="section-anchor"> <a href="#requirements"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The primary requirement of this ZIP is to provide a mechanism for specifying the funding streams that are used in ZIP 214 [#zip-0214] to implement the Zcash Development Fund. It should be sufficiently expressive to handle both the main three "slices" (ECC, ZF, and MG) defined in ZIP 1014 <a id="id9" class="footnote_reference" href="#zip-1014">12</a>, and also (with additional funding stream definitions) the "direct grant option" described in that ZIP.</p>
<p>As for the original Founders' Reward, addresses for a given funding stream are changed on a roughly-monthly basis, so that keys that are not yet needed may be kept off-line as a security measure.</p>
</section> </section>
<section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a href="#specification"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a href="#specification"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="definitions"><h3><span class="section-heading">Definitions</span><span class="section-anchor"> <a href="#definitions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> <section id="definitions"><h3><span class="section-heading">Definitions</span><span class="section-anchor"> <a href="#definitions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>We use the following constants and functions defined in <a id="id4" class="footnote_reference" href="#zip-0208">4</a>:</p> <p>We use the following constants and functions defined in <a id="id10" class="footnote_reference" href="#protocol-constants">4</a>, <a id="id11" class="footnote_reference" href="#protocol-subsidies">5</a>, and <a id="id12" class="footnote_reference" href="#protocol-foundersreward">6</a>:</p>
<ul> <ul>
<li><code>BlossomActivationHeight</code></li> <li><code>BlossomActivationHeight</code></li>
<li><code>PostBlossomHalvingInterval</code></li> <li><code>PostBlossomHalvingInterval</code></li>
<li><code>Halving(height)</code></li> <li><code>Halving(height)</code></li>
<li><code>BlockSubsidy(height)</code></li>
<li><code>RedeemScriptHash(height)</code>.</li>
</ul> </ul>
<p>We also define the following constants and functions:</p> <p>We also define the following function:</p>
<ul> <ul>
<li><code>SlowStartShift</code> as-defined in <a id="id5" class="footnote_reference" href="#block-subsidy">2</a>.</li>
<li><code>HeightForHalving(halving)</code>: Smallest <code>height</code> such that <code>Halving(height) = halving</code></li> <li><code>HeightForHalving(halving)</code>: Smallest <code>height</code> such that <code>Halving(height) = halving</code></li>
</ul> </ul>
</section> </section>
<section id="funding-streams"><h3><span class="section-heading">Funding streams</span><span class="section-anchor"> <a href="#funding-streams"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> <section id="funding-streams"><h3><span class="section-heading">Funding streams</span><span class="section-anchor"> <a href="#funding-streams"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<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>A funding stream is defined by a block subsidy 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 id="id6" class="footnote_reference" href="#zip-0208">4</a>).</p> <p>By defining the issuance as a proportion of the total block subsidy, rather than absolute zatoshis, this ZIP dovetails with any changes to both block target spacing and issuance-per-block rates, while maintaining an unchanged target-time-based issuance schedule. Such a target-time / issuance rate change occurred at the Blossom network upgrade, for example. <a id="id13" class="footnote_reference" href="#zip-0208">8</a></p>
<p>The value of a funding stream at a given block height is defined as:</p> <p>The value of a funding stream at a given block height is defined as:</p>
<pre>FundingStream[FUND].Value(height) = <pre>FundingStream[FUND].Value(height) =
floor(( floor((
BlockReward(height) * FundingStream[FUND].ValueNumerator BlockSubsidy(height) * FundingStream[FUND].ValueNumerator
) / FundingStream[FUND].ValueDenominator)</pre> ) / FundingStream[FUND].ValueDenominator)</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>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> <p>Each funding stream has an associated sequence of recipient addresses, each of which MUST be either a transparent P2SH address or a Sapling address.</p>
<p>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>AddressChangeInterval = PostBlossomHalvingInterval / 48 <pre>AddressChangeInterval = PostBlossomHalvingInterval / 48
AddressPeriod(height) = AddressPeriod(height) =
floor(( floor((
@ -57,311 +75,116 @@ FundingStream[FUND].AddressIndex(height) =
Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex(height)]</pre> Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex(height)]</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>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> <p>Below is a visual representation of how stream addresses align with funding periods:</p>
<table> <blockquote>
<thead> <table>
<tr> <thead>
<th>Example height</th> <tr>
<th>Stream A</th> <th>Example height</th>
<th>Stream B</th> <th>Stream A</th>
<th>Stream C</th> <th>Stream B</th>
</tr> <th>Stream C</th>
</thead> </tr>
<tbody> </thead>
<tr> <tbody>
<td><code>AddressChangeInterval - 2</code></td> <tr>
<td>A0</td> <td><code>AddressChangeInterval - 2</code></td>
<td></td> <td>A0</td>
<td></td> <td></td>
</tr> <td></td>
<tr> </tr>
<td><code>AddressChangeInterval - 1</code></td> <tr>
<td>A0</td> <td><code>AddressChangeInterval - 1</code></td>
<td></td> <td>A0</td>
<td></td> <td></td>
</tr> <td></td>
<tr> </tr>
<td><code>AddressChangeInterval</code></td> <tr>
<td>A1</td> <td><code>AddressChangeInterval</code></td>
<td>B0</td> <td>A1</td>
<td>C0</td> <td>B0</td>
</tr> <td>C0</td>
<tr> </tr>
<td><code>AddressChangeInterval + 1</code></td> <tr>
<td>A1</td> <td><code>AddressChangeInterval + 1</code></td>
<td>B0</td> <td>A1</td>
<td>C0</td> <td>B0</td>
</tr> <td>C0</td>
<tr> </tr>
<td>...</td> <tr>
<td></td> <td>...</td>
<td></td> <td></td>
<td></td> <td></td>
</tr> <td></td>
<tr> </tr>
<td><code>2*AddressChangeInterval - 2</code></td> <tr>
<td>A1</td> <td><code>2*AddressChangeInterval - 2</code></td>
<td>B0</td> <td>A1</td>
<td>C0</td> <td>B0</td>
</tr> <td>C0</td>
<tr> </tr>
<td><code>2*AddressChangeInterval - 1</code></td> <tr>
<td>A1</td> <td><code>2*AddressChangeInterval - 1</code></td>
<td>B0</td> <td>A1</td>
<td>C0</td> <td>B0</td>
</tr> <td>C0</td>
<tr> </tr>
<td><code>2*AddressChangeInterval</code></td> <tr>
<td>A2</td> <td><code>2*AddressChangeInterval</code></td>
<td></td> <td>A2</td>
<td>C1</td> <td></td>
</tr> <td>C1</td>
<tr> </tr>
<td><code>2*AddressChangeInterval + 1</code></td> <tr>
<td>A2</td> <td><code>2*AddressChangeInterval + 1</code></td>
<td></td> <td>A2</td>
<td>C1</td> <td></td>
</tr> <td>C1</td>
<tr> </tr>
<td>...</td> <tr>
<td></td> <td>...</td>
<td></td> <td></td>
<td></td> <td></td>
</tr> <td></td>
<tr> </tr>
<td><code>PostBlossomHalvingInterval - 2</code></td> <tr>
<td>A2</td> <td><code>PostBlossomHalvingInterval - 2</code></td>
<td></td> <td>A2</td>
<td>C1</td> <td></td>
</tr> <td>C1</td>
<tr> </tr>
<td><code>PostBlossomHalvingInterval - 1</code></td> <tr>
<td>A2</td> <td><code>PostBlossomHalvingInterval - 1</code></td>
<td></td> <td>A2</td>
<td>C1</td> <td></td>
</tr> <td>C1</td>
<tr> </tr>
<td><code>PostBlossomHalvingInterval</code></td> <tr>
<td></td> <td><code>PostBlossomHalvingInterval</code></td>
<td></td> <td></td>
<td>C2</td> <td></td>
</tr> <td>C2</td>
<tr> </tr>
<td><code>PostBlossomHalvingInterval + 1</code></td> <tr>
<td></td> <td><code>PostBlossomHalvingInterval + 1</code></td>
<td></td> <td></td>
<td>C2</td> <td></td>
</tr> <td>C2</td>
</tbody> </tr>
</table> </tbody>
<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 id="id7" class="footnote_reference" href="#original-fr-consensus-rule">5</a>). There will be a shortened Founders' Reward address period prior to Blossom activation.</p> </table>
</blockquote>
<p>On Mainnet, ${NU4} is planned to activate exactly at the point when the Founders' Reward expires, at block height 1046400. On Testnet, there will be a shortened Founders' Reward address period prior to ${NU4} activation.</p>
</section> </section>
<section id="consensus-rules"><h3><span class="section-heading">Consensus rules</span><span class="section-anchor"> <a href="#consensus-rules"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> <section id="consensus-rules"><h3><span class="section-heading">Consensus rules</span><span class="section-anchor"> <a href="#consensus-rules"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Prior to activation of the Blossom network upgrade, the existing consensus rule for payment of the original Founders' Reward is enforced. <a id="id8" class="footnote_reference" href="#original-fr-consensus-rule">5</a></p> <p>Prior to activation of the ${NU4} network upgrade, the existing consensus rule for payment of the original Founders' Reward is enforced. <a id="id14" class="footnote_reference" href="#protocol-foundersreward">6</a></p>
<p>Once the Blossom network upgrade activates:</p> <p>Once the ${NU4} network upgrade activates:</p>
<ul> <ul>
<li>The existing consensus rule <a id="id9" class="footnote_reference" href="#original-fr-consensus-rule">5</a> is no longer active.</li> <li>The existing consensus rule <a id="id15" class="footnote_reference" href="#protocol-foundersreward">6</a> is no longer active. (This would be the case under the preexisting consensus rules for Mainnet, but not for Testnet.)</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> <li>The coinbase transaction in each block MUST contain at least one output per active funding stream that pays the stream's value in the prescribed way to the stream's recipient address for the block's height.</li>
</ul> <li>The "prescribed way" to pay a transparent P2SH address is to use a standard P2SH script of the form <code>OP_HASH160 RedeemScriptHash(height) OP_EQUAL</code> as the <code>scriptPubKey</code>.</li>
</section> <li>The "prescribed way" to pay a Sapling address is as defined in <a id="id16" class="footnote_reference" href="#zip-0213">9</a>. That is, all Sapling outputs in coinbase transactions (including, but not limited to, outputs for funding streams) MUST have valid note commitments when recovered using a 32-byte array of zeroes as the outgoing viewing key.</li>
<section id="stream-definitions"><h3><span class="section-heading">Stream definitions</span><span class="section-anchor"> <a href="#stream-definitions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<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>
<th>Stream</th>
<th>Value numerator</th>
<th>Value denominator</th>
<th>Start height</th>
<th>End height</th>
</tr>
</thead>
<tbody>
<tr>
<td>FS 1</td>
<td>3</td>
<td>40</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 2</td>
<td>1</td>
<td>25</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 3</td>
<td>1</td>
<td>40</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 4</td>
<td>1</td>
<td>50</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 5</td>
<td>1</td>
<td>80</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 6</td>
<td>1</td>
<td>80</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 7</td>
<td>1</td>
<td>100</td>
<td><code>BlossomActivationHeight</code></td>
<td><code>HeightForHalving(1)</code></td>
</tr>
<tr>
<td>FS 8</td>
<td>1</td>
<td>200</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 id="id10" class="footnote_reference" href="#protocol-constants">6</a>).</p>
<p>The sets of recipient addresses are defined as follows:</p>
<pre data-language="cpp"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_1_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS1INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS1INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_2_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS2INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS2INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_3_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS3INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS3INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_4_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS4INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS4INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_5_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS5INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS5INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_6_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS6INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS6INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_7_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS7INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS7INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">FS_8_ADDRESSES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s">&quot;tFS8INVALIDADDRESS00&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS01&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS02&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS03&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS04&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS05&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS06&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS07&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS08&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS09&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS10&quot;</span><span class="p">,</span>
<span class="s">&quot;tFS8INVALIDADDRESS11&quot;</span><span class="p">,</span>
<span class="p">];</span></pre>
<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> </ul>
<p>For the funding stream definitions to be activated at ${NU4}, see ZIP 214. <a id="id17" class="footnote_reference" href="#zip-0214">10</a> Funding stream definitions can be added, changed, or deleted in ZIPs associated with subsequent network upgrades, subject to the ZIP process. <a id="id18" class="footnote_reference" href="#zip-0000">7</a></p>
</section> </section>
<section id="example-implementation"><h3><span class="section-heading">Example implementation</span><span class="section-anchor"> <a href="#example-implementation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> <section id="example-implementation"><h3><span class="section-heading">Example implementation</span><span class="section-anchor"> <a href="#example-implementation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<pre data-language="cpp"><span class="k">struct</span> <span class="n">FundingPeriod</span> <span class="p">{</span> <pre data-language="cpp"><span class="k">struct</span> <span class="n">FundingPeriod</span> <span class="p">{</span>
@ -373,14 +196,9 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
<span class="p">};</span> <span class="p">};</span>
<span class="k">enum</span> <span class="n">FundingStream</span> <span class="p">{</span> <span class="k">enum</span> <span class="n">FundingStream</span> <span class="p">{</span>
<span class="n">FS_1</span><span class="p">,</span> <span class="n">FS_ECC</span><span class="p">,</span>
<span class="n">FS_2</span><span class="p">,</span> <span class="n">FS_ZF</span><span class="p">,</span>
<span class="n">FS_3</span><span class="p">,</span> <span class="n">FS_MG</span><span class="p">,</span>
<span class="n">FS_4</span><span class="p">,</span>
<span class="n">FS_5</span><span class="p">,</span>
<span class="n">FS_6</span><span class="p">,</span>
<span class="n">FS_7</span><span class="p">,</span>
<span class="n">FS_8</span><span class="p">,</span>
<span class="n">MAX_FUNDING_STREAMS</span><span class="p">,</span> <span class="n">MAX_FUNDING_STREAMS</span><span class="p">,</span>
<span class="p">};</span> <span class="p">};</span>
@ -413,14 +231,9 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
<span class="n">consensus</span><span class="p">.</span><span class="n">nFundingPeriodLength</span> <span class="o">=</span> <span class="n">consensus</span><span class="p">.</span><span class="n">nSubsidyPostBlossomHalvingInterval</span> <span class="o">/</span> <span class="mi">48</span><span class="p">;</span> <span class="n">consensus</span><span class="p">.</span><span class="n">nFundingPeriodLength</span> <span class="o">=</span> <span class="n">consensus</span><span class="p">.</span><span class="n">nSubsidyPostBlossomHalvingInterval</span> <span class="o">/</span> <span class="mi">48</span><span class="p">;</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_1</span><span class="p">,</span> <span class="n">FS_1_ADDRESSES</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> <span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_ECC</span><span class="p">,</span> <span class="n">FS_ECC_ADDRESSES</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_2</span><span class="p">,</span> <span class="n">FS_2_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">25</span><span class="p">);</span> <span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_ZF</span><span class="p">,</span> <span class="n">FS_ZF_ADDRESSES</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_3</span><span class="p">,</span> <span class="n">FS_3_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">40</span><span class="p">);</span> <span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_MG</span><span class="p">,</span> <span class="n">FS_MG_ADDRESSES</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_4</span><span class="p">,</span> <span class="n">FS_4_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">50</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_5</span><span class="p">,</span> <span class="n">FS_5_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">80</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_6</span><span class="p">,</span> <span class="n">FS_6_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">80</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_7</span><span class="p">,</span> <span class="n">FS_7_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">AddZIP207FundingStream</span><span class="p">(</span><span class="n">consensus</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">FS_8</span><span class="p">,</span> <span class="n">FS_8_ADDRESSES</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span>
<span class="p">...</span> <span class="p">...</span>
<span class="p">}</span> <span class="p">}</span>
@ -476,7 +289,7 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
<span class="p">{</span> <span class="p">{</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">NetworkUpgradeActive</span><span class="p">(</span><span class="n">nHeight</span><span class="p">,</span> <span class="n">consensusParams</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">UPGRADE_BLOSSOM</span><span class="p">))</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">NetworkUpgradeActive</span><span class="p">(</span><span class="n">nHeight</span><span class="p">,</span> <span class="n">consensusParams</span><span class="p">,</span> <span class="n">Consensus</span><span class="o">::</span><span class="n">UPGRADE_NU4</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">// Coinbase transaction must include outputs corresponding to the consensus</span> <span class="c1">// Coinbase transaction must include outputs corresponding to the consensus</span>
<span class="c1">// funding streams active at the current block height.</span> <span class="c1">// funding streams active at the current block height.</span>
<span class="k">auto</span> <span class="n">requiredStreams</span> <span class="o">=</span> <span class="n">GetActiveFundingStreams</span><span class="p">(</span><span class="n">nHeight</span><span class="p">,</span> <span class="n">consensusParams</span><span class="p">);</span> <span class="k">auto</span> <span class="n">requiredStreams</span> <span class="o">=</span> <span class="n">GetActiveFundingStreams</span><span class="p">(</span><span class="n">nHeight</span><span class="p">,</span> <span class="n">consensusParams</span><span class="p">);</span>
@ -491,14 +304,15 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
<span class="p">}</span> <span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">requiredStreams</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">requiredStreams</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">state</span><span class="p">.</span><span class="n">DoS</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;%s: funding stream missing&quot;</span><span class="p">,</span> <span class="n">__func__</span><span class="p">),</span> <span class="n">REJECT_INVALID</span><span class="p">,</span> <span class="s">&quot;cb-funding-stream-missing&quot;</span><span class="p">);</span> <span class="k">return</span> <span class="n">state</span><span class="p">.</span><span class="n">DoS</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;%s: funding stream missing&quot;</span><span class="p">,</span> <span class="n">__func__</span><span class="p">),</span>
<span class="n">REJECT_INVALID</span><span class="p">,</span> <span class="s">&quot;cb-funding-stream-missing&quot;</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// Coinbase transaction must include an output sending 20% of</span> <span class="c1">// Coinbase transaction must include an output sending 20% of</span>
<span class="c1">// the block reward to a founders reward script, until the last founders</span> <span class="c1">// the block subsidy to a Founders&#39; Reward script, until the last founders</span>
<span class="c1">// reward block is reached, with exception of the genesis block.</span> <span class="c1">// reward block is reached, with exception of the genesis block.</span>
<span class="c1">// The last founders reward block is defined as the block just before the</span> <span class="c1">// The last Founders&#39; Reward block is defined as the block just before the</span>
<span class="c1">// first subsidy halving block, which occurs at halving_interval + slow_start_shift</span> <span class="c1">// first subsidy halving block.</span>
<span class="k">if</span> <span class="p">((</span><span class="n">nHeight</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">nHeight</span> <span class="o">&lt;=</span> <span class="n">consensusParams</span><span class="p">.</span><span class="n">GetLastFoundersRewardBlockHeight</span><span class="p">()))</span> <span class="p">{</span> <span class="k">if</span> <span class="p">((</span><span class="n">nHeight</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">nHeight</span> <span class="o">&lt;=</span> <span class="n">consensusParams</span><span class="p">.</span><span class="n">GetLastFoundersRewardBlockHeight</span><span class="p">()))</span> <span class="p">{</span>
<span class="kt">bool</span> <span class="n">found</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="kt">bool</span> <span class="n">found</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
@ -512,7 +326,8 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
<span class="p">}</span> <span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">found</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">found</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">state</span><span class="p">.</span><span class="n">DoS</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;%s: founders reward missing&quot;</span><span class="p">,</span> <span class="n">__func__</span><span class="p">),</span> <span class="n">REJECT_INVALID</span><span class="p">,</span> <span class="s">&quot;cb-no-founders-reward&quot;</span><span class="p">);</span> <span class="k">return</span> <span class="n">state</span><span class="p">.</span><span class="n">DoS</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">error</span><span class="p">(</span><span class="s">&quot;%s: founders reward missing&quot;</span><span class="p">,</span> <span class="n">__func__</span><span class="p">),</span>
<span class="n">REJECT_INVALID</span><span class="p">,</span> <span class="s">&quot;cb-no-founders-reward&quot;</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
<span class="p">}</span> <span class="p">}</span>
<span class="p">}</span> <span class="p">}</span>
@ -522,15 +337,10 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
</section> </section>
</section> </section>
<section id="deployment"><h2><span class="section-heading">Deployment</span><span class="section-anchor"> <a href="#deployment"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="deployment"><h2><span class="section-heading">Deployment</span><span class="section-anchor"> <a href="#deployment"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>This proposal was originally intended to be deployed with the Blossom network upgrade. <a id="id11" class="footnote_reference" href="#zip-0206">7</a></p> <p>This proposal is intended to be deployed with ${NU4}. <a id="id19" class="footnote_reference" href="#zip-0251">11</a></p>
</section> </section>
<section id="backward-compatibility"><h2><span class="section-heading">Backward compatibility</span><span class="section-anchor"> <a href="#backward-compatibility"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="backward-compatibility"><h2><span class="section-heading">Backward compatibility</span><span class="section-anchor"> <a href="#backward-compatibility"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<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> <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>
<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>
<section id="interactions-with-other-zips"><h3><span class="section-heading">Interactions with other ZIPs</span><span class="section-anchor"> <a href="#interactions-with-other-zips"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p><a id="id12" class="footnote_reference" href="#zip-0208">4</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 id="id13" class="footnote_reference" href="#zip-0206">7</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>
</section>
</section> </section>
<section id="reference-implementation"><h2><span class="section-heading">Reference Implementation</span><span class="section-anchor"> <a href="#reference-implementation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2> <section id="reference-implementation"><h2><span class="section-heading">Reference Implementation</span><span class="section-anchor"> <a href="#reference-implementation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>TBC</p> <p>TBC</p>
@ -544,51 +354,91 @@ Address(height) = FundingStream[FUND].Addresses[FundingStream[FUND].AddressIndex
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table id="block-subsidy" class="footnote"> <table id="protocol" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>2</th> <th>2</th>
<td><a href="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></td> <td><a href="protocol/protocol.pdf">Zcash Protocol Specification, Version 2020.1.1 or later</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table id="continued-funding" class="footnote"> <table id="protocol-subsidyconcepts" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>3</th> <th>3</th>
<td><a href="https://electriccoin.co/blog/continued-funding-and-transparency/">Continued Funding and Transparency</a></td> <td><a href="protocol/protocol.pdf#subsidyconcepts">Section 3.9: Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later</a></td>
</tr>
</tbody>
</table>
<table id="zip-0208" class="footnote">
<tbody>
<tr>
<th>4</th>
<td><a href="zip-0208">ZIP 208: Shorter Block Target Spacing</a></td>
</tr>
</tbody>
</table>
<table id="original-fr-consensus-rule" class="footnote">
<tbody>
<tr>
<th>5</th>
<td><a href="protocol/protocol.pdf">Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table id="protocol-constants" class="footnote"> <table id="protocol-constants" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>6</th> <th>4</th>
<td><a href="protocol/protocol.pdf">Section 5.3: Constants. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling]</a></td> <td><a href="protocol/protocol.pdf#constants">Section 5.3: Constants. Zcash Protocol Specification, Version 2020.1.1 or later</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table id="zip-0206" class="footnote"> <table id="protocol-subsidies" class="footnote">
<tbody>
<tr>
<th>5</th>
<td><a href="protocol/protocol.pdf#subsidies">Section 7.7: Calculation of Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later</a></td>
</tr>
</tbody>
</table>
<table id="protocol-foundersreward" class="footnote">
<tbody>
<tr>
<th>6</th>
<td><a href="protocol/protocol.pdf#foundersreward">Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later</a></td>
</tr>
</tbody>
</table>
<table id="zip-0000" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>7</th> <th>7</th>
<td><a href="zip-0206">ZIP 206: Blossom Network Upgrade</a></td> <td><a href="zip-0000">ZIP 0: ZIP Process</a></td>
</tr>
</tbody>
</table>
<table id="zip-0208" class="footnote">
<tbody>
<tr>
<th>8</th>
<td><a href="zip-0208">ZIP 208: Shorter Block Target Spacing</a></td>
</tr>
</tbody>
</table>
<table id="zip-0213" class="footnote">
<tbody>
<tr>
<th>9</th>
<td><a href="zip-0213">ZIP 213: Shielded Coinbase</a></td>
</tr>
</tbody>
</table>
<table id="zip-0214" class="footnote">
<tbody>
<tr>
<th>10</th>
<td><a href="zip-0214">ZIP 214: Consensus rules for a Zcash Development Fund</a></td>
</tr>
</tbody>
</table>
<table id="zip-0251" class="footnote">
<tbody>
<tr>
<th>11</th>
<td><a href="zip-0251">ZIP 251: Deployment of the ${NU4} Network Upgrade</a></td>
</tr>
</tbody>
</table>
<table id="zip-1014" class="footnote">
<tbody>
<tr>
<th>12</th>
<td><a href="zip-1014">ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants</a></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -1,10 +1,11 @@
:: ::
ZIP: 207 ZIP: 207
Title: Split Founders' Reward Title: Funding Streams
Owners: Jack Grigg <str4d@electriccoin.co> Owners: Jack Grigg <str4d@electriccoin.co>
Daira Hopwood <daira@electriccoin.co>
Category: Consensus Category: Consensus
Status: Withdrawn Status: Draft
Created: 2019-01-04 Created: 2019-01-04
License: MIT License: MIT
@ -15,26 +16,59 @@ Terminology
The key words "MUST", "SHOULD", "SHOULD NOT", and "MAY" in this document are The key words "MUST", "SHOULD", "SHOULD NOT", and "MAY" in this document are
to be interpreted as described in RFC 2119. [#RFC2119]_ to be interpreted as described in RFC 2119. [#RFC2119]_
The terms "block subsidy" and "halving" in this document are to be interpreted
as described in sections 3.9 and 7.7 of the Zcash Protocol Specification.
[#protocol-subsidyconcepts]_ [#protocol-subsidies]_
The terms below are to be interpreted as follows:
${NU4}
Code-name for the fifth Zcash network upgrade, also known as Network Upgrade 4.
Testnet
The Zcash test network, as defined in the Zcash Protocol Specification. [#protocol]_
Mainnet
The Zcash production network, as defined in the Zcash Protocol Specification. [#protocol]_
Abstract Abstract
======== ========
This Withdrawn proposal would have altered consensus rules to split the original Founders' Reward across This proposal specifies a mechanism to support funding streams, distributed
several recipient addresses per block instead of one, corresponding to the several funding streams contained from a portion of the block subsidy for a specified range of block heights.
within it.
This is intended as a means of implementing the Zcash Development Fund,
using the funding stream definitions specified in ZIP 214 [#zip-0214]_. It
should be read in conjunction with ZIP 1014 [#zip-1014]_, which describes
the high-level requirements for that fund.
Motivation Motivation
========== ==========
Since the launch of the Zcash network, the consensus rules have required that until the first block reward Motivation for the Zcash Development Fund is considered in ZIP 1014 [#zip-1014]_.
halving (at block 850,000), each block must send 20% of the block subsidy to a hard-coded transparent address.
[#block-subsidy]_ 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 This ZIP 207 was originally proposed for the Blossom network upgrade, as a
logical funding streams (for background, see [#continued-funding]_). Modifying the consensus rules to allocate means of splitting the original Founders' Reward into several streams. It was
the 2.5 ZEC across separate recipient addresses decouples these funding streams organizationally, legally, and then withdrawn when such splitting was judged to be unnecessary at the consensus
operationally. It further reinforces transparency as to the structure of the original Founders' Reward. level. Since the capabilities of the funding stream mechanism match the
requirements for the Zcash Development Fund, the ZIP is being reintroduced
for that purpose in order to reuse specification, analysis, and implementation
effort.
Requirements
============
The primary requirement of this ZIP is to provide a mechanism for specifying
the funding streams that are used in ZIP 214 [#zip-0214] to implement the Zcash
Development Fund. It should be sufficiently expressive to handle both the main
three "slices" (ECC, ZF, and MG) defined in ZIP 1014 [#zip-1014]_, and also
(with additional funding stream definitions) the "direct grant option" described
in that ZIP.
As for the original Founders' Reward, addresses for a given funding stream are
changed on a roughly-monthly basis, so that keys that are not yet needed may be
kept off-line as a security measure.
Specification Specification
@ -43,42 +77,48 @@ Specification
Definitions Definitions
----------- -----------
We use the following constants and functions defined in [#zip-0208]_: We use the following constants and functions defined in [#protocol-constants]_,
[#protocol-subsidies]_, and [#protocol-foundersreward]_:
- ``BlossomActivationHeight`` - ``BlossomActivationHeight``
- ``PostBlossomHalvingInterval`` - ``PostBlossomHalvingInterval``
- ``Halving(height)`` - ``Halving(height)``
- ``BlockSubsidy(height)``
- ``RedeemScriptHash(height)``.
We also define the following constants and functions: We also define the following function:
- ``HeightForHalving(halving)``: Smallest ``height`` such that
``Halving(height) = halving``
- ``SlowStartShift`` as-defined in [#block-subsidy]_.
- ``HeightForHalving(halving)``: Smallest ``height`` such that ``Halving(height) = halving``
Funding streams Funding streams
--------------- ---------------
A funding stream is defined by a block reward fraction (represented as a A funding stream is defined by a block subsidy fraction (represented as a
numerator and a denominator), a start height (inclusive), and an end height numerator and a denominator), a start height (inclusive), and an end height
(exclusive). (exclusive).
By defining the issuance as a proportion of the total block issuance, rather By defining the issuance as a proportion of the total block subsidy, rather
than absolute zatoshis, this ZIP dovetails with any changes to both block than absolute zatoshis, this ZIP dovetails with any changes to both block
target times and issuance-per-block rates while maintaining an unchanged target spacing and issuance-per-block rates, while maintaining an unchanged
target-time-based issuance schedule. We anticipate such target-time / issuance target-time-based issuance schedule. Such a target-time / issuance rate change
rate changes in other ZIPs (for example, [#zip-0208]_). occurred at the Blossom network upgrade, for example. [#zip-0208]_
The value of a funding stream at a given block height is defined as:: The value of a funding stream at a given block height is defined as::
FundingStream[FUND].Value(height) = FundingStream[FUND].Value(height) =
floor(( floor((
BlockReward(height) * FundingStream[FUND].ValueNumerator BlockSubsidy(height) * FundingStream[FUND].ValueNumerator
) / FundingStream[FUND].ValueDenominator) ) / FundingStream[FUND].ValueDenominator)
An active funding stream at a given block height is defined as a funding 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 stream for which the block height is less than its end height, but not less
than its start height. than its start height.
Each funding stream has an associated set of recipient addresses. Each funding stream has an associated sequence of recipient addresses,
each of which MUST be either a transparent P2SH address or a Sapling address.
Each address is used for at most 1/48th of a halving interval, creating a 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 roughly-monthly sequence of funding periods. The address to be used for a
given block height is defined as follows:: given block height is defined as follows::
@ -101,193 +141,59 @@ necessary outputs for each funding period.
Below is a visual representation of how stream addresses align with funding Below is a visual representation of how stream addresses align with funding
periods: periods:
================================== ======== ======== ======== ================================== ======== ======== ========
Example height Stream A Stream B Stream C Example height Stream A Stream B Stream C
================================== ======== ======== ======== ================================== ======== ======== ========
``AddressChangeInterval - 2`` A0 ``AddressChangeInterval - 2`` A0
``AddressChangeInterval - 1`` A0 ``AddressChangeInterval - 1`` A0
``AddressChangeInterval`` A1 B0 C0 ``AddressChangeInterval`` A1 B0 C0
``AddressChangeInterval + 1`` A1 B0 C0 ``AddressChangeInterval + 1`` A1 B0 C0
\... \...
``2*AddressChangeInterval - 2`` A1 B0 C0 ``2*AddressChangeInterval - 2`` A1 B0 C0
``2*AddressChangeInterval - 1`` A1 B0 C0 ``2*AddressChangeInterval - 1`` A1 B0 C0
``2*AddressChangeInterval`` A2 C1 ``2*AddressChangeInterval`` A2 C1
``2*AddressChangeInterval + 1`` A2 C1 ``2*AddressChangeInterval + 1`` A2 C1
\... \...
``PostBlossomHalvingInterval - 2`` A2 C1 ``PostBlossomHalvingInterval - 2`` A2 C1
``PostBlossomHalvingInterval - 1`` A2 C1 ``PostBlossomHalvingInterval - 1`` A2 C1
``PostBlossomHalvingInterval`` C2 ``PostBlossomHalvingInterval`` C2
``PostBlossomHalvingInterval + 1`` C2 ``PostBlossomHalvingInterval + 1`` C2
================================== ======== ======== ======== ================================== ======== ======== ========
On Mainnet, ${NU4} is planned to activate exactly at the point when the Founders'
Reward expires, at block height 1046400. On Testnet, there will be a shortened
Founders' Reward address period prior to ${NU4} activation.
Note that this is not intended to align with the end of a pre-Blossom Founders' Reward address period (as
defined by ``FounderAddressChangeInterval`` in [#original-fr-consensus-rule]_). There will be a shortened
Founders' Reward address period prior to Blossom activation.
Consensus rules Consensus rules
--------------- ---------------
Prior to activation of the Blossom network upgrade, the existing consensus rule Prior to activation of the ${NU4} network upgrade, the existing consensus rule
for payment of the original Founders' Reward is enforced. [#original-fr-consensus-rule]_ for payment of the original Founders' Reward is enforced. [#protocol-foundersreward]_
Once the Blossom network upgrade activates: Once the ${NU4} network upgrade activates:
- The existing consensus rule [#protocol-foundersreward]_ is no longer active.
(This would be the case under the preexisting consensus rules for Mainnet, but
not for Testnet.)
- The existing consensus rule [#original-fr-consensus-rule]_ is no longer
active.
- The coinbase transaction in each block MUST contain at least one output per - 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 active funding stream that pays the stream's value in the prescribed way to
address for the block's height. the stream's recipient address for the block's height.
Stream definitions - The "prescribed way" to pay a transparent P2SH address is to use a standard
------------------ P2SH script of the form ``OP_HASH160 RedeemScriptHash(height) OP_EQUAL`` as
the ``scriptPubKey``.
The consensus-defined funding streams described above each start at the Blossom activation height, and end at - The "prescribed way" to pay a Sapling address is as defined in [#zip-0213]_.
the first block reward halving. They are defined as follows: That is, all Sapling outputs in coinbase transactions (including, but not
limited to, outputs for funding streams) MUST have valid note commitments
when recovered using a 32-byte array of zeroes as the outgoing viewing key.
====== =============== ================= =========================== ======================= For the funding stream definitions to be activated at ${NU4}, see ZIP 214. [#zip-0214]_
Stream Value numerator Value denominator Start height End height Funding stream definitions can be added, changed, or deleted in ZIPs associated
====== =============== ================= =========================== ======================= with subsequent network upgrades, subject to the ZIP process. [#zip-0000]_
FS 1 3 40 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 2 1 25 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 3 1 40 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 4 1 50 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 5 1 80 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 6 1 80 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 7 1 100 ``BlossomActivationHeight`` ``HeightForHalving(1)``
FS 8 1 200 ``BlossomActivationHeight`` ``HeightForHalving(1)``
====== =============== ================= =========================== =======================
- 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 [#protocol-constants]_).
The sets of recipient addresses are defined as follows:
.. code:: 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 Example implementation
---------------------- ----------------------
@ -303,14 +209,9 @@ Example implementation
}; };
enum FundingStream { enum FundingStream {
FS_1, FS_ECC,
FS_2, FS_ZF,
FS_3, FS_MG,
FS_4,
FS_5,
FS_6,
FS_7,
FS_8,
MAX_FUNDING_STREAMS, MAX_FUNDING_STREAMS,
}; };
@ -343,14 +244,9 @@ Example implementation
consensus.nFundingPeriodLength = consensus.nSubsidyPostBlossomHalvingInterval / 48; consensus.nFundingPeriodLength = consensus.nSubsidyPostBlossomHalvingInterval / 48;
AddZIP207FundingStream(consensus, Consensus::FS_1, FS_1_ADDRESSES, 3, 40); AddZIP207FundingStream(consensus, Consensus::FS_ECC, FS_ECC_ADDRESSES, 7, 100);
AddZIP207FundingStream(consensus, Consensus::FS_2, FS_2_ADDRESSES, 1, 25); AddZIP207FundingStream(consensus, Consensus::FS_ZF, FS_ZF_ADDRESSES, 5, 100);
AddZIP207FundingStream(consensus, Consensus::FS_3, FS_3_ADDRESSES, 1, 40); AddZIP207FundingStream(consensus, Consensus::FS_MG, FS_MG_ADDRESSES, 8, 100);
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);
... ...
} }
@ -406,7 +302,7 @@ Example implementation
{ {
... ...
if (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_BLOSSOM)) { if (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_NU4)) {
// Coinbase transaction must include outputs corresponding to the consensus // Coinbase transaction must include outputs corresponding to the consensus
// funding streams active at the current block height. // funding streams active at the current block height.
auto requiredStreams = GetActiveFundingStreams(nHeight, consensusParams); auto requiredStreams = GetActiveFundingStreams(nHeight, consensusParams);
@ -421,14 +317,15 @@ Example implementation
} }
if (!requiredStreams.empty()) { if (!requiredStreams.empty()) {
return state.DoS(100, error("%s: funding stream missing", __func__), REJECT_INVALID, "cb-funding-stream-missing"); return state.DoS(100, error("%s: funding stream missing", __func__),
REJECT_INVALID, "cb-funding-stream-missing");
} }
} else { } else {
// Coinbase transaction must include an output sending 20% of // Coinbase transaction must include an output sending 20% of
// the block reward to a founders reward script, until the last founders // the block subsidy to a Founders' Reward script, until the last founders
// reward block is reached, with exception of the genesis block. // reward block is reached, with exception of the genesis block.
// The last founders reward block is defined as the block just before the // 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 // first subsidy halving block.
if ((nHeight > 0) && (nHeight <= consensusParams.GetLastFoundersRewardBlockHeight())) { if ((nHeight > 0) && (nHeight <= consensusParams.GetLastFoundersRewardBlockHeight())) {
bool found = false; bool found = false;
@ -442,7 +339,8 @@ Example implementation
} }
if (!found) { if (!found) {
return state.DoS(100, error("%s: founders reward missing", __func__), REJECT_INVALID, "cb-no-founders-reward"); return state.DoS(100, error("%s: founders reward missing", __func__),
REJECT_INVALID, "cb-no-founders-reward");
} }
} }
} }
@ -454,7 +352,7 @@ Example implementation
Deployment Deployment
========== ==========
This proposal was originally intended to be deployed with the Blossom network upgrade. [#zip-0206]_ This proposal is intended to be deployed with ${NU4}. [#zip-0251]_
Backward compatibility Backward compatibility
@ -466,23 +364,6 @@ upgrade their software to a compatible version within the upgrade window.
Older software will treat post-upgrade blocks as invalid, and will follow any Older software will treat post-upgrade blocks as invalid, and will follow any
pre-upgrade branch that persists. 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
----------------------------
[#zip-0208]_ (Shorter Block Target Spacing) specifies a change to the block target spacing. It is planned
to take effect in the Blossom network upgrade [#zip-0206]_. 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 Reference Implementation
======================== ========================
@ -494,9 +375,14 @@ References
========== ==========
.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels <https://www.rfc-editor.org/rfc/rfc2119.html>`_ .. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels <https://www.rfc-editor.org/rfc/rfc2119.html>`_
.. [#block-subsidy] `Section 7.7: Calculation of Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling] <protocol/protocol.pdf>`_ .. [#protocol] `Zcash Protocol Specification, Version 2020.1.1 or later <protocol/protocol.pdf>`_
.. [#continued-funding] `Continued Funding and Transparency <https://electriccoin.co/blog/continued-funding-and-transparency/>`_ .. [#protocol-subsidyconcepts] `Section 3.9: Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later <protocol/protocol.pdf#subsidyconcepts>`_
.. [#protocol-constants] `Section 5.3: Constants. Zcash Protocol Specification, Version 2020.1.1 or later <protocol/protocol.pdf#constants>`_
.. [#protocol-subsidies] `Section 7.7: Calculation of Block Subsidy and Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later <protocol/protocol.pdf#subsidies>`_
.. [#protocol-foundersreward] `Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2020.1.1 or later <protocol/protocol.pdf#foundersreward>`_
.. [#zip-0000] `ZIP 0: ZIP Process <zip-0000.rst>`_
.. [#zip-0208] `ZIP 208: Shorter Block Target Spacing <zip-0208.rst>`_ .. [#zip-0208] `ZIP 208: Shorter Block Target Spacing <zip-0208.rst>`_
.. [#original-fr-consensus-rule] `Section 7.8: Payment of Founders' Reward. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling] <protocol/protocol.pdf>`_ .. [#zip-0213] `ZIP 213: Shielded Coinbase <zip-0213.rst>`_
.. [#protocol-constants] `Section 5.3: Constants. Zcash Protocol Specification, Version 2018.0-beta-33 or later [Overwinter+Sapling] <protocol/protocol.pdf>`_ .. [#zip-0214] `ZIP 214: Consensus rules for a Zcash Development Fund <zip-0214.rst>`_
.. [#zip-0206] `ZIP 206: Blossom Network Upgrade <zip-0206.rst>`_ .. [#zip-0251] `ZIP 251: Deployment of the ${NU4} Network Upgrade <zip-0251.rst>`_
.. [#zip-1014] `ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants <zip-1014.rst>`_