-
Notifications
You must be signed in to change notification settings - Fork 344
Introduce more strongly typed SNatives and contract templates #500
Introduce more strongly typed SNatives and contract templates #500
Conversation
c320376
to
0fc330b
Compare
…ract, and test for permissions contract
0fc330b
to
3d1e7ec
Compare
Am in favor of changing the names. So yea...lets make this happen. |
@VoR0220 Can we get some consensus on what the type signatures should actually be also? |
@silasdavis i think i know what you mean but youre going to need to clarify. I think you mean solidity types. In which case there should be changes. For one, all ints should be uint64s to better align with golang. We should also contemplate switching from bytes32 to string as it could enable longer strings and dynamic ones at that. |
What I need is a decision on:
These will be breaking changes, but seeing as it was already not working properly I think we are at liberty to make them if they improve the situation. Here is the contract as currently defined in snatives.go: /**
* Interface for managing Secure Native authorizations.
* @dev This Solidity interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB).
*/
contract permissions_contract {
/**
* @notice Removes a role from an account
* @param _account account
* @param _role role
* @return result whether role was removed
*/
function rm_role(address _account, bytes32 _role) constant returns (bool result);
/**
* @notice Sets a base authorization for an account
* @param _account account
* @param _authorization base authorization
* @param _value value of base authorization
* @return result value passed in
*/
function set_base(address _account, uint64 _authorization, uint64 _value) constant returns (bool result);
/**
* @notice Indicates whether an account has a base authorization
* @param _account account
* @param _authorization base authorization
* @return result whether account has base authorization set
*/
function has_base(address _account, uint64 _authorization) constant returns (bool result);
/**
* @notice Sets a base authorization for an account to the global (default) value of the base authorization
* @param _account account
* @param _authorization base authorization
* @return authorization base authorization passed in
*/
function unset_base(address _account, uint64 _authorization) constant returns (uint64 authorization);
/**
* @notice Sets global (default) value for a base authorization
* @param _account account
* @param _authorization base authorization
* @param _value value of base authorization
* @return authorization base authorization passed in
*/
function set_global(uint64 _authorization, uint64 _value) constant returns (uint64 authorization);
/**
* @notice Adds a role to an account
* @param _account account
* @param _role role
* @return result whether role was added
*/
function add_role(address _account, bytes32 _role) constant returns (bool result);
/**
* @notice Indicates whether an account has a role
* @param _account account
* @param _role role
* @return result whether account has role
*/
function has_role(address _account, bytes32 _role) constant returns (bool result);
} |
let me play with turning it to string and get back to you later today. It may very well be worth it to send in a string instead of a bytes32 simply because a string can be longer than 32 bytes (why you would ever make a string like that, IDK, but the liberty is nice). |
contract := SNativeContracts()["permissions_contract"] | ||
|
||
assertContractFunction(t, contract, "3fbf7da5", | ||
"add_role(address,bytes32)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought we said camelCase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right yeah, I can do that, but it will involve a few more changes. Obviously just a search and replace job in Eris db so I can do it, but it got me to question the wisdom, will do it if you and Jason and Ben think it's good idea
27b6875
to
1add855
Compare
1add855
to
96df876
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall very nice work. I do want to raise the concern that the SNative should be (possible) without being Solidity specific. We can come back to this at a later point.
The idea with be to define the Args
as LanguageUint64
etc rather than SolidityUint64
; the templates should be solidity specific only imo
@@ -378,6 +379,8 @@ func Bytecode(bytelikes ...interface{}) []byte { | |||
if int64(bytes[i]) != b { | |||
panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b)) | |||
} | |||
case word256.Word256: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice :)
manager/eris-mint/evm/snative.go
Outdated
} | ||
|
||
//----------------------------------------------------------------------------- | ||
// snative are native contracts that can access and modify an account's permissions | ||
|
||
type SNativeFuncDescription struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly speaking, should this not be an interface for which we have a Solidity implementation? The argument is that Solidity is not the only language that can access our Ethereum compatible secure native functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second thought / correction: SNativeFuncDescription
should not become an interface as suggested above. Rather the SNative definition should be defined with LanguageTypes
and the templating should be a package on itself, that produces the solidity code based on the mapping of LanguageType
to SolidityType
. We can raise this as an issue and proceed as is for now; the net gain in readability is sufficient for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make that ProtoType
rather than LanguageType
manager/eris-mint/evm/snative.go
Outdated
fid := f.ID() | ||
otherF, ok := fs[fid] | ||
if ok { | ||
panic(fmt.Errorf("Function with ID %x already defined: %s", fid, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not panic, even if it would only be called on initialization;
manager/eris-mint/evm/snative.go
Outdated
if !HasPermission(appState, caller, d.PermFlag) { | ||
return nil, ErrInvalidPermission{caller.Address, d.Name} | ||
if !HasPermission(appState, caller, function.PermFlag) { | ||
return Zero256.Bytes(), ErrInvalidPermission{caller.Address, function.Name} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good on returning Zero256
manager/eris-mint/evm/snative.go
Outdated
// Returns a map of all SNative contracts defined indexed by name | ||
func SNativeContracts() map[string]SNativeContractDescription { | ||
permFlagType := SolidityUint64 | ||
roleType := SolidityBytes32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internally we treat roles as strings, but I agree that it is better and sufficient to type it strictly as bytes32
; alternatively we should change our impl to treat it as Word256
LGTM. I have raised comments on the unpleasantness of infection of solidity into the evm/snatives; Talked with Silas and he will examine further; although he does not like to call it |
…bi package, improve documentation of permissions snatives and improve argument and return types
dbc97cb
to
9c52e95
Compare
The latest commit:
|
# Dumps Solidity interface contracts for SNatives | ||
.PHONY: snatives | ||
snatives: | ||
@go run ./util/snatives/cmd/main.go |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried this out, works like a charm. Good work.
@@ -13,7 +13,7 @@ import ( | |||
"github.com/stretchr/testify/assert" | |||
) | |||
|
|||
var mockInterval = 10 * time.Millisecond | |||
var mockInterval = 40 * time.Millisecond |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a CI failure, timing here was a little tight anyway, also ugly, but pre-existing and we'll get around to that.
@@ -0,0 +1,27 @@ | |||
package abi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should clarify in the notes below that this is an ABI for our SNative contracts. That it creates a binding from our native Go Code to Solidity and vice versa, and could further be extended to Java and whatever language the enterprise institutions want.
@@ -3,7 +3,6 @@ package vm | |||
import ( | |||
"fmt" | |||
|
|||
. "github.com/eris-ltd/eris-db/manager/eris-mint/evm" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
@@ -5,7 +5,6 @@ import ( | |||
"reflect" | |||
"testing" | |||
|
|||
. "github.com/eris-ltd/eris-db/manager/eris-mint/evm" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
manager/eris-mint/evm/snative.go
Outdated
registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = add_role | ||
registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rm_role | ||
*/ | ||
type SNativeContractDescription struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs Godoc documentation of what each of the parameters that are exported do.
manager/eris-mint/evm/snative.go
Outdated
// snative are native contracts that can access and modify an account's permissions | ||
|
||
type SNativeFuncDescription struct { | ||
type SNativeFunctionDescription struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
manager/eris-mint/evm/snative.go
Outdated
@@ -115,7 +297,7 @@ func has_base(appState AppState, caller *Account, args []byte, gas *int64) (outp | |||
} | |||
|
|||
func set_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { | |||
addr, permNum, perm := returnThreeArgs(args) | |||
addr, permNum, permVal := returnThreeArgs(args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much better name ++
manager/eris-mint/evm/snative.go
Outdated
@@ -228,6 +410,10 @@ func ValidPermN(n ptypes.PermFlag) bool { | |||
return true | |||
} | |||
|
|||
func resultantPermBytes(basePerms ptypes.BasePermissions) []byte { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice.
https://ethereum.github.io/browser-solidity yields: | ||
|
||
Functions | ||
3fbf7da5 add_role(address,bytes32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to decide if we're going CamelCase Here...or mixedCase (as is Solidity convention).
manager/eris-mint/evm/snative.go
Outdated
* Interface for managing Secure Native authorizations. | ||
* @dev This interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB). | ||
`, | ||
"permissions_contract", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
permissions_contract or are we doing PermissionsContract? Either way I'm fine. Just clarifying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a couple of documentation changes and then its GTM.
…le guide, add missing godoc comments, automate signature test
Very approved. Merge away. |
In for a penny, in for pound. Have changed case convention of permissions functions to camelCase. Also renamed permission contract to The generated solidity for the permissions contract now looks like this: /**
* Interface for managing Secure Native authorizations.
* @dev This interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB).
* @dev These functions can be accessed as if this contract were deployed at the address 0x0000000000000000005065726d697373696f6e73
*/
contract Permissions {
/**
* @notice Adds a role to an account
* @param _account account address
* @param _role role name
* @return result whether role was added
*/
function addRole(address _account, bytes32 _role) constant returns (bool result);
/**
* @notice Removes a role from an account
* @param _account account address
* @param _role role name
* @return result whether role was removed
*/
function removeRole(address _account, bytes32 _role) constant returns (bool result);
/**
* @notice Indicates whether an account has a role
* @param _account account address
* @param _role role name
* @return result whether account has role
*/
function hasRole(address _account, bytes32 _role) constant returns (bool result);
/**
* @notice Sets the permission flags for an account. Makes them explicitly set (on or off).
* @param _account account address
* @param _permission the base permissions flags to set for the account
* @param _set whether to set or unset the permissions flags at the account level
* @return result the resultant permissions flags on the account after the call
*/
function setBase(address _account, uint64 _permission, bool _set) constant returns (uint64 result);
/**
* @notice Unsets the permissions flags for an account. Causes permissions being unset to fall through to global permissions.
* @param _account account address
* @param _permission the permissions flags to unset for the account
* @return result the resultant permissions flags on the account after the call
*/
function unsetBase(address _account, uint64 _permission) constant returns (uint64 result);
/**
* @notice Indicates whether an account has a subset of permissions set
* @param _account account address
* @param _permission the permissions flags (mask) to check whether enabled against base permissions for the account
* @return result whether account has the passed permissions flags set
*/
function hasBase(address _account, uint64 _permission) constant returns (uint64 result);
/**
* @notice Sets the global (default) permissions flags for the entire chain
* @param _permission the permissions flags to set
* @param _set whether to set (or unset) the permissions flags
* @return result the resultant permissions flags on the account after the call
*/
function setGlobal(uint64 _permission, bool _set) constant returns (uint64 result);
} |
5df55ed
to
1f421ff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would want a response on the Resultant Permissions and why we need it; other than than; let s ping products team on the change to the function names; needs to be updated in tooling too then
@@ -19,6 +19,8 @@ type TxCache struct { | |||
storages map[Tuple256]Word256 | |||
} | |||
|
|||
var _ vm.AppState = &TxCache{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment is not unwelcome; but great! thx for adding this line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"TxCache implements vm.AppState", what sort of comment were you after?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optionally yes, it s not entirely obvious otherwise
@@ -112,6 +112,12 @@ func (p *BasePermissions) IsSet(ty PermFlag) bool { | |||
return p.SetBit&ty > 0 | |||
} | |||
|
|||
// Returns the Perms PermFlag masked with SetBit bit field to give the resultant | |||
// permissions enabled by this BasePermissions | |||
func (p *BasePermissions) ResultantPerms() PermFlag { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not ok as a public function; It can encourage usage of it and it should be clear that effective permissions are those of the global permissions + delta of base permissions for that account. Why would we have this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to see what permissions are set at the account level. Knowing effective permissions is also useful I agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that BasePermissions.Perms
and BasePermissions.SetBit
are both public fields I'd say this was arguably less obscure in meaning than those. Callers are allowed to interrogate account level permissions and global permissions separately.
@@ -0,0 +1,133 @@ | |||
package templates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice ! I like that you moved them to util; even better than having them in evm
@@ -147,7 +147,7 @@ func testPermissions(t *testing.T, | |||
nonceString := "" | |||
|
|||
_, err := Permissions(nodeClient, keyClient, publicKeyString, addressString, | |||
nonceString, "set_base", []string{permAddressString, "root", "true"}) | |||
nonceString, "setBase", []string{permAddressString, "root", "true"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're going to harden these, now would be the time to add a test for every permission. This way we can effectively gauge what parts are on the jobs failing and what parts are on e-db failing, atleast more easily...currently I'm having trouble deciphering this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are extensive unit tests in /manager/eris-mint/state/permissions_test.go
that have been passing without failure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine, but working directly on the EVM/SNative is not the same as going through the RPC (as we've seen with #477). I would recommend that there is atleast one of every RPC permission call type included in here and to ensure that they are passing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BasePermissions.Set actually sets many bits at the same time; the comment is misleading and I thought wrong about it; this is good
LGTM |
…emplates Introduce more strongly typed SNatives and contract templates
This PR aims to address the issue of having many versions of the permissions contract in different places. Since eris-db is responsible for interpreting SNative calls it seems sensible that eris-db holds the defintion for SNatives. This PR:
It doesn't change the fundamentals of how SNatives work.
The permissions contract structure is built from the libraries' team's version: https://github.com/eris-ltd/eris-contract-bundles/blob/master/src/commons-auth/contracts/SecureNativeAuthorizations.sol which Jason linked me too which is nicely commented.
Outstanding for this is:
Once that is done then we can mechanical generate the solidity interface that we are advertising to clients and we can do this for any future SNatives (which is why I thought it was worth doing). By running:
Also note that the current version of snative.go on release-0.16 is missing a bracket in the signature.
fixes #498
fixes #418
fixes #417