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

fork-choice test vectors: starting with get_head tests #2202

Merged
merged 9 commits into from
Mar 13, 2021

Conversation

hwwhww
Copy link
Contributor

@hwwhww hwwhww commented Feb 19, 2021

I’m transforming the current pyspec fork choice test cases into test vectors. 🧶

Test formats


Discussions

  1. Any suggestions on the above proposal?

  2. It's easy to convert get_head tests. However, in our on_block tests, we directly set the fields of Store to prepare the tests. For example:
    https://github.com/ethereum/eth2.0-specs/blob/8ec082fcf9ca58bf143977abb4dce9c8c417dbdd/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_block.py#L30-L31
    https://github.com/ethereum/eth2.0-specs/blob/8ec082fcf9ca58bf143977abb4dce9c8c417dbdd/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_block.py#L129-L132
    I may have to rewrite them to get rid of the Store field manipulations if we are going to follow the above test formats.

  3. Alternatively, we can output the whole store object. However, some drawbacks:

    • Store object could be really huge. We probably can only output Minimal config tests.
    • Client teams may have implemented the concept of Store in a very different, optimized solution.

20210313 updated:

See fork choice test format doc

@ericsson49
Copy link
Contributor

ericsson49 commented Feb 19, 2021

When I was designing my fork choice tests, I avoided explicit instantiation of Store objects, for the same reasons.
My fork choice tests are integration tests rather than unit tests, so I use sequences of tick, on_block and on_attestation events (along with initial state) to reach desired Store configurations.
That's of course more tricky, but with the approach, one is making less assumptions about implementation details. Which I believe is important for such kind of tests, as it can hinder implementer's optimizations or similar.

While any implementation should know how to handle on_tick, on_block and on_attestation, so it shouldn't be a big deal to integrate such tests with an existing implementation. I validated that while integrating my tests with Teku.

@djrtwo
Copy link
Contributor

djrtwo commented Feb 22, 2021

  1. The direct store manipulations are to avoid very inefficient state transitions and state copies found in on_block. We need to be careful not to inflate CI running time too much. A couple of options
    1. mod them and take the hit on CI. Might be quite a hit though
    2. put a conditional in the helpers that does full calls to on_block, etc, when running testgen, but store manipulations on CI. Do we have a conditional that can detect context? This is nice, but then there is a worry that the logic isn't 1:1 and some bug surfaces during testgen that you didn't catch in CI
    3. write some separate testgen scenarios that only run during testgen and no CI. Probably better than (2) but still has the issue that something might surface during the rarely run testgens

@ericsson49
Copy link
Contributor

To reduce test vector generation time, I have been using either a caching BLS implementation or a dummy BLS implementation (which is completely insecure, but still able to distinguish good and bad signatures).
Actually, for most fork choice tests one can switch off BLS checks, with a a couple of exceptions (wrong block or attestation signatures).

@djrtwo
Copy link
Contributor

djrtwo commented Feb 25, 2021

Right, and we have a test function decorator never_bls to do just that. The state trnasitions themselves can be very expensive in the unoptimized python as well though

@hwwhww hwwhww marked this pull request as ready for review March 11, 2021 16:52
@djrtwo
Copy link
Contributor

djrtwo commented Mar 11, 2021

So do we leave the fork choice unit tests untouched?

Copy link
Contributor

@djrtwo djrtwo left a comment

Choose a reason for hiding this comment

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

awesome! only minor comments

Should we remove the old unittest test_get_head file? This new file is strictly the previous functionality + generators, right?

tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
Copy link
Collaborator

@protolambda protolambda left a comment

Choose a reason for hiding this comment

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

Left some minor comments, looks good to me, nice work 👍

tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
tests/formats/fork_choice/README.md Outdated Show resolved Hide resolved
Comment on lines -129 to -130
for attestation in attestations:
spec.on_attestation(store, attestation)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: run_on_block will run on_attestation for each attestation from block.message.body.attestations.



@with_all_phases
@spec_state_test
@with_configs([MINIMAL], reason="too slow")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: the test generation time of other tests is acceptable, for me.

Comment on lines +109 to +110
- For each execution, look up the corresponding ssz_snappy file. Execute the corresponding helper function on the current store.
- For the `on_block` execution step: if `len(block.message.body.attestations) > 0`, execute each attestation with `on_attestation(store, attestation)` after executing `on_block(store, block)`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: on_block execution step implies running on_attestation.

Note that to execute on_attestation after on_block

Output more checking field

Disable mainnet config test_filtered_block_tree

Fix after rectoring + use more run_on_block

Fix and refactor `tick_and_run_on_attestation`
Copy link
Contributor

@djrtwo djrtwo left a comment

Choose a reason for hiding this comment

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

lgtm!

@hwwhww hwwhww merged commit 5dcc992 into dev Mar 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants