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

ACL: Multiple enhancements #584

Merged
merged 12 commits into from
Jul 1, 2020
Merged

ACL: Multiple enhancements #584

merged 12 commits into from
Jul 1, 2020

Conversation

facuspagnuolo
Copy link
Contributor

@facuspagnuolo facuspagnuolo commented Jun 10, 2020

Fixes #582

This PR includes:

  • Optimization for internal calls: external + internal over public functions
  • Allow knowing the original address being evaluated for permissions set to ANY_ENTITY

@coveralls
Copy link

coveralls commented Jun 11, 2020

Coverage Status

Coverage decreased (-0.3%) to 98.862% when pulling 17c8ee9 on acl_enhancements into d068879 on next.

@@ -227,8 +227,8 @@ contract ACL is IACL, TimeHelpers, AragonApp, ACLHelpers {
* @param _role Identifier for a group of actions in app
* @return address of the manager for the permission
*/
function getPermissionManager(address _app, bytes32 _role) public view returns (address) {
return permissionManager[roleHash(_app, _role)];
function getPermissionManager(address _app, bytes32 _role) external view returns (address) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What’s the reason for this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm proposing to avoid having public functions and provide both external and internal functions instead so we reduce gas costs when using these

Copy link
Contributor

Choose a reason for hiding this comment

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

How do you reduce gas costs? Unless the compiler with optimizations enabled decides to inline the internal method, which not only is kind of uncertain but also would increase the bytecode size, I don’t understand the gas benefit of doing it this way.

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 in this case we don't get any gas savings; IIRC you only get them with dynamically sized calldata parameters on external interfaces.

But I don't mind forcing anything we don't use internally to be external anyway—the idea of making something easy to inherit has come and gone, I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree if we don’t use it internally, but this function we do use it, so I don’t see the point. I don’t think there is gas saving here.

// TODO: this should be external
// See https://github.com/ethereum/solidity/issues/4832
function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
function hasPermission(address who, address where, bytes32 what, bytes how) external view returns (bool);
Copy link
Contributor

Choose a reason for hiding this comment

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

I’m not aware of any app inheriting from here (other than ACL here), so I guess it’s fine, but this may break them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this will be released as a major version so I think we can introduce breaking changes

contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Show resolved Hide resolved
@@ -15,27 +15,27 @@ contract ACLHelper {


contract AcceptOracle is IACLOracle {
function canPerform(address, address, bytes32, uint256[]) external view returns (bool) {
function canPerform(address, address, address, bytes32, uint256[]) external view returns (bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder, does it make sense to assign an ACL Oracle with anything else than ANY_ENTITY? Because otherwise we could keep only one param and send the real sender instead of ANY_ENTITY in _hasPermission.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

does it make sense to assign an ACL Oracle with anything else than ANY_ENTITY?

Probably it doesn't, but I wouldn't assume that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Contrived, but you could assign a specific entity (e.g. an Agent) from not performing something via the ACL Oracle.

This could, for example, be used to disallow the AN DAO from changing court values too steeply.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t get it: so would you assign the permission to the Agent instead of ANY_ENTITY? Then only the agent would be able to call the function protected by the ACL Oracle, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, exactly.

Copy link
Contributor

Choose a reason for hiding this comment

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

But if you assign the role to a particular entity (Agent for instance), what do you want the new address param for?

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, attending to the initial question:

Because otherwise we could keep only one param and send the real sender

It is contrived, but I consider the old behaviour as "not a bug" specifically because your ACL Oracle could behave differently if it was defined to be completely open for ANY_ADDRESS vs. specific to an address.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, that makes ACL Oracles even more complex and harder to understand.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed—in this case, it was a couple of different concerns:

  • This information about the ANY_ENTITY grantee was available in the old version
  • We needed a different function signature so any combination of ACLv1, ACLv2, ACLOracleV1, and ACLOracleV2 could work together (assuming the app implemented both)

Copy link
Contributor

@sohkai sohkai left a comment

Choose a reason for hiding this comment

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

Have a couple of small notes, but looks good to me otherwise 🏎!

@@ -227,8 +227,8 @@ contract ACL is IACL, TimeHelpers, AragonApp, ACLHelpers {
* @param _role Identifier for a group of actions in app
* @return address of the manager for the permission
*/
function getPermissionManager(address _app, bytes32 _role) public view returns (address) {
return permissionManager[roleHash(_app, _role)];
function getPermissionManager(address _app, bytes32 _role) external view returns (address) {
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 in this case we don't get any gas savings; IIRC you only get them with dynamically sized calldata parameters on external interfaces.

But I don't mind forcing anything we don't use internally to be external anyway—the idea of making something easy to inherit has come and gone, I think.

contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/acl/ACL.sol Outdated Show resolved Hide resolved
contracts/test/tests/TestACLInterpreter.sol Show resolved Hide resolved
test/contracts/acl/acl_params.js Show resolved Hide resolved
contracts/acl/IACLOracle.sol Show resolved Hide resolved
@facuspagnuolo
Copy link
Contributor Author

@sohkai addressed your comments! Let me know your thoughts!

Copy link
Contributor

@sohkai sohkai left a comment

Choose a reason for hiding this comment

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

LGTM, I just added a commit to separate the ACLOracle tests into separate ones with a bit more comments :).

@facuspagnuolo facuspagnuolo merged commit a70d806 into next Jul 1, 2020
@facuspagnuolo facuspagnuolo deleted the acl_enhancements branch July 1, 2020 23:15
facuspagnuolo added a commit that referenced this pull request Aug 3, 2020
facuspagnuolo added a commit that referenced this pull request Aug 4, 2020
* Revert "ACL: update user/who parameters to who/grantee (#589)"

This reverts commit e6ea55f.

* Revert "ACL: Multiple enhancements (#584)"

This reverts commit a70d806.

* Disputable: Rollback ACL v2 support for Agreement mock
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.

ACLOracle: update interface to receive who properly
4 participants