@@ -0,0 +1,70 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>deploy-root</artifactId> | |||
<groupId>com.jd.blockchain</groupId> | |||
<version>1.4.0-SNAPSHOT</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>docker-sdk</artifactId> | |||
<properties> | |||
<ledger.version>1.3.0.RELEASE</ledger.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-classic</artifactId> | |||
<version>${ledger.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-sm</artifactId> | |||
<version>${ledger.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
<version>${ledger.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
<version>${ledger.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<artifactId>maven-assembly-plugin</artifactId> | |||
<configuration> | |||
<appendAssemblyId>false</appendAssemblyId> | |||
<descriptorRefs> | |||
<descriptorRef>jar-with-dependencies</descriptorRef> | |||
</descriptorRefs> | |||
<archive> | |||
<manifest> | |||
<!-- 程序入口 --> | |||
<mainClass>com.jd.blockchain.SDKDemo</mainClass> | |||
</manifest> | |||
</archive> | |||
</configuration> | |||
<executions> | |||
<execution> | |||
<id>make-assembly</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>single</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,107 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
public class ContractParams { | |||
String contractZipName; | |||
BlockchainKeypair signAdminKey; | |||
BlockchainIdentity contractIdentity; | |||
boolean isDeploy; | |||
boolean isExecute; | |||
boolean hasVersion; //contract's version; | |||
long version; | |||
BlockchainIdentity dataAccount; | |||
String key; | |||
String value; | |||
public String getContractZipName() { | |||
return contractZipName; | |||
} | |||
public ContractParams setContractZipName(String contractZipName) { | |||
this.contractZipName = contractZipName; | |||
return this; | |||
} | |||
public BlockchainKeypair getSignAdminKey() { | |||
return signAdminKey; | |||
} | |||
public ContractParams setSignAdminKey(BlockchainKeypair signAdminKey) { | |||
this.signAdminKey = signAdminKey; | |||
return this; | |||
} | |||
public BlockchainIdentity getContractIdentity() { | |||
return contractIdentity; | |||
} | |||
public ContractParams setContractIdentity(BlockchainIdentity contractIdentity) { | |||
this.contractIdentity = contractIdentity; | |||
return this; | |||
} | |||
public boolean isDeploy() { | |||
return isDeploy; | |||
} | |||
public ContractParams setDeploy(boolean deploy) { | |||
isDeploy = deploy; | |||
return this; | |||
} | |||
public boolean isExecute() { | |||
return isExecute; | |||
} | |||
public ContractParams setExecute(boolean execute) { | |||
isExecute = execute; | |||
return this; | |||
} | |||
public boolean isHasVersion() { | |||
return hasVersion; | |||
} | |||
public ContractParams setHasVersion(boolean hasVersion) { | |||
this.hasVersion = hasVersion; | |||
return this; | |||
} | |||
public long getVersion() { | |||
return version; | |||
} | |||
public ContractParams setVersion(long version) { | |||
this.version = version; | |||
return this; | |||
} | |||
public BlockchainIdentity getDataAccount() { | |||
return dataAccount; | |||
} | |||
public ContractParams setDataAccount(BlockchainIdentity dataAccount) { | |||
this.dataAccount = dataAccount; | |||
return this; | |||
} | |||
public String getKey() { | |||
return key; | |||
} | |||
public ContractParams setKey(String key) { | |||
this.key = key; | |||
return this; | |||
} | |||
public String getValue() { | |||
return value; | |||
} | |||
public ContractParams setValue(String value) { | |||
this.value = value; | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.ledger.*; | |||
import org.apache.commons.codec.binary.Base64; | |||
import java.util.Random; | |||
import java.util.UUID; | |||
public class SDKDemo extends SDK_Base_Demo{ | |||
public static void main(String[] args) { | |||
SDKDemo sdkDemo = new SDKDemo(); | |||
//注册用户; | |||
sdkDemo.registerUsers(); | |||
//构建数据账户; | |||
sdkDemo.genDataAccount(); | |||
//发布和执行合约; | |||
sdkDemo.deployContract(); | |||
} | |||
//注册用户; | |||
public void registerUsers(){ | |||
this.registerUser(); | |||
} | |||
//构建数据账户; | |||
public void genDataAccount(){ | |||
byte[] arr = new byte[1024]; | |||
new Random().nextBytes(arr); | |||
String value = Base64.encodeBase64String(arr); | |||
this.insertData(null,null,"key1",value,-1); | |||
} | |||
public BlockchainKeypair insertData(BlockchainKeypair dataAccount, BlockchainKeypair signAdminKey, | |||
String key, String value, long version) { | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
//采用KeyGenerator来生成BlockchainKeypair; | |||
if(dataAccount == null){ | |||
dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
} | |||
System.out.println("current dataAccount=" + dataAccount.getAddress()); | |||
txTemp.dataAccount(dataAccount.getAddress()).setText(key, value, version); | |||
txTemp.dataAccount(dataAccount.getAddress()).setTimestamp(UUID.randomUUID().toString(),System.currentTimeMillis(),-1); | |||
// TX 准备就绪 | |||
commit(txTemp,signAdminKey); | |||
//get the version | |||
TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, | |||
dataAccount.getAddress().toBase58(), key); | |||
System.out.println(String.format("key1 info:key=%s,value=%s,version=%d", | |||
kvData[0].getKey(),kvData[0].getValue().toString(),kvData[0].getVersion())); | |||
return dataAccount; | |||
} | |||
public void deployContract(){ | |||
ContractParams contractParams = new ContractParams(); | |||
contractParams.setContractZipName("contract-compile-1.3.0.RELEASE.car").setDeploy(true).setExecute(false); | |||
BlockchainIdentity contractAddress = | |||
this.contractHandle(contractParams); | |||
contractParams.setContractIdentity(contractAddress); | |||
this.contractHandle(contractParams); | |||
this.contractHandle(contractParams.setExecute(true)); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.crypto.KeyGenUtils; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import org.apache.commons.io.FileUtils; | |||
import org.springframework.core.io.ClassPathResource; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
public class SDKDemo_Constant { | |||
public static String GW_IPADDR = "localhost"; | |||
public static int GW_PORT = 8080; | |||
public static String GW_PUB_KEY = "3snPdw7i7PisoLpqqtETdqzQeKVjQReP2Eid9wYK67q9z6trvByGZs"; | |||
public static String GW_PRIV_KEY = "177gk2PbxhHeEdfAAqGfShJQyeV4XvGsJ9CvJFUbToBqwW1YJd5obicySE1St6SvPPaRrUP"; | |||
public static String GW_PASSWORD = "8EjkXVSTxMFjCvNNsTo8RBMDEVQmk7gYkW4SCDuvdsBG"; | |||
public static PrivKey gwPrivkey0 = KeyGenUtils.decodePrivKey(GW_PRIV_KEY, GW_PASSWORD); | |||
public static PubKey gwPubKey0 = KeyGenUtils.decodePubKey(GW_PUB_KEY); | |||
public static BlockchainKeypair adminKey = new BlockchainKeypair(gwPubKey0, gwPrivkey0); | |||
public static final byte[] readChainCodes(String contractZip) { | |||
// 构建合约的字节数组; | |||
try { | |||
ClassPathResource contractPath = new ClassPathResource(contractZip); | |||
// File contractFile = new File(contractPath.getURI()); | |||
InputStream in = contractPath.getInputStream(); | |||
// 将文件写入至config目录下 | |||
File directory = new File("."); | |||
String configPath = directory.getAbsolutePath() + File.separator + "contract.jar"; | |||
File targetFile = new File(configPath); | |||
// 先将原来文件删除再Copy | |||
if (targetFile.exists()) { | |||
FileUtils.forceDelete(targetFile); | |||
} | |||
FileUtils.copyInputStreamToFile(in, targetFile); | |||
return FileUtils.readFileToByteArray(targetFile); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,191 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.chain.contract.TransferContract; | |||
import static com.jd.blockchain.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
public abstract class SDK_Base_Demo { | |||
protected BlockchainKeypair adminKey; | |||
protected HashDigest ledgerHash; | |||
protected BlockchainService blockchainService; | |||
public SDK_Base_Demo() { | |||
init(); | |||
} | |||
public void init() { | |||
// 生成连接网关的账号 | |||
adminKey = SDKDemo_Constant.adminKey; | |||
// 连接网关 | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(SDKDemo_Constant.GW_IPADDR, | |||
SDKDemo_Constant.GW_PORT, false, adminKey); | |||
// 获取网关对应的Service处理类 | |||
blockchainService = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
// 获取当前账本Hash | |||
ledgerHash = ledgerHashs[0]; | |||
} | |||
public TransactionResponse commit(TransactionTemplate txTpl){ | |||
return this.commitA(txTpl,null); | |||
} | |||
/** | |||
* 默认使用A方式commit; | |||
* @param txTpl | |||
* @param signAdminKey | |||
* @return | |||
*/ | |||
public TransactionResponse commit(TransactionTemplate txTpl, BlockchainKeypair signAdminKey){ | |||
return commitA(txTpl, signAdminKey); | |||
} | |||
/** | |||
* 采用A方式提交; | |||
* @param txTpl | |||
* @param signAdminKey | |||
* @return | |||
*/ | |||
public TransactionResponse commitA(TransactionTemplate txTpl, BlockchainKeypair signAdminKey) { | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
if(signAdminKey != null){ | |||
System.out.println("signAdminKey's pubKey = "+signAdminKey.getIdentity().getPubKey()); | |||
ptx.sign(signAdminKey); | |||
}else { | |||
System.out.println("adminKey's pubKey = "+adminKey.getIdentity().getPubKey()); | |||
ptx.sign(adminKey); | |||
} | |||
TransactionResponse transactionResponse = ptx.commit(); | |||
if (transactionResponse.isSuccess()) { | |||
System.out.println(String.format("height=%d, ###OK#, contentHash=%s, executionState=%s", | |||
transactionResponse.getBlockHeight(), | |||
transactionResponse.getContentHash(), transactionResponse.getExecutionState().toString())); | |||
} else { | |||
System.out.println(String.format("height=%d, ###exception#, contentHash=%s, executionState=%s", | |||
transactionResponse.getBlockHeight(), | |||
transactionResponse.getContentHash(), transactionResponse.getExecutionState().toString())); | |||
} | |||
return transactionResponse; | |||
} | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public BlockchainKeypair registerUser() { | |||
return this.registerUser(null,null,null); | |||
} | |||
public BlockchainKeypair registerUser(String cryptoType, BlockchainKeypair signAdminKey, BlockchainKeypair userKeypair) { | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
if(userKeypair == null){ | |||
if("SM2".equals(cryptoType)){ | |||
userKeypair = BlockchainKeyGenerator.getInstance().generate(cryptoType); | |||
}else { | |||
userKeypair = BlockchainKeyGenerator.getInstance().generate(); | |||
} | |||
} | |||
System.out.println("user'address="+userKeypair.getAddress()); | |||
txTemp.users().register(userKeypair.getIdentity()); | |||
// TX 准备就绪; | |||
commit(txTemp,signAdminKey); | |||
return userKeypair; | |||
} | |||
public BlockchainKeypair registerUser(BlockchainKeypair signAdminKey, BlockchainKeypair userKeypair) { | |||
return registerUser(null,signAdminKey,userKeypair); | |||
} | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public BlockchainKeypair registerUserByNewSigner(BlockchainKeypair signer) { | |||
return this.registerUser(signer,null); | |||
} | |||
public BlockchainIdentity createDataAccount() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
commit(txTpl); | |||
return newDataAccount.getIdentity(); | |||
} | |||
public String create1(Bytes contractAddress, String address, String account, String content) { | |||
System.out.println(String.format("params,String address=%s, String account=%s, String content=%s, Bytes contractAddress=%s", | |||
address,account,content,contractAddress.toBase58())); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract guanghu = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(guanghu.putval(address, account, content, System.currentTimeMillis())); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
public BlockchainIdentity contractHandle(ContractParams contractParams) { | |||
if(contractParams.getContractZipName() == null){ | |||
contractParams.setContractZipName("contract-JDChain-Contract.jar"); | |||
} | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
Bytes contractAddress = null; | |||
if(contractParams.getContractIdentity() != null){ | |||
contractAddress = contractParams.getContractIdentity().getAddress(); | |||
} | |||
if(contractParams.isDeploy){ | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes(contractParams.getContractZipName()); | |||
// 生成一个合约账号 | |||
if(contractParams.getContractIdentity() == null){ | |||
contractParams.setContractIdentity(BlockchainKeyGenerator.getInstance().generate().getIdentity()); | |||
} | |||
contractAddress = contractParams.getContractIdentity().getAddress(); | |||
System.out.println("contract's address=" + contractAddress); | |||
// 生成发布合约操作 | |||
if(contractParams.isHasVersion()){ | |||
// txTpl.contracts().deploy(contractParams.contractIdentity, contractCode, contractParams.version); | |||
} else { | |||
txTpl.contracts().deploy(contractParams.contractIdentity, contractCode); | |||
} | |||
// 生成预发布交易; | |||
commit(txTpl,contractParams.getSignAdminKey()); | |||
} | |||
if(contractParams.isExecute){ | |||
// 注册一个数据账户 | |||
if(contractParams.dataAccount == null){ | |||
contractParams.dataAccount = createDataAccount(); | |||
contractParams.key = "jd_zhangsan"; | |||
contractParams.value = "{\"dest\":\"KA006\",\"id\":\"cc-fin08-01\",\"items\":\"FIN001|3030\",\"source\":\"FIN001\"}"; | |||
} | |||
// 获取数据账户地址x | |||
String dataAddress = contractParams.dataAccount.getAddress().toBase58(); | |||
// 打印数据账户地址 | |||
System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
System.out.println("return value = "+create1(contractAddress, dataAddress, contractParams.key, contractParams.value)); | |||
} | |||
return contractParams.contractIdentity; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.jd.chain.contract; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
@Contract | |||
public interface TransferContract { | |||
@ContractEvent(name = "create") | |||
String create(String address, String account, long money); | |||
@ContractEvent(name = "transfer") | |||
String transfer(String address, String from, String to, long money); | |||
@ContractEvent(name = "read") | |||
long read(String address, String account); | |||
@ContractEvent(name = "readAll") | |||
String readAll(String address, String account); | |||
@ContractEvent(name = "putval1") | |||
String putval(String address, String account, String content, Long time); | |||
@ContractEvent(name = "putvalBif") | |||
String putvalBifurcation(String address, String account, String content, String isHalf); | |||
@ContractEvent(name = "getTxSigners") | |||
String getTxSigners(String input); | |||
@ContractEvent(name = "test") | |||
String test(String input); | |||
} |