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 msg.data environment variable VIP-1181 #2343

Merged
merged 12 commits into from
Apr 9, 2021

Conversation

skellet0r
Copy link
Contributor

@skellet0r skellet0r commented Apr 5, 2021

What I did

As per #1181, I added the msg.data environment variable, allowing access to the complete calldata within external functions.

Also updated the docs to include information on the syntax/usage of msg.data.

How I did it

  1. Defined the data member in the msg environment variable - vyper/context/environment.py
  2. Modified the StatementAnnotationVisitor to attach metadata to the msg.data node depending on usage - vyper/context/validation/annotation.py
  3. Added the msg.data branch in the parse_Attribute fn, to return the appropriate LLLNode based on whether usage is in len or slice - vyper/parser/expr.py
  4. Modified code validation to throw a StateAccessViolation when msg.data is used inside an internal function - vyper/context/validation/local.py
  5. Modified code validation to throw a SyntaxException when msg.data is used outside of len or slice

Similar to before this copies the calldata to an internal variable before it gets sliced, I'm sure in the future we can work on cacheing msg.data but that's a whole 'nother beast. The use of len(msg.data) simply just used the calldatasize opcode and isn't as bad I hope.

How to verify it

I've added a few tests, which can be found in tests/parser/syntax/test_msg_data.py.

Description for the changelog

Added msg.data syntax allowing access to full calldata in external functions

Cute Animal Picture

Cute Animal Picture

Closes #1181

Copy link
Member

@fubuloubu fubuloubu left a comment

Choose a reason for hiding this comment

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

I was thinking the implementation would be slightly different, more like this:

tests/parser/syntax/test_msg_data.py Outdated Show resolved Hide resolved
tests/parser/syntax/test_msg_data.py Outdated Show resolved Hide resolved
tests/parser/syntax/test_msg_data.py Outdated Show resolved Hide resolved
tests/parser/syntax/test_msg_data.py Outdated Show resolved Hide resolved
docs/constants-and-vars.rst Outdated Show resolved Hide resolved
docs/constants-and-vars.rst Outdated Show resolved Hide resolved
docs/constants-and-vars.rst Outdated Show resolved Hide resolved
.pre-commit-config.yaml Outdated Show resolved Hide resolved
@skellet0r
Copy link
Contributor Author

skellet0r commented Apr 6, 2021

Ahhh @fubuloubu I like that syntax/implementation better, since it looks like one is explicitly extracting a piece of the calldata, instead of the syntax I used which looks like indexing a reference to calldata. I'll get to work on adjusting 👍

@codecov-io
Copy link

codecov-io commented Apr 8, 2021

Codecov Report

Merging #2343 (806a4c0) into master (84be2b5) will increase coverage by 0.03%.
The diff coverage is 96.66%.

❗ Current head 806a4c0 differs from pull request most recent head 9cf8d76. Consider uploading reports for the commit 9cf8d76 to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2343      +/-   ##
==========================================
+ Coverage   85.73%   85.77%   +0.03%     
==========================================
  Files          90       90              
  Lines        8765     8795      +30     
  Branches     2091     2099       +8     
==========================================
+ Hits         7515     7544      +29     
  Misses        760      760              
- Partials      490      491       +1     
Impacted Files Coverage Δ
vyper/context/validation/annotation.py 92.37% <85.71%> (-0.42%) ⬇️
vyper/context/environment.py 100.00% <100.00%> (ø)
vyper/context/validation/local.py 90.76% <100.00%> (+0.36%) ⬆️
vyper/parser/expr.py 77.29% <100.00%> (+0.54%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 84be2b5...9cf8d76. Read the comment docs.

@skellet0r
Copy link
Contributor Author

Sorry for the force push ... not sure if that's accepted around these parts 👀
I didn't implement the compile-time bounds checking as you commented @fubuloubu, since there are times in which calldatasize will exceed the compile-time expected size. EIP-2771 for example. I also totally missed previously handling len(msg.data) so that's included now, as well as the right syntax slice(msg.data, x, k).

Copy link
Member

@fubuloubu fubuloubu left a comment

Choose a reason for hiding this comment

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

Sorry for the force push ... not sure if that's accepted around these parts

No worries, works for me!

I didn't implement the compile-time bounds checking as you commented @fubuloubu, since there are times in which calldatasize will exceed the compile-time expected size. EIP-2771 for example. I also totally missed previously handling len(msg.data) so that's included now, as well as the right syntax slice(msg.data, x, k).

This should be okay! I think if you try to pull calldata longer than CALLDATASIZE the EVM's behavior is to give you empty data. So, it should be safe. Also, it is okay for CALLDATASIZE to exceed the expected size, the check was that it is at least the expected size to make sure we don't run into empty values unexpectedly (leading to difficult-to-debug behavior).

As such, this PR is a great addition! Thank you!

docs/constants-and-vars.rst Show resolved Hide resolved
tests/parser/syntax/test_msg_data.py Outdated Show resolved Hide resolved
@skellet0r
Copy link
Contributor Author

Also, it is okay for CALLDATASIZE to exceed the expected size, the check was that it is at least the expected size to make sure we don't run into empty values unexpectedly.

ahh @fubuloubu I see what you mean, isn't that handled already though? Indirectly through vyper/parser/arg_clamps.py? I guess if you call a function and give it calldata with a length < EXPECTED_CALLDATASIZE, the arg clamps it's effectively just zero those args to the default values for the type?

I think if you try to pull calldata longer than CALLDATASIZE the EVM's behavior is to give you empty data. So, it should be safe

Should I remove that runtime bounds check then? Since like you said, if you slice past the bound of CALLDATASIZE you'll just get null bytes appended to the end. Could just leave as it is, and if any complaints remove the runtime bounds check.

@fubuloubu
Copy link
Member

fubuloubu commented Apr 8, 2021

Should I remove that runtime bounds check then?

I prefer to have it. For some reason I misread and thought you hadn't implemented it, but I see now that you did!

@skellet0r
Copy link
Contributor Author

Awesome! The checks just have to run through one last time and should be good then 🤞

- Assignment to storage
- Free memory pointer correctly goes to next position
- TypeMismatch Error for assignment to bytes32
@skellet0r
Copy link
Contributor Author

skellet0r commented Apr 9, 2021

What happens if I assign a slice of msg.data to a storage variable?

@iamdefinitelyahuman that's a good test case I didn't include, I added it in, looks like that works as expected, along with the memory position advancement, and assignment to bytes32 throwing a TypeMismatch exception.

Copy link
Contributor

@iamdefinitelyahuman iamdefinitelyahuman left a comment

Choose a reason for hiding this comment

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

Great job!

Copy link
Member

@fubuloubu fubuloubu left a comment

Choose a reason for hiding this comment

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

lgtm

@fubuloubu fubuloubu merged commit 398866d into vyperlang:master Apr 9, 2021
@skellet0r skellet0r deleted the feat/vip-1181 branch April 11, 2021 03:53
@mahsaC28
Copy link

does anyone know how can I do this without use msg.data???

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.

VIP: msg.data
5 participants