Skip to content

Use STATICCALL for pure function calls.#2966

Merged
axic merged 3 commits intodevelopfrom
useStaticCall
Mar 6, 2018
Merged

Use STATICCALL for pure function calls.#2966
axic merged 3 commits intodevelopfrom
useStaticCall

Conversation

@chriseth
Copy link
Contributor

No description provided.

@chriseth
Copy link
Contributor Author

This still needs tests and requires an updated version of cpp-ethereum.

Changelog.md Outdated

Features:
* Parser: Better error message for unexpected trailing comma in parameter lists.
* Code Generator: Use STATICCALL opcode for calling pure functions.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why pure only?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh right. I'm not yet fully awake...

if (isDelegateCall)
solAssert(!_functionType.valueSet(), "Value set for delegatecall");
else if (isStaticCall)
solAssert(!_functionType.valueSet(), "Value set for delegatecall");
Copy link
Contributor

Choose a reason for hiding this comment

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

Text is wrong.

bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall;
bool isCallCode = funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::CallCode;
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
bool isStaticCall = (_functionType.stateMutability() <= StateMutability::View);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer to have an experimental pragma for this.

bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
bool useStaticCall =
_functionType.stateMutability() <= StateMutability::View &&
m_context.experimentalFeatureActive(ExperimentalFeature::STATICCALL;
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo here

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed.

Changelog.md Outdated
(previously, some amount was retained in order to work in pre-tangerine whistle
EVM versions)
* Code Generator: Use STATICCALL opcode for calling view and pure functions. Enable
via `pragma experimental STATICCALL;`.
Copy link
Contributor

@axic axic Oct 16, 2017

Choose a reason for hiding this comment

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

Why don't we go for pragma experimental Byzantium;?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is still a question.

bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall;
bool isCallCode = funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::CallCode;
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
bool useStaticCall =
Copy link
Contributor

Choose a reason for hiding this comment

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

I think use suits this better, but the other two are named is so perhaps just go with isStaticCall or alternatively rename the other two to use?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a different thing. I would call it isStaticCall out of the function type, but useStaticCall tells whether the compiler is also allowed to use the opcode due to pragmas.

Copy link
Contributor

@axic axic left a comment

Choose a reason for hiding this comment

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

Needs tests, changelog update and a rebase.

@axic axic force-pushed the useStaticCall branch 2 times, most recently from e952b6f to 1e04cc3 Compare December 12, 2017 02:48
@axic
Copy link
Contributor

axic commented Dec 12, 2017

Still needs tests.

@chriseth
Copy link
Contributor Author

Added tests and documentation. Should be ready to merge.

@axic
Copy link
Contributor

axic commented Jan 16, 2018

Perhaps we should have a target pragma specifying the chain (related #1117). The question there becomes wether we enforce the latest chain and allow to go back to the previous one or we stay on longer on the "old chain".

In example:

  • stay on Homestead and enable Byzantium via pragma target byztantium or pragma byzantium
  • stay on Byzantium and enable Homestead via pragma homestead

@chriseth
Copy link
Contributor Author

I would prefer a pragma homestead directive, or perhaps pragma target homestead

@chriseth
Copy link
Contributor Author

Decision from discussion:

add a pragma target <x> pragma. The default is always "latest version of the EVM". Currently supported values are byzantium and homestead. Everything else is rejected.

homestead could also be used to force gas calculation for calls (which is currently still the default).

@axic
Copy link
Contributor

axic commented Feb 14, 2018

Should use the new evmTarget from #1117.

@chriseth
Copy link
Contributor Author

@axic this only requires the evm target check, or is something else missing?

@chriseth chriseth force-pushed the useStaticCall branch 2 times, most recently from e98d4e6 to 9955015 Compare March 2, 2018 16:02
@chriseth
Copy link
Contributor Author

chriseth commented Mar 2, 2018

Rebased. Now depends on #3569 and #3600 .

Changelog.md Outdated
Features:
* C99/C++-style scoping rules (instead of JavaScript function scoping) take effect as experimental v0.5.0 feature.
* Code Generator: Assert that ``k != 0`` for ``molmod(a, b, k)`` and ``addmod(a, b, k)`` as experimental 0.5.0 feature.
* Code Generator: Use STATICCALL opcode for calling view and pure functions as experimenal 0.5.0 feature.
Copy link
Contributor

Choose a reason for hiding this comment

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

``STATICCALL`` :)

Also could fix the molmod above here.

You can switch the compiler to use STATICCALL when calling such functions and thus
prevent modifications to the state on the level of the EVM by adding
``pragma experimental "v0.5.0";``
It is not possible to prevent functions from reading the state at the level
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be a separate warning block?

@axic
Copy link
Contributor

axic commented Mar 2, 2018

The static call changes look good.

Copy link
Contributor

@axic axic left a comment

Choose a reason for hiding this comment

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

Apart from the changelog comment the staticcall changes looks fine. (Should of course merge the dependant PRs first.)

@chriseth chriseth force-pushed the useStaticCall branch 2 times, most recently from 01390b2 to bec98c6 Compare March 5, 2018 18:31
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
bool useStaticCall =
_functionType.stateMutability() <= StateMutability::View &&
m_context.experimentalFeatureActive(ExperimentalFeature::V050) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually this contradicts #3600.

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 really need this line? We should just enable it based on the EMV version (which we also have as a condition below).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We perform changes in codegen from time to time without requiring a breaking release. The condition for that is that the actual semantics visible from outside do not change. This is only the case if people do not perform invalid type conversions and if they use the most recent EVM version. I think it is fine to assume the latter, so we can just remove it. We should highlight that in the release notes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok but actually arguing the other way around: If we remove this condition, then we actually assume that it is perfectly fine to use. This means it is not an experimental feature. In turn, we don't have to warn about using experimental 0.5.0.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copying this from the channel for the record:

The argument is that we specifically state in the changelog that pragma experimental v0.5.0 is analysis only and won’t change the codegen phase.

The second argument is whether staticcall is experiemental or not and I’m leaning towards to say it isn’t experimental. That code should work, if it doesn’t that is a broken VM or a broken implementation in the codegen.

There is one case where this could cause an issue if the user disregards the warnings from the ViewPureChecker and does expected state modification in a view function and calls it externally in another contract.

Luckily, the ViewPureChecker reports a warning for these cases (https://github.com/ethereum/solidity/blob/develop/libsolidity/analysis/ViewPureChecker.cpp#L254) so it should only fail as a matter of programmer error.

Though it is kind of a breaking change because if they disregard the warning the output will not work.

@axic
Copy link
Contributor

axic commented Mar 6, 2018

Rebased it.

@axic axic merged commit 14b12ae into develop Mar 6, 2018
@axic axic deleted the useStaticCall branch March 6, 2018 16:07
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