account permissions and some gendoug

This commit is contained in:
Ethan Buchman
2015-05-12 20:40:19 -04:00
committed by Jae Kwon
parent 3468956e1f
commit a0f3b94e83
9 changed files with 421 additions and 23 deletions

View File

@ -27,6 +27,14 @@ var (
ErrInvalidContract = errors.New("Invalid contract")
)
type ErrPermission struct {
typ string
}
func (err ErrPermission) Error() string {
return fmt.Sprintf("Contract does not have permission to %s", err.typ)
}
type Debug bool
const (
@ -51,6 +59,10 @@ type VM struct {
callDepth int
evc events.Fireable
doug bool // is this the gendoug contract
sendPerm, callPerm, createPerm bool // this contract's permissions
}
func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM {
@ -60,6 +72,7 @@ func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM {
origin: origin,
callDepth: 0,
txid: txid,
doug: false,
}
}
@ -68,6 +81,19 @@ func (vm *VM) SetFireable(evc events.Fireable) {
vm.evc = evc
}
// to allow calls to native DougContracts (off by default)
func (vm *VM) EnableDoug() {
vm.doug = true
}
// set the contract's generic permissions
func (vm *VM) SetPermissions(send, call, create bool) {
// TODO: distinction between send and call not defined at the VM yet (it's all through a CALL!)
vm.sendPerm = send
vm.callPerm = call
vm.createPerm = create
}
// CONTRACT appState is aware of caller and callee, so we can just mutate them.
// value: To be transferred from caller to callee. Refunded upon error.
// gas: Available gas. No refunds for gas.
@ -659,6 +685,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
dbg.Printf(" => %v\n", log)
case CREATE: // 0xF0
if !vm.createPerm {
return nil, ErrPermission{"create"}
}
contractValue := stack.Pop64()
offset, size := stack.Pop64(), stack.Pop64()
input, ok := subslice(memory, offset, size)
@ -684,6 +713,9 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
}
case CALL, CALLCODE: // 0xF1, 0xF2
if !vm.callPerm {
return nil, ErrPermission{"call"}
}
gasLimit := stack.Pop64()
addr, value := stack.Pop(), stack.Pop64()
inOffset, inSize := stack.Pop64(), stack.Pop64() // inputs
@ -710,6 +742,9 @@ 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 dougContract := dougContracts[addr]; vm.doug && dougContract != nil {
// This is Doug and we're calling a doug contract
ret, err = dougContract(args, &gasLimit)
} else {
// EVM contract
if ok = useGas(gas, GasGetAccount); !ok {