diff --git a/deploy/docker-sdk/pom.xml b/deploy/docker-sdk/pom.xml
new file mode 100644
index 00000000..1c7e0787
--- /dev/null
+++ b/deploy/docker-sdk/pom.xml
@@ -0,0 +1,70 @@
+
+
+
+ deploy-root
+ com.jd.blockchain
+ 1.4.0-SNAPSHOT
+
+ 4.0.0
+
+ docker-sdk
+
+
+ 1.3.0.RELEASE
+
+
+
+
+ com.jd.blockchain
+ crypto-classic
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ crypto-sm
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ ledger-model
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ sdk-client
+ ${ledger.version}
+
+
+
+
+
+
+ maven-assembly-plugin
+
+ false
+
+ jar-with-dependencies
+
+
+
+
+ com.jd.blockchain.SDKDemo
+
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/deploy/docker-sdk/src/main/java/com/jd/blockchain/ContractParams.java b/deploy/docker-sdk/src/main/java/com/jd/blockchain/ContractParams.java
new file mode 100644
index 00000000..b1464b4e
--- /dev/null
+++ b/deploy/docker-sdk/src/main/java/com/jd/blockchain/ContractParams.java
@@ -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;
+ }
+}
diff --git a/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo.java b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo.java
new file mode 100644
index 00000000..5e02ccf1
--- /dev/null
+++ b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo.java
@@ -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));
+ }
+}
diff --git a/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo_Constant.java b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo_Constant.java
new file mode 100644
index 00000000..ec7ec7c2
--- /dev/null
+++ b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDKDemo_Constant.java
@@ -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);
+ }
+ }
+}
diff --git a/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDK_Base_Demo.java b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDK_Base_Demo.java
new file mode 100644
index 00000000..51cc1741
--- /dev/null
+++ b/deploy/docker-sdk/src/main/java/com/jd/blockchain/SDK_Base_Demo.java
@@ -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 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;
+ }
+}
diff --git a/deploy/docker-sdk/src/main/java/com/jd/chain/contract/TransferContract.java b/deploy/docker-sdk/src/main/java/com/jd/chain/contract/TransferContract.java
new file mode 100644
index 00000000..a3a41529
--- /dev/null
+++ b/deploy/docker-sdk/src/main/java/com/jd/chain/contract/TransferContract.java
@@ -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);
+}
diff --git a/deploy/docker-sdk/src/main/resources/contract-compile-1.3.0.RELEASE.car b/deploy/docker-sdk/src/main/resources/contract-compile-1.3.0.RELEASE.car
new file mode 100644
index 00000000..cd7c3c82
Binary files /dev/null and b/deploy/docker-sdk/src/main/resources/contract-compile-1.3.0.RELEASE.car differ