Search in sources :

Example 11 with MethodCode

use of io.nuls.contract.vm.code.MethodCode in project nuls by nuls-io.

the class Heap method runToString.

public String runToString(ObjectRef objectRef) {
    if (objectRef == null) {
        return null;
    }
    String type = objectRef.getVariableType().getType();
    if (objectRef.getVariableType().isArray() && objectRef.getVariableType().isPrimitiveType()) {
        type = VariableType.OBJECT_TYPE.getType();
    }
    MethodCode methodCode = this.vm.methodArea.loadMethod(type, Constants.TO_STRING_METHOD_NAME, Constants.TO_STRING_METHOD_DESC);
    this.vm.run(methodCode, new Object[] { objectRef }, false);
    Object result = this.vm.getResultValue();
    String value = (String) getObject((ObjectRef) result);
    return value;
}
Also used : MethodCode(io.nuls.contract.vm.code.MethodCode)

Example 12 with MethodCode

use of io.nuls.contract.vm.code.MethodCode in project nuls by nuls-io.

the class ProgramExecutorImpl method execute.

private ProgramResult execute(ProgramInvoke programInvoke) {
    if (programInvoke.getPrice() < 1) {
        return revert("gas price must be greater than zero");
    }
    if (programInvoke.getGasLimit() < 1) {
        return revert("gas must be greater than zero");
    }
    long maxGas;
    if (programInvoke.isViewMethod()) {
        maxGas = VMContext.getCustomMaxViewGasLimit();
    } else {
        maxGas = VM.MAX_GAS;
    }
    if (programInvoke.getGasLimit() > maxGas) {
        return revert("gas must be less than " + maxGas);
    }
    if (programInvoke.getValue().compareTo(BigInteger.ZERO) < 0) {
        return revert("value can't be less than zero");
    }
    blockNumber = programInvoke.getNumber();
    logTime("start");
    try {
        Map<String, ClassCode> classCodes;
        if (programInvoke.isCreate()) {
            if (programInvoke.getData() == null) {
                return revert("contract code can't be null");
            }
            classCodes = ClassCodeLoader.loadJarCache(programInvoke.getData());
            logTime("load new code");
            ProgramChecker.check(classCodes);
            logTime("check code");
            AccountState accountState = repository.getAccountState(programInvoke.getContractAddress());
            if (accountState != null) {
                return revert(String.format("contract[%s] already exists", programInvoke.getAddress()));
            }
            accountState = repository.createAccount(programInvoke.getContractAddress(), programInvoke.getSender());
            logTime("new account state");
            repository.saveCode(programInvoke.getContractAddress(), programInvoke.getData());
            logTime("save code");
        } else {
            if ("<init>".equals(programInvoke.getMethodName())) {
                return revert("can't invoke <init> method");
            }
            AccountState accountState = repository.getAccountState(programInvoke.getContractAddress());
            if (accountState == null) {
                return revert(String.format("contract[%s] does not exist", programInvoke.getAddress()));
            }
            logTime("load account state");
            if (accountState.getNonce().compareTo(BigInteger.ZERO) <= 0) {
                return revert(String.format("contract[%s] has stopped", programInvoke.getAddress()));
            }
            byte[] codes = repository.getCode(programInvoke.getContractAddress());
            classCodes = ClassCodeLoader.loadJarCache(codes);
            logTime("load code");
        }
        VM vm = VMFactory.createVM();
        logTime("load vm");
        vm.heap.loadClassCodes(classCodes);
        vm.methodArea.loadClassCodes(classCodes);
        logTime("load classes");
        ClassCode contractClassCode = getContractClassCode(classCodes);
        String methodDesc = ProgramDescriptors.parseDesc(programInvoke.getMethodDesc());
        MethodCode methodCode = vm.methodArea.loadMethod(contractClassCode.name, programInvoke.getMethodName(), methodDesc);
        if (methodCode == null) {
            return revert(String.format("can't find method %s%s", programInvoke.getMethodName(), programInvoke.getMethodDesc() == null ? "" : programInvoke.getMethodDesc()));
        }
        if (!methodCode.isPublic) {
            return revert("can only invoke public method");
        }
        if (!methodCode.hasPayableAnnotation() && programInvoke.getValue().compareTo(BigInteger.ZERO) > 0) {
            return revert("not a payable method");
        }
        if (methodCode.argsVariableType.size() != programInvoke.getArgs().length) {
            return revert(String.format("require %s parameters in method [%s%s]", methodCode.argsVariableType.size(), methodCode.name, methodCode.normalDesc));
        }
        logTime("load method");
        ObjectRef objectRef;
        if (programInvoke.isCreate()) {
            objectRef = vm.heap.newContract(programInvoke.getContractAddress(), contractClassCode, repository);
        } else {
            objectRef = vm.heap.loadContract(programInvoke.getContractAddress(), contractClassCode, repository);
        }
        logTime("load contract ref");
        if (programInvoke.getValue().compareTo(BigInteger.ZERO) > 0) {
            getAccount(programInvoke.getContractAddress()).addBalance(programInvoke.getValue());
        }
        vm.setProgramExecutor(this);
        vm.setRepository(repository);
        vm.setGas(programInvoke.getGasLimit());
        vm.addGasUsed(programInvoke.getData() == null ? 0 : programInvoke.getData().length);
        logTime("load end");
        vm.run(objectRef, methodCode, vmContext, programInvoke);
        logTime("run");
        ProgramResult programResult = new ProgramResult();
        programResult.setGasUsed(vm.getGasUsed());
        Result vmResult = vm.getResult();
        Object resultValue = vmResult.getValue();
        if (vmResult.isError() || vmResult.isException()) {
            if (resultValue != null && resultValue instanceof ObjectRef) {
                vm.setResult(new Result());
                String error = vm.heap.runToString((ObjectRef) resultValue);
                String stackTrace = vm.heap.stackTrace((ObjectRef) resultValue);
                programResult.error(error);
                programResult.setStackTrace(stackTrace);
            } else {
                programResult.error(null);
            }
            logTime("contract exception");
            this.revert = true;
            programResult.setGasUsed(vm.getGasUsed());
            return programResult;
        }
        programResult.setTransfers(vm.getTransfers());
        programResult.setEvents(vm.getEvents());
        programResult.setBalance(getAccount(programInvoke.getContractAddress()).getBalance());
        if (resultValue != null) {
            if (resultValue instanceof ObjectRef) {
                String result = vm.heap.runToString((ObjectRef) resultValue);
                programResult.setResult(result);
            } else {
                programResult.setResult(resultValue.toString());
            }
        }
        if (methodCode.isPublic && methodCode.hasViewAnnotation()) {
            this.revert = true;
            programResult.view();
            programResult.setGasUsed(vm.getGasUsed());
            return programResult;
        }
        logTime("contract return");
        Map<DataWord, DataWord> contractState = vm.heap.contractState();
        logTime("contract state");
        for (Map.Entry<DataWord, DataWord> entry : contractState.entrySet()) {
            DataWord key = entry.getKey();
            DataWord value = entry.getValue();
            repository.addStorageRow(programInvoke.getContractAddress(), key, value);
        }
        logTime("add contract state");
        repository.increaseNonce(programInvoke.getContractAddress());
        programResult.setNonce(repository.getNonce(programInvoke.getContractAddress()));
        programResult.setGasUsed(vm.getGasUsed());
        return programResult;
    } catch (ErrorException e) {
        this.revert = true;
        // log.error("", e);
        ProgramResult programResult = new ProgramResult();
        programResult.setGasUsed(e.getGasUsed());
        // programResult.setStackTrace(e.getStackTraceMessage());
        logTime("error");
        return programResult.error(e.getMessage());
    } catch (Exception e) {
        log.error("", e);
        ProgramResult programResult = revert(e.getMessage());
        // programResult.setStackTrace(ExceptionUtils.getStackTrace(e));
        return programResult;
    }
}
Also used : DataWord(org.ethereum.vm.DataWord) AccountState(org.ethereum.core.AccountState) ErrorException(io.nuls.contract.vm.exception.ErrorException) Result(io.nuls.contract.vm.Result) ClassCode(io.nuls.contract.vm.code.ClassCode) VM(io.nuls.contract.vm.VM) MethodCode(io.nuls.contract.vm.code.MethodCode) ObjectRef(io.nuls.contract.vm.ObjectRef) ErrorException(io.nuls.contract.vm.exception.ErrorException)

