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

Allow EOF creation transactions #878

Merged
merged 9 commits into from
May 31, 2024
Merged

Allow EOF creation transactions #878

merged 9 commits into from
May 31, 2024

Conversation

pdobacz
Copy link
Collaborator

@pdobacz pdobacz commented Apr 30, 2024

First approach to allowing EOF creation transactions, thereby making the creator contract not necessary to deploy first EOF.

Follows the design from ipsilon/eof#78 / ethereum/EIPs#8498

However the validation problem has been resolved differently - it seemed easier to remove the validation rule to never have stray bytes in a container from the main validation_eof and to put it in the spots where it applies (TXCREATE initcontainer and subcontainers). This way this rule doesn't apply to creation transaction containers.

The validation state_tests are broken and should be reworked similar to the validation tests we have here, in light of the above change to validation.

The commit history reflects some interim steps, will be squashed before merging.

Copy link

codecov bot commented Apr 30, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.29%. Comparing base (a1e64f7) to head (abafe4f).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #878      +/-   ##
==========================================
+ Coverage   98.26%   98.29%   +0.02%     
==========================================
  Files         131      131              
  Lines       15701    15968     +267     
==========================================
+ Hits        15429    15696     +267     
  Misses        272      272              
Flag Coverage Δ
ethereum-tests 27.40% <11.82%> (-0.47%) ⬇️
ethereum-tests-silkpre 19.31% <3.04%> (-0.33%) ⬇️
execution-spec-tests 18.70% <3.26%> (-0.31%) ⬇️
unittests 94.24% <100.00%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
lib/evmone/eof.cpp 87.33% <100.00%> (ø)
lib/evmone/eof.hpp 100.00% <100.00%> (ø)
test/state/errors.hpp 50.00% <ø> (-1.93%) ⬇️
test/state/host.cpp 98.31% <100.00%> (+0.12%) ⬆️
test/state/host.hpp 100.00% <ø> (ø)
test/state/state.cpp 91.45% <100.00%> (ø)
test/unittests/eof_example_test.cpp 100.00% <100.00%> (ø)
test/unittests/eof_validation_test.cpp 100.00% <100.00%> (ø)
...est/unittests/state_transition_eof_create_test.cpp 100.00% <100.00%> (ø)
test/unittests/state_tx_test.cpp 100.00% <100.00%> (ø)

@gumb0
Copy link
Member

gumb0 commented May 2, 2024

So this kinda changes the definition of validation (at least for top-level container), which I'm not very sure is acceptable. (It would mean every client has to implement it in this way)

My other idea was something like:

  • move stray data bytes check from validate_section_headers() to a level above to validate_header()
  • make validation_section_headers() public
  • call validation_section_headers() in Host::prepare_message() and sum up all section sizes to find the full container size and split to container/calldata
  • validate container normally

@pdobacz
Copy link
Collaborator Author

pdobacz commented May 6, 2024

  • validate container normally

Hm, you mean we redo all the previous steps (from validation_section_headers) in this last step?

@gumb0
Copy link
Member

gumb0 commented May 6, 2024

  • validate container normally

Hm, you mean we redo all the previous steps (from validation_section_headers) in this last step?

Yes, I would say it's fine. Or make another variant of validate_eof() which accepts already parsed section headers.

@pdobacz
Copy link
Collaborator Author

pdobacz commented May 7, 2024

The other approach is in 903dae2. I like it, but it broadens eof.hpp significantly, not sure if this is a problem. I'll give it some more thought later. Or we can just proceed and plan a rewrite of these APIs later?

@pdobacz
Copy link
Collaborator Author

pdobacz commented May 7, 2024

One thing I've noticed is this. validate_header performs duties which are beyond validating the header:

  • validate_types
  • the new condition check for no stray bytes

If we could move these two outside of validate_header, we could use validate_header to parse the EOF1Header struct and not have to call again into read_valid_eof1_header in host.cpp, This is the only thing I came up with so far, but I'm not sure it's worth doing such logistics at this point. WDYT? @gumb0

Otherwise this should be good to review.

@pdobacz pdobacz requested a review from gumb0 May 7, 2024 13:12
@pdobacz pdobacz marked this pull request as ready for review May 8, 2024 10:27
if (holds_alternative<EOFValidationError>(section_headers_or_error))
return {}; // Light early exception.

