Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate spends of transparent coinbase outputs #2525

Merged
merged 18 commits into from
Jul 29, 2021

Conversation

teor2345
Copy link
Contributor

@teor2345 teor2345 commented Jul 26, 2021

Motivation

Zebra needs to check the consensus rules that restrict how transparent outputs of coinbase transactions can be spent.

Specifications

See #2329 and #2330.

Designs

These designs are more complex than we actually need:

https://github.com/ZcashFoundation/zebra/blob/main/book/src/dev/rfcs/0004-asynchronous-script-verification.md , particularly the changes in PR #1970

https://github.com/ZcashFoundation/zebra/blob/main/book/src/dev/rfcs/0005-state-updates.md#requestawaitspendableutxo--outpoint-outpoint-spend_height-height-spend_restriction-spendrestriction-

Solution

Implementation:

  • Add a CoinbaseSpendRestriction enum and Transaction method
  • Check UTXO spendability during contextual validation, using known valid UTXOs

Test fixes:

  • Skip created UTXOs in the genesis block in arbitrary block chains
  • Refactor out a new_transaction_ordered_outputs function
  • Add Transaction::outputs_mut for tests
  • Only spend valid UTXOs in arbitrary block chains

Closes #2329
Closes #2330
Closes #2410

WIP Tests

Skip

  • non-coinbase UTXOs
    • existing unit tests, acceptance tests, and cached state tests

Success

  • coinbase UTXO spent to shielded outputs after 100 or more blocks
    • existing unit tests, acceptance tests, and cached state tests
  • coinbase UTXO spent to shielded outputs after exactly 100 blocks
    • modified existing state request test

Failure

  • coinbase UTXO spent to non-shielded outputs after 100 or more blocks
  • coinbase UTXO spent to shielded outputs after less than 100 blocks

Test coverage

  • make the proptest chain lengths slightly longer (ideally using a single constant)
  • make sure that restriction-checked and unchecked proptest chains contain UTXO prevout spends

We could also do tests for finalized/non-finalized state, and both non-shielded and immature. But these tests are the essential ones.

I'm also running a full sync test locally on mainnet and testnet.

Review

I'd like an initial review from @jvff while I'm working on the rest of the tests.

Reviewer Checklist

  • Code implements Specs and Designs
  • Tests for Expected Behaviour
  • Tests for Errors

Follow Up Work

Move the design changes in PR #1970 to an "alternatives" section, and explain how the simpler design works.
(Or just revert most of PR #1970.)


This change is Reviewable

@teor2345 teor2345 added A-consensus Area: Consensus rule updates NU Sprout Network Upgrade: Sprout specific tasks (before Overwinter) A-rust Area: Updates to Rust code C-enhancement Category: This is an improvement P-Medium labels Jul 26, 2021
@teor2345 teor2345 requested a review from jvff July 26, 2021 03:24
@teor2345 teor2345 self-assigned this Jul 26, 2021
@mpguerra mpguerra linked an issue Jul 26, 2021 that may be closed by this pull request
Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 10 of 14 files at r1, 1 of 1 files at r2, 1 of 1 files at r3.
Reviewable status: 12 of 14 files reviewed, 4 unresolved discussions (waiting on @teor2345)


zebra-chain/src/transparent/utxo.rs, line 84 at r3 (raw file):

    SomeTransparentOutputs,

    /// The UTXO is spent in a transaction with all shielded outputs

Nit: maybe replace all with only?

    /// The UTXO is spent in a transaction with only shielded outputs.

Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 14 files at r1.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @teor2345)

@teor2345 teor2345 force-pushed the transparent-coinbase-spend branch from 8365fb1 to 4452d77 Compare July 27, 2021 06:32
Copy link
Contributor Author

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 7 of 14 files reviewed, 3 unresolved discussions (waiting on @daira, @jvff, and @teor2345)


zebra-chain/src/transparent/utxo.rs, line 84 at r3 (raw file):

Previously, jvff (Janito Vaqueiro Ferreira Filho) wrote…

Nit: maybe replace all with only?

    /// The UTXO is spent in a transaction with only shielded outputs.

Fixed in 4452d77


zebra-state/src/error.rs, line 104 at r3 (raw file):

