@@ -85,26 +85,9 @@ public interface DataCodes { | |||||
//contract related; | //contract related; | ||||
public static final int CONTRACT = 0xA00; | public static final int CONTRACT = 0xA00; | ||||
public static final int CONTRACT_BYTE = 0xA01; | |||||
public static final int CONTRACT_SHORT = 0xA02; | |||||
public static final int CONTRACT_INT = 0xA03; | |||||
public static final int CONTRACT_LONG = 0xA04; | |||||
public static final int CONTRACT_STRING = 0xA05; | |||||
public static final int CONTRACT_BYTES = 0xA06; | |||||
public static final int CONTRACT_BIG_INT = 0xA07; | |||||
//...0xA19 | //...0xA19 | ||||
public static final int CONTRACT_BIZ_CONTENT = 0xA20; | |||||
public static final int CONTRACT_ARGS = 0xA21; | |||||
public static final int CONTRACT_RETURN = 0xA22; | |||||
public static final int HASH = 0xB00; | public static final int HASH = 0xB00; | ||||
public static final int HASH_OBJECT = 0xB10; | public static final int HASH_OBJECT = 0xB10; | ||||
@@ -57,5 +57,7 @@ public class BinaryProtocol { | |||||
} | } | ||||
} | } |
@@ -11,6 +11,8 @@ import com.jd.blockchain.contract.ContractException; | |||||
import com.jd.blockchain.contract.EventProcessingAware; | import com.jd.blockchain.contract.EventProcessingAware; | ||||
import com.jd.blockchain.contract.engine.ContractCode; | import com.jd.blockchain.contract.engine.ContractCode; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
import com.jd.blockchain.ledger.BytesValueList; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
/** | /** | ||||
@@ -29,7 +31,7 @@ public abstract class AbstractContractCode implements ContractCode { | |||||
this.version = version; | this.version = version; | ||||
this.contractDefinition = contractDefinition; | this.contractDefinition = contractDefinition; | ||||
} | } | ||||
public ContractDefinition getContractDefinition() { | public ContractDefinition getContractDefinition() { | ||||
return contractDefinition; | return contractDefinition; | ||||
} | } | ||||
@@ -48,6 +50,7 @@ public abstract class AbstractContractCode implements ContractCode { | |||||
public BytesValue processEvent(ContractEventContext eventContext) { | public BytesValue processEvent(ContractEventContext eventContext) { | ||||
EventProcessingAware evtProcAwire = null; | EventProcessingAware evtProcAwire = null; | ||||
Object retn = null; | Object retn = null; | ||||
Method handleMethod = null; | |||||
Exception error = null; | Exception error = null; | ||||
try { | try { | ||||
// 执行预处理; | // 执行预处理; | ||||
@@ -61,17 +64,19 @@ public abstract class AbstractContractCode implements ContractCode { | |||||
} | } | ||||
// 反序列化参数; | // 反序列化参数; | ||||
Method handleMethod = contractDefinition.getType().getHandleMethod(eventContext.getEvent()); | |||||
handleMethod = contractDefinition.getType().getHandleMethod(eventContext.getEvent()); | |||||
if (handleMethod == null) { | if (handleMethod == null) { | ||||
throw new ContractException( | throw new ContractException( | ||||
String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(), | String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(), | ||||
contractDefinition.getType().getDeclaredClass().toString(), eventContext.getEvent())); | contractDefinition.getType().getDeclaredClass().toString(), eventContext.getEvent())); | ||||
} | } | ||||
Object[] args = resolveArgs(); | |||||
BytesValueList bytesValues = eventContext.getArgs(); | |||||
Object[] args = BytesValueEncoding.decode(bytesValues, handleMethod.getParameterTypes()); | |||||
retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); | retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
error = e; | error = e; | ||||
} | } | ||||
@@ -91,23 +96,10 @@ public abstract class AbstractContractCode implements ContractCode { | |||||
eventContext.getEvent(), address.toString(), error.getMessage()), error); | eventContext.getEvent(), address.toString(), error.getMessage()), error); | ||||
} | } | ||||
BytesValue retnBytes = resolveResult(retn); | |||||
BytesValue retnBytes = BytesValueEncoding.encode(retn, handleMethod.getReturnType()); | |||||
return retnBytes; | return retnBytes; | ||||
} | } | ||||
protected abstract Object getContractInstance(); | protected abstract Object getContractInstance(); | ||||
private BytesValue resolveResult(Object retn) { | |||||
if (retn == null) { | |||||
return null; | |||||
} | |||||
// TODO: resolve result in bytes; | |||||
throw new IllegalStateException("Not implemented!"); | |||||
} | |||||
private Object[] resolveArgs() { | |||||
// TODO Auto-generated method stub | |||||
throw new IllegalStateException("Not implemented!"); | |||||
} | |||||
} | } |
@@ -1,165 +1,165 @@ | |||||
package com.jd.blockchain.contract; | |||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
import com.jd.blockchain.contract.param.WRAP_BYTES; | |||||
import com.jd.blockchain.contract.param.WRAP_INT; | |||||
import com.jd.blockchain.contract.param.WRAP_LONG; | |||||
import com.jd.blockchain.contract.param.WRAP_SHORT; | |||||
import com.jd.blockchain.contract.param.WRAP_STRING; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.BytesValueList; | |||||
import com.jd.blockchain.utils.io.BytesUtils; | |||||
public class ContractSerializeUtils { | |||||
final static int INT_LENGTH = 4; | |||||
static Map<Class<?>, Class<?>> MAP = new HashMap<>(); | |||||
static { | |||||
MAP.put(byte[].class, WRAP_BYTES.class); | |||||
MAP.put(Short.class, WRAP_SHORT.class); | |||||
MAP.put(short.class, WRAP_SHORT.class); | |||||
MAP.put(Integer.class, WRAP_INT.class); | |||||
MAP.put(int.class, WRAP_INT.class); | |||||
MAP.put(Long.class, WRAP_LONG.class); | |||||
MAP.put(long.class, WRAP_LONG.class); | |||||
MAP.put(String.class, WRAP_STRING.class); | |||||
DataContractRegistry.register(WRAP_BYTES.class); | |||||
DataContractRegistry.register(WRAP_SHORT.class); | |||||
DataContractRegistry.register(WRAP_INT.class); | |||||
DataContractRegistry.register(WRAP_LONG.class); | |||||
DataContractRegistry.register(WRAP_STRING.class); | |||||
} | |||||
public static boolean support(Class<?> clazz) { | |||||
if (clazz.isAnnotationPresent(DataContract.class) || MAP.containsKey(clazz)) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
public static BytesValue serialize(Object data) { | |||||
if (data == null) { | |||||
return null; | |||||
} | |||||
Class<?> clazz = data.getClass(); | |||||
Class<?> serialClass; | |||||
Object wrapData = data; | |||||
if (clazz.isAnnotationPresent(DataContract.class)) { | |||||
serialClass = clazz; | |||||
} else { | |||||
// 判断类型是否可以序列化 | |||||
Class<?> wrapClass = MAP.get(clazz); | |||||
if (wrapClass == null) { | |||||
throw new IllegalArgumentException("There are Un-Support Type !!!"); | |||||
} | |||||
serialClass = wrapClass; | |||||
if (wrapClass.equals(WRAP_BYTES.class)) { | |||||
wrapData = (WRAP_BYTES) () -> (byte[]) data; | |||||
} else if (wrapClass.equals(WRAP_INT.class)) { | |||||
wrapData = (WRAP_INT) () -> (int) data; | |||||
} else if (wrapClass.equals(WRAP_LONG.class)) { | |||||
wrapData = (WRAP_LONG) () -> (long) data; | |||||
} else if (wrapClass.equals(WRAP_SHORT.class)) { | |||||
wrapData = (WRAP_SHORT) () -> (short) data; | |||||
} else if (wrapClass.equals(WRAP_STRING.class)) { | |||||
wrapData = (WRAP_STRING) () -> (String) data; | |||||
} | |||||
} | |||||
// 按照对应接口进行序列化 | |||||
// 生成该接口对应的对象 | |||||
return BinaryProtocol.encode(wrapData, serialClass); | |||||
} | |||||
public static BytesValueList serializeArray(Object[] datas) { | |||||
if (datas == null || datas.length == 0) { | |||||
return null; | |||||
} | |||||
int contentBytesSize = 0; | |||||
byte[] header = new byte[(datas.length + 1) * 4]; | |||||
System.arraycopy(BytesUtils.toBytes(datas.length), 0, header, 0, INT_LENGTH); | |||||
int offset = INT_LENGTH; | |||||
List<byte[]> serialBytesList = new ArrayList<>(); | |||||
for (Object data : datas) { | |||||
// 按照对应接口进行序列化 | |||||
byte[] currBytes = serialize(data); | |||||
// 长度写入 | |||||
System.arraycopy(BytesUtils.toBytes(currBytes.length), 0, header, offset, INT_LENGTH); | |||||
serialBytesList.add(currBytes); | |||||
contentBytesSize += currBytes.length; | |||||
offset += INT_LENGTH; | |||||
} | |||||
// 填充content | |||||
byte[] content = new byte[contentBytesSize]; | |||||
offset = 0; | |||||
for (byte[] bytes : serialBytesList) { | |||||
System.arraycopy(bytes, 0, content, offset, bytes.length); | |||||
offset += bytes.length; | |||||
} | |||||
// 将header和content组装 | |||||
return BytesUtils.concat(header, content); | |||||
} | |||||
public static Object[] resolveArray(byte[] bytes) { | |||||
if (bytes == null || bytes.length == 0) { | |||||
return null; | |||||
} | |||||
byte[] lengthBytes = new byte[INT_LENGTH]; | |||||
System.arraycopy(bytes, 0, lengthBytes, 0, INT_LENGTH); | |||||
int length = BytesUtils.toInt(lengthBytes); | |||||
Object[] datas = new Object[length]; | |||||
int headerOffset = INT_LENGTH; | |||||
int contentStart = (length + 1) * INT_LENGTH; | |||||
for (int i = 0; i < length; i++) { | |||||
byte[] currDataLengthBytes = new byte[INT_LENGTH]; | |||||
System.arraycopy(bytes, headerOffset, currDataLengthBytes, 0, INT_LENGTH); | |||||
int currDataLength = BytesUtils.toInt(currDataLengthBytes); | |||||
// 读取 | |||||
byte[] dataBytes = new byte[currDataLength]; | |||||
System.arraycopy(bytes, contentStart, dataBytes, 0, currDataLength); | |||||
datas[i] = resolve(dataBytes); | |||||
contentStart += currDataLength; | |||||
headerOffset += INT_LENGTH; | |||||
} | |||||
return datas; | |||||
} | |||||
public static Object resolve(BytesValue bytes) { | |||||
// 反序列化该接口 | |||||
Object currData = BinaryProtocol.decode(bytes); | |||||
// 代理对象类型不能使用class判断,只能使用instanceof | |||||
if (currData instanceof WRAP_STRING) { | |||||
return ((WRAP_STRING) currData).getValue(); | |||||
} else if (currData instanceof WRAP_INT) { | |||||
return ((WRAP_INT) currData).getValue(); | |||||
} else if (currData instanceof WRAP_LONG) { | |||||
return ((WRAP_LONG) currData).getValue(); | |||||
} else if (currData instanceof WRAP_BYTES) { | |||||
return ((WRAP_BYTES) currData).getValue(); | |||||
} else if (currData instanceof WRAP_SHORT) { | |||||
return ((WRAP_SHORT) currData).getValue(); | |||||
} else { | |||||
return currData; | |||||
} | |||||
} | |||||
} | |||||
//package com.jd.blockchain.contract; | |||||
// | |||||
//import java.util.ArrayList; | |||||
//import java.util.HashMap; | |||||
//import java.util.List; | |||||
//import java.util.Map; | |||||
// | |||||
//import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
//import com.jd.blockchain.binaryproto.DataContract; | |||||
//import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
//import com.jd.blockchain.contract.param.WRAP_BYTES; | |||||
//import com.jd.blockchain.contract.param.WRAP_INT; | |||||
//import com.jd.blockchain.contract.param.WRAP_LONG; | |||||
//import com.jd.blockchain.contract.param.WRAP_SHORT; | |||||
//import com.jd.blockchain.contract.param.WRAP_STRING; | |||||
//import com.jd.blockchain.ledger.BytesValue; | |||||
//import com.jd.blockchain.ledger.BytesValueList; | |||||
//import com.jd.blockchain.utils.io.BytesUtils; | |||||
// | |||||
//public class ContractSerializeUtils { | |||||
// | |||||
// final static int INT_LENGTH = 4; | |||||
// | |||||
// static Map<Class<?>, Class<?>> MAP = new HashMap<>(); | |||||
// | |||||
// static { | |||||
// MAP.put(byte[].class, WRAP_BYTES.class); | |||||
// MAP.put(Short.class, WRAP_SHORT.class); | |||||
// MAP.put(short.class, WRAP_SHORT.class); | |||||
// MAP.put(Integer.class, WRAP_INT.class); | |||||
// MAP.put(int.class, WRAP_INT.class); | |||||
// MAP.put(Long.class, WRAP_LONG.class); | |||||
// MAP.put(long.class, WRAP_LONG.class); | |||||
// MAP.put(String.class, WRAP_STRING.class); | |||||
// | |||||
// DataContractRegistry.register(WRAP_BYTES.class); | |||||
// DataContractRegistry.register(WRAP_SHORT.class); | |||||
// DataContractRegistry.register(WRAP_INT.class); | |||||
// DataContractRegistry.register(WRAP_LONG.class); | |||||
// DataContractRegistry.register(WRAP_STRING.class); | |||||
// } | |||||
// | |||||
// public static boolean support(Class<?> clazz) { | |||||
// if (clazz.isAnnotationPresent(DataContract.class) || MAP.containsKey(clazz)) { | |||||
// return true; | |||||
// } | |||||
// return false; | |||||
// } | |||||
// | |||||
// public static BytesValue serialize(Object data) { | |||||
// | |||||
// if (data == null) { | |||||
// return null; | |||||
// } | |||||
// | |||||
// Class<?> clazz = data.getClass(); | |||||
// Class<?> serialClass; | |||||
// Object wrapData = data; | |||||
// if (clazz.isAnnotationPresent(DataContract.class)) { | |||||
// serialClass = clazz; | |||||
// } else { | |||||
// // 判断类型是否可以序列化 | |||||
// Class<?> wrapClass = MAP.get(clazz); | |||||
// if (wrapClass == null) { | |||||
// throw new IllegalArgumentException("There are Un-Support Type !!!"); | |||||
// } | |||||
// serialClass = wrapClass; | |||||
// | |||||
// if (wrapClass.equals(WRAP_BYTES.class)) { | |||||
// wrapData = (WRAP_BYTES) () -> (byte[]) data; | |||||
// } else if (wrapClass.equals(WRAP_INT.class)) { | |||||
// wrapData = (WRAP_INT) () -> (int) data; | |||||
// } else if (wrapClass.equals(WRAP_LONG.class)) { | |||||
// wrapData = (WRAP_LONG) () -> (long) data; | |||||
// } else if (wrapClass.equals(WRAP_SHORT.class)) { | |||||
// wrapData = (WRAP_SHORT) () -> (short) data; | |||||
// } else if (wrapClass.equals(WRAP_STRING.class)) { | |||||
// wrapData = (WRAP_STRING) () -> (String) data; | |||||
// } | |||||
// } | |||||
// // 按照对应接口进行序列化 | |||||
// // 生成该接口对应的对象 | |||||
// return BinaryProtocol.encode(wrapData, serialClass); | |||||
// } | |||||
// | |||||
// public static BytesValueList serializeArray(Object[] datas) { | |||||
// if (datas == null || datas.length == 0) { | |||||
// return null; | |||||
// } | |||||
// int contentBytesSize = 0; | |||||
// byte[] header = new byte[(datas.length + 1) * 4]; | |||||
// System.arraycopy(BytesUtils.toBytes(datas.length), 0, header, 0, INT_LENGTH); | |||||
// int offset = INT_LENGTH; | |||||
// | |||||
// List<byte[]> serialBytesList = new ArrayList<>(); | |||||
// for (Object data : datas) { | |||||
// // 按照对应接口进行序列化 | |||||
// byte[] currBytes = serialize(data); | |||||
// // 长度写入 | |||||
// System.arraycopy(BytesUtils.toBytes(currBytes.length), 0, header, offset, INT_LENGTH); | |||||
// serialBytesList.add(currBytes); | |||||
// contentBytesSize += currBytes.length; | |||||
// offset += INT_LENGTH; | |||||
// } | |||||
// | |||||
// // 填充content | |||||
// byte[] content = new byte[contentBytesSize]; | |||||
// offset = 0; | |||||
// for (byte[] bytes : serialBytesList) { | |||||
// System.arraycopy(bytes, 0, content, offset, bytes.length); | |||||
// offset += bytes.length; | |||||
// } | |||||
// // 将header和content组装 | |||||
// return BytesUtils.concat(header, content); | |||||
// } | |||||
// | |||||
// public static Object[] resolveArray(byte[] bytes) { | |||||
// if (bytes == null || bytes.length == 0) { | |||||
// return null; | |||||
// } | |||||
// byte[] lengthBytes = new byte[INT_LENGTH]; | |||||
// System.arraycopy(bytes, 0, lengthBytes, 0, INT_LENGTH); | |||||
// int length = BytesUtils.toInt(lengthBytes); | |||||
// Object[] datas = new Object[length]; | |||||
// | |||||
// int headerOffset = INT_LENGTH; | |||||
// int contentStart = (length + 1) * INT_LENGTH; | |||||
// | |||||
// for (int i = 0; i < length; i++) { | |||||
// byte[] currDataLengthBytes = new byte[INT_LENGTH]; | |||||
// System.arraycopy(bytes, headerOffset, currDataLengthBytes, 0, INT_LENGTH); | |||||
// int currDataLength = BytesUtils.toInt(currDataLengthBytes); | |||||
// // 读取 | |||||
// byte[] dataBytes = new byte[currDataLength]; | |||||
// System.arraycopy(bytes, contentStart, dataBytes, 0, currDataLength); | |||||
// | |||||
// datas[i] = resolve(dataBytes); | |||||
// | |||||
// contentStart += currDataLength; | |||||
// headerOffset += INT_LENGTH; | |||||
// } | |||||
// | |||||
// return datas; | |||||
// } | |||||
// | |||||
// public static Object resolve(BytesValue bytes) { | |||||
// // 反序列化该接口 | |||||
// Object currData = BinaryProtocol.decode(bytes); | |||||
// | |||||
// // 代理对象类型不能使用class判断,只能使用instanceof | |||||
// if (currData instanceof WRAP_STRING) { | |||||
// return ((WRAP_STRING) currData).getValue(); | |||||
// } else if (currData instanceof WRAP_INT) { | |||||
// return ((WRAP_INT) currData).getValue(); | |||||
// } else if (currData instanceof WRAP_LONG) { | |||||
// return ((WRAP_LONG) currData).getValue(); | |||||
// } else if (currData instanceof WRAP_BYTES) { | |||||
// return ((WRAP_BYTES) currData).getValue(); | |||||
// } else if (currData instanceof WRAP_SHORT) { | |||||
// return ((WRAP_SHORT) currData).getValue(); | |||||
// } else { | |||||
// return currData; | |||||
// } | |||||
// } | |||||
//} |
@@ -1,195 +0,0 @@ | |||||
//package com.jd.blockchain.contract; | |||||
// | |||||
//import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
//import com.jd.blockchain.binaryproto.DataContract; | |||||
//import com.jd.blockchain.consts.DataCodes; | |||||
//import com.jd.blockchain.ledger.*; | |||||
//import com.jd.blockchain.utils.Bytes; | |||||
//import com.jd.blockchain.utils.IllegalDataException; | |||||
//import org.springframework.util.ReflectionUtils; | |||||
// | |||||
//import java.nio.ByteBuffer; | |||||
//import java.util.Arrays; | |||||
//import java.util.HashMap; | |||||
//import java.util.List; | |||||
//import java.util.Map; | |||||
// | |||||
///** | |||||
// * @author zhaogw | |||||
// * date 2019/5/16 18:05 | |||||
// */ | |||||
//public class ContractSerializeUtils { | |||||
// public static Map<Integer, Class<?>> DATA_CONTRACT_MAP = new HashMap<>(); | |||||
// public static final Integer[] PRIMITIVE_DATA_CODES = {DataCodes.CONTRACT_INT8, DataCodes.CONTRACT_INT16, DataCodes.CONTRACT_INT32, | |||||
// DataCodes.CONTRACT_INT64, DataCodes.CONTRACT_BIG_INT,DataCodes.CONTRACT_TEXT, DataCodes.CONTRACT_BINARY }; | |||||
// | |||||
// /** | |||||
// * serialize the Object[] by List<DataContract> list; | |||||
// * @param objArr | |||||
// * @param dataContractList | |||||
// * @return | |||||
// */ | |||||
// public static byte[] serializeMethodParam(Object[] objArr,List<DataContract> dataContractList) { | |||||
// byte[][] result = new byte[objArr.length][]; | |||||
// //将method中形参转换为实体对象,每个形参都必须为@DataContract类型;每个形参使用系统的BinaryProtocol来进行序列化,如果有5个参数,则使用5次序列化; | |||||
// int sum = 0; | |||||
// | |||||
// for(int i=0;i<objArr.length;i++){ | |||||
// DataContract dataContract = dataContractList.get(i); | |||||
// objArr[i] = regenObj(dataContract,objArr[i]); | |||||
// //get data interface; | |||||
// result[i] = BinaryProtocol.encode(objArr[i],getDataIntf().get(dataContract.code())); | |||||
// sum += result[i].length; | |||||
// } | |||||
// /** | |||||
// * return byte[] format: | |||||
// return is byte[], but now is byte[][], so we should reduct dimension by adding the header info to the rtnBytes[]; | |||||
// rtnBytes[]=classTypes.length/first length/second length/third length/result[0]/result[1]/result[2]; | |||||
// rtnBytes[0]: 4 bytes(classTypes.length); | |||||
// rtnBytes[1]: 4 bytes(1 param's length); | |||||
// rtnBytes[2]: 4 bytes(2 param's length); | |||||
// rtnBytes[3]: 4 bytes(3 param's length); | |||||
// rtnBytes[...]: result[0][] bytes(1 param's length); | |||||
// rtnBytes[...]: result[1][] bytes(2 param's length); | |||||
// rtnBytes[...]: result[2][] bytes(3 param's length); | |||||
// */ | |||||
// int bodyFirstPosition = 4 + 4 * (objArr.length); | |||||
// ByteBuffer byteBuffer = ByteBuffer.allocate(bodyFirstPosition + sum); | |||||
// byteBuffer.putInt(objArr.length); | |||||
// for(int j=0; j<result.length; j++) { | |||||
// byte[] curResult = result[j]; | |||||
// byteBuffer.putInt(curResult.length); | |||||
// } | |||||
// for(int k=0; k<result.length; k++){ | |||||
// byteBuffer.put(result[k]); | |||||
// } | |||||
// return byteBuffer.array(); | |||||
// } | |||||
// | |||||
// /** | |||||
// * deserialize the params bytes[]; | |||||
// * params format: nums|first length| second length| third length| ... |bytes[0]| byte[1] | bytes[2]| ... | |||||
// * @param params | |||||
// * @param dataContractList | |||||
// * @return | |||||
// */ | |||||
// public static Object[] deserializeMethodParam(byte[] params, List<DataContract> dataContractList) { | |||||
// Object result[] = new Object[dataContractList.size()]; | |||||
// ByteBuffer byteBuffer = ByteBuffer.allocate(params.length); | |||||
// byteBuffer.put(params); | |||||
// int paramNums = byteBuffer.getInt(0); | |||||
// | |||||
// if(paramNums != dataContractList.size()){ | |||||
// throw new IllegalArgumentException("deserialize Method param. params'length in byte[] != method's param length"); | |||||
// } | |||||
// | |||||
// int offsetPosition = (1 + dataContractList.size())*4; //start position of real data; | |||||
// for(int i=0; i<dataContractList.size(); i++){ | |||||
// DataContract dataContract = dataContractList.get(i); | |||||
// int curParamLength = byteBuffer.getInt((i+1)*4); | |||||
// ByteBuffer byteBuffer1 = ByteBuffer.allocate(curParamLength); | |||||
// byteBuffer1.put(params,offsetPosition,curParamLength); | |||||
// offsetPosition += curParamLength; | |||||
// //if dataContract=primitive type(byte/short/int/long/String),only use its getValues(); | |||||
// Object object = BinaryProtocol.decodeAs(byteBuffer1.array(), | |||||
// getDataIntf().get(dataContract.code())); | |||||
// if(isPrimitiveType(dataContract.code())){ | |||||
// Class<?> classObj = getDataIntf().get(dataContract.code()); | |||||
// try { | |||||
// result[i] = ReflectionUtils.invokeMethod(classObj.getMethod("getValue"),object); | |||||
// } catch (NoSuchMethodException e) { | |||||
// throw new IllegalStateException("no getValue(). detail="+e.getMessage()); | |||||
// } | |||||
// }else { | |||||
// result[i] = object; | |||||
// } | |||||
// byteBuffer1.clear(); | |||||
// } | |||||
// | |||||
// return result; | |||||
// } | |||||
// | |||||
// | |||||
// /** | |||||
// * the param types that we can support; | |||||
// * @param <T> | |||||
// * @return | |||||
// */ | |||||
// public static <T> Map<Integer, Class<?> > getDataIntf(){ | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT8, CONTRACT_INT8.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT16, CONTRACT_INT16.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT32, CONTRACT_INT32.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT64, CONTRACT_INT64.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_TEXT, CONTRACT_TEXT.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BINARY, CONTRACT_BINARY.class); | |||||
// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BIZ_CONTENT, ContractBizContent.class); | |||||
// return DATA_CONTRACT_MAP; | |||||
// } | |||||
// | |||||
// public static boolean isPrimitiveType(int dataContractCode){ | |||||
// return Arrays.asList(PRIMITIVE_DATA_CODES).contains(dataContractCode); | |||||
// } | |||||
// | |||||
// private static Object regenObj(DataContract dataContract, Object object){ | |||||
// if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT8.class)){ | |||||
// | |||||
// return (CONTRACT_INT8) () -> Byte.parseByte(object.toString()); | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT16.class)){ | |||||
// return (CONTRACT_INT16) () -> Short.parseShort(object.toString()); | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT32.class)){ | |||||
// return (CONTRACT_INT32) () -> Integer.parseInt(object.toString()); | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT64.class)){ | |||||
// return (CONTRACT_INT64) () -> Long.parseLong(object.toString()); | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_TEXT.class)){ | |||||
// return (CONTRACT_TEXT) () -> object.toString(); | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_BINARY.class)){ | |||||
// return (CONTRACT_BINARY) () -> (Bytes) object; | |||||
// }else if(getDataIntf().get(dataContract.code()).equals(ContractBizContent.class)){ | |||||
// ContractBizContent contractBizContent = (ContractBizContent)object; | |||||
// return contractBizContent; | |||||
// }else { | |||||
// throw new IllegalDataException("cann't get new Object by dataContract and object."); | |||||
// } | |||||
// } | |||||
// | |||||
// /** | |||||
// * get contractType(contain @DataContract) by primitive class type; | |||||
// * some class type can be supported default (byte/char/int/long/String/Bytes, and so on). | |||||
// * in other words, need not contain the @DataContract in its class for contract param's serialization or deserialization. | |||||
// * @param classType | |||||
// * @return | |||||
// */ | |||||
// private static Class<?> getContractTypeByPrimitiveType(Class<?> classType) { | |||||
// if(classType.equals(byte.class) || classType.equals(Byte.class)){ | |||||
// return CONTRACT_INT8.class; | |||||
// }else if(classType.equals(char.class) || classType.equals(Character.class)){ | |||||
// return CONTRACT_INT16.class; | |||||
// }else if(classType.equals(int.class) || classType.equals(Integer.class)){ | |||||
// return CONTRACT_INT32.class; | |||||
// }else if(classType.equals(long.class) || classType.equals(Long.class)){ | |||||
// return CONTRACT_INT64.class; | |||||
// }else if(classType.equals(String.class)){ | |||||
// return CONTRACT_TEXT.class; | |||||
// }else if(classType.equals(Bytes.class)){ | |||||
// return CONTRACT_BINARY.class; | |||||
// }else { | |||||
// throw new IllegalDataException(String.format("no support the classType=%s, please check @DataContract.",classType.toString())); | |||||
// } | |||||
// } | |||||
// | |||||
// public static DataContract parseDataContract(Class<?> classType){ | |||||
// DataContract dataContract = classType.getAnnotation(DataContract.class); | |||||
// //if the param's class Type don't contain @DataContract, then check parameterAnnotations of this method. | |||||
// if(dataContract == null){ | |||||
// boolean canPass = false; | |||||
// //if parameterAnnotations don't contain @DataContract, is it primitive type? | |||||
// Class<?> contractType = getContractTypeByPrimitiveType(classType); | |||||
// dataContract = contractType.getAnnotation(DataContract.class); | |||||
// } | |||||
// if(!getDataIntf().containsKey(dataContract.code())){ | |||||
// throw new IllegalArgumentException(String.format( | |||||
// "for now, this @dataContract(code=%s) is forbidden in the param list.",dataContract.code())); | |||||
// } | |||||
// return dataContract; | |||||
// } | |||||
//} |
@@ -5,7 +5,7 @@ import java.util.HashMap; | |||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | import java.util.Set; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
import com.jd.blockchain.utils.IllegalDataException; | import com.jd.blockchain.utils.IllegalDataException; | ||||
public class ContractType { | public class ContractType { | ||||
@@ -113,7 +113,7 @@ public class ContractType { | |||||
// check param's type is fit for need. | // check param's type is fit for need. | ||||
Class<?>[] paramTypes = method.getParameterTypes(); | Class<?>[] paramTypes = method.getParameterTypes(); | ||||
for (Class<?> currParamType : paramTypes) { | for (Class<?> currParamType : paramTypes) { | ||||
if (!ContractSerializeUtils.support(currParamType)) { | |||||
if (!BytesValueEncoding.supportType(currParamType)) { | |||||
throw new IllegalStateException( | throw new IllegalStateException( | ||||
String.format("Param Type = %s can not support !!!", currParamType.getName())); | String.format("Param Type = %s can not support !!!", currParamType.getName())); | ||||
} | } | ||||
@@ -121,7 +121,7 @@ public class ContractType { | |||||
// 判断返回值是否可序列化 | // 判断返回值是否可序列化 | ||||
Class<?> returnType = method.getReturnType(); | Class<?> returnType = method.getReturnType(); | ||||
if (!ContractSerializeUtils.support(returnType)) { | |||||
if (!BytesValueEncoding.supportType(returnType)) { | |||||
throw new IllegalStateException( | throw new IllegalStateException( | ||||
String.format("Return Type = %s can not support !!!", returnType.getName())); | String.format("Return Type = %s can not support !!!", returnType.getName())); | ||||
} | } | ||||
@@ -1,13 +0,0 @@ | |||||
package com.jd.blockchain.contract.param; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataField; | |||||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
import com.jd.blockchain.consts.DataCodes; | |||||
@DataContract(code = DataCodes.CONTRACT_BYTES) | |||||
public interface WRAP_BYTES { | |||||
@DataField(order = 1, primitiveType = PrimitiveType.BYTES) | |||||
byte[] getValue(); | |||||
} |
@@ -1,13 +0,0 @@ | |||||
package com.jd.blockchain.contract.param; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataField; | |||||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
import com.jd.blockchain.consts.DataCodes; | |||||
@DataContract(code = DataCodes.CONTRACT_INT) | |||||
public interface WRAP_INT { | |||||
@DataField(order = 1, primitiveType = PrimitiveType.INT32) | |||||
int getValue(); | |||||
} |
@@ -1,13 +0,0 @@ | |||||
package com.jd.blockchain.contract.param; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataField; | |||||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
import com.jd.blockchain.consts.DataCodes; | |||||
@DataContract(code = DataCodes.CONTRACT_LONG) | |||||
public interface WRAP_LONG { | |||||
@DataField(order = 1, primitiveType = PrimitiveType.INT64) | |||||
long getValue(); | |||||
} |
@@ -1,13 +0,0 @@ | |||||
package com.jd.blockchain.contract.param; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataField; | |||||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
import com.jd.blockchain.consts.DataCodes; | |||||
@DataContract(code = DataCodes.CONTRACT_SHORT) | |||||
public interface WRAP_SHORT { | |||||
@DataField(order = 1, primitiveType = PrimitiveType.INT16) | |||||
short getValue(); | |||||
} |
@@ -1,13 +0,0 @@ | |||||
package com.jd.blockchain.contract.param; | |||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.binaryproto.DataField; | |||||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||||
import com.jd.blockchain.consts.DataCodes; | |||||
@DataContract(code = DataCodes.CONTRACT_STRING) | |||||
public interface WRAP_STRING { | |||||
@DataField(order = 1, primitiveType = PrimitiveType.TEXT) | |||||
String getValue(); | |||||
} |
@@ -0,0 +1,60 @@ | |||||
package com.jd.blockchain.ledger; | |||||
public class BytesValueEncoding { | |||||
public static BytesValue encode(Object value, Class<?> type) { | |||||
} | |||||
public static BytesValueList encode(Object[] values, Class<?>[] types) { | |||||
} | |||||
public static Object decode(BytesValue value, Class<?> type) { | |||||
} | |||||
public static Object[] decode(BytesValueList values, Class<?>[] types) { | |||||
} | |||||
public static Object getDefaultValue(Class<?> type) { | |||||
if (type == void.class || type == Void.class) { | |||||
return null; | |||||
} | |||||
if (!type.isPrimitive()) { | |||||
// 非基本类型 | |||||
return null; | |||||
} else { | |||||
// 基本类型需要处理返回值,目前采用枚举遍历方式 | |||||
// 八种基本类型:int, double, float, long, short, boolean, byte, char, void | |||||
if (type.equals(int.class)) { | |||||
return 0; | |||||
} else if (type.equals(double.class)) { | |||||
return 0.0D; | |||||
} else if (type.equals(float.class)) { | |||||
return 0F; | |||||
} else if (type.equals(long.class)) { | |||||
return 0L; | |||||
} else if (type.equals(short.class)) { | |||||
return (short) 0; | |||||
} else if (type.equals(boolean.class)) { | |||||
return Boolean.FALSE; | |||||
} else if (type.equals(byte.class)) { | |||||
return (byte) 0; | |||||
} else if (type.equals(char.class)) { | |||||
return (char) 0; | |||||
} | |||||
return null; | |||||
} | |||||
} | |||||
public static boolean supportType(Class<?> currParamType) { | |||||
// TODO Auto-generated method stub | |||||
return false; | |||||
} | |||||
} |
@@ -6,6 +6,7 @@ import java.util.concurrent.Future; | |||||
import com.jd.blockchain.contract.ContractType; | import com.jd.blockchain.contract.ContractType; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
/** | /** | ||||
* ContractInvocation 包装了客户端发起的一次合约方法调用的相关信息,用于在客户端交易处理上下文进行共享处理状态; | * ContractInvocation 包装了客户端发起的一次合约方法调用的相关信息,用于在客户端交易处理上下文进行共享处理状态; | ||||
@@ -53,14 +54,9 @@ class ContractInvocation implements OperationReturnValueHandler { | |||||
@Override | @Override | ||||
public Object setReturnValue(BytesValue bytesValue) { | public Object setReturnValue(BytesValue bytesValue) { | ||||
// Resolve BytesValue to an value object with the return type; | // Resolve BytesValue to an value object with the return type; | ||||
Object returnValue = resolveValue(bytesValue, method.getReturnType()); | |||||
Object returnValue = BytesValueEncoding.decode(bytesValue, method.getReturnType()); | |||||
returnValueFuture.complete(returnValue); | returnValueFuture.complete(returnValue); | ||||
return returnValue; | return returnValue; | ||||
} | } | ||||
private Object resolveValue(BytesValue bytesValue, Class<?> returnType) { | |||||
// TODO: Resolve BytesValue to an value object with the return type; | |||||
throw new IllegalStateException("Not implemented!"); | |||||
} | |||||
} | } |
@@ -5,8 +5,8 @@ import java.lang.reflect.Method; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import com.jd.blockchain.contract.ContractException; | import com.jd.blockchain.contract.ContractException; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.contract.ContractType; | import com.jd.blockchain.contract.ContractType; | ||||
import com.jd.blockchain.ledger.BytesValueEncoding; | |||||
import com.jd.blockchain.ledger.BytesValueList; | import com.jd.blockchain.ledger.BytesValueList; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.IllegalDataException; | import com.jd.blockchain.utils.IllegalDataException; | ||||
@@ -52,7 +52,8 @@ public class ContractInvocationHandler implements InvocationHandler { | |||||
method.toString())); | method.toString())); | ||||
} | } | ||||
// 序列化调用参数; | // 序列化调用参数; | ||||
BytesValueList argBytes = serializeArgs(args); | |||||
Class<?>[] argTypes = method.getParameterTypes(); | |||||
BytesValueList argBytes = BytesValueEncoding.encode(args, argTypes); | |||||
// 定义合约调用操作; | // 定义合约调用操作; | ||||
ContractEventSendOpTemplate opTemplate = (ContractEventSendOpTemplate) sendOpBuilder.send(contractAddress, | ContractEventSendOpTemplate opTemplate = (ContractEventSendOpTemplate) sendOpBuilder.send(contractAddress, | ||||
@@ -68,42 +69,7 @@ public class ContractInvocationHandler implements InvocationHandler { | |||||
ContractInvocationStub.set(invocation); | ContractInvocationStub.set(invocation); | ||||
// 返回类型的默认值 | // 返回类型的默认值 | ||||
return getDefaultValue(method.getReturnType()); | |||||
return BytesValueEncoding.getDefaultValue(method.getReturnType()); | |||||
} | } | ||||
private BytesValueList serializeArgs(Object[] args) { | |||||
return ContractSerializeUtils.serializeArray(args); | |||||
} | |||||
private Object getDefaultValue(Class<?> returnType) { | |||||
if (returnType == void.class || returnType == Void.class) { | |||||
return null; | |||||
} | |||||
if (!returnType.isPrimitive()) { | |||||
// 非基本类型 | |||||
return null; | |||||
} else { | |||||
// 基本类型需要处理返回值,目前采用枚举遍历方式 | |||||
// 八种基本类型:int, double, float, long, short, boolean, byte, char, void | |||||
if (returnType.equals(int.class)) { | |||||
return 0; | |||||
} else if (returnType.equals(double.class)) { | |||||
return 0.0D; | |||||
} else if (returnType.equals(float.class)) { | |||||
return 0F; | |||||
} else if (returnType.equals(long.class)) { | |||||
return 0L; | |||||
} else if (returnType.equals(short.class)) { | |||||
return (short) 0; | |||||
} else if (returnType.equals(boolean.class)) { | |||||
return Boolean.FALSE; | |||||
} else if (returnType.equals(byte.class)) { | |||||
return (byte) 0; | |||||
} else if (returnType.equals(char.class)) { | |||||
return (char) 0; | |||||
} | |||||
return null; | |||||
} | |||||
} | |||||
} | } |