const auto header = read_valid_eof1_header(input);
Copy link
Member

Choose a reason for hiding this comment

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

it feels hacky to me, we don't read to re-parse the header at this point, we already have all section sizes returned from validate_section_headers() and can sum them up to find the split.

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 wanted to avoid the summing up, which we already handle in two places. BTW, did you see the comment #878 (comment), would this work in your opinion?

In general I would also prefer to take a safe and easy path now and possibly make a more thorough redesign of these validation routines, once we finalize the spec of the validations? There's still a lot of moving parts.

#include <vector>

namespace evmone
{
constexpr uint8_t MAGIC[] = {0xef, 0x00};
Copy link
Member

Choose a reason for hiding this comment

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

I didn't realize it will drag along all the constants into the header... What if instead of making validation_section_headers() public as is, we make a public wrapper of it that returns only full container size that we need? maybe like std::variant<size_t, EOFValidationError> validate_eof_section_headers(bytes_view)

Copy link
Member

Choose a reason for hiding this comment

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

Also MAGIC doesn't have to be in the header in any case, does it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

re MAGIC - yup, I grabbed too much. Re the fist comment, see my other comment and the idea to use validate_header instead.

@pdobacz
Copy link
Collaborator Author

pdobacz commented May 15, 2024

Okay, another version of. I figured that a new public wrapper of validate_section_headers would still not fully cut it, because we like to use the header.can_init in the creation transaction pipeline. But there was yet another possibility - to use validate_header, just moving the stray bytes check one level up (to validate eof1). It seems like a valid move, because the stray bytes check doesn't logically belong with validating the header... I suppose. This allows us to use that as the header parser in host.cpp. WDYT @gumb0 ?

This version needs to rely on #891 so that needs to merge first and then I force push the cherry-picked fix away.

@pdobacz pdobacz requested a review from gumb0 May 20, 2024 10:51
chfast pushed a commit that referenced this pull request May 24, 2024
While working on #878 I noticed the offset calculation in validate_header can overflow the uint16, if the _declared_ sizes of container sections are large. Currently there is no upper limit on container size in validation (there's only the indirect limit imposed by max_initcode_size), so there can be a large container, which has a subcontainer of size 0xffff, and will have it's `data_offset` not fit the uint16.

We have 2 tests which happened to run into this, but the problem was masked (the data_offset was just really tiny, despite the container had a huge subcontainer, but it was never used, and the check for stray data wasn't affected by the overflow). I adjust them so (IMO) they still test what they're supposed to test, but not overflow.
test/state/host.cpp Outdated Show resolved Hide resolved
test/state/state.cpp Outdated Show resolved Hide resolved
@pdobacz pdobacz requested a review from gumb0 May 29, 2024 09:51
@gumb0
Copy link
Member

gumb0 commented May 29, 2024

Looks good now, but there's weird clang-tidy warning now, not sure why.

@@ -256,7 +256,7 @@ std::optional<evmc_message> Host::prepare_message(evmc_message msg)
if (holds_alternative<EOFValidationError>(header_or_error))
return {}; // Light early exception.

const auto& header = std::get<EOF1Header>(header_or_error);
const auto header = std::get<EOF1Header>(header_or_error);
Copy link
Member

@gumb0 gumb0 May 29, 2024

Choose a reason for hiding this comment

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

So std::get is actually throwing, I guess that's why the warning.

  1. The reference shouldn't affect this I think, so would be good to report to clang-tidy if it's possible to reproduce on some minimal example
  2. To work around we can use get_if
                   const auto* header = std::get_if<EOF1Header>(&header_or_error);
                    if (!header)
                        return {};  // Light early exception.
  1. I think it makes sense to add noexcept to prepare_message()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But in validate_eof1 a similar pattern is OK, which is what throws me off completely. Thanks for the suggestions, I'll poke around this

Copy link
Member

@gumb0 gumb0 left a comment

Choose a reason for hiding this comment

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

Looks good, some squashing before merge would be nice

@pdobacz pdobacz merged commit 3417de7 into master May 31, 2024
25 checks passed
@pdobacz pdobacz deleted the isc-less-eof branch May 31, 2024 13:24
@pdobacz pdobacz linked an issue Jun 3, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EOF - implement EOF creation tx
3 participants