@@ -5,6 +5,7 @@ import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.IllegalDataException; | |||
import org.springframework.util.ReflectionUtils; | |||
import java.math.BigDecimal; | |||
import java.nio.ByteBuffer; | |||
@@ -117,7 +118,7 @@ public class ContractSerializeUtils { | |||
DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_TEXT, CONTRACT_TEXT.class); | |||
DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BINARY, CONTRACT_BINARY.class); | |||
DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BIG_INT, CONTRACT_BIG_INT.class); | |||
// DATA_CONTRACT_MAP.put(DataCodes.TX_CONTENT_BODY, TransactionContentBody.class); | |||
DATA_CONTRACT_MAP.put(DataCodes.CONTRACT_BIZ_CONTENT, ContractBizContent.class); | |||
return DATA_CONTRACT_MAP; | |||
} | |||
@@ -140,8 +141,12 @@ public class ContractSerializeUtils { | |||
return (CONTRACT_BINARY) () -> (Bytes) object; | |||
}else if(getDataIntf().get(dataContract.code()).equals(CONTRACT_BIG_INT.class)){ | |||
return (CONTRACT_BIG_INT) () -> new BigDecimal(object.toString()); | |||
}else if(getDataIntf().get(dataContract.code()).equals(ContractBizContent.class)){ | |||
ContractBizContent contractBizContent = (ContractBizContent)object; | |||
return contractBizContent; | |||
}else { | |||
throw new IllegalDataException("cann't get new Object by dataContract and object."); | |||
} | |||
return null; | |||
} | |||
/** | |||
@@ -164,6 +169,8 @@ public class ContractSerializeUtils { | |||
return CONTRACT_TEXT.class; | |||
}else if(classType.equals(Bytes.class)){ | |||
return CONTRACT_BINARY.class; | |||
}else if(classType.equals(BigDecimal.class)){ | |||
return CONTRACT_BIG_INT.class; | |||
} | |||
return null; | |||
} | |||
@@ -22,9 +22,16 @@ public interface ContractBizContent { | |||
HashDigest getLedgerHash(); | |||
/** | |||
* 操作列表; | |||
* 地址; | |||
* @return | |||
*/ | |||
@DataField(order = 2, list = true, refContract = true, genericContract = true) | |||
Operation[] getOperations(); | |||
@DataField(order = 2, primitiveType = PrimitiveType.TEXT) | |||
String getAddr(); | |||
/** | |||
* 年龄; | |||
* @return | |||
*/ | |||
@DataField(order = 3, primitiveType = PrimitiveType.INT32) | |||
int getAge(); | |||
} |
@@ -62,7 +62,7 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl | |||
DataContractRegistry.register(CONTRACT_INT64.class); | |||
DataContractRegistry.register(CONTRACT_TEXT.class); | |||
DataContractRegistry.register(CONTRACT_BINARY.class); | |||
// DataContractRegistry.register(CONTRACT_BIG_INT.class); | |||
DataContractRegistry.register(ContractBizContent.class); | |||
ByteArrayObjectUtil.init(); | |||
} | |||
@@ -4,9 +4,12 @@ import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
import com.jd.blockchain.ledger.ContractBizContent; | |||
import com.jd.blockchain.ledger.TransactionContentBody; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.math.BigDecimal; | |||
/** | |||
* 示例:一个“资产管理”智能合约; | |||
* | |||
@@ -22,19 +25,16 @@ public interface AssetContract2 { | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset-0") | |||
void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody, | |||
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress); | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
/** | |||
* issue asset; | |||
* @param transactionContentBody | |||
* @param contractBizContent | |||
* @param assetHolderAddress | |||
* @param cashNumber | |||
*/ | |||
@ContractEvent(name = "issue-asset") | |||
public void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody, | |||
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress, | |||
@DataContract(code = DataCodes.CONTRACT_INT64) long cashNumber); | |||
public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
/** | |||
* Bytes can bring the byte[]; | |||
@@ -49,5 +49,5 @@ public interface AssetContract2 { | |||
void issue(Byte bytes, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-4") | |||
void issue1(byte[] bytes, String assetHolderAddress, long cashNumber); | |||
void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
} |
@@ -23,7 +23,9 @@ import org.springframework.core.io.ClassPathResource; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.math.BigDecimal; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
/** | |||
@@ -64,21 +66,27 @@ public class SDK_Contract_Test { | |||
/** | |||
* 演示合约执行的过程; | |||
*/ | |||
@Test | |||
// @Test | |||
public void demoContract1() { | |||
String dataAddress = registerData4Contract(); | |||
// 发起交易; | |||
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
String contractAddress = "LdeNhjPGzHcHL6rLcJ7whHxUbn9Tv7qSKRfEA"; | |||
String contractAddress = "LdeNg8JHFCKABJt6AaRNVCZPgY4ofGPd8MgcR"; | |||
AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
TransactionContentBody transactionContentBody = new TransactionContentBody() { | |||
ContractBizContent contractBizContent = new ContractBizContent() { | |||
@Override | |||
public HashDigest getLedgerHash() { | |||
return new HashDigest(ClassicAlgorithm.SHA256, "zhaogw".getBytes()); | |||
} | |||
@Override | |||
public Operation[] getOperations() { | |||
return new Operation[0]; | |||
public String getAddr() { | |||
return "jinghailu street."; | |||
} | |||
@Override | |||
public int getAge() { | |||
return 100; | |||
} | |||
}; | |||
// assetContract.issue(transactionContentBody,contractAddress); | |||
@@ -86,13 +94,19 @@ public class SDK_Contract_Test { | |||
// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
// assetContract.issue(Bytes.fromString("zhaogw, contract based interface is OK!"),contractAddress,77777); | |||
Byte byteObj = Byte.parseByte("127"); | |||
assetContract.issue(byteObj,contractAddress,321123); | |||
assetContract.issue(byteObj,dataAddress,321123); | |||
assetContract.issue(contractBizContent,dataAddress); | |||
assetContract.issue(Byte.parseByte("126"),dataAddress,Bytes.fromString("100.234")); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(signKeyPair); | |||
// 提交交易; | |||
prepTx.commit(); | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
//check; | |||
KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,"total"); | |||
assertEquals("100",dataEntries[0].getValue().toString()); | |||
} | |||
@Test | |||
@@ -126,6 +140,22 @@ public class SDK_Contract_Test { | |||
this.setDataInDataAddress(dataAccount.getAddress(),keys,values2,1); | |||
} | |||
private String registerData4Contract(){ | |||
// 在本地定义 TX 模板 | |||
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
txTemp.dataAccount(dataAccount.getAddress()).set("total", 200, -1); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(signKeyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
assertTrue(transactionResponse.isSuccess()); | |||
return dataAccount.getAddress().toBase58(); | |||
} | |||
private void setDataInDataAddress(Bytes dataAddress, String[] keys, String[] values, long version){ | |||
// 在本地定义 TX 模板 | |||
TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
@@ -35,6 +35,7 @@ import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.math.BigDecimal; | |||
import java.net.URL; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
@@ -54,6 +55,7 @@ import static org.junit.Assert.*; | |||
*/ | |||
public class IntegrationBase { | |||
public static String KEY_TOTAL = "total"; | |||
static { | |||
DataContractRegistry.register(LedgerInitOperation.class); | |||
@@ -107,6 +109,7 @@ public class IntegrationBase { | |||
// 定义交易; | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(dataAccount.getIdentity()); | |||
txTpl.dataAccount(dataAccount.getAddress()).set("total", 200, -1); | |||
// 签名; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
@@ -440,6 +443,8 @@ public class IntegrationBase { | |||
static HashDigest txContentHash; | |||
public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, | |||
BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||
KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService); | |||
System.out.println("adminKey="+ AddressEncoding.generateAddress(adminKey.getPubKey())); | |||
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); | |||
System.out.println("userKey="+userKey.getAddress()); | |||
@@ -458,32 +463,34 @@ public class IntegrationBase { | |||
TransactionResponse txResp = ptx.commit(); | |||
assertTrue(txResp.isSuccess()); | |||
// 验证结果; | |||
txResp.getContentHash(); | |||
// 验证结果hash;请求的hash=相应的内容hash; | |||
assertEquals(ptx.getHash(),txResp.getContentHash()); | |||
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||
byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block).getContract(contractDeployKey.getAddress()) | |||
.getChainCode(); | |||
assertArrayEquals(contractCode, contractCodeInDb); | |||
txContentHash = ptx.getHash(); | |||
// execute the contract; | |||
testContractExe(adminKey, ledgerHash, userKey, blockchainService, ledgerRepository, AssetContract.class); | |||
testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); | |||
return block; | |||
} | |||
private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, | |||
BlockchainService blockchainService,LedgerRepository ledgerRepository,Class<T> contractIntf) { | |||
private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, | |||
BlockchainService blockchainService,LedgerRepository ledgerRepository) { | |||
LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); | |||
LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); | |||
// 定义交易; | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
Byte byteObj = Byte.parseByte("127"); | |||
Byte byteObj = Byte.parseByte("123"); | |||
// txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | |||
// contractDeployKey.getAddress().toBase58(),321123); | |||
txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, | |||
contractDeployKey.getAddress().toBase58(),321123); | |||
dataKey.getAddress().toBase58(),Bytes.fromString("123321")); | |||
// txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj,dataKey.getAddress().toBase58(),123456); | |||
// 签名; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
@@ -493,8 +500,11 @@ public class IntegrationBase { | |||
TransactionResponse txResp = ptx.commit(); | |||
// 验证结果; | |||
txResp.getContentHash(); | |||
Assert.assertTrue(txResp.isSuccess()); | |||
assertEquals(ptx.getHash(),txResp.getContentHash()); | |||
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); | |||
KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(0,1); | |||
assertEquals("100",kvDataEntries[0].getValue().toString()); | |||
} | |||
/** | |||
@@ -1,12 +1,12 @@ | |||
package test.com.jd.blockchain.intgr.contract; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.consts.DataCodes; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
import com.jd.blockchain.ledger.TransactionContentBody; | |||
import com.jd.blockchain.ledger.ContractBizContent; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.math.BigDecimal; | |||
/** | |||
* 示例:一个“资产管理”智能合约; | |||
* | |||
@@ -22,32 +22,23 @@ public interface AssetContract2 { | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset-0") | |||
void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody, | |||
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress); | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
/** | |||
* issue asset; | |||
* @param transactionContentBody | |||
* 发行资产; | |||
* 新发行的资产数量; | |||
* @param assetHolderAddress | |||
* @param cashNumber | |||
* 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset") | |||
public void issue(@DataContract(code = DataCodes.TX_CONTENT_BODY) TransactionContentBody transactionContentBody, | |||
@DataContract(code = DataCodes.CONTRACT_TEXT) String assetHolderAddress, | |||
@DataContract(code = DataCodes.CONTRACT_INT64) long cashNumber); | |||
void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
/** | |||
* Bytes can bring the byte[]; | |||
* @param bytes | |||
* @param assetHolderAddress | |||
* @param cashNumber | |||
*/ | |||
@ContractEvent(name = "issue-asset-2") | |||
void issue(Bytes bytes, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-3") | |||
void issue(Byte bytes, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-3") | |||
void issue(Byte byteObj, String assetHolderAddress, long cashNumber); | |||
@ContractEvent(name = "issue-asset-4") | |||
void issue1(byte[] bytes, String assetHolderAddress, long cashNumber); | |||
void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
} |