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

test: MBT: Add partial set security to model #1614

Closed
wants to merge 54 commits into from
Closed

Conversation

p-offtermatt
Copy link
Contributor

@p-offtermatt p-offtermatt commented Jan 31, 2024

Description

Closes: #1574

Adds partial set security to the Quint model.

This PR only contains logic, tests, and sanity checks, but no invariants yet.
The invariants are becoming more subtle and harder to define, so I want to see whether to prioritise MBT or defining the invariants first.

Highlights:

  • ccv_pss contains the logic for calculating the top N set. Notice it can be much simpler because I don't need synthetic updates, I just send the whole set
  • in ccv.qnt, some things changed to accomodate sending the partial validator sets

Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • Included the correct type prefix in the PR title
  • Targeted the correct branch (see PR Targeting)
  • Provided a link to the relevant issue or specification
  • Reviewed "Files changed" and left comments if necessary
  • Confirmed all CI checks have passed (test failure for MBT is expected)

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • Confirmed the correct type prefix in the PR title
  • Confirmed all author checklist items have been addressed
  • Confirmed that this PR does not change production code

@p-offtermatt p-offtermatt marked this pull request as ready for review February 5, 2024 13:31
@p-offtermatt p-offtermatt requested a review from a team as a code owner February 5, 2024 13:31
@@ -139,6 +139,71 @@ module extraSpells {
__set.fold(List(), (__l, __e) => __l.append(__e))
}

/// The type of orderings between comparable things
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the /// here and later instead of //?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, this is copy-pasted from the Quint "standard library" (there is no actual standard library yet, so copy-pasting what you need is atm the canonical way of using it) and their style differs sometimes

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. I guess in this case we could adhere to our own standard with just //.

@github-actions github-actions bot added the C:Build Assigned automatically by the PR labeler label Feb 6, 2024
import extraSpells.* from "./libraries/extraSpells"
import ccv_utils.* from "./ccv_utils"

// Given a base validator set, an N for a top N chain, and a set of validators that have opted in to the chain,
Copy link
Contributor

Choose a reason for hiding this comment

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

The way I read this, I would expect that an N parameter to this function which is not the case.

// Given a base validator set, an N for a top N chain, and a set of validators that have opted in to the chain,
// returns the validator set that should be sent to the chain.
// Assumes that the value for N is valid.
pure def GetPSSValidatorSet(providerState: ProviderState, origValSet: ValidatorSet, consumer: Chain): ValidatorSet = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to take the origValSet as a parameter here? Isn't this something we can extract from the providerState?

res._1
}

// Opts a validator in for a consumer chain the provider.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Opts a validator in for a consumer chain the provider.
// Opts a validator in for a consumer chain of the provider.

val topNVals = GetTopNVals(proviValSet, providerState.topNByConsumer.get(consumer))
val prevOptedInVals = providerState.optedInVals.getOrElse(consumer, Set())
// opt in all the top N validators, i.e. union the top N vals with the previous opted in vals
val newOptedInVals = providerState.optedInVals.put(consumer, prevOptedInVals.union(topNVals))
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess because we have sets here, we're guaranteed that a validator that IsTopN and has opted in only appears once at the optedInVals, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, exactly!

currentState.providerState.optedInVals.getOrElse(consumer, Set()).contains(validator)
}

// Opts a validator out. Safe to call before the consumer chain even runs.
Copy link
Contributor

Choose a reason for hiding this comment

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

Safe to call before the consumer chain even runs.

Regarding the implementation of this (although we do not have the code yet), I was thinking that we should not allow validators to opt out before the chain has started running. This is because, we assume validator that voted Yes on a ConsumerAdditionProposal are opted in by default, so it would be weird to give them the right to opt out before the chain starts. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. My thought was to use this, at the time the consumer starts, to determine who voted yes on the proposal (and is thus opted in), but maybe I am cutting too many corners here and it is not as clear.
But essentially I think this is an implementation detail and maybe abstracting away like I did is ok, but I would love to know if you disagree

Copy link
Contributor

@insumity insumity Feb 6, 2024

Choose a reason for hiding this comment

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

at the time the consumer starts, to determine who voted yes on the proposal (and is thus opted in) [...]

Thanks for your answer. This makes sense. We can leave as is :)


run TopNTest =
val valSet =
Map("a" -> 5, "a1" -> 5, "a2" -> 5, "b" -> 10, "b1" -> 10, "b2" -> 10, "c" -> 15, "c1" -> 15, "e" -> 25)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Why e is the last one and not d?

Copy link
Contributor

Choose a reason for hiding this comment

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

Might make sense to have the map written in descending order so it would be slightly clearer that e would be the first validator to be returned, then e, c1 and c, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

d was rationalized away at some point and I didn't change this :D
yeah, sorting the map the other way around is also a great point

assert(GetTopNVals(valSet, 85) == Set("e", "c1", "c", "b2", "b1", "b")),
assert(GetTopNVals(valSet, 86) == Set("e", "c1", "c", "b2", "b1", "b", "a2", "a1", "a")),
assert(GetTopNVals(valSet, 95) == Set("e", "c1", "c", "b2", "b1", "b", "a2", "a1", "a")),
assert(GetTopNVals(valSet, 100) == Set("e", "c1", "c", "b2", "b1", "b", "a2", "a1", "a")),
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Why not GetTopNVals(valSet, 100) == valSet?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. need to be valSet.keys(), because valSets are actually maps.. but still more descriptive :)

Copy link
Contributor

@insumity insumity left a comment

Choose a reason for hiding this comment

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

Great work! Thanks @p-offtermatt.

Would it make sense to merge this under the feat/partial-set-security branch? I'm suggesting this because it might take quite some time until we merge feat/partial-set-security back to main so it might complicate your upcoming MBT work.

@p-offtermatt
Copy link
Contributor Author

Great work! Thanks @p-offtermatt.

Would it make sense to merge this under the feat/partial-set-security branch? I'm suggesting this because it might take quite some time until we merge feat/partial-set-security back to main so it might complicate your upcoming MBT work.

Great point - let me retarget this.

@p-offtermatt p-offtermatt changed the base branch from main to feat/partial-set-security February 6, 2024 12:47
@p-offtermatt p-offtermatt changed the base branch from feat/partial-set-security to main February 6, 2024 13:11
@p-offtermatt
Copy link
Contributor Author

Great work! Thanks @p-offtermatt.
Would it make sense to merge this under the feat/partial-set-security branch? I'm suggesting this because it might take quite some time until we merge feat/partial-set-security back to main so it might complicate your upcoming MBT work.

Great point - let me retarget this.

That gave a lot of modified files, I think I will rather just make a new branch with the correct branch and cherry-pick.

@p-offtermatt
Copy link
Contributor Author

Closed in favor of #1627

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C:Build Assigned automatically by the PR labeler C:Testing Assigned automatically by the PR labeler
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Spike: Prototype Partial Set Security in Quint
2 participants