| @@ -3,14 +3,11 @@ 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(); | |||
| long getVersion(); | |||
| void processEvent(ContractEventContext eventContext, CompletableFuture<String> execReturn); | |||
| byte[] processEvent(ContractEventContext eventContext); | |||
| } | |||
| @@ -1,6 +1,5 @@ | |||
| package com.jd.blockchain.contract.engine; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| /** | |||
| @@ -27,9 +26,9 @@ public interface ContractEngine { | |||
| * 如果已经存在,则直接返回已有实例; | |||
| * | |||
| * @param address | |||
| * @param code | |||
| * @param codeBytes | |||
| * @return | |||
| */ | |||
| ContractCode setupContract(Bytes address, long version, byte[] code); | |||
| ContractCode setupContract(Bytes address, long version, byte[] codeBytes); | |||
| } | |||
| @@ -1,21 +1,19 @@ | |||
| package com.jd.blockchain.contract.jvm; | |||
| import java.lang.reflect.Method; | |||
| import java.util.List; | |||
| import java.util.concurrent.Callable; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.util.ReflectionUtils; | |||
| import com.jd.blockchain.binaryproto.DataContract; | |||
| 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.runtime.Module; | |||
| import com.jd.blockchain.transaction.ContractType; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.IllegalDataException; | |||
| import java.util.concurrent.CompletableFuture; | |||
| import java.util.concurrent.Future; | |||
| /** | |||
| * contract code based jvm | |||
| @@ -27,14 +25,22 @@ public class JavaContractCode implements ContractCode { | |||
| private Module codeModule; | |||
| private Bytes address; | |||
| private long version; | |||
| private ContractEventContext contractEventContext; | |||
| private Class<?> contractClass; | |||
| private ContractType contractType; | |||
| public JavaContractCode(Bytes address, long version, Module 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); | |||
| } | |||
| @Override | |||
| @@ -48,89 +54,77 @@ public class JavaContractCode implements ContractCode { | |||
| } | |||
| @Override | |||
| public void processEvent(ContractEventContext eventContext, CompletableFuture<String> execReturn) { | |||
| this.contractEventContext = eventContext; | |||
| codeModule.execute(new ContractExecution(execReturn)); | |||
| } | |||
| private Object resolveArgs(byte[] args, List<DataContract> dataContractList) { | |||
| if(args == null || args.length == 0){ | |||
| return null; | |||
| } | |||
| //TODO: Not implemented; | |||
| throw new IllegalStateException("Not implemented!"); | |||
| // return ContractSerializeUtils.deserializeMethodParam(args,dataContractList); | |||
| public byte[] processEvent(ContractEventContext eventContext) { | |||
| return codeModule.call(new ContractExecution(eventContext)); | |||
| } | |||
| class ContractExecution implements Runnable { | |||
| private class ContractExecution implements Callable<byte[]> { | |||
| private CompletableFuture<String> contractReturn; | |||
| private ContractEventContext eventContext; | |||
| public ContractExecution(CompletableFuture<String> contractReturn) { | |||
| this.contractReturn = contractReturn; | |||
| public ContractExecution(ContractEventContext contractEventContext) { | |||
| this.eventContext = contractEventContext; | |||
| } | |||
| public void run() { | |||
| LOGGER.info("ContractThread execute()."); | |||
| @Override | |||
| public byte[] call() throws Exception { | |||
| EventProcessingAwire evtProcAwire = null; | |||
| Object retn = null; | |||
| Exception error = null; | |||
| try { | |||
| // 执行预处理; | |||
| long startTime = System.currentTimeMillis(); | |||
| String contractClassName = codeModule.getMainClass(); | |||
| Class myClass = codeModule.loadClass(contractClassName); | |||
| Object contractMainClassObj = myClass.newInstance();// 合约主类生成的类实例; | |||
| Method beforeMth_ = myClass.getMethod("beforeEvent", | |||
| codeModule.loadClass(ContractEventContext.class.getName())); | |||
| ReflectionUtils.invokeMethod(beforeMth_, contractMainClassObj, contractEventContext); | |||
| LOGGER.info("beforeEvent,耗时:" + (System.currentTimeMillis() - startTime)); | |||
| Object contractInstance = contractClass.newInstance();// 合约主类生成的类实例; | |||
| if (contractInstance instanceof EventProcessingAwire) { | |||
| evtProcAwire = (EventProcessingAwire) contractInstance; | |||
| } | |||
| // Method eventMethod = this.getMethodByAnno(contractMainClassObj, contractEventContext.getEvent()); | |||
| startTime = System.currentTimeMillis(); | |||
| if (evtProcAwire != null) { | |||
| evtProcAwire.beforeEvent(eventContext); | |||
| } | |||
| // 反序列化参数; | |||
| contractType = ContractType.resolve(myClass); | |||
| Method handleMethod = contractType.getHandleMethod(contractEventContext.getEvent()); | |||
| Method handleMethod = contractType.getHandleMethod(eventContext.getEvent()); | |||
| if (handleMethod == null){ | |||
| throw new IllegalDataException("don't get this method by it's @ContractEvent."); | |||
| 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())); | |||
| } | |||
| //TODO: Not implemented; | |||
| // Object args = resolveArgs(contractEventContext.getArgs(), | |||
| // contractType.getDataContractMap().get(handleMethod)); | |||
| // | |||
| // Object[] params = null; | |||
| // if(args.getClass().isArray()){ | |||
| // params = (Object[])args; | |||
| // } | |||
| // ReflectionUtils.invokeMethod(handleMethod, contractMainClassObj, params); | |||
| LOGGER.info("合约执行,耗时:" + (System.currentTimeMillis() - startTime)); | |||
| Object[] args = resolveArgs(); | |||
| retn = ReflectionUtils.invokeMethod(handleMethod, contractInstance, args); | |||
| Method mth2 = myClass.getMethod("postEvent"); | |||
| startTime = System.currentTimeMillis(); | |||
| } catch (Exception e) { | |||
| error = e; | |||
| } | |||
| ReflectionUtils.invokeMethod(mth2, contractMainClassObj); | |||
| 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; | |||
| } | |||
| LOGGER.info("postEvent,耗时:" + (System.currentTimeMillis() - startTime)); | |||
| byte[] retnBytes = resolveResult(retn); | |||
| return retnBytes; | |||
| } | |||
| // 填充return结果 | |||
| if (this.contractReturn != null) { | |||
| //TODO: Not implemented; | |||
| throw new IllegalStateException("Not implemented!"); | |||
| // this.contractReturn.complete(contractReturn); | |||
| } | |||
| } catch (NoSuchMethodException e) { | |||
| throw new IllegalArgumentException(e.getMessage()); | |||
| } catch (Exception e) { | |||
| throw new IllegalDataException(e.getMessage()); | |||
| private byte[] resolveResult(Object retn) { | |||
| if (retn == null) { | |||
| return null; | |||
| } | |||
| // TODO: resolve result in bytes; | |||
| return null; | |||
| } | |||
| private Object[] resolveArgs() { | |||
| // TODO Auto-generated method stub | |||
| throw new IllegalStateException("Not implemented!"); | |||
| } | |||
| } | |||
| @@ -17,17 +17,7 @@ public class ReadContractImpl implements EventProcessingAwire, ReadContract { | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, ContractException error) { | |||
| } | |||
| @Override | |||
| public void postEvent(ContractException error) { | |||
| } | |||
| @Override | |||
| public void postEvent() { | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| @@ -21,18 +21,7 @@ import com.jd.blockchain.ledger.core.impl.handles.UserRegisterOperationHandle; | |||
| public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration { | |||
| private List<OperationHandle> opHandles = new ArrayList<>(); | |||
| // private UserRegisterOperationHandle userRegHandle; | |||
| // | |||
| // private DataAccountRegisterOperationHandle dataAccRegHandle; | |||
| // | |||
| // private DataAccountKVSetOperationHandle dataAccKVSetHandle; | |||
| // | |||
| // private ContractCodeDeployOperationHandle contractDplHandle; | |||
| // | |||
| // private ContractEventSendOperationHandle contractEvtSendHandle; | |||
| public DefaultOperationHandleRegisteration() { | |||
| initDefaultHandles(); | |||
| } | |||
| @@ -40,25 +29,30 @@ public class DefaultOperationHandleRegisteration implements OperationHandleRegis | |||
| /** | |||
| * 针对不采用bean依赖注入的方式来处理; | |||
| */ | |||
| private void initDefaultHandles(){ | |||
| private void initDefaultHandles() { | |||
| opHandles.add(new DataAccountKVSetOperationHandle()); | |||
| opHandles.add(new DataAccountRegisterOperationHandle()); | |||
| opHandles.add(new UserRegisterOperationHandle()); | |||
| opHandles.add(new ContractCodeDeployOperationHandle()); | |||
| opHandles.add(new ContractEventSendOperationHandle()); | |||
| } | |||
| // @PostConstruct | |||
| // private void init() { | |||
| // opHandles.add(dataAccKVSetHandle); | |||
| // opHandles.add(dataAccRegHandle); | |||
| // opHandles.add(userRegHandle); | |||
| // opHandles.add(contractDplHandle); | |||
| // opHandles.add(contractEvtSendHandle); | |||
| // } | |||
| /* (non-Javadoc) | |||
| * @see com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle(java.lang.Class) | |||
| /** | |||
| * 以最高优先级插入一个操作处理器; | |||
| * | |||
| * @param handle | |||
| */ | |||
| public void insertAsTopPriority(OperationHandle handle) { | |||
| opHandles.remove(handle); | |||
| opHandles.add(0, handle); | |||
| } | |||
| /* | |||
| * (non-Javadoc) | |||
| * | |||
| * @see | |||
| * com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle( | |||
| * java.lang.Class) | |||
| */ | |||
| @Override | |||
| public OperationHandle getHandle(Class<?> operationType) { | |||
| @@ -69,6 +63,5 @@ public class DefaultOperationHandleRegisteration implements OperationHandleRegis | |||
| } | |||
| throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!"); | |||
| } | |||
| } | |||
| @@ -31,24 +31,14 @@ public class ContractEventSendOperationHandle implements OperationHandle { | |||
| JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); | |||
| } | |||
| @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<String> contractReturn) { | |||
| @Override | |||
| public byte[] process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, | |||
| LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) { | |||
| ContractEventSendOperation contractOP = (ContractEventSendOperation) op; | |||
| // 先从账本校验合约的有效性; | |||
| // 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行; | |||
| @@ -83,7 +73,7 @@ public class ContractEventSendOperationHandle implements OperationHandle { | |||
| } | |||
| // 处理合约事件; | |||
| contractCode.processEvent(localContractEventContext, contractReturn); | |||
| return contractCode.processEvent(localContractEventContext); | |||
| } | |||
| } | |||
| @@ -0,0 +1,82 @@ | |||
| //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<Bytes, Object> contractInstances = new ConcurrentHashMap<Bytes, Object>(); | |||
| // | |||
| // @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<String> 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); | |||
| // } | |||
| // | |||
| //} | |||
| @@ -0,0 +1,110 @@ | |||
| package test.com.jd.blockchain.ledger; | |||
| import static org.junit.Assert.*; | |||
| import org.junit.Test; | |||
| 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.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.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionContentBody; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.UserRegisterOperation; | |||
| import com.jd.blockchain.ledger.core.LedgerDataSet; | |||
| import com.jd.blockchain.ledger.core.LedgerEditor; | |||
| import com.jd.blockchain.ledger.core.LedgerRepository; | |||
| import com.jd.blockchain.ledger.core.LedgerTransactionContext; | |||
| 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.storage.service.utils.MemoryKVStorage; | |||
| import com.jd.blockchain.transaction.TxBuilder; | |||
| public class ContractInvokingTest { | |||
| static { | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionContentBody.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(NodeRequest.class); | |||
| DataContractRegistry.register(EndpointRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| DataContractRegistry.register(UserRegisterOperation.class); | |||
| } | |||
| 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(); | |||
| private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 采用基于内存的 Storage; | |||
| private MemoryKVStorage storage = new MemoryKVStorage(); | |||
| @Test | |||
| public void test() { | |||
| // 初始化账本到指定的存储库; | |||
| HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); | |||
| // 重新加载账本; | |||
| LedgerManager ledgerManager = new LedgerManager(); | |||
| LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage); | |||
| OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); | |||
| //构建基于接口调用合约的交易请求; | |||
| TxBuilder txBuilder = new TxBuilder(ledgerHash); | |||
| // txBuilder.contract(address, contractIntf) | |||
| } | |||
| private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) { | |||
| // 创建初始化配置; | |||
| LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys); | |||
| // 创建账本; | |||
| LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage); | |||
| TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null); | |||
| LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq); | |||
| LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); | |||
| for (int i = 0; i < partiKeys.length; i++) { | |||
| UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(), | |||
| partiKeys[i].getPubKey()); | |||
| userAccount.setProperty("Name", "参与方-" + i, -1); | |||
| userAccount.setProperty("Share", "" + (10 + i), -1); | |||
| } | |||
| LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); | |||
| assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); | |||
| assertEquals(0, tx.getBlockHeight()); | |||
| LedgerBlock block = ldgEdt.prepare(); | |||
| assertEquals(0, block.getHeight()); | |||
| assertNotNull(block.getHash()); | |||
| assertNull(block.getPreviousHash()); | |||
| assertEquals(block.getHash(), block.getLedgerHash()); | |||
| // 提交数据,写入存储; | |||
| ldgEdt.commit(); | |||
| HashDigest ledgerHash = block.getHash(); | |||
| return ledgerHash; | |||
| } | |||
| } | |||
| @@ -96,6 +96,7 @@ public class LedgerTestUtils { | |||
| if (gatewayKeypair != null) { | |||
| txReqBuilder.signAsNode(gatewayKeypair); | |||
| } | |||
| return txReqBuilder.buildRequest(); | |||
| } | |||
| @@ -0,0 +1,49 @@ | |||
| package test.com.jd.blockchain.ledger; | |||
| public interface TestContract { | |||
| /** | |||
| * 发行资产; | |||
| * | |||
| * @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); | |||
| } | |||
| @@ -57,10 +57,10 @@ public class TransactionBatchProcessorTest { | |||
| private TransactionRequest transactionRequest; | |||
| // 采用基于内存的 Storage; | |||
| MemoryKVStorage storage = new MemoryKVStorage(); | |||
| private MemoryKVStorage storage = new MemoryKVStorage(); | |||
| @Test | |||
| public void testContractOperations() { | |||
| public void testTxReqProcess() { | |||
| // 初始化账本到指定的存储库; | |||
| ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); | |||
| @@ -2,6 +2,8 @@ package com.jd.blockchain.contract; | |||
| public class ContractException extends RuntimeException { | |||
| private static final long serialVersionUID = 4338023105616639257L; | |||
| public ContractException(String message) { | |||
| super(message); | |||
| } | |||
| @@ -21,19 +21,6 @@ public interface EventProcessingAwire extends ContractRuntimeAwire { | |||
| * @param error | |||
| * 错误;如果事件处理正常结束,则此参数为 null;如果事件处理发生了错误,此参数非空; | |||
| */ | |||
| void postEvent(ContractEventContext eventContext, ContractException error); | |||
| void postEvent(ContractEventContext eventContext, Exception error); | |||
| /** | |||
| * 在事件处理方法成功执行之后调用; | |||
| * | |||
| * @param error | |||
| * 错误;如果事件处理正常结束,则此参数为 null;如果事件处理发生了错误,此参数非空; | |||
| */ | |||
| void postEvent(ContractException error); | |||
| /** | |||
| * 在事件处理方法成功执行之后调用; | |||
| */ | |||
| void postEvent(); | |||
| } | |||
| @@ -10,7 +10,7 @@ public interface Module { | |||
| String getName(); | |||
| Class<?> loadClass(String className); | |||
| InputStream loadResourceAsStream(String name); | |||
| String getMainClass(); | |||
| @@ -171,17 +171,7 @@ public class AssetContractImpl implements EventProcessingAwire, AssetContract { | |||
| * com.jd.blockchain.contract.model.ContractError) | |||
| */ | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, ContractException error) { | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| this.eventContext = null; | |||
| } | |||
| @Override | |||
| public void postEvent(ContractException error) { | |||
| } | |||
| @Override | |||
| public void postEvent() { | |||
| } | |||
| } | |||
| @@ -8,12 +8,39 @@ | |||
| */ | |||
| package test.com.jd.blockchain.intgr; | |||
| import static org.junit.Assert.assertArrayEquals; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertNotNull; | |||
| import static org.junit.Assert.assertTrue; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.net.URL; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.Random; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import java.util.concurrent.atomic.AtomicLong; | |||
| import org.apache.commons.io.FileUtils; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| 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.*; | |||
| import com.jd.blockchain.ledger.core.LedgerManage; | |||
| 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; | |||
| @@ -21,31 +48,9 @@ import com.jd.blockchain.storage.service.DbConnection; | |||
| import com.jd.blockchain.storage.service.DbConnectionFactory; | |||
| import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.codec.HexUtils; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import org.apache.commons.io.FileUtils; | |||
| import org.junit.Assert; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import test.com.jd.blockchain.intgr.contract.AssetContract; | |||
| import test.com.jd.blockchain.intgr.contract.AssetContract2; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.math.BigDecimal; | |||
| import java.net.URL; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| import java.util.Random; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import java.util.concurrent.atomic.AtomicLong; | |||
| import static org.junit.Assert.*; | |||
| /** | |||
| * | |||
| * @author shaozhuguang | |||
| @@ -1,12 +1,32 @@ | |||
| package test.com.jd.blockchain.intgr; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertNotNull; | |||
| import static org.junit.Assert.assertTrue; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Properties; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import org.junit.Test; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import com.jd.blockchain.consensus.ConsensusProvider; | |||
| import com.jd.blockchain.consensus.ConsensusSettings; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.LedgerBlock; | |||
| import com.jd.blockchain.ledger.LedgerInfo; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.ledger.core.LedgerRepository; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| @@ -17,22 +37,12 @@ import com.jd.blockchain.tools.initializer.Prompter; | |||
| import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import org.junit.Test; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import test.com.jd.blockchain.intgr.IntegratedContext.Node; | |||
| import test.com.jd.blockchain.intgr.contract.AssetContract; | |||
| import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest; | |||
| import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest.NodeWebContext; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.Properties; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import static org.junit.Assert.*; | |||
| /** | |||
| * 测试合约,提交后不立即进行验证,因为此时可能还没有完成正式结块; | |||
| */ | |||
| @@ -65,17 +65,8 @@ public class AccountContractImpl implements EventProcessingAwire, AccountContrac | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, ContractException error) { | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| @Override | |||
| public void postEvent(ContractException error) { | |||
| } | |||
| @Override | |||
| public void postEvent() { | |||
| } | |||
| } | |||
| @@ -25,17 +25,8 @@ public class WriteContractImpl implements EventProcessingAwire, WriteContract { | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, ContractException error) { | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| System.out.println("----- postEvent1 -----"); | |||
| } | |||
| @Override | |||
| public void postEvent(ContractException error) { | |||
| System.out.println("----- postEvent2 -----"); | |||
| } | |||
| @Override | |||
| public void postEvent() { | |||
| System.out.println("----- postEvent3 -----"); | |||
| } | |||
| } | |||
| @@ -52,9 +52,9 @@ public class MockerContractExeHandle implements OperationHandle { | |||
| executorProxy.invoke(); | |||
| // After处理过程 | |||
| eventProcessingAwire.postEvent(); | |||
| eventProcessingAwire.postEvent(contractEventContext, null); | |||
| } catch (Exception e) { | |||
| eventProcessingAwire.postEvent(new ContractException(e.getMessage())); | |||
| eventProcessingAwire.postEvent(contractEventContext, new ContractException(e.getMessage())); | |||
| } finally { | |||
| removeExecutorProxy(txHash); | |||
| } | |||