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

[sui-execution] Verifier trait creates and accepts Meter #16941

Merged
merged 1 commit into from
Apr 4, 2024

Conversation

amnn
Copy link
Member

@amnn amnn commented Mar 28, 2024

Description

Supersede Verifier::meter_compiled_modules_with_overrides by:

  • Allowing meter_compiled_modules and meter_compiled_bytes to accept a custom meter.
  • Extracting the generation of VerifierConfig out to the sui-protocol-config crate.
  • Splitting up VerifierConfig into itself and MeterConfig.
  • Adding a Verifier::meter function for creating the meter that is used during signing.
  • Removed the meter as a field of each Verifier.

This means that we can now pass a different meter type when we don't want to enforce metering, and no longer need to modify the config in-place to achieve the same result.

To make this work, I needed to enable the use of a &mut dyn Meter trait object to instantiate what was previously a &mut impl Meter parameter everywhere. To do this, I created a forwarding trait implementation of Meter for &mut dyn Meter and added an extra relaxation of + ?Sized to all the &mut impl Meter parameters to allow the trait object to instantiate them.

This is in preparation for passing a custom meter into this new parameter when instantiated by the CLI to capture all information about scopes during metering.

Today we don't do that which means:

  • We only report back information about the last module and function we verified.
  • We can incorrectly report that everything is fine, (package would pass verification) even if there was some previous module or function that exceeded the stated limits.

Test Plan

sui$ cargo build --bin sui
sui$ cargo simtest
sui$ env SUI_SKIP_SIMTESTS=1 cargo nextest run
external-crates$ ./tests.sh
deepbook$ cargo run --bin sui -p sui -- client verify-bytecode-meter

Stack

@amnn amnn requested review from tzakian, dariorussi, stefan-mysten and a team March 28, 2024 23:05
@amnn amnn self-assigned this Mar 28, 2024
@amnn amnn requested a review from mystenmark as a code owner March 28, 2024 23:05
Copy link

vercel bot commented Mar 28, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
explorer ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 4, 2024 10:59pm
mysten-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 4, 2024 10:59pm
sui-core ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 4, 2024 10:59pm
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2024 10:59pm
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2024 10:59pm
sui-typescript-docs ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2024 10:59pm

Copy link
Member Author

Choose a reason for hiding this comment

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

This file contains the main change -- everything else flows from this.

