Browse Source

Merge branch 'contract-return' into feature/contract_invocation

# Conflicts:
#	source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
#	source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
#	source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
tags/1.0.0
huanghaiquan 6 years ago
parent
commit
2c4bf3318d
31 changed files with 432 additions and 54 deletions
  1. +4
    -0
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  2. +4
    -2
      source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java
  3. +25
    -2
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  4. +62
    -0
      source/contract/contract-samples/pom.xml
  5. +13
    -0
      source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContract.java
  6. +55
    -0
      source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java
  7. +2
    -1
      source/contract/pom.xml
  8. +1
    -1
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  9. +6
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
  10. +10
    -6
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
  11. +4
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
  12. +45
    -10
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
  13. +16
    -5
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
  14. +2
    -2
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
  15. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java
  16. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
  17. +17
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractReturnMessage.java
  18. +41
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractReturnMessageData.java
  19. +7
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java
  20. +11
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java
  21. +13
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java
  22. +17
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java
  23. +26
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.java
  24. +13
    -4
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java
  25. +5
    -0
      source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java
  26. +6
    -9
      source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/AbstractModule.java
  27. +7
    -0
      source/test/test-integration/pom.xml
  28. +16
    -0
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java
  29. BIN
      source/test/test-integration/src/test/resources/contract-read.jar
  30. +1
    -1
      source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java
  31. +1
    -1
      source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java

+ 4
- 0
source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java View File

@@ -30,6 +30,8 @@ public interface DataCodes {

public static final int TX_CONTENT_BODY = 0x220;

public static final int TX_RETURN_MESSAGE = 0x230;

public static final int TX_OP = 0x300;

public static final int TX_OP_LEDGER_INIT = 0x301;
@@ -79,6 +81,8 @@ public interface DataCodes {

public static final int DATA = 0x900;

public static final int CONTRACT_RETURN = 0xA22;

public static final int HASH = 0xB00;

public static final int HASH_OBJECT = 0xB10;


+ 4
- 2
source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java View File

@@ -3,12 +3,14 @@ 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);

void processEvent(ContractEventContext eventContext, CompletableFuture<String> execReturn);
}

+ 25
- 2
source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java View File

@@ -14,6 +14,8 @@ 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
@@ -46,9 +48,9 @@ public class JavaContractCode implements ContractCode {
}

