@@ -79,19 +79,6 @@ public interface DataCodes { | |||||
public static final int DATA = 0x900; | 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 = 0xB00; | ||||
public static final int HASH_OBJECT = 0xB10; | public static final int HASH_OBJECT = 0xB10; | ||||
@@ -1,19 +1,19 @@ | |||||
package com.jd.blockchain.contract.jvm; | 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.binaryproto.DataContract; | ||||
import com.jd.blockchain.contract.ContractEventContext; | import com.jd.blockchain.contract.ContractEventContext; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.contract.engine.ContractCode; | import com.jd.blockchain.contract.engine.ContractCode; | ||||
import com.jd.blockchain.runtime.Module; | import com.jd.blockchain.runtime.Module; | ||||
import com.jd.blockchain.transaction.ContractType; | import com.jd.blockchain.transaction.ContractType; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.IllegalDataException; | 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 | * contract code based jvm | ||||
@@ -55,7 +55,9 @@ public class JavaContractCode implements ContractCode { | |||||
if(args == null || args.length == 0){ | if(args == null || args.length == 0){ | ||||
return null; | return null; | ||||
} | } | ||||
return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); | |||||
//TODO: Not implemented; | |||||
throw new IllegalStateException("Not implemented!"); | |||||
// return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); | |||||
} | } | ||||
class ContractExecution implements Runnable { | class ContractExecution implements Runnable { | ||||
@@ -83,14 +85,15 @@ public class JavaContractCode implements ContractCode { | |||||
if (handleMethod == null){ | if (handleMethod == null){ | ||||
throw new IllegalDataException("don't get this method by it's @ContractEvent."); | 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)); | 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; | 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.InvocationHandler; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.utils.IllegalDataException; | |||||
public class ContractInvocationProxy implements InvocationHandler { | public class ContractInvocationProxy implements InvocationHandler { | ||||
// private String contractMessage; | // private String contractMessage; | ||||
@@ -49,6 +48,7 @@ public class ContractInvocationProxy implements InvocationHandler { | |||||
if(args == null || args.length==0){ | if(args == null || args.length==0){ | ||||
return null; | 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; | 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.Contract; | ||||
import com.jd.blockchain.contract.ContractEvent; | import com.jd.blockchain.contract.ContractEvent; | ||||
import com.jd.blockchain.contract.ContractException; | import com.jd.blockchain.contract.ContractException; | ||||
import com.jd.blockchain.contract.ContractSerializeUtils; | |||||
import com.jd.blockchain.utils.IllegalDataException; | import com.jd.blockchain.utils.IllegalDataException; | ||||
import java.lang.annotation.Annotation; | |||||
import java.lang.reflect.Method; | |||||
import java.util.*; | |||||
public class ContractType { | public class ContractType { | ||||
private String name; | private String name; | ||||
private Map<String, Method> events = new HashMap<>(); | private Map<String, Method> events = new HashMap<>(); | ||||
private Map<Method, String> handleMethods = 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(); | return events.keySet(); | ||||
} | } | ||||
public Map<Method, List<DataContract>> getDataContractMap() { | |||||
return dataContractMap; | |||||
} | |||||
// public Map<Method, List<DataContract>> getDataContractMap() { | |||||
// return dataContractMap; | |||||
// } | |||||
/** | /** | ||||
* 返回指定方法声明的事件;<br> | * 返回指定方法声明的事件;<br> | ||||
@@ -84,12 +86,13 @@ public class ContractType { | |||||
Class<?>[] paramTypes = method.getParameterTypes(); | Class<?>[] paramTypes = method.getParameterTypes(); | ||||
List dataContractList = new ArrayList(); | List dataContractList = new ArrayList(); | ||||
for(Class<?> curParamType : paramTypes){ | 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.events.put(eventName_, method); | ||||
contractType.handleMethods.put(method,eventName_); | 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.BlockchainIdentityData; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesValueEntry; | 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.ContractCodeDeployOperation; | ||||
import com.jd.blockchain.ledger.ContractEventSendOperation; | import com.jd.blockchain.ledger.ContractEventSendOperation; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
@@ -83,7 +83,7 @@ public class ClientOperationUtil { | |||||
} | } | ||||
public static Object readValueByBytesValue(BytesValue bytesValue) { | public static Object readValueByBytesValue(BytesValue bytesValue) { | ||||
BytesValueType dataType = bytesValue.getType(); | |||||
DataType dataType = bytesValue.getType(); | |||||
Bytes saveVal = bytesValue.getValue(); | Bytes saveVal = bytesValue.getValue(); | ||||
Object showVal; | Object showVal; | ||||
switch (dataType) { | switch (dataType) { | ||||
@@ -125,7 +125,7 @@ public class ClientOperationUtil { | |||||
String typeStr = valueObj.getString("type"); | String typeStr = valueObj.getString("type"); | ||||
String realValBase58 = valueObj.getString("value"); | String realValBase58 = valueObj.getString("value"); | ||||
String key = currWriteSetObj.getString("key"); | String key = currWriteSetObj.getString("key"); | ||||
BytesValueType dataType = BytesValueType.valueOf(typeStr); | |||||
DataType dataType = DataType.valueOf(typeStr); | |||||
BytesValue bytesValue =BytesValueEntry.fromType(dataType, Base58Utils.decode(realValBase58)); | BytesValue bytesValue =BytesValueEntry.fromType(dataType, Base58Utils.decode(realValBase58)); | ||||
KVData kvData = new KVData(key, bytesValue, expectedVersion); | KVData kvData = new KVData(key, bytesValue, expectedVersion); | ||||
kvOperation.set(kvData); | kvOperation.set(kvData); | ||||
@@ -56,14 +56,6 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl | |||||
DataContractRegistry.register(ClientIdentifications.class); | DataContractRegistry.register(ClientIdentifications.class); | ||||
DataContractRegistry.register(ClientIdentification.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(); | 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; | 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.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.BlockchainService; | ||||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | import com.jd.blockchain.sdk.client.GatewayServiceFactory; | ||||
import com.jd.blockchain.sdk.samples.SDKDemo_Contract; | 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.io.ByteArray; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | 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(); | 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 | // @Test | ||||
public void registerData(){ | 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; | // execute the contract; | ||||
testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | ||||
testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||||
// testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||||
return block; | return block; | ||||
} | } | ||||
@@ -512,33 +512,33 @@ public class IntegrationBase { | |||||
assertEquals("100",kvDataEntries[0].getValue().toString()); | 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.Contract; | ||||
import com.jd.blockchain.contract.ContractEvent; | import com.jd.blockchain.contract.ContractEvent; | ||||
import com.jd.blockchain.ledger.ContractBizContent; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import java.math.BigDecimal; | |||||
/** | /** | ||||
* 示例:一个“资产管理”智能合约; | * 示例:一个“资产管理”智能合约; | ||||
* | * | ||||
@@ -15,23 +12,23 @@ import java.math.BigDecimal; | |||||
@Contract | @Contract | ||||
public interface AssetContract2 { | 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") | @ContractEvent(name = "issue-asset-2") | ||||
void issue(Bytes bytes, String assetHolderAddress, long cashNumber); | void issue(Bytes bytes, String assetHolderAddress, long cashNumber); | ||||