@@ -3,14 +3,11 @@ package com.jd.blockchain.contract.engine; | |||||
import com.jd.blockchain.contract.ContractEventContext; | import com.jd.blockchain.contract.ContractEventContext; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import java.util.concurrent.CompletableFuture; | |||||
import java.util.concurrent.Future; | |||||
public interface ContractCode { | public interface ContractCode { | ||||
Bytes getAddress(); | Bytes getAddress(); | ||||
long getVersion(); | long getVersion(); | ||||
void processEvent(ContractEventContext eventContext, CompletableFuture<String> execReturn); | |||||
byte[] processEvent(ContractEventContext eventContext); | |||||
} | } |
@@ -1,6 +1,5 @@ | |||||
package com.jd.blockchain.contract.engine; | package com.jd.blockchain.contract.engine; | ||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
/** | /** | ||||
@@ -27,9 +26,9 @@ public interface ContractEngine { | |||||
* 如果已经存在,则直接返回已有实例; | * 如果已经存在,则直接返回已有实例; | ||||
* | * | ||||
* @param address | * @param address | ||||
* @param code | |||||
* @param codeBytes | |||||
* @return | * @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; | package com.jd.blockchain.contract.jvm; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.util.List; | |||||
import java.util.concurrent.Callable; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.util.ReflectionUtils; | import org.springframework.util.ReflectionUtils; | ||||
import com.jd.blockchain.binaryproto.DataContract; | |||||
import com.jd.blockchain.contract.ContractEventContext; | 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.engine.ContractCode; | ||||
import com.jd.blockchain.runtime.Module; | import com.jd.blockchain.runtime.Module; | ||||
import com.jd.blockchain.transaction.ContractType; | import com.jd.blockchain.transaction.ContractType; | ||||
import com.jd.blockchain.utils.Bytes; | 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 | * contract code based jvm | ||||
@@ -27,14 +25,22 @@ public class JavaContractCode implements ContractCode { | |||||
private Module codeModule; | private Module codeModule; | ||||
private Bytes address; | private Bytes address; | ||||
private long version; | private long version; | ||||
private ContractEventContext contractEventContext; | |||||
private Class<?> contractClass; | |||||
private ContractType contractType; | private ContractType contractType; | ||||
public JavaContractCode(Bytes address, long version, Module codeModule) { | public JavaContractCode(Bytes address, long version, Module codeModule) { | ||||
this.address = address; | this.address = address; | ||||
this.version = version; | this.version = version; | ||||
this.codeModule = codeModule; | this.codeModule = codeModule; | ||||
init(); | |||||
} | |||||
private void init() { | |||||
String contractClassName = codeModule.getMainClass(); | |||||
this.contractClass = codeModule.loadClass(contractClassName); | |||||
this.contractType = ContractType.resolve(contractClass); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -48,89 +54,77 @@ public class JavaContractCode implements ContractCode { | |||||
} | } | ||||
@Override | @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 { | 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 | @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 { | public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration { | ||||
private List<OperationHandle> opHandles = new ArrayList<>(); | private List<OperationHandle> opHandles = new ArrayList<>(); | ||||
// private UserRegisterOperationHandle userRegHandle; | |||||
// | |||||
// private DataAccountRegisterOperationHandle dataAccRegHandle; | |||||
// | |||||
// private DataAccountKVSetOperationHandle dataAccKVSetHandle; | |||||
// | |||||
// private ContractCodeDeployOperationHandle contractDplHandle; | |||||
// | |||||
// private ContractEventSendOperationHandle contractEvtSendHandle; | |||||
public DefaultOperationHandleRegisteration() { | public DefaultOperationHandleRegisteration() { | ||||
initDefaultHandles(); | initDefaultHandles(); | ||||
} | } | ||||
@@ -40,25 +29,30 @@ public class DefaultOperationHandleRegisteration implements OperationHandleRegis | |||||
/** | /** | ||||
* 针对不采用bean依赖注入的方式来处理; | * 针对不采用bean依赖注入的方式来处理; | ||||
*/ | */ | ||||
private void initDefaultHandles(){ | |||||
private void initDefaultHandles() { | |||||
opHandles.add(new DataAccountKVSetOperationHandle()); | opHandles.add(new DataAccountKVSetOperationHandle()); | ||||
opHandles.add(new DataAccountRegisterOperationHandle()); | opHandles.add(new DataAccountRegisterOperationHandle()); | ||||
opHandles.add(new UserRegisterOperationHandle()); | opHandles.add(new UserRegisterOperationHandle()); | ||||
opHandles.add(new ContractCodeDeployOperationHandle()); | opHandles.add(new ContractCodeDeployOperationHandle()); | ||||
opHandles.add(new ContractEventSendOperationHandle()); | 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 | @Override | ||||
public OperationHandle getHandle(Class<?> operationType) { | public OperationHandle getHandle(Class<?> operationType) { | ||||
@@ -69,6 +63,5 @@ public class DefaultOperationHandleRegisteration implements OperationHandleRegis | |||||
} | } | ||||
throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!"); | 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(); | 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 | @Override | ||||
public boolean support(Class<?> operationType) { | public boolean support(Class<?> operationType) { | ||||
return ContractEventSendOperation.class.isAssignableFrom(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; | 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) { | if (gatewayKeypair != null) { | ||||
txReqBuilder.signAsNode(gatewayKeypair); | txReqBuilder.signAsNode(gatewayKeypair); | ||||
} | } | ||||
return txReqBuilder.buildRequest(); | 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; | private TransactionRequest transactionRequest; | ||||
// 采用基于内存的 Storage; | // 采用基于内存的 Storage; | ||||
MemoryKVStorage storage = new MemoryKVStorage(); | |||||
private MemoryKVStorage storage = new MemoryKVStorage(); | |||||
@Test | @Test | ||||
public void testContractOperations() { | |||||
public void testTxReqProcess() { | |||||
// 初始化账本到指定的存储库; | // 初始化账本到指定的存储库; | ||||
ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); | ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3); | ||||
@@ -2,6 +2,8 @@ package com.jd.blockchain.contract; | |||||
public class ContractException extends RuntimeException { | public class ContractException extends RuntimeException { | ||||
private static final long serialVersionUID = 4338023105616639257L; | |||||
public ContractException(String message) { | public ContractException(String message) { | ||||
super(message); | super(message); | ||||
} | } | ||||
@@ -21,19 +21,6 @@ public interface EventProcessingAwire extends ContractRuntimeAwire { | |||||
* @param error | * @param error | ||||
* 错误;如果事件处理正常结束,则此参数为 null;如果事件处理发生了错误,此参数非空; | * 错误;如果事件处理正常结束,则此参数为 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(); | String getName(); | ||||
Class<?> loadClass(String className); | Class<?> loadClass(String className); | ||||
InputStream loadResourceAsStream(String name); | InputStream loadResourceAsStream(String name); | ||||
String getMainClass(); | String getMainClass(); | ||||
@@ -171,17 +171,7 @@ public class AssetContractImpl implements EventProcessingAwire, AssetContract { | |||||
* com.jd.blockchain.contract.model.ContractError) | * com.jd.blockchain.contract.model.ContractError) | ||||
*/ | */ | ||||
@Override | @Override | ||||
public void postEvent(ContractEventContext eventContext, ContractException error) { | |||||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||||
this.eventContext = null; | this.eventContext = null; | ||||
} | } | ||||
@Override | |||||
public void postEvent(ContractException error) { | |||||
} | |||||
@Override | |||||
public void postEvent() { | |||||
} | |||||
} | } |
@@ -8,12 +8,39 @@ | |||||
*/ | */ | ||||
package test.com.jd.blockchain.intgr; | 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.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.HashDigest; | 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.LedgerRepository; | ||||
import com.jd.blockchain.ledger.core.impl.LedgerManager; | import com.jd.blockchain.ledger.core.impl.LedgerManager; | ||||
import com.jd.blockchain.sdk.BlockchainService; | 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.storage.service.DbConnectionFactory; | ||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | ||||
import com.jd.blockchain.utils.Bytes; | 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.concurrent.ThreadInvoker; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | 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 | * @author shaozhuguang | ||||
@@ -1,12 +1,32 @@ | |||||
package test.com.jd.blockchain.intgr; | 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.ConsensusProvider; | ||||
import com.jd.blockchain.consensus.ConsensusSettings; | import com.jd.blockchain.consensus.ConsensusSettings; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | 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.ledger.core.LedgerRepository; | ||||
import com.jd.blockchain.sdk.BlockchainService; | import com.jd.blockchain.sdk.BlockchainService; | ||||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | 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.tools.keygen.KeyGenCommand; | ||||
import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | 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.IntegratedContext.Node; | ||||
import test.com.jd.blockchain.intgr.contract.AssetContract; | import test.com.jd.blockchain.intgr.contract.AssetContract; | ||||
import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest; | import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest; | ||||
import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest.NodeWebContext; | 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 | @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 | @Override | ||||
public void postEvent(ContractEventContext eventContext, ContractException error) { | |||||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||||
System.out.println("----- postEvent1 -----"); | 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(); | executorProxy.invoke(); | ||||
// After处理过程 | // After处理过程 | ||||
eventProcessingAwire.postEvent(); | |||||
eventProcessingAwire.postEvent(contractEventContext, null); | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
eventProcessingAwire.postEvent(new ContractException(e.getMessage())); | |||||
eventProcessingAwire.postEvent(contractEventContext, new ContractException(e.getMessage())); | |||||
} finally { | } finally { | ||||
removeExecutorProxy(txHash); | removeExecutorProxy(txHash); | ||||
} | } | ||||