diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java new file mode 100644 index 00000000..53aec345 --- /dev/null +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java @@ -0,0 +1,112 @@ +package com.jd.blockchain.contract.jvm; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; + +import com.jd.blockchain.contract.ContractEventContext; +import com.jd.blockchain.contract.ContractException; +import com.jd.blockchain.contract.EventProcessingAware; +import com.jd.blockchain.contract.engine.ContractCode; +import com.jd.blockchain.utils.Bytes; + +/** + * @author huanghaiquan + * + */ +public abstract class AbstractContractCode implements ContractCode { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractContractCode.class); + private Bytes address; + private long version; + + private ContractDefinition contractDefinition; + + public AbstractContractCode(Bytes address, long version, ContractDefinition contractDefinition) { + this.address = address; + this.version = version; + this.contractDefinition = contractDefinition; + } + + public ContractDefinition getContractDefinition() { + return contractDefinition; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public long getVersion() { + return version; + } + + @Override + public byte[] processEvent(ContractEventContext eventContext) { + EventProcessingAware evtProcAwire = null; + Object retn = null; + Exception error = null; + try { + // 执行预处理; + Object contractInstance = getContractInstance(); + if (contractInstance instanceof EventProcessingAware) { + evtProcAwire = (EventProcessingAware) contractInstance; + } + + if (evtProcAwire != null) { + evtProcAwire.beforeEvent(eventContext); + } + + // 反序列化参数; + Method handleMethod = contractDefinition.getType().getHandleMethod(eventContext.getEvent()); + + if (handleMethod == null) { + throw new ContractException( + String.format("Contract[%s:%s] has no handle method to handle event[%s]!", address.toString(), + contractDefinition.getType().getDeclaredClass().toString(), eventContext.getEvent())); + } + + Object[] args = resolveArgs(); + retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); + + } catch (Exception e) { + error = e; + } + + if (evtProcAwire != null) { + try { + evtProcAwire.postEvent(eventContext, error); + } catch (Exception e) { + String errorMessage = "Error occurred while posting contract event! --" + e.getMessage(); + LOGGER.error(errorMessage, e); + throw new ContractException(errorMessage, e); + } + } + if (error != null) { + // Rethrow error; + throw new ContractException(String.format("Error occurred while processing event[%s] of contract[%s]! --%s", + eventContext.getEvent(), address.toString(), error.getMessage()), error); + } + + byte[] retnBytes = resolveResult(retn); + return retnBytes; + } + + protected abstract Object getContractInstance(); + + private byte[] resolveResult(Object retn) { + if (retn == null) { + return null; + } + // TODO: resolve result in bytes; + throw new IllegalStateException("Not implemented!"); + } + + private Object[] resolveArgs() { + // TODO Auto-generated method stub + throw new IllegalStateException("Not implemented!"); + } + +} diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/ContractDefinition.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/ContractDefinition.java new file mode 100644 index 00000000..d61e037a --- /dev/null +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/ContractDefinition.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.contract.jvm; + +import com.jd.blockchain.contract.ContractType; + +public class ContractDefinition { + + private ContractType type; + + private Class mainClass; + + public Class getMainClass() { + return mainClass; + } + + public ContractType getType() { + return type; + } + + public ContractDefinition(ContractType type, Class mainClass) { + this.type = type; + this.mainClass = mainClass; + } + +} 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 9529d11a..20f97863 100644 --- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java @@ -1,47 +1,57 @@ 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; +import com.jd.blockchain.contract.Contract; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractException; -import com.jd.blockchain.contract.EventProcessingAwire; -import com.jd.blockchain.contract.engine.ContractCode; +import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.runtime.Module; -import com.jd.blockchain.transaction.ContractType; import com.jd.blockchain.utils.Bytes; /** - * contract code based jvm + * 基于 java jar 包并且以模块化方式独立加载的合约代码; * - * @author zhaogw + * @author huanghaiquan + * */ -public class JavaContractCode implements ContractCode { +public class JavaContractCode extends AbstractContractCode { private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class); private Module codeModule; private Bytes address; private long version; - private Class contractClass; - private ContractType contractType; - public JavaContractCode(Bytes address, long version, Module codeModule) { + super(address, version, resolveContractDefinition(codeModule)); this.address = address; this.version = version; this.codeModule = codeModule; - - init(); } - private void init() { - String contractClassName = codeModule.getMainClass(); - this.contractClass = codeModule.loadClass(contractClassName); - this.contractType = ContractType.resolve(contractClass); + protected static ContractDefinition resolveContractDefinition(Module codeModule) { + String mainClassName = codeModule.getMainClass(); + Class mainClass = codeModule.loadClass(mainClassName); + Class[] interfaces = mainClass.getInterfaces(); + Class contractInterface = null; + for (Class itf : interfaces) { + Contract annoContract = itf.getAnnotation(Contract.class); + if (annoContract != null) { + if (contractInterface == null) { + contractInterface = itf; + } else { + throw new ContractException( + "One contract definition is only allowed to implement one contract type!"); + } + } + } + if (contractInterface == null) { + throw new ContractException("No contract type is implemented!"); + } + ContractType type = ContractType.resolve(contractInterface); + return new ContractDefinition(type, mainClass); } @Override @@ -56,11 +66,32 @@ public class JavaContractCode implements ContractCode { @Override public byte[] processEvent(ContractEventContext eventContext) { - return codeModule.call(new ContractExecution(eventContext)); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Start processing event[%s] of contract[%s]...", eventContext.getEvent(), address.toString()); + } + try { + return codeModule.call(new ContractExecution(eventContext)); + } catch (Exception ex) { + LOGGER.error(String.format("Error occurred while processing event[%s] of contract[%s]! --%s", + eventContext.getEvent(), address.toString(), ex.getMessage()), ex); + throw ex; + } finally { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("End processing event[%s] of contract[%s]. ", eventContext.getEvent(), address.toString()); + } + } } - private class ContractExecution implements Callable { + protected Object getContractInstance() { + try { + // 每一次调用都通过反射创建合约的实例; + return getContractDefinition().getMainClass().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + private class ContractExecution implements Callable { private ContractEventContext eventContext; public ContractExecution(ContractEventContext contractEventContext) { @@ -69,57 +100,7 @@ public class JavaContractCode implements ContractCode { @Override public byte[] call() throws Exception { - EventProcessingAwire evtProcAwire = null; - Object retn = null; - Exception error = null; - try { - // 执行预处理; - Object contractInstance = contractClass.newInstance();// 合约主类生成的类实例; - if (contractInstance instanceof EventProcessingAwire) { - evtProcAwire = (EventProcessingAwire) contractInstance; - } - - if (evtProcAwire != null) { - evtProcAwire.beforeEvent(eventContext); - } - - // 反序列化参数; - Method handleMethod = contractType.getHandleMethod(eventContext.getEvent()); - - if (handleMethod == null) { - throw new ContractException( - String.format("Contract[%s:%s] has no handle method to handle event[%s]!", - address.toString(), contractClass.getName(), eventContext.getEvent())); - } - - Object[] args = resolveArgs(eventContext.getArgs()); - retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); - } catch (Exception e) { - error = e; - } - - if (evtProcAwire != null) { - try { - evtProcAwire.postEvent(eventContext, error); - } catch (Exception e) { - LOGGER.error("Error occurred while posting contract event! --" + e.getMessage(), e); - } - } - if (error != null) { - // Rethrow error; - throw error; - } - - byte[] retnBytes = resolveResult(retn); - return retnBytes; - } - - private byte[] resolveResult(Object retn) { - return ContractSerializeUtils.serialize(retn); - } - - private Object[] resolveArgs(byte[] argBytes) { - return ContractSerializeUtils.resolveArray(argBytes); + return JavaContractCode.super.processEvent(eventContext); } } diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java index 64a12e20..461917a4 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java @@ -8,7 +8,7 @@ import com.github.javaparser.ast.PackageDeclaration; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; -import com.jd.blockchain.transaction.ContractType; +import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.utils.IllegalDataException; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoFailureException; diff --git a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java index 83072f7a..e3d720a5 100644 --- a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java +++ b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java @@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.KVDataEntry; @Contract -public class ReadContractImpl implements EventProcessingAwire, ReadContract { +public class ReadContractImpl implements EventProcessingAware, ReadContract { private ContractEventContext eventContext; 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 10be0493..2a13690b 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 @@ -33,22 +33,22 @@ public interface OperationHandle { 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); +// /** +// * 异步解析和执行操作; +// * 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/DefaultOperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java index a1742499..1966c716 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java @@ -3,16 +3,12 @@ package com.jd.blockchain.ledger.core.impl; import java.util.ArrayList; import java.util.List; -import javax.annotation.PostConstruct; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle; -import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle; +import com.jd.blockchain.ledger.core.impl.handles.JVMContractEventSendOperationHandle; import com.jd.blockchain.ledger.core.impl.handles.DataAccountKVSetOperationHandle; import com.jd.blockchain.ledger.core.impl.handles.DataAccountRegisterOperationHandle; import com.jd.blockchain.ledger.core.impl.handles.UserRegisterOperationHandle; @@ -34,7 +30,7 @@ public class DefaultOperationHandleRegisteration implements OperationHandleRegis opHandles.add(new DataAccountRegisterOperationHandle()); opHandles.add(new UserRegisterOperationHandle()); opHandles.add(new ContractCodeDeployOperationHandle()); - opHandles.add(new ContractEventSendOperationHandle()); + opHandles.add(new JVMContractEventSendOperationHandle()); } /** 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/AbtractContractEventHandle.java similarity index 78% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbtractContractEventHandle.java index eb392edb..56a24db1 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/AbtractContractEventHandle.java @@ -2,8 +2,6 @@ package com.jd.blockchain.ledger.core.impl.handles; import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; - -import com.jd.blockchain.utils.concurrent.AsyncFuture; import org.springframework.stereotype.Service; import com.jd.blockchain.contract.LocalContractEventContext; @@ -23,13 +21,7 @@ import com.jd.blockchain.ledger.core.impl.LedgerQueryService; import com.jd.blockchain.ledger.core.impl.OperationHandleContext; @Service -public class ContractEventSendOperationHandle implements OperationHandle { - - private static final ContractEngine JVM_ENGINE; - - static { - JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); - } +public abstract class AbtractContractEventHandle implements OperationHandle { @Override public boolean support(Class operationType) { @@ -65,20 +57,15 @@ public class ContractEventSendOperationHandle implements OperationHandle { localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest()) .setLedgerContext(ledgerContext); - ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); - if (contractCode == null) { - // 装载合约; - contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), - contract.getChainCode()); - } + + // 装载合约; + ContractCode contractCode = loadContractCode(contract); // 处理合约事件; return contractCode.processEvent(localContractEventContext); } + + protected abstract ContractCode loadContractCode(ContractAccount contract); - @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/ContractCodeDeployOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java index 84fe06b9..a71b26d1 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 @@ -32,10 +32,10 @@ public class ContractCodeDeployOperationHandle implements OperationHandle { return null; } - @Override - public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { - 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) { 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 7a750fe2..9844d4c6 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 @@ -36,10 +36,10 @@ public class DataAccountKVSetOperationHandle implements OperationHandle { return null; } - @Override - public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { - 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) { 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 effed394..8bce4efd 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 @@ -29,10 +29,10 @@ public class DataAccountRegisterOperationHandle implements OperationHandle { return null; } - @Override - public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { - 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) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java new file mode 100644 index 00000000..a5b592ab --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java @@ -0,0 +1,43 @@ +package com.jd.blockchain.ledger.core.impl.handles; + +import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; + +import com.jd.blockchain.contract.engine.ContractCode; +import com.jd.blockchain.contract.engine.ContractEngine; +import com.jd.blockchain.contract.engine.ContractServiceProviders; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.core.ContractAccount; +import com.jd.blockchain.ledger.core.LedgerDataSet; +import com.jd.blockchain.ledger.core.LedgerService; +import com.jd.blockchain.ledger.core.TransactionRequestContext; +import com.jd.blockchain.ledger.core.impl.OperationHandleContext; +import com.jd.blockchain.utils.concurrent.AsyncFuture; + +public class JVMContractEventSendOperationHandle extends AbtractContractEventHandle { + + private static final ContractEngine JVM_ENGINE; + + static { + JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); + } + + @Override + protected ContractCode loadContractCode(ContractAccount contract) { + ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); + if (contractCode == null) { + // 装载合约; + contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), + contract.getChainCode()); + } + return contractCode; + } + +// @Override +// public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, +// TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, +// OperationHandleContext handleContext, LedgerService ledgerService) { +// // TODO Auto-generated method stub +// 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 98b68509..d4072aa7 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 @@ -29,10 +29,10 @@ public class UserRegisterOperationHandle implements OperationHandle { return userAddress.toBytes(); } - @Override - public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { - 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) { diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java index 0f081af9..c0a31321 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java @@ -1,82 +1,50 @@ -//package test.com.jd.blockchain.ledger; -// -//import java.util.Map; -//import java.util.concurrent.CompletableFuture; -//import java.util.concurrent.ConcurrentHashMap; -// -//import com.jd.blockchain.contract.LocalContractEventContext; -//import com.jd.blockchain.contract.engine.ContractCode; -//import com.jd.blockchain.ledger.ContractEventSendOperation; -//import com.jd.blockchain.ledger.LedgerException; -//import com.jd.blockchain.ledger.Operation; -//import com.jd.blockchain.ledger.core.ContractAccount; -//import com.jd.blockchain.ledger.core.ContractAccountSet; -//import com.jd.blockchain.ledger.core.LedgerDataSet; -//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.LedgerQueryService; -//import com.jd.blockchain.ledger.core.impl.OperationHandleContext; -//import com.jd.blockchain.ledger.core.impl.handles.ContractLedgerContext; -//import com.jd.blockchain.utils.Bytes; -// -//public class ContractInvokingHandle implements OperationHandle { -// -// private Map contractInstances = new ConcurrentHashMap(); -// -// @Override -// public byte[] process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, -// LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) { -// process(op, dataset, requestContext, previousBlockDataset, opHandleContext, ledgerService, null); -// -// // TODO: return value; -// return null; -// } -// -// @Override -// public boolean support(Class operationType) { -// return ContractEventSendOperation.class.isAssignableFrom(operationType); -// } -// -// public void process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, -// LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService, -// CompletableFuture contractReturn) { -// -// ContractEventSendOperation contractOP = (ContractEventSendOperation) op; -// // 先从账本校验合约的有效性; -// // 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行; -// ContractAccountSet contractSet = previousBlockDataset.getContractAccountSet(); -// if (!contractSet.contains(contractOP.getContractAddress())) { -// throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", -// contractOP.getContractAddress())); -// } -// -// // 创建合约的账本上下文实例; -// LedgerQueryService queryService = new LedgerQueryService(ledgerService); -// ContractLedgerContext ledgerContext = new ContractLedgerContext(queryService, opHandleContext); -// -// // 先检查合约引擎是否已经加载合约;如果未加载,再从账本中读取合约代码并装载到引擎中执行; -// ContractAccount contract = contractSet.getContract(contractOP.getContractAddress()); -// if (contract == null) { -// throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", -// contractOP.getContractAddress())); -// } -// -// // 创建合约上下文; -// LocalContractEventContext localContractEventContext = new LocalContractEventContext( -// requestContext.getRequest().getTransactionContent().getLedgerHash(), contractOP.getEvent()); -// localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest()) -// .setLedgerContext(ledgerContext); -// -// ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); -// if (contractCode == null) { -// // 装载合约; -// contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), -// contract.getChainCode()); -// } -// -// // 处理合约事件; -// contractCode.processEvent(localContractEventContext, contractReturn); -// } -// -//} +package test.com.jd.blockchain.ledger; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.jd.blockchain.contract.ContractType; +import com.jd.blockchain.contract.engine.ContractCode; +import com.jd.blockchain.contract.jvm.AbstractContractCode; +import com.jd.blockchain.contract.jvm.ContractDefinition; +import com.jd.blockchain.ledger.core.ContractAccount; +import com.jd.blockchain.ledger.core.impl.handles.AbtractContractEventHandle; +import com.jd.blockchain.utils.Bytes; + +public class ContractInvokingHandle extends AbtractContractEventHandle { + + private Map contractInstances = new ConcurrentHashMap(); + + @Override + protected ContractCode loadContractCode(ContractAccount contract) { + return contractInstances.get(contract.getAddress()); + } + + public ContractCode setup(Bytes address, Class contractIntf, T instance) { + ContractCodeInstance contract = new ContractCodeInstance(address, 0, contractIntf, instance); + contractInstances.put(address, contract); + return contract; + } + + private static class ContractCodeInstance extends AbstractContractCode { + + private T instance; + + public ContractCodeInstance(Bytes address, long version, Class delaredInterface, T instance) { + super(address, version, resolveContractDefinition(delaredInterface, instance.getClass())); + this.instance = instance; + } + + private static ContractDefinition resolveContractDefinition(Class declaredIntf, Class implementedClass) { + ContractType contractType = ContractType.resolve(declaredIntf); + return new ContractDefinition(contractType, implementedClass); + } + + @Override + protected T getContractInstance() { + return instance; + } + + } + +} diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java index 08d9f381..1f3fb3ed 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java @@ -1,21 +1,37 @@ package test.com.jd.blockchain.ledger; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Random; import org.junit.Test; +import org.mockito.Mockito; +import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.BytesValueEntry; import com.jd.blockchain.ledger.EndpointRequest; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.NodeRequest; +import com.jd.blockchain.ledger.OperationResult; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.TransactionContentBody; import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionRequestBuilder; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionState; import com.jd.blockchain.ledger.UserRegisterOperation; @@ -27,9 +43,11 @@ import com.jd.blockchain.ledger.core.UserAccount; import com.jd.blockchain.ledger.core.impl.DefaultOperationHandleRegisteration; import com.jd.blockchain.ledger.core.impl.LedgerManager; import com.jd.blockchain.ledger.core.impl.LedgerTransactionalEditor; -import com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration; +import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor; +import com.jd.blockchain.service.TransactionBatchResultHandle; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.transaction.TxBuilder; +import com.jd.blockchain.utils.Bytes; public class ContractInvokingTest { static { @@ -44,7 +62,6 @@ public class ContractInvokingTest { private static final String LEDGER_KEY_PREFIX = "LDG://"; - private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate(); private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate(); private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate(); @@ -56,18 +73,69 @@ public class ContractInvokingTest { @Test public void test() { // 初始化账本到指定的存储库; - HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); + HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); // 重新加载账本; LedgerManager ledgerManager = new LedgerManager(); LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage); - - OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); - - //构建基于接口调用合约的交易请求; + + // 创建合约处理器; + ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle(); + + // 创建和加载合约实例; + BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate(); + Bytes contractAddress = contractKey.getAddress(); + TestContract contractInstance = Mockito.mock(TestContract.class); + contractInvokingHandle.setup(contractAddress, TestContract.class, contractInstance); + + // 注册合约处理器; + DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); + opReg.insertAsTopPriority(contractInvokingHandle); + + // 创建新区块的交易处理器; + LedgerBlock preBlock = ledgerRepo.getLatestBlock(); + LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, + opReg, ledgerManager); + + // 构建基于接口调用合约的交易请求,用于测试合约调用; + Random rand = new Random(); TxBuilder txBuilder = new TxBuilder(ledgerHash); -// txBuilder.contract(address, contractIntf) - + TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class); + + String asset = "AK"; + long issueAmount = rand.nextLong(); + when(contractInstance.issue(anyString(), anyLong())).thenReturn(issueAmount); + contractProxy.issue(asset, issueAmount); + + TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); + txReqBuilder.signAsEndpoint(parti0); + txReqBuilder.signAsNode(parti0); + TransactionRequest txReq = txReqBuilder.buildRequest(); + + TransactionResponse resp = txbatchProcessor.schedule(txReq); + verify(contractInstance, times(1)).issue(asset, issueAmount); + OperationResult[] opResults = resp.getOperationResults(); + assertEquals(1, opResults.length); + assertEquals(0, opResults[0].getIndex()); + + byte[] retnBytes = BinaryProtocol.encode(BytesValueEntry.fromInt64(issueAmount), BytesValue.class); + assertArrayEquals(retnBytes, opResults[0].getResult()); + + // 提交区块; + TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare(); + txResultHandle.commit(); + + LedgerBlock latestBlock = ledgerRepo.getLatestBlock(); + assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight()); + assertEquals(resp.getBlockHeight(), latestBlock.getHeight()); + assertEquals(resp.getBlockHash(), latestBlock.getHash()); + + // 再验证一次结果; + assertEquals(1, opResults.length); + assertEquals(0, opResults[0].getIndex()); + assertArrayEquals(retnBytes, opResults[0].getResult()); } private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) { diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java index ed56f49f..4d9a5ccd 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java @@ -1,5 +1,9 @@ package test.com.jd.blockchain.ledger; +import com.jd.blockchain.contract.Contract; +import com.jd.blockchain.contract.ContractEvent; + +@Contract public interface TestContract { /** @@ -9,6 +13,7 @@ public interface TestContract { * @param amount 本次发行的资产数量; * @return 资产总量; */ + @ContractEvent(name = "issue") long issue(String asset, long amount); /** @@ -17,6 +22,7 @@ public interface TestContract { * @param asset * @return */ + @ContractEvent(name = "get-amount") long getAmount(String asset); /** @@ -26,6 +32,7 @@ public interface TestContract { * @param asset * @return */ + @ContractEvent(name = "get-balance") long getBalance(String address, String asset); /** @@ -35,6 +42,7 @@ public interface TestContract { * @param asset * @param amount */ + @ContractEvent(name = "assign") void assign(String address, String asset, int amount); /** @@ -45,5 +53,6 @@ public interface TestContract { * @param asset * @param amount */ + @ContractEvent(name = "transfer") void transfer(String fromAddress, String toAddress, String asset, long amount); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java new file mode 100644 index 00000000..3375f7f3 --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java @@ -0,0 +1,49 @@ +package test.com.jd.blockchain.ledger; + +public interface TestContractImpl { + + /** + * 发行资产; + * + * @param asset 资产代码; + * @param amount 本次发行的资产数量; + * @return 资产总量; + */ + long issue(String asset, long amount); + + /** + * 获取资产总量; + * + * @param asset + * @return + */ + long getAmount(String asset); + + /** + * 获取资产余额; + * + * @param address + * @param asset + * @return + */ + long getBalance(String address, String asset); + + /** + * 向账户分配资产; + * + * @param address + * @param asset + * @param amount + */ + void assign(String address, String asset, int amount); + + /** + * 转移资产; + * + * @param fromAddress + * @param toAddress + * @param asset + * @param amount + */ + void transfer(String fromAddress, String toAddress, String asset, long amount); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAware.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAware.java new file mode 100644 index 00000000..87c51fec --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAware.java @@ -0,0 +1,11 @@ +package com.jd.blockchain.contract; + +/** + * 合约实现 {@link ContractAware} 的子接口可以监听运行时的生命周期事件; + * + * @author huanghaiquan + * + */ +public interface ContractAware { + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractException.java index 725d878a..c5382d8e 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractException.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractException.java @@ -1,18 +1,17 @@ package com.jd.blockchain.contract; -public class ContractException extends RuntimeException { - - private static final long serialVersionUID = 4338023105616639257L; +import com.jd.blockchain.ledger.LedgerException; + +public class ContractException extends LedgerException { + + private static final long serialVersionUID = -4643365435848655115L; public ContractException(String message) { super(message); } - public ContractException(String message,ErrorCodeEnum errorCodeEnum) { - super(message+","+errorCodeEnum.toString()); + public ContractException(String message, Throwable cause) { + super(message, cause); } - public ContractException(ErrorCodeEnum errorCodeEnum) { - super(errorCodeEnum.toString()); - } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAppLifecycleAwire.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractLifecycleAware.java similarity index 73% rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAppLifecycleAwire.java rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractLifecycleAware.java index c8f4f8a9..881de255 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractAppLifecycleAwire.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractLifecycleAware.java @@ -7,7 +7,7 @@ package com.jd.blockchain.contract; * @author huanghaiquan * */ -public interface ContractAppLifecycleAwire extends ContractRuntimeAwire { +public interface ContractLifecycleAware extends ContractAware { void postConstruct(); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractRuntimeAwire.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractRuntimeAwire.java deleted file mode 100644 index eab96a41..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractRuntimeAwire.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.jd.blockchain.contract; - -/** - * 合约实现 {@link ContractRuntimeAwire} 的子接口可以监听运行时的生命周期事件; - * - * @author huanghaiquan - * - */ -public interface ContractRuntimeAwire { - -} 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/contract/ContractType.java similarity index 90% rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractType.java index 34acfb5e..bbd967a1 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/contract/ContractType.java @@ -1,13 +1,10 @@ -package com.jd.blockchain.transaction; +package com.jd.blockchain.contract; import java.lang.reflect.Method; import java.util.HashMap; 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; @@ -16,7 +13,16 @@ public class ContractType { private String name; private Map events = new HashMap<>(); private Map handleMethods = new HashMap<>(); -// private Map> dataContractMap = new HashMap<>(); + + private Class declaredClass; + + public String getName() { + return name; + } + + public Class getDeclaredClass() { + return declaredClass; + } /** * 返回声明的所有事件; @@ -27,10 +33,6 @@ public class ContractType { return events.keySet(); } -// public Map> getDataContractMap() { -// return dataContractMap; -// } - /** * 返回指定方法声明的事件;
* @@ -58,6 +60,12 @@ public class ContractType { private ContractType() { } + /** + * 解析合约的声明; + * + * @param delaredInterface 声明合约的接口类型; + * @return + */ public static ContractType resolve(Class contractIntf) { // 如果是Class则首先获取其接口 diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ErrorCodeEnum.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ErrorCodeEnum.java deleted file mode 100644 index f978cb2f..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ErrorCodeEnum.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.jd.blockchain.contract; - -/** - * 给每个错误编码,编译快速定位; - * @Author zhaogw - * @Date 2018/11/8 15:32 - */ -public enum ErrorCodeEnum { - //<100为致命错误; - GATEWAY_CONNECT_ERROR(1,ErrorType.ERROR,"GatewayServiceFactory connect error.!"), - CONTRACT_CLASSPATH_NOT_SET(2,ErrorType.ERROR,"in private contract classLoader,no jar in the contract folder!"), - //其它错误从101开始计数; - AMOUNT_NEGATIVE(101,ErrorType.ALARM,"The amount is negative!"); - - - private int code; - private int type; - private String message; - - ErrorCodeEnum(int code, int type, String message) { - this.code = code; - this.type = type; - this.message = message; - } - - public int getCode() { - return code; - } - public int getType() { - return type; - } - public String getMessage() { - return message; - } - - @Override - public String toString(){ - return "code:"+code+", type:"+type+", message:"+message; - } -} - -/** - * 给错误分个类,便于汇总; - */ -class ErrorType { - public static final int ALARM = 0; - public static final int ERROR = 1; - public static final int CONTRACT_EXE = 2; - public static final int CONTRACT_COMPILE = 3; -} - - diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAwire.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAware.java similarity index 89% rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAwire.java rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAware.java index e6e07ebb..0e309dbd 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAwire.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventProcessingAware.java @@ -4,7 +4,7 @@ package com.jd.blockchain.contract; * @author huanghaiquan * */ -public interface EventProcessingAwire extends ContractRuntimeAwire { +public interface EventProcessingAware extends ContractAware { /** * 在事件处理方法执行之前调用; diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java index e18d7714..abeec3b5 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java @@ -13,17 +13,14 @@ import com.jd.blockchain.ledger.TransactionRequest; public class LocalContractEventContext implements ContractEventContext,Cloneable { private HashDigest ledgeHash; private String event; - private byte[] chainCode; private byte[] args; private TransactionRequest transactionRequest; private Set txSigners; - private Set contractOwners; private LedgerContext ledgerContext; public LocalContractEventContext(HashDigest ledgeHash, String event){ this.ledgeHash = ledgeHash; this.event = event; -// this.chainCode = chainCode; } @Override @@ -81,11 +78,6 @@ public class LocalContractEventContext implements ContractEventContext,Cloneable return this; } - public LocalContractEventContext setContractOwners(Set contractOwners) { - this.contractOwners = contractOwners; - return this; - } - public LocalContractEventContext setLedgerContext(LedgerContext ledgerContext) { this.ledgerContext = ledgerContext; return this; 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 465bb9f5..00a8edfc 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 @@ -4,6 +4,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import com.jd.blockchain.contract.ContractSerializeUtils; +import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.IllegalDataException; 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 ad4a1cd5..2d0d902a 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 @@ -5,6 +5,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.jd.blockchain.contract.EventResult; +import com.jd.blockchain.contract.ContractType; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.IllegalDataException; diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java new file mode 100644 index 00000000..77430442 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java @@ -0,0 +1,69 @@ +package test.com.jd.blockchain.ledger.data; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; +import java.util.Set; + +import org.junit.Test; + +import com.jd.blockchain.contract.ContractException; +import com.jd.blockchain.contract.ContractType; + +public class ContractTypeTest { + + /** + * 正常测试; + * @throws SecurityException + * @throws NoSuchMethodException + */ + @Test + public void normalTest() throws NoSuchMethodException, SecurityException { + ContractType contractType = ContractType.resolve(NormalContract.class); + + assertEquals(NormalContract.class, contractType.getDeclaredClass()); + assertEquals("NORMAL-CONTRACT", contractType.getName()); + + Set events = contractType.getEvents(); + assertEquals(5, events.size()); + assertTrue(events.contains("issue")); + assertTrue(events.contains("get_amount")); + assertTrue(events.contains("get_balance")); + assertTrue(events.contains("assign")); + assertTrue(events.contains("transfer")); + + Method issueMethod = contractType.getHandleMethod("issue"); + assertNotNull(issueMethod); + Method getAmountMethod = contractType.getHandleMethod("get_amount"); + assertNotNull(getAmountMethod); + Method getBalanceMethod = contractType.getHandleMethod("get_balance"); + assertNotNull(getBalanceMethod); + Method assignMethod = contractType.getHandleMethod("assign"); + assertNotNull(assignMethod); + Method transferMethod = contractType.getHandleMethod("transfer"); + assertNotNull(transferMethod); + + assertEquals("issue", contractType.getEvent(issueMethod)); + assertEquals("get_amount", contractType.getEvent(getAmountMethod)); + assertEquals("get_balance", contractType.getEvent(getBalanceMethod)); + assertEquals("assign", contractType.getEvent(assignMethod)); + assertEquals("transfer", contractType.getEvent(transferMethod)); + + Method toStringMethod = NormalContractImpl.class.getMethod("toString"); + assertNull(contractType.getEvent(toStringMethod)); + assertNull(contractType.getHandleMethod("NotExist")); + + //解析非合约声明接口类型时,应该引发异常 ContractException; + ContractException ex = null; + try { + ContractType.resolve(NormalContractImpl.class); + } catch (ContractException e) { + ex = e; + } + assertNotNull(ex); + } + +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java new file mode 100644 index 00000000..87dcd127 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java @@ -0,0 +1,58 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.contract.Contract; +import com.jd.blockchain.contract.ContractEvent; + +@Contract(name="NORMAL-CONTRACT") +public interface NormalContract { + + /** + * 发行资产; + * + * @param asset 资产代码; + * @param amount 本次发行的资产数量; + * @return 资产总量; + */ + @ContractEvent(name="issue") + long issue(String asset, long amount); + + /** + * 获取资产总量; + * + * @param asset + * @return + */ + @ContractEvent(name="get_amount") + long getAmount(String asset); + + /** + * 获取资产余额; + * + * @param address + * @param asset + * @return + */ + @ContractEvent(name="get_balance") + long getBalance(String address, String asset); + + /** + * 向账户分配资产; + * + * @param address + * @param asset + * @param amount + */ + @ContractEvent(name="assign") + void assign(String address, String asset, int amount); + + /** + * 转移资产; + * + * @param fromAddress + * @param toAddress + * @param asset + * @param amount + */ + @ContractEvent(name="transfer") + void transfer(String fromAddress, String toAddress, String asset, long amount); +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java new file mode 100644 index 00000000..ad71598d --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java @@ -0,0 +1,35 @@ +package test.com.jd.blockchain.ledger.data; + +public class NormalContractImpl implements NormalContract{ + + @Override + public long issue(String asset, long amount) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getAmount(String asset) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getBalance(String address, String asset) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void assign(String address, String asset, int amount) { + // TODO Auto-generated method stub + + } + + @Override + public void transfer(String fromAddress, String toAddress, String asset, long amount) { + // TODO Auto-generated method stub + + } + +} diff --git a/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java b/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java index c161371e..569a95a5 100644 --- a/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java +++ b/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java @@ -131,17 +131,17 @@ public abstract class RuntimeContext { private ClassLoader moduleClassLoader; - private String MainClass; + private String mainClass; public DefaultModule(String name, ClassLoader cl, String mainClass) { this.name = name; this.moduleClassLoader = cl; - this.MainClass = mainClass; + this.mainClass = mainClass; } @Override public String getMainClass() { - return MainClass; + return mainClass; } diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java index 272a55a2..02258ed2 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java @@ -6,7 +6,7 @@ import java.util.Set; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractException; -import com.jd.blockchain.contract.EventProcessingAwire; +import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.KVDataEntry; @@ -21,7 +21,7 @@ import com.jd.blockchain.ledger.KVDataObject; * @author huanghaiquan * */ -public class AssetContractImpl implements EventProcessingAwire, AssetContract { +public class AssetContractImpl implements EventProcessingAware, AssetContract { // 资产管理账户的地址; private static final String ASSET_ADDRESS = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; // 保存资产总数的键; diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/AccountContractImpl.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/AccountContractImpl.java index 421cc919..e414e2df 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/AccountContractImpl.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/AccountContractImpl.java @@ -2,11 +2,11 @@ package com.jd.blockchain.mocker.contracts; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractException; -import com.jd.blockchain.contract.EventProcessingAwire; +import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.KVDataEntry; -public class AccountContractImpl implements EventProcessingAwire, AccountContract { +public class AccountContractImpl implements EventProcessingAware, AccountContract { private ContractEventContext eventContext; diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/WriteContractImpl.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/WriteContractImpl.java index c6d6edda..83f5521d 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/WriteContractImpl.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/contracts/WriteContractImpl.java @@ -2,9 +2,9 @@ package com.jd.blockchain.mocker.contracts; import com.jd.blockchain.contract.ContractEventContext; import com.jd.blockchain.contract.ContractException; -import com.jd.blockchain.contract.EventProcessingAwire; +import com.jd.blockchain.contract.EventProcessingAware; -public class WriteContractImpl implements EventProcessingAwire, WriteContract { +public class WriteContractImpl implements EventProcessingAware, WriteContract { private ContractEventContext eventContext; 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 68e8488d..ec321728 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 @@ -1,22 +1,28 @@ package com.jd.blockchain.mocker.handler; -import com.jd.blockchain.contract.*; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.jd.blockchain.contract.ContractEventContext; +import com.jd.blockchain.contract.ContractException; +import com.jd.blockchain.contract.ContractSerializeUtils; +import com.jd.blockchain.contract.EventProcessingAware; +import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.core.*; +import com.jd.blockchain.ledger.core.LedgerDataSet; +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.LedgerManager; 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; -import java.util.concurrent.ConcurrentHashMap; public class MockerContractExeHandle implements OperationHandle { @@ -44,10 +50,10 @@ public class MockerContractExeHandle implements OperationHandle { contractOP.getEvent(), requestContext.getRequest(), ledgerContext); Object instance = executorProxy.getInstance(); - EventProcessingAwire awire = null; + EventProcessingAware awire = null; - if (instance instanceof EventProcessingAwire) { - awire = (EventProcessingAwire) instance; + if (instance instanceof EventProcessingAware) { + awire = (EventProcessingAware) instance; awire.beforeEvent(contractEventContext); } @@ -70,10 +76,10 @@ public class MockerContractExeHandle implements OperationHandle { return ContractSerializeUtils.serialize(result); } - @Override - public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { - 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) {