Browse Source

reduce the invoke of reflection to improve the performance.

tags/1.0.0
zhaoguangwei 6 years ago
parent
commit
b8dff42d04
12 changed files with 188 additions and 194 deletions
  1. +2
    -0
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  2. +1
    -1
      source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java
  3. +12
    -41
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  4. +41
    -91
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java
  5. +30
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java
  6. +4
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java
  7. +0
    -40
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java
  8. +33
    -7
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java
  9. +1
    -1
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java
  10. +11
    -12
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
  11. +53
    -0
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java
  12. BIN
      source/test/test-integration/src/test/resources/contract.jar

+ 2
- 0
source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java View File

@@ -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;



+ 1
- 1
source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/DataType.java View File

@@ -7,7 +7,7 @@ public interface DataType {
*/
public static final byte NIL = (byte) 0x00;

/**
/**LdeNhjPGzHcHL6rLcJ7whHxUbn9Tv7qSKRfEA
* 布尔;
*/
public static final byte BOOLEAN = (byte) 0x01;


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

@@ -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<DataContract> 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<ContractEvent> contractEventClass = null;
// try {
// contractEventClass = (Class<ContractEvent>) c.getClassLoader().loadClass(ContractEvent.class.getName());
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
// Method[] classMethods = c.getMethods();
// Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>();
// Map<String, Method> annoMethodMap = new HashMap<String, Method>();
// 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;
// }
// }
}

}

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

@@ -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<DataContract> 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<DataContract> dataContractList) {
byte[][] result = new byte[objArr.length][];
//将method中形参转换为实体对象,每个形参都必须为@DataContract类型;每个形参使用系统的BinaryProtocol来进行序列化,如果有5个参数,则使用5次序列化;
int sum = 0;
for(int i=0;i<classTypes.length;i++){
Class <?> 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<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;
@@ -91,9 +52,9 @@ public class ContractSerializeUtils {
rtnBytes[...]: result[1][] bytes(2 param's length);
rtnBytes[...]: result[2][] bytes(3 param's length);
*/
int bodyFirstPosition = 4 + 4 * (classTypes.length);
int bodyFirstPosition = 4 + 4 * (objArr.length);
ByteBuffer byteBuffer = ByteBuffer.allocate(bodyFirstPosition + sum);
byteBuffer.putInt(classTypes.length);
byteBuffer.putInt(objArr.length);
for(int j=0; j<result.length; j++) {
byte[] curResult = result[j];
byteBuffer.putInt(curResult.length);
@@ -108,59 +69,26 @@ public class ContractSerializeUtils {
* deserialize the params bytes[];
* params format: nums|first length| second length| third length| ... |bytes[0]| byte[1] | bytes[2]| ...
* @param params
* @param method
* @param dataContractList
* @return
*/
public static Object[] deserializeMethodParam(byte[] params, Method method) {
if (params == null) {
return null;
}

Class<?>[] classTypes = method.getParameterTypes();
Object result[] = new Object[classTypes.length];

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 != 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<classTypes.length; i++){
Class<?> classType = classTypes[i];
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);
DataContract dataContract = classType.getDeclaredAnnotation(DataContract.class);
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;
// }
// }
//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.");
}
}
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;
}
}

+ 30
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractBizContent.java View File

@@ -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();
}

+ 4
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java View File

@@ -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));
}
}

+ 0
- 40
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java View File

@@ -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<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>();
Map<String, Method> annoMethodMap = new HashMap<String, Method>();
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


+ 33
- 7
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java View File

@@ -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<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<>();

/**
* 返回声明的所有事件;
@@ -25,6 +27,10 @@ public class ContractType {
return events.keySet();
}

public Map<Method, List<DataContract>> getDataContractMap() {
return dataContractMap;
}

/**
* 返回指定方法声明的事件;<br>
*
@@ -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_);
}


+ 1
- 1
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 = "LdeNw7PsVrXTrffQMfYLTvqscDyQ8QCUPruTS";
String contractAddress = "LdeNhjPGzHcHL6rLcJ7whHxUbn9Tv7qSKRfEA";
AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class);
TransactionContentBody transactionContentBody = new TransactionContentBody() {
@Override


+ 11
- 12
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java View File

@@ -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 <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
BlockchainService blockchainService,LedgerRepository ledgerRepository,Class<T> 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;


+ 53
- 0
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/contract/AssetContract2.java View File

@@ -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);
}

BIN
source/test/test-integration/src/test/resources/contract.jar View File


Loading…
Cancel
Save