diff options
Diffstat (limited to 'core/vm/vm.go')
-rw-r--r-- | core/vm/vm.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/core/vm/vm.go b/core/vm/vm.go new file mode 100644 index 000000000..8d4dffd0b --- /dev/null +++ b/core/vm/vm.go @@ -0,0 +1,105 @@ +package vm + +import ( + "fmt" + "math/big" + + "github.com/dexon-foundation/dexon/common" +) + +const ( + EVM = byte(iota) + SQLVM +) + +var ( + MULTIVM = true +) + +type VM interface { + Create(ContractRef, []byte, uint64, *big.Int, + Interpreter) ([]byte, common.Address, uint64, error) + Create2(ContractRef, []byte, uint64, *big.Int, *big.Int, + Interpreter) ([]byte, common.Address, uint64, error) + Call(ContractRef, common.Address, []byte, uint64, *big.Int, + Interpreter) ([]byte, uint64, error) + CallCode(ContractRef, common.Address, []byte, uint64, + *big.Int, Interpreter) ([]byte, uint64, error) + DelegateCall(ContractRef, common.Address, []byte, uint64, + Interpreter) ([]byte, uint64, error) + StaticCall(ContractRef, common.Address, []byte, uint64, + Interpreter) ([]byte, uint64, error) +} + +type Interpreter interface { + StateDB() StateDB +} + +var vmList map[byte]VM + +func init() { + vmList = make(map[byte]VM) +} +func Register(vmType byte, vm VM) { + vmList[vmType] = vm +} +func Create(caller ContractRef, code []byte, gas uint64, value *big.Int, + interpreter Interpreter) (ret []byte, contractAddr common.Address, + leftOverGas uint64, err error) { + + name, code := getVMAndCode(code) + return vmList[name].Create(caller, code, gas, value, interpreter) +} + +func Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, + salt *big.Int, interpreter Interpreter) (ret []byte, + contractAddr common.Address, leftOverGas uint64, err error) { + + name, code := getVMAndCode(code) + return vmList[name].Create2(caller, code, gas, endowment, salt, interpreter) +} + +func Call(caller ContractRef, addr common.Address, input []byte, gas uint64, + value *big.Int, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + + code := interpreter.StateDB().GetCode(addr) + name, _ := getVMAndCode(code) + return vmList[name].Call(caller, addr, input, gas, value, interpreter) +} + +func CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, + value *big.Int, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + + code := interpreter.StateDB().GetCode(addr) + name, _ := getVMAndCode(code) + return vmList[name].CallCode(caller, addr, input, gas, value, interpreter) +} + +func DelegateCall(caller ContractRef, addr common.Address, input []byte, + gas uint64, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + + code := interpreter.StateDB().GetCode(addr) + name, _ := getVMAndCode(code) + return vmList[name].DelegateCall(caller, addr, input, gas, interpreter) +} + +func StaticCall(caller ContractRef, addr common.Address, input []byte, + gas uint64, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + + code := interpreter.StateDB().GetCode(addr) + name, _ := getVMAndCode(code) + return vmList[name].StaticCall(caller, addr, input, gas, interpreter) +} + +func getVMAndCode(code []byte) (byte, []byte) { + if MULTIVM && len(code) > 0 { + switch code[0] { + case EVM, SQLVM: + return code[0], code[1:] + default: + fmt.Printf("Unknow code prefix %x\n", code[0]) + return EVM, code[1:] + } + } + return EVM, code +} |