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

Move timestamp verification into validity window package #1895

Merged
merged 5 commits into from
Jan 31, 2025

Conversation

aaronbuchwald
Copy link
Collaborator

@aaronbuchwald aaronbuchwald commented Jan 27, 2025

This PR moves timestamp verification checks into the time validity window package. Same code will be shared across tx and chunks.

@aaronbuchwald aaronbuchwald marked this pull request as ready for review January 27, 2025 21:37
),
wantErr: ErrInvalidChunk,
producerNode: nodeID,
nodeLastAcceptedTimestamp: 1,
chunkExpiry: 1 + int64(testingDefaultValidityWindowDuration),
chunkExpiry: 2 + int64(testingDefaultValidityWindowDuration),
Copy link
Contributor

Choose a reason for hiding this comment

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

not opposing to, but - was this change intentional ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is needed to get the boundary test case passing and align with the behavior of the time validity window. These two were slightly different in how they enforced it.

Previous boundary verification: https://github.com/ava-labs/hypersdk/blob/main/x/dsmr/storage.go#L80
Tx boundary verification: https://github.com/ava-labs/hypersdk/blob/main/chain/base.go#L39

When we call SetMin on the validity window for timestamp t, we will clear out all containers that are strictly less than timestamp t: https://github.com/ava-labs/hypersdk/blob/main/internal/emap/emap.go#L101. This means that allowing a transaction in at the forward boundary ie. blkTimestamp + validityWindow at blkTimestamp, the transaction will be screened out and marked as invalid in any future block with a timestamp up to and including blkTimestamp + validityWindow. After that, it will be marked as invalid because it has expired.

I'll write up a comment and add a test case inside the validitywindow package.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a test here: 3278211

The previous code in chunk verification was overly defensive - it would mark a chunk as invalid if it was at the validity window duration in the future. This would be required if the emap removed any containers <= the current minimum timestamp.

@@ -184,11 +183,10 @@ func (v *TimeValidityWindow[T]) calculateOldestAllowed(timestamp int64) int64 {
return max(0, timestamp-v.getTimeValidityWindow(timestamp))
}

func VerifyTimestamp(containerTimestamp int64, executionTimestamp int64, validityWindow int64) error {
func VerifyTimestamp(containerTimestamp int64, executionTimestamp int64, divisor int64, validityWindow int64) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

the term divisor is mathematically correct, but a bit misleading, imho. I'd opt to use the term gradient or frame here.

Copy link
Contributor

Choose a reason for hiding this comment

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

gradient doesn't make sense to me IMO... I also don't like the divisor name but I don't have a good concrete suggestion... I would probably call this something like boundary but I also feel like this name is not amazing

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

divisor is the right term, old code had referred to this as modulus which I don't think was right.

Happy to change if there's a better term, otherwise will leave as is since it seems the consensus here is that we don't love the term, but it is the most correct, and we don't have a better one. I do agree with both of you though haha.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like we're now referring this as boundary anyways in this test, should we rename? 3278211

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't see any place in the added test where we are referring to the divisor as boundary. In that test, we are passing in 1 (ie. there's no such thing as a misaligned timestamp) in each instance.

Comment on lines +190 to +192
case containerTimestamp < executionTimestamp: // expiry: 100 block: 110
return fmt.Errorf("%w: timestamp (%d) < block timestamp (%d)", ErrTimestampExpired, containerTimestamp, executionTimestamp)
case containerTimestamp > executionTimestamp+validityWindow: // expiry: 100 block 10
Copy link
Contributor

Choose a reason for hiding this comment

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

These were in the old code but I feel like we should delete these comments as part of this diff anyways

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I find these helpful, would prefer not to delete. Would you prefer they be moved in some way?

Copy link
Contributor

@joshua-kim joshua-kim Jan 28, 2025

Choose a reason for hiding this comment

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

IMO it's unnecessary to comment to explain how < and > work, but if you find it helpful feel free free to leave it in. IMO these lines are self-documenting

Comment on lines -519 to +524
chunkExpiry: 1 + int64(testingDefaultValidityWindowDuration),
chunkExpiry: 2 + int64(testingDefaultValidityWindowDuration),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this diff needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Comment on lines +325 to +335
// Verify a timestamp at the validity window boundary fails for both a processing
// and accepted parent.
// Processing:
r.ErrorIs(validityWindow.VerifyExpiryReplayProtection(context.Background(), blk2), ErrDuplicateContainer)

// Accepted:
validityWindow.Accept(blk1)
r.ErrorIs(validityWindow.VerifyExpiryReplayProtection(context.Background(), blk2), ErrDuplicateContainer)

// Verify that after passing the validity window, the timestamp is no longer valid
r.ErrorIs(VerifyTimestamp(validityWindowDuration, validityWindowDuration+1, 1, validityWindowDuration), ErrTimestampExpired)
Copy link
Contributor

Choose a reason for hiding this comment

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

All of these look like separate test cases to me, can we make them separate tests? I don't think this is going to work well in a table-test which is why I suspect this test was written this way, but the cost of copy-and-paste is not that bad and I would prefer we did that over having a single monolithic test that tests multiple cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought of this as the lifespan of a single tx being invalidated, but can break it up / see about making it a table test

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a separate table test for VerifyTimestamp and kept this test showing the lifespan of the tx (with an added comment).

The combination of the newly added test and the existing VerifyExpiryReplayProtection tests provides the same coverage (already covers processing/accepted at the boundary). Happy to remove this test if you prefer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@aaronbuchwald aaronbuchwald merged commit 397710b into main Jan 31, 2025
17 checks passed
@aaronbuchwald aaronbuchwald deleted the move-verify-timestamp-validity-window branch January 31, 2025 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants