update samples See merge request jd-blockchain/jdchain!22tags/1.4.0^2
| @@ -0,0 +1,60 @@ | |||
| ## JD Chain Samples | |||
| 本项目为`JD Chain SDK`的使用样例,开发者可以参考此项目快速上手`JD Chain SDK`,主要包括[交易发送查询](#交易发送查询),[合约开发部署](#合约开发部署)两部分。 | |||
| 本项目提供了基于内存的`JD Chain`四节点+网关的网络环境启动程序[TestNet](/sdk-samples/src/main/java/com/jdchain/samples/sdk/TestNet.java),运行`TestNet`的`main`方法启动测试网络,等待日志输出:`START TESTNET SUCCESS`,网络启动成功会写入一些测试数据,可直接运行本项目提供的所有测试用例。 | |||
| > `TestNet`测试网络默认会占用`8910`/`8920`/`8930`/`8940`/`8911`/`8921`/`8931`/`8941`用于共识服务,`12000`/`12010`/`12020`/`12030`用于四节点`API`服务端口,`11000`用于网关`API`服务端口,启动前请检查相关端口可用。 | |||
| ### 交易发送查询 | |||
| 相关代码放在[sdk-sample](/sdk-samples/src)下。 | |||
| > 若并非使用`TestNet`启动的测试网络,开发者在运行本样例前,请根据实际环境修改[config.properties](/sdk-samples/src/main/resources/config.properties)中的网关配置,用户配置等信息。 | |||
| #### 交易发送 | |||
| 参照[UserSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/UserSample.java)实现注册用户,配置用户角色权限功能; | |||
| 参照[DataAccountSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/DataAccountSample.java)实现注册数据账户,存储`KV`数据功能; | |||
| 参照[EventSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/EventSample.java)实现注册事件账户,发布事件,事件监听功能; | |||
| 参照[ContractSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/ContractSample.java)实现合约调用,非插件方式合约部署功能。 | |||
| #### 数据查询 | |||
| 参照[QuerySample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/QuerySample.java)实现对于区块链上数据查询功能。 | |||
| ### 合约开发部署 | |||
| [contract-samples](/contract-samples/src)提供了通过合约注册用户,注册数据账户,注册事件账户,设置`KV`,发布事件的简单合约样例。 | |||
| > 若并非使用`TestNet`启动的测试网络,开发者在运行本样例前,请根据实际环境修改[pom.xml](/contract-samples/pom.xml)中的网关配置,用户配置等信息。 | |||
| 修改相关代码,确认配置正确,`contract-samples`项目目录下命令行执行: | |||
| - 合约打包 | |||
| ```bash | |||
| mvn clean package | |||
| ``` | |||
| 可以生成`car`包,可以用于`SDK`方式合约部署。 | |||
| - 合约部署 | |||
| ```bash | |||
| mvn clean deploy | |||
| ``` | |||
| 可以直接部署合约上链。 | |||
| ### 了解更多 | |||
| 访问[JD Chain官网](http://ledger.jd.com/)查阅设计及文档。 | |||
| 访问[github主页](https://github.com/blockchain-jd-com)阅读`JD Chain`源码并参与社区建设。 | |||
| Thanks~ | |||
| @@ -4,73 +4,79 @@ | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| </parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| </parent> | |||
| <artifactId>contract-samples</artifactId> | |||
| <!-- 声明为合约代码工程,编译输出扩展名为".car"合约代码 --> | |||
| <packaging>contract</packaging> | |||
| <artifactId>contract-samples</artifactId> | |||
| <name>contract-samples</name> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>ledger-model</artifactId> | |||
| <scope>provided</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <artifactId>contract-starter</artifactId> | |||
| <version>${framework.version}</version> | |||
| <scope>provided</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.alibaba</groupId> | |||
| <artifactId>fastjson</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <artifactId>maven-assembly-plugin</artifactId> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-compiler-plugin</artifactId> | |||
| <configuration> | |||
| <finalName>complex</finalName> | |||
| <appendAssemblyId>false</appendAssemblyId> | |||
| <archive> | |||
| <manifest> | |||
| <mainClass>com.jd.blockchain.contract.ComplexContractImpl</mainClass> | |||
| </manifest> | |||
| </archive> | |||
| <descriptorRefs> | |||
| <descriptorRef>jar-with-dependencies</descriptorRef> | |||
| </descriptorRefs> | |||
| <source>1.8</source> | |||
| <target>1.8</target> | |||
| <encoding>UTF-8</encoding> | |||
| <optimize>false</optimize> | |||
| <debug>true</debug> | |||
| <showDeprecation>false</showDeprecation> | |||
| <showWarnings>false</showWarnings> | |||
| </configuration> | |||
| <executions> | |||
| <execution> | |||
| <id>make-assembly</id> | |||
| <phase>package</phase> | |||
| <goals> | |||
| <goal>single</goal> | |||
| </goals> | |||
| </execution> | |||
| </executions> | |||
| </plugin> | |||
| <!-- 合约编译、打包、发布插件 --> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-deploy-plugin</artifactId> | |||
| <version>2.8.2</version> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>contract-maven-plugin</artifactId> | |||
| <version>${framework.version}</version> | |||
| <extensions>true</extensions> | |||
| <!-- 合约发布配置,不配置时请不要执行deploy阶段 --> | |||
| <configuration> | |||
| <skip>true</skip> | |||
| <!-- <maxCarSize>1</maxCarSize>--> | |||
| <!-- <maxCarSizeUnit>MB</maxCarSizeUnit>--> | |||
| <deployment> | |||
| <!-- 线上网关的配置,必选项 --> | |||
| <gateway> | |||
| <host>localhost</host> | |||
| <port>11000</port> | |||
| </gateway> | |||
| <!-- 账本,不填默认选择列表第一个 --> | |||
| <!-- <ledger>j5uXbSp6V9VCXxHQzp8pFGKoR9NrAkE6TUvfwWxvEVR5HK</ledger>--> | |||
| <!-- 更新已存在合约代码 --> | |||
| <!-- <contractAddress>--> | |||
| <!-- <pubKey></pubKey>--> | |||
| <!-- </contractAddress>--> | |||
| <!-- 用户信息,必选项,任何一个合约发布都需要拥有者进行签名 --> | |||
| <signer> | |||
| <pubKey>3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9</pubKey> | |||
| <privKey>177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x</privKey> | |||
| <privKeyPwd>DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY</privKeyPwd> | |||
| </signer> | |||
| </deployment> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </project> | |||
| @@ -1,7 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| @Contract | |||
| public interface ComplexContract { | |||
| @ContractEvent(name = "read-key") | |||
| String read(String address, String key); | |||
| } | |||
| @@ -1,12 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.alibaba.fastjson.JSON; | |||
| public class ComplexContractImpl implements ComplexContract { | |||
| @Override | |||
| public String read(String address, String key) { | |||
| String json = JSON.toJSONString(address); | |||
| return System.currentTimeMillis() + "" + json; | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| @Contract | |||
| public interface RandomContract { | |||
| @ContractEvent(name = "random-put") | |||
| void put(String address, String key, String value); | |||
| @ContractEvent(name = "random-putAndGet") | |||
| String putAndGet(String address, String key, String value); | |||
| } | |||
| @@ -1,43 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import java.util.Random; | |||
| public class RandomContractImpl implements RandomContract, EventProcessingAware { | |||
| private static final Random RANDOM_TIME = new Random(); | |||
| private ContractEventContext eventContext; | |||
| private HashDigest ledgerHash; | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| @Override | |||
| public void put(String address, String key, String value) { | |||
| String saveVal = value + "-" + RANDOM_TIME.nextInt(1024); | |||
| eventContext.getLedger().dataAccount(address).setText(key, saveVal, -1L); | |||
| } | |||
| @Override | |||
| public String putAndGet(String address, String key, String value) { | |||
| String saveVal = value + "-" + RANDOM_TIME.nextInt(1024); | |||
| eventContext.getLedger().dataAccount(address).setText(key, saveVal, -1L); | |||
| return address; | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| @Contract | |||
| public interface ReadContract { | |||
| @ContractEvent(name = "read-key") | |||
| String read(String address, String key); | |||
| @ContractEvent(name = "version-key") | |||
| Long readVersion(String address, String key); | |||
| int test(); | |||
| } | |||
| @@ -1,50 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| @Contract | |||
| public class ReadContractImpl implements EventProcessingAware, ReadContract { | |||
| private ContractEventContext eventContext; | |||
| private HashDigest ledgerHash; | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| @Override | |||
| @ContractEvent(name = "read-key") | |||
| public String read(String address, String key) { | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); | |||
| if (kvDataEntries != null && kvDataEntries.length == 1) { | |||
| return kvDataEntries[0].getValue().toString(); | |||
| } | |||
| return null; | |||
| } | |||
| @Override | |||
| @ContractEvent(name = "version-key") | |||
| public Long readVersion(String address, String key) { | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); | |||
| if (kvDataEntries != null && kvDataEntries.length == 1) { | |||
| return kvDataEntries[0].getVersion(); | |||
| } | |||
| return -1L; | |||
| } | |||
| @Override | |||
| public int test() { | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| @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); | |||
| } | |||
| @@ -1,109 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.ledger.KVDataVO; | |||
| import com.jd.blockchain.ledger.KVInfoVO; | |||
| public class TransferContractImpl implements EventProcessingAware, TransferContract { | |||
| private ContractEventContext eventContext; | |||
| private HashDigest ledgerHash; | |||
| @Override | |||
| public String create(String address, String account, long money) { | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
| // 肯定有返回值,但若不存在则返回version=-1 | |||
| if (kvDataEntries != null && kvDataEntries.length > 0) { | |||
| long currVersion = kvDataEntries[0].getVersion(); | |||
| if (currVersion > -1) { | |||
| throw new IllegalStateException(String.format("%s -> %s already have created !!!", address, account)); | |||
| } | |||
| eventContext.getLedger().dataAccount(address).setInt64(account, money, -1L); | |||
| } else { | |||
| throw new IllegalStateException(String.format("Ledger[%s] inner Error !!!", ledgerHash.toBase58())); | |||
| } | |||
| return String.format("DataAccountAddress[%s] -> Create(By Contract Operation) Account = %s and Money = %s Success!!! \r\n", | |||
| address, account, money); | |||
| } | |||
| @Override | |||
| public String transfer(String address, String from, String to, long money) { | |||
| // 首先查询余额 | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); | |||
| if (kvDataEntries == null || kvDataEntries.length != 2) { | |||
| throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to)); | |||
| } else { | |||
| // 判断from账号中钱数量是否足够 | |||
| long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L; | |||
| for (TypedKVEntry kvDataEntry : kvDataEntries) { | |||
| if (kvDataEntry.getKey().equals(from)) { | |||
| fromMoney = (long) kvDataEntry.getValue(); | |||
| fromVersion = kvDataEntry.getVersion(); | |||
| } else { | |||
| toMoney = (long) kvDataEntry.getValue(); | |||
| toVersion = kvDataEntry.getVersion(); | |||
| } | |||
| } | |||
| if (fromMoney < money) { | |||
| throw new IllegalStateException(String.format("%s -> %s not have enough money !!!", address, from)); | |||
| } | |||
| long fromNewMoney = fromMoney - money; | |||
| long toNewMoney = toMoney + money; | |||
| // 重新设置 | |||
| eventContext.getLedger().dataAccount(address).setInt64(from, fromNewMoney, fromVersion); | |||
| eventContext.getLedger().dataAccount(address).setInt64(to, toNewMoney, toVersion); | |||
| } | |||
| return String.format("DataAccountAddress[%s] transfer from [%s] to [%s] and [money = %s] Success !!!", address, from, to, money); | |||
| } | |||
| @Override | |||
| public long read(String address, String account) { | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
| if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
| return -1; | |||
| } | |||
| return (long)kvDataEntries[0].getValue(); | |||
| } | |||
| @Override | |||
| public String readAll(String address, String account) { | |||
| TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
| // 获取最新的版本号 | |||
| if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
| return ""; | |||
| } | |||
| long newestVersion = kvDataEntries[0].getVersion(); | |||
| if (newestVersion == -1) { | |||
| return ""; | |||
| } | |||
| KVDataVO[] kvDataVOS = new KVDataVO[1]; | |||
| long[] versions = new long[(int)newestVersion + 1]; | |||
| for (int i = 0; i < versions.length; i++) { | |||
| versions[i] = i; | |||
| } | |||
| KVDataVO kvDataVO = new KVDataVO(account, versions); | |||
| kvDataVOS[0] = kvDataVO; | |||
| KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS); | |||
| TypedKVEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); | |||
| return JSON.toJSONString(allEntries); | |||
| } | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
| } | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| package com.jdchain.samples.contract; | |||
| import com.jd.blockchain.contract.Contract; | |||
| import com.jd.blockchain.contract.ContractEvent; | |||
| /** | |||
| * 合约样例,提供通过合约创建用户/数据账户/事件账户,写入KV,发布事件等功能 | |||
| */ | |||
| @Contract | |||
| public interface SampleContract { | |||
| /** | |||
| * 设置KV | |||
| * | |||
| * @param address 数据账户地址 | |||
| * @param key 键 | |||
| * @param value 值 | |||
| * @param version 版本 | |||
| */ | |||
| @ContractEvent(name = "setKVWithVersion") | |||
| void setKVWithVersion(String address, String key, String value, long version); | |||
| /** | |||
| * 设置KV,基于最新数据版本 | |||
| * | |||
| * @param address 数据账户地址 | |||
| * @param key 键 | |||
| * @param value 值 | |||
| */ | |||
| @ContractEvent(name = "setKV") | |||
| void setKV(String address, String key, String value); | |||
| /** | |||
| * 注册用户 | |||
| * | |||
| * @param seed 种子,不小于32个字符 | |||
| */ | |||
| @ContractEvent(name = "registerUser") | |||
| String registerUser(String seed); | |||
| /** | |||
| * 注册数据账户 | |||
| * | |||
| * @param seed 种子,不小于32个字符 | |||
| */ | |||
| @ContractEvent(name = "registerDataAccount") | |||
| String registerDataAccount(String seed); | |||
| /** | |||
| * 注册事件账户 | |||
| * | |||
| * @param seed 种子,不小于32个字符 | |||
| */ | |||
| @ContractEvent(name = "registerEventAccount") | |||
| String registerEventAccount(String seed); | |||
| /** | |||
| * 发布事件 | |||
| * | |||
| * @param address 事件账户地址 | |||
| * @param topic 消息名称 | |||
| * @param content 内容 | |||
| * @param sequence 当前消息名称下最大序号(初始为-1) | |||
| */ | |||
| @ContractEvent(name = "publishEventWithSequence") | |||
| void publishEventWithSequence(String address, String topic, String content, long sequence); | |||
| /** | |||
| * 发布事件,基于最新时间序号 | |||
| * | |||
| * @param address 事件账户地址 | |||
| * @param topic 消息名称 | |||
| * @param content 内容 | |||
| */ | |||
| @ContractEvent(name = "publishEvent") | |||
| void publishEvent(String address, String topic, String content); | |||
| } | |||
| @@ -0,0 +1,106 @@ | |||
| package com.jdchain.samples.contract; | |||
| import com.jd.blockchain.contract.ContractEventContext; | |||
| import com.jd.blockchain.contract.EventProcessingAware; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.Event; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| /** | |||
| * 合约样例实现 | |||
| */ | |||
| public class SampleContractImpl implements EventProcessingAware, SampleContract { | |||
| private ContractEventContext eventContext; | |||
| @Override | |||
| public void setKVWithVersion(String address, String key, String value, long version) { | |||
| eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); | |||
| } | |||
| @Override | |||
| public void setKV(String address, String key, String value) { | |||
| // 查询最新版本,初始为-1 | |||
| TypedKVEntry[] entries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), address, key); | |||
| long version = -1; | |||
| if (null != entries && entries.length > 0) { | |||
| version = entries[0].getVersion(); | |||
| } | |||
| eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); | |||
| } | |||
| @Override | |||
| public String registerUser(String seed) { | |||
| CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
| SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
| AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
| BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| eventContext.getLedger().users().register(keypair.getIdentity()); | |||
| return keypair.getAddress().toBase58(); | |||
| } | |||
| @Override | |||
| public String registerDataAccount(String seed) { | |||
| CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
| SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
| AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
| BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| eventContext.getLedger().dataAccounts().register(keypair.getIdentity()); | |||
| return keypair.getAddress().toBase58(); | |||
| } | |||
| @Override | |||
| public String registerEventAccount(String seed) { | |||
| CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
| SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
| AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
| BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| eventContext.getLedger().eventAccounts().register(keypair.getIdentity()); | |||
| return keypair.getAddress().toBase58(); | |||
| } | |||
| @Override | |||
| public void publishEventWithSequence(String address, String topic, String content, long sequence) { | |||
| eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); | |||
| } | |||
| @Override | |||
| public void publishEvent(String address, String topic, String content) { | |||
| // 查询最新序号,初始为-1 | |||
| Event event = eventContext.getLedger().getLatestEvent(eventContext.getCurrentLedgerHash(), address, topic); | |||
| long sequence = -1; | |||
| if (null != event) { | |||
| sequence = event.getSequence(); | |||
| } | |||
| eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); | |||
| } | |||
| /** | |||
| * 合约方法调用前操作 | |||
| * | |||
| * @param eventContext | |||
| */ | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| } | |||
| /** | |||
| * 合约方法调用后操作 | |||
| * | |||
| * @param eventContext | |||
| * @param error | |||
| */ | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| } | |||
| } | |||
| @@ -1,65 +1,40 @@ | |||
| <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"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-parent</artifactId> | |||
| <version>1.1.4.RELEASE</version> | |||
| <relativePath>../project/parent</relativePath> | |||
| </parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| <packaging>pom</packaging> | |||
| <properties> | |||
| <framework.version>1.4.0.RELEASE</framework.version> | |||
| </properties> | |||
| <modules> | |||
| <module>../framework</module> | |||
| <module>sdk-samples</module> | |||
| <module>contract-samples</module> | |||
| </modules> | |||
| <dependencyManagement> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>sdk-client</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>ledger-model</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-classic</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-sm</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-base</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </dependencyManagement> | |||
| 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"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| <packaging>pom</packaging> | |||
| <properties> | |||
| <framework.version>1.4.0.RELEASE</framework.version> | |||
| </properties> | |||
| <modules> | |||
| <module>sdk-samples</module> | |||
| <module>contract-samples</module> | |||
| </modules> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-compiler-plugin</artifactId> | |||
| <version>3.8.1</version> | |||
| <configuration> | |||
| <source>1.8</source> | |||
| <target>1.8</target> | |||
| <encoding>UTF-8</encoding> | |||
| <optimize>false</optimize> | |||
| <debug>true</debug> | |||
| <showDeprecation>false</showDeprecation> | |||
| <showWarnings>false</showWarnings> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| </build> | |||
| </project> | |||
| @@ -1,83 +1,79 @@ | |||
| <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"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| </parent> | |||
| <artifactId>sdk-samples</artifactId> | |||
| 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"> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <parent> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>jdchain-samples</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| </parent> | |||
| <artifactId>sdk-samples</artifactId> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>sdk-client</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>ledger-model</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-classic</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-sm</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>contract-samples</artifactId> | |||
| <version>${project.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-base</artifactId> | |||
| <version>1.4.0.RELEASE</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-framework</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-classic</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-sm</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-utils-classic</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| </dependencies> | |||
| <dependencies> | |||
| <!--以下依赖用于SDK常规使用--> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>sdk-client</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-deploy-plugin</artifactId> | |||
| <configuration> | |||
| <skip>true</skip> | |||
| </configuration> | |||
| </plugin> | |||
| <!--<plugin> --> | |||
| <!--<groupId>org.springframework.boot</groupId> --> | |||
| <!--<artifactId>spring-boot-maven-plugin</artifactId> --> | |||
| <!--<configuration> --> | |||
| <!--<mainClass>com.jd.blockchain.sdk.samples.SDKDemo_RegisterTest</mainClass> --> | |||
| <!--</configuration> --> | |||
| <!--</plugin> --> | |||
| </plugins> | |||
| </build> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>sdk-rpc</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>crypto-classic</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>ledger-model</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <!--样例程序中使用到的合约--> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>contract-samples</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <!--以下依赖用于 com.jdchain.samples.Network 中四节点网路环境初始化和启动 --> | |||
| <dependency> | |||
| <groupId>org.reflections</groupId> | |||
| <artifactId>reflections</artifactId> | |||
| <version>0.9.12</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>tools-initializer</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>peer</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>utils-common</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.jd.blockchain</groupId> | |||
| <artifactId>gateway</artifactId> | |||
| <version>${framework.version}</version> | |||
| </dependency> | |||
| <!--Junit--> | |||
| <dependency> | |||
| <groupId>junit</groupId> | |||
| <artifactId>junit</artifactId> | |||
| <version>4.12</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -1,93 +0,0 @@ | |||
| package com.jd.blockchain.contract; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| import com.jd.blockchain.utils.io.FileUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| import static com.jd.blockchain.utils.BaseConstant.SYS_CONTRACT_CONF; | |||
| import static com.jd.blockchain.utils.BaseConstant.SYS_CONTRACT_PROPS_NAME; | |||
| /** | |||
| * | |||
| * @author zhaogw | |||
| * date 2019/3/15 18:22 | |||
| */ | |||
| public enum ContractConfigure { | |||
| instance(); | |||
| private static final Logger LOGGER = LoggerFactory.getLogger(ContractConfigure.class); | |||
| static Properties pp; | |||
| ContractConfigure(){ | |||
| init(); | |||
| } | |||
| private void init(){ | |||
| String contractConfPath = System.getProperty(SYS_CONTRACT_CONF); | |||
| System.out.println("contractConfPath="+contractConfPath); | |||
| try { | |||
| if (contractConfPath == null) { | |||
| ConsoleUtils.info("Load build-in default contractConf in ContractConfigure ..."); | |||
| ClassPathResource contractConfigResource = new ClassPathResource(SYS_CONTRACT_PROPS_NAME); | |||
| InputStream in = contractConfigResource.getInputStream(); | |||
| pp = FileUtils.readProperties(in, BaseConstant.CHARSET_UTF_8); | |||
| } else { | |||
| ConsoleUtils.info("Load configuration in ContractConfigure,contractConfPath="+contractConfPath); | |||
| File file = new File(contractConfPath); | |||
| pp = FileUtils.readProperties(file, BaseConstant.CHARSET_UTF_8); | |||
| } | |||
| } catch (Exception e) { | |||
| LOGGER.info(SYS_CONTRACT_PROPS_NAME+"文件异常!"+e.getMessage()); | |||
| } | |||
| } | |||
| public String values(String key) { | |||
| if(pp == null){ | |||
| init(); | |||
| } | |||
| return pp.getProperty(key); | |||
| } | |||
| public String allValues() { | |||
| if(pp == null){ | |||
| init(); | |||
| } | |||
| Set<String> allKeys = pp.stringPropertyNames(); | |||
| List<String> propList = new ArrayList(); | |||
| for(String _key : allKeys){ | |||
| String value = pp.getProperty(_key); | |||
| propList.add(_key+": "+value); | |||
| LOGGER.info("key={}, value={}",_key,value); | |||
| } | |||
| return propList.toString(); | |||
| } | |||
| //写入资源文件信息 | |||
| public static void writeProperties(String fileAllName, String comments, Map<String,String> map){ | |||
| Properties properties=new Properties(); | |||
| try { | |||
| File file = new File(fileAllName); | |||
| if (!file.getParentFile().exists()) { | |||
| boolean result = file.getParentFile().mkdirs(); | |||
| if (!result) { | |||
| System.out.println("文件创建失败."); | |||
| } | |||
| } | |||
| OutputStream outputStream=new FileOutputStream(file); | |||
| for(Map.Entry<String,String> entry : map.entrySet()){ | |||
| properties.setProperty(entry.getKey(), entry.getValue()); | |||
| } | |||
| properties.store(outputStream, comments); | |||
| outputStream.close(); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,35 +0,0 @@ | |||
| package com.jd.blockchain.contract.samples; | |||
| import com.jd.blockchain.contract.Contract; | |||
| import com.jd.blockchain.contract.ContractEvent; | |||
| /** | |||
| * 示例:一个“资产管理”智能合约; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| @Contract | |||
| public interface AssetContract { | |||
| /** | |||
| * 发行资产; | |||
| * | |||
| * @param amount 新发行的资产数量; | |||
| * @param assetHolderAddress 新发行的资产的持有账户; | |||
| */ | |||
| @ContractEvent(name = "issue-asset") | |||
| void issue(long amount, String assetHolderAddress); | |||
| /** | |||
| * 转移资产 | |||
| * | |||
| * @param fromAddress 转出账户; | |||
| * @param toAddress 转入账户; | |||
| * @param amount 转移的资产数额; | |||
| * @return 返回转出账户的余额; | |||
| */ | |||
| @ContractEvent(name = "transfer-asset") | |||
| long transfer(String fromAddress, String toAddress, long amount); | |||
| } | |||
| @@ -1,53 +0,0 @@ | |||
| //package com.jd.blockchain.contract.samples; | |||
| // | |||
| //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; | |||
| // | |||
| ///** | |||
| // * 示例:一个“资产管理”智能合约; | |||
| // * | |||
| // * @author zhaogw | |||
| // */ | |||
| //@Contract | |||
| //public interface AssetContract2 { | |||
| // | |||
| // /** | |||
| // * 发行资产; | |||
| // * 新发行的资产数量; | |||
| // * @param assetHolderAddress | |||
| // * 新发行的资产的持有账户; | |||
| // */ | |||
| // @ContractEvent(name = "issue-asset-0") | |||
| // void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
| // | |||
| // /** | |||
| // * issue asset; | |||
| // * @param contractBizContent | |||
| // * @param assetHolderAddress | |||
| // * @param cashNumber | |||
| // */ | |||
| // @ContractEvent(name = "issue-asset") | |||
| // public 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-4") | |||
| // void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
| //} | |||
| @@ -1,173 +0,0 @@ | |||
| package com.jd.blockchain.contract.samples; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import java.util.Set; | |||
| import com.jd.blockchain.contract.ContractEventContext; | |||
| import com.jd.blockchain.contract.ContractException; | |||
| import com.jd.blockchain.contract.EventProcessingAware; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.ledger.TypedKVData; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| /** | |||
| * 示例:一个“资产管理”智能合约的实现; | |||
| * | |||
| * 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现 | |||
| * AssetContract 接口定义的合约方法; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class AssetContractImpl implements EventProcessingAware, AssetContract { | |||
| // 资产管理账户的地址; | |||
| private static final String ASSET_ADDRESS = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; | |||
| // 保存资产总数的键; | |||
| private static final String KEY_TOTAL = "TOTAL"; | |||
| // 合约事件上下文; | |||
| private ContractEventContext eventContext; | |||
| /** | |||
| * ------------------- 定义可以由外部用户通过提交“交易”触发的调用方法 ------------------ | |||
| */ | |||
| @Override | |||
| public void issue(long amount, String assetHolderAddress) { | |||
| checkAllOwnersAgreementPermission(); | |||
| // 新发行的资产数量; | |||
| if (amount < 0) { | |||
| throw new ContractException("The amount is negative!"); | |||
| } | |||
| if (amount == 0) { | |||
| return; | |||
| } | |||
| // 查询当前值; | |||
| TypedKVEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL, | |||
| assetHolderAddress); | |||
| // 计算资产的发行总数; | |||
| TypedKVData currTotal = (TypedKVData) kvEntries[0]; | |||
| long newTotal = currTotal.longValue() + amount; | |||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion()); | |||
| // 分配到持有者账户; | |||
| TypedKVData holderAmount = (TypedKVData) kvEntries[1]; | |||
| long newHodlerAmount = holderAmount.longValue() + amount; | |||
| eventContext.getLedger().dataAccount(ASSET_ADDRESS) | |||
| .setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1) | |||
| .setText("k3", "info3", 3); | |||
| } | |||
| @Override | |||
| public long transfer(String fromAddress, String toAddress, long amount) { | |||
| if (amount < 0) { | |||
| throw new ContractException("The amount is negative!"); | |||
| } | |||
| if (amount > 20000) { | |||
| throw new ContractException("The amount exceeds the limit of 20000!"); | |||
| } | |||
| // 校验“转出账户”是否已签名; | |||
| checkSignerPermission(fromAddress); | |||
| // 查询现有的余额; | |||
| TypedKVEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, | |||
| fromAddress, toAddress); | |||
| TypedKVEntry fromBalanceKV = origBalances[0]; | |||
| TypedKVEntry toBalanceKV = origBalances[1]; | |||
| long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue(); | |||
| long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue(); | |||
| // 检查是否余额不足; | |||
| if ((fromBalance - amount) < 0) { | |||
| throw new ContractException("The balance is insufficient and the transfer failed!"); | |||
| } | |||
| fromBalance = fromBalance + amount; | |||
| toBalance = toBalance + amount; | |||
| // 把数据的更改写入到账本; | |||
| eventContext.getLedger().dataAccount(fromAddress).setInt64(ASSET_ADDRESS, fromBalance, fromBalanceKV.getVersion()); | |||
| eventContext.getLedger().dataAccount(toAddress).setInt64(ASSET_ADDRESS, toBalance, toBalanceKV.getVersion()); | |||
| return -1; | |||
| } | |||
| // ------------------------------------------------------------- | |||
| // ------------------- 定义只在合约内部调用的方法 ------------------ | |||
| // ------------------------------------------------------------- | |||
| /** | |||
| * 只有全部的合约拥有者同意才能通过校验; | |||
| */ | |||
| private void checkAllOwnersAgreementPermission() { | |||
| Set<BlockchainIdentity> owners = eventContext.getContracOwners(); | |||
| Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
| if (requestors.size() != owners.size()) { | |||
| throw new ContractException("Permission Error! -- The requestors is not exactlly being owners!"); | |||
| } | |||
| Map<Bytes, BlockchainIdentity> ownerMap = new HashMap<>(); | |||
| for (BlockchainIdentity o : owners) { | |||
| ownerMap.put(o.getAddress(), o); | |||
| } | |||
| for (BlockchainIdentity r : requestors) { | |||
| if (!ownerMap.containsKey(r.getAddress())) { | |||
| throw new ContractException("Permission Error! -- No agreement of all owners!"); | |||
| } | |||
| } | |||
| } | |||
| private HashDigest currentLedgerHash() { | |||
| return eventContext.getCurrentLedgerHash(); | |||
| } | |||
| /** | |||
| * 校验指定的账户是否签署了当前交易; | |||
| * | |||
| * @param address | |||
| */ | |||
| private void checkSignerPermission(String address) { | |||
| Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
| for (BlockchainIdentity r : requestors) { | |||
| if (r.getAddress().equals(address)) { | |||
| return; | |||
| } | |||
| } | |||
| throw new ContractException("Permission Error! -- No signature !"); | |||
| } | |||
| // ---------------------------------------------------------- | |||
| // ------------------- 在运行时捕捉上下文事件 ------------------ | |||
| // ---------------------------------------------------------- | |||
| /* | |||
| * (non-Javadoc) | |||
| * | |||
| * @see | |||
| * com.jd.blockchain.contract.model.EventProcessingAwire#beforeEvent(com.jd. | |||
| * blockchain.contract.model.ContractEventContext) | |||
| */ | |||
| @Override | |||
| public void beforeEvent(ContractEventContext eventContext) { | |||
| this.eventContext = eventContext; | |||
| } | |||
| /* | |||
| * (non-Javadoc) | |||
| * | |||
| * @see com.jd.blockchain.contract.model.EventProcessingAwire#postEvent(com.jd. | |||
| * blockchain.contract.model.ContractEventContext, | |||
| * com.jd.blockchain.contract.model.ContractError) | |||
| */ | |||
| @Override | |||
| public void postEvent(ContractEventContext eventContext, Exception error) { | |||
| this.eventContext = null; | |||
| } | |||
| } | |||
| @@ -1,72 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.utils.http.converters.JsonResponseConverter; | |||
| import com.jd.blockchain.utils.web.model.WebResponse; | |||
| import org.apache.http.HttpResponse; | |||
| import org.apache.http.client.HttpClient; | |||
| import org.apache.http.client.entity.UrlEncodedFormEntity; | |||
| import org.apache.http.client.methods.HttpPost; | |||
| import org.apache.http.impl.client.HttpClients; | |||
| import org.apache.http.message.BasicNameValuePair; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * @Author: zhangshuang | |||
| * @Date: 2020/5/27 5:18 PM | |||
| * Version 1.0 | |||
| */ | |||
| public class SDKDemo_ActiveParticipant { | |||
| // 接受激活参与方操作的共识节点Http服务地址, 根据具体环境配置进行修改 | |||
| private static String httpIp = "127.0.0.1"; | |||
| private static String httpPort = "7080"; | |||
| public static void main(String[] args) { | |||
| String url = "http://" + httpIp + ":" + httpPort + "/management/delegate/activeparticipant"; | |||
| System.out.println("url = " + url); | |||
| HttpPost httpPost = new HttpPost(url); | |||
| List<BasicNameValuePair> para=new ArrayList<BasicNameValuePair>(); | |||
| // 账本值根据具体情况进行修改 | |||
| BasicNameValuePair base58LedgerHash = new BasicNameValuePair("ledgerHash", "j5tuvAR3Q6ATsMNYTwt7SxVeCqd73itQbpmePxzSg6Zsxc"); | |||
| // 激活的新参与方的共识网络地址 | |||
| BasicNameValuePair host = new BasicNameValuePair("consensusHost", "127.0.0.1"); | |||
| BasicNameValuePair port = new BasicNameValuePair("consensusPort", "16000"); | |||
| // 指定已经启动的其他共识节点的HTTP管理端口 | |||
| BasicNameValuePair manageHost = new BasicNameValuePair("remoteManageHost", "127.0.0.1"); | |||
| BasicNameValuePair managePort = new BasicNameValuePair("remoteManagePort", "7083"); | |||
| para.add(base58LedgerHash); | |||
| para.add(host); | |||
| para.add(port); | |||
| para.add(manageHost); | |||
| para.add(managePort); | |||
| try { | |||
| httpPost.setEntity(new UrlEncodedFormEntity(para,"UTF-8")); | |||
| HttpClient httpClient = HttpClients.createDefault(); | |||
| HttpResponse response = httpClient.execute(httpPost); | |||
| JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); | |||
| WebResponse webResponse = (WebResponse) jsonConverter.getResponse(null, response.getEntity().getContent(), null); | |||
| System.out.println("response result = " + webResponse.isSuccess()); | |||
| if (!webResponse.isSuccess()) { | |||
| System.out.println("error msg = " + webResponse.getError().getErrorMessage()); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| System.out.println("Active participant post request error!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,94 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/10/18 下午2:00 | |||
| * Description: 注册用户 | |||
| */ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| /** | |||
| * 注册用户 | |||
| * | |||
| * @author shaozhuguang | |||
| * @create 2018/10/18 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDKDemo_ConfigureSecurity { | |||
| public static void main(String[] args) { | |||
| String GATEWAY_IPADDR = "127.0.0.1"; | |||
| int GATEWAY_PORT = 8081; | |||
| if (args != null && args.length == 2) { | |||
| GATEWAY_IPADDR = args[0]; | |||
| GATEWAY_PORT = Integer.parseInt(args[1]); | |||
| } | |||
| // 注册相关class | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| PrivKey privKey = SDKDemo_Params.privkey1; | |||
| PubKey pubKey = SDKDemo_Params.pubKey1; | |||
| BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
| boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| // existed signer | |||
| AsymmetricKeypair signer = getSigner(); | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.users().register(user.getIdentity()); | |||
| txTemp.security().roles() | |||
| .configure("ADMIN") | |||
| .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.DIRECT_OPERATION) | |||
| .configure("GUEST") | |||
| .enable(TransactionPermission.CONTRACT_OPERATION); | |||
| txTemp.security().authorziations() | |||
| .forUser(user.getIdentity()) | |||
| .authorize("ADMIN", "MANAGER") | |||
| .forUser(CLIENT_CERT.getAddress()) | |||
| .authorize("GUEST"); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(signer); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
| } | |||
| private static AsymmetricKeypair getSigner() { | |||
| return new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); | |||
| } | |||
| } | |||
| @@ -1,53 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import org.apache.commons.io.FileUtils; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import java.io.File; | |||
| public class SDKDemo_Constant { | |||
| public static final String GW_IPADDR = "jdchain-cloud0-8080.jdfmgt.com"; | |||
| // public static final String GW_IPADDR = "192.168.151.41"; | |||
| public static final int GW_PORT = 80; | |||
| // public static final int GW_PORT = 18081; | |||
| public static final String[] PUB_KEYS = { | |||
| "3snPdw7i7Pf2u9KTNUhxrYxgEymH24zP3NNNauRVwX5yDD6rzu2uBY", | |||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"}; | |||
| public static final String[] PRIV_KEYS = { | |||
| "177gjy71kcL5pU2YayqeZ44AfE87o8b5PfLeBER1rjsjViGux3TzdLcQs7QEznRMCw2sAHD", | |||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"}; | |||
| // public static final String[] PUB_KEYS = { | |||
| // "3snPdw7i7PXvEDgq96QyzcKhfWL4mgYspzKwvgXiuAidWb2rkRMgDY", | |||
| // "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
| // "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
| // "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"}; | |||
| // | |||
| // public static final String[] PRIV_KEYS = { | |||
| // "177gjsxj2ezADGthZ4tGqWeCAqRAwtNvesPjRnyKqCb1huU8LKZmJ3HGZNMPKWQJK3DP1B2", | |||
| // "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
| // "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
| // "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"}; | |||
| public static final String PASSWORD = "abc"; | |||
| public static final byte[] readChainCodes(String contractZip) { | |||
| // 构建合约的字节数组; | |||
| try { | |||
| ClassPathResource contractPath = new ClassPathResource(contractZip); | |||
| File contractFile = new File(contractPath.getURI()); | |||
| return FileUtils.readFileToByteArray(contractFile); | |||
| } catch (Exception e) { | |||
| throw new IllegalStateException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,153 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.contract.samples.AssetContract; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.ContractReturnValue; | |||
| import com.jd.blockchain.transaction.LongValueHolder; | |||
| import com.jd.blockchain.utils.io.ByteArray; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||
| /** | |||
| * 演示合约执行的过程; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class SDKDemo_Contract { | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| public static void main(String[] args) { | |||
| demoContract(); | |||
| } | |||
| /** | |||
| * 演示合约执行的过程; | |||
| */ | |||
| public static void demoContract() { | |||
| // 账本地址; | |||
| String ledgerAddress = "j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7"; | |||
| // 节点地址列表; | |||
| // NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| // new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| // new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "localhost"; | |||
| final int GATEWAY_PORT = 11000; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // -------------------------------------- | |||
| // 一个贸易账户,贸易结算后的利润将通过一个合约账户来执行利润分配; | |||
| // 合约账户被设置为通用的账户,不具备对贸易结算账户的直接权限; | |||
| // 只有当前交易发起人具备对贸易账户的直接权限,当交易发起人对交易进行签名之后,权限被间接传递给合约账户; | |||
| String commerceAccount = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 处理利润分成的通用业务逻辑的合约账户; | |||
| String profitDistributionContract = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 收益人账户; | |||
| String receiptorAccount1 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| String receiptorAccount2 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 资产编码; | |||
| String assetKey = "RMB-ASSET"; | |||
| // 此次待分配利润; | |||
| long profit = 1000000; | |||
| // 备注信息; | |||
| Remark remark = new Remark(); | |||
| String remarkJSON = JSONSerializeUtils.serializeToJSON(remark); | |||
| // 发起交易; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| AssetContract assetContract = txTemp.contract(profitDistributionContract, AssetContract.class); | |||
| assetContract.issue(1000, receiptorAccount1); | |||
| LongValueHolder balance = ContractReturnValue.decode(assetContract.transfer(receiptorAccount1, receiptorAccount2, 600)); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey();//示例方法,取发起人的私钥; | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| //获取返回值; | |||
| System.out.println("balance = " + balance.get()); | |||
| } | |||
| private static HashDigest getLedgerHash() { | |||
| // TODO Init ledger hash; | |||
| return null; | |||
| } | |||
| /** | |||
| * 交易发起人的私钥;<br> | |||
| * | |||
| * 注:私钥由调用方在本地保管和使用; | |||
| * | |||
| * @return | |||
| */ | |||
| private static AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| /** | |||
| * 商品信息; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public static class Remark { | |||
| private String code; | |||
| private String name; | |||
| private String venderAddress; | |||
| public String getCode() { | |||
| return code; | |||
| } | |||
| public void setCode(String code) { | |||
| this.code = code; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public String getVenderAddress() { | |||
| return venderAddress; | |||
| } | |||
| public void setVenderAddress(String venderAddress) { | |||
| this.venderAddress = venderAddress; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,81 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| public class SDKDemo_DataAccount { | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| /** | |||
| * 生成一个区块链用户,并注册到区块链; | |||
| */ | |||
| public static void registerDataAccount() { | |||
| // 区块链共识域; | |||
| String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // 节点地址列表; | |||
| NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 网关客户端编号; | |||
| int gatewayId = 1001; | |||
| // 账本地址; | |||
| String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| // 客户端的认证账户; | |||
| String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| String privKey = "safefsd32q34vdsvs"; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "127.0.0.1"; | |||
| final int GATEWAY_PORT = 80; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 在本地产生要注册的账户的秘钥; | |||
| BlockchainKeyGenerator generator = BlockchainKeyGenerator.getInstance(); | |||
| BlockchainKeypair dataAccount = generator.generate("ED25519"); | |||
| txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
| // -------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| } | |||
| private static HashDigest getLedgerHash() { | |||
| // TODO Init ledger hash; | |||
| return null; | |||
| } | |||
| private static AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| } | |||
| @@ -1,77 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.http.converters.JsonResponseConverter; | |||
| import com.jd.blockchain.utils.web.model.WebResponse; | |||
| import org.apache.http.HttpResponse; | |||
| import org.apache.http.client.HttpClient; | |||
| import org.apache.http.client.entity.UrlEncodedFormEntity; | |||
| import org.apache.http.client.methods.HttpPost; | |||
| import org.apache.http.impl.client.HttpClients; | |||
| import org.apache.http.message.BasicNameValuePair; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * @Author: zhangshuang | |||
| * @Date: 2020/5/27 5:18 PM | |||
| * Version 1.0 | |||
| */ | |||
| public class SDKDemo_DeactiveParticipant { | |||
| // 接受去激活参与方操作的共识节点Http服务地址, 根据具体环境配置进行修改 | |||
| private static String httpIp = "127.0.0.1"; | |||
| private static String httpPort = "7080"; | |||
| public static void main(String[] args) { | |||
| String url = "http://" + httpIp + ":" + httpPort + "/management/delegate/deactiveparticipant"; | |||
| // 即将进行去激活的共识节点公钥信息 | |||
| String PUB = "3snPdw7i7Pf2u9KTNUhxrYxgEymH24zP3NNNauRVwX5yDD6rzu2uBY"; | |||
| PubKey deactivePubKey = KeyGenUtils.decodePubKey(PUB); | |||
| Bytes address = AddressEncoding.generateAddress(deactivePubKey); | |||
| System.out.println("url = " + url); | |||
| HttpPost httpPost = new HttpPost(url); | |||
| List<BasicNameValuePair> para=new ArrayList<BasicNameValuePair>(); | |||
| // 账本值根据具体情况进行修改 | |||
| BasicNameValuePair base58LedgerHash = new BasicNameValuePair("ledgerHash", "j5tuvAR3Q6ATsMNYTwt7SxVeCqd73itQbpmePxzSg6Zsxc"); | |||
| BasicNameValuePair deactiveAddress = new BasicNameValuePair("participantAddress", address.toBase58()); | |||
| // 指定已经启动的其他共识节点的HTTP管理端口 | |||
| BasicNameValuePair manageHost = new BasicNameValuePair("remoteManageHost", "127.0.0.1"); | |||
| BasicNameValuePair managePort = new BasicNameValuePair("remoteManagePort", "7083"); | |||
| para.add(base58LedgerHash); | |||
| para.add(deactiveAddress); | |||
| para.add(manageHost); | |||
| para.add(managePort); | |||
| try { | |||
| httpPost.setEntity(new UrlEncodedFormEntity(para,"UTF-8")); | |||
| HttpClient httpClient = HttpClients.createDefault(); | |||
| HttpResponse response = httpClient.execute(httpPost); | |||
| JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); | |||
| WebResponse webResponse = (WebResponse) jsonConverter.getResponse(null, response.getEntity().getContent(), null); | |||
| System.out.println("response result = " + webResponse.isSuccess()); | |||
| if (!webResponse.isSuccess()) { | |||
| System.out.println("error msg = " + webResponse.getError().getErrorMessage()); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| System.out.println("Active participant post request error!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,74 +0,0 @@ | |||
| //package com.jd.blockchain.sdk.samples; | |||
| // | |||
| //import com.jd.blockchain.ledger.BlockchainEventType; | |||
| //import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| //import com.jd.blockchain.ledger.BlockchainKeyPair; | |||
| //import com.jd.blockchain.ledger.CryptoKeyType; | |||
| //import com.jd.blockchain.ledger.StateMap; | |||
| //import com.jd.blockchain.sdk.BlockchainEventHandle; | |||
| //import com.jd.blockchain.sdk.BlockchainEventListener; | |||
| //import com.jd.blockchain.sdk.BlockchainEventMessage; | |||
| //import com.jd.blockchain.sdk.BlockchainService; | |||
| //import com.jd.blockchain.sdk.client.BlockchainServiceFactory; | |||
| // | |||
| //import my.utils.net.NetworkAddress; | |||
| // | |||
| ///** | |||
| // * 演示监听区块链事件的过程; | |||
| // * | |||
| // * @author huanghaiquan | |||
| // * | |||
| // */ | |||
| //public class SDKDemo_EventListener { | |||
| // | |||
| // public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); | |||
| // | |||
| // /** | |||
| // * 演示合约执行的过程; | |||
| // */ | |||
| // public static void demoContract() { | |||
| // // 区块链共识域; | |||
| // String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // // 节点地址列表; | |||
| // NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| // new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| // new NetworkAddress("192.168.10.13", 8080) }; | |||
| // | |||
| // // 网关客户端编号; | |||
| // int gatewayId = 1001; | |||
| // // 账本地址; | |||
| // String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| // // 客户端的认证账户; | |||
| // String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| // String privKey = "safefsd32q34vdsvs"; | |||
| // // 创建服务代理; | |||
| // final String GATEWAY_IP = "127.0.0.1"; | |||
| // final int GATEWAY_PORT = 80; | |||
| // final boolean SECURE = false; | |||
| // BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| // CLIENT_CERT); | |||
| // BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // | |||
| // // 监听账户变动; | |||
| // String walletAccount = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| // service.addBlockchainEventListener(BlockchainEventType.PAYLOAD_UPDATED.CODE, null, walletAccount, | |||
| // new BlockchainEventListener() { | |||
| // @Override | |||
| // public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle) { | |||
| // // 钱包余额; | |||
| // StateMap balancePayload = service.getState(walletAccount, "RMB-ASSET","name"); | |||
| // Long balance = (Long) balancePayload.get("RMB-ASSET").longValue(); | |||
| // if (balance != null) { | |||
| // // notify balance change; | |||
| // } else { | |||
| // // wallet is empty and isn't listened any more; | |||
| // eventHandle.cancel(); | |||
| // } | |||
| // } | |||
| // }); | |||
| // | |||
| // // 销毁服务代理; | |||
| // serviceFactory.close(); | |||
| // } | |||
| // | |||
| //} | |||
| @@ -1,127 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.io.ByteArray; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| /** | |||
| * 演示数据写入的调用过程; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class SDKDemo_InsertData { | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| /** | |||
| * 演示数据写入的调用过程; | |||
| */ | |||
| public static void insertData() { | |||
| // 区块链共识域; | |||
| String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // 节点地址列表; | |||
| NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 网关客户端编号; | |||
| int gatewayId = 1001; | |||
| // 账本地址; | |||
| String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| // 客户端的认证账户; | |||
| String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| String privKey = "safefsd32q34vdsvs"; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "127.0.0.1"; | |||
| final int GATEWAY_PORT = 80; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 将商品信息写入到指定的账户中; | |||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
| String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| Commodity commodity1 = new Commodity(); | |||
| txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", commodity1.getCode(), -1); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| String txHash = ByteArray.toBase64(prepTx.getTransactionHash().toBytes()); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| } | |||
| private static HashDigest getLedgerHash() { | |||
| // TODO Init ledger hash; | |||
| return null; | |||
| } | |||
| private static AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| /** | |||
| * 商品信息; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public static class Commodity { | |||
| private String code; | |||
| private String name; | |||
| private String venderAddress; | |||
| public String getCode() { | |||
| return code; | |||
| } | |||
| public void setCode(String code) { | |||
| this.code = code; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public String getVenderAddress() { | |||
| return venderAddress; | |||
| } | |||
| public void setVenderAddress(String venderAddress) { | |||
| this.venderAddress = venderAddress; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,46 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: com.jd.blockchain.sdk.samples.SDKDemo_Params | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/10/18 下午2:16 | |||
| * Description: | |||
| */ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| /** | |||
| * | |||
| * @author shaozhuguang | |||
| * @create 2018/10/18 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDKDemo_Params { | |||
| public static final String PASSWORD = "abc"; | |||
| public static final String[] PUB_KEYS = { | |||
| "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; | |||
| public static final String[] PRIV_KEYS = { | |||
| "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||
| public static PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); | |||
| public static PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); | |||
| public static PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); | |||
| public static PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); | |||
| public static PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); | |||
| public static PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); | |||
| public static PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); | |||
| public static PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); | |||
| } | |||
| @@ -1,75 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| public class SDKDemo_PrivilegeSetting { | |||
| // public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); | |||
| // | |||
| // /** | |||
| // * 生成一个区块链账户,并注册到区块链; | |||
| // */ | |||
| // public static void registerAccount() { | |||
| // // 区块链共识域; | |||
| // String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // // 节点地址列表; | |||
| // NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| // new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| // new NetworkAddress("192.168.10.13", 8080) }; | |||
| // | |||
| // // 网关客户端编号; | |||
| // int gatewayId = 1001; | |||
| // // 账本地址; | |||
| // String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| // // 客户端的认证账户; | |||
| // String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| // String privKey = "safefsd32q34vdsvs"; | |||
| // // 创建服务代理; | |||
| // final String GATEWAY_IP = "127.0.0.1"; | |||
| // final int GATEWAY_PORT = 80; | |||
| // final boolean SECURE = false; | |||
| // BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| // CLIENT_CERT); | |||
| // BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
| // | |||
| // HashDigest ledgerHash = getLedgerHash(); | |||
| // // 在本地定义注册账号的 TX; | |||
| // TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // | |||
| // // -------------------------------------- | |||
| // // 配置账户的权限; | |||
| // String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| // String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| // String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| // // 配置: | |||
| // // “状态数据的写入权限”的阈值为 100; | |||
| // // 需要 user1、user2 两个账户的联合签名才能写入; | |||
| // // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; | |||
| // | |||
| // | |||
| // | |||
| // txTemp.configPrivilege(walletAccount).setThreshhold(PrivilegeType.STATE_WRITE, 100) | |||
| // .enable(PrivilegeType.STATE_WRITE, user1, 50).enable(PrivilegeType.STATE_WRITE, user2, 50) | |||
| // .disable(PrivilegeType.STATE_WRITE, walletAccount); | |||
| // // -------------------------------------- | |||
| // | |||
| // // TX 准备就绪; | |||
| // PreparedTransaction prepTx = txTemp.prepare(); | |||
| // | |||
| // // 使用私钥进行签名; | |||
| // BlockchainKeyPair sponsorKey = getSponsorKey(); | |||
| // prepTx.sign(sponsorKey); | |||
| // | |||
| // // 提交交易; | |||
| // prepTx.commit(); | |||
| // } | |||
| // | |||
| // private static HashDigest getLedgerHash() { | |||
| // // TODO Init ledger hash; | |||
| // return null; | |||
| // } | |||
| // | |||
| // private static BlockchainKeyPair getSponsorKey() { | |||
| // // TODO Auto-generated method stub | |||
| // return null; | |||
| // } | |||
| } | |||
| @@ -1,85 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.ledger.LedgerBlock; | |||
| import com.jd.blockchain.ledger.LedgerTransaction; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| /** | |||
| * 演示区块链信息查询的过程; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public class SDKDemo_Query { | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| public static final HashDigest LEDGER_HASH = Crypto.getHashFunction("SHA256") | |||
| .hash("xkxjcioewfqwe".getBytes()); | |||
| /** | |||
| * 演示合约执行的过程; | |||
| */ | |||
| public static void demoContract() { | |||
| // 区块链共识域; | |||
| String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // 节点地址列表; | |||
| NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 网关客户端编号; | |||
| int gatewayId = 1001; // 客户端的认证账户; | |||
| // 账本地址; | |||
| String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| String privKey = "safefsd32q34vdsvs"; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "127.0.0.1"; | |||
| final int GATEWAY_PORT = 80; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| // 查询区块信息; | |||
| // 区块高度; | |||
| long ledgerNumber = service.getLedger(LEDGER_HASH).getLatestBlockHeight(); | |||
| // 最新区块; | |||
| LedgerBlock latestBlock = service.getBlock(LEDGER_HASH, ledgerNumber); | |||
| // 区块中的交易的数量; | |||
| long txCount = service.getTransactionCount(LEDGER_HASH, latestBlock.getHash()); | |||
| // 获取交易列表; | |||
| LedgerTransaction[] txList = service.getTransactions(LEDGER_HASH, ledgerNumber, 0, 100); | |||
| // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
| HashDigest txHash = txList[0].getRequest().getTransactionHash(); | |||
| LedgerTransaction tx = service.getTransactionByContentHash(LEDGER_HASH, txHash); | |||
| // 获取数据; | |||
| String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| String[] objKeys = new String[] { "x001", "x002" }; | |||
| TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); | |||
| long payloadVersion = kvData[0].getVersion(); | |||
| // boolean exist = service.containState(LEDGER_HASH, commerceAccount, "x003"); | |||
| // 按条件查询; | |||
| // 1、从保存会员信息的账户地址查询; | |||
| // String condition = "female = true AND age > 18 AND address.city = 'beijing'"; | |||
| // String memberInfoAccountAddress = "kkf2io39823jfIjfiIRWKQj30203fx=="; | |||
| // StateMap memberInfo = service.queryObject(LEDGER_HASH, memberInfoAccountAddress, condition); | |||
| // | |||
| // // 2、从保存会员信息的账户地址查询; | |||
| // Map<String, StateMap> memberInfoWithAccounts = service.queryObject(LEDGER_HASH, condition); | |||
| } | |||
| } | |||
| @@ -1,82 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.*; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| /** | |||
| * @Author: zhangshuang | |||
| * @Date: 2020/5/27 5:18 PM | |||
| * Version 1.0 | |||
| */ | |||
| public class SDKDemo_RegistParticipant { | |||
| public static void main(String[] args) { | |||
| PrivKey privKey; | |||
| PubKey pubKey; | |||
| BlockchainKeypair CLIENT_CERT = null; | |||
| String GATEWAY_IPADDR = null; | |||
| int GATEWAY_PORT; | |||
| boolean SECURE; | |||
| BlockchainService service; | |||
| //根据密码工具产生的公私钥 | |||
| String PUB = "3snPdw7i7PkdgqiGX7GbZuFSi1cwZn7vtjw4vifb1YoXgr9k6Kfmis"; | |||
| String PRIV = "177gjtZu8w1phqHFVNiFhA35cfimXmP6VuqrBFhfbXBWK8s4TRwro2tnpffwP1Emwr6SMN6"; | |||
| privKey = SDKDemo_Params.privkey1; | |||
| pubKey = SDKDemo_Params.pubKey1; | |||
| CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 11000; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| DataContractRegistry.register(ParticipantRegisterOperation.class); | |||
| DataContractRegistry.register(ParticipantStateUpdateOperation.class); | |||
| DataContractRegistry.register(ConsensusSettingsUpdateOperation.class); | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| //existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
| privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); | |||
| pubKey = KeyGenUtils.decodePubKey(PUB); | |||
| System.out.println("Address = " + AddressEncoding.generateAddress(pubKey)); | |||
| BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); | |||
| // 注册参与方 | |||
| txTemp.participants().register("Peer4", user.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| } | |||
| } | |||
| @@ -1,54 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| 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.utils.ConsoleUtils; | |||
| public class SDKDemo_RegisterAccount { | |||
| public static void main(String[] args) { | |||
| String GATEWAY_IPADDR = "127.0.0.1"; | |||
| int GATEWAY_PORT = 8081; | |||
| if (args != null && args.length == 2) { | |||
| GATEWAY_IPADDR = args[0]; | |||
| GATEWAY_PORT = Integer.parseInt(args[1]); | |||
| } | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
| boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| //existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); | |||
| BlockchainKeypair dataAcount = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.dataAccounts().register(dataAcount.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| ConsoleUtils.info("register dataaccount complete, result is [%s]", transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,39 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/10/18 下午2:00 | |||
| * Description: 注册用户 | |||
| */ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| /** | |||
| * 注册用户 | |||
| * @author shaozhuguang | |||
| * @create 2018/10/18 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDKDemo_RegisterTest { | |||
| public static void main(String[] args) { | |||
| if (args != null) { | |||
| if (args[0].equals("user")) { | |||
| SDKDemo_RegisterUser.main(null); | |||
| } else if (args[0].equals("dataaccount")) { | |||
| SDKDemo_RegisterAccount.main(null); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,83 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/10/18 下午2:00 | |||
| * Description: 注册用户 | |||
| */ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| /** | |||
| * 注册用户 | |||
| * | |||
| * @author shaozhuguang | |||
| * @create 2018/10/18 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDKDemo_RegisterUser { | |||
| public static void main(String[] args) { | |||
| String GATEWAY_IPADDR = "127.0.0.1"; | |||
| int GATEWAY_PORT = 8081; | |||
| if (args != null && args.length == 2) { | |||
| GATEWAY_IPADDR = args[0]; | |||
| GATEWAY_PORT = Integer.parseInt(args[1]); | |||
| } | |||
| // 注册相关class | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| PrivKey privKey = SDKDemo_Params.privkey1; | |||
| PubKey pubKey = SDKDemo_Params.pubKey1; | |||
| BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
| boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| // existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // 定义角色权限; | |||
| txTemp.security().roles().configure("MANAGER") | |||
| .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.CONTRACT_OPERATION); | |||
| txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,109 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/10/18 下午2:00 | |||
| * Description: 注册用户 | |||
| */ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.SignatureUtils; | |||
| import com.jd.blockchain.utils.ConsoleUtils; | |||
| /** | |||
| * 注册用户 | |||
| * | |||
| * @author shaozhuguang | |||
| * @create 2018/10/18 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDKDemo_Tx_Persistance { | |||
| public static void main(String[] args) { | |||
| String GATEWAY_IPADDR = "127.0.0.1"; | |||
| int GATEWAY_PORT = 11000; | |||
| if (args != null && args.length == 2) { | |||
| GATEWAY_IPADDR = args[0]; | |||
| GATEWAY_PORT = Integer.parseInt(args[1]); | |||
| } | |||
| // 注册相关class | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| PrivKey privKey1 = SDKDemo_Params.privkey0; | |||
| PubKey pubKey1 = SDKDemo_Params.pubKey0; | |||
| PrivKey privKey2 = SDKDemo_Params.privkey1; | |||
| PubKey pubKey2 = SDKDemo_Params.pubKey1; | |||
| BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
| boolean SECURE = false; | |||
| GatewayServiceFactory gatewayServiceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService blockchainService = gatewayServiceFactory.getBlockchainService(); | |||
| HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHashs[0]); | |||
| // existed signer | |||
| AsymmetricKeypair keyPair1 = new BlockchainKeypair(pubKey1, privKey1); | |||
| AsymmetricKeypair keyPair2 = new BlockchainKeypair(pubKey2, privKey2); | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // 定义角色权限; | |||
| txTemp.security().roles().configure("MANAGER") | |||
| .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.CONTRACT_OPERATION); | |||
| txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 序列化交易内容; | |||
| byte[] txContentBytes = BinaryProtocol.encode(prepTx.getTransactionContent(), TransactionContent.class); | |||
| // 反序列化交易内容; | |||
| TransactionContent txContent = BinaryProtocol.decode(txContentBytes, TransactionContent.class); | |||
| // 对交易内容签名; | |||
| DigitalSignature signature1 = SignatureUtils.sign(keyPair1.getAlgorithm(), txContent, keyPair1); | |||
| // 根据交易内容重新准备交易; | |||
| PreparedTransaction decodedPrepTx = blockchainService.prepareTransaction(txContent); | |||
| // 使用私钥进行签名,或附加签名; | |||
| decodedPrepTx.addSignature(signature1); | |||
| decodedPrepTx.sign(keyPair2); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = decodedPrepTx.commit(); | |||
| // 解析返回结果;如果是合约调用的操作,需要自行解析返回结果; | |||
| if (transactionResponse.isSuccess()) { | |||
| // 操作结果对应于交易中的操作顺序;无返回结果的操作对应结果为 null; | |||
| OperationResult opResult = transactionResponse.getOperationResults()[0];// | |||
| Class<?> dataClazz = null;//返回值的类型; | |||
| Object value = BytesValueEncoding.decode(opResult.getResult(), dataClazz); | |||
| } | |||
| ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,95 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| public class SDKDemo_User { | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(); | |||
| /** | |||
| * 生成一个区块链用户,并注册到区块链; | |||
| */ | |||
| public static void registerUser() { | |||
| // 区块链共识域; | |||
| String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
| // 节点地址列表; | |||
| NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 网关客户端编号; | |||
| int gatewayId = 1001; | |||
| // 账本地址; | |||
| String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
| // 客户端的认证账户; | |||
| String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
| String privKey = "safefsd32q34vdsvs"; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "127.0.0.1"; | |||
| final int GATEWAY_PORT = 80; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 配置账户的权限; | |||
| String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
| String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| // 配置: | |||
| // “状态数据的写入权限”的阈值为 100; | |||
| // 需要 user1、user2 两个账户的联合签名才能写入; | |||
| // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; | |||
| String userPubKeyStr = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
| // 在本地产生要注册的账户的秘钥; | |||
| //BlockchainKeyGenerator generator = BlockchainKeyGenerator.getInstance(); | |||
| //BlockchainKeyPair user = generator.generate(CryptoKeyType.PUBLIC); | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||
| BlockchainKeypair user = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| txTemp.users().register(user.getIdentity()); | |||
| // -------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| } | |||
| private static HashDigest getLedgerHash() { | |||
| // TODO Init ledger hash; | |||
| return null; | |||
| } | |||
| private static AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| } | |||
| @@ -1,56 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| 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 com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| public abstract class SDK_Base_Demo { | |||
| protected BlockchainKeypair adminKey; | |||
| protected HashDigest ledgerHash; | |||
| protected BlockchainService blockchainService; | |||
| public SDK_Base_Demo() { | |||
| init(); | |||
| } | |||
| public void init() { | |||
| // 生成连接网关的账号 | |||
| PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], SDKDemo_Constant.PASSWORD); | |||
| PubKey pubKey = KeyGenUtils.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); | |||
| adminKey = new BlockchainKeypair(pubKey, privKey); | |||
| // 连接网关 | |||
| 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) { | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(adminKey); | |||
| return ptx.commit(); | |||
| } | |||
| protected void printTxResponse(TransactionResponse response) { | |||
| System.out.printf("TxResponse's state = [%s][%s], blockHeight = [%s] ! \r\n", | |||
| response.isSuccess(), response.getExecutionState(), response.getBlockHeight()); | |||
| } | |||
| } | |||
| @@ -1,42 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.Property; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| public class SDK_ConsensusSettings_Update_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_ConsensusSettings_Update_Demo().updateSettings(); | |||
| } | |||
| public void updateSettings() { | |||
| List<Property> properties = new ArrayList<Property>(); | |||
| // 修改bftsmart.conf配置文件中的选项; | |||
| properties.add(new Property("system.communication.useSenderThread", "false")); | |||
| Property[] propertiesArray = properties.toArray(new Property[properties.size()]); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.settings().update(propertiesArray); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTpl.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(adminKey); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| System.out.println(transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,70 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
| import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.transaction.GenericValueHolder; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.chain.contracts.ContractTestInf; | |||
| public class SDK_Contract_Check_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_Contract_Check_Demo().executeContract(); | |||
| } | |||
| public void executeContract() { | |||
| // 发布jar包 | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 将jar包转换为二进制数据 | |||
| byte[] contractCode = readChainCodes("contract-jdchain.jar"); | |||
| // 生成一个合约账号 | |||
| BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 生成发布合约操作 | |||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
| // 生成预发布交易; | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| // 对交易进行签名 | |||
| ptx.sign(adminKey); | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| // 获取合约地址 | |||
| Bytes contractAddress = contractDeployKey.getAddress(); | |||
| // 打印交易返回信息 | |||
| System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
| txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
| txResp.isSuccess(), txResp.getExecutionState()); | |||
| // 打印合约地址 | |||
| System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
| // 执行合约 | |||
| exeContract(contractAddress); | |||
| } | |||
| private void exeContract(Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| ContractTestInf contract = txTpl.contract(contractAddress, ContractTestInf.class); | |||
| GenericValueHolder<String> result = decode(contract.randomChars(1024)); | |||
| commit(txTpl); | |||
| String random = result.get(); | |||
| System.out.println(random); | |||
| } | |||
| } | |||
| @@ -1,156 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
| import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
| import com.jd.blockchain.contract.TransferContract; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.transaction.GenericValueHolder; | |||
| import com.jd.blockchain.transaction.LongValueHolder; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class SDK_Contract_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_Contract_Demo().executeContract(); | |||
| } | |||
| public void executeContract() { | |||
| // 发布jar包 | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 将jar包转换为二进制数据 | |||
| byte[] contractCode = readChainCodes("transfer.jar"); | |||
| // 生成一个合约账号 | |||
| BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 生成发布合约操作 | |||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
| // 生成预发布交易; | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| // 对交易进行签名 | |||
| ptx.sign(adminKey); | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| // 获取合约地址 | |||
| Bytes contractAddress = contractDeployKey.getAddress(); | |||
| // 打印交易返回信息 | |||
| System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
| txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
| txResp.isSuccess(), txResp.getExecutionState()); | |||
| // 打印合约地址 | |||
| System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
| // 注册一个数据账户 | |||
| BlockchainKeypair dataAccount = createDataAccount(); | |||
| // 获取数据账户地址 | |||
| String dataAddress = dataAccount.getAddress().toBase58(); | |||
| // 打印数据账户地址 | |||
| System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
| // 创建两个账号: | |||
| String account0 = "jd_zhangsan", account1 = "jd_lisi"; | |||
| long account0Money = 3000L, account1Money = 2000L; | |||
| // 创建两个账户 | |||
| // 使用KV操作创建一个账户 | |||
| System.out.println(create(dataAddress, account0, account0Money, false, null)); | |||
| // 使用合约创建一个账户 | |||
| System.out.println(create(dataAddress, account1, account1Money, true, contractAddress)); | |||
| // 转账,使得双方钱达到一致 | |||
| System.out.println(transfer(dataAddress, account0, account1, 500L, contractAddress)); | |||
| // 通过合约读取account0的当前信息 | |||
| System.out.printf("Read DataAccountAddress[%s] Account = %s 's money = %s (By Contract)\r\n", dataAddress, | |||
| account0, readByContract(dataAddress, account0, contractAddress)); | |||
| // 通过KV读取account1的当前信息 | |||
| System.out.printf("Read DataAccountAddress[%s] Account = %s 's money = %s (By KV Operation)\r\n", dataAddress, | |||
| account1, readByKvOperation(dataAddress, account1)); | |||
| // 通过合约读取account0的历史信息 | |||
| System.out.println(readAll(dataAddress, account0, contractAddress)); | |||
| // 通过合约读取account1的历史信息 | |||
| System.out.println(readAll(dataAddress, account1, contractAddress)); | |||
| } | |||
| private String readAll(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private long readByContract(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| LongValueHolder result = decode(transferContract.read(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private long readByKvOperation(String address, String account) { | |||
| TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); | |||
| if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
| throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); | |||
| } | |||
| TypedKVEntry kvDataEntry = kvDataEntries[0]; | |||
| if (kvDataEntry.getVersion() == -1) { | |||
| return 0L; | |||
| } | |||
| return (long) (kvDataEntry.getValue()); | |||
| } | |||
| private String transfer(String address, String from, String to, long money, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private BlockchainKeypair createDataAccount() { | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
| commit(txTpl); | |||
| return newDataAccount; | |||
| } | |||
| private String create(String address, String account, long money, boolean useContract, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| if (useContract) { | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } else { | |||
| // 通过KV创建 | |||
| txTpl.dataAccount(address).setInt64(account, money, -1); | |||
| TransactionResponse txResp = commit(txTpl); | |||
| return String.format( | |||
| "DataAccountAddress[%s] -> Create(By KV Operation) Account = %s and Money = %s Success!!! \r\n", | |||
| address, account, money); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,120 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.contract.RandomContract; | |||
| import com.jd.blockchain.contract.TransferContract; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.transaction.GenericValueHolder; | |||
| import com.jd.blockchain.transaction.LongValueHolder; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import java.util.Random; | |||
| import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
| import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
| public class SDK_Contract_Random_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) throws Exception { | |||
| new SDK_Contract_Random_Demo().executeContract(); | |||
| } | |||
| public void executeContract() throws Exception { | |||
| // 发布jar包 | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 将jar包转换为二进制数据 | |||
| byte[] contractCode = readChainCodes("random.jar"); | |||
| // 生成一个合约账号 | |||
| BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 生成发布合约操作 | |||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
| // 生成预发布交易; | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| // 对交易进行签名 | |||
| ptx.sign(adminKey); | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| // 获取合约地址 | |||
| Bytes contractAddress = contractDeployKey.getAddress(); | |||
| // 打印交易返回信息 | |||
| System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
| txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
| txResp.isSuccess(), txResp.getExecutionState()); | |||
| // 打印合约地址 | |||
| System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
| String result = create("LdeNzfhZd2qiBRk3YrEX6GZgiVRZJaf3MKJAY", "zhangshuang", "jingdong", contractAddress); | |||
| Thread.sleep(5000); | |||
| System.out.println(result); | |||
| } | |||
| private String readAll(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private long readByContract(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| LongValueHolder result = decode(transferContract.read(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private long readByKvOperation(String address, String account) { | |||
| TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); | |||
| if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
| throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); | |||
| } | |||
| TypedKVEntry kvDataEntry = kvDataEntries[0]; | |||
| if (kvDataEntry.getVersion() == -1) { | |||
| return 0L; | |||
| } | |||
| return (long) (kvDataEntry.getValue()); | |||
| } | |||
| private String transfer(String address, String from, String to, long money, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private BlockchainKeypair createDataAccount() { | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
| commit(txTpl); | |||
| return newDataAccount; | |||
| } | |||
| private String create(String address, String account, String value, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| RandomContract randomContract = txTpl.contract(contractAddress, RandomContract.class); | |||
| GenericValueHolder<String> result = decode(randomContract.putAndGet(address, account, value)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| } | |||
| @@ -1,49 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.contract.TransferContract; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.transaction.GenericValueHolder; | |||
| import com.jd.blockchain.transaction.LongValueHolder; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
| import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
| public class SDK_DataAccount_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_DataAccount_Demo().executeDataAccount(); | |||
| } | |||
| public void executeDataAccount() { | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 注册一个数据账户 | |||
| BlockchainKeypair dataAccount = createDataAccount(); | |||
| // 获取数据账户地址 | |||
| String dataAddress = dataAccount.getAddress().toBase58(); | |||
| // 打印数据账户地址 | |||
| System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
| // 通过KV创建 | |||
| txTpl.dataAccount(dataAddress) | |||
| .setText("zhangsan", "我的世界", -1) | |||
| .setText("张三", "My World", -1); | |||
| TransactionResponse txResp = commit(txTpl); | |||
| System.out.println(txResp.isSuccess()); | |||
| } | |||
| private BlockchainKeypair createDataAccount() { | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
| commit(txTpl); | |||
| return newDataAccount; | |||
| } | |||
| } | |||
| @@ -1,96 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.ledger.Event; | |||
| import com.jd.blockchain.ledger.SystemEvent; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.EventContext; | |||
| import com.jd.blockchain.sdk.EventListenerHandle; | |||
| import com.jd.blockchain.sdk.SystemEventListener; | |||
| import com.jd.blockchain.sdk.SystemEventPoint; | |||
| import com.jd.blockchain.sdk.UserEventListener; | |||
| import com.jd.blockchain.sdk.UserEventPoint; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| public class SDK_Event_Demo extends SDK_Base_Demo { | |||
| // 注册事件账户 | |||
| private BlockchainKeypair createEventAccount() { | |||
| BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.eventAccounts().register(eventAccount.getIdentity()); | |||
| commit(txTpl); | |||
| return eventAccount; | |||
| } | |||
| /** | |||
| * 发布事件 | |||
| * | |||
| * @param eventAccount 事件账户 | |||
| */ | |||
| private void publishEvent(BlockchainKeypair eventAccount) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // sequence传递当前事件名链上最新序号,不存在时传-1 | |||
| Event event = blockchainService.getLatestEvent(ledgerHash, eventAccount.getAddress().toBase58(), "name"); | |||
| long sequence = null != event ? event.getSequence() : -1; | |||
| txTpl.eventAccount(eventAccount.getAddress()).publish("name", "string", sequence + 1); | |||
| txTpl.eventAccount(eventAccount.getAddress()).publish("name", 0, sequence + 2); | |||
| commit(txTpl); | |||
| } | |||
| /** | |||
| * 监听用户自定义事件 | |||
| * | |||
| * @param eventAccount 事件账户 | |||
| * @param eventName 事件名 | |||
| */ | |||
| private void monitorUserEvent(BlockchainKeypair eventAccount, String eventName) { | |||
| EventListenerHandle<UserEventPoint> handler = blockchainService.monitorUserEvent(ledgerHash, eventAccount.getAddress().toBase58(), eventName, 0, new UserEventListener<UserEventPoint>() { | |||
| @Override | |||
| public void onEvent(Event eventMessage, EventContext<UserEventPoint> eventContext) { | |||
| BytesValue content = eventMessage.getContent(); | |||
| switch (content.getType()) { | |||
| case TEXT: | |||
| System.out.println(content.getBytes().toUTF8String()); | |||
| break; | |||
| case INT64: | |||
| System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| // 关闭监听的两种方式:1 | |||
| eventContext.getHandle().cancel(); | |||
| } | |||
| }); | |||
| // 关闭监听的两种方式:2 | |||
| handler.cancel(); | |||
| } | |||
| /** | |||
| * 监听新区块生成事件 | |||
| */ | |||
| private void monitorNewBlockCreatedEvent() { | |||
| EventListenerHandle<SystemEventPoint> handler = blockchainService.monitorSystemEvent(ledgerHash, SystemEvent.NEW_BLOCK_CREATED, 0, new SystemEventListener<SystemEventPoint>() { | |||
| @Override | |||
| public void onEvents(Event[] eventMessages, EventContext<SystemEventPoint> eventContext) { | |||
| for (Event eventMessage : eventMessages) { | |||
| BytesValue content = eventMessage.getContent(); | |||
| // content中存放的是当前链上最新高度 | |||
| System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); | |||
| } | |||
| // 关闭监听的两种方式:1 | |||
| eventContext.getHandle().cancel(); | |||
| } | |||
| }); | |||
| // 关闭监听的两种方式:2 | |||
| handler.cancel(); | |||
| } | |||
| } | |||
| @@ -1,120 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.sdk.converters.ClientResolveUtil; | |||
| public class SDK_InsertData_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| SDK_InsertData_Demo sdkDemo_insertData = new SDK_InsertData_Demo(); | |||
| sdkDemo_insertData.insertData(); | |||
| } | |||
| /** | |||
| * 生成一个区块链数据账户,并注册到区块链; | |||
| */ | |||
| public void insertData() { | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
| //采用原始的方式来生成BlockchainKeypair; | |||
| // SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| // AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||
| // BlockchainKeypair dataAccount = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
| //采用KeyGenerator来生成BlockchainKeypair; | |||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
| txTemp.dataAccount(dataAccount.getAddress()).setText("key1","value1",-1); | |||
| // TX 准备就绪 | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(adminKey); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| getData(dataAccount.getAddress().toBase58()); | |||
| } | |||
| public void getData(String commerceAccount) { | |||
| // 查询区块信息; | |||
| // 区块高度; | |||
| long ledgerNumber = blockchainService.getLedger(ledgerHash).getLatestBlockHeight(); | |||
| // 最新区块; | |||
| LedgerBlock latestBlock = blockchainService.getBlock(ledgerHash, ledgerNumber); | |||
| // 区块中的交易的数量; | |||
| long txCount = blockchainService.getTransactionCount(ledgerHash, latestBlock.getHash()); | |||
| // 获取交易列表; | |||
| LedgerTransaction[] txList = blockchainService.getTransactions(ledgerHash, ledgerNumber, 0, 100); | |||
| // 遍历交易列表 | |||
| for (LedgerTransaction ledgerTransaction : txList) { | |||
| TransactionContent txContent = ledgerTransaction.getRequest().getTransactionContent(); | |||
| Operation[] operations = txContent.getOperations(); | |||
| if (operations != null && operations.length > 0) { | |||
| for (Operation operation : operations) { | |||
| operation = ClientResolveUtil.read(operation); | |||
| // 操作类型:数据账户注册操作 | |||
| if (operation instanceof DataAccountRegisterOperation) { | |||
| DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = daro.getAccountID(); | |||
| } | |||
| // 操作类型:用户注册操作 | |||
| else if (operation instanceof UserRegisterOperation) { | |||
| UserRegisterOperation uro = (UserRegisterOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = uro.getUserID(); | |||
| } | |||
| // 操作类型:账本注册操作 | |||
| else if (operation instanceof LedgerInitOperation) { | |||
| LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation; | |||
| LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting(); | |||
| ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants(); | |||
| } | |||
| // 操作类型:合约发布操作 | |||
| else if (operation instanceof ContractCodeDeployOperation) { | |||
| ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation; | |||
| BlockchainIdentity blockchainIdentity = ccdo.getContractID(); | |||
| } | |||
| // 操作类型:合约执行操作 | |||
| else if (operation instanceof ContractEventSendOperation) { | |||
| ContractEventSendOperation ceso = (ContractEventSendOperation) operation; | |||
| } | |||
| // 操作类型:KV存储操作 | |||
| else if (operation instanceof DataAccountKVSetOperation) { | |||
| DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries = | |||
| ((DataAccountKVSetOperation) operation).getWriteSet(); | |||
| if (kvWriteEntries != null && kvWriteEntries.length > 0) { | |||
| for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) { | |||
| BytesValue bytesValue = kvWriteEntry.getValue(); | |||
| DataType dataType = bytesValue.getType(); | |||
| Object showVal = ClientResolveUtil.readValueByBytesValue(bytesValue); | |||
| System.out.println("writeSet.key=" + kvWriteEntry.getKey()); | |||
| System.out.println("writeSet.value=" + showVal); | |||
| System.out.println("writeSet.type=" + dataType); | |||
| System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
| HashDigest txHash = txList[0].getRequest().getTransactionHash(); | |||
| // Transaction tx = blockchainService.getTransactionByContentHash(ledgerHash, txHash); | |||
| // String[] objKeys = new String[] { "x001", "x002" }; | |||
| // KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, objKeys); | |||
| // 获取数据账户下所有的KV列表 | |||
| TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100); | |||
| if (kvData != null && kvData.length > 0) { | |||
| for (TypedKVEntry kvDatum : kvData) { | |||
| System.out.println("kvData.key=" + kvDatum.getKey()); | |||
| System.out.println("kvData.version=" + kvDatum.getVersion()); | |||
| System.out.println("kvData.type=" + kvDatum.getType()); | |||
| System.out.println("kvData.value=" + kvDatum.getValue()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,50 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| 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 com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| public class SDK_RegistParticipant_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_RegistParticipant_Demo().regParticipant(); | |||
| } | |||
| public void regParticipant() { | |||
| //新参与方的公私钥 | |||
| String PUB = "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"; | |||
| String PRIV = "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x"; | |||
| PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); | |||
| PubKey pubKey = KeyGenUtils.decodePubKey(PUB); | |||
| System.out.println("Address = " + AddressEncoding.generateAddress(pubKey)); | |||
| BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(blockchainService.getLedgerHashs()[0]); | |||
| // 注册参与方 | |||
| txTpl.participants().register("Peer4", user.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTpl.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(adminKey); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| System.out.println(transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,26 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.*; | |||
| public class SDK_RoleConfig_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_RoleConfig_Demo().executeRoleConfig(); | |||
| } | |||
| public void executeRoleConfig() { | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 新增加一个角色 | |||
| txTpl.security().roles().configure("MyRole") | |||
| .enable(LedgerPermission.APPROVE_TX, LedgerPermission.CONSENSUS_TX) | |||
| .disable(TransactionPermission.CONTRACT_OPERATION); | |||
| TransactionResponse txResp = commit(txTpl); | |||
| System.out.println(txResp.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,56 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import java.util.Random; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import java.util.concurrent.ExecutorService; | |||
| import java.util.concurrent.Executors; | |||
| public class SDK_Threads_KvInsert_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) throws Exception { | |||
| new SDK_Threads_KvInsert_Demo().executeThreadsInsert(); | |||
| } | |||
| public void executeThreadsInsert() throws Exception { | |||
| final int MAX = 30; | |||
| final String dataAddress = "LdeNqP4S88t1YjkGQaCGbX95ygD6hA2B6yjp6"; | |||
| ExecutorService threadPool = Executors.newFixedThreadPool(50); | |||
| final CountDownLatch latch = new CountDownLatch(MAX); | |||
| for (int i = 0; i < MAX; i++) { | |||
| threadPool.execute(() -> { | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
| String key = System.currentTimeMillis() + "-" + | |||
| System.nanoTime() + "-" + | |||
| new Random(Thread.currentThread().getId()).nextInt(1024); | |||
| txTemp.dataAccount(dataAddress).setText(key,"value1",-1); | |||
| // TX 准备就绪 | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(adminKey); | |||
| // 提交交易; | |||
| TransactionResponse response = prepTx.commit(); | |||
| System.out.printf("Key = %s, Result = %s \r\n", key, response.isSuccess()); | |||
| latch.countDown(); | |||
| }); | |||
| } | |||
| latch.await(); | |||
| System.out.println("It is Over !!!"); | |||
| System.exit(0); | |||
| } | |||
| } | |||
| @@ -1,42 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.Property; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| public class SDK_Update_ConsensusSettings_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_Update_ConsensusSettings_Demo().updateSettings(); | |||
| } | |||
| public void updateSettings() { | |||
| List<Property> properties = new ArrayList<Property>(); | |||
| // 修改bftsmart.conf配置文件中的选项; | |||
| properties.add(new Property("system.communication.useSenderThread", "false")); | |||
| Property[] propertiesArray = properties.toArray(new Property[properties.size()]); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.settings().update(propertiesArray); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTpl.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(adminKey); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| System.out.println(transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,44 +0,0 @@ | |||
| package com.jd.blockchain.sdk.samples; | |||
| import com.jd.blockchain.ledger.*; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class SDK_User2Role_Demo extends SDK_Base_Demo { | |||
| public static void main(String[] args) { | |||
| new SDK_User2Role_Demo().executeUser2Role(); | |||
| } | |||
| public void executeUser2Role() { | |||
| // 定义交易模板 | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 注册一个用户 | |||
| BlockchainKeypair user = createUser(); | |||
| Bytes userAddress = user.getAddress(); | |||
| // 获取数据账户地址 | |||
| System.out.printf("UserAddress = %s \r\n", userAddress.toBase58()); | |||
| txTpl.security().authorziations().forUser(user.getIdentity()) | |||
| .authorize("MYROLE") | |||
| .setPolicy(RolesPolicy.UNION) | |||
| .unauthorize("MYROLE"); | |||
| TransactionResponse txResp = commit(txTpl); | |||
| System.out.println(txResp.isSuccess()); | |||
| } | |||
| private BlockchainKeypair createUser() { | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair newUser = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.users().register(newUser.getIdentity()); | |||
| commit(txTpl); | |||
| return newUser; | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| package com.jd.chain.contracts; | |||
| import com.jd.blockchain.contract.Contract; | |||
| import com.jd.blockchain.contract.ContractEvent; | |||
| @Contract | |||
| public interface ContractTestInf { | |||
| @ContractEvent(name = "print") | |||
| void print(String name, int age); | |||
| @ContractEvent(name = "random") | |||
| String randomChars(int max); | |||
| } | |||
| @@ -0,0 +1,294 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.gateway.GatewayConfigProperties; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.LedgerInitProperties; | |||
| import com.jd.blockchain.ledger.LedgerPermission; | |||
| import com.jd.blockchain.ledger.ParticipantNode; | |||
| import com.jd.blockchain.ledger.ParticipantNodeState; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionPermission; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.tools.initializer.DBConnectionConfig; | |||
| import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | |||
| import com.jd.blockchain.tools.initializer.PresetAnswerPrompter; | |||
| import com.jd.blockchain.tools.initializer.Prompter; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker; | |||
| import com.jd.blockchain.utils.io.FileUtils; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import com.jdchain.samples.sdk.testnet.GatewayRunner; | |||
| import com.jdchain.samples.sdk.testnet.NodeWebContext; | |||
| import com.jdchain.samples.sdk.testnet.PartNode; | |||
| import com.jdchain.samples.sdk.testnet.PeerServer; | |||
| import org.apache.logging.log4j.Level; | |||
| import org.apache.logging.log4j.core.config.Configurator; | |||
| import org.junit.Assert; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.net.URL; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.concurrent.CountDownLatch; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertNotNull; | |||
| /** | |||
| * 测试网络 | |||
| * 初始化启动基于内存的4节点JD Chain网络 | |||
| */ | |||
| public class TestNet { | |||
| // 测试网络公私钥及私钥密码信息 | |||
| private static final String[] PUB_KEYS = { | |||
| "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"}; | |||
| private static final String[] PRIV_KEYS = { | |||
| "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"}; | |||
| private static final String PASSWORD = "abc"; | |||
| // 存储配置 | |||
| private static final String[] dbConnections = { | |||
| "memory://local/0", | |||
| "memory://local/1", | |||
| "memory://local/2", | |||
| "memory://local/3"}; | |||
| // 共识协议 | |||
| private static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; | |||
| // node节点服务端口,共识节点还会占用8910/8920/8930/8940/8911/8921/8931/8941用于共识服务,可以通过修改resources/network/bftsmart.config修改 | |||
| private static final int[] NODE_PORTS = {12000, 12010, 12020, 12030}; | |||
| // 网关服务端口 | |||
| private static final int GATEWAY_PORT = 11000; | |||
| public static void main(String[] args) { | |||
| try { | |||
| Configurator.setRootLevel(Level.OFF); | |||
| // 内存账本初始化 | |||
| HashDigest ledgerHash = initLedger(); | |||
| // 启动Peer节点 | |||
| PeerServer[] peerNodes = peerNodeStart(ledgerHash); | |||
| // 睡20秒,等待共识节点启动成功 | |||
| Thread.sleep(20000); | |||
| // 启动网关 | |||
| startGateway(peerNodes); | |||
| // 初始化样例数据 | |||
| initSampleData(ledgerHash); | |||
| System.out.println(" ------------------- START NETWORK SUCCESS ------------------- "); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| System.out.println(" ------------------- START NETWORK FAILED ------------------- "); | |||
| System.exit(-1); | |||
| } | |||
| } | |||
| private static HashDigest initLedger() throws IOException { | |||
| Prompter consolePrompter = new PresetAnswerPrompter("N"); | |||
| LedgerInitProperties initSetting = LedgerInitProperties.resolve(new ClassPathResource("testnet/ledger.init").getInputStream()); | |||
| ParticipantNode[] participantNodes = new ParticipantNode[PUB_KEYS.length]; | |||
| for (int i = 0; i < PUB_KEYS.length; i++) { | |||
| participantNodes[i] = new PartNode(i, KeyGenUtils.decodePubKey(PUB_KEYS[i]), ParticipantNodeState.CONSENSUS); | |||
| } | |||
| NetworkAddress initAddr0 = initSetting.getConsensusParticipant(0).getInitializerAddress(); | |||
| NodeWebContext node0 = new NodeWebContext(0, initAddr0); | |||
| NetworkAddress initAddr1 = initSetting.getConsensusParticipant(1).getInitializerAddress(); | |||
| NodeWebContext node1 = new NodeWebContext(1, initAddr1); | |||
| NetworkAddress initAddr2 = initSetting.getConsensusParticipant(2).getInitializerAddress(); | |||
| NodeWebContext node2 = new NodeWebContext(2, initAddr2); | |||
| NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); | |||
| NodeWebContext node3 = new NodeWebContext(3, initAddr3); | |||
| PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); | |||
| PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); | |||
| PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); | |||
| PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); | |||
| CountDownLatch quitLatch = new CountDownLatch(4); | |||
| DBConnectionConfig testDb0 = new DBConnectionConfig(); | |||
| testDb0.setConnectionUri(dbConnections[0]); | |||
| ThreadInvoker.AsyncCallback<HashDigest> callback0 = node0.startInit(privkey0, initSetting, testDb0, consolePrompter, | |||
| quitLatch); | |||
| DBConnectionConfig testDb1 = new DBConnectionConfig(); | |||
| testDb1.setConnectionUri(dbConnections[1]); | |||
| ThreadInvoker.AsyncCallback<HashDigest> callback1 = node1.startInit(privkey1, initSetting, testDb1, consolePrompter, | |||
| quitLatch); | |||
| DBConnectionConfig testDb2 = new DBConnectionConfig(); | |||
| testDb2.setConnectionUri(dbConnections[2]); | |||
| ThreadInvoker.AsyncCallback<HashDigest> callback2 = node2.startInit(privkey2, initSetting, testDb2, consolePrompter, | |||
| quitLatch); | |||
| DBConnectionConfig testDb03 = new DBConnectionConfig(); | |||
| testDb03.setConnectionUri(dbConnections[3]); | |||
| ThreadInvoker.AsyncCallback<HashDigest> callback3 = node3.startInit(privkey3, initSetting, testDb03, consolePrompter, | |||
| quitLatch); | |||
| HashDigest ledgerHash0 = callback0.waitReturn(); | |||
| HashDigest ledgerHash1 = callback1.waitReturn(); | |||
| HashDigest ledgerHash2 = callback2.waitReturn(); | |||
| HashDigest ledgerHash3 = callback3.waitReturn(); | |||
| assertNotNull(ledgerHash0); | |||
| assertEquals(ledgerHash0, ledgerHash1); | |||
| assertEquals(ledgerHash0, ledgerHash2); | |||
| assertEquals(ledgerHash0, ledgerHash3); | |||
| return ledgerHash0; | |||
| } | |||
| private static PeerServer[] peerNodeStart(HashDigest ledgerHash) { | |||
| NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", NODE_PORTS[0]); | |||
| LedgerBindingConfig bindingConfig0 = loadBindingConfig(0, ledgerHash); | |||
| PeerServer peer0 = new PeerServer(peerSrvAddr0, bindingConfig0); | |||
| NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", NODE_PORTS[1]); | |||
| LedgerBindingConfig bindingConfig1 = loadBindingConfig(1, ledgerHash); | |||
| PeerServer peer1 = new PeerServer(peerSrvAddr1, bindingConfig1); | |||
| NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", NODE_PORTS[2]); | |||
| LedgerBindingConfig bindingConfig2 = loadBindingConfig(2, ledgerHash); | |||
| PeerServer peer2 = new PeerServer(peerSrvAddr2, bindingConfig2); | |||
| NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", NODE_PORTS[3]); | |||
| LedgerBindingConfig bindingConfig3 = loadBindingConfig(3, ledgerHash); | |||
| PeerServer peer3 = new PeerServer(peerSrvAddr3, bindingConfig3); | |||
| ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start(); | |||
| ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start(); | |||
| ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start(); | |||
| ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start(); | |||
| peerStarting0.waitReturn(); | |||
| peerStarting1.waitReturn(); | |||
| peerStarting2.waitReturn(); | |||
| peerStarting3.waitReturn(); | |||
| return new PeerServer[]{peer0, peer1, peer2, peer3}; | |||
| } | |||
| private static LedgerBindingConfig loadBindingConfig(int id, HashDigest ledgerHash) { | |||
| LedgerBindingConfig ledgerBindingConfig; | |||
| String newLedger = ledgerHash.toBase58(); | |||
| String resourceClassPath = "testnet/ledger-binding-mem-" + id + ".conf"; | |||
| String ledgerBindingUrl = TestNet.class.getResource("/") + resourceClassPath; | |||
| try { | |||
| URL url = new URL(ledgerBindingUrl); | |||
| File ledgerBindingConf = new File(url.getPath()); | |||
| if (ledgerBindingConf.exists()) { | |||
| List<String> readLines = org.apache.commons.io.FileUtils.readLines(ledgerBindingConf); | |||
| List<String> writeLines = new ArrayList<>(); | |||
| if (readLines != null && !readLines.isEmpty()) { | |||
| String oldLedgerLine = null; | |||
| for (String readLine : readLines) { | |||
| if (readLine.startsWith("ledger")) { | |||
| oldLedgerLine = readLine; | |||
| break; | |||
| } | |||
| } | |||
| String[] oldLedgerArray = oldLedgerLine.split("="); | |||
| String oldLedger = oldLedgerArray[1]; | |||
| if (!oldLedger.equalsIgnoreCase(newLedger)) { | |||
| for (String readLine : readLines) { | |||
| String newLine = readLine.replace(oldLedger, newLedger); | |||
| writeLines.add(newLine); | |||
| } | |||
| } | |||
| if (!writeLines.isEmpty()) { | |||
| org.apache.commons.io.FileUtils.writeLines(ledgerBindingConf, writeLines); | |||
| } | |||
| } | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| ClassPathResource res = new ClassPathResource(resourceClassPath); | |||
| try (InputStream in = res.getInputStream()) { | |||
| ledgerBindingConfig = LedgerBindingConfig.resolve(in); | |||
| } catch (IOException e) { | |||
| throw new IllegalStateException(e.getMessage(), e); | |||
| } | |||
| return ledgerBindingConfig; | |||
| } | |||
| private static void startGateway(PeerServer[] peerNodes) { | |||
| GatewayConfigProperties.KeyPairConfig keyPairConfig = new GatewayConfigProperties.KeyPairConfig(); | |||
| keyPairConfig.setPubKeyValue(PUB_KEYS[0]); | |||
| keyPairConfig.setPrivKeyValue(PRIV_KEYS[0]); | |||
| keyPairConfig.setPrivKeyPassword(KeyGenUtils.encodePasswordAsBase58(PASSWORD)); | |||
| GatewayRunner gateway = new GatewayRunner("127.0.0.1", GATEWAY_PORT, keyPairConfig, new String[]{BFTSMART_PROVIDER}, null, peerNodes[0].getServiceAddress()); | |||
| ThreadInvoker.AsyncCallback<Object> gwStarting = gateway.start(); | |||
| gwStarting.waitReturn(); | |||
| } | |||
| private static void initSampleData(HashDigest ledgerHash) throws IOException { | |||
| BlockchainKeypair admin = new BlockchainKeypair(KeyGenUtils.decodePubKey(PUB_KEYS[0]), KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD)); | |||
| BlockchainKeypair user = new BlockchainKeypair( | |||
| KeyGenUtils.decodePubKey("3snPdw7i7PbXVQoUX1Ywo6Cenm9gDB6DFztVazXWrq2qbbmzcAMUVC"), | |||
| KeyGenUtils.decodePrivKey("177gjuGapUVdLnEDAkqjQWhZxHh5jL5W6Hg1q8kbdsbk1BKht4QkmuB6dKvyJrgKTRmXSgK", "8EjkXVSTxMFjCvNNsTo8RBMDEVQmk7gYkW4SCDuvdsBG")); | |||
| BlockchainService blockchainService = GatewayServiceFactory.connect( | |||
| "127.0.0.1", GATEWAY_PORT, false, admin).getBlockchainService(); | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
| // 初始化一个用户 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // 创建角色 MANAGER | |||
| txTemp.security().roles().configure("SAMPLE-ROLE") | |||
| .enable(LedgerPermission.WRITE_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.DIRECT_OPERATION); | |||
| // 设置用户角色权限 | |||
| txTemp.security().authorziations().forUser(user.getAddress()).authorize("SAMPLE-ROLE"); | |||
| // 初始化一个数据账户并设置KV | |||
| txTemp.dataAccounts().register(user.getIdentity()); | |||
| txTemp.dataAccount(user.getAddress()).setText("sample-key", "sample-value", -1); | |||
| // 初始化一个事件账户并发布一个事件 | |||
| txTemp.eventAccounts().register(user.getIdentity()); | |||
| txTemp.eventAccount(user.getAddress()).publish("sample-event", "sample-content", -1); | |||
| // 初始化一个合约 | |||
| txTemp.contracts().deploy(user.getIdentity(), FileUtils.readBytes(new ClassPathResource("contract-samples-1.4.0.RELEASE.car").getFile())); | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| ptx.sign(admin); | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| package com.jdchain.samples.sdk.testnet; | |||
| import com.jd.blockchain.gateway.GatewayConfigProperties; | |||
| import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; | |||
| import com.jd.blockchain.gateway.GatewayServerBooter; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import org.springframework.util.CollectionUtils; | |||
| import java.util.Map; | |||
| public class GatewayRunner { | |||
| private NetworkAddress serviceAddress; | |||
| private GatewayServerBooter gatewayServer; | |||
| public GatewayRunner(String host, int port, KeyPairConfig gatewayDefaultKey, NetworkAddress... masterPeerAddresses) { | |||
| this(host, port, gatewayDefaultKey, null, null, masterPeerAddresses); | |||
| } | |||
| public GatewayRunner(String host, int port, KeyPairConfig gatewayDefaultKey, String[] providers, | |||
| Map<String, Object> otherMap, NetworkAddress... masterPeerAddresses) { | |||
| this.serviceAddress = new NetworkAddress(host, port); | |||
| GatewayConfigProperties config = new GatewayConfigProperties(); | |||
| config.http().setHost(host); | |||
| config.http().setPort(port); | |||
| if (providers != null) { | |||
| for (String provider : providers) { | |||
| config.providerConfig().add(provider); | |||
| } | |||
| } | |||
| for (NetworkAddress address : masterPeerAddresses) { | |||
| config.setMasterPeerAddress(address); | |||
| } | |||
| config.keys().getDefault().setPubKeyValue(gatewayDefaultKey.getPubKeyValue()); | |||
| config.keys().getDefault().setPrivKeyValue(gatewayDefaultKey.getPrivKeyValue()); | |||
| config.keys().getDefault().setPrivKeyPassword(gatewayDefaultKey.getPrivKeyPassword()); | |||
| if (!CollectionUtils.isEmpty(otherMap)) { | |||
| config.setDataRetrievalUrl(otherMap.get("DATA_RETRIEVAL_URL").toString()); | |||
| } | |||
| //get the springConfigLocation; | |||
| ClassPathResource configResource = new ClassPathResource("application-gw.properties"); | |||
| String springConfigLocation = "classPath:" + configResource.getPath(); | |||
| this.gatewayServer = new GatewayServerBooter(config, springConfigLocation); | |||
| } | |||
| public AsyncCallback<Object> start() { | |||
| ThreadInvoker<Object> invoker = new ThreadInvoker<Object>() { | |||
| @Override | |||
| protected Object invoke() throws Exception { | |||
| gatewayServer.start(); | |||
| return null; | |||
| } | |||
| }; | |||
| return invoker.start(); | |||
| } | |||
| public void stop() { | |||
| gatewayServer.close(); | |||
| } | |||
| public NetworkAddress getServiceAddress() { | |||
| return serviceAddress; | |||
| } | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package com.jdchain.samples.sdk.testnet; | |||
| import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; | |||
| import com.jd.blockchain.tools.initializer.web.InitWebSecurityConfiguration; | |||
| import com.jd.blockchain.tools.initializer.web.InitWebServerConfiguration; | |||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.context.annotation.Import; | |||
| @SpringBootApplication | |||
| @Configuration | |||
| @EnableConfigurationProperties | |||
| @Import(value = { InitWebServerConfiguration.class, InitWebSecurityConfiguration.class }) | |||
| public class LedgerInit { | |||
| @Bean | |||
| public CompositeConnectionFactory getCompositeConnectionFactory() { | |||
| return new CompositeConnectionFactory(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,105 @@ | |||
| package com.jdchain.samples.sdk.testnet; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.ledger.LedgerInitProperties; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.core.LedgerInitDecision; | |||
| import com.jd.blockchain.ledger.core.LedgerInitProposal; | |||
| import com.jd.blockchain.ledger.core.LedgerManager; | |||
| import com.jd.blockchain.ledger.core.LedgerQuery; | |||
| import com.jd.blockchain.storage.service.DbConnection; | |||
| import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; | |||
| import com.jd.blockchain.tools.initializer.DBConnectionConfig; | |||
| import com.jd.blockchain.tools.initializer.LedgerInitProcess; | |||
| import com.jd.blockchain.tools.initializer.Prompter; | |||
| import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import org.springframework.boot.SpringApplication; | |||
| import org.springframework.context.ConfigurableApplicationContext; | |||
| import java.util.concurrent.CountDownLatch; | |||
| public class NodeWebContext { | |||
| private NetworkAddress serverAddress; | |||
| private DBConnectionConfig dbConnConfig; | |||
| private volatile ConfigurableApplicationContext ctx; | |||
| private volatile LedgerInitProcess initProcess; | |||
| private volatile LedgerInitializeWebController controller; | |||
| private volatile LedgerManager ledgerManager; | |||
| private volatile CompositeConnectionFactory db; | |||
| private int id; | |||
| public int getId() { | |||
| return controller.getId(); | |||
| } | |||
| public TransactionContent getInitTxContent() { | |||
| return controller.getInitTxContent(); | |||
| } | |||
| public LedgerInitProposal getLocalPermission() { | |||
| return controller.getLocalPermission(); | |||
| } | |||
| public LedgerInitDecision getLocalDecision() { | |||
| return controller.getLocalDecision(); | |||
| } | |||
| public NodeWebContext(int id, NetworkAddress serverAddress) { | |||
| this.id = id; | |||
| this.serverAddress = serverAddress; | |||
| } | |||
| public LedgerQuery registLedger(HashDigest ledgerHash) { | |||
| DbConnection conn = db.connect(dbConnConfig.getUri()); | |||
| LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); | |||
| return ledgerRepo; | |||
| } | |||
| public ThreadInvoker.AsyncCallback<HashDigest> startInit(PrivKey privKey, LedgerInitProperties setting, | |||
| DBConnectionConfig dbConnConfig, Prompter prompter, CountDownLatch quitLatch) { | |||
| ThreadInvoker<HashDigest> invoker = new ThreadInvoker<HashDigest>() { | |||
| @Override | |||
| protected HashDigest invoke() throws Exception { | |||
| doStartServer(); | |||
| NodeWebContext.this.dbConnConfig = dbConnConfig; | |||
| HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, | |||
| dbConnConfig, prompter); | |||
| quitLatch.countDown(); | |||
| return ledgerHash; | |||
| } | |||
| }; | |||
| return invoker.start(); | |||
| } | |||
| public void doStartServer() { | |||
| String argServerAddress = String.format("--server.address=%s", serverAddress.getHost()); | |||
| String argServerPort = String.format("--server.port=%s", serverAddress.getPort()); | |||
| String nodebug = "--debug=false"; | |||
| String[] innerArgs = {argServerAddress, argServerPort, nodebug}; | |||
| ctx = SpringApplication.run(LedgerInit.class, innerArgs); | |||
| ctx.setId("Node-" + id); | |||
| controller = ctx.getBean(LedgerInitializeWebController.class); | |||
| ledgerManager = ctx.getBean(LedgerManager.class); | |||
| db = ctx.getBean(CompositeConnectionFactory.class); | |||
| initProcess = ctx.getBean(LedgerInitProcess.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,58 @@ | |||
| package com.jdchain.samples.sdk.testnet; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.ParticipantNode; | |||
| import com.jd.blockchain.ledger.ParticipantNodeState; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class PartNode implements ParticipantNode { | |||
| private int id; | |||
| private Bytes address; | |||
| private String name; | |||
| private PubKey pubKey; | |||
| private ParticipantNodeState participantNodeState; | |||
| public PartNode(int id, PubKey pubKey, ParticipantNodeState participantNodeState) { | |||
| this(id, id + "", pubKey, participantNodeState); | |||
| } | |||
| public PartNode(int id, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { | |||
| this.id = id; | |||
| this.name = name; | |||
| this.pubKey = pubKey; | |||
| this.address = AddressEncoding.generateAddress(pubKey); | |||
| this.participantNodeState = participantNodeState; | |||
| } | |||
| @Override | |||
| public int getId() { | |||
| return id; | |||
| } | |||
| @Override | |||
| public Bytes getAddress() { | |||
| return address; | |||
| } | |||
| @Override | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| @Override | |||
| public PubKey getPubKey() { | |||
| return pubKey; | |||
| } | |||
| @Override | |||
| public ParticipantNodeState getParticipantNodeState() { | |||
| return participantNodeState; | |||
| } | |||
| } | |||
| @@ -0,0 +1,66 @@ | |||
| package com.jdchain.samples.sdk.testnet; | |||
| import com.jd.blockchain.ledger.core.LedgerManager; | |||
| import com.jd.blockchain.peer.PeerServerBooter; | |||
| import com.jd.blockchain.storage.service.DbConnectionFactory; | |||
| import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | |||
| import com.jd.blockchain.utils.concurrent.ThreadInvoker; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| public class PeerServer { | |||
| private NetworkAddress serviceAddress; | |||
| private volatile PeerServerBooter booter; | |||
| private LedgerBindingConfig ledgerBindingConfig; | |||
| public DbConnectionFactory getDBConnectionFactory() { | |||
| return booter.getDBConnectionFactory(); | |||
| } | |||
| public NetworkAddress getServiceAddress() { | |||
| return serviceAddress; | |||
| } | |||
| public LedgerBindingConfig getLedgerBindingConfig() { | |||
| return ledgerBindingConfig; | |||
| } | |||
| public PeerServer(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig) { | |||
| this(serviceAddress, ledgerBindingConfig, null, null); | |||
| } | |||
| public PeerServer(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig, DbConnectionFactory dbConnectionFactory) { | |||
| this(serviceAddress, ledgerBindingConfig, dbConnectionFactory, null); | |||
| } | |||
| public PeerServer(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig, | |||
| DbConnectionFactory dbConnectionFactory, LedgerManager ledgerManager) { | |||
| this.serviceAddress = serviceAddress; | |||
| this.ledgerBindingConfig = ledgerBindingConfig; | |||
| if (dbConnectionFactory == null) { | |||
| this.booter = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), | |||
| serviceAddress.getPort()); | |||
| } else { | |||
| this.booter = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), | |||
| serviceAddress.getPort(), dbConnectionFactory, ledgerManager); | |||
| } | |||
| } | |||
| public ThreadInvoker.AsyncCallback<Object> start() { | |||
| ThreadInvoker<Object> invoker = new ThreadInvoker<Object>() { | |||
| @Override | |||
| protected Object invoke() throws Exception { | |||
| booter.start(); | |||
| return null; | |||
| } | |||
| }; | |||
| return invoker.start(); | |||
| } | |||
| public void stop() { | |||
| booter.close(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| # SDK Sample 相关配置,请根据实际情况进行修改 | |||
| # 签名用户配置 | |||
| # 公钥 | |||
| pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 | |||
| # 私钥 | |||
| privkey=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x | |||
| # Base58编码的私钥密码 | |||
| password=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY | |||
| # 网关配置 | |||
| # IP | |||
| gateway.host=localhost | |||
| # 端口 | |||
| gateway.port=11000 | |||
| # 账本,为空时选择网关查询到的账本列表第一个 | |||
| ledger= | |||
| @@ -0,0 +1,155 @@ | |||
| # Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags | |||
| # | |||
| # Licensed under the Apache License, Version 2.0 (the "License"); | |||
| # you may not use this file except in compliance with the License. | |||
| # You may obtain a copy of the License at | |||
| # | |||
| # http://www.apache.org/licenses/LICENSE-2.0 | |||
| # | |||
| # Unless required by applicable law or agreed to in writing, software | |||
| # distributed under the License is distributed on an "AS IS" BASIS, | |||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| # See the License for the specific language governing permissions and | |||
| # limitations under the License. | |||
| ############################################ | |||
| ###### Consensus Participant0 ###### | |||
| ############################################ | |||
| system.server.0.network.host=127.0.0.1 | |||
| system.server.0.network.port=8910 | |||
| system.server.0.network.secure=false | |||
| ############################################ | |||
| ###### #Consensus Participant1 ###### | |||
| ############################################ | |||
| system.server.1.network.host=127.0.0.1 | |||
| system.server.1.network.port=8920 | |||
| system.server.1.network.secure=false | |||
| ############################################ | |||
| ###### #Consensus Participant2 ###### | |||
| ############################################ | |||
| system.server.2.network.host=127.0.0.1 | |||
| system.server.2.network.port=8930 | |||
| system.server.2.network.secure=false | |||
| ############################################ | |||
| ###### Consensus Participant3 ###### | |||
| ############################################ | |||
| system.server.3.network.host=127.0.0.1 | |||
| system.server.3.network.port=8940 | |||
| system.server.3.network.secure=false | |||
| ############################################ | |||
| ####### Communication Configurations ####### | |||
| ############################################ | |||
| #HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value) | |||
| #This parameter is not currently being used being used | |||
| #system.authentication.hmacAlgorithm = HmacSHA1 | |||
| #Specify if the communication system should use a thread to send data (true or false) | |||
| system.communication.useSenderThread = true | |||
| #Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments | |||
| #and benchmarks, but must not be used in production systems. | |||
| system.communication.defaultkeys = true | |||
| ############################################ | |||
| ### Replication Algorithm Configurations ### | |||
| ############################################ | |||
| #Number of servers in the group | |||
| system.servers.num = 4 | |||
| #Maximum number of faulty replicas | |||
| system.servers.f = 1 | |||
| #Timeout to asking for a client request | |||
| system.totalordermulticast.timeout = 5000 | |||
| #Maximum batch size (in number of messages) | |||
| system.totalordermulticast.maxbatchsize = 400 | |||
| #Number of nonces (for non-determinism actions) generated | |||
| system.totalordermulticast.nonces = 10 | |||
| #if verification of leader-generated timestamps are increasing | |||
| #it can only be used on systems in which the network clocks | |||
| #are synchronized | |||
| system.totalordermulticast.verifyTimestamps = false | |||
| #Quantity of messages that can be stored in the receive queue of the communication system | |||
| system.communication.inQueueSize = 500000 | |||
| # Quantity of messages that can be stored in the send queue of each replica | |||
| system.communication.outQueueSize = 500000 | |||
| #Set to 1 if SMaRt should use signatures, set to 0 if otherwise | |||
| system.communication.useSignatures = 0 | |||
| #Set to 1 if SMaRt should use MAC's, set to 0 if otherwise | |||
| system.communication.useMACs = 1 | |||
| #Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise | |||
| system.debug = 0 | |||
| #Print information about the replica when it is shutdown | |||
| system.shutdownhook = true | |||
| ############################################ | |||
| ###### State Transfer Configurations ####### | |||
| ############################################ | |||
| #Activate the state transfer protocol ('true' to activate, 'false' to de-activate) | |||
| system.totalordermulticast.state_transfer = true | |||
| #Maximum ahead-of-time message not discarded | |||
| system.totalordermulticast.highMark = 10000 | |||
| #Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered) | |||
| system.totalordermulticast.revival_highMark = 10 | |||
| #Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs | |||
| system.totalordermulticast.timeout_highMark = 200 | |||
| ############################################ | |||
| ###### Log and Checkpoint Configurations ### | |||
| ############################################ | |||
| system.totalordermulticast.log = true | |||
| system.totalordermulticast.log_parallel = false | |||
| system.totalordermulticast.log_to_disk = false | |||
| system.totalordermulticast.sync_log = false | |||
| #Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) | |||
| system.totalordermulticast.checkpoint_period = 1000 | |||
| system.totalordermulticast.global_checkpoint_period = 120000 | |||
| system.totalordermulticast.checkpoint_to_disk = false | |||
| system.totalordermulticast.sync_ckp = false | |||
| ############################################ | |||
| ###### Reconfiguration Configurations ###### | |||
| ############################################ | |||
| #Replicas ID for the initial view, separated by a comma. | |||
| # The number of replicas in this parameter should be equal to that specified in 'system.servers.num' | |||
| system.initial.view = 0,1,2,3 | |||
| #The ID of the trust third party (TTP) | |||
| system.ttp.id = 2001 | |||
| #This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults | |||
| system.bft = true | |||
| #Custom View Storage; | |||
| #view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage | |||
| @@ -0,0 +1,23 @@ | |||
| #绑定的账本的hash列表;以逗号分隔; | |||
| ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ | |||
| #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; | |||
| #账本的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=sample-network | |||
| #账本的当前共识参与方的ID; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=0 | |||
| #账本的当前共识参与方的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=a.com | |||
| #账本的当前共识参与方的私钥文件的保存路径; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= | |||
| #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x | |||
| #账本的当前共识参与方的私钥文件的读取口令;可为空;如果为空时,节点的启动过程中需要手动从控制台输入; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY | |||
| #账本的当前共识参与方地址 | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.address=LdeP3fY7jJbNwL8CiL2wU21AF9unDWQjVEW5w | |||
| #账本的存储数据库的连接字符串; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.uri=memory://local/0 | |||
| #账本的存储数据库的连接口令; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.pwd= | |||
| @@ -0,0 +1,23 @@ | |||
| #绑定的账本的hash列表;以逗号分隔; | |||
| ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ | |||
| #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; | |||
| #账本的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=sample-network | |||
| #账本的当前共识参与方的ID; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=1 | |||
| #账本的当前共识参与方的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=b.com | |||
| #账本的当前共识参与方的私钥文件的保存路径; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= | |||
| #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk=177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT | |||
| #账本的当前共识参与方的私钥文件的读取口令;可为空;如果为空时,节点的启动过程中需要手动从控制台输入; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY | |||
| #账本的当前共识参与方地址 | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.address=LdeNnz88dH6CA6PwkVdn3nFRibUKP3sFT2byG | |||
| #账本的存储数据库的连接字符串; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.uri=memory://local/1 | |||
| #账本的存储数据库的连接口令; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.pwd= | |||
| @@ -0,0 +1,23 @@ | |||
| #绑定的账本的hash列表;以逗号分隔; | |||
| ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ | |||
| #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; | |||
| #账本的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=sample-network | |||
| #账本的当前共识参与方的ID; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=2 | |||
| #账本的当前共识参与方的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=c.com | |||
| #账本的当前共识参与方的私钥文件的保存路径; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= | |||
| #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk=177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF | |||
| #账本的当前共识参与方的私钥文件的读取口令;可为空;如果为空时,节点的启动过程中需要手动从控制台输入; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY | |||
| #账本的当前共识参与方地址 | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.address=LdeNmdpT4DiTwLUP9jRQhwdRBRiXeHno456vy | |||
| #账本的存储数据库的连接字符串; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.uri=memory://local/2 | |||
| #账本的存储数据库的连接口令; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.pwd= | |||
| @@ -0,0 +1,23 @@ | |||
| #绑定的账本的hash列表;以逗号分隔; | |||
| ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ | |||
| #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; | |||
| #账本的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=sample-network | |||
| #账本的当前共识参与方的ID; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=3 | |||
| #账本的当前共识参与方的名字; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=d.com | |||
| #账本的当前共识参与方的私钥文件的保存路径; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= | |||
| #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk=177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns | |||
| #账本的当前共识参与方的私钥文件的读取口令;可为空;如果为空时,节点的启动过程中需要手动从控制台输入; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY | |||
| #账本的当前共识参与方地址 | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.address=LdeNekdXMHqyz9Qxc2jDSBnkvvZLbty6pRDdP | |||
| #账本的存储数据库的连接字符串; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.uri=memory://local/3 | |||
| #账本的存储数据库的连接口令; | |||
| binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.db.pwd= | |||
| @@ -0,0 +1,74 @@ | |||
| #账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取; | |||
| ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe | |||
| #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; | |||
| ledger.name=sample-ledger | |||
| #声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 | |||
| created-time=2019-08-01 14:26:58.069+0800 | |||
| #共识服务提供者;必须; | |||
| consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider | |||
| #共识服务的参数配置;必须; | |||
| consensus.conf=classpath:testnet/bftsmart.config | |||
| #密码服务提供者列表,以英文逗点“,”分隔;必须; | |||
| crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ | |||
| com.jd.blockchain.crypto.service.sm.SMCryptoService | |||
| #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; | |||
| cons_parti.count=4 | |||
| #第0个参与方的名称; | |||
| cons_parti.0.name=a.com | |||
| #第0个参与方的公钥文件路径; | |||
| cons_parti.0.pubkey-path= | |||
| #第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | |||
| cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 | |||
| #第0个参与方的账本初始服务的主机; | |||
| cons_parti.0.initializer.host=127.0.0.1 | |||
| #第0个参与方的账本初始服务的端口; | |||
| cons_parti.0.initializer.port=9800 | |||
| #第0个参与方的账本初始服务是否开启安全连接; | |||
| cons_parti.0.initializer.secure=false | |||
| #第1个参与方的名称; | |||
| cons_parti.1.name=b.com | |||
| #第1个参与方的公钥文件路径; | |||
| cons_parti.1.pubkey-path= | |||
| #第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | |||
| cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX | |||
| #第1个参与方的账本初始服务的主机; | |||
| cons_parti.1.initializer.host=127.0.0.1 | |||
| #第1个参与方的账本初始服务的端口; | |||
| cons_parti.1.initializer.port=9810 | |||
| #第1个参与方的账本初始服务是否开启安全连接; | |||
| cons_parti.1.initializer.secure=false | |||
| #第2个参与方的名称; | |||
| cons_parti.2.name=c.com | |||
| #第2个参与方的公钥文件路径; | |||
| cons_parti.2.pubkey-path= | |||
| #第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | |||
| cons_parti.2.pubkey=3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x | |||
| #第2个参与方的账本初始服务的主机; | |||
| cons_parti.2.initializer.host=127.0.0.1 | |||
| #第2个参与方的账本初始服务的端口; | |||
| cons_parti.2.initializer.port=9820 | |||
| #第2个参与方的账本初始服务是否开启安全连接; | |||
| cons_parti.2.initializer.secure=false | |||
| #第3个参与方的名称; | |||
| cons_parti.3.name=c.com | |||
| #第3个参与方的公钥文件路径; | |||
| cons_parti.3.pubkey-path= | |||
| #第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; | |||
| cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk | |||
| #第3个参与方的账本初始服务的主机; | |||
| cons_parti.3.initializer.host=127.0.0.1 | |||
| #第3个参与方的账本初始服务的端口; | |||
| cons_parti.3.initializer.port=9830 | |||
| #第3个参与方的账本初始服务是否开启安全连接; | |||
| cons_parti.3.initializer.secure=false | |||
| @@ -0,0 +1,65 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.io.FileUtils; | |||
| import com.jdchain.samples.contract.SampleContract; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| /** | |||
| * 合约相关操作示例: | |||
| * 合约部署,合约调用 | |||
| */ | |||
| public class ContractSample extends SampleBase { | |||
| /** | |||
| * 有两种方式部署合约: | |||
| * 1. contract-samples模块下,配置好pom里面的参数,执行 mvn clean deploy 即可 | |||
| * 2. 打包contract-samples项目生成 car包,参考testDeploy测试代码部署 | |||
| */ | |||
| @Test | |||
| public void testDeploy() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成合约账户 | |||
| BlockchainKeypair contractAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("合约地址:" + contractAccount.getAddress()); | |||
| // 部署合约 | |||
| txTemp.contracts().deploy(contractAccount.getIdentity(), FileUtils.readBytes("src/main/resources/contract-samples-1.4.0.RELEASE.car")); | |||
| // 准备交易 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 合约调用 | |||
| */ | |||
| @Test | |||
| public void testExecute() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 运行前,填写正确的合约地址 | |||
| // 调用合约的 registerUser 方法 | |||
| txTemp.contract("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye", SampleContract.class).registerUser("至少32位字节数-----------------------------"); | |||
| // 准备交易 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| Assert.assertEquals(1, response.getOperationResults().length); | |||
| System.out.println(response.getOperationResults()[0].getResult().getBytes().toString()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| /** | |||
| * 数据账户相关操作示例: | |||
| * 创建数据账户,写入KV数据 | |||
| */ | |||
| public class DataAccountSample extends SampleBase { | |||
| /** | |||
| * 注册数据账户 | |||
| */ | |||
| @Test | |||
| public void testRegisterDataAccount() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成数据账户 | |||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("数据账户地址:" + dataAccount.getAddress()); | |||
| // 注册数据账户 | |||
| txTemp.dataAccounts().register(adminKey.getIdentity()); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 设置KV | |||
| */ | |||
| @Test | |||
| public void testSetKV() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 请正确填写数据账户地址 | |||
| // expVersion是针对此key的插入更新操作次数严格递增,初始为-1 | |||
| txTemp.dataAccount(Bytes.fromBase58("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye")) | |||
| .setText("key1", "value1", -1) | |||
| .setInt64("key2", 1, -1) | |||
| .setJSON("key3", "{}", -1) | |||
| .setBytes("key4", Bytes.fromInt(2), -1); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 注册数据账户的同时设置KV,一个事务内 | |||
| */ | |||
| @Test | |||
| public void testRegisterDataAccountAndSetKV() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成数据账户 | |||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("数据账户地址:" + dataAccount.getAddress()); | |||
| // 注册数据账户 | |||
| txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
| // 设置KV | |||
| txTemp.dataAccount(dataAccount.getAddress()) | |||
| .setText("key", "value", -1); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,137 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.ledger.Event; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.SystemEvent; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| import java.util.concurrent.CountDownLatch; | |||
| /** | |||
| * 事件账户相关操作示例: | |||
| * 事件账户创建,事件发布,事件监听 | |||
| */ | |||
| public class EventSample extends SampleBase { | |||
| /** | |||
| * 事件监听 | |||
| */ | |||
| @Test | |||
| public void testEventListen() { | |||
| // 事件监听会创建子线程,为阻止子线程被直接关闭,加入等待 | |||
| CountDownLatch cdl = new CountDownLatch(1); | |||
| // 监听系统事件,目前仅有新区快产生事件 | |||
| blockchainService.monitorSystemEvent(ledger, | |||
| SystemEvent.NEW_BLOCK_CREATED, 0, (eventMessages, eventContext) -> { | |||
| for (Event eventMessage : eventMessages) { | |||
| // content中存放的是当前链上最新高度 | |||
| System.out.println("New block:" + eventMessage.getSequence() + ":" + BytesUtils.toLong(eventMessage.getContent().getBytes().toBytes())); | |||
| } | |||
| }); | |||
| // 监听用户自定义事件 | |||
| blockchainService.monitorUserEvent(ledger, "LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye", "sample-event", 0, (eventMessage, eventContext) -> { | |||
| BytesValue content = eventMessage.getContent(); | |||
| switch (content.getType()) { | |||
| case TEXT: | |||
| case XML: | |||
| case JSON: | |||
| System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + content.getBytes().toUTF8String()); | |||
| break; | |||
| case INT64: | |||
| case TIMESTAMP: | |||
| System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + BytesUtils.toLong(content.getBytes().toBytes())); | |||
| break; | |||
| default: // byte[], Bytes | |||
| System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + content.getBytes().toBase58()); | |||
| break; | |||
| } | |||
| }); | |||
| try { | |||
| cdl.await(); | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| /** | |||
| * 注册事件账户 | |||
| */ | |||
| @Test | |||
| public void testRegisterEventAccount() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成事件账户 | |||
| BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("事件账户地址:" + eventAccount.getAddress()); | |||
| // 注册事件账户 | |||
| txTemp.eventAccounts().register(eventAccount.getIdentity()); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 发布事件 | |||
| */ | |||
| @Test | |||
| public void testPublishEvent() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 请正确填写数据账户地址 | |||
| // sequence是针对此消息name的插入更新操作次数严格递增,初始为-1 | |||
| txTemp.eventAccount(Bytes.fromBase58("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye")) | |||
| .publish("topic1", "content1", -1) | |||
| .publish("topic1", "content2", 0) | |||
| .publish("topic1", "content3", 1) | |||
| .publish("topic2", "content", -1) | |||
| .publish("topic3", 1, -1) | |||
| .publish("topic4", Bytes.fromInt(1), -1); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 注册事件账户的同时发布事件,一个事务内 | |||
| */ | |||
| @Test | |||
| public void testRegisterEventAccountAndPublishEvent() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成事件账户 | |||
| BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("事件账户地址:" + eventAccount.getAddress()); | |||
| // 注册事件账户 | |||
| txTemp.eventAccounts().register(eventAccount.getIdentity()); | |||
| // 发布事件 | |||
| txTemp.eventAccount(eventAccount.getAddress()).publish("topic", "content", -1); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,132 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import com.jd.blockchain.utils.http.converters.JsonResponseConverter; | |||
| import com.jd.blockchain.utils.security.ShaUtils; | |||
| import com.jd.blockchain.utils.web.model.WebResponse; | |||
| import org.apache.http.HttpResponse; | |||
| import org.apache.http.client.HttpClient; | |||
| import org.apache.http.client.entity.UrlEncodedFormEntity; | |||
| import org.apache.http.client.methods.HttpPost; | |||
| import org.apache.http.impl.client.HttpClients; | |||
| import org.apache.http.message.BasicNameValuePair; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| /** | |||
| * 参与方节点相关操作示例: | |||
| * 注册/激活/移除参与方操作 | |||
| * <p> | |||
| * 本样例无法直接运行,请用户务必参照共识节点相关操作文档步骤完成各种前置操作,然后根据实际配置修改本样例各方法内参数 | |||
| */ | |||
| public class ParticipantSample extends SampleBase { | |||
| // 注册参与方 | |||
| @Test | |||
| public void registerParticipant() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成用户信息 | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| String pwd = Base58Utils.encode(ShaUtils.hash_256("1".getBytes())); | |||
| System.out.println("参与方私钥:" + KeyGenUtils.encodePrivKey(user.getPrivKey(), pwd)); | |||
| System.out.println("参与方私钥密码:" + pwd); | |||
| System.out.println("参与方公钥:" + KeyGenUtils.encodePubKey(user.getPubKey())); | |||
| System.out.println("参与方地址:" + user.getAddress()); | |||
| // 注册参与方 | |||
| txTemp.participants().register("new peer node", user.getIdentity()); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 激活参与方 | |||
| * 执行前请确保新节点已注册,且已经参照共识节点相关操作文档创建并启动新节点!!! | |||
| * 然后根据实际情况修改请求参数 | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Test | |||
| public void activeParticipant() throws Exception { | |||
| // 新节点API服务IP和端口 | |||
| String newNodeIp = "127.0.0.1"; | |||
| String newNodeApiPort = "12040"; | |||
| // 账本信息 | |||
| String ledgerHash = ledger.toString(); | |||
| // 新节点共识配置 | |||
| String newNodeConsensusHost = "127.0.0.1"; | |||
| String newNodeConsensusPot = "8950"; | |||
| // 区块高度最新的节点API服务IP和端口,用于区块同步 | |||
| String syncNodeHost = "127.0.0.1"; | |||
| String syncNodePort = "12000"; | |||
| // 发送POST请求执行节点激活操作 | |||
| HttpPost httpPost = new HttpPost(String.format("http://%s:%s/management/delegate/activeparticipant", newNodeIp, newNodeApiPort)); | |||
| List<BasicNameValuePair> params = new ArrayList<>(); | |||
| params.add(new BasicNameValuePair("ledgerHash", ledgerHash)); | |||
| params.add(new BasicNameValuePair("consensusHost", newNodeConsensusHost)); | |||
| params.add(new BasicNameValuePair("consensusPort", newNodeConsensusPot)); | |||
| params.add(new BasicNameValuePair("remoteManageHost", syncNodeHost)); | |||
| params.add(new BasicNameValuePair("remoteManagePort", syncNodePort)); | |||
| params.add(new BasicNameValuePair("shutdown", "false")); | |||
| httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); | |||
| HttpClient httpClient = HttpClients.createDefault(); | |||
| HttpResponse response = httpClient.execute(httpPost); | |||
| JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); | |||
| WebResponse webResponse = (WebResponse) jsonConverter.getResponse(null, response.getEntity().getContent(), null); | |||
| Assert.assertTrue(webResponse.isSuccess()); | |||
| } | |||
| /** | |||
| * 移除参与方 | |||
| * 执行前请确保新节点已启动且出于参与共识状态!!! | |||
| * 然后根据实际情况修改请求参数 | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Test | |||
| public void removeParticipant() throws Exception { | |||
| // 待移除节点API服务IP和端口 | |||
| String nodeIp = "127.0.0.1"; | |||
| String nodeApiPort = "12030"; | |||
| // 账本信息 | |||
| String ledgerHash = ledger.toString(); | |||
| // 待移除节点地址 | |||
| String participantAddress = "LdeNekdXMHqyz9Qxc2jDSBnkvvZLbty6pRDdP"; | |||
| // 区块高度最新的节点API服务IP和端口,用于区块同步 | |||
| String syncNodeHost = "127.0.0.1"; | |||
| String syncNodePort = "12000"; | |||
| // 发送POST请求执行节点移除操作 | |||
| HttpPost httpPost = new HttpPost(String.format("http://%s:%s/management/delegate/deactiveparticipant", nodeIp, nodeApiPort)); | |||
| List<BasicNameValuePair> params = new ArrayList<>(); | |||
| params.add(new BasicNameValuePair("ledgerHash", ledgerHash)); | |||
| params.add(new BasicNameValuePair("participantAddress", participantAddress)); | |||
| params.add(new BasicNameValuePair("remoteManageHost", syncNodeHost)); | |||
| params.add(new BasicNameValuePair("remoteManagePort", syncNodePort)); | |||
| httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); | |||
| HttpClient httpClient = HttpClients.createDefault(); | |||
| HttpResponse response = httpClient.execute(httpPost); | |||
| JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); | |||
| WebResponse webResponse = (WebResponse) jsonConverter.getResponse(null, response.getEntity().getContent(), null); | |||
| Assert.assertTrue(webResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,587 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.BytesValue; | |||
| import com.jd.blockchain.ledger.ContractInfo; | |||
| import com.jd.blockchain.ledger.DataAccountInfo; | |||
| import com.jd.blockchain.ledger.Event; | |||
| import com.jd.blockchain.ledger.KVDataVO; | |||
| import com.jd.blockchain.ledger.KVInfoVO; | |||
| import com.jd.blockchain.ledger.LedgerAdminInfo; | |||
| import com.jd.blockchain.ledger.LedgerBlock; | |||
| import com.jd.blockchain.ledger.LedgerInfo; | |||
| import com.jd.blockchain.ledger.LedgerMetadata; | |||
| import com.jd.blockchain.ledger.LedgerPermission; | |||
| import com.jd.blockchain.ledger.LedgerTransaction; | |||
| import com.jd.blockchain.ledger.ParticipantNode; | |||
| import com.jd.blockchain.ledger.PrivilegeSet; | |||
| import com.jd.blockchain.ledger.TransactionPermission; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.ledger.UserInfo; | |||
| import com.jd.blockchain.ledger.UserPrivilegeSet; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import com.jd.blockchain.utils.io.BytesUtils; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| /** | |||
| * 查询样例 | |||
| */ | |||
| public class QuerySample extends SampleBase { | |||
| HashDigest sampleHash = Crypto.resolveAsHashDigest(Base58Utils.decode("j5sTuEAWmLWKFwXgpdUCxbQN1XmZfkQdC94UT2AqQEt7hp")); | |||
| String sampleAddress = "LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye"; | |||
| String sampleKey = "sample-key"; | |||
| String sampleEvent = "sample-event"; | |||
| long sampleVersion = 0; | |||
| String sampleRoleName = "SAMPLE-ROLE"; | |||
| /** | |||
| * 查询账本列表 | |||
| */ | |||
| @Test | |||
| public void getLedgerHashs() { | |||
| HashDigest[] digests = blockchainService.getLedgerHashs(); | |||
| for (HashDigest digest : digests) { | |||
| System.out.println(digest.toBase58()); | |||
| } | |||
| } | |||
| /** | |||
| * 查询账本信息,区块hash,区块高度 | |||
| */ | |||
| @Test | |||
| public void getLedger() { | |||
| LedgerInfo ledgerInfo = blockchainService.getLedger(ledger); | |||
| System.out.println(ledgerInfo.getHash()); | |||
| } | |||
| /** | |||
| * 查询账本信息,元数据,参与方,账本配置等 | |||
| */ | |||
| @Test | |||
| public void getLedgerAdminInfo() { | |||
| LedgerAdminInfo adminInfo = blockchainService.getLedgerAdminInfo(ledger); | |||
| System.out.println(adminInfo.getParticipantCount()); | |||
| } | |||
| /** | |||
| * 查询共识参与方 | |||
| */ | |||
| @Test | |||
| public void getConsensusParticipants() { | |||
| ParticipantNode[] nodes = blockchainService.getConsensusParticipants(ledger); | |||
| for (ParticipantNode node : nodes) { | |||
| System.out.println("ID: " + node.getId()); | |||
| System.out.println("Address: " + node.getAddress().toString()); | |||
| System.out.println("PubKey: " + node.getPubKey().toString()); | |||
| System.out.println("State: " + node.getParticipantNodeState()); | |||
| } | |||
| } | |||
| /** | |||
| * 查询账本的元数据 | |||
| */ | |||
| @Test | |||
| public void getLedgerMetadata() { | |||
| LedgerMetadata metadata = blockchainService.getLedgerMetadata(ledger); | |||
| System.out.println(Base58Utils.encode(metadata.getSeed())); | |||
| System.out.println(metadata.getParticipantsHash().toBase58()); | |||
| System.out.println(metadata.getSettingsHash().toBase58()); | |||
| } | |||
| /** | |||
| * 根据高度查询区块 | |||
| */ | |||
| @Test | |||
| public void getBlockByHeight() { | |||
| LedgerBlock block1 = blockchainService.getBlock(ledger, -1); | |||
| LedgerBlock block2 = blockchainService.getBlock(ledger, Integer.MAX_VALUE); | |||
| Assert.assertNotNull(block1); | |||
| Assert.assertEquals(block1.getHash(), block2.getHash()); | |||
| LedgerBlock block3 = blockchainService.getBlock(ledger, 0); | |||
| Assert.assertTrue(block1.getHeight() >= block3.getHeight()); | |||
| } | |||
| /** | |||
| * 根据hash查询区块 | |||
| */ | |||
| @Test | |||
| public void getBlockByHash() { | |||
| LedgerBlock block = blockchainService.getBlock(ledger, sampleHash); | |||
| Assert.assertNull(block); | |||
| } | |||
| /** | |||
| * 查询某一高度(包括)之前所有交易数 | |||
| */ | |||
| @Test | |||
| public void getTransactionCountByHeight() { | |||
| long count = blockchainService.getTransactionCount(ledger, -1); | |||
| Assert.assertEquals(0, count); | |||
| count = blockchainService.getTransactionCount(ledger, 1); | |||
| Assert.assertNotEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询某一区块(包括)之前所有交易数 | |||
| */ | |||
| @Test | |||
| public void getTransactionCountByHash() { | |||
| long count = blockchainService.getTransactionCount(ledger, sampleHash); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询交易总数 | |||
| */ | |||
| @Test | |||
| public void getTransactionTotalCount() { | |||
| long count = blockchainService.getTransactionTotalCount(ledger); | |||
| Assert.assertNotEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询某一高度(包括)之前数据账户数 | |||
| */ | |||
| @Test | |||
| public void getDataAccountCountByHeight() { | |||
| long count = blockchainService.getDataAccountCount(ledger, 0); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询某一区块(包括)之前数据账户数 | |||
| */ | |||
| @Test | |||
| public void getDataAccountCountByHash() { | |||
| long count = blockchainService.getDataAccountCount(ledger, sampleHash); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询数据账户总数 | |||
| */ | |||
| @Test | |||
| public void getDataAccountTotalCount() { | |||
| long count = blockchainService.getDataAccountTotalCount(ledger); | |||
| System.out.println("Total DataAccount count: " + count); | |||
| } | |||
| /** | |||
| * 查询某一高度(包括)之前用户数 | |||
| */ | |||
| @Test | |||
| public void getUserCountByHeight() { | |||
| long count = blockchainService.getUserCount(ledger, 0); | |||
| Assert.assertEquals(4, count); | |||
| } | |||
| /** | |||
| * 查询某一区块(包括)之前用户数 | |||
| */ | |||
| @Test | |||
| public void getUserCountByHash() { | |||
| long count = blockchainService.getUserCount(ledger, sampleHash); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询用户总数 | |||
| */ | |||
| @Test | |||
| public void getUserTotalCount() { | |||
| long count = blockchainService.getUserTotalCount(ledger); | |||
| System.out.println("Total User count: " + count); | |||
| } | |||
| /** | |||
| * 查询某一高度(包括)之前合约数 | |||
| */ | |||
| @Test | |||
| public void getContractCountByHeight() { | |||
| long count = blockchainService.getContractCount(ledger, 0); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询某一区块(包括)之前合约数 | |||
| */ | |||
| @Test | |||
| public void getContractCountByHash() { | |||
| long count = blockchainService.getContractCount(ledger, sampleHash); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 查询合约总数 | |||
| */ | |||
| @Test | |||
| public void getContractTotalCount() { | |||
| long count = blockchainService.getContractTotalCount(ledger); | |||
| System.out.println("Total Contract count: " + count); | |||
| } | |||
| /** | |||
| * 分页查询交易某一高度(包括)之前的所有交易 | |||
| */ | |||
| @Test | |||
| public void getTransactionsByHeight() { | |||
| LedgerTransaction[] txs = blockchainService.getTransactions(ledger, 0, 0, 1); | |||
| Assert.assertEquals(1, txs.length); | |||
| } | |||
| /** | |||
| * 分页查询交易某一区块(包括)之前的所有交易 | |||
| */ | |||
| @Test | |||
| public void getTransactionsByHash() { | |||
| LedgerTransaction[] txs = blockchainService.getTransactions(ledger, | |||
| sampleHash, 0, 1); | |||
| Assert.assertNull(txs); | |||
| } | |||
| /** | |||
| * 分页查询某一高度中的交易 | |||
| */ | |||
| @Test | |||
| public void getAdditionalTransactionsByHeight() { | |||
| LedgerTransaction[] txs = blockchainService.getTransactions(ledger, 0, 0, 1); | |||
| Assert.assertEquals(1, txs.length); | |||
| } | |||
| /** | |||
| * 分页查询某一区块中的交易 | |||
| */ | |||
| @Test | |||
| public void getAdditionalTransactionsByHash() { | |||
| LedgerTransaction[] txs = blockchainService.getTransactions(ledger, sampleHash, 0, 1); | |||
| Assert.assertNull(txs); | |||
| } | |||
| /** | |||
| * 根据交易hash查询交易详情 | |||
| */ | |||
| @Test | |||
| public void getTransactionByContentHash() { | |||
| LedgerTransaction tx = blockchainService.getTransactionByContentHash(ledger, sampleHash); | |||
| Assert.assertNull(tx); | |||
| } | |||
| /** | |||
| * 根据交易hash查询交易状态 | |||
| */ | |||
| @Test | |||
| public void getTransactionStateByContentHash() { | |||
| TransactionState state = blockchainService.getTransactionStateByContentHash(ledger, sampleHash); | |||
| Assert.assertNull(state); | |||
| } | |||
| /** | |||
| * 根据地址查询用户信息 | |||
| */ | |||
| @Test | |||
| public void getUser() { | |||
| UserInfo user = blockchainService.getUser(ledger, sampleAddress); | |||
| if (null != user) { | |||
| System.out.println(user.getAddress().toString()); | |||
| } | |||
| } | |||
| /** | |||
| * 根据地址查询数据账户 | |||
| */ | |||
| @Test | |||
| public void getDataAccount() { | |||
| DataAccountInfo dataAccount = blockchainService.getDataAccount(ledger, sampleAddress); | |||
| if (null != dataAccount) { | |||
| System.out.println(dataAccount.getAddress().toString()); | |||
| } | |||
| } | |||
| /** | |||
| * 根据地址和键查询KV信息(只包含最高数据版本) | |||
| */ | |||
| @Test | |||
| public void getDataEntriesByKey() { | |||
| TypedKVEntry[] kvs = blockchainService.getDataEntries(ledger, sampleAddress, sampleKey); | |||
| for (TypedKVEntry kv : kvs) { | |||
| System.out.println(kv.getKey() + ":" + kv.getVersion() + ":" + kv.getValue()); | |||
| } | |||
| } | |||
| /** | |||
| * 根据地址和指定键及数据版本查询KV信息 | |||
| */ | |||
| @Test | |||
| public void getDataEntriesWithKeyAndVersion() { | |||
| TypedKVEntry[] kvs = blockchainService.getDataEntries(ledger, sampleAddress, new KVInfoVO(new KVDataVO[]{new KVDataVO(sampleKey, new long[]{-1})})); | |||
| for (TypedKVEntry kv : kvs) { | |||
| System.out.println(kv.getKey() + ":" + kv.getVersion() + ":" + kv.getValue()); | |||
| } | |||
| } | |||
| /** | |||
| * 查询数据账户KV总数 | |||
| */ | |||
| @Test | |||
| public void getDataEntriesTotalCount() { | |||
| long count = blockchainService.getDataEntriesTotalCount(ledger, sampleAddress); | |||
| System.out.println(count); | |||
| } | |||
| /** | |||
| * 分页查询指定数据账户KV数据 | |||
| */ | |||
| @Test | |||
| public void getDataEntries() { | |||
| TypedKVEntry[] kvs = blockchainService.getDataEntries(ledger, sampleAddress, 0, 1); | |||
| for (TypedKVEntry kv : kvs) { | |||
| System.out.println(kv.getKey() + ":" + kv.getVersion() + ":" + kv.getValue()); | |||
| } | |||
| } | |||
| /** | |||
| * 查询合约信息 | |||
| */ | |||
| @Test | |||
| public void getContract() { | |||
| ContractInfo contract = blockchainService.getContract(ledger, sampleAddress); | |||
| if (null != contract) { | |||
| System.out.println(contract.getAddress().toString()); | |||
| } | |||
| } | |||
| /** | |||
| * 分页查询指定系统事件名下所有消息 | |||
| */ | |||
| @Test | |||
| public void getSystemEvents() { | |||
| Event[] events = blockchainService.getSystemEvents(ledger, sampleEvent, 0, 1); | |||
| Assert.assertTrue(null == events || events.length == 0); | |||
| } | |||
| /** | |||
| * 查询系统事件名总数 | |||
| */ | |||
| @Test | |||
| public void getSystemEventNameTotalCount() { | |||
| long count = blockchainService.getSystemEventNameTotalCount(ledger); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 分页查询系统事件名 | |||
| */ | |||
| @Test | |||
| public void getSystemEventNames() { | |||
| String[] names = blockchainService.getSystemEventNames(ledger, 0, 1); | |||
| Assert.assertEquals(0, names.length); | |||
| } | |||
| /** | |||
| * 查询指定系统事件名最新事件 | |||
| */ | |||
| @Test | |||
| public void getLatestEvent() { | |||
| Event event = blockchainService.getLatestEvent(ledger, sampleEvent); | |||
| Assert.assertNull(event); | |||
| } | |||
| /** | |||
| * 获取指定系统事件名下所有事件 | |||
| */ | |||
| @Test | |||
| public void getSystemEventsTotalCount() { | |||
| long count = blockchainService.getSystemEventsTotalCount(ledger, sampleEvent); | |||
| Assert.assertEquals(0, count); | |||
| } | |||
| /** | |||
| * 分页查询用户事件账户 | |||
| * | |||
| * @return | |||
| */ | |||
| @Test | |||
| public void getUserEventAccounts() { | |||
| BlockchainIdentity[] ids = blockchainService.getUserEventAccounts(ledger, 0, 1); | |||
| System.out.println(ids.length); | |||
| } | |||
| /** | |||
| * 获取用户事件账户 | |||
| */ | |||
| @Test | |||
| public void getUserEventAccount() { | |||
| BlockchainIdentity id = blockchainService.getUserEventAccount(ledger, sampleAddress); | |||
| if (null != id) { | |||
| System.out.println(id.getAddress().toString()); | |||
| } | |||
| } | |||
| /** | |||
| * 获取用户事件账户总数 | |||
| */ | |||
| @Test | |||
| public void getUserEventAccountTotalCount() { | |||
| long count = blockchainService.getUserEventAccountTotalCount(ledger); | |||
| System.out.println(count); | |||
| } | |||
| /** | |||
| * 获取指定用户事件账户下事件名数 | |||
| */ | |||
| @Test | |||
| public void getUserEventNameTotalCount() { | |||
| long count = blockchainService.getUserEventNameTotalCount(ledger, sampleAddress); | |||
| System.out.println(count); | |||
| } | |||
| /** | |||
| * 分页查询指定用户事件账户下事件名 | |||
| */ | |||
| @Test | |||
| public void getUserEventNames() { | |||
| String[] names = blockchainService.getUserEventNames(ledger, sampleAddress, 0, 1); | |||
| for (String name : names) { | |||
| System.out.println(name); | |||
| } | |||
| } | |||
| /** | |||
| * 获取指定用户事件账户指定事件名下最新事件 | |||
| */ | |||
| @Test | |||
| public void getLatestUserEvent() { | |||
| Event event = blockchainService.getLatestEvent(ledger, sampleAddress, sampleEvent); | |||
| if (null != event) { | |||
| BytesValue content = event.getContent(); | |||
| switch (content.getType()) { | |||
| case TEXT: | |||
| case XML: | |||
| case JSON: | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + content.getBytes().toUTF8String()); | |||
| break; | |||
| case INT64: | |||
| case TIMESTAMP: | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + BytesUtils.toLong(content.getBytes().toBytes())); | |||
| break; | |||
| default: // byte[], Bytes | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + content.getBytes().toBase58()); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 获取指定用户事件账户指定事件名下事件总数 | |||
| */ | |||
| @Test | |||
| public void getUserEventsTotalCount() { | |||
| long count = blockchainService.getUserEventsTotalCount(ledger, sampleAddress, sampleEvent); | |||
| System.out.println(count); | |||
| } | |||
| /** | |||
| * 分页查询指定用户事件账户指定事件名下事件 | |||
| */ | |||
| @Test | |||
| public void getUserEvents() { | |||
| Event[] events = blockchainService.getUserEvents(ledger, sampleAddress, sampleEvent, 0, 1); | |||
| for (Event event : events) { | |||
| BytesValue content = event.getContent(); | |||
| switch (content.getType()) { | |||
| case TEXT: | |||
| case XML: | |||
| case JSON: | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + content.getBytes().toUTF8String()); | |||
| break; | |||
| case INT64: | |||
| case TIMESTAMP: | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + BytesUtils.toLong(content.getBytes().toBytes())); | |||
| break; | |||
| default: // byte[], Bytes | |||
| System.out.println(event.getName() + ":" + event.getSequence() + ":" + content.getBytes().toBase58()); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 获取指定版本合约 | |||
| */ | |||
| @Test | |||
| public void getContractByAddressAndVersion() { | |||
| ContractInfo contract = blockchainService.getContract(ledger, sampleAddress, sampleVersion); | |||
| if (null != contract) { | |||
| System.out.println(contract.getAddress().toString()); | |||
| System.out.println(contract.getChainCodeVersion()); | |||
| System.out.println(contract.getChainCode()); | |||
| } | |||
| } | |||
| /** | |||
| * 分页查询用户 | |||
| */ | |||
| @Test | |||
| public void getUsers() { | |||
| BlockchainIdentity[] ids = blockchainService.getUsers(ledger, 0, 1); | |||
| Assert.assertEquals(1, ids.length); | |||
| } | |||
| /** | |||
| * 分页查询数据账户 | |||
| */ | |||
| @Test | |||
| public void getDataAccounts() { | |||
| BlockchainIdentity[] ids = blockchainService.getDataAccounts(ledger, 0, 1); | |||
| System.out.println(ids.length); | |||
| } | |||
| /** | |||
| * 分页查询合约账户 | |||
| */ | |||
| @Test | |||
| public void getContractAccounts() { | |||
| BlockchainIdentity[] ids = blockchainService.getContractAccounts(ledger, 0, 1); | |||
| System.out.println(ids.length); | |||
| } | |||
| /** | |||
| * 查询指定角色权限信息 | |||
| */ | |||
| @Test | |||
| public void getRolePrivileges() { | |||
| PrivilegeSet privilegeSet = blockchainService.getRolePrivileges(ledger, sampleRoleName); | |||
| if (null != privilegeSet) { | |||
| for (LedgerPermission ledgerpermission : privilegeSet.getLedgerPrivilege().getPrivilege()) { | |||
| System.out.println(ledgerpermission); | |||
| } | |||
| for (TransactionPermission transactionPermission : privilegeSet.getTransactionPrivilege().getPrivilege()) { | |||
| System.out.println(transactionPermission); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 查询指定用户权限信息 | |||
| */ | |||
| @Test | |||
| public void getUserPrivileges() { | |||
| UserPrivilegeSet userPrivileges = blockchainService.getUserPrivileges(ledger, sampleAddress); | |||
| if (null != userPrivileges) { | |||
| for (String role : userPrivileges.getUserRole()) { | |||
| System.out.println(role); | |||
| } | |||
| for (LedgerPermission ledgerpermission : userPrivileges.getLedgerPrivilegesBitset().getPrivilege()) { | |||
| System.out.println(ledgerpermission); | |||
| } | |||
| for (TransactionPermission transactionPermission : userPrivileges.getTransactionPrivilegesBitset().getPrivilege()) { | |||
| System.out.println(transactionPermission); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| 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 com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import java.util.Properties; | |||
| public class SampleBase { | |||
| // 交易签名用户 | |||
| protected static BlockchainKeypair adminKey; | |||
| // 网关IP | |||
| protected static String gatewayHost; | |||
| // 网关端口 | |||
| protected static int gatewayPort; | |||
| // 账本Hash | |||
| protected static HashDigest ledger; | |||
| // 区块链服务 | |||
| protected static BlockchainService blockchainService; | |||
| static { | |||
| try { | |||
| // 读取配置文件 | |||
| Properties properties = new Properties(); | |||
| properties.load(SampleBase.class.getClassLoader().getResourceAsStream("config.properties")); | |||
| // 初始配置交易签名用户信息 | |||
| PubKey pubKey = KeyGenUtils.decodePubKey(properties.getProperty("pubkey")); | |||
| PrivKey privKey = KeyGenUtils.decodePrivKey(properties.getProperty("privkey"), properties.getProperty("password")); | |||
| adminKey = new BlockchainKeypair(pubKey, privKey); | |||
| // 读取网关配置 | |||
| gatewayHost = properties.getProperty("gateway.host"); | |||
| gatewayPort = Integer.parseInt(properties.getProperty("gateway.port")); | |||
| // 读取账本配置 | |||
| String ledgerHash = properties.getProperty("ledger"); | |||
| // 初始化区块链服务 | |||
| blockchainService = GatewayServiceFactory.connect(gatewayHost, gatewayPort, false, adminKey).getBlockchainService(); | |||
| // 初始配置账本,从配置文件中读取,未设置获取账本列表第一个 | |||
| if (!ledgerHash.isEmpty()) { | |||
| ledger = Crypto.resolveAsHashDigest(Base58Utils.decode(ledgerHash)); | |||
| } else { | |||
| ledger = blockchainService.getLedgerHashs()[0]; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,111 @@ | |||
| package com.jdchain.samples.sdk; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.LedgerPermission; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionPermission; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import org.junit.Assert; | |||
| import org.junit.Test; | |||
| /** | |||
| * 用户账户相关操作示例: | |||
| * 用户注册,角色创建,权限设置 | |||
| */ | |||
| public class UserSample extends SampleBase { | |||
| /** | |||
| * 注册用户 | |||
| */ | |||
| @Test | |||
| public void registerUser() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成用户 | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("用户地址:" + user.getAddress()); | |||
| // 注册用户 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 创建角色 | |||
| */ | |||
| @Test | |||
| public void createRole() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 创建角色 MANAGER ,并设置可以写数据账户,能执行交易 | |||
| txTemp.security().roles().configure("MANAGER") | |||
| .enable(LedgerPermission.WRITE_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.DIRECT_OPERATION); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 配置角色权限 | |||
| */ | |||
| @Test | |||
| public void configUserRole() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 给用户设置 MANAGER 角色权限 | |||
| txTemp.security().authorziations().forUser(Bytes.fromBase58("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye")).authorize("MANAGER"); | |||
| // 交易准备 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| /** | |||
| * 注册用户的同时配置角色权限,同一事务内 | |||
| */ | |||
| @Test | |||
| public void testRegisterUserAndConfigRole() { | |||
| // 新建交易 | |||
| TransactionTemplate txTemp = blockchainService.newTransaction(ledger); | |||
| // 生成用户 | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| System.out.println("用户地址:" + user.getAddress()); | |||
| // 注册用户 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // 创建角色 MANAGER | |||
| txTemp.security().roles().configure("MANAGER") | |||
| .enable(LedgerPermission.WRITE_DATA_ACCOUNT) | |||
| .enable(TransactionPermission.DIRECT_OPERATION); | |||
| // 设置用户角色权限 | |||
| txTemp.security().authorziations().forUser(user.getAddress()).authorize("MANAGER"); | |||
| // 交易主恩贝 | |||
| PreparedTransaction ptx = txTemp.prepare(); | |||
| // 交易签名 | |||
| ptx.sign(adminKey); | |||
| // 提交交易 | |||
| TransactionResponse response = ptx.commit(); | |||
| Assert.assertTrue(response.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,165 +0,0 @@ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
| import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.contract.TransferContract; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.sdk.samples.SDKDemo_Constant; | |||
| import com.jd.blockchain.transaction.GenericValueHolder; | |||
| import com.jd.blockchain.transaction.LongValueHolder; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| public class SDKDemo_Contract_Test_ { | |||
| private BlockchainKeypair adminKey; | |||
| private HashDigest ledgerHash; | |||
| private BlockchainService blockchainService; | |||
| @Before | |||
| public void init() { | |||
| // 生成连接网关的账号 | |||
| PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], | |||
| SDKDemo_Constant.PASSWORD); | |||
| PubKey pubKey = KeyGenUtils.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); | |||
| adminKey = new BlockchainKeypair(pubKey, privKey); | |||
| // 连接网关 | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(SDKDemo_Constant.GW_IPADDR, | |||
| SDKDemo_Constant.GW_PORT, false, adminKey); | |||
| blockchainService = serviceFactory.getBlockchainService(); | |||
| HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
| ledgerHash = ledgerHashs[0]; | |||
| } | |||
| @Test | |||
| public void testContract() { | |||
| // 发布jar包 | |||
| // 定义交易; | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| byte[] contractCode = readChainCodes("transfer.jar"); | |||
| // 生成一个合约账号 | |||
| BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
| txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
| // 签名; | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(adminKey); | |||
| // 提交并等待共识返回; | |||
| TransactionResponse txResp = ptx.commit(); | |||
| System.out.println(txResp.isSuccess()); | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair dataAccount = createDataAccount(); | |||
| String dataAddress = dataAccount.getAddress().toBase58(); | |||
| Bytes contractAddress = contractDeployKey.getAddress(); | |||
| // 创建两个账号: | |||
| String account0 = "jd_zhangsan", account1 = "jd_lisi"; | |||
| long account0Money = 3000L, account1Money = 2000L; | |||
| // 创建两个账户 | |||
| // 使用KV创建一个账户 | |||
| System.out.println(create(dataAddress, account0, account0Money, false, null)); | |||
| // 使用合约创建一个账户 | |||
| System.out.println(create(dataAddress, account1, account1Money, true, contractAddress)); | |||
| // 转账,使得双方钱达到一致 | |||
| System.out.println(transfer(dataAddress, account0, account1, 500L, contractAddress)); | |||
| // 读取当前结果 | |||
| System.out.println(read(dataAddress, account0, contractAddress)); | |||
| System.out.println(read(dataAddress, account1, contractAddress)); | |||
| // 读取账号历史信息 | |||
| System.out.println(readAll(dataAddress, account0, contractAddress)); | |||
| System.out.println(readAll(dataAddress, account1, contractAddress)); | |||
| } | |||
| private String readAll(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private long read(String address, String account, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| LongValueHolder result = decode(transferContract.read(address, account)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private String transfer(String address, String from, String to, long money, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } | |||
| private BlockchainKeypair createDataAccount() { | |||
| // 首先注册一个数据账户 | |||
| BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
| commit(txTpl); | |||
| return newDataAccount; | |||
| } | |||
| private String create(String address, String account, long money, boolean useContract, Bytes contractAddress) { | |||
| TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
| if (useContract) { | |||
| // 使用合约创建 | |||
| TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
| GenericValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||
| commit(txTpl); | |||
| return result.get(); | |||
| } else { | |||
| // 通过KV创建 | |||
| txTpl.dataAccount(address).setInt64(account, money, -1); | |||
| TransactionResponse txResp = commit(txTpl); | |||
| return account + money; | |||
| } | |||
| } | |||
| private TransactionResponse commit(TransactionTemplate txTpl) { | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(adminKey); | |||
| return ptx.commit(); | |||
| } | |||
| } | |||
| @@ -1,384 +0,0 @@ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static org.junit.Assert.assertTrue; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| import com.jd.blockchain.crypto.base.DefaultCryptoEncoding; | |||
| import com.jd.blockchain.crypto.base.HashDigestBytes; | |||
| import org.junit.Before; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.core.io.ClassPathResource; | |||
| import com.jd.blockchain.contract.samples.AssetContract; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.sdk.samples.SDKDemo_Contract; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| import com.jd.blockchain.utils.io.ByteArray; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||
| /** | |||
| * 演示合约执行的过程; | |||
| * | |||
| * @author zhaogw | |||
| * 2019-05-21 11:03 | |||
| */ | |||
| public class SDK_Contract_Test { | |||
| public static Logger log = LoggerFactory.getLogger(SDKDemo_Contract.class); | |||
| public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| // 账本地址; | |||
| public static String ledgerAddress; | |||
| private PrivKey privKey; | |||
| private PubKey pubKey; | |||
| BlockchainService bcsrv; | |||
| AsymmetricKeypair signKeyPair; | |||
| HashDigest ledgerHash; | |||
| @Before | |||
| public void init(){ | |||
| ledgerAddress = "j5qHcS8jG6XwpE5wXv9HYMeGTb5Fs2gQao3TPQ3irqFpQL"; | |||
| ledgerHash = getLedgerHash(); | |||
| pubKey = SDK_GateWay_KeyPair_Para.pubKey0; | |||
| privKey = SDK_GateWay_KeyPair_Para.privkey0; | |||
| // 使用私钥进行签名; | |||
| signKeyPair = new BlockchainKeypair(pubKey, privKey); | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "localhost"; | |||
| final int GATEWAY_PORT = 11000; | |||
| NetworkAddress addr = new NetworkAddress(GATEWAY_IP,GATEWAY_PORT); | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(addr); | |||
| bcsrv = serviceFactory.getBlockchainService(); | |||
| } | |||
| // /** | |||
| // * 演示合约执行的过程; | |||
| // */ | |||
| //// @Test | |||
| // public void demoContract1() { | |||
| // String dataAddress = registerData4Contract(); | |||
| // // 发起交易; | |||
| // TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
| // String contractAddress = "LdeNg8JHFCKABJt6AaRNVCZPgY4ofGPd8MgcR"; | |||
| // AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
| //// assetContract.issue(transactionContentBody,contractAddress); | |||
| //// assetContract.issue(transactionContentBody,contractAddress,888888); | |||
| //// 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,dataAddress,321123); | |||
| //// assetContract.issue(contractBizContent,dataAddress); | |||
| // assetContract.issue(Byte.parseByte("126"),dataAddress,Bytes.fromString("100.234")); | |||
| // | |||
| // // TX 准备就绪; | |||
| // PreparedTransaction prepTx = txTemp.prepare(); | |||
| // prepTx.sign(signKeyPair); | |||
| // // 提交交易; | |||
| // TransactionResponse transactionResponse = prepTx.commit(); | |||
| // | |||
| // //check; | |||
| // KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,"total"); | |||
| // assertEquals("100",dataEntries[0].getValue().toString()); | |||
| // } | |||
| // /** | |||
| // * 演示合约执行的过程; | |||
| // */ | |||
| //// @Test | |||
| // public void demoContract2() throws IOException { | |||
| // String contractAddress = deploy(); | |||
| // String dataAddress = registerData4Contract(); | |||
| // System.out.println("dataAddress="+dataAddress); | |||
| // // 发起交易; | |||
| // TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
| // | |||
| // AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
| // ContractBizContent contractBizContent = () -> new String[]{"param1","param2"}; | |||
| // assetContract.issue(contractBizContent,dataAddress,123456); | |||
| // | |||
| // // TX 准备就绪; | |||
| // PreparedTransaction prepTx = txTemp.prepare(); | |||
| // prepTx.sign(signKeyPair); | |||
| // // 提交交易; | |||
| // TransactionResponse transactionResponse = prepTx.commit(); | |||
| // | |||
| // //check; | |||
| // assertTrue(transactionResponse.isSuccess()); | |||
| // KVDataEntry[] dataEntries = bcsrv.getDataEntries(ledgerHash,dataAddress,contractBizContent.getAttrs()[0],contractBizContent.getAttrs()[1]); | |||
| // assertEquals("value1",dataEntries[0].getValue().toString()); | |||
| // assertEquals(888,dataEntries[1].getValue()); | |||
| // } | |||
| // @Test | |||
| public void registerData(){ | |||
| // 在本地定义 TX 模板 | |||
| TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
| String key1 = "jd_key1"; | |||
| String val1 = "www.jd1.com"; | |||
| String key2 = "jd_key2"; | |||
| String val2 = "www.jd2.com"; | |||
| // 定义交易,传输最简单的数字、字符串、提取合约中的地址; | |||
| txTemp.dataAccount(dataAccount.getAddress()).setText(key1, val1, -1); | |||
| txTemp.dataAccount(dataAccount.getAddress()).setText(key2, val2, -1); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(signKeyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| //repeat; | |||
| String[] keys = {key1,key2}; | |||
| String[] values = {"www.jd1.com.v1","www.jd2.com.v1"}; | |||
| this.setDataInDataAddress(dataAccount.getAddress(),keys,values,0); | |||
| String[] values2 = {"www.jd1.com.v2","www.jd2.com.v2"}; | |||
| 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()).setInt64("total", 200, -1); | |||
| txTemp.dataAccount(dataAccount.getAddress()).setText("param1", "v", -1); | |||
| txTemp.dataAccount(dataAccount.getAddress()).setInt64("param2", 123, -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); | |||
| BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
| for(int i=0; i<keys.length; i++){ | |||
| txTemp.dataAccount(dataAddress).setText(keys[i], values[i], version); | |||
| } | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(signKeyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| } | |||
| private String deploy() throws IOException { | |||
| ClassPathResource classPathResource = new ClassPathResource("contract.jar"); | |||
| byte[] chainCode = this.getChainCode(classPathResource.getURL().getPath()); | |||
| TransactionTemplate txTpl = this.bcsrv.newTransaction(ledgerHash); | |||
| BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity(); | |||
| txTpl.contracts().deploy(contractIdentity, chainCode); | |||
| PreparedTransaction ptx = txTpl.prepare(); | |||
| ptx.sign(signKeyPair); | |||
| TransactionResponse txResp = ptx.commit(); | |||
| System.out.println("contract's address=" + contractIdentity.getAddress()); | |||
| String contractAddr = contractIdentity.getAddress().toBase58(); | |||
| log.info("contractAddr="+contractAddr); | |||
| return contractAddr; | |||
| } | |||
| public byte[] getChainCode(String path) { | |||
| byte[] chainCode = null; | |||
| File file = null; | |||
| FileInputStream input = null; | |||
| try { | |||
| file = new File(path); | |||
| input = new FileInputStream(file); | |||
| chainCode = new byte[input.available()]; | |||
| input.read(chainCode); | |||
| } catch (IOException var14) { | |||
| var14.printStackTrace(); | |||
| } finally { | |||
| try { | |||
| if (input != null) { | |||
| input.close(); | |||
| } | |||
| } catch (IOException var13) { | |||
| var13.printStackTrace(); | |||
| } | |||
| } | |||
| return chainCode; | |||
| } | |||
| /** | |||
| * 演示合约执行的过程; | |||
| */ | |||
| public static void demoContract() { | |||
| // 账本地址; | |||
| String ledgerAddress = "j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7"; | |||
| // 节点地址列表; | |||
| // NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
| // new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
| // new NetworkAddress("192.168.10.13", 8080) }; | |||
| // 创建服务代理; | |||
| final String GATEWAY_IP = "localhost"; | |||
| final int GATEWAY_PORT = 11000; | |||
| final boolean SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| BlockchainService service = serviceFactory.getBlockchainService(); | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 发起交易; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 一个贸易账户,贸易结算后的利润将通过一个合约账户来执行利润分配; | |||
| // 合约账户被设置为通用的账户,不具备对贸易结算账户的直接权限; | |||
| // 只有当前交易发起人具备对贸易账户的直接权限,当交易发起人对交易进行签名之后,权限被间接传递给合约账户; | |||
| String commerceAccount = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 处理利润分成的通用业务逻辑的合约账户; | |||
| String profitDistributionContract = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 收益人账户; | |||
| String receiptorAccount1 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| String receiptorAccount2 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
| // 资产编码; | |||
| String assetKey = "RMB-ASSET"; | |||
| // 此次待分配利润; | |||
| long profit = 1000000; | |||
| // 备注信息; | |||
| Remark remark = new Remark(); | |||
| String remarkJSON = JSONSerializeUtils.serializeToJSON(remark); | |||
| AssetContract assetContract = txTemp.contract(profitDistributionContract, AssetContract.class); | |||
| assetContract.issue(1000, receiptorAccount1); | |||
| assetContract.transfer(receiptorAccount1, receiptorAccount2, 600); | |||
| // assetContract. | |||
| // -------------------------------------- | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| String txHash = ByteArray.toBase64(prepTx.getTransactionHash().toBytes()); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| prepTx.commit(); | |||
| } | |||
| private static HashDigest getLedgerHash() { | |||
| return new HashDigestBytes(DefaultCryptoEncoding.decodeAlgorithm(Base58Utils.decode(ledgerAddress)), Base58Utils.decode(ledgerAddress)); | |||
| } | |||
| /** | |||
| * 交易发起人的私钥;<br> | |||
| * | |||
| * 注:私钥由调用方在本地保管和使用; | |||
| * | |||
| * @return | |||
| */ | |||
| private static AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| /** | |||
| * 商品信息; | |||
| * | |||
| * @author huanghaiquan | |||
| * | |||
| */ | |||
| public static class Remark { | |||
| private String code; | |||
| private String name; | |||
| private String venderAddress; | |||
| public String getCode() { | |||
| return code; | |||
| } | |||
| public void setCode(String code) { | |||
| this.code = code; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public String getVenderAddress() { | |||
| return venderAddress; | |||
| } | |||
| public void setVenderAddress(String venderAddress) { | |||
| this.venderAddress = venderAddress; | |||
| } | |||
| } | |||
| // @Test | |||
| // public void testStringArr(){ | |||
| // ContractBizContent contractBizContent = () -> new String[]{"1","2","you are welcome!"}; | |||
| // byte[] bizBytes = BinaryProtocol.encode(contractBizContent,ContractBizContent.class); | |||
| // ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class); | |||
| // assertArrayEquals(contractBizContent.getAttrs(),actualObj.getAttrs()); | |||
| // } | |||
| // @Test | |||
| // public void testContractArgs(){ | |||
| // ContractBizContent contractBizContent = () -> new String[]{"param1"}; | |||
| // Method method = ReflectionUtils.findMethod(AssetContract2.class,"issue",ContractBizContent.class,String.class); | |||
| // ContractArgs contractArgs = new ContractArgs() { | |||
| // @Override | |||
| // public Method getMethod() { | |||
| // return method; | |||
| // } | |||
| // | |||
| // @Override | |||
| // public Object[] getArgs() { | |||
| // return new Object[]{contractBizContent,"hello"}; | |||
| // } | |||
| // }; | |||
| // | |||
| // //add the annotation; | |||
| // | |||
| // } | |||
| } | |||
| @@ -1,138 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/9/4 上午11:06 | |||
| * Description: 插入数据测试 | |||
| */ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static org.junit.Assert.assertEquals; | |||
| import com.jd.blockchain.crypto.base.DefaultCryptoEncoding; | |||
| import com.jd.blockchain.crypto.base.HashDigestBytes; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.HashFunction; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.TxResponseMessage; | |||
| import com.jd.blockchain.utils.codec.Base58Utils; | |||
| /** | |||
| * 插入数据测试 | |||
| * @author shaozhuguang | |||
| * @create 2018/9/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_BatchInsertData_Test_ { | |||
| String ledgerHash = ""; | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainTransactionService service; | |||
| @Before | |||
| public void init() { | |||
| CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 8000; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| } | |||
| @Test | |||
| public void batchInsertData_Test() { | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 将商品信息写入到指定的账户中; | |||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
| String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| String key1 = "jd_key1"; | |||
| String val1 = "www.jd.com"; | |||
| String key2 = "jd_key2"; | |||
| String val2 = "www.jd.com"; | |||
| txTemp.dataAccount(dataAccount).setText(key1, val1, -1); | |||
| txTemp.dataAccount(dataAccount).setText(key2, val2, -1); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| // 期望返回结果 | |||
| TransactionResponse expectResp = initResponse(); | |||
| System.out.println("---------- assert start ----------"); | |||
| assertEquals(expectResp.isSuccess(), transactionResponse.isSuccess()); | |||
| assertEquals(expectResp.getExecutionState(), transactionResponse.getExecutionState()); | |||
| assertEquals(expectResp.getContentHash(), transactionResponse.getContentHash()); | |||
| assertEquals(expectResp.getBlockHeight(), transactionResponse.getBlockHeight()); | |||
| assertEquals(expectResp.getBlockHash(), transactionResponse.getBlockHash()); | |||
| System.out.println("---------- assert OK ----------"); | |||
| } | |||
| private HashDigest getLedgerHash() { | |||
| return new HashDigestBytes(DefaultCryptoEncoding.decodeAlgorithm(Base58Utils.decode(ledgerHash)), Base58Utils.decode(ledgerHash)); | |||
| } | |||
| private AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| private TransactionResponse initResponse() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256");; | |||
| HashDigest contentHash = hashFunc.hash("contentHash".getBytes()); | |||
| HashDigest blockHash = hashFunc.hash("blockHash".getBytes()); | |||
| long blockHeight = 9998L; | |||
| TxResponseMessage resp = new TxResponseMessage(contentHash); | |||
| resp.setBlockHash(blockHash); | |||
| resp.setBlockHeight(blockHeight); | |||
| resp.setExecutionState(TransactionState.SUCCESS); | |||
| return resp; | |||
| } | |||
| } | |||
| @@ -1,131 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/9/4 上午11:06 | |||
| * Description: 插入数据测试 | |||
| */ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.HashFunction; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.TxResponseMessage; | |||
| /** | |||
| * 插入数据测试 | |||
| * @author shaozhuguang | |||
| * @create 2018/9/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_DataAccount_Test_ { | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainService service; | |||
| @Before | |||
| public void init() { | |||
| CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 8081; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| } | |||
| @Test | |||
| public void registerDataAccount_Test() { | |||
| // HashDigest ledgerHash = getLedgerHash(); | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| // SignatureFunction signatureFunction = getSignatureFunction(); | |||
| // | |||
| // CryptoKeyPair cryptoKeyPair = signatureFunction.generateKeyPair(); | |||
| //existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey1, SDK_GateWay_KeyPair_Para.privkey1); | |||
| BlockchainKeypair dataAcount = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.dataAccounts().register(dataAcount.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| // // 期望返回结果 | |||
| // TransactionResponse expectResp = initResponse(); | |||
| // | |||
| // System.out.println("---------- assert start ----------"); | |||
| // assertEquals(expectResp.isSuccess(), transactionResponse.isSuccess()); | |||
| // assertEquals(expectResp.getExecutionState(), transactionResponse.getExecutionState()); | |||
| // assertEquals(expectResp.getContentHash(), transactionResponse.getContentHash()); | |||
| // assertEquals(expectResp.getBlockHeight(), transactionResponse.getBlockHeight()); | |||
| // assertEquals(expectResp.getBlockHash(), transactionResponse.getBlockHash()); | |||
| // System.out.println("---------- assert OK ----------"); | |||
| } | |||
| private HashDigest getLedgerHash() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256");; | |||
| HashDigest ledgerHash =hashFunc.hash("jd-gateway".getBytes()); | |||
| return ledgerHash; | |||
| } | |||
| private SignatureFunction getSignatureFunction() { | |||
| return Crypto.getSignatureFunction("ED25519"); | |||
| } | |||
| private AsymmetricKeypair getSponsorKey() { | |||
| return getSignatureFunction().generateKeypair(); | |||
| } | |||
| private TransactionResponse initResponse() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256");; | |||
| HashDigest contentHash = hashFunc.hash("contentHash".getBytes()); | |||
| HashDigest blockHash = hashFunc.hash("blockHash".getBytes()); | |||
| long blockHeight = 9998L; | |||
| TxResponseMessage resp = new TxResponseMessage(contentHash); | |||
| resp.setBlockHash(blockHash); | |||
| resp.setBlockHeight(blockHeight); | |||
| resp.setExecutionState(TransactionState.SUCCESS); | |||
| return resp; | |||
| } | |||
| } | |||
| @@ -1,131 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/9/4 上午11:06 | |||
| * Description: 插入数据测试 | |||
| */ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.HashFunction; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.TxResponseMessage; | |||
| /** | |||
| * 插入数据测试 | |||
| * @author shaozhuguang | |||
| * @create 2018/9/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_InsertData_Test_ { | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainTransactionService service; | |||
| @Before | |||
| public void init() { | |||
| CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 8000; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| } | |||
| @Test | |||
| public void insertData_Test() { | |||
| HashDigest ledgerHash = getLedgerHash(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
| // -------------------------------------- | |||
| // 将商品信息写入到指定的账户中; | |||
| // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
| String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| String dataKey = "jd_code"; | |||
| String dataVal = "www.jd.com"; | |||
| txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| AsymmetricKeypair keyPair = getSponsorKey(); | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| // 期望返回结果 | |||
| TransactionResponse expectResp = initResponse(); | |||
| System.out.println("---------- assert start ----------"); | |||
| assertEquals(expectResp.isSuccess(), transactionResponse.isSuccess()); | |||
| assertEquals(expectResp.getExecutionState(), transactionResponse.getExecutionState()); | |||
| assertEquals(expectResp.getContentHash(), transactionResponse.getContentHash()); | |||
| assertEquals(expectResp.getBlockHeight(), transactionResponse.getBlockHeight()); | |||
| assertEquals(expectResp.getBlockHash(), transactionResponse.getBlockHash()); | |||
| System.out.println("---------- assert OK ----------"); | |||
| } | |||
| private HashDigest getLedgerHash() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256"); | |||
| HashDigest ledgerHash = hashFunc.hash("jd-gateway".getBytes()); | |||
| return ledgerHash; | |||
| } | |||
| private AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| private TransactionResponse initResponse() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256"); | |||
| HashDigest contentHash = hashFunc.hash("contentHash".getBytes()); | |||
| HashDigest blockHash = hashFunc.hash("blockHash".getBytes()); | |||
| long blockHeight = 9998L; | |||
| TxResponseMessage resp = new TxResponseMessage(contentHash); | |||
| resp.setBlockHash(blockHash); | |||
| resp.setBlockHeight(blockHeight); | |||
| resp.setExecutionState(TransactionState.SUCCESS); | |||
| return resp; | |||
| } | |||
| } | |||
| @@ -1,34 +0,0 @@ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| /** | |||
| * Created by zhangshuang3 on 2018/10/17. | |||
| */ | |||
| public class SDK_GateWay_KeyPair_Para { | |||
| public static final String PASSWORD = "abc"; | |||
| public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||
| "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
| "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
| "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; | |||
| public static final String[] PRIV_KEYS = { | |||
| "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||
| "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
| "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
| "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||
| public static PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); | |||
| public static PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); | |||
| public static PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); | |||
| public static PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); | |||
| public static PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); | |||
| public static PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); | |||
| public static PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); | |||
| public static PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); | |||
| } | |||
| @@ -1,100 +0,0 @@ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static org.junit.Assert.assertTrue; | |||
| import com.jd.blockchain.ledger.*; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AddressEncoding; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.KeyGenUtils; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.sdk.samples.SDKDemo_Constant; | |||
| import com.jd.blockchain.utils.net.NetworkAddress; | |||
| /** | |||
| * 注册参与方测试 | |||
| * @author zhangshuang | |||
| * @create 2019/7/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_Participant_Regist_Test_ { | |||
| private PrivKey privKey; | |||
| private PubKey pubKey; | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainService service; | |||
| //根据密码工具产生的公私钥 | |||
| static String PUB = "3snPdw7i7PkdgqiGX7GbZuFSi1cwZn7vtjw4vifb1YoXgr9k6Kfmis"; | |||
| String PRIV = "177gjtZu8w1phqHFVNiFhA35cfimXmP6VuqrBFhfbXBWK8s4TRwro2tnpffwP1Emwr6SMN6"; | |||
| @Before | |||
| public void init() { | |||
| privKey = SDK_GateWay_KeyPair_Para.privkey1; | |||
| pubKey = SDK_GateWay_KeyPair_Para.pubKey1; | |||
| CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 11000; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| DataContractRegistry.register(ParticipantRegisterOperation.class); | |||
| DataContractRegistry.register(ParticipantStateUpdateOperation.class); | |||
| DataContractRegistry.register(ConsensusSettingsUpdateOperation.class); | |||
| } | |||
| @Test | |||
| public void registerParticipant_Test() { | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| //existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
| PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); | |||
| PubKey pubKey = KeyGenUtils.decodePubKey(PUB); | |||
| System.out.println("Address = "+AddressEncoding.generateAddress(pubKey)); | |||
| BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); | |||
| // 注册参与方 | |||
| txTemp.participants().register("Peer4", user.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| } | |||
| } | |||
| @@ -1,184 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/9/4 上午11:06 | |||
| * Description: 插入数据测试 | |||
| */ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.HashFunction; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainIdentity; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.DigitalSignature; | |||
| import com.jd.blockchain.ledger.LedgerBlock; | |||
| import com.jd.blockchain.ledger.LedgerInfo; | |||
| import com.jd.blockchain.ledger.LedgerTransaction; | |||
| import com.jd.blockchain.ledger.ParticipantNode; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TypedKVEntry; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.TxResponseMessage; | |||
| /** | |||
| * 插入数据测试 | |||
| * | |||
| * @author shaozhuguang | |||
| * @create 2018/9/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_Query_Test_ { | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainService service; | |||
| @Before | |||
| public void init() { | |||
| CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 11000; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| } | |||
| @Test | |||
| public void query_Test() { | |||
| HashDigest ledgerHash = service.getLedgerHashs()[0]; | |||
| ; | |||
| // ParserConfig.global.setAutoTypeSupport(true); | |||
| LedgerInfo ledgerInfo = service.getLedger(ledgerHash); | |||
| long ledgerNumber = ledgerInfo.getLatestBlockHeight(); | |||
| System.out.println(ledgerNumber); | |||
| HashDigest hashDigest = ledgerInfo.getHash(); | |||
| System.out.println(hashDigest); | |||
| // 最新区块; | |||
| LedgerBlock latestBlock = service.getBlock(ledgerHash, ledgerNumber); | |||
| System.out.println("latestBlock.Hash=" + latestBlock.getHash()); | |||
| long count = service.getContractCount(ledgerHash, 3L); | |||
| System.out.println("contractCount=" + count); | |||
| count = service.getContractCount(ledgerHash, hashDigest); | |||
| System.out.println("contractCount=" + count); | |||
| BlockchainIdentity contract = service.getContract(ledgerHash, "12345678"); | |||
| System.out.println(contract); | |||
| LedgerBlock block = service.getBlock(ledgerHash, hashDigest); | |||
| System.out.println("block.Hash=" + block.getHash()); | |||
| count = service.getDataAccountCount(ledgerHash, 123456); | |||
| System.out.println("dataAccountCount=" + count); | |||
| count = service.getDataAccountCount(ledgerHash, hashDigest); | |||
| System.out.println("dataAccountCount=" + count); | |||
| BlockchainIdentity dataAccount = service.getDataAccount(ledgerHash, "1245633"); | |||
| System.out.println(dataAccount.getAddress()); | |||
| count = service.getTransactionCount(ledgerHash, hashDigest); | |||
| System.out.println("transactionCount=" + count); | |||
| count = service.getTransactionCount(ledgerHash, 12456); | |||
| System.out.println("transactionCount=" + count); | |||
| LedgerTransaction[] txList = service.getTransactions(ledgerHash, ledgerNumber, 0, 100); | |||
| for (LedgerTransaction ledgerTransaction : txList) { | |||
| System.out.println("ledgerTransaction.Hash=" + ledgerTransaction.getRequest().getTransactionHash()); | |||
| } | |||
| txList = service.getTransactions(ledgerHash, hashDigest, 0, 100); | |||
| for (LedgerTransaction ledgerTransaction : txList) { | |||
| System.out.println("ledgerTransaction.Hash=" + ledgerTransaction.getRequest().getTransactionHash()); | |||
| } | |||
| LedgerTransaction tx = service.getTransactionByContentHash(ledgerHash, hashDigest); | |||
| DigitalSignature[] signatures = tx.getRequest().getEndpointSignatures(); | |||
| for (DigitalSignature signature : signatures) { | |||
| System.out.println(signature.getDigest().getAlgorithm()); | |||
| } | |||
| System.out.println("transaction.blockHeight=" + tx.getResult().getBlockHeight()); | |||
| System.out.println("transaction.executionState=" + tx.getResult().getExecutionState()); | |||
| ParticipantNode[] participants = service.getConsensusParticipants(ledgerHash); | |||
| for (ParticipantNode participant : participants) { | |||
| System.out.println("participant.name=" + participant.getName()); | |||
| // System.out.println(participant.getConsensusAddress()); | |||
| // System.out.println("participant.host=" + | |||
| // participant.getConsensusAddress().getHost()); | |||
| System.out.println("participant.getPubKey=" + participant.getPubKey()); | |||
| System.out.println("participant.getKeyType=" + participant.getPubKey().getKeyType()); | |||
| System.out.println("participant.getRawKeyBytes=" + participant.getPubKey().getRawKeyBytes()); | |||
| System.out.println("participant.algorithm=" + participant.getPubKey().getAlgorithm()); | |||
| } | |||
| String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
| String[] objKeys = new String[] { "x001", "x002" }; | |||
| TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys); | |||
| for (TypedKVEntry kvDatum : kvData) { | |||
| System.out.println("kvData.key=" + kvDatum.getKey()); | |||
| System.out.println("kvData.version=" + kvDatum.getVersion()); | |||
| System.out.println("kvData.value=" + kvDatum.getValue()); | |||
| } | |||
| HashDigest[] hashs = service.getLedgerHashs(); | |||
| for (HashDigest hash : hashs) { | |||
| System.out.println("hash.toBase58=" + hash.toBase58()); | |||
| } | |||
| } | |||
| private HashDigest getLedgerHash() { | |||
| HashDigest ledgerHash = Crypto.getHashFunction("SHA256").hash("jd-gateway".getBytes()); | |||
| return ledgerHash; | |||
| } | |||
| private SignatureFunction getSignatureFunction() { | |||
| return Crypto.getSignatureFunction("ED25519"); | |||
| } | |||
| private BlockchainKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = getSignatureFunction(); | |||
| AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||
| BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), | |||
| cryptoKeyPair.getPrivKey()); | |||
| return blockchainKeyPair; | |||
| } | |||
| private TransactionResponse initResponse() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256"); | |||
| HashDigest contentHash = hashFunc.hash("contentHash".getBytes()); | |||
| HashDigest blockHash = hashFunc.hash("blockHash".getBytes()); | |||
| long blockHeight = 9998L; | |||
| TxResponseMessage resp = new TxResponseMessage(contentHash); | |||
| resp.setBlockHash(blockHash); | |||
| resp.setBlockHeight(blockHeight); | |||
| resp.setExecutionState(TransactionState.SUCCESS); | |||
| return resp; | |||
| } | |||
| } | |||
| @@ -1,151 +0,0 @@ | |||
| /** | |||
| * Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
| * FileName: test.com.jd.blockchain.sdk.test.SDK_GateWay_InsertData_Test | |||
| * Author: shaozhuguang | |||
| * Department: 区块链研发部 | |||
| * Date: 2018/9/4 上午11:06 | |||
| * Description: 插入数据测试 | |||
| */ | |||
| package test.com.jd.blockchain.sdk.test; | |||
| import static org.junit.Assert.assertTrue; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
| import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
| import com.jd.blockchain.crypto.Crypto; | |||
| import com.jd.blockchain.crypto.HashDigest; | |||
| import com.jd.blockchain.crypto.HashFunction; | |||
| import com.jd.blockchain.crypto.PrivKey; | |||
| import com.jd.blockchain.crypto.PubKey; | |||
| import com.jd.blockchain.crypto.SignatureFunction; | |||
| import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
| import com.jd.blockchain.ledger.BlockchainKeypair; | |||
| import com.jd.blockchain.ledger.PreparedTransaction; | |||
| import com.jd.blockchain.ledger.TransactionContent; | |||
| import com.jd.blockchain.ledger.TransactionRequest; | |||
| import com.jd.blockchain.ledger.TransactionResponse; | |||
| import com.jd.blockchain.ledger.TransactionState; | |||
| import com.jd.blockchain.ledger.TransactionTemplate; | |||
| import com.jd.blockchain.sdk.BlockchainService; | |||
| import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
| import com.jd.blockchain.transaction.TxResponseMessage; | |||
| /** | |||
| * 插入数据测试 | |||
| * @author shaozhuguang | |||
| * @create 2018/9/4 | |||
| * @since 1.0.0 | |||
| */ | |||
| public class SDK_GateWay_User_Test_ { | |||
| // public static final String PASSWORD = SDK_GateWay_KeyPair_Para.PASSWORD; | |||
| // | |||
| // public static final String[] PUB_KEYS = SDK_GateWay_KeyPair_Para.PUB_KEYS; | |||
| // | |||
| // public static final String[] PRIV_KEYS = SDK_GateWay_KeyPair_Para.PRIV_KEYS; | |||
| private PrivKey privKey; | |||
| private PubKey pubKey; | |||
| private BlockchainKeypair CLIENT_CERT = null; | |||
| private String GATEWAY_IPADDR = null; | |||
| private int GATEWAY_PORT; | |||
| private boolean SECURE; | |||
| private BlockchainService service; | |||
| @Before | |||
| public void init() { | |||
| // PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); | |||
| // PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); | |||
| // PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); | |||
| // PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); | |||
| // | |||
| // PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); | |||
| // PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); | |||
| // PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); | |||
| // PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); | |||
| privKey = SDK_GateWay_KeyPair_Para.privkey1; | |||
| pubKey = SDK_GateWay_KeyPair_Para.pubKey1; | |||
| CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); | |||
| GATEWAY_IPADDR = "127.0.0.1"; | |||
| GATEWAY_PORT = 10300; | |||
| SECURE = false; | |||
| GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
| CLIENT_CERT); | |||
| service = serviceFactory.getBlockchainService(); | |||
| DataContractRegistry.register(TransactionContent.class); | |||
| DataContractRegistry.register(TransactionRequest.class); | |||
| DataContractRegistry.register(TransactionResponse.class); | |||
| } | |||
| @Test | |||
| public void registerUser_Test() { | |||
| HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
| // 在本地定义注册账号的 TX; | |||
| TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
| //existed signer | |||
| AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
| BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
| // 注册 | |||
| txTemp.users().register(user.getIdentity()); | |||
| // TX 准备就绪; | |||
| PreparedTransaction prepTx = txTemp.prepare(); | |||
| // 使用私钥进行签名; | |||
| prepTx.sign(keyPair); | |||
| // 提交交易; | |||
| TransactionResponse transactionResponse = prepTx.commit(); | |||
| assertTrue(transactionResponse.isSuccess()); | |||
| // 期望返回结果 | |||
| // TransactionResponse expectResp = initResponse(); | |||
| // | |||
| // System.out.println("---------- assert start ----------"); | |||
| // assertEquals(expectResp.isSuccess(), transactionResponse.isSuccess()); | |||
| // assertEquals(expectResp.getExecutionState(), transactionResponse.getExecutionState()); | |||
| // assertEquals(expectResp.getContentHash(), transactionResponse.getContentHash()); | |||
| // assertEquals(expectResp.getBlockHeight(), transactionResponse.getBlockHeight()); | |||
| // assertEquals(expectResp.getBlockHash(), transactionResponse.getBlockHash()); | |||
| // System.out.println("---------- assert OK ----------"); | |||
| } | |||
| // private HashDigest getLedgerHash() { | |||
| // byte[] hashBytes = Base58Utils.decode(ledgerHashBase58); | |||
| // return new HashDigest(hashBytes); | |||
| // } | |||
| private AsymmetricKeypair getSponsorKey() { | |||
| SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
| return signatureFunction.generateKeypair(); | |||
| } | |||
| private TransactionResponse initResponse() { | |||
| HashFunction hashFunc = Crypto.getHashFunction("SHA256");; | |||
| HashDigest contentHash = hashFunc.hash("contentHash".getBytes()); | |||
| HashDigest blockHash = hashFunc.hash("blockHash".getBytes()); | |||
| long blockHeight = 9998L; | |||
| TxResponseMessage resp = new TxResponseMessage(contentHash); | |||
| resp.setBlockHash(blockHash); | |||
| resp.setBlockHeight(blockHeight); | |||
| resp.setExecutionState(TransactionState.SUCCESS); | |||
| return resp; | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| #ledger info; | |||
| ownerPubPath=F:\\jdsk\\jdsk-files\\github\\jdchain-starter\\conf\\jd-com.pub | |||
| ownerPrvPath=F:\\jdsk\\jdsk-files\\github\\jdchain-starter\\conf\\jd-com.priv | |||
| ownerPassword=F:\\jdsk\\jdsk-files\\github\\jdchain-starter\\conf\\jd-com.pwd | |||
| ledgerHash=j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7 | |||
| host=localhost | |||
| port=11000 | |||
| #execute contract; | |||
| event = issue-asset | |||
| chainCodePath=F:\\jdsk\\jdsk-files\\github\\jdchain-starter\\contract-compile\\target\\contract.jar | |||
| contractArgs=1000##fromAddr##LdeNvLeq6MB6y8CoyawYxgCCYCJkrp5xoVGUw | |||
| #contractArgs=fromAddr##toAddr##30##LdeNvLeq6MB6y8CoyawYxgCCYCJkrp5xoVGUw | |||