Example 13 with MethodCode

use of io.nuls.contract.vm.code.MethodCode in project nuls by nuls-io.

the class NativeUtils method newBigIntegerArrayList.

private static ObjectRef newBigIntegerArrayList(Frame frame, List<byte[]> seeds) {
    ObjectRef objectRef = frame.heap.newArrayList();
    MethodCode arrayListAddMethodCode = frame.vm.methodArea.loadMethod(VariableType.ARRAYLIST_TYPE.getType(), Constants.ARRAYLIST_ADD_METHOD_NAME, Constants.ARRAYLIST_ADD_METHOD_DESC);
    for (byte[] seed : seeds) {
        frame.vm.run(arrayListAddMethodCode, new Object[] { objectRef, frame.heap.newBigInteger(seed) }, false);
    }
    return objectRef;
}
Also used : MethodCode(io.nuls.contract.vm.code.MethodCode)

Example 14 with MethodCode

use of io.nuls.contract.vm.code.MethodCode in project nuls by nuls-io.

the class Invokeinterface method invokeinterface.

public static void invokeinterface(Frame frame) {
    MethodInsnNode methodInsnNode = frame.methodInsnNode();
    String interfaceName = methodInsnNode.owner;
    String interfaceMethodName = methodInsnNode.name;
    String interfaceMethodDesc = methodInsnNode.desc;
    List<VariableType> variableTypes = VariableType.parseArgs(interfaceMethodDesc);
    MethodArgs methodArgs = new MethodArgs(variableTypes, frame.operandStack, false);
    ObjectRef objectRef = methodArgs.objectRef;
    if (objectRef == null) {
        frame.throwNullPointerException();
        return;
    }
    String className = objectRef.getVariableType().getType();
    MethodCode methodCode = frame.methodArea.loadMethod(className, interfaceMethodName, interfaceMethodDesc);
    // Log.opcode(frame.getCurrentOpCode(), className, interfaceMethodName, interfaceMethodDesc);
    frame.vm.run(methodCode, methodArgs.frameArgs, true);
}
Also used : VariableType(io.nuls.contract.vm.code.VariableType) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) ObjectRef(io.nuls.contract.vm.ObjectRef) MethodCode(io.nuls.contract.vm.code.MethodCode) MethodArgs(io.nuls.contract.vm.MethodArgs)

