Browse Source

faster binding of snatives to vm (available every call)

pull/102/head
Ethan Buchman 9 years ago
committed by Jae Kwon
parent
commit
b2282d5a39
3 changed files with 44 additions and 25 deletions
  1. +3
    -7
      state/execution.go
  2. +35
    -0
      vm/snative.go
  3. +6
    -18
      vm/vm.go

+ 3
- 7
state/execution.go View File

@ -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 {


+ 35
- 0
vm/snative.go View File

@ -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)


+ 6
- 18
vm/vm.go View File

@ -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


Loading…
Cancel
Save