go-ethereum/core/vm/state_manager.go
2020-05-14 14:57:12 -04:00

100 lines
3.4 KiB
Go

package vm
import (
"encoding/binary"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
var (
StateManagerAddress = common.HexToAddress(os.Getenv("STATE_MANAGER_ADDRESS"))
)
type stateManagerFunction func(*EVM, *Contract, []byte) ([]byte, error)
type methodId [4]byte
var funcs = map[string]stateManagerFunction{
"getStorage(address,bytes32)": getStorage,
"setStorage(address,bytes32,bytes32)": setStorage,
"deployContract(address,bytes,bool,address)": deployContract,
"getOvmContractNonce(address)": getOvmContractNonce,
"getCodeContractBytecode(address)": getCodeContractBytecode,
"getCodeContractHash(address)": getCodeContractHash,
"incrementOvmContractNonce(address)": incrementOvmContractNonce,
}
var methodIds map[[4]byte]stateManagerFunction
var executionMangerBytecode []byte
func init() {
methodIds = make(map[[4]byte]stateManagerFunction, len(funcs))
for methodSignature, f := range funcs {
methodIds[MethodSignatureToMethodId(methodSignature)] = f
}
}
func MethodSignatureToMethodId(methodSignature string) [4]byte {
var methodId [4]byte
copy(methodId[:], crypto.Keccak256([]byte(methodSignature)))
return methodId
}
func callStateManager(input []byte, evm *EVM, contract *Contract) (ret []byte, err error) {
var methodId [4]byte
copy(methodId[:], input[:4])
ret, err = methodIds[methodId](evm, contract, input)
return ret, err
}
func setStorage(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
key := common.BytesToHash(input[36:68])
val := common.BytesToHash(input[68:100])
evm.StateDB.SetState(address, key, val)
return nil, nil
}
func getStorage(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
key := common.BytesToHash(input[36:68])
val := evm.StateDB.GetState(address, key)
return val.Bytes(), nil
}
func getCodeContractBytecode(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
code := evm.StateDB.GetCode(address)
return code, nil
}
func getCodeContractHash(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
codeHash := evm.StateDB.GetCodeHash(address)
return codeHash.Bytes(), nil
}
func getOvmContractNonce(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, evm.StateDB.GetNonce(address))
val := append(make([]byte, 24), b[:]...)
return val, nil
}
func incrementOvmContractNonce(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
oldNonce := evm.StateDB.GetNonce(address)
evm.StateDB.SetNonce(address, oldNonce+1)
return nil, nil
}
func deployContract(evm *EVM, contract *Contract, input []byte) (ret []byte, err error) {
address := common.BytesToAddress(input[4:36])
callerAddress := common.BytesToAddress(input[100:132])
initCodeLength := binary.BigEndian.Uint32(input[160:164])
initCode := input[164 : 164+initCodeLength]
callerContractRef := &Contract{self: AccountRef(callerAddress)}
returnVal, _, _, err := evm.OvmCreate(callerContractRef, address, initCode, contract.Gas, bigZero)
return returnVal, nil
}