From 1c8df1ac9dd6a3b741aa604eb04623ac59014277 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Thu, 13 Jun 2019 18:44:49 +0800 Subject: [PATCH] modify contract return message ! --- .../com/jd/blockchain/consts/DataCodes.java | 22 ++ .../contract/engine/ContractCode.java | 3 + .../contract/jvm/JVMContractEngine.java | 1 - .../contract/jvm/JavaContractCode.java | 15 +- .../project-to-test/AssetContract2.java | 1 - .../project-to-test/AssetContractImpl2.java | 1 - .../jd/blockchain/ledger/core/AccountSet.java | 6 +- .../blockchain/ledger/core/DataAccount.java | 2 +- .../ledger/core/LedgerTransactionContext.java | 38 +++- .../ledger/core/OperationHandle.java | 27 ++- .../ledger/core/impl/LedgerQueryService.java | 10 +- .../core/impl/LedgerTransactionalEditor.java | 31 ++- .../core/impl/TransactionBatchProcessor.java | 67 +++--- .../ContractCodeDeployOperationHandle.java | 13 +- .../ContractEventSendOperationHandle.java | 7 +- .../DataAccountKVSetOperationHandle.java | 12 +- .../DataAccountRegisterOperationHandle.java | 11 +- .../handles/UserRegisterOperationHandle.java | 16 +- .../contract/ContractSerializeUtils.java | 149 +++++++++++++ .../contract/ContractSerializeUtils2.java | 195 ++++++++++++++++++ .../blockchain/contract/param/WRAP_BYTES.java | 13 ++ .../blockchain/contract/param/WRAP_INT.java | 13 ++ .../blockchain/contract/param/WRAP_LONG.java | 13 ++ .../blockchain/contract/param/WRAP_SHORT.java | 13 ++ .../contract/param/WRAP_STRING.java | 13 ++ .../jd/blockchain/ledger/OperationResult.java | 11 +- .../ledger/OperationResultData.java | 51 +++-- .../com/jd/blockchain/ledger/Transaction.java | 2 +- .../ledger/TransactionRespHandle.java | 10 +- .../ledger/TransactionResponse.java | 4 +- .../ledger/TransactionReturnMessage.java | 17 -- .../ledger/TransactionReturnMessageData.java | 26 --- .../transaction/ContractInvocationProxy.java | 11 +- .../ContractInvocationProxyBuilder.java | 6 +- .../blockchain/transaction/ContractType.java | 47 ++--- .../jd/blockchain/transaction/PreparedTx.java | 18 +- .../transaction/TxResponseMessage.java | 19 +- .../consensus/ConsensusMessageDispatcher.java | 4 +- .../jd/blockchain/intgr/IntegrationBase.java | 87 ++++++-- .../handler/MockerContractExeHandle.java | 6 + 40 files changed, 799 insertions(+), 212 deletions(-) create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils2.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_BYTES.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_INT.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_LONG.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_SHORT.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_STRING.java delete mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java delete mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.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 423d59b5..39850af6 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 @@ -51,6 +51,8 @@ public interface DataCodes { public static final int TX_RESPONSE = 0x350; + public static final int TX_OP_RESULT = 0x360; + public static final int METADATA = 0x600; public static final int METADATA_INIT_SETTING = 0x610; @@ -81,6 +83,26 @@ public interface DataCodes { public static final int DATA = 0x900; + //contract related; + public static final int CONTRACT = 0xA00; + public static final int CONTRACT_BYTE = 0xA01; + + public static final int CONTRACT_SHORT = 0xA02; + + public static final int CONTRACT_INT = 0xA03; + + public static final int CONTRACT_LONG = 0xA04; + + public static final int CONTRACT_STRING = 0xA05; + + public static final int CONTRACT_BYTES = 0xA06; + + public static final int CONTRACT_BIG_INT = 0xA07; + //...0xA19 + public static final int CONTRACT_BIZ_CONTENT = 0xA20; + + public static final int CONTRACT_ARGS = 0xA21; + public static final int CONTRACT_RETURN = 0xA22; public static final int HASH = 0xB00; diff --git a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java index fc7bc64e..962c767d 100644 --- a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java +++ b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java @@ -3,6 +3,9 @@ package com.jd.blockchain.contract.engine; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.utils.Bytes; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + public interface ContractCode { Bytes getAddress(); diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java index 0a8b0018..ea1ee9fa 100644 --- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java @@ -2,7 +2,6 @@ package com.jd.blockchain.contract.jvm; import com.jd.blockchain.contract.engine.ContractCode; import com.jd.blockchain.contract.engine.ContractEngine; -import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.runtime.Module; import com.jd.blockchain.runtime.RuntimeContext; import com.jd.blockchain.utils.Bytes; 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 5686b6b9..9529d11a 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 @@ -3,6 +3,7 @@ package com.jd.blockchain.contract.jvm; import java.lang.reflect.Method; import java.util.concurrent.Callable; +import com.jd.blockchain.contract.ContractSerializeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.ReflectionUtils; @@ -91,9 +92,8 @@ public class JavaContractCode implements ContractCode { address.toString(), contractClass.getName(), eventContext.getEvent())); } - Object[] args = resolveArgs(); + Object[] args = resolveArgs(eventContext.getArgs()); retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); - } catch (Exception e) { error = e; } @@ -115,16 +115,11 @@ public class JavaContractCode implements ContractCode { } private byte[] resolveResult(Object retn) { - if (retn == null) { - return null; - } - // TODO: resolve result in bytes; - return null; + return ContractSerializeUtils.serialize(retn); } - private Object[] resolveArgs() { - // TODO Auto-generated method stub - throw new IllegalStateException("Not implemented!"); + private Object[] resolveArgs(byte[] argBytes) { + return ContractSerializeUtils.resolveArray(argBytes); } } diff --git a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java index b597558e..19822d00 100644 --- a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java +++ b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java @@ -1,6 +1,5 @@ package com.jd.blockchain.contract; -import com.jd.blockchain.ledger.ContractBizContent; import com.jd.blockchain.utils.Bytes; /** diff --git a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java index 06af2632..9f5588bb 100644 --- a/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java +++ b/source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java @@ -1,6 +1,5 @@ package com.jd.blockchain.contract; -import com.jd.blockchain.ledger.ContractBizContent; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataObject; import com.jd.blockchain.utils.Bytes; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java index 01ed4d2f..a28a5fb5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java @@ -162,8 +162,10 @@ public class AccountSet implements Transactional, MerkleProvable { * * 只有最新版本的账户才能可写的,其它都是只读; * - * @param address 账户地址; - * @param version 账户版本;如果指定为 -1,则返回最新版本; + * @param address + * 账户地址; + * @param version + * 账户版本;如果指定为 -1,则返回最新版本; * @return */ public BaseAccount getAccount(Bytes address, long version) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java index 4d23ec27..d7092e63 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java @@ -57,7 +57,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { BytesValue bytesValue = BytesValueEntry.fromBytes(value); return baseAccount.setBytes(key, bytesValue, version); } - + /** * Return the latest version entry associated the specified key; If the key * doesn't exist, then return -1; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java index 6eda929a..33f589c5 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java @@ -1,10 +1,8 @@ package com.jd.blockchain.ledger.core; -import com.jd.blockchain.ledger.TransactionReturnMessage; -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.OperationResult; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.*; + +import java.util.List; /** * 事务上下文; @@ -28,27 +26,45 @@ public interface LedgerTransactionContext { */ TransactionRequest getRequestTX(); + /** + * 提交对账本数据的修改,以指定的交易状态提交交易; + * + * @param txResult + * + * @return + */ + LedgerTransaction commit(TransactionState txResult); + /** * 提交对账本数据的修改,以指定的交易状态提交交易; * * @param txResult - * @param returnMessage + * @param operationResults * * @return */ - LedgerTransaction commit(TransactionState txResult, OperationResult... opResults); - + LedgerTransaction commit(TransactionState txResult, List operationResults); /** * 抛弃对账本数据的修改,以指定的交易状态提交交易;
- * - * 通常来说,当在开启事务之后,修改账本或者尝试提交交易({@link #commit(TransactionState, TransactionReturnMessage)})时发生错误,都应该抛弃数据,通过此方法记录一个表示错误状态的交易; - * + * + * 通常来说,当在开启事务之后,修改账本或者尝试提交交易({@link #commit(TransactionState)})时发生错误,都应该抛弃数据,通过此方法记录一个表示错误状态的交易; + * * @param txResult * @return */ LedgerTransaction discardAndCommit(TransactionState txResult); + /** + * 抛弃对账本数据的修改,以指定的交易状态提交交易;
+ * + * 通常来说,当在开启事务之后,修改账本或者尝试提交交易({@link #commit(TransactionState, List)})时发生错误,都应该抛弃数据,通过此方法记录一个表示错误状态的交易; + * + * @param txResult + * @return + */ + LedgerTransaction discardAndCommit(TransactionState txResult, List operationResults); + /** * 回滚事务,抛弃本次事务的所有数据更新; */ diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java index 9889a457..10be0493 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java @@ -2,6 +2,8 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; +import com.jd.blockchain.utils.concurrent.AsyncFuture; + public interface OperationHandle { @@ -14,8 +16,9 @@ public interface OperationHandle { boolean support(Class operationType); /** - * 解析和执行操作; - * + * 同步解析和执行操作; + * + * * @param op * 操作实例; * @param newBlockDataset @@ -24,8 +27,28 @@ public interface OperationHandle { * 交易请求上下文; * @param previousBlockDataset * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; + * + * @return 操作执行结果 */ byte[] process(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService); + /** + * 异步解析和执行操作; + * TODO 未来规划实现 + * + * + * @param op + * 操作实例; + * @param newBlockDataset + * 需要修改的新区块的数据集; + * @param requestContext + * 交易请求上下文; + * @param previousBlockDataset + * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; + * + * @return 操作执行结果 + */ + AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, + LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java index 66fbda39..2806b5af 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java @@ -276,15 +276,15 @@ public class LedgerQueryService implements BlockchainQueryService { KVDataEntry[] entries = new KVDataEntry[keys.length]; long ver; for (int i = 0; i < entries.length; i++) { - ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); + final String currKey = keys[i]; - dataAccount.getBytes(Bytes.fromString(keys[i]), 1); + ver = dataAccount.getDataVersion(Bytes.fromString(currKey)); if (ver < 0) { - entries[i] = new KVDataObject(keys[i], -1, null); + entries[i] = new KVDataObject(currKey, -1, null); } else { - BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - entries[i] = new KVDataObject(keys[i], ver, value); + BytesValue value = dataAccount.getBytes(Bytes.fromString(currKey), ver); + entries[i] = new KVDataObject(currKey, ver, value); } } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java index 0aae1738..af9294bf 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java @@ -1,5 +1,6 @@ package com.jd.blockchain.ledger.core.impl; +import java.util.List; import java.util.Stack; import com.jd.blockchain.binaryproto.BinaryProtocol; @@ -348,9 +349,14 @@ public class LedgerTransactionalEditor implements LedgerEditor { public TransactionRequest getRequestTX() { return txRequest; } - + + @Override + public LedgerTransaction commit(TransactionState txResult) { + return commit(txResult, null); + } + @Override - public LedgerTransaction commit(TransactionState txResult, OperationResult... opResults) { + public LedgerTransaction commit(TransactionState txResult, List operationResults) { checkTxState(); // capture snapshot @@ -359,7 +365,8 @@ public class LedgerTransactionalEditor implements LedgerEditor { // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, // txResult, txDataSnapshot); - LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null, opResults); + + LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null, operationResultArray(operationResults)); this.txset.add(tx); // this.txset.commit(); @@ -374,9 +381,14 @@ public class LedgerTransactionalEditor implements LedgerEditor { committed = true; return tx; } - + @Override public LedgerTransaction discardAndCommit(TransactionState txResult) { + return discardAndCommit(txResult, null); + } + + @Override + public LedgerTransaction discardAndCommit(TransactionState txResult, List operationResults) { checkTxState(); // 未处理 @@ -385,7 +397,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { // TransactionStagedSnapshot txDataSnapshot = takeSnapshot(); // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, // txResult, txDataSnapshot); - LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null); + LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null, operationResultArray(operationResults)); this.txset.add(tx); // this.txset.commit(); @@ -410,6 +422,15 @@ public class LedgerTransactionalEditor implements LedgerEditor { return txDataSnapshot; } + private OperationResult[] operationResultArray(List operationResults) { + OperationResult[] operationResultArray = null; + if (operationResults != null && !operationResults.isEmpty()) { + operationResultArray = new OperationResult[operationResults.size()]; + operationResults.toArray(operationResultArray); + } + return operationResultArray; + } + @Override public void rollback() { if (this.rollbacked) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java index c251af2d..bfb8a08d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java @@ -50,9 +50,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { private TransactionBatchResult batchResult; /** - * @param newBlockEditor 新区块的数据编辑器; - * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; - * @param opHandles 操作处理对象注册表; + * @param newBlockEditor + * 新区块的数据编辑器; + * @param previousBlockDataset + * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; + * @param opHandles + * 操作处理对象注册表; */ public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset, OperationHandleRegisteration opHandles, LedgerService ledgerService) { @@ -73,9 +76,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { public TransactionResponse schedule(TransactionRequest request) { // 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上; LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request); - TransactionState txResult; - OperationResult[] opResults = null; + TransactionState result; + + List operationResults = new ArrayList<>(); + try { + LedgerDataSet dataset = txCtx.getDataSet(); TransactionRequestContext reqCtx = new TransactionRequestContextImpl(request); // TODO: 验证签名者的有效性; @@ -95,44 +101,44 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { OperationHandleContext handleContext = new OperationHandleContext() { @Override public void handle(Operation operation) { - // assert; Instance of operation are one of User related operations or - // DataAccount related operations; + //assert; Instance of operation are one of User related operations or DataAccount related operations; OperationHandle hdl = opHandles.getHandle(operation.getClass()); hdl.process(operation, dataset, reqCtx, previousBlockDataset, this, ledgerService); } }; OperationHandle opHandle; - int contractOpIndex = 0; - List opResultList = new ArrayList(); - int opIdx = 0; + int opIndex = 0; for (Operation op : ops) { opHandle = opHandles.getHandle(op.getClass()); - byte[] retn = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService); - if (op instanceof ContractEventSendOperation) { - // 支持返回值的操作; - opResultList.add(new OperationResultData(opIdx, retn)); + byte[] opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService); + if (opResult != null) { + operationResults.add(new OperationResultData(opIndex, opResult)); } - - opIdx++; + opIndex++; } // 提交交易(事务); - txResult = TransactionState.SUCCESS; - opResults = opResultList.toArray(new OperationResult[opResultList.size()]); - txCtx.commit(txResult, opResults); + result = TransactionState.SUCCESS; + + txCtx.commit(result, operationResults); } catch (LedgerException e) { // TODO: 识别更详细的异常类型以及执行对应的处理; - txResult = TransactionState.LEDGER_ERROR; - txCtx.discardAndCommit(TransactionState.LEDGER_ERROR); + result = TransactionState.LEDGER_ERROR; + txCtx.discardAndCommit(TransactionState.LEDGER_ERROR, operationResults); LOGGER.warn(String.format("Transaction rollback caused by the ledger exception! --[TxHash=%s] --%s", request.getHash().toBase58(), e.getMessage()), e); } catch (Exception e) { - txResult = TransactionState.SYSTEM_ERROR; - txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR); + result = TransactionState.SYSTEM_ERROR; + txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults); LOGGER.warn(String.format("Transaction rollback caused by the system exception! --[TxHash=%s] --%s", request.getHash().toBase58(), e.getMessage()), e); } - TxResponseHandle resp = new TxResponseHandle(request, txResult, opResults); + TxResponseHandle resp = new TxResponseHandle(request, result); + + if (!operationResults.isEmpty()) { + OperationResult[] operationResultArray = new OperationResult[operationResults.size()]; + resp.setOperationResults(operationResults.toArray(operationResultArray)); + } responseList.add(resp); @@ -213,12 +219,11 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { private TransactionState result; - private OperationResult[] opResults; + private OperationResult[] operationResults; - public TxResponseHandle(TransactionRequest request, TransactionState result, OperationResult... opResults) { + public TxResponseHandle(TransactionRequest request, TransactionState result) { this.request = request; this.result = result; - this.opResults = opResults; } @Override @@ -247,8 +252,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { } @Override - public OperationResult[] getContractReturn() { - return opResults; + public OperationResult[] getOperationResults() { + return operationResults; + } + + public void setOperationResults(OperationResult[] operationResults) { + this.operationResults = operationResults; } } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java index a6b2ac85..84fe06b9 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java @@ -1,5 +1,6 @@ package com.jd.blockchain.ledger.core.impl.handles; +import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.ledger.ContractCodeDeployOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.core.LedgerDataSet; @@ -8,8 +9,12 @@ import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.TransactionRequestContext; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.concurrent.AsyncFuture; import org.springframework.stereotype.Service; +import java.util.concurrent.Future; + @Service public class ContractCodeDeployOperationHandle implements OperationHandle { @@ -20,9 +25,15 @@ public class ContractCodeDeployOperationHandle implements OperationHandle { // TODO: 校验合约代码的正确性; // TODO: 请求者应该提供合约账户的公钥签名,已确定注册的地址的唯一性; + dataset.getContractAccountSet().deploy(contractOP.getContractID().getAddress(), contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode()); - //No result; + + return null; + } + + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { return null; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java index aab23e21..eb392edb 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java @@ -2,8 +2,8 @@ package com.jd.blockchain.ledger.core.impl.handles; import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; -import java.util.concurrent.CompletableFuture; +import com.jd.blockchain.utils.concurrent.AsyncFuture; import org.springframework.stereotype.Service; import com.jd.blockchain.contract.LocalContractEventContext; @@ -76,4 +76,9 @@ public class ContractEventSendOperationHandle implements OperationHandle { return contractCode.processEvent(localContractEventContext); } + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { + return null; + } + } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java index cc1f16b9..7a750fe2 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java @@ -1,5 +1,7 @@ package com.jd.blockchain.ledger.core.impl.handles; +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.utils.concurrent.AsyncFuture; import org.springframework.stereotype.Service; import com.jd.blockchain.binaryproto.DataContractRegistry; @@ -26,12 +28,16 @@ public class DataAccountKVSetOperationHandle implements OperationHandle { LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { DataAccountKVSetOperation kvWriteOp = (DataAccountKVSetOperation) op; DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress()); - KVWriteEntry[] writeset = kvWriteOp.getWriteSet(); - for (KVWriteEntry kvw : writeset) { + KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); + for (KVWriteEntry kvw : writeSet) { +// byte[] value = BinaryProtocol.encode(kvw.getValue(), BytesValue.class); account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion()); } + return null; + } - // No return value; + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { return null; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java index 29178dab..effed394 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java @@ -9,6 +9,7 @@ import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.TransactionRequestContext; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; +import com.jd.blockchain.utils.concurrent.AsyncFuture; import org.springframework.stereotype.Service; @Service @@ -20,12 +21,16 @@ public class DataAccountRegisterOperationHandle implements OperationHandle { DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op; BlockchainIdentity bid = dataAccountRegOp.getAccountID(); - // TODO: 校验用户身份; + //TODO: 校验用户身份; - // TODO: 请求者应该提供数据账户的公钥签名,已确定注册的地址的唯一性; + //TODO: 请求者应该提供数据账户的公钥签名,已确定注册的地址的唯一性; dataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null); - // No return value; + return null; + } + + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { return null; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java index bc6e1cb7..98b68509 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java @@ -8,17 +8,29 @@ import com.jd.blockchain.ledger.core.LedgerService; import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.TransactionRequestContext; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.concurrent.AsyncFuture; + public class UserRegisterOperationHandle implements OperationHandle { @Override public byte[] process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { + + UserRegisterOperation userRegOp = (UserRegisterOperation) op; BlockchainIdentity bid = userRegOp.getUserID(); - dataset.getUserAccountSet().register(bid.getAddress(), bid.getPubKey()); - // No return value; + Bytes userAddress = bid.getAddress(); + + dataset.getUserAccountSet().register(userAddress, bid.getPubKey()); + + return userAddress.toBytes(); + } + + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { 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 new file mode 100644 index 00000000..ffbd4437 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils.java @@ -0,0 +1,149 @@ +package com.jd.blockchain.contract; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.contract.param.*; +import com.jd.blockchain.utils.io.BytesUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ContractSerializeUtils { + + final static int INT_LENGTH = 4; + + static Map, Class> MAP = new HashMap<>(); + + static { + MAP.put(byte[].class, WRAP_BYTES.class); + MAP.put(Short.class, WRAP_SHORT.class); + MAP.put(Integer.class, WRAP_INT.class); + MAP.put(Long.class, WRAP_LONG.class); + MAP.put(String.class, WRAP_STRING.class); + } + + public static boolean support(Class clazz) { + if (clazz.isAnnotationPresent(DataContract.class) || MAP.containsKey(clazz)) { + return true; + } + return false; + } + + public static byte[] serialize(Object data) { + + if (data == null) { + return null; + } + + Class clazz = data.getClass(); + Class serialClass; + Object wrapData = data; + if (clazz.isAnnotationPresent(DataContract.class)) { + serialClass = clazz; + } else { + // 判断类型是否可以序列化 + Class wrapClass = MAP.get(clazz); + if (wrapClass == null) { + throw new IllegalArgumentException("There are Un-Support Type !!!"); + } + serialClass = wrapClass; + + if (wrapClass.equals(WRAP_BYTES.class)) { + wrapData = (WRAP_BYTES) () -> (byte[])data; + } else if (wrapClass.equals(WRAP_INT.class)) { + wrapData = (WRAP_INT) () -> (int)data; + } else if (wrapClass.equals(WRAP_LONG.class)) { + wrapData = (WRAP_LONG) () -> (long)data; + } else if (wrapClass.equals(WRAP_SHORT.class)) { + wrapData = (WRAP_SHORT) () -> (short)data; + } else if (wrapClass.equals(WRAP_STRING.class)) { + wrapData = (WRAP_STRING) () -> (String)data; + } + } + // 按照对应接口进行序列化 + // 生成该接口对应的对象 + return BinaryProtocol.encode(wrapData, serialClass); + } + + public static byte[] serializeArray(Object[] datas) { + if (datas == null || datas.length == 0) { + return null; + } + int contentBytesSize = 0; + byte[] header = new byte[(datas.length + 1) * 4]; + System.arraycopy(BytesUtils.toBytes(datas.length), 0, header, 0, INT_LENGTH); + int offset = INT_LENGTH; + + List serialBytesList = new ArrayList<>(); + for (Object data : datas) { + // 按照对应接口进行序列化 + byte[] currBytes = serialize(data); + // 长度写入 + System.arraycopy(BytesUtils.toBytes(currBytes.length), 0, header, offset, INT_LENGTH); + serialBytesList.add(currBytes); + contentBytesSize += currBytes.length; + offset += INT_LENGTH; + } + + // 填充content + byte[] content = new byte[contentBytesSize]; + offset = 0; + for (byte[] bytes : serialBytesList) { + System.arraycopy(bytes, 0, content, offset, bytes.length); + offset += bytes.length; + } + // 将header和content组装 + return BytesUtils.concat(header, content); + } + + public static Object[] resolveArray(byte[] bytes) { + if (bytes == null || bytes.length == 0) { + return null; + } + byte[] lengthBytes = new byte[INT_LENGTH]; + System.arraycopy(bytes, 0, lengthBytes, 0, INT_LENGTH); + int length = BytesUtils.toInt(lengthBytes); + Object[] datas = new Object[length]; + + int headerOffset = INT_LENGTH; + int contentStart = (length + 1) * INT_LENGTH; + + for (int i = 0 ; i < length; i++) { + byte[] currDataLengthBytes = new byte[INT_LENGTH]; + System.arraycopy(bytes, headerOffset, currDataLengthBytes, 0, INT_LENGTH); + int currDataLength = BytesUtils.toInt(currDataLengthBytes); + // 读取 + byte[] dataBytes = new byte[currDataLength]; + System.arraycopy(bytes, contentStart, dataBytes, 0, currDataLength); + + datas[i] = resolve(dataBytes); + + contentStart += currDataLength; + headerOffset += INT_LENGTH; + } + + return datas; + } + + public static Object resolve(byte[] bytes) { + // 反序列化该接口 + Object currData = BinaryProtocol.decode(bytes); + + // 代理对象类型不能使用class判断,只能使用instanceof + if (currData instanceof WRAP_STRING) { + return ((WRAP_STRING) currData).getValue(); + } else if (currData instanceof WRAP_INT) { + return ((WRAP_INT) currData).getValue(); + } else if (currData instanceof WRAP_LONG) { + return ((WRAP_LONG) currData).getValue(); + } else if (currData instanceof WRAP_BYTES) { + return ((WRAP_BYTES) currData).getValue(); + } else if (currData instanceof WRAP_SHORT) { + return ((WRAP_SHORT) currData).getValue(); + } else { + return currData; + } + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils2.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils2.java new file mode 100644 index 00000000..22bbdb38 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractSerializeUtils2.java @@ -0,0 +1,195 @@ +//package com.jd.blockchain.contract; +// +//import com.jd.blockchain.binaryproto.BinaryProtocol; +//import com.jd.blockchain.binaryproto.DataContract; +//import com.jd.blockchain.consts.DataCodes; +//import com.jd.blockchain.ledger.*; +//import com.jd.blockchain.utils.Bytes; +//import com.jd.blockchain.utils.IllegalDataException; +//import org.springframework.util.ReflectionUtils; +// +//import java.nio.ByteBuffer; +//import java.util.Arrays; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +///** +// * @author zhaogw +// * date 2019/5/16 18:05 +// */ +//public class ContractSerializeUtils { +// public static Map> DATA_CONTRACT_MAP = new HashMap<>(); +// 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 }; +// +// /** +// * serialize the Object[] by List list; +// * @param objArr +// * @param dataContractList +// * @return +// */ +// 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 dataContractList) { +// Object result[] = new Object[dataContractList.size()]; +// ByteBuffer byteBuffer = ByteBuffer.allocate(params.length); +// byteBuffer.put(params); +// int paramNums = byteBuffer.getInt(0); +// +// if(paramNums != dataContractList.size()){ +// throw new IllegalArgumentException("deserialize Method param. params'length in byte[] != method's param length"); +// } +// +// int offsetPosition = (1 + dataContractList.size())*4; //start position of real data; +// for(int i=0; i classObj = getDataIntf().get(dataContract.code()); +// try { +// result[i] = ReflectionUtils.invokeMethod(classObj.getMethod("getValue"),object); +// } catch (NoSuchMethodException e) { +// throw new IllegalStateException("no getValue(). detail="+e.getMessage()); +// } +// }else { +// result[i] = object; +// } +// byteBuffer1.clear(); +// } +// +// return result; +// } +// +// +// /** +// * 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); +// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT32, CONTRACT_INT32.class); +// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_INT64, CONTRACT_INT64.class); +// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_TEXT, CONTRACT_TEXT.class); +// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BINARY, CONTRACT_BINARY.class); +// DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BIZ_CONTENT, ContractBizContent.class); +// return DATA_CONTRACT_MAP; +// } +// +// public static boolean isPrimitiveType(int dataContractCode){ +// return Arrays.asList(PRIMITIVE_DATA_CODES).contains(dataContractCode); +// } +// +// 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()); +// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT32.class)){ +// return (CONTRACT_INT32) () -> Integer.parseInt(object.toString()); +// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_INT64.class)){ +// return (CONTRACT_INT64) () -> Long.parseLong(object.toString()); +// }else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_TEXT.class)){ +// 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(ContractBizContent.class)){ +// ContractBizContent contractBizContent = (ContractBizContent)object; +// return contractBizContent; +// }else { +// throw new IllegalDataException("cann't get new Object by dataContract and object."); +// } +// } +// +// /** +// * 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; +// }else { +// throw new IllegalDataException(String.format("no support the classType=%s, please check @DataContract.",classType.toString())); +// } +// } +// +// public static DataContract parseDataContract(Class classType){ +// 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.getAnnotation(DataContract.class); +// } +// 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/contract/param/WRAP_BYTES.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_BYTES.java new file mode 100644 index 00000000..b99e6786 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_BYTES.java @@ -0,0 +1,13 @@ +package com.jd.blockchain.contract.param; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.CONTRACT_BYTES) +public interface WRAP_BYTES { + + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + byte[] getValue(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_INT.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_INT.java new file mode 100644 index 00000000..48e2d1d9 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_INT.java @@ -0,0 +1,13 @@ +package com.jd.blockchain.contract.param; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.CONTRACT_INT) +public interface WRAP_INT { + + @DataField(order = 1, primitiveType = PrimitiveType.INT32) + int getValue(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_LONG.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_LONG.java new file mode 100644 index 00000000..8b402b04 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_LONG.java @@ -0,0 +1,13 @@ +package com.jd.blockchain.contract.param; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.CONTRACT_LONG) +public interface WRAP_LONG { + + @DataField(order = 1, primitiveType = PrimitiveType.INT64) + long getValue(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_SHORT.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_SHORT.java new file mode 100644 index 00000000..d30cc366 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_SHORT.java @@ -0,0 +1,13 @@ +package com.jd.blockchain.contract.param; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.CONTRACT_SHORT) +public interface WRAP_SHORT { + + @DataField(order = 1, primitiveType = PrimitiveType.INT16) + short getValue(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_STRING.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_STRING.java new file mode 100644 index 00000000..7c475c79 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/param/WRAP_STRING.java @@ -0,0 +1,13 @@ +package com.jd.blockchain.contract.param; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.CONTRACT_STRING) +public interface WRAP_STRING { + + @DataField(order = 1, primitiveType = PrimitiveType.TEXT) + String getValue(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResult.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResult.java index 87ff2bdc..49e48be7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResult.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResult.java @@ -5,13 +5,14 @@ import com.jd.blockchain.binaryproto.DataField; import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.consts.DataCodes; -@DataContract(code = DataCodes.CONTRACT_RETURN) +@DataContract(code = DataCodes.TX_OP_RESULT) public interface OperationResult { - @DataField(order = 1, primitiveType = PrimitiveType.INT32) - int getIndex(); + @DataField(order=1, primitiveType = PrimitiveType.INT32) + int getIndex(); - @DataField(order = 2, primitiveType = PrimitiveType.BYTES) - byte[] getResult(); + @DataField(order=2, primitiveType = PrimitiveType.BYTES) + byte[] getResult(); + T getResultData(); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResultData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResultData.java index a96fe407..f8eb0959 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResultData.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationResultData.java @@ -1,26 +1,45 @@ package com.jd.blockchain.ledger; +import com.jd.blockchain.contract.ContractSerializeUtils; + public class OperationResultData implements OperationResult { - private int index; + private int index; + + private byte[] result; + + public OperationResultData() { + } + + public OperationResultData(OperationResult operationResult) { + this(operationResult.getIndex(), operationResult.getResult()); + } + + public OperationResultData(int index, byte[] result) { + this.index = index; + this.result = result; + } - private byte[] result; + @Override + public int getIndex() { + return index; + } - public OperationResultData() { - } + @Override + public byte[] getResult() { + return result; + } - public OperationResultData(int operationIndex, byte[] result) { - this.index = operationIndex; - this.result = result; - } + @Override + public T getResultData() { + return (T) ContractSerializeUtils.resolve(result); + } - @Override - public int getIndex() { - return index; - } + public void setIndex(int index) { + this.index = index; + } - @Override - public byte[] getResult() { - return result; - } + public void setResult(byte[] result) { + this.result = result; + } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java index 26b744bd..542a3a49 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java @@ -49,6 +49,6 @@ public interface Transaction extends NodeRequest, HashObject { * * @return */ - @DataField(order = 4, refContract = true, list = true) + @DataField(order=4, list = true, refContract=true) OperationResult[] getOperationResults(); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java index 62fc3ebe..3856f668 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java @@ -27,7 +27,7 @@ public class TransactionRespHandle implements TransactionResponse { private TransactionState globalResult; - private OperationResult[] contractReturn; + private OperationResult[] operationResults; public TransactionRespHandle(TransactionRequest request, TransactionState result, TransactionState globalResult) { this.request = request; @@ -51,8 +51,8 @@ public class TransactionRespHandle implements TransactionResponse { this.result = result; } - public void setContractReturn(OperationResult[] contractReturn) { - this.contractReturn = contractReturn; + public void setOperationResults(OperationResult[] operationResults) { + this.operationResults = operationResults; } public LedgerBlock getBlock() { @@ -97,7 +97,7 @@ public class TransactionRespHandle implements TransactionResponse { } @Override - public OperationResult[] getContractReturn() { - return contractReturn; + public OperationResult[] getOperationResults() { + return operationResults; } } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java index 6d6916a0..662d595b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java @@ -63,6 +63,6 @@ public interface TransactionResponse { * * @return */ - @DataField(order = 6, list = true, refContract = true) - OperationResult[] getContractReturn(); + @DataField(order=6, list=true, refContract = true) + OperationResult[] getOperationResults(); } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java deleted file mode 100644 index 94cef8b0..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code= DataCodes.TX_RETURN_MESSAGE) -public interface TransactionReturnMessage { - - /** - * 合约返回值列表 - * - * @return - */ - @DataField(order=1, list = true, refContract=true) - OperationResult[] getContractReturn(); -} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.java deleted file mode 100644 index 7f324158..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.jd.blockchain.ledger; - -import java.util.ArrayList; -import java.util.List; - -public class TransactionReturnMessageData implements TransactionReturnMessage { - - private List contractReturnMessages = new ArrayList<>(); - - public void addContractReturnMessage(OperationResult contractReturnMessage) { - contractReturnMessages.add(contractReturnMessage); - } - - public boolean isContractReturnEmpty() { - return contractReturnMessages.isEmpty(); - } - - @Override - public OperationResult[] getContractReturn() { - if (isContractReturnEmpty()) { - return null; - } - OperationResult[] crms = new OperationResult[contractReturnMessages.size()]; - return contractReturnMessages.toArray(crms); - } -} 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 7ec2bbb6..bcccf78b 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 @@ -3,6 +3,7 @@ package com.jd.blockchain.transaction; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import com.jd.blockchain.contract.ContractSerializeUtils; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.IllegalDataException; @@ -37,18 +38,14 @@ public class ContractInvocationProxy implements InvocationHandler { // hashCode 方法; } // 合约方法; - byte[] argBytes = serializeArgs(args,method); + byte[] argBytes = serializeArgs(args); sendOpBuilder.send(contractAddress, event, argBytes); // TODO: 暂时未考虑有返回值的情况; return null; } - private byte[] serializeArgs(Object[] args, Method method) { - if(args == null || args.length==0){ - return null; - } - throw new IllegalStateException("Not implemented!"); - //return ContractSerializeUtils.serializeMethodParam(args,contractType.getDataContractMap().get(method)); + private byte[] serializeArgs(Object[] args) { + return ContractSerializeUtils.serializeArray(args); } } 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 bc696279..66d79b4a 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 @@ -35,9 +35,9 @@ public class ContractInvocationProxyBuilder { } // TODO 检查返回值类型; - ContractType contractType1 = ContractType.resolve(contractIntf); - contractTypes.put(contractIntf,contractType1); - return contractType1; + ContractType ct = ContractType.resolve(contractIntf); + contractTypes.put(contractIntf, ct); + return ct; } 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 d26b2aca..3e8835aa 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,16 +1,14 @@ package com.jd.blockchain.transaction; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; 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; public class ContractType { @@ -60,42 +58,41 @@ public class ContractType { private ContractType() { } - public static ContractType resolve(Class contractIntf){ - ContractType contractType = new ContractType(); - - Annotation annotation = contractIntf.getDeclaredAnnotation(Contract.class); + public static ContractType resolve(Class contractIntf) { - //contains: @Contract? - boolean isContractType = annotation != null ? true : false; - if(!isContractType){ - throw new IllegalDataException("is not Contract Type, becaust there is not @Contract."); + // 接口上必须有注解 + if (!contractIntf.isAnnotationPresent(Contract.class)) { + throw new IllegalDataException("It is not a Contract Type, because there is not @Contract !"); } - //contractIntf contains @Contract and @ContractEvent; Method[] classMethods = contractIntf.getDeclaredMethods(); + + if (classMethods.length == 0) { + throw new IllegalDataException("This interface have not any methods !"); + } + + ContractType contractType = new ContractType(); + for (Method method : classMethods) { + // if current method contains @ContractEvent,then put it in this map; ContractEvent contractEvent = method.getAnnotation(ContractEvent.class); + if (contractEvent != null) { - String eventName_ = contractEvent.name(); + String eventName = contractEvent.name(); //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! - if(contractType.events.containsKey(eventName_)){ + if(contractType.events.containsKey(eventName)){ 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){ - throw new IllegalStateException("Not implemented!"); -// DataContract dataContract = ContractSerializeUtils.parseDataContract(curParamType); -// dataContractList.add(dataContract); + for(Class currParamType : paramTypes) { + if (!ContractSerializeUtils.support(currParamType)) { + throw new IllegalStateException(String.format("Param Type = %s can not support !!!", currParamType.getName())); + } } -// if(dataContractList.size()>0){ -// contractType.dataContractMap.put(method,dataContractList); -// } - - contractType.events.put(eventName_, method); - contractType.handleMethods.put(method,eventName_); + contractType.events.put(eventName, method); + contractType.handleMethods.put(method, eventName); } } return contractType; diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java index 2b0422c0..34432aeb 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java @@ -7,12 +7,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.PreparedTransaction; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.ledger.TransactionResponse; +import com.jd.blockchain.ledger.*; public class PreparedTx implements PreparedTransaction { @@ -56,6 +51,17 @@ public class PreparedTx implements PreparedTransaction { TransactionRequest txReq = txReqBuilder.buildRequest(); // 发起交易请求; TransactionResponse txResponse = txProcessor.process(txReq); + // 重新包装操作集合 + OperationResult[] operationResults = txResponse.getOperationResults(); + if (operationResults != null && operationResults.length > 0) { + OperationResult[] wrapOpResults = new OperationResult[operationResults.length]; + for (int i = 0; i < operationResults.length; i++) { + wrapOpResults[i] = new OperationResultData(operationResults[i]); + } + return new TxResponseMessage(txResponse, wrapOpResults); + } return txResponse; } + + } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java index a966239b..57107ff3 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java @@ -19,10 +19,19 @@ public class TxResponseMessage implements TransactionResponse { private TransactionState executionState; - private OperationResult[] contractReturn; + private OperationResult[] operationResults; public TxResponseMessage() { } + + // 重新包装operationResults + public TxResponseMessage(TransactionResponse transactionResponse, OperationResult[] operationResults) { + this.contentHash = transactionResponse.getContentHash(); + this.blockHash = transactionResponse.getBlockHash(); + this.blockHeight = transactionResponse.getBlockHeight(); + this.executionState = transactionResponse.getExecutionState(); + this.operationResults = operationResults; + } public TxResponseMessage(HashDigest contentHash) { this.contentHash = contentHash; @@ -60,8 +69,8 @@ public class TxResponseMessage implements TransactionResponse { this.blockHeight = blockHeight; } - public void setContractReturn(OperationResult[] contractReturn) { - this.contractReturn = contractReturn; + public void setOperationResults(OperationResult[] operationResults) { + this.operationResults = operationResults; } @Override @@ -70,8 +79,8 @@ public class TxResponseMessage implements TransactionResponse { } @Override - public OperationResult[] getContractReturn() { - return contractReturn; + public OperationResult[] getOperationResults() { + return operationResults; } } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java index 97d7b9ba..d207d725 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java @@ -310,8 +310,8 @@ public class ConsensusMessageDispatcher implements MessageHandle { } @Override - public OperationResult[] getContractReturn() { - return txResp.getContractReturn(); + public OperationResult[] getOperationResults() { + return txResp.getOperationResults(); } } 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 25360ebe..9e4d16b3 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 @@ -24,6 +24,8 @@ import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicLong; +import com.jd.blockchain.contract.ReadContract; +import com.jd.blockchain.ledger.*; import org.apache.commons.io.FileUtils; import org.springframework.core.io.ClassPathResource; @@ -31,16 +33,6 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.KVDataEntry; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.PreparedTransaction; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.TransactionTemplate; -import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.impl.LedgerManager; import com.jd.blockchain.sdk.BlockchainService; @@ -446,9 +438,9 @@ public class IntegrationBase { // 合约测试使用的初始化数据; static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); - // 保存资产总数的键; - // 第二个参数; - private static String contractZipName = "contract.jar"; + // 保存资产总数的键; + // 第二个参数; + private static String contractZipName = "contract-read.jar"; static HashDigest txContentHash; public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, @@ -484,7 +476,7 @@ public class IntegrationBase { // execute the contract; // testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); // testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); - + testExeReadContract(adminKey, ledgerHash, blockchainService); return block; } @@ -545,6 +537,73 @@ public class IntegrationBase { // assertEquals(888L,kvDataEntries[1].getValue()); // } + private static void testExeReadContract(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) { + + // 首先注册一个数据账户 + BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); + + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + txTpl.dataAccounts().register(newDataAccount.getIdentity()); + + PreparedTransaction ptx = txTpl.prepare(); + ptx.sign(adminKey); + + // 提交并等待共识返回; + ptx.commit(); + + // 再提交一个KV写入 + String key1 = "JingDong", value1 = "www.jd.com"; + String key2 = "JD", value2 = "JingDong"; + + TransactionTemplate txKv = blockchainService.newTransaction(ledgerHash); + txKv.dataAccount(newDataAccount.getAddress()).setText(key1, value1, -1).setText(key2, value2, -1); + PreparedTransaction kvPtx = txKv.prepare(); + kvPtx.sign(adminKey); + + // 提交并等待共识返回; + kvPtx.commit(); + + // 下面才是执行Read交易 + // 定义交易; + TransactionTemplate txContract = blockchainService.newTransaction(ledgerHash); + + ReadContract readContract1 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); + readContract1.read(newDataAccount.getAddress().toBase58(), key1); + + ReadContract readContract2 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); + readContract2.read(newDataAccount.getAddress().toBase58(), key2); + + ReadContract readContract3 = txContract.contract(contractDeployKey.getAddress(), ReadContract.class); + readContract3.readVersion(newDataAccount.getAddress().toBase58(), key2); + + // 签名; + PreparedTransaction contractPtx = txContract.prepare(); + contractPtx.sign(adminKey); + + // 提交并等待共识返回; + TransactionResponse readTxResp = contractPtx.commit(); + + OperationResult[] operationResults = readTxResp.getOperationResults(); + + // 打印结果 + for (OperationResult or : operationResults) { + System.out.printf("操作[%s].Result = %s \r\n", or.getIndex(), or.getResultData()); + } +// +// // 验证结果 +// assertNotNull(contractReturn); +// assertEquals(contractReturn.length, 3); +// +// String returnVal1 = contractReturn[0]; +// assertEquals(value1, returnVal1); +// +// String returnVal2 = contractReturn[1]; +// assertEquals(value2, returnVal2); +// +// String returnVal3 = contractReturn[2]; +// assertEquals("0", returnVal3); + } + /** * 根据合约构建字节数组; * diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java index 0e9364fa..c16c3aba 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java @@ -15,6 +15,7 @@ import com.jd.blockchain.ledger.core.impl.LedgerQueryService; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; import com.jd.blockchain.ledger.core.impl.handles.ContractLedgerContext; import com.jd.blockchain.mocker.proxy.ExecutorProxy; +import com.jd.blockchain.utils.concurrent.AsyncFuture; import java.util.Map; import java.util.Set; @@ -64,6 +65,11 @@ public class MockerContractExeHandle implements OperationHandle { return null; } + @Override + public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { + return null; + } + @Override public boolean support(Class operationType) { return ContractEventSendOperation.class.isAssignableFrom(operationType);