aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/vm.go
blob: 4c39d401c1a92e9bf216e9614d27abb2d0742003 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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("Unknown code prefix %x\n", code[0])
            return EVM, code[1:]
        }
    }
    return EVM, code
}