Previously, jvff (Janito Vaqueiro Ferreira Filho) wrote…

Nit: Would it make sense to start breaking the long error messages in multi-line strings?

    #[error(
        "immature transparent coinbase spend: \
        attempt to spend {outpoint:?} at {spend_height:?}, \
        but spends are invalid before {min_spend_height:?}, \
        which is {MIN_TRANSPARENT_COINBASE_MATURITY:?} blocks \
        after it was created at {created_height:?}"
    )]

Fixed in ee0ea49

@teor2345 teor2345 force-pushed the transparent-coinbase-spend branch from 4452d77 to 9494795 Compare July 27, 2021 07:20
@teor2345 teor2345 force-pushed the transparent-coinbase-spend branch from f90ca64 to 3ce46ef Compare July 27, 2021 10:26
Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 5 files at r6, 9 of 10 files at r7, 3 of 8 files at r8, 2 of 3 files at r9.
Reviewable status: 15 of 18 files reviewed, 5 unresolved discussions (waiting on @daira, @jvff, and @teor2345)

jvff
jvff previously approved these changes Jul 27, 2021
Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 8 files at r8, 1 of 3 files at r9.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @daira and @teor2345)

Copy link
Contributor Author

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dismissed @daira from a discussion.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @jvff and @teor2345)

@teor2345 teor2345 force-pushed the transparent-coinbase-spend branch from af60baf to 6965782 Compare July 28, 2021 06:10
Copy link
Contributor Author

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 10 of 24 files reviewed, 1 unresolved discussion (waiting on @jvff and @teor2345)


zebra-chain/src/block/arbitrary.rs, line 368 at r9 (raw file):

Previously, teor2345 (teor) wrote…

Once all the tests are working, I'll split this into a bunch of different methods

Here are the new commits I added:

Test that generated chains contain at least one transparent spend 48e4b6b
Make generated chains long enough for reliable tests 0df08ca
Split chain generation into 3 functions da95c01
Test that unshielded and immature transparent coinbase spends fail 6965782

This PR is getting a bit big. If you'd like, I can split these changes into other PRs, and get them merged first:

Refactor out a new_transaction_ordered_outputs function 8ead80c
Add Transaction::outputs_mut for tests 281fd68
Add transparent and shielded input and output methods to Transaction 7580673

The other changes will be a bit harder to split out.

@teor2345 teor2345 changed the title WIP: Validate spends of transparent coinbase outputs Validate spends of transparent coinbase outputs Jul 28, 2021
@teor2345 teor2345 requested a review from jvff July 28, 2021 06:21
@teor2345 teor2345 marked this pull request as ready for review July 28, 2021 06:22
Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 9 files at r10, 2 of 7 files at r11, 3 of 5 files at r12.
Reviewable status: 16 of 24 files reviewed, 2 unresolved discussions (waiting on @jvff and @teor2345)


zebra-state/src/service.rs, line 35 at r12 (raw file):

#[cfg(any(test, feature = "proptest-impl"))]
pub mod arbitrary;

Just curious: is there a guideline for splitting module declarations? I want to know if/how I should them in my PRs 😅

Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 3 of 9 files at r10, 1 of 7 files at r11, 2 of 5 files at r12.
Reviewable status: 22 of 24 files reviewed, 5 unresolved discussions (waiting on @jvff and @teor2345)


zebra-chain/src/block/arbitrary.rs, line 1 at r12 (raw file):

//! Randomised property testing for [`Block`]s

Nit: Maybe add a period at the end?


zebra-state/src/service/arbitrary.rs, line 21 at r12 (raw file):

use super::*;

/// The minimum height required for reliable non-finalized state property tests.

Minor: Should the documentation say something like maximum height for unreliable...? Also wondering if it would make sense to add a margin of error to it 🤔


zebra-state/src/service/check/tests/utxo.rs, line 76 at r12 (raw file):

    let min_spend_height = Height(created_height.0 + MIN_TRANSPARENT_COINBASE_MATURITY);
    let spend_height = Height(min_spend_height.0 - 1);

Minor: Should we add a test where spend_height = min_spend_height?

jvff
jvff previously approved these changes Jul 28, 2021
Copy link
Contributor

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 1 of 9 files at r10, 1 of 7 files at r11.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @teor2345)