@Override
public void processEvent(ContractEventContext eventContext) {
public void processEvent(ContractEventContext eventContext, CompletableFuture<String> execReturn) {
this.contractEventContext = eventContext;
codeModule.execute(new ContractExecution());
codeModule.execute(new ContractExecution(execReturn));
}

private Object resolveArgs(byte[] args, List<DataContract> dataContractList) {
@@ -61,6 +63,13 @@ public class JavaContractCode implements ContractCode {
}

class ContractExecution implements Runnable {

private CompletableFuture<String> contractReturn;

public ContractExecution(CompletableFuture<String> contractReturn) {
this.contractReturn = contractReturn;
}

public void run() {
LOGGER.info("ContractThread execute().");
try {
@@ -68,12 +77,16 @@ public class JavaContractCode implements ContractCode {
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));

// Method eventMethod = this.getMethodByAnno(contractMainClassObj, contractEventContext.getEvent());
@@ -81,7 +94,9 @@ public class JavaContractCode implements ContractCode {

// 反序列化参数;
contractType = ContractType.resolve(myClass);

Method handleMethod = contractType.getHandleMethod(contractEventContext.getEvent());

if (handleMethod == null){
throw new IllegalDataException("don't get this method by it's @ContractEvent.");
}
@@ -98,9 +113,17 @@ public class JavaContractCode implements ContractCode {
LOGGER.info("合约执行,耗时:" + (System.currentTimeMillis() - startTime));

Method mth2 = myClass.getMethod("postEvent");

startTime = System.currentTimeMillis();

ReflectionUtils.invokeMethod(mth2, contractMainClassObj);

LOGGER.info("postEvent,耗时:" + (System.currentTimeMillis() - startTime));

// 填充return结果
if (this.contractReturn != null) {
this.contractReturn.complete(contractReturn);
}
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e.getMessage());
} catch (Exception e) {


+ 62
- 0
source/contract/contract-samples/pom.xml View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>contract</artifactId>
<groupId>com.jd.blockchain</groupId>
<version>0.9.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>contract-samples</artifactId>

<name>contract-samples</name>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger-model</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto-framework</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>contract</finalName>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.jd.blockchain.contract.ReadContractImpl</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>

+ 13
- 0
source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContract.java View File

@@ -0,0 +1,13 @@
package com.jd.blockchain.contract;


@Contract
public interface ReadContract {

@ContractEvent(name = "read-key")
String read(String address, String key);

@ContractEvent(name = "version-key")
Long readVersion(String address, String key);
}


+ 55
- 0
source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java View File

@@ -0,0 +1,55 @@
package com.jd.blockchain.contract;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.KVDataEntry;

@Contract
public class ReadContractImpl implements EventProcessingAwire, ReadContract {

private ContractEventContext eventContext;

private HashDigest ledgerHash;

@Override
public void beforeEvent(ContractEventContext eventContext) {
this.eventContext = eventContext;
this.ledgerHash = eventContext.getCurrentLedgerHash();
}

@Override
public void postEvent(ContractEventContext eventContext, ContractException error) {

}

@Override
public void postEvent(ContractException error) {

}

@Override
public void postEvent() {

}

@Override
@ContractEvent(name = "read-key")
public String read(String address, String key) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);

if (kvDataEntries != null && kvDataEntries.length == 1) {
return kvDataEntries[0].getValue().toString();
}
return null;
}

@Override
@ContractEvent(name = "version-key")
public Long readVersion(String address, String key) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);

if (kvDataEntries != null && kvDataEntries.length == 1) {
return kvDataEntries[0].getVersion();
}
return -1L;
}
}

+ 2
- 1
source/contract/pom.xml View File

@@ -13,6 +13,7 @@
<module>contract-framework</module>
<module>contract-jvm</module>
<module>contract-maven-plugin</module>
</modules>
<module>contract-samples</module>
</modules>
</project>

+ 1
- 1
source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java View File

@@ -55,7 +55,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService {

// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants")
@Override
public ParticipantNode[] getConsensusParticipants(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
return peerService.getQueryService().getConsensusParticipants(ledgerHash);
}



+ 6
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java View File

@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.TransactionReturnMessage;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionRequest;
@@ -30,19 +31,21 @@ public interface LedgerTransactionContext {
* 提交对账本数据的修改,以指定的交易状态提交交易;
*
* @param txResult
* @param returnMessage
*
* @return
*/
LedgerTransaction commit(TransactionState txResult);
LedgerTransaction commit(TransactionState txResult, TransactionReturnMessage returnMessage);

/**
* 抛弃对账本数据的修改,以指定的交易状态提交交易;<br>
*
* 通常来说,当在开启事务之后,修改账本或者尝试提交交易({@link #commit(TransactionState)})时发生错误,都应该抛弃数据,通过此方法记录一个表示错误状态的交易;
* 通常来说,当在开启事务之后,修改账本或者尝试提交交易({@link #commit(TransactionState, TransactionReturnMessage)})时发生错误,都应该抛弃数据,通过此方法记录一个表示错误状态的交易;
*
* @param txResult
* @return
*/
LedgerTransaction discardAndCommit(TransactionState txResult);
LedgerTransaction discardAndCommit(TransactionState txResult, TransactionReturnMessage returnMessage);

/**
* 回滚事务,抛弃本次事务的所有数据更新;


+ 10
- 6
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java View File

@@ -1,11 +1,7 @@
package com.jd.blockchain.ledger.core.impl;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.*;

public class LedgerTransactionData implements LedgerTransaction {

@@ -23,6 +19,8 @@ public class LedgerTransactionData implements LedgerTransaction {

private long blockHeight;

private TransactionReturnMessage returnMessage;

// private HashDigest adminAccountHash;
//
// private HashDigest userAccountSetHash;
@@ -49,7 +47,7 @@ public class LedgerTransactionData implements LedgerTransaction {
* 交易级的系统快照;
*/
public LedgerTransactionData(long blockHeight, TransactionRequest txReq, TransactionState execState,
TransactionStagedSnapshot txSnapshot) {
TransactionStagedSnapshot txSnapshot, TransactionReturnMessage returnMessage) {
this.blockHeight = blockHeight;
// this.txSnapshot = txSnapshot == null ? new TransactionStagedSnapshot() : txSnapshot;
this.txSnapshot = txSnapshot;
@@ -57,6 +55,7 @@ public class LedgerTransactionData implements LedgerTransaction {
this.endpointSignatures = txReq.getEndpointSignatures();
this.nodeSignatures = txReq.getNodeSignatures();
this.executionState = execState;
this.returnMessage = returnMessage;
}

@Override
@@ -74,6 +73,11 @@ public class LedgerTransactionData implements LedgerTransaction {
return executionState;
}

@Override
public TransactionReturnMessage getReturnMessage() {
return returnMessage;
}

@Override
public TransactionContent getTransactionContent() {
return this.transactionContent;


+ 4
- 4
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java View File

@@ -350,7 +350,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}

@Override
public LedgerTransaction commit(TransactionState txResult) {
public LedgerTransaction commit(TransactionState txResult, TransactionReturnMessage returnMessage) {
checkTxState();

// capture snapshot
@@ -359,7 +359,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {

// LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
// txResult, txDataSnapshot);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null, returnMessage);
this.txset.add(tx);
// this.txset.commit();

@@ -376,7 +376,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}

@Override
public LedgerTransaction discardAndCommit(TransactionState txResult) {
public LedgerTransaction discardAndCommit(TransactionState txResult, TransactionReturnMessage returnMessage) {
checkTxState();

// 未处理
@@ -385,7 +385,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
// TransactionStagedSnapshot txDataSnapshot = takeSnapshot();
// LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
// txResult, txDataSnapshot);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null, returnMessage);
this.txset.add(tx);
// this.txset.commit();



+ 45
- 10
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java View File

@@ -3,17 +3,15 @@ package com.jd.blockchain.ledger.core.impl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerService;
@@ -74,6 +72,8 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
// 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上;
LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request);
TransactionState result;
TransactionReturnMessageData returnMessageData = new TransactionReturnMessageData();

try {
LedgerDataSet dataset = txCtx.getDataSet();
TransactionRequestContext reqCtx = new TransactionRequestContextImpl(request);
@@ -100,28 +100,53 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
}
};
OperationHandle opHandle;
int contractOpIndex = 0;
for (Operation op : ops) {
opHandle = opHandles.getHandle(op.getClass());
opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService);
// 合约执行需要填充执行结果
if (opHandle instanceof ContractEventSendOperationHandle) {
CompletableFuture<String> currContractReturn = new CompletableFuture<>();
ContractReturnMessageData crmd = new ContractReturnMessageData(contractOpIndex++, currContractReturn);
returnMessageData.addContractReturnMessage(crmd);
((ContractEventSendOperationHandle) opHandle).process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService, currContractReturn);
} else {
opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService);
}
}

// 提交交易(事务);
result = TransactionState.SUCCESS;
txCtx.commit(result);
txCtx.commit(result, returnMessageData);
} catch (LedgerException e) {
// TODO: 识别更详细的异常类型以及执行对应的处理;
result = TransactionState.LEDGER_ERROR;
txCtx.discardAndCommit(TransactionState.LEDGER_ERROR);
txCtx.discardAndCommit(TransactionState.LEDGER_ERROR, returnMessageData);
LOGGER.warn(String.format("Transaction rollback caused by the ledger exception! --[TxHash=%s] --%s",
request.getHash().toBase58(), e.getMessage()), e);
} catch (Exception e) {
result = TransactionState.SYSTEM_ERROR;
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR);
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, returnMessageData);
LOGGER.warn(String.format("Transaction rollback caused by the system exception! --[TxHash=%s] --%s",
request.getHash().toBase58(), e.getMessage()), e);
}