Comment on lines +2078 to +2093
Some(self.max_back_edges_per_function() as usize),
Some(self.max_back_edges_per_module() as usize),
)
} else {
(None, None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this sort of split? I thought we used the DummyMeter outside of signing (in which case these would be ignored?)

Copy link
Member Author

Choose a reason for hiding this comment

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

The problem is that these configs are not part of metering, they are part of the verifier itself. I do think it's a bit incongruous that we change these verifier configs to be more restrictive during signing, but I didn't want to remove them.

Previously we were using the same Meter whether it was signing or not, and had to pass it different parameters. This PR changes that requirement, so it highlights this incongruity a bit more. I think it's something we can definitely revisit -- it would clean things up even more.

@@ -70,7 +70,7 @@ pub(crate) fn verify<'a>(
resolver: &'a BinaryIndexedView<'a>,
function_view: &FunctionView,
name_def_map: &'a HashMap<IdentifierIndex, FunctionDefinitionIndex>,
meter: &mut impl Meter,
meter: &mut (impl Meter + ?Sized),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to change the declaration of Meter to something like trait Meter: ?Sized to reduce the number of changes here?

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -71,7 +71,7 @@ fn test_max_number_of_bytecode() {
let module = dummy_procedure_module(nops);

let result =
CodeUnitVerifier::verify_module(&VerifierConfig::unbounded(), &module, &mut DummyMeter);
CodeUnitVerifier::verify_module(&VerifierConfig::default(), &module, &mut DummyMeter);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did a lot of these change from unbounded to default?

Copy link
Member Author

Choose a reason for hiding this comment

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

Previously the config for the meter and for the verifier were coupled, and the only difference between VerifierConfig::unbounded and VerifierConfig::default were parameters that actually belong to the meter. By creating a separate MeterConfig, I got rid of the distinction (the parameters were unused anyway because here we're passing in a DummyMeter).

Base automatically changed from amnn/verify-meter to main April 4, 2024 22:23
Supersede `Verifier::meter_compiled_modules_with_overrides` by:

- Allowing `meter_compiled_modules` and `meter_compiled_bytes` to
  accept a custom meter.
- Extracting the generation of `VerifierConfig` out to the
  `sui-protocol-config` crate.
- Splitting up `VerifierConfig` into itself and `MeterConfig`.
- Adding a `Verifier::meter` function for creating the meter that is
  used during signing.
- Removed the meter as a field of each `Verifier`.

This means that we can now pass a different meter type when we don't
want to enforce metering, and no longer need to modify the config
in-place to achieve the same result.

To make this work, I needed to enable the use of a `&mut dyn Meter`
trait object to instantiate what was previously a `&mut impl Meter`
parameter everywhere. To do this, I created a forwarding trait
implementation of `Meter` for `&mut dyn Meter` and added an extra
relaxation of `+ ?Sized` to all the `&mut impl Meter` parameters to
allow the trait object to instantiate them.

This is in preparation for passing a custom meter into this new
parameter when instantiated by the CLI to capture all information
about scopes during metering.

Today we don't do that which means:

- We only report back information about the last module and function
  we verified.
- We can incorrectly report that everything is fine, (package would
  pass verification) even if there was some previous module or
  function that exceeded the stated limits.

Test Plan:

```
sui$ cargo build --bin sui
sui$ cargo simtest
sui$ env SUI_SKIP_SIMTESTS=1 cargo nextest run
external-crates$ ./tests.sh
deepbook$ cargo run --bin sui -p sui -- client verify-bytecode-meter
```
@amnn amnn merged commit f8809c0 into main Apr 4, 2024
43 checks passed
@amnn amnn deleted the amnn/verify-meter-trait branch April 4, 2024 23:31
amnn added a commit that referenced this pull request Apr 4, 2024
## Description

The motivation for this change is to properly track the modules being
visited in the `Meter`, so that in our command line tool, we can provide
an output that correctly tracks how many meter ticks were used to verify
each function and module.

Prior to this change, the metered verifier pretended like there was only
"one module" that all the functions being verified were in. This change
introduces the level of packages that ticks from modules are transferred
to.

We also add an explicit protocol config parameter to set a max tick
limit per package (whose value is the same as the function and module
level limits currently). This was not strictly necessary but was done to
avoid confusion (caused by treating the module level limit as the
package level limit).

This should be a behaviour preserving change, but in some cases we may
do more work verifying transactions because of how the ticks for each
module are now gathered in isolation before being transferred to the
package scope. In any case, a behaviour change would be okay, because
metering (and related errors) is only used during signing, and not
execution.

## Test Plan

```
sui$ cargo simtest
deepbook$ cargo run --bin sui -p sui -- client verify-bytecode-meter
```

## Stack

- #16903 
- #16941
amnn added a commit that referenced this pull request Apr 8, 2024
…6963)

## Description

Use a custom meter to track every function and module that is verified,
and display all of them.

## Test Plan

```
deepbook$ cargo run --bin sui -p sui \
  -- client verify-bytecode-meter    \
  --module build/DeepBook/bytecode_modules/math.mv

╭──────────────────────────────────────╮
│ Package will pass metering check!    │
├──────────────────────────────────────┤
│ Limits                               │
├─────────────────────────┬────────────┤
│ packages                │ 16,000,000 │
│   modules               │ 16,000,000 │
│     functions           │ 16,000,000 │
├─────────────────────────┴────────────┤
│ Ticks Used                           │
├─────────────────────────┬────────────┤
│ <unknown>               │     41,915 │
│   math                  │     41,915 │
│     unsafe_mul          │      1,225 │
│     unsafe_mul_round    │      5,675 │
│     mul                 │      2,410 │
│     mul_round           │      2,905 │
│     unsafe_div          │      1,225 │
│     unsafe_div_round    │      6,085 │
│     div_round           │      2,905 │
│     count_leading_zeros │     19,485 │
├─────────────────────────┴────────────┤
│ Package will pass metering check!    │
╰──────────────────────────────────────╯
```

## Stack

- #16903
- #16941 
- #16945 

---
If your changes are not user-facing and do not break anything, you can
skip the following section. Otherwise, please briefly describe what has
changed under the Release Notes section.

### Type of Change (Check all that apply)

- [ ] protocol change
- [x] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

`sui client verify-bytecode-meter` prints a breakdown of verifier cost
by module and function in a package.
amnn added a commit that referenced this pull request Apr 8, 2024
When passing modules to `sui client verify-bytecode-meter`, support
passing multiple `--modules` to be treated as a single package.

## Test Plan

```
deepbook$ cargo run --bin sui -p sui               \
  -- client verify-bytecode-meter                  \
  --module build/DeepBook/bytecode_modules/math.mv \
  --module build/DeepBook/bytecode_modules/clob.mv

Running bytecode verifier for 2 modules
╭──────────────────────────────────────────────────╮
│ Package will pass metering check!                │
├──────────────────────────────────────────────────┤
│ Limits                                           │
├─────────────────────────────────────┬────────────┤
│ packages                            │ 16,000,000 │
│   modules                           │ 16,000,000 │
│     functions                       │ 16,000,000 │
├─────────────────────────────────────┴────────────┤
│ Ticks Used                                       │
├─────────────────────────────────────┬────────────┤
│ <unknown>                           │  1,859,140 │
│   math                              │     41,915 │
│     unsafe_mul                      │      1,225 │
│     unsafe_mul_round                │      5,675 │
│     mul                             │      2,410 │
│     mul_round                       │      2,905 │
│     unsafe_div                      │      1,225 │
│     unsafe_div_round                │      6,085 │
│     div_round                       │      2,905 │
│     count_leading_zeros             │     19,485 │
│   clob                              │  1,817,225 │
│     destroy_empty_level             │      1,205 │
│     create_account                  │        360 │
│     create_pool                     │        480 │
│     deposit_base                    │      5,490 │
│     deposit_quote                   │      5,490 │
│     withdraw_base                   │      6,500 │
│     withdraw_quote                  │      6,500 │
│     swap_exact_base_for_quote       │     20,805 │
│     swap_exact_quote_for_base       │     18,590 │
│     match_bid_with_quote_quantity   │    383,275 │
│     match_bid                       │    310,200 │
│     match_ask                       │    316,500 │
│     place_market_order              │     37,615 │
│     inject_limit_order              │     70,195 │
│     place_limit_order               │    184,740 │
│     order_is_bid                    │        540 │
│     emit_order_canceled             │      4,905 │
│     emit_order_filled               │      8,335 │
│     cancel_order                    │     57,890 │
│     remove_order                    │     20,095 │
│     cancel_all_orders               │     64,425 │
│     batch_cancel_order              │    102,405 │
│     list_open_orders                │     57,300 │
│     account_balance                 │      6,620 │
│     get_market_price                │      3,265 │
│     get_level2_book_status_bid_side │     39,785 │
│     get_level2_book_status_ask_side │     39,785 │
│     get_level2_book_status          │     23,545 │
│     get_order_status                │     20,385 │
├─────────────────────────────────────┴────────────┤
│ Package will pass metering check!                │
╰──────────────────────────────────────────────────╯
```

## Stack

- #16903 
- #16941 
- #16945 
- #16963 

---
If your changes are not user-facing and do not break anything, you can
skip the following section. Otherwise, please briefly describe what has
changed under the Release Notes section.

### Type of Change (Check all that apply)

- [ ] protocol change
- [x] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

`sui client verify-bytecode-meter` supports passing multiple `--module`
flags to verify multiple compiled modules together as if they were one
package.
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.

2 participants