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