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

ZIP-203: Validate Transaction Expiry Height in the transaction verifier #2387

Closed
teor2345 opened this issue Jun 24, 2021 · 6 comments · Fixed by #3103
Closed

ZIP-203: Validate Transaction Expiry Height in the transaction verifier #2387

teor2345 opened this issue Jun 24, 2021 · 6 comments · Fixed by #3103
Assignees
Labels
A-consensus Area: Consensus rule updates A-rust Area: Updates to Rust code C-enhancement Category: This is an improvement NU-0 Overwinter Network Upgrade: Overwinter specific tasks (Sprout after Overwinter)

Comments

@teor2345
Copy link
Contributor

teor2345 commented Jun 24, 2021

Motivation

The transaction verifier needs to check the ZIP-203: Transaction Expiry consensus rules.

Specifications

Zcash Spec

[Overwinter to Canopy inclusive, pre-NU5] nExpiryHeight MUST be less than or equal to 499999999.

[NU5 onward] nExpiryHeight MUST be less than or equal to 499999999 for non-coinbase transactions.

[Overwinter onward] If a transaction is not a coinbase transaction and its nExpiryHeight field is nonzero, then it MUST NOT be mined at a block height greater than its nExpiryHeight.

image

https://zips.z.cash/protocol/protocol.pdf#txnencodingandconsensus

ZIP-203

nExpiryHeight will never be a UNIX timestamp, unlike nLockTime values

Coinbase: nExpiryHeight on coinbase transactions is ignored [before NU5 activation]

https://zips.z.cash/zip-0203#specification

This rule is in ZIP 203, but we don't think it was ever implemented in zcashd:
If used in combination with nLockTime, both nLockTime and nExpiryHeight must be block heights.

NU5 Changes

from NU5 activation, the nExpiryHeight field of a coinbase transaction MUST be set equal to the block height.

The motivation is to ensure that transaction IDs remain unique

https://zips.z.cash/zip-0203#changes-for-nu5

Note: this rule applies to both v4 and v5 transactions after NU5 activation.

Designs

Zebra parses the expiry height, and validates it in the mempool storage, but not in the transaction verifier:

/// Get this transaction's expiry height, if any.
pub fn expiry_height(&self) -> Option<block::Height> {

Related Work

Validate the lock time field #2389

Support the large block heights required by the spec #1113 - out of scope for NU5 testnet activation

@teor2345 teor2345 added A-consensus Area: Consensus rule updates A-rust Area: Updates to Rust code NU-0 Overwinter Network Upgrade: Overwinter specific tasks (Sprout after Overwinter) C-enhancement Category: This is an improvement S-needs-triage Status: A bug report needs triage labels Jun 24, 2021
@teor2345 teor2345 added this to the 2021 Sprint 15 milestone Jun 24, 2021
@teor2345
Copy link
Contributor Author

I've updated this ticket to include https://zips.z.cash/zip-0203#changes-for-nu5

@mpguerra mpguerra removed the S-needs-triage Status: A bug report needs triage label Jun 28, 2021
@mpguerra mpguerra assigned upbqdn and unassigned upbqdn Nov 9, 2021
@oxarbitrage oxarbitrage self-assigned this Nov 15, 2021
@teor2345 teor2345 changed the title ZIP-203: Validate Transaction Expiry Height ZIP-203: Validate Transaction Expiry Height in the transaction verifier Nov 15, 2021
@oxarbitrage
Copy link
Contributor

In this ticket several of the rules are hard to know if we need to implement them and if so how to do it in Zebra.

[Overwinter to Canopy inclusive, pre-NU5] nExpiryHeight MUST be less than or equal to 499999999.

In Zebra nExpiryHeight is of type Height(u32). Each Height has a max value of 499_999_999: https://github.com/ZcashFoundation/zebra/blob/main/zebra-chain/src/block/height.rs#L44

[NU5 onward] nExpiryHeight MUST be less than or equal to 499999999 for non-coinbase transactions.

This is always the case in zebra for coinbase and non coinbase transactions by the use of Height. I can't see the reason to remove this constraint after nu5 when nExpiryHeight need to match the block height (which can't be above 499_999_999 anyway). If we need to make changes to support heights above 499_999_999 to use in this field i don't know what will be the best approach to do so.

[Overwinter onward] If a transaction is not a coinbase transaction and its nExpiryHeight field is nonzero, then it MUST NOT be mined at a block height greater than its nExpiryHeight.

I think we already did this in the mempool work (need to double check).

nExpiryHeight will never be a UNIX timestamp, unlike nLockTime values

We use Height(u32) for this field.

Coinbase: nExpiryHeight on coinbase transactions is ignored [before NU5 activation]

This is what we do now.

from NU5 activation, the nExpiryHeight field of a coinbase transaction MUST be set equal to the block height.

The motivation is to ensure that transaction IDs remain unique

This is clear, i have a PR for this that will push soon.

@conradoplg
Copy link
Collaborator

In this ticket several of the rules are hard to know if we need to implement them and if so how to do it in Zebra.

[Overwinter to Canopy inclusive, pre-NU5] nExpiryHeight MUST be less than or equal to 499999999.

In Zebra nExpiryHeight is of type Height(u32). Each Height has a max value of 499_999_999: https://github.com/ZcashFoundation/zebra/blob/main/zebra-chain/src/block/height.rs#L44

This is true, but that Height limit is supposed to be higher, see #1113. It's also not always being enforced correctly, see #3068

So it's best to explicitly add the 499999999 limit to nExpiryHeight, which will be redundant now but it won't be anymore when we increase the Height limit.

[NU5 onward] nExpiryHeight MUST be less than or equal to 499999999 for non-coinbase transactions.

This is always the case in zebra for coinbase and non coinbase transactions by the use of Height. I can't see the reason to remove this constraint after nu5 when nExpiryHeight need to match the block height (which can't be above 499_999_999 anyway). If we need to make changes to support heights above 499_999_999 to use in this field i don't know what will be the best approach to do so.

The same reasoning as the previous one applies.

nExpiryHeight will never be a UNIX timestamp, unlike nLockTime values

We use Height(u32) for this field.

The reason for that comment is that nLockTime may be either a block height or a timestamp, depending on its value. But this doesn't apply for nExpiryHeight, it's always a height.

@oxarbitrage
Copy link
Contributor

Thanks for the replies @conradoplg . Much clear now. I was able to mock a PR with that help.

#3082

It seems this ticket involves 3 rules where the PR is implementing 2 of them. We have pending at least one rule to complete the ticket (more details in the PR).

@mpguerra
Copy link
Contributor

How does this issue relate to #1113? do we need to do #1113 for NU5 mainnet activation? It seems like we might and if so we need to schedule it in for next sprint

@teor2345
Copy link
Contributor Author

How does this issue relate to #1113? do we need to do #1113 for NU5 mainnet activation? It seems like we might and if so we need to schedule it in for next sprint

No, we don't need to do #1113 any time soon:

  • the coinbase script height won't reach block height 500 million until the year 3000, so we can wait until then to remove the limit
  • the expiry height is not checked against the limit, this is already implemented correctly
  • the consensus rules for parsing the lock time require this limit, this is already implemented correctly

I'll update that ticket.

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-0 Overwinter Network Upgrade: Overwinter specific tasks (Sprout after Overwinter)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants