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 2a09cd1b..da3297bf 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 @@ -7,7 +7,7 @@ import com.jd.blockchain.ledger.*; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.IllegalDataException; import org.springframework.util.ReflectionUtils; -import java.math.BigDecimal; + import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; @@ -110,6 +110,11 @@ public class ContractSerializeUtils { } + /** + * the param types that we can support; + * @param + * @return + */ public static Map > getDataIntf(){ DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT8, CONTRACT_INT8.class); DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT16, CONTRACT_INT16.class); @@ -128,6 +133,7 @@ public class ContractSerializeUtils { 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()); @@ -139,8 +145,6 @@ public class ContractSerializeUtils { 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(CONTRACT_BIG_INT.class)){ - return (CONTRACT_BIG_INT) () -> new BigDecimal(object.toString()); }else if(getDataIntf().get(dataContract.code()).equals(ContractBizContent.class)){ ContractBizContent contractBizContent = (ContractBizContent)object; return contractBizContent; @@ -169,26 +173,19 @@ public class ContractSerializeUtils { return CONTRACT_TEXT.class; }else if(classType.equals(Bytes.class)){ return CONTRACT_BINARY.class; - }else if(classType.equals(BigDecimal.class)){ - return CONTRACT_BIG_INT.class; + }else { + throw new IllegalDataException(String.format("no support the classType=%s, please check @DataContract.",classType.toString())); } - return null; } public static DataContract parseDataContract(Class classType){ - DataContract dataContract = classType.getDeclaredAnnotation(DataContract.class); + 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.getDeclaredAnnotation(DataContract.class); - if(dataContract != null){ - canPass = true; - } - if(!canPass){ - throw new IllegalArgumentException("must set @DataContract for each param of contract."); - } + dataContract = contractType.getAnnotation(DataContract.class); } if(!getDataIntf().containsKey(dataContract.code())){ throw new IllegalArgumentException(String.format( 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 index ab2ff4c3..56e6bc24 100644 --- 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 @@ -4,34 +4,17 @@ 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; + * build complex param Object, provide more String attributes; */ @DataContract(code = DataCodes.CONTRACT_BIZ_CONTENT) public interface ContractBizContent { - - /** - * 执行交易的账本地址; - * 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null; - * - * @return - */ - @DataField(order = 1, primitiveType = PrimitiveType.BYTES) - HashDigest getLedgerHash(); - /** - * 地址; + * param lists; * @return */ - @DataField(order = 2, primitiveType = PrimitiveType.TEXT) - String getAddr(); + @DataField(order = 1, list = true, primitiveType = PrimitiveType.TEXT, genericContract = true) + String[] getAttrs(); - /** - * 年龄; - * @return - */ - @DataField(order = 3, primitiveType = PrimitiveType.INT32) - int getAge(); } 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 acabd5b4..f5f83708 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 @@ -46,7 +46,6 @@ public class ContractInvocationProxy implements InvocationHandler { } private byte[] serializeArgs(Object[] args, Method method) { - // TODO 根据方法参数的定义序列化参数; if(args == null || args.length==0){ return null; } 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 12954711..76bdceed 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 @@ -1,12 +1,11 @@ package test.com.jd.blockchain.sdk.test; +import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.contract.samples.AssetContract; import com.jd.blockchain.contract.samples.AssetContract2; import com.jd.blockchain.crypto.*; -import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.ledger.*; import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.BlockchainServiceFactory; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.sdk.samples.SDKDemo_Contract; import com.jd.blockchain.utils.Bytes; @@ -23,7 +22,6 @@ import org.springframework.core.io.ClassPathResource; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.math.BigDecimal; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -66,36 +64,20 @@ public class SDK_Contract_Test { /** * 演示合约执行的过程; */ -// @Test + @Test public void demoContract1() { String dataAddress = registerData4Contract(); // 发起交易; TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); String contractAddress = "LdeNg8JHFCKABJt6AaRNVCZPgY4ofGPd8MgcR"; AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); - ContractBizContent contractBizContent = new ContractBizContent() { - @Override - public HashDigest getLedgerHash() { - return new HashDigest(ClassicAlgorithm.SHA256, "zhaogw".getBytes()); - } - - @Override - public String getAddr() { - return "jinghailu street."; - } - - @Override - public int getAge() { - return 100; - } - }; // 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(contractBizContent,dataAddress); assetContract.issue(Byte.parseByte("126"),dataAddress,Bytes.fromString("100.234")); // TX 准备就绪; @@ -109,6 +91,34 @@ public class SDK_Contract_Test { assertEquals("100",dataEntries[0].getValue().toString()); } + /** + * 演示合约执行的过程; + */ + @Test + public void demoContract2() throws IOException { + String contractAddress = deploy(); + String dataAddress = registerData4Contract(); + System.out.println("dataAddress="+dataAddress); + // 发起交易; + TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); + + AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); + ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; + assetContract.issue(contractBizContent,dataAddress,123456); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + prepTx.sign(signKeyPair); + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + + //check; + assertTrue(transactionResponse.isSuccess()); + KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,contractBizContent.getAttrs()[0],contractBizContent.getAttrs()[1]); + assertEquals("value1",dataEntries[0].getValue().toString()); + assertEquals(888,dataEntries[1].getValue()); + } + @Test public void registerData(){ // 在本地定义 TX 模板 @@ -146,6 +156,8 @@ public class SDK_Contract_Test { BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); txTemp.dataAccounts().register(dataAccount.getIdentity()); txTemp.dataAccount(dataAccount.getAddress()).set("total", 200, -1); + txTemp.dataAccount(dataAccount.getAddress()).set("param1", "v", -1); + txTemp.dataAccount(dataAccount.getAddress()).set("param2", 123, -1); // TX 准备就绪; PreparedTransaction prepTx = txTemp.prepare(); prepTx.sign(signKeyPair); @@ -173,8 +185,7 @@ public class SDK_Contract_Test { assertTrue(transactionResponse.isSuccess()); } - @Test - public void deploy() throws IOException { + private String deploy() throws IOException { ClassPathResource classPathResource = new ClassPathResource("contract.jar"); byte[] chainCode = this.getChainCode(classPathResource.getURL().getPath()); TransactionTemplate txTpl = this.bcsrv.newTransaction(ledgerHash); @@ -186,6 +197,7 @@ public class SDK_Contract_Test { System.out.println("contract's address=" + contractIdentity.getAddress()); String contractAddr = contractIdentity.getAddress().toBase58(); log.info("contractAddr="+contractAddr); + return contractAddr; } public byte[] getChainCode(String path) { @@ -333,4 +345,17 @@ public class SDK_Contract_Test { } + @Test + public void testStringArr(){ + String[] strArr = {"1","2","you are welcome!"}; + ContractBizContent contractBizContent = new ContractBizContent() { + @Override + public String[] getAttrs() { + return strArr; + } + }; + byte[] bizBytes = BinaryProtocol.encode(contractBizContent,ContractBizContent.class); + ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class); + assertEquals(contractBizContent,actualObj); + } } diff --git a/source/sdk/sdk-samples/src/test/resources/contract.jar b/source/sdk/sdk-samples/src/test/resources/contract.jar index 3f21f9b3..3ff8a821 100644 Binary files a/source/sdk/sdk-samples/src/test/resources/contract.jar and b/source/sdk/sdk-samples/src/test/resources/contract.jar differ