From b8dff42d04373b70e1e4aa6703c8af0d53ba87e8 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Tue, 28 May 2019 17:30:02 +0800 Subject: [PATCH] reduce the invoke of reflection to improve the performance. --- .../com/jd/blockchain/consts/DataCodes.java | 2 + .../jd/blockchain/binaryproto/DataType.java | 2 +- .../contract/jvm/JavaContractCode.java | 53 ++----- .../contract/ContractSerializeUtils.java | 132 ++++++------------ .../blockchain/ledger/ContractBizContent.java | 30 ++++ .../transaction/ContractInvocationProxy.java | 5 +- .../ContractInvocationProxyBuilder.java | 40 ------ .../blockchain/transaction/ContractType.java | 40 +++++- .../sdk/test/SDK_Contract_Test.java | 2 +- .../jd/blockchain/intgr/IntegrationBase.java | 23 ++- .../intgr/contract/AssetContract2.java | 53 +++++++ .../src/test/resources/contract.jar | Bin 5602 -> 7648 bytes 12 files changed, 188 insertions(+), 194 deletions(-) create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java create mode 100644 source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java diff --git a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java index 9d069903..a7382d0a 100644 --- a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java +++ b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java @@ -88,6 +88,8 @@ public interface DataCodes { 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 HASH = 0xB00; diff --git a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java index 9df9f7bd..1129518b 100644 --- a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java +++ b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java @@ -7,7 +7,7 @@ public interface DataType { */ public static final byte NIL = (byte) 0x00; - /** + /**LdeNhjPGzHcHL6rLcJ7whHxUbn9Tv7qSKRfEA * 布尔; */ public static final byte BOOLEAN = (byte) 0x01; diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java index 854e23b7..6bf5e859 100644 --- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java @@ -1,5 +1,6 @@ package com.jd.blockchain.contract.jvm; +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; @@ -12,6 +13,7 @@ import org.slf4j.LoggerFactory; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Method; +import java.util.List; /** * contract code based jvm @@ -25,7 +27,7 @@ public class JavaContractCode implements ContractCode { private long version; private ContractEventContext contractEventContext; - private ContractType contractType ; + private ContractType contractType; public JavaContractCode(Bytes address, long version, Module codeModule) { this.address = address; @@ -49,8 +51,11 @@ public class JavaContractCode implements ContractCode { codeModule.execute(new ContractExecution()); } - private Object resolveArgs(byte[] args, Method method) { - return ContractSerializeUtils.deserializeMethodParam(args,method); + private Object resolveArgs(byte[] args, List dataContractList) { + if(args == null || args.length == 0){ + return null; + } + return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); } class ContractExecution implements Runnable { @@ -73,11 +78,13 @@ public class JavaContractCode implements ContractCode { startTime = System.currentTimeMillis(); // 反序列化参数; - Method handleMethod = ContractType.resolve(myClass).getHandleMethod(contractEventContext.getEvent()); + contractType = ContractType.resolve(myClass); + Method handleMethod = contractType.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 args = resolveArgs(contractEventContext.getArgs(), + contractType.getDataContractMap().get(handleMethod)); Object[] params = null; if(args.getClass().isArray()){ @@ -97,42 +104,6 @@ public class JavaContractCode implements ContractCode { throw new IllegalDataException(e.getMessage()); } } - - // 得到当前类中相关方法和注解对应关系; -// Method getMethodByAnno(Object classObj, String eventName) { -// Class c = classObj.getClass(); -// Class contractEventClass = null; -// try { -// contractEventClass = (Class) c.getClassLoader().loadClass(ContractEvent.class.getName()); -// } catch (ClassNotFoundException e) { -// e.printStackTrace(); -// } -// Method[] classMethods = c.getMethods(); -// Map methodAnnoMap = new HashMap(); -// Map annoMethodMap = new HashMap(); -// for (int i = 0; i < classMethods.length; i++) { -// Annotation[] a = classMethods[i].getDeclaredAnnotations(); -// methodAnnoMap.put(classMethods[i], a); -// // 如果当前方法中包含@ContractEvent注解,则将其放入Map; -// for (Annotation annotation_ : a) { -// // 如果是合同事件类型,则放入map; -// if (classMethods[i].isAnnotationPresent(contractEventClass)) { -// Object obj = classMethods[i].getAnnotation(contractEventClass); -// String annoAllName = obj.toString(); -// // format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset) -// String eventName_ = obj.toString().substring(BaseConstant.CONTRACT_EVENT_PREFIX.length(), -// annoAllName.length() - 1); -// annoMethodMap.put(eventName_, classMethods[i]); -// break; -// } -// } -// } -// if (annoMethodMap.containsKey(eventName)) { -// return annoMethodMap.get(eventName); -// } else { -// return null; -// } -// } } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java index 474a1838..9d5d3d77 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java @@ -6,13 +6,11 @@ import com.jd.blockchain.consts.DataCodes; import com.jd.blockchain.ledger.*; import com.jd.blockchain.utils.Bytes; import org.springframework.util.ReflectionUtils; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; import java.math.BigDecimal; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -24,57 +22,20 @@ public class ContractSerializeUtils { 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 - * @param method + * serialize the Object[] by List list; + * @param objArr + * @param dataContractList * @return */ - public static byte[] serializeMethodParam(Object object,Method method) { - if (object == null) { - return null; - } - - Object[] objArr = null; - if(object.getClass().isArray()){ - objArr = (Object[]) object; - } - - Class[] classTypes = method.getParameterTypes(); - byte[][] result = new byte[classTypes.length][]; + public static byte[] serializeMethodParam(Object[] objArr,List dataContractList) { + byte[][] result = new byte[objArr.length][]; //将method中形参转换为实体对象,每个形参都必须为@DataContract类型;每个形参使用系统的BinaryProtocol来进行序列化,如果有5个参数,则使用5次序列化; int sum = 0; - for(int i=0;i classType = classTypes[i]; - DataContract dataContract = classType.getDeclaredAnnotation(DataContract.class); - //if the param's class Type don't contain @DataContract, then check parameterAnnotations of this method. - 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; -// } -// } - //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(!canPass){ - throw new IllegalArgumentException("must set @DataContract for each param of contract."); - } - } - if(!getDataIntf().containsKey(dataContract.code())){ - throw new IllegalArgumentException(String.format( - "for now, this @dataContract(code=%s) is forbidden in the param list.",dataContract.code())); - } + + for(int i=0;i[] classTypes = method.getParameterTypes(); - Object result[] = new Object[classTypes.length]; - + public static Object[] deserializeMethodParam(byte[] params, List dataContractList) { + Object result[] = new Object[dataContractList.size()]; ByteBuffer byteBuffer = ByteBuffer.allocate(params.length); byteBuffer.put(params); int paramNums = byteBuffer.getInt(0); - if(paramNums != classTypes.length){ + if(paramNums != dataContractList.size()){ throw new IllegalArgumentException("deserialize Method param. params'length in byte[] != method's param length"); } - Annotation [][] annotations = method.getParameterAnnotations(); - int offsetPosition = (1 + classTypes.length)*4; //start position of real data; - for(int i=0; i classType = classTypes[i]; + int offsetPosition = (1 + dataContractList.size())*4; //start position of real data; + for(int i=0; i 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."); - } - } ByteBuffer byteBuffer1 = ByteBuffer.allocate(curParamLength); byteBuffer1.put(params,offsetPosition,curParamLength); offsetPosition += curParamLength; - - if(!getDataIntf().containsKey(dataContract.code())){ - throw new IllegalArgumentException(String.format( - "for now, this @dataContract(code=%s) is forbidden in the param list.",dataContract.code())); - } //if dataContract=primitive type(byte/short/int/long/String),only use its getValues(); Object object = BinaryProtocol.decodeAs(byteBuffer1.array(), getDataIntf().get(dataContract.code())); @@ -239,4 +167,26 @@ public class ContractSerializeUtils { } return null; } + + public static DataContract parseDataContract(Class classType){ + DataContract dataContract = classType.getDeclaredAnnotation(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.getDeclaredAnnotation(DataContract.class); + if(dataContract != null){ + canPass = true; + } + if(!canPass){ + throw new IllegalArgumentException("must set @DataContract for each param of contract."); + } + } + 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; + } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java new file mode 100644 index 00000000..e9cabf75 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java @@ -0,0 +1,30 @@ +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.crypto.HashDigest; + +/** + * build complex param Object; + */ +@DataContract(code = DataCodes.CONTRACT_BIZ_CONTENT) +public interface ContractBizContent { + + /** + * 执行交易的账本地址; + * 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + HashDigest getLedgerHash(); + + /** + * 操作列表; + * @return + */ + @DataField(order = 2, list = true, refContract = true, genericContract = true) + Operation[] getOperations(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java index a5a3fd09..acabd5b4 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java @@ -47,6 +47,9 @@ public class ContractInvocationProxy implements InvocationHandler { private byte[] serializeArgs(Object[] args, Method method) { // TODO 根据方法参数的定义序列化参数; - return ContractSerializeUtils.serializeMethodParam(args,method); + if(args == null || args.length==0){ + return null; + } + return ContractSerializeUtils.serializeMethodParam(args,contractType.getDataContractMap().get(method)); } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java index 4bf825b7..06c6b386 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java @@ -38,19 +38,6 @@ public class ContractInvocationProxyBuilder { if (contractType != null) { return contractType; } - - // 判断是否是标注了合约的接口类型; - if (!isContractType(contractIntf)){ - throw new IllegalDataException("is not Contract Type, becaust there is not @Contract."); - } - - // 解析合约事件处理方法,检查是否有重名; - if(!isUniqueEvent(contractIntf)){ - throw new IllegalDataException("there is repeat definition of contractEvent to @ContractEvent."); - } - - // TODO 检查是否不支持的参数类型; - // TODO 检查返回值类型; ContractType contractType1 = ContractType.resolve(contractIntf); @@ -59,33 +46,6 @@ public class ContractInvocationProxyBuilder { } - private boolean isUniqueEvent(Class contractIntf) { - boolean isUnique = true; - Method[] classMethods = contractIntf.getMethods(); - Map methodAnnoMap = new HashMap(); - Map annoMethodMap = new HashMap(); - for (int i = 0; i < classMethods.length; i++) { - Annotation[] annotations = classMethods[i].getDeclaredAnnotations(); - methodAnnoMap.put(classMethods[i], annotations); - // if current method contains @ContractEvent,then put it in this map; - Method curMethod = classMethods[i]; - ContractEvent contractEvent = curMethod.getAnnotation(ContractEvent.class); - if (contractEvent != null) { - Object obj = classMethods[i].getAnnotation(ContractEvent.class); - String annoAllName = obj.toString(); - // format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset) - String eventName_ = contractEvent.name(); - //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! - if(annoMethodMap.containsKey(eventName_)){ - isUnique = false; - } - annoMethodMap.put(eventName_, classMethods[i]); - } - } - - return isUnique; - } - /** * is contractType really? identified by @Contract; * @param contractIntf diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java index 97424e48..8110fc33 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java @@ -1,20 +1,22 @@ package com.jd.blockchain.transaction; +import com.jd.blockchain.binaryproto.DataContract; +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.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; public class ContractType { private String name; - private Map events = new HashMap<>(); - - private Map handleMethods = new HashMap<>();; + private Map handleMethods = new HashMap<>(); + private Map> dataContractMap = new HashMap<>(); /** * 返回声明的所有事件; @@ -25,6 +27,10 @@ public class ContractType { return events.keySet(); } + public Map> getDataContractMap() { + return dataContractMap; + } + /** * 返回指定方法声明的事件;
* @@ -54,6 +60,15 @@ public class ContractType { public static ContractType resolve(Class contractIntf){ ContractType contractType = new ContractType(); + + Annotation annotation = contractIntf.getDeclaredAnnotation(Contract.class); + + //contains: @Contract? + boolean isContractType = annotation != null ? true : false; + if(!isContractType){ + throw new IllegalDataException("is not Contract Type, becaust there is not @Contract."); + } + //contractIntf contains @Contract and @ContractEvent; Method[] classMethods = contractIntf.getDeclaredMethods(); for (Method method : classMethods) { @@ -63,8 +78,19 @@ public class ContractType { String eventName_ = contractEvent.name(); //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! if(contractType.events.containsKey(eventName_)){ - throw new ContractException("too many same eventNames exists in the contract, check it."); + throw new ContractException("there is repeat definition of contractEvent to @ContractEvent."); + } + //check param's type is fit for need. + 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); + } + contractType.events.put(eventName_, method); contractType.handleMethods.put(method,eventName_); } diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java index b2aa577d..000e7879 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java @@ -68,7 +68,7 @@ public class SDK_Contract_Test { public void demoContract1() { // 发起交易; TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); - String contractAddress = "LdeNw7PsVrXTrffQMfYLTvqscDyQ8QCUPruTS"; + String contractAddress = "LdeNhjPGzHcHL6rLcJ7whHxUbn9Tv7qSKRfEA"; AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); TransactionContentBody transactionContentBody = new TransactionContentBody() { @Override diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java index e3bf4f16..7bbfa791 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java @@ -29,6 +29,7 @@ import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.springframework.core.io.ClassPathResource; import test.com.jd.blockchain.intgr.contract.AssetContract; +import test.com.jd.blockchain.intgr.contract.AssetContract2; import java.io.File; import java.io.FileInputStream; @@ -431,17 +432,13 @@ public class IntegrationBase { } // 合约测试使用的初始化数据; - BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); - BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); + static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); + static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); // 保存资产总数的键; - private static final String KEY_TOTAL = "TOTAL"; // 第二个参数; - private static final String KEY_ABC = "abc"; - private String contractZipName = "Example1.jar"; - HashDigest txContentHash; - String pubKeyVal = "jd.com"+System.currentTimeMillis(); - private String eventName = "issue-asset"; - public LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, + private static String contractZipName = "contract.jar"; + static HashDigest txContentHash; + public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService,LedgerRepository ledgerRepository) { System.out.println("adminKey="+ AddressEncoding.generateAddress(adminKey.getPubKey())); BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); @@ -476,7 +473,7 @@ public class IntegrationBase { return block; } - private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, + private static void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, BlockchainService blockchainService,LedgerRepository ledgerRepository,Class contractIntf) { LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); @@ -484,7 +481,9 @@ public class IntegrationBase { // 定义交易; TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); - txTpl.contract(contractDeployKey.getAddress(),AssetContract.class).issue(10,"abc"); + Byte byteObj = Byte.parseByte("127"); + txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, + contractDeployKey.getAddress().toBase58(),321123); // 签名; PreparedTransaction ptx = txTpl.prepare(); @@ -503,7 +502,7 @@ public class IntegrationBase { * * @return */ - private byte[] getChainCodeBytes() { + private static byte[] getChainCodeBytes() { // 构建合约的字节数组; byte[] contractCode = null; File file = null; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java new file mode 100644 index 00000000..c554ba46 --- /dev/null +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java @@ -0,0 +1,53 @@ +package test.com.jd.blockchain.intgr.contract; + +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.TransactionContentBody; +import com.jd.blockchain.utils.Bytes; + +/** + * 示例:一个“资产管理”智能合约; + * + * @author zhaogw + */ +@Contract +public interface AssetContract2 { + + /** + * 发行资产; + * 新发行的资产数量; + * @param assetHolderAddress + * 新发行的资产的持有账户; + */ + @ContractEvent(name = "issue-asset-0") + void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody, + @DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress); + + /** + * issue asset; + * @param transactionContentBody + * @param assetHolderAddress + * @param cashNumber + */ + @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); + + /** + * 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 issue1(byte[] bytes, String assetHolderAddress, long cashNumber); +} \ No newline at end of file diff --git a/source/test/test-integration/src/test/resources/contract.jar b/source/test/test-integration/src/test/resources/contract.jar index 8cdfebfb565f56ed425cf48ad3c280955ab8d660..a0e2ab0a648d77a0854abbe790d5d0f36ab46cb9 100644 GIT binary patch delta 4619 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 delta 2734 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 N$qfM5{*g5R;6GFI7a9Nn