diff --git a/state/execution.go b/state/execution.go index 924b8cb2c..7e8458d8c 100644 --- a/state/execution.go +++ b/state/execution.go @@ -361,7 +361,6 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea case *types.CallTx: var inAcc, outAcc *account.Account - var isDoug bool // is this a call to the gendoug? // Validate input inAcc = blockCache.GetAccount(tx.Input.Address) @@ -466,14 +465,11 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea txCache.UpdateAccount(callee) // because we adjusted by input above. vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx)) vmach.SetFireable(evc) - vmach.EnablePermissions() - // NOTE: Call() transfers the value from caller to callee iff call succeeds. - if isDoug { - // enables the snative contracts - vmach.EnableDoug() // setupDoug(vmach, txCache, _s) - } + vmach.EnablePermissions() // permission checks on CALL/CREATE + vmach.EnableSNatives() // allows calls to snatives (with permission checks) + // NOTE: Call() transfers the value from caller to callee iff call succeeds. ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas) exception := "" if err != nil { diff --git a/vm/snative.go b/vm/snative.go index 0d9d02503..52d4c9319 100644 --- a/vm/snative.go +++ b/vm/snative.go @@ -21,6 +21,7 @@ const ( // first 32 bits of BasePermission are for chain, second 32 are for snative FirstSNativePerm ptypes.PermFlag = 1 << 32 + // each snative has an associated permission flag HasBasePerm ptypes.PermFlag = FirstSNativePerm << iota SetBasePerm UnsetBasePerm @@ -35,8 +36,42 @@ const ( TopSNativePermission ptypes.PermFlag = FirstSNativePerm << (NumSNativePermissions - 1) ) +var registeredSNativeContracts = map[Word256]ptypes.PermFlag{ + RightPadWord256([]byte("hasBasePerm")): HasBasePerm, + RightPadWord256([]byte("setBasePerm")): SetBasePerm, + RightPadWord256([]byte("unsetBasePerm")): UnsetBasePerm, + RightPadWord256([]byte("setGlobalPerm")): SetGlobalPerm, + RightPadWord256([]byte("hasRole")): HasRole, + RightPadWord256([]byte("addRole")): AddRole, + RightPadWord256([]byte("rmRole")): RmRole, +} + +// takes an account so it can check for permission to access the contract +// NOTE: the account is the currently executing account (the callee), not say an origin caller type SNativeContract func(acc *Account, input []byte) (output []byte, err error) +func (vm *VM) SNativeContract(name Word256) SNativeContract { + flag := registeredSNativeContracts[name] + switch flag { + case HasBasePerm: + return vm.hasBasePerm + case SetBasePerm: + return vm.setBasePerm + case UnsetBasePerm: + return vm.unsetBasePerm + case SetGlobalPerm: + return vm.setGlobalPerm + case HasRole: + return vm.hasRole + case AddRole: + return vm.addRole + case RmRole: + return vm.rmRole + default: + return nil + } +} + //----------------------------------------------------------------------------- // snative are native contracts that can access and manipulate the chain state // (in particular the permissions values) diff --git a/vm/vm.go b/vm/vm.go index cac76c360..4c9eaa08d 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -61,9 +61,8 @@ type VM struct { evc events.Fireable - doug bool // is this the gendoug contract - perms bool // permission checking can be turned off - snativeContracts map[Word256]SNativeContract + perms bool // permission checking can be turned off + snative bool // access to snatives } func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM { @@ -73,7 +72,6 @@ func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM { origin: origin, callDepth: 0, txid: txid, - doug: false, } } @@ -83,17 +81,8 @@ func (vm *VM) SetFireable(evc events.Fireable) { } // to allow calls to native DougContracts (off by default) -func (vm *VM) EnableDoug() { - vm.doug = true - vm.snativeContracts = map[Word256]SNativeContract{ - RightPadWord256([]byte("hasBasePerm")): vm.hasBasePerm, - RightPadWord256([]byte("setBasePerm")): vm.setBasePerm, - RightPadWord256([]byte("unsetBasePerm")): vm.unsetBasePerm, - RightPadWord256([]byte("setGlobalPerm")): vm.setGlobalPerm, - RightPadWord256([]byte("hasRole")): vm.hasRole, - RightPadWord256([]byte("addRole")): vm.addRole, - RightPadWord256([]byte("rmRole")): vm.rmRole, - } +func (vm *VM) EnableSNatives() { + vm.snative = true } // run permission checks before call and create @@ -757,9 +746,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas if nativeContract := nativeContracts[addr]; nativeContract != nil { // Native contract ret, err = nativeContract(args, &gasLimit) - } else if snativeContract := vm.snativeContracts[addr]; vm.doug && snativeContract != nil { - // This is Doug and we're calling a snative contract - // TODO: Doug contract should have all permissions + } else if snativeContract := vm.SNativeContract(addr); vm.snative && snativeContract != nil { + // Secure native contract (with access to chain state) ret, err = snativeContract(callee, args) } else { // EVM contract