Browse Source

The judgment of annotations to contract parameters is removed. Now you don't have to fill in parameter annotations in the interface. The primitive data types are automatically mapped in the background.

tags/1.0.0
zhaoguangwei 6 years ago
parent
commit
38c54c18aa
5 changed files with 78 additions and 111 deletions
  1. +7
    -3
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  2. +53
    -17
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java
  3. +13
    -4
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract2.java
  4. +0
    -85
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl2.java
  5. +5
    -2
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java

+ 7
- 3
source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java View File

@@ -1,11 +1,12 @@
package com.jd.blockchain.contract.jvm;

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.contract.ContractSerializeUtils;
import com.jd.blockchain.utils.IllegalDataException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
@@ -73,6 +74,9 @@ public class JavaContractCode implements ContractCode {

// 反序列化参数;
Method handleMethod = ContractType.resolve(myClass).getHandleMethod(contractEventContext.getEvent());
if (handleMethod == null){
throw new IllegalDataException("don't get this method by it's @ContractEvent.");
}
Object args = resolveArgs(contractEventContext.getArgs(), handleMethod);

Object[] params = null;
@@ -88,9 +92,9 @@ public class JavaContractCode implements ContractCode {
ReflectionUtils.invokeMethod(mth2, contractMainClassObj);
LOGGER.info("postEvent,耗时:" + (System.currentTimeMillis() - startTime));
} catch (NoSuchMethodException e) {
e.printStackTrace();
throw new IllegalArgumentException(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new IllegalDataException(e.getMessage());
}
}



+ 53
- 17
source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java View File

@@ -21,9 +21,10 @@ import java.util.Map;
*/
public class ContractSerializeUtils {
public static Map<Integer, Class<?>> DATA_CONTRACT_MAP = new HashMap<>();
public static final Integer[] PRIMITIVE_TYPES = {DataCodes.CONTRACT_INT8, DataCodes.CONTRACT_INT16, DataCodes.CONTRACT_INT32,
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 };


/**
* valid then parse the Object by Method params;
* @param object
@@ -31,7 +32,6 @@ public class ContractSerializeUtils {
* @return
*/
public static byte[] serializeMethodParam(Object object,Method method) {

if (object == null) {
return null;
}
@@ -53,15 +53,21 @@ public class ContractSerializeUtils {
if(dataContract == null){
boolean canPass = false;
//check by annotation;
Annotation[] annotationArr = annotations[i];
for(Annotation annotation : annotationArr){
if(annotation instanceof DataContract){
dataContract = (DataContract) annotation;
objArr[i] = regenObj(dataContract,objArr[i]);
canPass = true;
}
// Annotation[] annotationArr = annotations[i];
// for(Annotation annotation : annotationArr){
// if(annotation instanceof DataContract){
// dataContract = (DataContract) annotation;
// objArr[i] = regenObj(dataContract,objArr[i]);
// canPass = true;
// }
// }
//if parameterAnnotations don't contain @DataContract, is it primitive type?
Class<?> contractType = getContractTypeByPrimitiveType(classType);
dataContract = contractType.getDeclaredAnnotation(DataContract.class);
if(dataContract != null){
objArr[i] = regenObj(dataContract,objArr[i]);
canPass = true;
}
//if parameterAnnotations don't contain @DataContract, we will say goodbye.
if(!canPass){
throw new IllegalArgumentException("must set @DataContract for each param of contract.");
}
@@ -131,12 +137,18 @@ public class ContractSerializeUtils {
if(dataContract == null){
boolean canPass = false;
//check by annotation;
Annotation[] annotationArr = annotations[i];
for(Annotation annotation : annotationArr){
if(annotation.annotationType().equals(DataContract.class)){
dataContract = (DataContract) annotation;
canPass = true;
}
// Annotation[] annotationArr = annotations[i];
// for(Annotation annotation : annotationArr){
// if(annotation.annotationType().equals(DataContract.class)){
// dataContract = (DataContract) annotation;
// canPass = true;
// }
// }
//if parameterAnnotations don't contain @DataContract, is it primitive type?
Class<?> contractType = getContractTypeByPrimitiveType(classType);
dataContract = contractType.getDeclaredAnnotation(DataContract.class);
if(dataContract != null){
canPass = true;
}
if(!canPass){
throw new IllegalArgumentException("must set annotation in each param of contract.");
@@ -183,7 +195,7 @@ public class ContractSerializeUtils {
}

public static boolean isPrimitiveType(int dataContractCode){
return Arrays.asList(PRIMITIVE_TYPES).contains(dataContractCode);
return Arrays.asList(PRIMITIVE_DATA_CODES).contains(dataContractCode);
}

private static Object regenObj(DataContract dataContract, Object object){
@@ -204,4 +216,28 @@ public class ContractSerializeUtils {
}
return null;
}

/**
* 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;
}
return null;
}
}

+ 13
- 4
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract2.java View File

@@ -4,7 +4,6 @@ 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.CONTRACT_TEXT;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.utils.Bytes;

@@ -37,8 +36,18 @@ public interface AssetContract2 {
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress,
@DataContract(code = DataCodes.CONTRACT_INT64) long cashNumber);

/**
* Bytes can bring the byte[];
* @param bytes
* @param assetHolderAddress
* @param cashNumber
*/
@ContractEvent(name = "issue-asset-2")
void issue(@DataContract(code = DataCodes.CONTRACT_BINARY) Bytes bytes,
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress,
@DataContract(code = DataCodes.CONTRACT_INT64) long cashNumber);
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 issue1(byte[] bytes, String assetHolderAddress, long cashNumber);
}

+ 0
- 85
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl2.java View File

@@ -1,85 +0,0 @@
package com.jd.blockchain.contract.samples;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.contract.ContractEvent;
import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.EventProcessingAwire;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* 示例:一个“资产管理”智能合约的实现;
*
* 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现
* AssetContract 接口定义的合约方法;
*
* @author huanghaiquan
*
*/
public class AssetContractImpl2 implements EventProcessingAwire, AssetContract2 {
// 合约事件上下文;
private ContractEventContext eventContext;

@Override
public void issue(TransactionContentBody transactionContentBody, String assetHolderAddress) {
System.out.println(transactionContentBody.toString());
}

@Override
@ContractEvent(name = "issue-asset")
public void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody,
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress,
@DataContract(code = DataCodes.CONTRACT_INT64) long cashNumber) {
System.out.println(transactionContentBody.toString()+",address="+assetHolderAddress+",cashNumber="+cashNumber);
}

@Override
public void issue(Bytes bytes, String assetHolderAddress, long cashNumber) {

}

/*
* (non-Javadoc)
*
* @see
* com.jd.blockchain.contract.model.EventProcessingAwire#beforeEvent(com.jd.
* blockchain.contract.model.ContractEventContext)
*/
@Override
public void beforeEvent(ContractEventContext eventContext) {
this.eventContext = eventContext;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.contract.model.EventProcessingAwire#postEvent(com.jd.
* blockchain.contract.model.ContractEventContext,
* com.jd.blockchain.contract.model.ContractError)
*/
@Override
public void postEvent(ContractEventContext eventContext, ContractException error) {
this.eventContext = null;
}

@Override
public void postEvent(ContractException error) {

}

@Override
public void postEvent() {

}
}

+ 5
- 2
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java View File

@@ -68,7 +68,7 @@ public class SDK_Contract_Test {
public void demoContract1() {
// 发起交易;
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash);
String contractAddress = "LdeNvwqrHKCDtEVv5m3nQSpJ66ahds2E7FtnV";
String contractAddress = "LdeNmSdtUqVfURfcVxmJda252HC4FYHYfGTQv";
AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class);
TransactionContentBody transactionContentBody = new TransactionContentBody() {
@Override
@@ -83,7 +83,10 @@ public class SDK_Contract_Test {
};
// assetContract.issue(transactionContentBody,contractAddress);
// assetContract.issue(transactionContentBody,contractAddress,888888);
assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,999999);
// 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,contractAddress,321123);

// TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare();


Loading…
Cancel
Save