From 94b5f8d300b5b0f9dce9a8b830cc3b957359c5e5 Mon Sep 17 00:00:00 2001 From: dongjianhui Date: Thu, 13 Jun 2019 22:17:43 +0800 Subject: [PATCH] feat(*): add contract maintain service --- .../sdk/service/ContractService.java | 3 + .../sdk/service/impl/ContractServiceImpl.java | 18 ++++- .../sdk/transaction/Transaction.java | 80 +++++++++++++++---- src/test/java/cn/hyperchain/sdk/EVMTest.java | 23 ++++++ src/test/java/cn/hyperchain/sdk/HVMTest.java | 28 ++++++- 5 files changed, 134 insertions(+), 18 deletions(-) diff --git a/src/main/java/cn/hyperchain/sdk/service/ContractService.java b/src/main/java/cn/hyperchain/sdk/service/ContractService.java index d53ea633..13caecb8 100644 --- a/src/main/java/cn/hyperchain/sdk/service/ContractService.java +++ b/src/main/java/cn/hyperchain/sdk/service/ContractService.java @@ -17,4 +17,7 @@ public interface ContractService { Request invoke(Transaction transaction, int... nodeIds); Request getReceipt(String txHash, int... nodeIds); + + Request maintain(Transaction transaction, int... nodeIds); + } diff --git a/src/main/java/cn/hyperchain/sdk/service/impl/ContractServiceImpl.java b/src/main/java/cn/hyperchain/sdk/service/impl/ContractServiceImpl.java index ce76f7ee..9968731b 100644 --- a/src/main/java/cn/hyperchain/sdk/service/impl/ContractServiceImpl.java +++ b/src/main/java/cn/hyperchain/sdk/service/impl/ContractServiceImpl.java @@ -77,11 +77,27 @@ public Request getReceipt(String txHash, int... nodeIds) { receiptResponsePollingRequest.addParams(txHash); receiptResponsePollingRequest.setJsonrpc(jsonrpc); - receiptResponsePollingRequest.setJsonrpc(namespace); + receiptResponsePollingRequest.setNamespace(namespace); return receiptResponsePollingRequest; } + @Override + public Request maintain(Transaction transaction, int... nodeIds) { + ContractRequest txHashResponseContractRequest = new ContractRequest(CONTRACT_PREFIX + "maintainContract", providerManager, TxHashResponse.class, transaction, nodeIds); + + Map params = commonParamMap(transaction); + params.put("to", transaction.getTo()); + params.put("opcode", transaction.getOpCode()); + + txHashResponseContractRequest.addParams(params); + txHashResponseContractRequest.setJsonrpc(jsonrpc); + txHashResponseContractRequest.setNamespace(namespace); + txHashResponseContractRequest.setContractService(this); + + return txHashResponseContractRequest; + } + private Map commonParamMap(Transaction transaction) { HashMap map = new HashMap(); map.put("from", transaction.getFrom()); diff --git a/src/main/java/cn/hyperchain/sdk/transaction/Transaction.java b/src/main/java/cn/hyperchain/sdk/transaction/Transaction.java index ff189358..c0fdc369 100644 --- a/src/main/java/cn/hyperchain/sdk/transaction/Transaction.java +++ b/src/main/java/cn/hyperchain/sdk/transaction/Transaction.java @@ -12,7 +12,8 @@ import java.util.Date; public class Transaction { - private Transaction() {} + private Transaction() { + } private static final Logger logger = Logger.getLogger(Transaction.class); @@ -34,6 +35,7 @@ public static class Builder { /** * create transfer or generate transaction. + * * @param from account address */ public Builder(String from) { @@ -44,7 +46,8 @@ public Builder(String from) { /** * create a transform transaction from account A to account B. - * @param to origin account + * + * @param to origin account * @param value goal account * @return {@link Builder} */ @@ -56,6 +59,7 @@ public Builder transfer(String to, long value) { /** * make transaction status is simulate. + * * @return {@link Builder} */ public Builder simulate() { @@ -65,6 +69,7 @@ public Builder simulate() { /** * add transaction extra info. + * * @param extra extra data * @return {@link Builder} */ @@ -73,8 +78,46 @@ public Builder extra(String extra) { return this; } + /** + * upgrade contract. + * + * @param contractAddress contract address in chain + * @param payload payload of the new contract + * @return {@link Builder} + */ + public Builder upgrade(String contractAddress, String payload) { + transaction.setPayload(payload); + transaction.setTo(contractAddress); + transaction.setOpCode(1); + return this; + } + + /** + * freeze contract. + * + * @param contractAddress contract address in chain + * @return {@link Builder} + */ + public Builder freeze(String contractAddress) { + transaction.setOpCode(2); + transaction.setTo(contractAddress); + return this; + } + + /** + * unfreeze contract. + * @param contractAddress contract address in chain + * @return {@link Builder} + */ + public Builder unfreeze(String contractAddress) { + transaction.setTo(contractAddress); + transaction.setOpCode(3); + return this; + } + /** * build transaction instance. + * * @return {@link Transaction} */ public Transaction build() { @@ -93,6 +136,7 @@ public HVMBuilder(String from) { /** * create deployment transaction for {@link VMType} HVM. + * * @param fis FileInputStream for the given jar file * @return {@link Builder} */ @@ -105,8 +149,9 @@ public Builder deploy(InputStream fis) { /** * create invoking transaction for {@link VMType} HVM. + * * @param contractAddress contract address in chain - * @param baseInvoke an instance of {@link BaseInvoke} + * @param baseInvoke an instance of {@link BaseInvoke} * @return {@link Builder} */ public Builder invoke(String contractAddress, BaseInvoke baseInvoke) { @@ -115,6 +160,8 @@ public Builder invoke(String contractAddress, BaseInvoke baseInvoke) { super.transaction.setPayload(payload); return this; } + + } public static class EVMBuilder extends Builder { @@ -125,6 +172,7 @@ public EVMBuilder(String from) { /** * deploy Solidity contract bin. + * * @param bin contract bin * @return {@link Builder} */ @@ -136,8 +184,9 @@ public Builder deploy(String bin) { /** * deploy Solidity contract bin with params. - * @param bin contract bin - * @param abi contract abi + * + * @param bin contract bin + * @param abi contract abi * @param params deploy contract params * @return {@link Builder} */ @@ -150,9 +199,10 @@ public Builder deploy(String bin, Abi abi, Object... params) { /** * invoke Solidity contract whit specific method and params. + * * @param methodName method name - * @param abi contract abi - * @param params invoke params + * @param abi contract abi + * @param params invoke params * @return {@link Builder} */ public Builder invoke(String contractAddress, String methodName, Abi abi, Object... params) { @@ -161,18 +211,20 @@ public Builder invoke(String contractAddress, String methodName, Abi abi, Object super.transaction.setPayload(payload); return this; } + + } private void setNeedHashString() { String value = Utils.isBlank(this.payload) ? String.valueOf(this.value) : this.payload; this.needHashString = "from=" + chPrefix(this.from.toLowerCase()) - + "&to=" + chPrefix(this.to.toLowerCase()) - + "&value=" + chPrefix(value).toLowerCase() - + "×tamp=0x" + Long.toHexString(this.timestamp) - + "&nonce=0x" + Long.toHexString(this.nonce) - + "&opcode=" + this.opCode - + "&extra=" + this.extra - + "&vmtype=" + this.vmType.getType(); + + "&to=" + chPrefix(this.to.toLowerCase()) + + "&value=" + chPrefix(value).toLowerCase() + + "×tamp=0x" + Long.toHexString(this.timestamp) + + "&nonce=0x" + Long.toHexString(this.nonce) + + "&opcode=" + this.opCode + + "&extra=" + this.extra + + "&vmtype=" + this.vmType.getType(); } public void sign(Account account) { diff --git a/src/test/java/cn/hyperchain/sdk/EVMTest.java b/src/test/java/cn/hyperchain/sdk/EVMTest.java index 68cc9fef..0f2eca4d 100644 --- a/src/test/java/cn/hyperchain/sdk/EVMTest.java +++ b/src/test/java/cn/hyperchain/sdk/EVMTest.java @@ -42,6 +42,7 @@ public void testEVM() throws Exception { String bin = FileUtil.readFile(inputStream1); String abiStr = FileUtil.readFile(inputStream2); Abi abi = Abi.fromJson(abiStr); + Transaction transaction = new Transaction.EVMBuilder(account.getAddress()).deploy(bin, abi, "contract01").build(); transaction.sign(account); ReceiptResponse receiptResponse = contractService.deploy(transaction).send().polling(); @@ -68,5 +69,27 @@ public void testEVM() throws Exception { System.out.println(o.getClass()); System.out.println(new String((byte[]) o)); } + + System.out.println("*********************************************************************"); + // maintain contract test + + // test freeze + Transaction transaction2 = new Transaction.EVMBuilder(account.getAddress()).upgrade(contractAddress, bin).build(); + transaction2.sign(account); + ReceiptResponse receiptResponse2 = contractService.maintain(transaction2).send().polling(); + System.out.println(receiptResponse2.getRet()); + + // test thaw + Transaction transaction3 = new Transaction.EVMBuilder(account.getAddress()).freeze(contractAddress).build(); + transaction3.sign(account); + ReceiptResponse receiptResponse3 = contractService.maintain(transaction3).send().polling(); + System.out.println(receiptResponse3.getRet()); + + // test upgrade + Transaction transaction4 = new Transaction.EVMBuilder(account.getAddress()).unfreeze(contractAddress).build(); + transaction4.sign(account); + ReceiptResponse receiptResponse4 = contractService.maintain(transaction4).send().polling(); + System.out.println(receiptResponse4.getRet()); + } } diff --git a/src/test/java/cn/hyperchain/sdk/HVMTest.java b/src/test/java/cn/hyperchain/sdk/HVMTest.java index 309e6661..433f5a46 100644 --- a/src/test/java/cn/hyperchain/sdk/HVMTest.java +++ b/src/test/java/cn/hyperchain/sdk/HVMTest.java @@ -10,7 +10,9 @@ import cn.hyperchain.sdk.hvm.StudentInvoke; import cn.hyperchain.sdk.provider.DefaultHttpProvider; import cn.hyperchain.sdk.provider.ProviderManager; +import cn.hyperchain.sdk.request.Request; import cn.hyperchain.sdk.response.ReceiptResponse; +import cn.hyperchain.sdk.response.TxHashResponse; import cn.hyperchain.sdk.service.AccountService; import cn.hyperchain.sdk.service.ContractService; import cn.hyperchain.sdk.service.ServiceManager; @@ -38,6 +40,7 @@ public void testHVM() throws RequestException, IOException { AccountService accountService = ServiceManager.getAccountService(providerManager); // 3. build transaction Account account = accountService.genAccount(Algo.SMRAW); + Account backup = account; InputStream payload = FileUtil.readFileAsStream("hvm-jar/hvmbasic-1.0.0-student.jar"); Transaction transaction = new Transaction.HVMBuilder(account.getAddress()).deploy(payload).build(); transaction.sign(accountService.fromAccountJson(account.toJson())); @@ -46,19 +49,38 @@ public void testHVM() throws RequestException, IOException { // 4. get request ReceiptResponse receiptResponse = contractService.deploy(transaction).send().polling(); // 5. polling && get result && decode result - System.out.println("合约地址: " + receiptResponse.getContractAddress()); + String contractAddress = receiptResponse.getContractAddress(); + System.out.println("合约地址: " + contractAddress); System.out.println("部署返回(未解码): " + receiptResponse.getRet()); System.out.println("部署返回(解码):" + Decoder.decodeHVM(receiptResponse.getRet(), String.class)); // 6. invoke account = accountService.genAccount(Algo.ECRAW); - Transaction transaction1 = new Transaction.HVMBuilder(account.getAddress()).invoke(receiptResponse.getContractAddress(), new StudentInvoke()).build(); + Transaction transaction1 = new Transaction.HVMBuilder(account.getAddress()).invoke(contractAddress, new StudentInvoke()).build(); transaction1.sign(accountService.fromAccountJson(account.toJson())); Assert.assertTrue(account.verify(transaction1.getNeedHashString().getBytes(), ByteUtil.fromHex(transaction1.getSignature()))); Assert.assertTrue(SignerUtil.verifySign(transaction1.getNeedHashString(), transaction1.getSignature(), account.getPublicKey())); // 7. request - ReceiptResponse receiptResponse1 = contractService.invoke(transaction1).send().polling(); + TxHashResponse txHashResponse = contractService.invoke(transaction1).send(); + ReceiptResponse receiptResponse1 = txHashResponse.polling(); // 8. get result & decode result System.out.println("调用返回(未解码): " + receiptResponse1.getRet()); System.out.println("调用返回(解码):" + Decoder.decodeHVM(receiptResponse1.getRet(), String.class)); + + Transaction transaction2 = new Transaction.HVMBuilder(backup.getAddress()).freeze(contractAddress).build(); + transaction2.sign(backup); + Assert.assertTrue(backup.verify(transaction2.getNeedHashString().getBytes(), ByteUtil.fromHex(transaction2.getSignature()))); + Assert.assertTrue(SignerUtil.verifySign(transaction2.getNeedHashString(), transaction2.getSignature(), backup.getPublicKey())); + TxHashResponse response = contractService.maintain(transaction2).send(); + ReceiptResponse receiptResponse2 = response.polling(); + System.out.println("调用返回(未解码): " + receiptResponse2.getRet()); + System.out.println("调用返回(解码):" + Decoder.decodeHVM(receiptResponse2.getRet(), String.class)); + + Transaction transaction3 = new Transaction.HVMBuilder(backup.getAddress()).unfreeze(contractAddress).build(); + transaction3.sign(backup); + Assert.assertTrue(backup.verify(transaction2.getNeedHashString().getBytes(), ByteUtil.fromHex(transaction2.getSignature()))); + Assert.assertTrue(SignerUtil.verifySign(transaction2.getNeedHashString(), transaction2.getSignature(), backup.getPublicKey())); + ReceiptResponse receiptResponse3 = contractService.maintain(transaction3).send().polling(); + System.out.println("调用返回(未解码): " + receiptResponse3.getRet()); + System.out.println("调用返回(解码):" + Decoder.decodeHVM(receiptResponse3.getRet(), String.class)); } }