@@ -79,19 +79,6 @@ public interface DataCodes { | |||
public static final int DATA = 0x900; | |||
//contract related; | |||
public static final int CONTRACT = 0xA00; | |||
public static final int CONTRACT_INT8 = 0xA01; | |||
public static final int CONTRACT_INT16 = 0xA02; | |||
public static final int CONTRACT_INT32 = 0xA03; | |||
public static final int CONTRACT_INT64 = 0xA04; | |||
public static final int CONTRACT_TEXT = 0xA05; | |||
public static final int CONTRACT_BINARY = 0xA06; | |||
public static final int CONTRACT_BIG_INT = 0xA07; | |||
//...0xA19 | |||
public static final int CONTRACT_BIZ_CONTENT = 0xA20; | |||
public static final int CONTRACT_ARGS = 0xA21; | |||
public static final int HASH = 0xB00; | |||
public static final int HASH_OBJECT = 0xB10; | |||
@@ -1,19 +1,19 @@ | |||
package com.jd.blockchain.contract.jvm; | |||
import java.lang.reflect.Method; | |||
import java.util.List; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.util.ReflectionUtils; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.contract.ContractEventContext; | |||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||
import com.jd.blockchain.contract.engine.ContractCode; | |||
import com.jd.blockchain.runtime.Module; | |||
import com.jd.blockchain.transaction.ContractType; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.util.ReflectionUtils; | |||
import java.lang.reflect.Method; | |||
import java.util.List; | |||
/** | |||
* contract code based jvm | |||
@@ -55,7 +55,9 @@ public class JavaContractCode implements ContractCode { | |||
if(args == null || args.length == 0){ | |||
return null; | |||
} | |||
return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); | |||
//TODO: Not implemented; | |||
throw new IllegalStateException("Not implemented!"); | |||
// return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); | |||
} | |||
class ContractExecution implements Runnable { | |||
@@ -83,14 +85,15 @@ public class JavaContractCode implements ContractCode { | |||
if (handleMethod == null){ | |||
throw new IllegalDataException("don't get this method by it's @ContractEvent."); | |||
} | |||
Object args = resolveArgs(contractEventContext.getArgs(), | |||
contractType.getDataContractMap().get(handleMethod)); | |||
Object[] params = null; | |||
if(args.getClass().isArray()){ | |||
params = (Object[])args; | |||
} | |||
ReflectionUtils.invokeMethod(handleMethod, contractMainClassObj, params); | |||
//TODO: Not implemented; | |||
// Object args = resolveArgs(contractEventContext.getArgs(), | |||
// contractType.getDataContractMap().get(handleMethod)); | |||
// | |||
// Object[] params = null; | |||
// if(args.getClass().isArray()){ | |||
// params = (Object[])args; | |||
// } | |||
// ReflectionUtils.invokeMethod(handleMethod, contractMainClassObj, params); | |||
LOGGER.info("合约执行,耗时:" + (System.currentTimeMillis() - startTime)); | |||
@@ -1,196 +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_BIG_INT, CONTRACT_BIG_INT.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; | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import java.math.BigDecimal; | |||
/** | |||
* contract args for BIG_INT; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_BIG_INT) | |||
public interface CONTRACT_BIG_INT { | |||
@DataField(order=2, primitiveType= PrimitiveType.BIG_INT) | |||
BigDecimal getValue(); | |||
} |
@@ -1,19 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import com.jd.blockchain.utils.Bytes; | |||
/** | |||
* contract args for Binary; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_BINARY) | |||
public interface CONTRACT_BINARY { | |||
@DataField(order=2, primitiveType= PrimitiveType.BYTES) | |||
Bytes getValue(); | |||
} |
@@ -1,18 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* contract args for int16; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_INT16) | |||
public interface CONTRACT_INT16 { | |||
@DataField(order=2, primitiveType= PrimitiveType.INT16) | |||
short getValue(); | |||
} |
@@ -1,18 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* contract args for int32; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_INT32) | |||
public interface CONTRACT_INT32 { | |||
@DataField(order=2, primitiveType= PrimitiveType.INT32) | |||
int getValue(); | |||
} |
@@ -1,18 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* contract args for int64; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_INT64) | |||
public interface CONTRACT_INT64 { | |||
@DataField(order=2, primitiveType= PrimitiveType.INT64) | |||
long getValue(); | |||
} |
@@ -1,18 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* contract args for int8; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_INT8) | |||
public interface CONTRACT_INT8 { | |||
@DataField(order=2, primitiveType= PrimitiveType.INT8) | |||
Byte getValue(); | |||
} |
@@ -1,18 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* contract args for String; | |||
* @author zhaogw | |||
* date 2019-05-17 15:32 | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_TEXT) | |||
public interface CONTRACT_TEXT { | |||
@DataField(order=2, primitiveType= PrimitiveType.TEXT) | |||
String getValue(); | |||
} |
@@ -1,14 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import java.lang.reflect.Method; | |||
/** | |||
* contract's args; | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_ARGS) | |||
public interface ContractArgs { | |||
Method getMethod(); | |||
Object[] getArgs(); | |||
} |
@@ -1,20 +0,0 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
/** | |||
* build complex param Object, provide more String attributes; | |||
*/ | |||
@DataContract(code = DataCodes.CONTRACT_BIZ_CONTENT) | |||
public interface ContractBizContent { | |||
/** | |||
* param lists; | |||
* @return | |||
*/ | |||
@DataField(order = 1, list = true, primitiveType = PrimitiveType.TEXT, genericContract = true) | |||
String[] getAttrs(); | |||
} |
@@ -1,12 +1,11 @@ | |||
package com.jd.blockchain.transaction; | |||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
import java.lang.reflect.InvocationHandler; | |||
import java.lang.reflect.Method; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
public class ContractInvocationProxy implements InvocationHandler { | |||
// private String contractMessage; | |||
@@ -49,6 +48,7 @@ public class ContractInvocationProxy implements InvocationHandler { | |||
if(args == null || args.length==0){ | |||
return null; | |||
} | |||
return ContractSerializeUtils.serializeMethodParam(args,contractType.getDataContractMap().get(method)); | |||
throw new IllegalStateException("Not implemented!"); | |||
//return ContractSerializeUtils.serializeMethodParam(args,contractType.getDataContractMap().get(method)); | |||
} | |||
} |
@@ -1,22 +1,24 @@ | |||
package com.jd.blockchain.transaction; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import java.lang.annotation.Annotation; | |||
import java.lang.reflect.Method; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
import com.jd.blockchain.contract.ContractException; | |||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
import java.lang.annotation.Annotation; | |||
import java.lang.reflect.Method; | |||
import java.util.*; | |||
public class ContractType { | |||
private String name; | |||
private Map<String, Method> events = new HashMap<>(); | |||
private Map<Method, String> handleMethods = new HashMap<>(); | |||
private Map<Method, List<DataContract>> dataContractMap = new HashMap<>(); | |||
// private Map<Method, List<DataContract>> dataContractMap = new HashMap<>(); | |||
/** | |||
* 返回声明的所有事件; | |||
@@ -27,9 +29,9 @@ public class ContractType { | |||
return events.keySet(); | |||
} | |||
public Map<Method, List<DataContract>> getDataContractMap() { | |||
return dataContractMap; | |||
} | |||
// public Map<Method, List<DataContract>> getDataContractMap() { | |||
// return dataContractMap; | |||
// } | |||
/** | |||
* 返回指定方法声明的事件;<br> | |||
@@ -84,12 +86,13 @@ public class ContractType { | |||
Class<?>[] paramTypes = method.getParameterTypes(); | |||
List dataContractList = new ArrayList(); | |||
for(Class<?> curParamType : paramTypes){ | |||
DataContract dataContract = ContractSerializeUtils.parseDataContract(curParamType); | |||
dataContractList.add(dataContract); | |||
} | |||
if(dataContractList.size()>0){ | |||
contractType.dataContractMap.put(method,dataContractList); | |||
throw new IllegalStateException("Not implemented!"); | |||
// DataContract dataContract = ContractSerializeUtils.parseDataContract(curParamType); | |||
// dataContractList.add(dataContract); | |||
} | |||
// if(dataContractList.size()>0){ | |||
// contractType.dataContractMap.put(method,dataContractList); | |||
// } | |||
contractType.events.put(eventName_, method); | |||
contractType.handleMethods.put(method,eventName_); | |||
@@ -19,7 +19,7 @@ import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.BlockchainIdentityData; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.BytesValueEntry; | |||
import com.jd.blockchain.ledger.BytesValueType; | |||
import com.jd.blockchain.ledger.DataType; | |||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | |||
import com.jd.blockchain.ledger.ContractEventSendOperation; | |||
import com.jd.blockchain.ledger.CryptoSetting; | |||
@@ -83,7 +83,7 @@ public class ClientOperationUtil { | |||
} | |||
public static Object readValueByBytesValue(BytesValue bytesValue) { | |||
BytesValueType dataType = bytesValue.getType(); | |||
DataType dataType = bytesValue.getType(); | |||
Bytes saveVal = bytesValue.getValue(); | |||
Object showVal; | |||
switch (dataType) { | |||
@@ -125,7 +125,7 @@ public class ClientOperationUtil { | |||
String typeStr = valueObj.getString("type"); | |||
String realValBase58 = valueObj.getString("value"); | |||
String key = currWriteSetObj.getString("key"); | |||
BytesValueType dataType = BytesValueType.valueOf(typeStr); | |||
DataType dataType = DataType.valueOf(typeStr); | |||
BytesValue bytesValue =BytesValueEntry.fromType(dataType, Base58Utils.decode(realValBase58)); | |||
KVData kvData = new KVData(key, bytesValue, expectedVersion); | |||
kvOperation.set(kvData); | |||
@@ -56,14 +56,6 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl | |||
DataContractRegistry.register(ClientIdentifications.class); | |||
DataContractRegistry.register(ClientIdentification.class); | |||
DataContractRegistry.register(CONTRACT_INT8.class); | |||
DataContractRegistry.register(CONTRACT_INT16.class); | |||
DataContractRegistry.register(CONTRACT_INT32.class); | |||
DataContractRegistry.register(CONTRACT_INT64.class); | |||
DataContractRegistry.register(CONTRACT_TEXT.class); | |||
DataContractRegistry.register(CONTRACT_BINARY.class); | |||
DataContractRegistry.register(ContractBizContent.class); | |||
ByteArrayObjectUtil.init(); | |||
} | |||
@@ -1,53 +1,53 @@ | |||
package com.jd.blockchain.contract.samples; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
import com.jd.blockchain.ledger.ContractBizContent; | |||
import com.jd.blockchain.ledger.TransactionContentBody; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.math.BigDecimal; | |||
/** | |||
* 示例:一个“资产管理”智能合约; | |||
* | |||
* @author zhaogw | |||
*/ | |||
@Contract | |||
public interface AssetContract2 { | |||
/** | |||
* 发行资产; | |||
* 新发行的资产数量; | |||
* @param assetHolderAddress | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset-0") | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
/** | |||
* issue asset; | |||
* @param contractBizContent | |||
* @param assetHolderAddress | |||
* @param cashNumber | |||
*/ | |||
@ContractEvent(name = "issue-asset") | |||
public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
/** | |||
* Bytes can bring the byte[]; | |||
* @param bytes | |||
* @param assetHolderAddress | |||
* @param cashNumber | |||
*/ | |||
@ContractEvent(name = "issue-asset-2") | |||
void issue(Bytes bytes,String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-3") | |||
void issue(Byte bytes, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-4") | |||
void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
} | |||
//package com.jd.blockchain.contract.samples; | |||
// | |||
//import com.jd.blockchain.binaryproto.DataContract; | |||
//import com.jd.blockchain.consts.DataCodes; | |||
//import com.jd.blockchain.contract.Contract; | |||
//import com.jd.blockchain.contract.ContractEvent; | |||
//import com.jd.blockchain.ledger.ContractBizContent; | |||
//import com.jd.blockchain.ledger.TransactionContentBody; | |||
//import com.jd.blockchain.utils.Bytes; | |||
// | |||
//import java.math.BigDecimal; | |||
// | |||
///** | |||
// * 示例:一个“资产管理”智能合约; | |||
// * | |||
// * @author zhaogw | |||
// */ | |||
//@Contract | |||
//public interface AssetContract2 { | |||
// | |||
// /** | |||
// * 发行资产; | |||
// * 新发行的资产数量; | |||
// * @param assetHolderAddress | |||
// * 新发行的资产的持有账户; | |||
// */ | |||
// @ContractEvent(name = "issue-asset-0") | |||
// void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
// | |||
// /** | |||
// * issue asset; | |||
// * @param contractBizContent | |||
// * @param assetHolderAddress | |||
// * @param cashNumber | |||
// */ | |||
// @ContractEvent(name = "issue-asset") | |||
// public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
// | |||
// /** | |||
// * Bytes can bring the byte[]; | |||
// * @param bytes | |||
// * @param assetHolderAddress | |||
// * @param cashNumber | |||
// */ | |||
// @ContractEvent(name = "issue-asset-2") | |||
// void issue(Bytes bytes,String assetHolderAddress, long cashNumber); | |||
// | |||
// @ContractEvent(name = "issue-asset-3") | |||
// void issue(Byte bytes, String assetHolderAddress, long cashNumber); | |||
// | |||
// @ContractEvent(name = "issue-asset-4") | |||
// void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
//} |
@@ -1,10 +1,29 @@ | |||
package test.com.jd.blockchain.sdk.test; | |||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import org.junit.Before; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.core.io.ClassPathResource; | |||
import com.jd.blockchain.contract.samples.AssetContract; | |||
import com.jd.blockchain.contract.samples.AssetContract2; | |||
import com.jd.blockchain.crypto.*; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.sdk.samples.SDKDemo_Contract; | |||
@@ -13,19 +32,6 @@ import com.jd.blockchain.utils.codec.Base58Utils; | |||
import com.jd.blockchain.utils.io.ByteArray; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.core.io.ClassPathResource; | |||
import org.springframework.util.ReflectionUtils; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.lang.reflect.Method; | |||
import static org.junit.Assert.*; | |||
/** | |||
* 演示合约执行的过程; | |||
@@ -62,63 +68,63 @@ public class SDK_Contract_Test { | |||
bcsrv = serviceFactory.getBlockchainService(); | |||
} | |||
/** | |||
* 演示合约执行的过程; | |||
*/ | |||
// @Test | |||
public void demoContract1() { | |||
String dataAddress = registerData4Contract(); | |||
// 发起交易; | |||
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
String contractAddress = "LdeNg8JHFCKABJt6AaRNVCZPgY4ofGPd8MgcR"; | |||
AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
// assetContract.issue(transactionContentBody,contractAddress); | |||
// assetContract.issue(transactionContentBody,contractAddress,888888); | |||
// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
Byte byteObj = Byte.parseByte("127"); | |||
assetContract.issue(byteObj,dataAddress,321123); | |||
// assetContract.issue(contractBizContent,dataAddress); | |||
assetContract.issue(Byte.parseByte("126"),dataAddress,Bytes.fromString("100.234")); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(signKeyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
//check; | |||
KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,"total"); | |||
assertEquals("100",dataEntries[0].getValue().toString()); | |||
} | |||
/** | |||
* 演示合约执行的过程; | |||
*/ | |||
// @Test | |||
public void demoContract2() throws IOException { | |||
String contractAddress = deploy(); | |||
String dataAddress = registerData4Contract(); | |||
System.out.println("dataAddress="+dataAddress); | |||
// 发起交易; | |||
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; | |||
assetContract.issue(contractBizContent,dataAddress,123456); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(signKeyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
//check; | |||
assertTrue(transactionResponse.isSuccess()); | |||
KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,contractBizContent.getAttrs()[0],contractBizContent.getAttrs()[1]); | |||
assertEquals("value1",dataEntries[0].getValue().toString()); | |||
assertEquals(888,dataEntries[1].getValue()); | |||
} | |||
// /** | |||
// * 演示合约执行的过程; | |||
// */ | |||
//// @Test | |||
// public void demoContract1() { | |||
// String dataAddress = registerData4Contract(); | |||
// // 发起交易; | |||
// TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
// String contractAddress = "LdeNg8JHFCKABJt6AaRNVCZPgY4ofGPd8MgcR"; | |||
// AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
//// assetContract.issue(transactionContentBody,contractAddress); | |||
//// assetContract.issue(transactionContentBody,contractAddress,888888); | |||
//// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
//// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
// Byte byteObj = Byte.parseByte("127"); | |||
// assetContract.issue(byteObj,dataAddress,321123); | |||
//// assetContract.issue(contractBizContent,dataAddress); | |||
// assetContract.issue(Byte.parseByte("126"),dataAddress,Bytes.fromString("100.234")); | |||
// | |||
// // TX 准备就绪; | |||
// PreparedTransaction prepTx = txTemp.prepare(); | |||
// prepTx.sign(signKeyPair); | |||
// // 提交交易; | |||
// TransactionResponse transactionResponse = prepTx.commit(); | |||
// | |||
// //check; | |||
// KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,"total"); | |||
// assertEquals("100",dataEntries[0].getValue().toString()); | |||
// } | |||
// /** | |||
// * 演示合约执行的过程; | |||
// */ | |||
//// @Test | |||
// public void demoContract2() throws IOException { | |||
// String contractAddress = deploy(); | |||
// String dataAddress = registerData4Contract(); | |||
// System.out.println("dataAddress="+dataAddress); | |||
// // 发起交易; | |||
// TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
// | |||
// AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
// ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; | |||
// assetContract.issue(contractBizContent,dataAddress,123456); | |||
// | |||
// // TX 准备就绪; | |||
// PreparedTransaction prepTx = txTemp.prepare(); | |||
// prepTx.sign(signKeyPair); | |||
// // 提交交易; | |||
// TransactionResponse transactionResponse = prepTx.commit(); | |||
// | |||
// //check; | |||
// assertTrue(transactionResponse.isSuccess()); | |||
// KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,contractBizContent.getAttrs()[0],contractBizContent.getAttrs()[1]); | |||
// assertEquals("value1",dataEntries[0].getValue().toString()); | |||
// assertEquals(888,dataEntries[1].getValue()); | |||
// } | |||
// @Test | |||
public void registerData(){ | |||
@@ -346,31 +352,31 @@ public class SDK_Contract_Test { | |||
} | |||
@Test | |||
public void testStringArr(){ | |||
ContractBizContent contractBizContent = () -> new String[]{"1","2","you are welcome!"}; | |||
byte[] bizBytes = BinaryProtocol.encode(contractBizContent,ContractBizContent.class); | |||
ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class); | |||
assertArrayEquals(contractBizContent.getAttrs(),actualObj.getAttrs()); | |||
} | |||
@Test | |||
public void testContractArgs(){ | |||
ContractBizContent contractBizContent = () -> new String[]{"param1"}; | |||
Method method = ReflectionUtils.findMethod(AssetContract2.class,"issue",ContractBizContent.class,String.class); | |||
ContractArgs contractArgs = new ContractArgs() { | |||
@Override | |||
public Method getMethod() { | |||
return method; | |||
} | |||
@Override | |||
public Object[] getArgs() { | |||
return new Object[]{contractBizContent,"hello"}; | |||
} | |||
}; | |||
//add the annotation; | |||
// @Test | |||
// public void testStringArr(){ | |||
// ContractBizContent contractBizContent = () -> new String[]{"1","2","you are welcome!"}; | |||
// byte[] bizBytes = BinaryProtocol.encode(contractBizContent,ContractBizContent.class); | |||
// ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class); | |||
// assertArrayEquals(contractBizContent.getAttrs(),actualObj.getAttrs()); | |||
// } | |||
} | |||
// @Test | |||
// public void testContractArgs(){ | |||
// ContractBizContent contractBizContent = () -> new String[]{"param1"}; | |||
// Method method = ReflectionUtils.findMethod(AssetContract2.class,"issue",ContractBizContent.class,String.class); | |||
// ContractArgs contractArgs = new ContractArgs() { | |||
// @Override | |||
// public Method getMethod() { | |||
// return method; | |||
// } | |||
// | |||
// @Override | |||
// public Object[] getArgs() { | |||
// return new Object[]{contractBizContent,"hello"}; | |||
// } | |||
// }; | |||
// | |||
// //add the annotation; | |||
// | |||
// } | |||
} |
@@ -478,7 +478,7 @@ public class IntegrationBase { | |||
// execute the contract; | |||
testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||
testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||
// testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||
return block; | |||
} | |||
@@ -512,33 +512,33 @@ public class IntegrationBase { | |||
assertEquals("100",kvDataEntries[0].getValue().toString()); | |||
} | |||
private static <T> void testContractExe1(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, | |||
BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||
LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||
LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||
// 定义交易; | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
AssetContract2 assetContract = txTpl.contract(contractDeployKey.getAddress(), AssetContract2.class); | |||
ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; | |||
assetContract.issue(contractBizContent,dataKey.getAddress().toBase58(),123456); | |||
// 签名; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
ptx.sign(adminKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 验证结果; | |||
Assert.assertTrue(txResp.isSuccess()); | |||
assertEquals(ptx.getHash(),txResp.getContentHash()); | |||
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||
KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2); | |||
assertEquals("value1",kvDataEntries[0].getValue().toString()); | |||
assertEquals(888L,kvDataEntries[1].getValue()); | |||
} | |||
// private static <T> void testContractExe1(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, | |||
// BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||
// LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||
// LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||
// | |||
// // 定义交易; | |||
// TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// | |||
// AssetContract2 assetContract = txTpl.contract(contractDeployKey.getAddress(), AssetContract2.class); | |||
// ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; | |||
// assetContract.issue(contractBizContent,dataKey.getAddress().toBase58(),123456); | |||
// | |||
// // 签名; | |||
// PreparedTransaction ptx = txTpl.prepare(); | |||
// ptx.sign(adminKey); | |||
// | |||
// // 提交并等待共识返回; | |||
// TransactionResponse txResp = ptx.commit(); | |||
// | |||
// // 验证结果; | |||
// Assert.assertTrue(txResp.isSuccess()); | |||
// assertEquals(ptx.getHash(),txResp.getContentHash()); | |||
// LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||
// KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2); | |||
// assertEquals("value1",kvDataEntries[0].getValue().toString()); | |||
// assertEquals(888L,kvDataEntries[1].getValue()); | |||
// } | |||
/** | |||
* 根据合约构建字节数组; | |||
@@ -2,11 +2,8 @@ package test.com.jd.blockchain.intgr.contract; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
import com.jd.blockchain.ledger.ContractBizContent; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.math.BigDecimal; | |||
/** | |||
* 示例:一个“资产管理”智能合约; | |||
* | |||
@@ -15,23 +12,23 @@ import java.math.BigDecimal; | |||
@Contract | |||
public interface AssetContract2 { | |||
/** | |||
* 发行资产; | |||
* 新发行的资产数量; | |||
* @param assetHolderAddress | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset-0") | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
/** | |||
* 发行资产; | |||
* 新发行的资产数量; | |||
* @param assetHolderAddress | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset") | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
// /** | |||
// * 发行资产; | |||
// * 新发行的资产数量; | |||
// * @param assetHolderAddress | |||
// * 新发行的资产的持有账户; | |||
// */ | |||
// @ContractEvent(name = "issue-asset-0") | |||
// void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
// | |||
// /** | |||
// * 发行资产; | |||
// * 新发行的资产数量; | |||
// * @param assetHolderAddress | |||
// * 新发行的资产的持有账户; | |||
// */ | |||
// @ContractEvent(name = "issue-asset") | |||
// void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-2") | |||
void issue(Bytes bytes, String assetHolderAddress, long cashNumber); | |||