zebra-chain/src/block/arbitrary.rs, line 368 at r9 (raw file):

Previously, teor2345 (teor) wrote…

Here are the new commits I added:

Test that generated chains contain at least one transparent spend 48e4b6b
Make generated chains long enough for reliable tests 0df08ca
Split chain generation into 3 functions da95c01
Test that unshielded and immature transparent coinbase spends fail 6965782

This PR is getting a bit big. If you'd like, I can split these changes into other PRs, and get them merged first:

Refactor out a new_transaction_ordered_outputs function 8ead80c
Add Transaction::outputs_mut for tests 281fd68
Add transparent and shielded input and output methods to Transaction 7580673

The other changes will be a bit harder to split out.

I think that won't be necessary. Most of it has been reviewed 😁

Copy link
Contributor Author

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 22 of 24 files reviewed, 2 unresolved discussions (waiting on @jvff)


zebra-state/src/service.rs, line 35 at r12 (raw file):

Previously, jvff (Janito Vaqueiro Ferreira Filho) wrote…

Just curious: is there a guideline for splitting module declarations? I want to know if/how I should them in my PRs 😅

I have no idea 🤷

This might be a bad habit of mine from C, where conditional compilation happens using macros in #if ... #endif blocks.

Happy to go with a Rust guideline if we find one.


zebra-state/src/service/arbitrary.rs, line 21 at r12 (raw file):

Previously, jvff (Janito Vaqueiro Ferreira Filho) wrote…

Minor: Should the documentation say something like maximum height for unreliable...? Also wondering if it would make sense to add a margin of error to it 🤔

I clarified the comment here, and for PREVOUTS_CHAIN_HEIGHT.

There is already a margin of error built in to PREVOUTS_CHAIN_HEIGHT, currently the failure rate should be around 1 in 10 million test runs.

I just picked a really rare probability, we can tweak it if it becomes an issue later on.


zebra-state/src/service/check/tests/utxo.rs, line 76 at r12 (raw file):

Previously, jvff (Janito Vaqueiro Ferreira Filho) wrote…

Minor: Should we add a test where spend_height = min_spend_height?

Good idea, I had one of those, but it might have got deleted when I simplified the PR.

Also I think the chain itself checks this, but it's an easy test to write, so I'll do it now.

Copy link
Contributor Author

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 21 of 24 files reviewed, all discussions resolved (waiting on @jvff)


zebra-state/src/service/check/tests/utxo.rs, line 76 at r12 (raw file):

Previously, teor2345 (teor) wrote…

Good idea, I had one of those, but it might have got deleted when I simplified the PR.

Also I think the chain itself checks this, but it's an easy test to write, so I'll do it now.

Done in b11310f

@teor2345
Copy link
Contributor Author

I just worked out that this PR is blocking the next PR after #2486.
There's a chain of about 5 PRs we need to do there.

So I might just admin-merge this PR after CI passes.
After the last approval, I added one requested test and some comments.

@teor2345 teor2345 merged commit 3d792f7 into main Jul 29, 2021
@teor2345 teor2345 deleted the transparent-coinbase-spend branch July 29, 2021 04:23
@teor2345
Copy link
Contributor Author

Admin-merged, because the PR was approved before minor changes, and it's blocking other work

@teor2345 teor2345 mentioned this pull request Jul 29, 2021
6 tasks
mpguerra added a commit that referenced this pull request Jul 29, 2021
mpguerra added a commit that referenced this pull request Jul 29, 2021
* Draft CHANGELOG for Zebra 1.0.0-alpha.14

* Add PR #2533 to CHANGELOG

* Apply suggestions from code review

Co-authored-by: teor <teor@riseup.net>

* Remove entry about updating the changelog

* move #2497

* add #2529

* Add a missing space

* Add #2458, #2525, #2486, #2542 and  #2539 to CHANGELOG

Co-authored-by: teor <teor@riseup.net>
Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-consensus Area: Consensus rule updates A-rust Area: Updates to Rust code C-enhancement Category: This is an improvement NU Sprout Network Upgrade: Sprout specific tasks (before Overwinter)
Projects
None yet
3 participants