Example 15 with MethodCode

use of io.nuls.contract.vm.code.MethodCode in project nuls by nuls-io.

the class Invokevirtual method invokevirtual.

public static void invokevirtual(Frame frame) {
    MethodInsnNode methodInsnNode = frame.methodInsnNode();
    String className = methodInsnNode.owner;
    String methodName = methodInsnNode.name;
    String methodDesc = methodInsnNode.desc;
    List<VariableType> variableTypes = VariableType.parseArgs(methodDesc);
    MethodArgs methodArgs = new MethodArgs(variableTypes, frame.operandStack, false);
    ObjectRef objectRef = methodArgs.objectRef;
    if (objectRef == null) {
        frame.throwNullPointerException();
        return;
    }
    String type = objectRef.getVariableType().getType();
    if (!Objects.equals(className, type)) {
        if (objectRef.getVariableType().isPrimitiveType()) {
        } else {
            className = type;
        }
    }
    if (objectRef.isArray()) {
        className = Constants.OBJECT_CLASS_NAME;
    }
    MethodCode methodCode = frame.methodArea.loadMethod(className, methodName, methodDesc);
    // Log.opcode(frame.getCurrentOpCode(), objectRef, methodName, methodDesc);
    Result result = NativeMethod.run(methodCode, methodArgs, frame);
    if (result != null) {
        return;
    }
    frame.vm.run(methodCode, methodArgs.frameArgs, true);
}
Also used : VariableType(io.nuls.contract.vm.code.VariableType) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) ObjectRef(io.nuls.contract.vm.ObjectRef) MethodCode(io.nuls.contract.vm.code.MethodCode) MethodArgs(io.nuls.contract.vm.MethodArgs) Result(io.nuls.contract.vm.Result)

Aggregations

MethodCode (io.nuls.contract.vm.code.MethodCode)15 ObjectRef (io.nuls.contract.vm.ObjectRef)7 Result (io.nuls.contract.vm.Result)7 ClassCode (io.nuls.contract.vm.code.ClassCode)7 MethodArgs (io.nuls.contract.vm.MethodArgs)4 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)4 VM (io.nuls.contract.vm.VM)2 VariableType (io.nuls.contract.vm.code.VariableType)2 ErrorException (io.nuls.contract.vm.exception.ErrorException)2 AccountState (org.ethereum.core.AccountState)2 DataWord (org.ethereum.vm.DataWord)2 BlockHeaderDto (io.nuls.contract.entity.BlockHeaderDto)1 VMContext (io.nuls.contract.util.VMContext)1 OpCode (io.nuls.contract.vm.OpCode)1 VMFactory (io.nuls.contract.vm.VMFactory)1 ClassCodeLoader (io.nuls.contract.vm.code.ClassCodeLoader)1 ClassCodes (io.nuls.contract.vm.code.ClassCodes)1 NativeAddress (io.nuls.contract.vm.natives.io.nuls.contract.sdk.NativeAddress)1 io.nuls.contract.vm.program (io.nuls.contract.vm.program)1 Constants (io.nuls.contract.vm.util.Constants)1