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

Add Formal Specifications for Vouch & Burn Module Safety and Correctness #328

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Jayfromthe13th
Copy link

@Jayfromthe13th Jayfromthe13th commented Nov 17, 2024

Description:
This PR adds comprehensive formal specifications to the vouch module to ensure safety, correctness, and proper state management. The specifications verify critical properties of the vouching system.

File Location:
vouch.spec.move

Key Specifications Added:

  1. Global Invariants:
  • Ensures vector alignment between incoming_vouches and epoch_vouched
  • Maintains consistency of vouch state across operations
  1. Function Specifications:
  • true_friends(): Verifies correct friend relationship validation
  • revoke(): Ensures proper vouch removal and state updates
  • all_not_expired(): Validates epoch-based expiration logic
  • is_valid_voucher_for(): Confirms voucher validity
  • bulk_set(): Ensures atomic updates of vouch records
  1. Safety Properties:
  • No self-vouching allowed
  • Proper initialization checks
  • Maximum vouch limit enforcement
  • Expiration period validation
  1. State Management:
  • VouchInvariant schema for consistent state transitions
  • Proper handling of GivenVouches and ReceivedVouches
  • Price calculation verification

These specifications help ensure:

  • Vector alignment invariants are maintained
  • Proper validation of vouch operations
  • Safe revocation procedures
  • Correct expiration checks
  • Consistent state management

Testing:

  • All specifications verified using Move Prover
  • Aborts conditions properly specified
  • State transitions verified

Screenshot 2024-11-14 230444

Add Formal Specifications for Burn Module Safety and Correctness

This PR adds comprehensive formal specifications to the burn module to ensure safety, correctness, and proper state management of burning operations.

File Location:
burn.spec.move

Key Specifications Added:

  1. Global Invariants:
  • Ensures BurnCounter is always initialized before operations
  • Maintains lifetime burned and recycled counters within MAX_U64
  • Enforces consistent state management across burn operations
  1. Function Specifications:
  • initialize(): Verifies proper initialization of burn counter
  • epoch_burn_fees(): Ensures safe fee burning and state updates
  • burn_and_track(): Validates burn operations and counter updates
  • set_send_community(): Manages community burn preferences
  1. Safety Properties:
  • Arithmetic overflow prevention for burn counters
  • Authorization checks for privileged operations
  • Resource existence validation
  • Safe state transitions during burns
  1. State Management:
  • BurnCounter resource invariants
  • UserBurnPreference state consistency
  • Proper tracking of burned and recycled amounts
  • Safe counter updates during operations

These specifications help ensure:

  • Safe initialization of burn tracking
  • Proper authorization for burn operations
  • Prevention of counter overflows
  • Consistent state updates during burns
  • Safe community preference management

Testing:

  • All specifications verified using Move Prover
  • Abort conditions comprehensively specified
  • State transitions fully verified
  • Resource management safety confirmed

The burn module specifications provide critical safety guarantees for:

  1. Tracking burned coins accurately
  2. Managing recycled amounts safely
  3. Handling community burn preferences
  4. Maintaining consistent burn state
  5. Preventing unauthorized operations

These formal specifications help ensure the burn module operates safely and correctly under all conditions.

damn101

Jayfromthe13th and others added 5 commits November 17, 2024 13:28
- Added global invariants for vector alignment
- Added specs for true_friends, revoke, all_not_expired
- Added VouchInvariant schema
- Added specs for bulk_set and get_vouch_price
added indepth spec for burn.move module
@Jayfromthe13th Jayfromthe13th changed the title Add Formal Specifications for Vouch Module Safety and Correctness Add Formal Specifications for Vouch & Burn Module Safety and Correctness Nov 20, 2024
Copy link
Contributor

@0o-de-lally 0o-de-lally left a comment

Choose a reason for hiding this comment

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

Really tremendous first PR! No changes necessary to merge. There are a couple opportunities for more code comments.
Amazing!

pragma aborts_if_is_strict = true;

// Global invariant: BurnCounter must be initialized before any operations
invariant [suspendable] exists<BurnCounter>(@ol_framework);
Copy link
Contributor

Choose a reason for hiding this comment

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

good one, an important check for all system state


spec BurnCounter {
// Resource invariant
invariant lifetime_burned <= MAX_U64;
Copy link
Contributor

Choose a reason for hiding this comment

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

nice. it might be good to check that some of the interim calculations don't overflow as well.

let addr = signer::address_of(vm);

// Preconditions
requires system_addresses::is_ol_framework_address(addr);
Copy link
Contributor

Choose a reason for hiding this comment

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

Great. For future reference: this is an important check for all initializers. There is the 0x0 address which is the VM and the 0x1 which is framework. In the past, and in tests we have used is_root(), which would actually cause missing state if we used 0x0. So yes, this is an important check going forward.

ensures global<BurnCounter>(@ol_framework).lifetime_recycled == 0;
}

spec epoch_burn_fees {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nicely done here. Perhaps add a comment about where result_1 comes from.

old(global<BurnCounter>(@ol_framework).lifetime_recycled);
}

spec set_send_community(sender: &signer, community: bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good. One check we could possibly add for completeness, is that system addresses should not be able to add this.

pragma verify = true;
pragma aborts_if_is_strict = false;

// Global invariant: ensure vectors are always aligned
Copy link
Contributor

Choose a reason for hiding this comment

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

Great! Something we have been concerned about in the past.

@@ -0,0 +1,93 @@
spec ol_framework::vouch {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be great if you added the same code comments as you did in burn.move.spec: preconditions, aborts, postconditions.


spec is_valid_voucher_for(voucher: address, recipient: address): bool {
aborts_if false;
ensures result == vector::contains(true_friends(recipient), voucher);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not 100% what is being checked here, it may be I forgot how it this check works. Can you add a comment?

@0o-de-lally
Copy link
Contributor

@Jayfromthe13th All looks good above, except that one of our CI tests is failing on a Move compilation issue. I haven't seen this before. The rest of the Move code compiles and tests fine. It's just on our Upgrade verification.

https://github.com/0LNetworkCommunity/libra-framework/actions/runs/11947536237/job/33395319449#step:5:1190

@dboreham
Copy link
Contributor

This looks great thanks. However I noticed that these tests appear to fail in CI:
https://github.com/0LNetworkCommunity/libra-framework/actions/runs/11947536238/job/33395302385#step:5:308
Even more interesting -- the CI job actually shows as passing even though there are fatal errors output by the move prover.
So presumably we have a bug somewhere in the connecting up between test result and action step pass/fail?

@kalvkusk
Copy link
Contributor

run: make -f prover.mk prove
possibly subcommand that runs actual prover tests fails, but make command exits with 0 ( success), hence the job is marked success.

@Jayfromthe13th
Copy link
Author

Thanks for the feedback. I'll make those changes @0o-de-lally . Also, thanks for catching this @dboreham ! It does seem like there's an issue with the make command not propagating the error correctly. I’ll investigate further and see locally to confirm. Ik there was some recent updates with the fv which may be causing issues depending

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.

4 participants