TxResponseHandle resp = new TxResponseHandle(request, result);

if (!returnMessageData.isContractReturnEmpty()) {

ContractReturnMessage[] contractReturnMessages = returnMessageData.getContractReturn();

// 获取结果中的字符串
String[] returnValue = new String[contractReturnMessages.length];
try {
for (int i = 0; i < contractReturnMessages.length; i++) {
returnValue[i] = contractReturnMessages[i].getReturnMessage();
}
resp.setContractReturn(returnValue);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

responseList.add(resp);

return resp;
@@ -201,6 +226,8 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {

private TransactionState result;

private String[] contractReturn;

public TxResponseHandle(TransactionRequest request, TransactionState result) {
this.request = request;
this.result = result;
@@ -231,6 +258,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
return globalResult == null ? result == TransactionState.SUCCESS : globalResult == TransactionState.SUCCESS;
}

@Override
public String[] getContractReturn() {
return contractReturn;
}

public void setContractReturn(String[] contractReturn) {
this.contractReturn = contractReturn;
}
}

private class TransactionBatchResultImpl implements TransactionBatchResult {


+ 16
- 5
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java View File

@@ -20,6 +20,9 @@ import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.impl.LedgerQueryService;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

@Service
public class ContractEventSendOperationHandle implements OperationHandle {

@@ -32,6 +35,18 @@ public class ContractEventSendOperationHandle implements OperationHandle {
@Override
public void process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
process(op, dataset, requestContext, previousBlockDataset, opHandleContext, ledgerService, 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;
// 先从账本校验合约的有效性;
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行;
@@ -66,12 +81,8 @@ public class ContractEventSendOperationHandle implements OperationHandle {
}

// 处理合约事件;
contractCode.processEvent(localContractEventContext);
contractCode.processEvent(localContractEventContext, contractReturn);
}

@Override
public boolean support(Class<?> operationType) {
return ContractEventSendOperation.class.isAssignableFrom(operationType);
}

}

+ 2
- 2
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java View File

@@ -97,7 +97,7 @@ public class LedgerManagerTest {
System.out.println("UserAddress=" + userAccount.getAddress());

// 提交交易结果;
LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS);
LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS, null);

assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
assertEquals(0, tx.getBlockHeight());
@@ -137,7 +137,7 @@ public class LedgerManagerTest {

LedgerTransactionContext txCtx1 = editor1.newTransaction(txRequest);
txCtx1.getDataSet().getDataAccountSet().register(dataKey.getAddress(), dataKey.getPubKey(), null);
txCtx1.commit(TransactionState.SUCCESS);
txCtx1.commit(TransactionState.SUCCESS, null);

LedgerBlock block1 = editor1.prepare();
editor1.commit();


+ 1
- 1
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java View File

@@ -68,7 +68,7 @@ public class LedgerTransactionDataTest {

long blockHeight = 9986L;
data = new LedgerTransactionData(blockHeight, txRequestMessage, TransactionState.SUCCESS,
initTransactionStagedSnapshot());
initTransactionStagedSnapshot(), null);

HashDigest hash = new HashDigest(ClassicAlgorithm.SHA256, "zhangsan".getBytes());
HashDigest adminAccountHash = new HashDigest(ClassicAlgorithm.SHA256, "lisi".getBytes());


+ 1
- 1
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java View File

@@ -98,7 +98,7 @@ public class TransactionSetTest {
txSnapshot.setContractAccountSetHash(contractAccountSetHash);

long blockHeight = 8922L;
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot);
LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot, null);
txset.add(tx);

assertTrue(txset.isUpdated());


+ 17
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractReturnMessage.java View File

@@ -0,0 +1,17 @@
package com.jd.blockchain.ledger;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;

@DataContract(code= DataCodes.CONTRACT_RETURN)
public interface ContractReturnMessage {

@DataField(order=1, primitiveType = PrimitiveType.INT32)
int getOperationIndex();

@DataField(order=2, primitiveType = PrimitiveType.TEXT)
String getReturnMessage();

}

+ 41
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractReturnMessageData.java View File

@@ -0,0 +1,41 @@
package com.jd.blockchain.ledger;

import java.util.concurrent.CompletableFuture;

public class ContractReturnMessageData implements ContractReturnMessage {

private int operationIndex;

private CompletableFuture<String> returnMsgFuture;

public ContractReturnMessageData() {
}

public ContractReturnMessageData(int operationIndex, CompletableFuture<String> returnMsgFuture) {
this.operationIndex = operationIndex;
this.returnMsgFuture = returnMsgFuture;
}

public void setOperationIndex(int operationIndex) {
this.operationIndex = operationIndex;
}

public void setReturnMsgFuture(CompletableFuture<String> returnMsgFuture) {
this.returnMsgFuture = returnMsgFuture;
}

@Override
public int getOperationIndex() {
return operationIndex;
}

@Override
public String getReturnMessage() {
try {
return returnMsgFuture.get();
} catch (Exception e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
}

+ 7
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java View File

@@ -45,4 +45,11 @@ public interface Transaction extends NodeRequest, HashObject {
@DataField(order=3, refEnum=true)
TransactionState getExecutionState();
/**
* 交易的返回结果
*
* @return
*/
@DataField(order=4, refContract=true)
TransactionReturnMessage getReturnMessage();
}

+ 11
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRespHandle.java View File

@@ -27,6 +27,8 @@ public class TransactionRespHandle implements TransactionResponse {

private TransactionState globalResult;

private String[] contractReturn;

public TransactionRespHandle(TransactionRequest request, TransactionState result, TransactionState globalResult) {
this.request = request;
this.result = result;
@@ -49,6 +51,10 @@ public class TransactionRespHandle implements TransactionResponse {
this.result = result;
}

public void setContractReturn(String[] contractReturn) {
this.contractReturn = contractReturn;
}

public LedgerBlock getBlock() {
return block;
}
@@ -89,4 +95,9 @@ public class TransactionRespHandle implements TransactionResponse {
public boolean isSuccess() {
return globalResult == null ? result == TransactionState.SUCCESS : globalResult == TransactionState.SUCCESS;
}

@Override
public String[] getContractReturn() {
return contractReturn;
}
}

+ 13
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java View File

@@ -49,8 +49,20 @@ public interface TransactionResponse {
*/
@DataField(order=4, primitiveType=PrimitiveType.INT64)
long getBlockHeight();
/**
* 交易是否执行成功
*
* @return
*/
@DataField(order=5, primitiveType=PrimitiveType.BOOLEAN)
boolean isSuccess();
/**
* 合约返回值
*
* @return
*/
@DataField(order=6, list=true, primitiveType=PrimitiveType.TEXT)
String[] getContractReturn();
}

+ 17
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessage.java View File

@@ -0,0 +1,17 @@
package com.jd.blockchain.ledger;

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.consts.DataCodes;

@DataContract(code= DataCodes.TX_RETURN_MESSAGE)
public interface TransactionReturnMessage {

/**
* 合约返回值列表
*
* @return
*/
@DataField(order=1, list = true, refContract=true)
ContractReturnMessage[] getContractReturn();
}

+ 26
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionReturnMessageData.java View File

@@ -0,0 +1,26 @@
package com.jd.blockchain.ledger;

import java.util.ArrayList;
import java.util.List;

public class TransactionReturnMessageData implements TransactionReturnMessage {

private List<ContractReturnMessage> contractReturnMessages = new ArrayList<>();

public void addContractReturnMessage(ContractReturnMessage contractReturnMessage) {
contractReturnMessages.add(contractReturnMessage);
}

public boolean isContractReturnEmpty() {
return contractReturnMessages.isEmpty();
}

@Override
public ContractReturnMessage[] getContractReturn() {
if (isContractReturnEmpty()) {
return null;
}
ContractReturnMessage[] crms = new ContractReturnMessage[contractReturnMessages.size()];
return contractReturnMessages.toArray(crms);
}
}

+ 13
- 4
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java View File

@@ -17,6 +17,8 @@ public class TxResponseMessage implements TransactionResponse {
private long blockHeight;
private TransactionState executionState;
private String[] contractReturn;
public TxResponseMessage() {
}
@@ -39,9 +41,6 @@ public class TxResponseMessage implements TransactionResponse {
this.executionState = executionState;
}
/* (non-Javadoc)
* @see com.jd.blockchain.ledger.TransactionResponse#getBlockHash()
*/
@Override
public HashDigest getBlockHash() {
return blockHash;
@@ -55,13 +54,23 @@ public class TxResponseMessage implements TransactionResponse {
public long getBlockHeight() {
return blockHeight;
}
public void setBlockHeight(long blockHeight) {
this.blockHeight = blockHeight;
}
public void setContractReturn(String[] contractReturn) {
this.contractReturn = contractReturn;
}
@Override
public boolean isSuccess() {
return blockHash != null & executionState == TransactionState.SUCCESS;
}
@Override
public String[] getContractReturn() {
return contractReturn;
}
}

+ 5
- 0
source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java View File

@@ -307,6 +307,11 @@ public class ConsensusMessageDispatcher implements MessageHandle {
public boolean isSuccess() {
return this.txResp.isSuccess();
}

@Override
public String[] getContractReturn() {
return txResp.getContractReturn();
}
}

private final class BlockStateSnapshot implements StateSnapshot {


+ 6
- 9
source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/AbstractModule.java View File

@@ -50,15 +50,12 @@ public abstract class AbstractModule implements Module {
if (origClassLoader != moduleClassLoader) {
Thread.currentThread().setContextClassLoader(moduleClassLoader);
}
return CompletableAsyncFuture.runAsync(new Runnable() {
@Override
public void run() {
try {
runnable.run();
} finally {
if (origClassLoader != Thread.currentThread().getContextClassLoader()) {
Thread.currentThread().setContextClassLoader(origClassLoader);
}
return CompletableAsyncFuture.runAsync(() -> {
try {
runnable.run();
} finally {
if (origClassLoader != Thread.currentThread().getContextClassLoader()) {
Thread.currentThread().setContextClassLoader(origClassLoader);
}
}
});


+ 7
- 0
source/test/test-integration/pom.xml View File

@@ -40,6 +40,13 @@
<artifactId>sdk-client</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract-samples</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.nats</groupId>
<artifactId>jnats</artifactId>


+ 16
- 0
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java View File

@@ -15,9 +15,11 @@ import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.concurrent.ThreadInvoker;

import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest;
import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4Nodes;

import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -85,6 +87,20 @@ public class IntegrationTest4Contract {
BlockchainService blockchainService = gwsrvFact.getBlockchainService();

if(isContractDeployAndExe){
// 合约测试需要runtime路径
try {
ClassPathResource contractPath = new ClassPathResource("");
File file = new File(contractPath.getURI());
String runTimePath = file.getParentFile().getParent() + File.separator + "runtime";
File runTime = new File(runTimePath);
if (!runTime.exists()) {
runTime.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
}


IntegrationBase.testSDK_Contract(adminKey,ledgerHash,blockchainService,ledgerRepository);
}



BIN
source/test/test-integration/src/test/resources/contract-read.jar View File


+ 1
- 1
source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java View File

@@ -425,7 +425,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI
userRegOP.getUserID().getPubKey());
}

txCtx.commit(TransactionState.SUCCESS);
txCtx.commit(TransactionState.SUCCESS, null);

return ledgerEditor.prepare();
}


+ 1
- 1
source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java View File

@@ -293,7 +293,7 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon
userRegOP.getUserID().getPubKey());
}

txCtx.commit(TransactionState.SUCCESS);
txCtx.commit(TransactionState.SUCCESS, null);

return ledgerEditor.prepare();
}


Loading…
Cancel
Save