Browse Source

Completed the basic processing of invoking contract with it's interface;

tags/1.0.0
huanghaiquan 5 years ago
parent
commit
91ea158efc
12 changed files with 186 additions and 92 deletions
  1. +47
    -31
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JavaContractCode.java
  2. +16
    -16
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
  3. +3
    -6
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
  4. +0
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
  5. +35
    -8
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java
  6. +40
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java
  7. +12
    -13
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractType.java
  8. +15
    -4
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/EventOperator.java
  9. +8
    -3
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
  10. +4
    -4
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
  11. +0
    -2
      source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java
  12. +6
    -3
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java

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

@@ -13,12 +13,14 @@ import com.jd.blockchain.contract.ContractEvent;
import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.transaction.ContractType;
import com.jd.blockchain.utils.BaseConstant;
import com.jd.blockchain.utils.Bytes;

/**
* contract code based jvm
* @author zhaogw
*
* @author zhaogw
*/
public class JavaContractCode implements ContractCode {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class);
@@ -26,7 +28,9 @@ public class JavaContractCode implements ContractCode {
private Bytes address;
private long version;
private ContractEventContext contractEventContext;

private ContractType contractType;

public JavaContractCode(Bytes address, long version, Module codeModule) {
this.address = address;
this.version = version;
@@ -37,7 +41,7 @@ public class JavaContractCode implements ContractCode {
public Bytes getAddress() {
return address;
}
@Override
public long getVersion() {
return version;
@@ -46,35 +50,45 @@ public class JavaContractCode implements ContractCode {
@Override
public void processEvent(ContractEventContext eventContext) {
this.contractEventContext = eventContext;
codeModule.execute(new ContractThread());
codeModule.execute(new ContractExecution());
}

class ContractThread implements Runnable{
public void run(){
private Object[] resolveArgs(byte[] args) {
// TODO Auto-generated method stub
return null;
}

class ContractExecution implements Runnable {
public void run() {
LOGGER.info("ContractThread execute().");
try {
//执行预处理;
// 执行预处理;
long startTime = System.currentTimeMillis();

String contractClassName = codeModule.getMainClass();
Class myClass = codeModule.loadClass(contractClassName);
Object contractMainClassObj = myClass.newInstance();//合约主类生成的类实例;
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 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());
Method eventMethod = this.getMethodByAnno(contractMainClassObj, contractEventContext.getEvent());
startTime = System.currentTimeMillis();

ReflectionUtils.invokeMethod(eventMethod,contractMainClassObj,contractEventContext);
// 反序列化参数;
Method handleMethod = contractType.getHandleMethod(contractEventContext.getEvent());
Object[] args = resolveArgs(contractEventContext.getArgs());

ReflectionUtils.invokeMethod(handleMethod, contractMainClassObj, args);

LOGGER.info("合约执行,耗时:"+(System.currentTimeMillis()-startTime));
LOGGER.info("合约执行,耗时:" + (System.currentTimeMillis() - startTime));

Method mth2 = myClass.getMethod("postEvent");
startTime = System.currentTimeMillis();
ReflectionUtils.invokeMethod(mth2,contractMainClassObj);
LOGGER.info("postEvent,耗时:"+(System.currentTimeMillis()-startTime));
ReflectionUtils.invokeMethod(mth2, contractMainClassObj);
LOGGER.info("postEvent,耗时:" + (System.currentTimeMillis() - startTime));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (Exception e) {
@@ -82,39 +96,41 @@ public class JavaContractCode implements ContractCode {
}
}

//得到当前类中相关方法和注解对应关系;
Method getMethodByAnno(Object classObj, String eventName){
// 得到当前类中相关方法和注解对应关系;
Method getMethodByAnno(Object classObj, String eventName) {
Class<?> c = classObj.getClass();
Class <ContractEvent> contractEventClass = null;
Class<ContractEvent> contractEventClass = null;
try {
contractEventClass = (Class <ContractEvent>)c.getClassLoader().loadClass(ContractEvent.class.getName());
contractEventClass = (Class<ContractEvent>) c.getClassLoader().loadClass(ContractEvent.class.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] classMethods = c.getMethods();
Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>();
Map<String,Method> annoMethodMap = new HashMap<String,Method>();
for(int i = 0;i<classMethods.length;i++){
Map<String, Method> annoMethodMap = new HashMap<String, Method>();
for (int i = 0; i < classMethods.length; i++) {
Annotation[] a = classMethods[i].getDeclaredAnnotations();
methodAnnoMap.put(classMethods[i], a);
//如果当前方法中包含@ContractEvent注解,则将其放入Map;
for(Annotation annotation_ : a){
//如果是合同事件类型,则放入map;
if(classMethods[i].isAnnotationPresent(contractEventClass)){
// 如果当前方法中包含@ContractEvent注解,则将其放入Map;
for (Annotation annotation_ : a) {
// 如果是合同事件类型,则放入map;
if (classMethods[i].isAnnotationPresent(contractEventClass)) {
Object obj = classMethods[i].getAnnotation(contractEventClass);
String annoAllName = obj.toString();
//format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset)
String eventName_ = obj.toString().substring(BaseConstant.CONTRACT_EVENT_PREFIX.length(),annoAllName.length()-1);
annoMethodMap.put(eventName_,classMethods[i]);
// format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset)
String eventName_ = obj.toString().substring(BaseConstant.CONTRACT_EVENT_PREFIX.length(),
annoAllName.length() - 1);
annoMethodMap.put(eventName_, classMethods[i]);
break;
}
}
}
if(annoMethodMap.containsKey(eventName)){
if (annoMethodMap.containsKey(eventName)) {
return annoMethodMap.get(eventName);
}else {
} else {
return null;
}
}
}

}

+ 16
- 16
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java View File

@@ -43,22 +43,22 @@ public class LedgerTestUtils {
return txHandle.txRequest;
}

public static TransactionRequest createContractEventTxRequest(HashDigest ledgerHash,
SignatureFunction signatureFunction, String contractAddress, String event, byte[] args) {
TxHandle txHandle = new TxHandle();
TxTemplate txTemp = new TxTemplate(ledgerHash, txHandle);
txTemp.contractEvents().send(contractAddress, event, args);
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
PubKey pubKey = cryptoKeyPair.getPubKey();
txTemp.users().register(new BlockchainIdentityData(pubKey));
PreparedTransaction ptx = txTemp.prepare();
ptx.sign(cryptoKeyPair);
ptx.commit();
return txHandle.txRequest;
}
// public static TransactionRequest createContractEventTxRequest(HashDigest ledgerHash,
// SignatureFunction signatureFunction, String contractAddress, String event, byte[] args) {
// TxHandle txHandle = new TxHandle();
//
// TxTemplate txTemp = new TxTemplate(ledgerHash, txHandle);
//
// txTemp.contractEvents().send(contractAddress, event, args);
//
// AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
// PubKey pubKey = cryptoKeyPair.getPubKey();
// txTemp.users().register(new BlockchainIdentityData(pubKey));
// PreparedTransaction ptx = txTemp.prepare();
// ptx.sign(cryptoKeyPair);
// ptx.commit();
// return txHandle.txRequest;
// }

public static TransactionStagedSnapshot generateRandomSnapshot() {
TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot();


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

@@ -6,14 +6,12 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.security.KeyFactory;
import java.util.Random;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;

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.ContractCodeDeployOperation;
@@ -25,7 +23,6 @@ import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.ledger.TransactionState;
@@ -62,7 +59,7 @@ public class TransactionSetTest {

// Build transaction request;
HashDigest ledgerHash = LedgerTestUtils.generateRandomHash();
TransactionBuilder txBuilder = new TxBuilder(ledgerHash);
TxBuilder txBuilder = new TxBuilder(ledgerHash);

BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
UserRegisterOperation userRegOp = txBuilder.users().register(userKey.getIdentity());


+ 0
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java View File

@@ -74,7 +74,6 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
return contractCodeDeployOpBuilder;
}
@Override
public ContractEventSendOperationBuilder contractEvents() {
return contractEventSendOpBuilder;
}


+ 35
- 8
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java View File

@@ -3,19 +3,46 @@ package com.jd.blockchain.transaction;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ContractInvocationProxy implements InvocationHandler {
private String contractMessage;
import com.jd.blockchain.utils.Bytes;

public class ContractInvocationProxy implements InvocationHandler {

// private String contractMessage;

private Bytes contractAddress;

private ContractType contractType;

private ContractEventSendOperationBuilder sendOpBuilder;

public ContractInvocationProxy(Bytes contractAddress, ContractType contractType,
ContractEventSendOperationBuilder sendOpBuilder) {
this.contractAddress = contractAddress;
this.contractType = contractType;
this.sendOpBuilder = sendOpBuilder;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub

String event = contractType.getEvent(method);
if (event == null) {
// 适配 Object 对象的方法;
// toString 方法;
return String.format("[%s]-%s", contractAddress, contractType.toString());

// hashCode 方法;
}
// 合约方法;
byte[] argBytes = serializeArgs(args);
sendOpBuilder.send(contractAddress, event, argBytes);

// TODO: 暂时未考虑有返回值的情况;
return null;
}

private byte[] serializeArgs(Object[] args) {
// TODO 根据方法参数的定义序列化参数;
return null;
}



+ 40
- 1
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java View File

@@ -1,6 +1,45 @@
package com.jd.blockchain.transaction;
class ContractInvocationProxyBuilder {
import java.lang.reflect.Proxy;
import java.util.Map;
import com.jd.blockchain.utils.Bytes;
public class ContractInvocationProxyBuilder {
private Map<Class<?>, ContractType> contractTypes;
public <T> T create(String address, Class<T> contractIntf, BlockchainOperationFactory opFactory) {
return create(Bytes.fromBase58(address), contractIntf, opFactory);
}
@SuppressWarnings("unchecked")
public <T> T create(Bytes address, Class<T> contractIntf, BlockchainOperationFactory opFactory) {
ContractType contractType = resolveContractType(contractIntf);
ContractInvocationProxy proxyHandler = new ContractInvocationProxy(address, contractType,
opFactory.contractEvents());
T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[] { contractIntf }, proxyHandler);
return (T) proxy;
}
private ContractType resolveContractType(Class<?> contractIntf) {
ContractType contractType = contractTypes.get(contractIntf);
if (contractType != null) {
return contractType;
}
// 判断是否是标注了合约的接口类型;
// 解析合约事件处理方法,检查是否有重名;
// TODO 检查是否不支持的参数类型;
// TODO 检查返回值类型;
return null;
}
}

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

@@ -4,12 +4,12 @@ import java.lang.reflect.Method;
import java.util.Set;
import java.util.SortedMap;

class ContractType {
public class ContractType {
private String name;
private SortedMap<String, Method> events;
private SortedMap<Method, String> handleMethods;

/**
@@ -17,7 +17,7 @@ class ContractType {
*
* @return
*/
Set<String> getEvents() {
public Set<String> getEvents() {
return events.keySet();
}

@@ -29,7 +29,7 @@ class ContractType {
* @param method
* @return
*/
String getEvent(Method method) {
public String getEvent(Method method) {
return handleMethods.get(method);
}

@@ -41,16 +41,15 @@ class ContractType {
* @param event
* @return
*/
Method getHandleMethod(String event) {
public Method getHandleMethod(String event) {
return events.get(event);
}
private ContractType() {
}
// public static ContractType resolve(Class<?> contractIntf) {
//
// }

// public static ContractType resolve(Class<?> contractIntf) {
//
// }

}

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

@@ -1,14 +1,25 @@
package com.jd.blockchain.transaction;

import com.jd.blockchain.utils.Bytes;

public interface EventOperator {

// /**
// * 合约事件;
// *
// * @return
// */
// @Deprecated
// ContractEventSendOperationBuilder contractEvents();

/**
* 部署合约;
* 创建调用合约的代理实例
*
* @param address
* @param contractIntf
* @return
*/
@Deprecated
ContractEventSendOperationBuilder contractEvents();
<T> T contract(String address, Class<T> contractIntf);
/**
* 创建调用合约的代理实例;
@@ -17,6 +28,6 @@ public interface EventOperator {
* @param contractIntf
* @return
*/
<T> T contract(String address, Class<T> contractIntf);
<T> T contract(Bytes address, Class<T> contractIntf);

}

+ 8
- 3
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java View File

@@ -21,6 +21,8 @@ public class TxBuilder implements TransactionBuilder {
private static final String DEFAULT_HASH_ALGORITHM = "SHA256";
private HashDigest ledgerHash;
private ContractInvocationProxyBuilder contractInvoProxyBuilder;
public TxBuilder(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
@@ -79,15 +81,18 @@ public class TxBuilder implements TransactionBuilder {
return opFactory.contracts();
}
@Override
public ContractEventSendOperationBuilder contractEvents() {
return opFactory.contractEvents();
}
@Override
public <T> T contract(Bytes address, Class<T> contractIntf) {
return contractInvoProxyBuilder.create(address, contractIntf, opFactory);
}
@Override
public <T> T contract(String address, Class<T> contractIntf) {
// TODO Auto-generated method stub
throw new IllegalStateException("Not implemented.");
return contractInvoProxyBuilder.create(address, contractIntf, opFactory);
}
}

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

@@ -53,10 +53,10 @@ public class TxTemplate implements TransactionTemplate {
return txBuilder.contracts();
}
@Override
public ContractEventSendOperationBuilder contractEvents() {
return txBuilder.contractEvents();
}
// @Override
// public ContractEventSendOperationBuilder contractEvents() {
// return txBuilder.contractEvents();
// }
@Override
public <T> T contract(String address, Class<T> contractIntf) {


+ 0
- 2
source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java View File

@@ -4,8 +4,6 @@ import com.jd.blockchain.consensus.service.NodeServer;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.tools.initializer.LedgerBindingConfig;

import java.util.List;

public interface LedgerBindingConfigAware {
void setConfig(LedgerBindingConfig config);


+ 6
- 3
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java View File

@@ -68,9 +68,12 @@ public class SDKDemo_Contract {
Remark remark = new Remark();
String remarkJSON = JSONSerializeUtils.serializeToJSON(remark);
// AssetContract assetContract = txTemp.contract("", AssetContract.class);
// txTemp.contractInvocation(assetContract.issue(amount, assetHolderAddress))

AssetContract assetContract = txTemp.contract(profitDistributionContract, AssetContract.class);
assetContract.issue(1000, receiptorAccount1);
assetContract.transfer(receiptorAccount1, receiptorAccount2, 600);
// assetContract.
// --------------------------------------

// TX 准备就绪;


Loading…
Cancel
Save