Browse Source

Optimized contract loading.

tags/1.0.0
huanghaiquan 5 years ago
parent
commit
9cdda49897
8 changed files with 105 additions and 77 deletions
  1. +2
    -1
      source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractCode.java
  2. +4
    -2
      source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
  3. +5
    -5
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
  4. +4
    -3
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  5. +0
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  6. +48
    -25
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
  7. +12
    -13
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java
  8. +30
    -24
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java

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

@@ -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();



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

@@ -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);

/**
* 装入合约代码;<br>
@@ -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);

}

+ 5
- 5
source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java View File

@@ -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){


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

@@ -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;
}


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

@@ -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);
}
}

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

@@ -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


+ 12
- 13
source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/LocalContractEventContext.java View File

@@ -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<BlockchainIdentity> 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;


+ 30
- 24
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java View File

@@ -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);


Loading…
Cancel
Save