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;
}
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;
}
}
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;
}
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);
}
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);
}
Aggregations