Search in sources :

Example 16 with ClassCode

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

the class Heap method loadClassCodes.

public void loadClassCodes(Map<String, ClassCode> classCodes) {
    if (classCodes != null) {
        int i = 0;
        for (ClassCode classCode : classCodes.values()) {
            this.classNames.put(String.valueOf(i++), classCode.variableType.getDesc());
        }
        this.classNames.putAll(VariableType.DESCRIPTORS);
    }
}
Also used : ClassCode(io.nuls.contract.vm.code.ClassCode)

Example 17 with ClassCode

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

the class NativeClass method getSuperclass.

/**
 * native
 *
 * @see Class#getSuperclass()
 */
private static Result getSuperclass(MethodCode methodCode, MethodArgs methodArgs, Frame frame) {
    ObjectRef objectRef = methodArgs.objectRef;
    VariableType variableType;
    if (objectRef.getVariableType().isArray()) {
        variableType = objectRef.getVariableType();
    } else {
        variableType = VariableType.valueOf(objectRef.getRef());
    }
    ClassCode classCode = frame.methodArea.loadClass(variableType.getType());
    VariableType superVariableType = VariableType.valueOf(classCode.superName);
    ObjectRef classRef = frame.heap.getClassRef(superVariableType.getDesc());
    Result result = NativeMethod.result(methodCode, classRef, frame);
    return result;
}
Also used : ClassCode(io.nuls.contract.vm.code.ClassCode) VariableType(io.nuls.contract.vm.code.VariableType) ObjectRef(io.nuls.contract.vm.ObjectRef) Result(io.nuls.contract.vm.Result)

Example 18 with ClassCode

use of io.nuls.contract.vm.code.ClassCode 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 19 with ClassCode

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

the class NativeUtils method emit.

/**
 * native
 *
 * @see Utils#emit(Event)
 */
private static Result emit(MethodCode methodCode, MethodArgs methodArgs, Frame frame) {
    ObjectRef objectRef = (ObjectRef) methodArgs.invokeArgs[0];
    // String str = frame.heap.runToString(objectRef);
    ClassCode classCode = frame.methodArea.loadClass(objectRef.getVariableType().getType());
    Map<String, Object> jsonMap = toJson(objectRef, frame);
    EventJson eventJson = new EventJson();
    eventJson.setContractAddress(frame.vm.getProgramInvoke().getAddress());
    eventJson.setBlockNumber(frame.vm.getProgramInvoke().getNumber() + 1);
    eventJson.setEvent(classCode.simpleName);
    eventJson.setPayload(jsonMap);
    String json = JsonUtils.toJson(eventJson);
    frame.vm.getEvents().add(json);
    Result result = NativeMethod.result(methodCode, null, frame);
    return result;
}
Also used : ClassCode(io.nuls.contract.vm.code.ClassCode)

Aggregations

ClassCode (io.nuls.contract.vm.code.ClassCode)19 MethodCode (io.nuls.contract.vm.code.MethodCode)7 ObjectRef (io.nuls.contract.vm.ObjectRef)6 Result (io.nuls.contract.vm.Result)6 VariableType (io.nuls.contract.vm.code.VariableType)4 VM (io.nuls.contract.vm.VM)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 FieldCode (io.nuls.contract.vm.code.FieldCode)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 DBService (io.nuls.db.service.DBService)1