use of io.nuls.contract.vm.ObjectRef in project nuls by nuls-io.
the class JsonUtils method decodeArray.
public static Object decodeArray(String value, Class<?> elementType, BiMap<String, String> classNames) {
if (elementType == ObjectRef.class) {
Object array = toArray(value, String.class);
int length = Array.getLength(array);
ObjectRef[] objectRefs = new ObjectRef[length];
for (int i = 0; i < length; i++) {
String s = (String) Array.get(array, i);
if (s != null) {
objectRefs[i] = new ObjectRef(s, classNames);
}
}
return objectRefs;
} else {
return toArray(value, elementType);
}
}
use of io.nuls.contract.vm.ObjectRef 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.ObjectRef in project nuls by nuls-io.
the class Astore method astore.
public static void astore(final Frame frame) {
int index = frame.varInsnNode().var;
ObjectRef objectRef = frame.operandStack.popRef();
frame.localVariables.setRef(index, objectRef);
// Log.result(frame.getCurrentOpCode(), objectRef, index);
}
use of io.nuls.contract.vm.ObjectRef in project nuls by nuls-io.
the class Anewarray method anewarray.
public static void anewarray(Frame frame) {
TypeInsnNode typeInsnNode = frame.typeInsnNode();
String className = typeInsnNode.desc;
int length = frame.operandStack.popInt();
if (length < 0) {
frame.throwNegativeArraySizeException();
return;
} else {
ObjectRef arrayRef;
if (className.contains(Constants.ARRAY_START)) {
VariableType type = VariableType.valueOf(className);
int[] dimensions = new int[type.getDimensions() + 1];
dimensions[0] = length;
VariableType variableType = VariableType.valueOf(Constants.ARRAY_START + className);
arrayRef = frame.heap.newArray(variableType, dimensions);
} else {
VariableType variableType = VariableType.valueOf(Constants.ARRAY_PREFIX + className + Constants.ARRAY_SUFFIX);
arrayRef = frame.heap.newArray(variableType, length);
}
frame.operandStack.pushRef(arrayRef);
// Log.opcode(frame.getCurrentOpCode(), arrayRef);
}
}
use of io.nuls.contract.vm.ObjectRef 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);
}
Aggregations