diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go index f3d02f21591e4d8396f0265207929df178cef146..aa71878d76e2c2a495d2feda06ad12460e861db8 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go @@ -147,6 +147,32 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas return } + +// [This implementation is up for review]. +// DelegateCall is executed by the DELEGATECALL opcode, introduced as off Ethereum Homestead. +// The intent of delegate call is to run the code of the callee in the storage context of the caller; +// while preserving the original caller to the previous callee. +// [ -->] Different to the normal CALL or CALLCODE, the value does not need to be transferred to the callee. [<-- CORRECT?] +func (vm *VM) DelegateCall(caller, callee *Account, code, input []byte, value int64, gas *int64) (output []byte, err error) { + + exception := new(string) + // fire the post call event (including exception if applicable) + defer vm.fireCallEvent(exception, &output, caller, callee, input, value, gas) + + // DelegateCall does not transfer the value to the callee. + + if len(code) > 0 { + vm.callDepth += 1 + output, err = vm.call(caller, callee, code, input, value, gas) + vm.callDepth -= 1 + if err != nil { + *exception = err.Error() + } + } + + return +} + // Try to deduct gasToUse from gasLeft. If ok return false, otherwise // set err and return true. func useGasNegative(gasLeft *int64, gasToUse int64, err *error) bool { @@ -799,6 +825,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas return nil, firstErr(err, ErrUnknownAddress) } ret, err = vm.Call(callee, callee, acc.Code, args, value, gas) + } else if op == DELEGATECALL { + if acc == nil { + return nil, firstErr(err, ErrUnknownAddress) + } + ret, err = vm.DelegateCall(caller, callee, acc.Code, args, value, gas) } else { // nil account means we're sending funds to a new account if acc == nil {