diff --git a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java
index d75f5b60..891acd4c 100644
--- a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java
+++ b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java
@@ -1,10 +1,11 @@
package com.jd.blockchain.contract.engine;
import com.jd.blockchain.contract.ContractEventContext;
+import com.jd.blockchain.utils.Bytes;
public interface ContractCode {
- String getAddress();
+ Bytes getAddress();
long getVersion();
diff --git a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
index e047bcc7..3f5a21c1 100644
--- a/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
+++ b/source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
@@ -1,5 +1,7 @@
package com.jd.blockchain.contract.engine;
+import com.jd.blockchain.utils.Bytes;
+
/**
* 合约引擎;
*
@@ -16,7 +18,7 @@ public interface ContractEngine {
* @param address
* @return
*/
- ContractCode getContract(String address, long version);
+ ContractCode getContract(Bytes address, long version);
/**
* 装入合约代码;
@@ -27,6 +29,6 @@ public interface ContractEngine {
* @param code
* @return
*/
- ContractCode setupContract(String address, long version, byte[] code);
+ ContractCode setupContract(Bytes address, long version, byte[] code);
}
diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
index e07e5215..ea1ee9fa 100644
--- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
+++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
@@ -4,18 +4,18 @@ import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.runtime.RuntimeContext;
+import com.jd.blockchain.utils.Bytes;
public class JVMContractEngine implements ContractEngine {
private RuntimeContext runtimeContext = RuntimeContext.get();
-// private RuntimeContext runtimeContext = ModularRuntimeContext.setup(System.getProperty("user.dir"));
- private String getCodeName(String address, long version) {
- return address + "_" + version;
+ private String getCodeName(Bytes address, long version) {
+ return address.toBase58() + "_" + version;
}
@Override
- public ContractCode getContract(String address, long version) {
+ public ContractCode getContract(Bytes address, long version) {
String codeName = getCodeName(address, version);
Module module = runtimeContext.getDynamicModule(codeName);
if (module == null) {
@@ -25,7 +25,7 @@ public class JVMContractEngine implements ContractEngine {
}
@Override
- public ContractCode setupContract(String address, long version, byte[] code) {
+ public ContractCode setupContract(Bytes address, long version, byte[] code) {
//is there the contractCode before setup? if yes ,then return;
ContractCode contractCode = getContract(address,version);
if(contractCode != null){
diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
index da5d2fb8..90f68d5a 100644
--- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
+++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
@@ -14,6 +14,7 @@ import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.utils.BaseConstant;
+import com.jd.blockchain.utils.Bytes;
/**
* contract code based jvm
@@ -22,18 +23,18 @@ import com.jd.blockchain.utils.BaseConstant;
public class JavaContractCode implements ContractCode {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class);
private Module codeModule;
- private String address;
+ private Bytes address;
private long version;
private ContractEventContext contractEventContext;
- public JavaContractCode(String address, long version, Module codeModule) {
+ public JavaContractCode(Bytes address, long version, Module codeModule) {
this.address = address;
this.version = version;
this.codeModule = codeModule;
}
@Override
- public String getAddress() {
+ public Bytes getAddress() {
return address;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
index 06817550..323960f3 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
@@ -8,11 +8,8 @@ import com.jd.blockchain.utils.io.BytesUtils;
public class ContractAccount implements AccountHeader {
- // private static final String CONTRACT_INFO_PREFIX = "INFO" +
- // LedgerConsts.KEY_SEPERATOR;
private static final Bytes CONTRACT_INFO_PREFIX = Bytes.fromString("INFO" + LedgerConsts.KEY_SEPERATOR);
- // private static final String CHAIN_CODE_KEY = "CHAIN-CODE";
private static final Bytes CHAIN_CODE_KEY = Bytes.fromString("CHAIN-CODE");
private BaseAccount accBase;
@@ -74,7 +71,6 @@ public class ContractAccount implements AccountHeader {
private Bytes encodePropertyKey(Bytes key) {
return CONTRACT_INFO_PREFIX.concat(key);
-// return key.concatTo(CONTRACT_INFO_PREFIX);
}
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
index 5c3b67cc..e1930a35 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
@@ -1,49 +1,72 @@
package com.jd.blockchain.ledger.core.impl.handles;
+import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;
+
+import org.springframework.stereotype.Service;
+
import com.jd.blockchain.contract.LocalContractEventContext;
+import com.jd.blockchain.contract.engine.ContractCode;
+import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.contract.engine.ContractServiceProviders;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.*;
+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.LedgerException;
+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 org.springframework.stereotype.Service;
-
-import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;
@Service
public class ContractEventSendOperationHandle implements OperationHandle {
+
+ private static final ContractEngine JVM_ENGINE;
+
+ static {
+ JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine();
+ }
+
@Override
public void process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
ContractEventSendOperation contractOP = (ContractEventSendOperation) op;
// 先从账本校验合约的有效性;
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行;
- if (!previousBlockDataset.getContractAccountSet().contains(contractOP.getContractAddress())) {
- throw new LedgerException(
- String.format("Target contract of ContractEvent was not registered! --[ContractAddress=%s]",
- contractOP.getContractAddress()));
+ 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) ;
+
+ // 创建合约的账本上下文实例;
+ LedgerQueryService queryService = new LedgerQueryService(ledgerService);
ContractLedgerContext ledgerContext = new ContractLedgerContext(queryService, opHandleContext);
- // TODO:从合约引擎加载合约,执行合约代码;
- ContractAccount contract = previousBlockDataset.getContractAccountSet()
- .getContract(contractOP.getContractAddress());
- try {
- // 在调用方法前,需要加载上下文信息;
- LocalContractEventContext localContractEventContext = new LocalContractEventContext(
- requestContext.getRequest().getTransactionContent().getLedgerHash(),contract.getChainCode(), contractOP.getEvent());
- localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest()).
- setLedgerContext(ledgerContext);
- ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine().setupContract(
- contract.getAddress().toBase58(),contract.getChaincodeVersion(),contract.getChainCode()).
- processEvent(localContractEventContext);
- } catch (Exception e) {
- e.printStackTrace();
+ // 先检查合约引擎是否已经加载合约;如果未加载,再从账本中读取合约代码并装载到引擎中执行;
+ 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);
}
@Override
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java
index 7d366d0c..e18d7714 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java
@@ -1,11 +1,10 @@
package com.jd.blockchain.contract;
+import java.util.Set;
+
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.utils.io.ByteArray;
-
-import java.util.Set;
/**
* @Author zhaogw
@@ -21,10 +20,10 @@ public class LocalContractEventContext implements ContractEventContext,Cloneable
private Set contractOwners;
private LedgerContext ledgerContext;
- public LocalContractEventContext(HashDigest ledgeHash, byte[] chainCode, String event){
+ public LocalContractEventContext(HashDigest ledgeHash, String event){
this.ledgeHash = ledgeHash;
this.event = event;
- this.chainCode = chainCode;
+// this.chainCode = chainCode;
}
@Override
@@ -92,14 +91,14 @@ public class LocalContractEventContext implements ContractEventContext,Cloneable
return this;
}
- public byte[] getChainCode() {
- return chainCode;
- }
-
- public LocalContractEventContext setChainCode(byte[] chainCode) {
- this.chainCode = chainCode;
- return this;
- }
+// public byte[] getChainCode() {
+// return chainCode;
+// }
+//
+// public LocalContractEventContext setChainCode(byte[] chainCode) {
+// this.chainCode = chainCode;
+// return this;
+// }
public LocalContractEventContext setArgs(byte[] args) {
this.args = args;
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java
index 7b7921b8..2aeb488e 100644
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java
@@ -8,6 +8,12 @@ import com.jd.blockchain.utils.io.BytesSerializable;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.io.RuntimeIOException;
+/**
+ * Bytes 被设计为不可变对象;
+ *
+ * @author huanghaiquan
+ *
+ */
public class Bytes implements BytesSerializable {
public static final Bytes EMPTY = new Bytes(BytesUtils.EMPTY_BYTES);
@@ -38,7 +44,7 @@ public class Bytes implements BytesSerializable {
}
public Bytes() {
- prefix=null;
+ prefix = null;
data = null;
hashCode = hashCode(1);
}
@@ -47,7 +53,7 @@ public class Bytes implements BytesSerializable {
if (data == null) {
throw new IllegalArgumentException("data is null!");
}
- this.prefix=null;
+ this.prefix = null;
this.data = data;
hashCode = hashCode(1);
}
@@ -56,30 +62,30 @@ public class Bytes implements BytesSerializable {
if (data == null) {
throw new IllegalArgumentException("data is null!");
}
- this.prefix=prefix;
+ this.prefix = prefix;
this.data = data;
-// setPrefix(prefix);
+ // setPrefix(prefix);
hashCode = hashCode(1);
}
public Bytes(Bytes prefix, Bytes data) {
-// setData(data.toBytes());
-// setPrefix(prefix);
+ // setData(data.toBytes());
+ // setPrefix(prefix);
if (data == null) {
throw new IllegalArgumentException("data is null!");
}
- this.prefix=prefix;
+ this.prefix = prefix;
this.data = data.toBytes();
-
+
hashCode = hashCode(1);
}
-// private void setData(byte[] data) {
-// if (data == null) {
-// throw new IllegalArgumentException("data is null!");
-// }
-// this.data = data;
-// }
+ // private void setData(byte[] data) {
+ // if (data == null) {
+ // throw new IllegalArgumentException("data is null!");
+ // }
+ // this.data = data;
+ // }
/**
* 返回当前的字节数组(不包含前缀对象);
@@ -98,16 +104,16 @@ public class Bytes implements BytesSerializable {
return new Bytes(Base58Utils.decode(str));
}
-// /**
-// * 连接指定的前缀后面;此操作并不会更改“prefix”参数;
-// *
-// * @param prefix
-// * @return
-// */
-// private Bytes setPrefix(Bytes prefix) {
-// this.prefix = prefix;
-// return this;
-// }
+ // /**
+ // * 连接指定的前缀后面;此操作并不会更改“prefix”参数;
+ // *
+ // * @param prefix
+ // * @return
+ // */
+ // private Bytes setPrefix(Bytes prefix) {
+ // this.prefix = prefix;
+ // return this;
+ // }
public Bytes concat(Bytes key) {
return new Bytes(this, key);