@@ -13,12 +13,14 @@ import com.jd.blockchain.contract.ContractEvent; | |||||
import com.jd.blockchain.contract.ContractEventContext; | import com.jd.blockchain.contract.ContractEventContext; | ||||
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.utils.BaseConstant; | import com.jd.blockchain.utils.BaseConstant; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
/** | /** | ||||
* contract code based jvm | * contract code based jvm | ||||
* @author zhaogw | |||||
* | |||||
* @author zhaogw | |||||
*/ | */ | ||||
public class JavaContractCode implements ContractCode { | public class JavaContractCode implements ContractCode { | ||||
private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class); | private static final Logger LOGGER = LoggerFactory.getLogger(JavaContractCode.class); | ||||
@@ -26,7 +28,9 @@ public class JavaContractCode implements ContractCode { | |||||
private Bytes address; | private Bytes address; | ||||
private long version; | private long version; | ||||
private ContractEventContext contractEventContext; | private ContractEventContext contractEventContext; | ||||
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; | ||||
@@ -37,7 +41,7 @@ public class JavaContractCode implements ContractCode { | |||||
public Bytes getAddress() { | public Bytes getAddress() { | ||||
return address; | return address; | ||||
} | } | ||||
@Override | @Override | ||||
public long getVersion() { | public long getVersion() { | ||||
return version; | return version; | ||||
@@ -46,35 +50,45 @@ public class JavaContractCode implements ContractCode { | |||||
@Override | @Override | ||||
public void processEvent(ContractEventContext eventContext) { | public void processEvent(ContractEventContext eventContext) { | ||||
this.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()."); | LOGGER.info("ContractThread execute()."); | ||||
try { | try { | ||||
//执行预处理; | |||||
// 执行预处理; | |||||
long startTime = System.currentTimeMillis(); | long startTime = System.currentTimeMillis(); | ||||
String contractClassName = codeModule.getMainClass(); | String contractClassName = codeModule.getMainClass(); | ||||
Class myClass = codeModule.loadClass(contractClassName); | 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(); | 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"); | Method mth2 = myClass.getMethod("postEvent"); | ||||
startTime = System.currentTimeMillis(); | 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) { | } catch (NoSuchMethodException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} catch (Exception e) { | } 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<?> c = classObj.getClass(); | ||||
Class <ContractEvent> contractEventClass = null; | |||||
Class<ContractEvent> contractEventClass = null; | |||||
try { | try { | ||||
contractEventClass = (Class <ContractEvent>)c.getClassLoader().loadClass(ContractEvent.class.getName()); | |||||
contractEventClass = (Class<ContractEvent>) c.getClassLoader().loadClass(ContractEvent.class.getName()); | |||||
} catch (ClassNotFoundException e) { | } catch (ClassNotFoundException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
Method[] classMethods = c.getMethods(); | Method[] classMethods = c.getMethods(); | ||||
Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>(); | 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(); | Annotation[] a = classMethods[i].getDeclaredAnnotations(); | ||||
methodAnnoMap.put(classMethods[i], a); | 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); | Object obj = classMethods[i].getAnnotation(contractEventClass); | ||||
String annoAllName = obj.toString(); | 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; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if(annoMethodMap.containsKey(eventName)){ | |||||
if (annoMethodMap.containsKey(eventName)) { | |||||
return annoMethodMap.get(eventName); | return annoMethodMap.get(eventName); | ||||
}else { | |||||
} else { | |||||
return null; | return null; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -43,22 +43,22 @@ public class LedgerTestUtils { | |||||
return txHandle.txRequest; | 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() { | public static TransactionStagedSnapshot generateRandomSnapshot() { | ||||
TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot(); | TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot(); | ||||
@@ -6,14 +6,12 @@ import static org.junit.Assert.assertNotNull; | |||||
import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||
import static org.junit.Assert.assertTrue; | import static org.junit.Assert.assertTrue; | ||||
import java.security.KeyFactory; | |||||
import java.util.Random; | import java.util.Random; | ||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import org.junit.Test; | 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.BlockchainKeyGenerator; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | 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.DigitalSignature; | ||||
import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.ledger.TransactionBuilder; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
import com.jd.blockchain.ledger.TransactionRequestBuilder; | import com.jd.blockchain.ledger.TransactionRequestBuilder; | ||||
import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
@@ -62,7 +59,7 @@ public class TransactionSetTest { | |||||
// Build transaction request; | // Build transaction request; | ||||
HashDigest ledgerHash = LedgerTestUtils.generateRandomHash(); | HashDigest ledgerHash = LedgerTestUtils.generateRandomHash(); | ||||
TransactionBuilder txBuilder = new TxBuilder(ledgerHash); | |||||
TxBuilder txBuilder = new TxBuilder(ledgerHash); | |||||
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | ||||
UserRegisterOperation userRegOp = txBuilder.users().register(userKey.getIdentity()); | UserRegisterOperation userRegOp = txBuilder.users().register(userKey.getIdentity()); | ||||
@@ -74,7 +74,6 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe | |||||
return contractCodeDeployOpBuilder; | return contractCodeDeployOpBuilder; | ||||
} | } | ||||
@Override | |||||
public ContractEventSendOperationBuilder contractEvents() { | public ContractEventSendOperationBuilder contractEvents() { | ||||
return contractEventSendOpBuilder; | return contractEventSendOpBuilder; | ||||
} | } | ||||
@@ -3,19 +3,46 @@ package com.jd.blockchain.transaction; | |||||
import java.lang.reflect.InvocationHandler; | import java.lang.reflect.InvocationHandler; | ||||
import java.lang.reflect.Method; | 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; | private ContractEventSendOperationBuilder sendOpBuilder; | ||||
public ContractInvocationProxy(Bytes contractAddress, ContractType contractType, | |||||
ContractEventSendOperationBuilder sendOpBuilder) { | |||||
this.contractAddress = contractAddress; | |||||
this.contractType = contractType; | |||||
this.sendOpBuilder = sendOpBuilder; | |||||
} | |||||
@Override | @Override | ||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | 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; | return null; | ||||
} | } | ||||
@@ -1,6 +1,45 @@ | |||||
package com.jd.blockchain.transaction; | 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; | |||||
} | |||||
} | } |
@@ -4,12 +4,12 @@ import java.lang.reflect.Method; | |||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.SortedMap; | import java.util.SortedMap; | ||||
class ContractType { | |||||
public class ContractType { | |||||
private String name; | private String name; | ||||
private SortedMap<String, Method> events; | private SortedMap<String, Method> events; | ||||
private SortedMap<Method, String> handleMethods; | private SortedMap<Method, String> handleMethods; | ||||
/** | /** | ||||
@@ -17,7 +17,7 @@ class ContractType { | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
Set<String> getEvents() { | |||||
public Set<String> getEvents() { | |||||
return events.keySet(); | return events.keySet(); | ||||
} | } | ||||
@@ -29,7 +29,7 @@ class ContractType { | |||||
* @param method | * @param method | ||||
* @return | * @return | ||||
*/ | */ | ||||
String getEvent(Method method) { | |||||
public String getEvent(Method method) { | |||||
return handleMethods.get(method); | return handleMethods.get(method); | ||||
} | } | ||||
@@ -41,16 +41,15 @@ class ContractType { | |||||
* @param event | * @param event | ||||
* @return | * @return | ||||
*/ | */ | ||||
Method getHandleMethod(String event) { | |||||
public Method getHandleMethod(String event) { | |||||
return events.get(event); | return events.get(event); | ||||
} | } | ||||
private ContractType() { | private ContractType() { | ||||
} | } | ||||
// public static ContractType resolve(Class<?> contractIntf) { | |||||
// | |||||
// } | |||||
// public static ContractType resolve(Class<?> contractIntf) { | |||||
// | |||||
// } | |||||
} | } |
@@ -1,14 +1,25 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import com.jd.blockchain.utils.Bytes; | |||||
public interface EventOperator { | public interface EventOperator { | ||||
// /** | |||||
// * 合约事件; | |||||
// * | |||||
// * @return | |||||
// */ | |||||
// @Deprecated | |||||
// ContractEventSendOperationBuilder contractEvents(); | |||||
/** | /** | ||||
* 部署合约; | |||||
* 创建调用合约的代理实例; | |||||
* | * | ||||
* @param address | |||||
* @param contractIntf | |||||
* @return | * @return | ||||
*/ | */ | ||||
@Deprecated | |||||
ContractEventSendOperationBuilder contractEvents(); | |||||
<T> T contract(String address, Class<T> contractIntf); | |||||
/** | /** | ||||
* 创建调用合约的代理实例; | * 创建调用合约的代理实例; | ||||
@@ -17,6 +28,6 @@ public interface EventOperator { | |||||
* @param contractIntf | * @param contractIntf | ||||
* @return | * @return | ||||
*/ | */ | ||||
<T> T contract(String address, Class<T> contractIntf); | |||||
<T> T contract(Bytes address, Class<T> contractIntf); | |||||
} | } |
@@ -21,6 +21,8 @@ public class TxBuilder implements TransactionBuilder { | |||||
private static final String DEFAULT_HASH_ALGORITHM = "SHA256"; | private static final String DEFAULT_HASH_ALGORITHM = "SHA256"; | ||||
private HashDigest ledgerHash; | private HashDigest ledgerHash; | ||||
private ContractInvocationProxyBuilder contractInvoProxyBuilder; | |||||
public TxBuilder(HashDigest ledgerHash) { | public TxBuilder(HashDigest ledgerHash) { | ||||
this.ledgerHash = ledgerHash; | this.ledgerHash = ledgerHash; | ||||
@@ -79,15 +81,18 @@ public class TxBuilder implements TransactionBuilder { | |||||
return opFactory.contracts(); | return opFactory.contracts(); | ||||
} | } | ||||
@Override | |||||
public ContractEventSendOperationBuilder contractEvents() { | public ContractEventSendOperationBuilder contractEvents() { | ||||
return opFactory.contractEvents(); | return opFactory.contractEvents(); | ||||
} | } | ||||
@Override | |||||
public <T> T contract(Bytes address, Class<T> contractIntf) { | |||||
return contractInvoProxyBuilder.create(address, contractIntf, opFactory); | |||||
} | |||||
@Override | @Override | ||||
public <T> T contract(String address, Class<T> contractIntf) { | 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); | |||||
} | } | ||||
} | } |
@@ -53,10 +53,10 @@ public class TxTemplate implements TransactionTemplate { | |||||
return txBuilder.contracts(); | return txBuilder.contracts(); | ||||
} | } | ||||
@Override | |||||
public ContractEventSendOperationBuilder contractEvents() { | |||||
return txBuilder.contractEvents(); | |||||
} | |||||
// @Override | |||||
// public ContractEventSendOperationBuilder contractEvents() { | |||||
// return txBuilder.contractEvents(); | |||||
// } | |||||
@Override | @Override | ||||
public <T> T contract(String address, Class<T> contractIntf) { | public <T> T contract(String address, Class<T> contractIntf) { | ||||
@@ -4,8 +4,6 @@ import com.jd.blockchain.consensus.service.NodeServer; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | ||||
import java.util.List; | |||||
public interface LedgerBindingConfigAware { | public interface LedgerBindingConfigAware { | ||||
void setConfig(LedgerBindingConfig config); | void setConfig(LedgerBindingConfig config); | ||||
@@ -68,9 +68,12 @@ public class SDKDemo_Contract { | |||||
Remark remark = new Remark(); | Remark remark = new Remark(); | ||||
String remarkJSON = JSONSerializeUtils.serializeToJSON(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 准备就绪; | // TX 准备就绪; | ||||