├── .ci
├── ci_check.sh
└── ci_check_commit.sh
├── .codecov.yml
├── .github
└── workflows
│ ├── ci_check.yml
│ └── publish_binaries.yml
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── Changelog.md
├── LICENSE
├── README.md
├── build.gradle
├── docs
└── images
│ └── menu_logo_wecross.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── release_note.txt
├── scripts
└── start.sh
├── settings.gradle
└── src
├── main
├── java
│ └── com
│ │ └── webank
│ │ └── wecross
│ │ └── console
│ │ ├── Initializer.java
│ │ ├── Shell.java
│ │ ├── common
│ │ ├── ConsoleUtils.java
│ │ ├── FileUtils.java
│ │ ├── Hash.java
│ │ ├── HelpInfo.java
│ │ ├── IgnoreCaseCompleter.java
│ │ ├── JlineUtils.java
│ │ ├── PrintUtils.java
│ │ ├── TarUtils.java
│ │ ├── TransactionInfo.java
│ │ ├── Version.java
│ │ └── WelcomeInfo.java
│ │ ├── custom
│ │ ├── BCOSCommand.java
│ │ └── FabricCommand.java
│ │ ├── exception
│ │ ├── ErrorCode.java
│ │ └── WeCrossConsoleException.java
│ │ ├── mock
│ │ ├── MockResource.java
│ │ └── MockWeCross.java
│ │ ├── routine
│ │ ├── HTLCFace.java
│ │ ├── HTLCImpl.java
│ │ ├── XAFace.java
│ │ └── XAImpl.java
│ │ └── rpc
│ │ ├── RPCFace.java
│ │ └── RPCImpl.java
└── resources
│ ├── application-sample.toml
│ ├── application.toml
│ ├── contracts
│ ├── chaincode
│ │ ├── asset
│ │ │ └── assetSample.go
│ │ ├── evidence
│ │ │ ├── evidenceSample.go
│ │ │ └── policy.yaml
│ │ ├── helloworld
│ │ │ └── helloworld.go
│ │ ├── htlc
│ │ │ ├── htlc.go
│ │ │ └── htlc_sample.go
│ │ ├── interchain
│ │ │ └── interchainSample.go
│ │ ├── ledger
│ │ │ └── ledger_sample.go
│ │ └── sacc
│ │ │ ├── policy.yaml
│ │ │ └── sacc.go
│ ├── liquid
│ │ └── hello_world
│ │ │ ├── .gitignore
│ │ │ ├── .liquid
│ │ │ └── abi_gen
│ │ │ │ ├── Cargo.toml
│ │ │ │ └── main.rs
│ │ │ ├── Cargo.toml
│ │ │ ├── hello_world.abi
│ │ │ ├── hello_world.wasm
│ │ │ ├── hello_world_gm.wasm
│ │ │ └── src
│ │ │ └── lib.rs
│ └── solidity
│ │ ├── AssetSample.sol
│ │ ├── EvidenceSample.sol
│ │ ├── HTLC.sol
│ │ ├── HelloWeCross.sol
│ │ ├── HelloWorld.sol
│ │ ├── InterchainGetBlockSample.sol
│ │ ├── InterchainSample.sol
│ │ ├── LedgerSample.sol
│ │ ├── LedgerSampleHTLC.sol
│ │ ├── Sacc.sol
│ │ └── WeCrossHub.sol
│ └── log4j2.xml
└── test
├── java
└── com
│ └── webank
│ └── wecross
│ └── console
│ ├── ConsoleUtilsTest.java
│ ├── FileUtilsTest.java
│ └── TarUtilsTest.java
└── resources
├── ContractTypeTest.sol
└── TupleTest.sol
/.ci/ci_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cp -r src/main/resources/contracts src/test/resources/
4 |
5 | set -e
6 |
7 | ./gradlew verifyGoogleJavaFormat
8 | ./gradlew build
9 | ./gradlew test
10 | ./gradlew jacocoTestReport
11 |
--------------------------------------------------------------------------------
/.ci/ci_check_commit.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | scan_code_script="cobra/cobra.py -f json -o /tmp/report.json -t "
6 | ignore_files=(application-sample.yml application.yml HelpInfo.java)
7 |
8 | LOG_ERROR() {
9 | content=${1}
10 | echo -e "\033[31m${content}\033[0m"
11 | }
12 |
13 | LOG_INFO() {
14 | content=${1}
15 | echo -e "\033[32m${content}\033[0m"
16 | }
17 |
18 | should_ignore() {
19 | local file=${1}
20 | for ignore in ${ignore_files[*]}; do
21 | if echo ${file} | grep ${ignore} &>/dev/null; then
22 | echo "ignore ${file} ${ignore}"
23 | return 0
24 | fi
25 | done
26 | return 1
27 | }
28 |
29 | scan_code() {
30 | # Redirect output to stderr.
31 | exec 1>&2
32 | for file in $(git diff-index --name-status HEAD^ | awk '{print $2}'); do
33 | if should_ignore ${file}; then continue; fi
34 | if [ ! -f ${file} ]; then continue; fi
35 | LOG_INFO "check file ${file}"
36 | python ${scan_code_script} $file
37 | trigger_rules=$(jq -r '.' /tmp/report.json | grep 'trigger_rules' | awk '{print $2}' | sed 's/,//g')
38 | echo "trigger_rules is ${trigger_rules}"
39 | rm /tmp/report.json
40 | if [ ${trigger_rules} -ne 0 ]; then
41 | echo "######### ERROR: Scan code failed, please adjust them before commit"
42 | exit 1
43 | fi
44 | done
45 | }
46 |
47 | install_cobra() {
48 | git clone https://github.com/WhaleShark-Team/cobra.git
49 | pip install -r cobra/requirements.txt
50 | cp cobra/config.template cobra/config
51 | }
52 |
53 | install_cobra
54 | scan_code
55 |
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project:
4 | default:
5 | target: 30%
6 | threshold: null
7 | if_not_found: success
8 | patch:
9 | default:
10 | enabled: no
11 | if_not_found: success
12 | changes:
13 | default:
14 | enabled: no
15 | if_not_found: success
16 |
--------------------------------------------------------------------------------
/.github/workflows/ci_check.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Gradle
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
3 |
4 | name: ci check
5 |
6 | on: pull_request
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 | - name: Set up JDK 1.8
15 | uses: actions/setup-java@v1
16 | with:
17 | java-version: 1.8
18 | - name: run ci_check.sh
19 | run: bash .ci/ci_check.sh
20 | - name: upload coverage
21 | run: bash <(curl -s https://codecov.io/bash)
22 |
--------------------------------------------------------------------------------
/.github/workflows/publish_binaries.yml:
--------------------------------------------------------------------------------
1 | name: Publish binaries
2 |
3 | on:
4 | release:
5 | types: [prereleased]
6 |
7 | jobs:
8 | build:
9 | name: Publish binaries
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v1
14 | - name: Set up JDK 1.8
15 | uses: actions/setup-java@v1
16 | with:
17 | java-version: 1.8
18 | - name: Build with Gradle
19 | run: ./gradlew assemble
20 | - name: Download scripts
21 | run: mkdir -p dist/conf/accounts && cd dist/conf/accounts && curl -LO https://raw.githubusercontent.com/FISCO-BCOS/console/master/tools/get_account.sh && curl -LO https://raw.githubusercontent.com/FISCO-BCOS/console/master/tools/get_gm_account.sh && chmod +x *.sh && cd -
22 | - name: Pack
23 | run: chmod +x dist/*.sh && mv dist WeCross-Console && tar -zcvf WeCross-Console.tar.gz WeCross-Console
24 | - name: Checksum
25 | run: md5sum WeCross-Console.tar.gz > WeCross-Console.tar.gz.md5
26 | - name: Upload binaries to release
27 | uses: svenstaro/upload-release-action@v1-release
28 | with:
29 | repo_token: ${{ secrets.GITHUB_TOKEN }}
30 | file: WeCross-Console.tar.gz
31 | asset_name: WeCross-Console.tar.gz
32 | tag: ${{ github.ref }}
33 | overwrite: true
34 |
35 | - name: Upload checksum to release
36 | uses: svenstaro/upload-release-action@v1-release
37 | with:
38 | repo_token: ${{ secrets.GITHUB_TOKEN }}
39 | file: WeCross-Console.tar.gz.md5
40 | asset_name: WeCross-Console.tar.gz.md5
41 | tag: ${{ github.ref }}
42 | overwrite: true
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Java template
3 | *.class
4 |
5 | # Package Files #
6 | *.war
7 | *.ear
8 | *.bin
9 | *.abi
10 |
11 | ### Gradle template
12 | .gradle
13 | build
14 | gradle.properties
15 |
16 | ### output
17 | dist
18 | logs
19 |
20 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
21 | !gradle-wrapper.jar
22 |
23 | # Cache of project
24 | .gradletasknamecache
25 |
26 | # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
27 | # gradle/wrapper/gradle-wrapper.properties
28 |
29 | .idea
30 | *.iml
31 |
32 | # OS X
33 | .DS_Store
34 |
35 | .settings/
36 | .classpath
37 | .project
38 | src/main/resources/application.toml
39 |
40 | *.key
41 | *.crt
42 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # safelist
2 | branches:
3 | only:
4 | - /.*/
5 |
6 | matrix:
7 | fast_finish: true
8 | include:
9 | - language: python
10 | python: 3.6
11 | dist: xenial
12 | before_cache:
13 | cache:
14 | before_install:
15 | script: |
16 | bash .ci/ci_check_commit.sh
17 |
18 | - language: java
19 | jdk: openjdk8
20 | os: linux
21 | dist: xenial
22 | sudo: required
23 |
24 | - language: java
25 | jdk: openjdk9
26 | os: linux
27 | dist: xenial
28 | sudo: required
29 |
30 | - language: java
31 | jdk: openjdk10
32 | os: linux
33 | dist: xenial
34 | sudo: required
35 |
36 | - language: java
37 | jdk: openjdk11
38 | os: linux
39 | dist: xenial
40 | sudo: required
41 |
42 | # - language: java
43 | # jdk: openjdk11
44 | # os: osx
45 | # before_install:
46 | # - brew install gradle && gradle wrapper
47 |
48 | before_cache:
49 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
50 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
51 | cache:
52 | directories:
53 | - $HOME/.gradle/caches/
54 | - $HOME/.gradle/wrapper/
55 | before_install:
56 | - gradle wrapper
57 | script: |
58 | bash .ci/ci_check.sh
59 |
60 | after_success:
61 | - bash <(curl -s https://codecov.io/bash)
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # 贡献代码
2 |
3 | 非常感谢能有心为WeCross贡献代码!
4 |
5 | ## 分支策略
6 |
7 | 项目采用[git-flow](https://jeffkreeftmeijer.com/git-flow/)的分支策略。
8 |
9 | * master:最新的稳定分支
10 | * dev:待发布的稳定分支
11 | * feature-xxxx:一个正在开发xxxx特性分支
12 | * bugfix-xxxx:一个正在修bug xxxx的分支
13 |
14 | ## 贡献方法
15 |
16 | ### Issue
17 |
18 | 可直接去[issues page](https://github.com/WeBankBlockchain/WeCross-Console/issues)提issue。
19 |
20 | ### 修复bug
21 |
22 | 1. Fork本仓库到个人仓库
23 | 2. 从个人仓库的master分支拉出一个bugfix-xxxx分支
24 | 3. 在bugfix-xxxx上修复bug
25 | 4. 测试修复的bug
26 | 5. PR(Pull Request)到本仓库的dev分支
27 | 6. 等待社区review这个PR
28 | 7. PR合入,bug修复完成!
29 |
30 | ### 开发新特性
31 |
32 | 1. Fork本仓库到个人仓库
33 | 2. 从个人仓库的dev分支拉出一个feature-xxxx分支
34 | 3. 在feature-xxxx上进行特性开发
35 | 4. 不定期的从本仓库的dev分支pull最新的改动到feature-xxxx分支
36 | 5. 测试新特性
37 | 6. PR(Pull Request)到本参考的dev分支
38 | 7. 等待社区review这个PR
39 | 8. PR合入,特性开发完成!
40 |
41 | ## 代码格式化
42 |
43 | 代码格式化gradle插件[google-java-format-gradle-plugin](https://github.com/sherter/google-java-format-gradle-plugin).
44 |
45 | 执行任务 `googleJavaFormat`格式化java文件。
46 | ```
47 | ./gradlew goJF
48 | ```
49 | 执行任务 `verifyGoogleJavaFormat`验证java文件是否格式化完成
50 | ```
51 | ./gradlew verGJF
52 | ```
53 |
--------------------------------------------------------------------------------
/Changelog.md:
--------------------------------------------------------------------------------
1 | ### v1.4.0
2 |
3 | (2024-03-01)
4 |
5 | **新增**
6 |
7 | - 增加获取区块的命令 `getBlock` https://github.com/WeBankBlockchain/WeCross-Console/pull/187
8 | - 增加跨链获取区块的示例合约 https://github.com/WeBankBlockchain/WeCross-Console/pull/188
9 |
10 | **更新**
11 |
12 | - 更新版本依赖,修复安全问题 https://github.com/WeBankBlockchain/WeCross-Console/pull/190
13 |
14 | ### v1.3.1
15 |
16 | (2023-07-31)
17 |
18 | **新增**
19 |
20 | * 支持FISCO BCOS 3.+ WASM执行版本,支持WASM合约部署、调用等功能。
21 |
22 | ### v1.3.0
23 |
24 | (2023-03-15)
25 |
26 | **新增**
27 |
28 | * 新增HelloWorld的Fabric chaincode #169,新增Sacc的Solidity合约 #170。
29 | * 新增单笔事务写交易接口 `autoCommitXATransaction`
30 | * 新增对FISCO BCOS 3.x 版本的支持
31 |
32 | **更改**
33 |
34 | * 优化Fabric交易接口。 #177
35 | * 更新commons-compress、log4j的版本号。
36 |
37 | ### v1.2.1
38 |
39 | (2021-12-15)
40 |
41 | **修复**
42 |
43 | * 修复log4j的漏洞,将其升级至2.15
44 |
45 | ### v1.2.0
46 |
47 | (2021-08-20)
48 |
49 | **新增**
50 |
51 | * 适配Fabric2.0类型的链账户
52 |
53 | ### v1.1.1
54 |
55 | (2021-04-02)
56 |
57 | **更改**
58 |
59 | * 启动时打印版本号
60 | * 升级wecross-java-sdk以支持Router的URL前缀可配
61 | * help 提示信息分类展示
62 |
63 | ### v1.1.0
64 |
65 | (2020-02-02)
66 |
67 | **更新**
68 |
69 | * 升级`groovy-all`版本,详情参考`build.gradle`修改
70 | * 修改`login`逻辑,参数加密以及`token`验证逻辑移植到`java-sdk`中
71 |
72 | **删除**
73 |
74 | * 删除`status`命令
75 |
76 | ### v1.0.1
77 |
78 | (2020-01-15)
79 |
80 | **功能**
81 |
82 | * 启动脚本添加参数,修复新版本JDK无法使用的问题
83 |
84 | ### v1.0.0
85 |
86 | (2020-12-17)
87 |
88 | **新增**
89 |
90 | * 账户相关命令:registerAccount、login、logout、addChainAccount、setDefaultAccount、listAccount
91 | * 新增事务命令:invoke,根据上下文自动选择发交易的方式
92 | * 新增合约: 桥接合约(WeCrossHub)、资产示例合约(AssetSample)
93 | * 文件名补全:部署相关命令支持文件名补全
94 |
95 | **更改**
96 |
97 | * 删除获取账户列表的命令:listAccounts
98 | * 资源调用相关命令参数列表去掉账户名
99 | * 部分事务命令重命名:
100 | * getTransactionIDs => getXATransaction
101 | * getTransactionIDs => listXATransactions
102 |
103 | ### v1.0.0-rc4
104 |
105 | (2020-08-18)
106 |
107 | **新增**
108 |
109 | * 资源部署命令
110 | * FISCO BCOS:bcosDeploy、bcosRegister
111 | * Fabric:fabricInstall、fabricInstantiate、fabricUpgrade
112 | * 2PC事务操作命令
113 | * 操作:startTransaction、execTransaction、callTransaction、commitTransaction、rollbackTransaction
114 | * 查询:getTransactionInfo、getTransactionIDs
115 | * 跨链资源集
116 | * 一般示例代码:HelloWorld.sol、sacc.go、fabcar.java
117 | * HTLC合约代码:HTLC.sol、htlc.go等
118 | * 两阶段示例:EvidenceSample.sol、EvidenceSample.go等
119 |
120 | ### v1.0.0-rc3
121 |
122 | (2020-06-15)
123 |
124 | **更改**
125 |
126 | * 适配v1.0.0-rc3的wecross-java-sdk
127 | * 下载脚本稳定性修复
128 |
129 | ### v1.0.0-rc2
130 |
131 | (2020-05-12)
132 |
133 | **新增**
134 |
135 | * 安全通讯:控制台和Router之间采用TLS协议通讯
136 | * 增加命令:
137 | * detail:查看资源详情信息
138 | * supportedStubs:查看连接Router支持的Stub插件列表
139 | * listAccounts:查看Router配置的账户列表
140 | * genSecretAndHash:跨链转账辅助命令,生成一个秘密和它的哈希
141 | * genTimelock:跨链转账辅助命令,生成两个合法的时间戳
142 | * newContract:创建一个基于哈希时间锁合约的跨链转账合同
143 |
144 | **更改**
145 |
146 | * 合约调用:合约调用需要指定签名的账户
147 | * 命令更新:合约调用不再需要指定返回值类型列表,因此删除了相关衍生命令
148 | * 配置文件:更新配置文件为toml格式,新增TLS配置项
149 |
150 | ### v1.0.0-rc1
151 |
152 | (2019-12-30)
153 |
154 | **功能**
155 |
156 | * 跨连控制台基本功能
157 |
158 | ```
159 | =============================================================================================
160 | Welcome to WeCross console(v1.0.0-rc1)!
161 | Type 'help' or 'h' for help. Type 'quit' or 'q' to quit console.
162 |
163 | =============================================================================================
164 | [server1]> -h
165 | Error: unsupported command.
166 |
167 | [server1]> help
168 | ---------------------------------------------------------------------------------------------
169 | quit Quit console.
170 | currentServer Show currently connected WeCross server.
171 | listServers List all configured WeCross servers.
172 | switch Switch to a specific WeCross server.
173 | listLocalResources List local resources configured by WeCross server.
174 | listResources List all resources including remote resources.
175 | status Check if the resource exists.
176 | getData Get data from contract.
177 | setData Set data for contract.
178 | call Call constant method of smart contract.
179 | callInt Call constant method of smart contract with int returned.
180 | callIntArray Call constant method of smart contract with int array returned.
181 | callString Call constant method of smart contract with string returned.
182 | callStringArray Call constant method of smart contract with string array returned.
183 | sendTransaction Call non-constant method of smart contract.
184 | sendTransactionInt Call non-constant method of smart contract with int returned.
185 | sendTransactionIntArray Call non-constant method of smart contract with int array returned.
186 | sendTransactionString Call non-constant method of smart contract with string returned.
187 | sendTransactionStringArray Call non-constant method of smart contract with string array returned.
188 | WeCross.getResource Init resource by path, and assign it to a custom variable.
189 | [resource].[command] Equal to command: command [path].
190 |
191 | ---------------------------------------------------------------------------------------------
192 | ```
193 |
194 | **框架**
195 |
196 | * 适配WeCross跨连路由v1.0.0-rc1版本
197 | * 集成WeCross Java SDK v1.0.0-rc1版本
198 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # WeCross-Console
4 |
5 | [](https://www.codefactor.io/repository/github/webankblockchain/WeCross-Console) [](https://travis-ci.org/WeBankBlockchain/WeCross-Console) [](https://github.com/WeBankBlockchain/WeCross-Console/releases/latest)
6 | [](https://www.apache.org/licenses/LICENSE-2.0) [](https://www.java.com)
7 |
8 | WeCross Console是[WeCross](https://github.com/WeBankBlockchain/WeCross)的重要交互式客户端工具。
9 |
10 | ## 关键特性
11 |
12 | - 支持交互式命令
13 | - 提供了针对跨链资源的操作命令
14 |
15 | ## 部署使用
16 |
17 | 可直接下载WeCross控制台压缩包,然后解压并使用,具体请参考[部署和使用文档](https://wecross.readthedocs.io/zh_CN/latest/docs/tutorial/networks.html#id7)。
18 |
19 | ## 源码编译
20 |
21 | **环境要求**:
22 |
23 | - [JDK8及以上](https://www.oracle.com/java/technologies/javase-downloads.html)
24 | - Gradle 5.0及以上
25 |
26 | **编译命令**:
27 |
28 | ```bash
29 | $ cd WeCross-Console
30 | $ ./gradlew assemble
31 | ```
32 |
33 | 如果编译成功,将在当前目录的dist/apps目录下生成控制台jar包。
34 |
35 | ## 项目贡献
36 |
37 | 欢迎参与WeCross社区的维护和建设:
38 |
39 | - 提交代码(Pull requests),可参考[代码贡献流程](CONTRIBUTING.md)以及[wiki指南](https://github.com/WeBankBlockchain/WeCross/wiki/%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81)
40 | - [提问和提交BUG](https://github.com/WeBankBlockchain/WeCross/issues/new)
41 |
42 | 您将成为贡献者,感谢各位贡献者的付出:
43 |
44 |
45 |
46 | ## 开源社区
47 |
48 | 参与meetup:[活动日历](https://github.com/WeBankBlockchain/WeCross/wiki#%E6%B4%BB%E5%8A%A8%E6%97%A5%E5%8E%86)
49 |
50 | 学习知识、讨论方案、开发新特性:[联系微信小助手,加入跨链兴趣小组(CC-SIG)](https://wecross.readthedocs.io/zh_CN/latest/docs/community/cc-sig.html#id3)
51 |
52 | ## License
53 |
54 | WeCross Console的开源协议为Apache License 2.0,详情参考[LICENSE](./LICENSE)。
55 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.github.sherter.google-java-format' version '0.8'
3 | id 'org.ajoberstar.grgit' version '4.0.1'
4 | }
5 |
6 | apply plugin: 'maven'
7 | apply plugin: 'idea'
8 | apply plugin: 'eclipse'
9 | apply plugin: 'java'
10 | apply plugin: 'jacoco'
11 |
12 | group = 'com.webank'
13 | version = '1.4.0'
14 | sourceCompatibility = '1.8'
15 |
16 | repositories {
17 | jcenter()
18 | maven { url "https://maven.aliyun.com/nexus/content/groups/public/" }
19 | maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
20 | mavenCentral()
21 | }
22 |
23 | googleJavaFormat {
24 | options style: 'AOSP'
25 | source = sourceSets*.allJava
26 | include '**/*.java'
27 | exclude '**/temp/*.java'
28 | }
29 |
30 | verifyGoogleJavaFormat {
31 | source = sourceSets*.allJava
32 | include '**/*.java'
33 | exclude '**/temp/*.java'
34 | }
35 |
36 | def log4j_version = '2.22.1'
37 | List logger = [
38 | "org.apache.logging.log4j:log4j-api:$log4j_version",
39 | "org.apache.logging.log4j:log4j-core:$log4j_version",
40 | "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version",
41 | //"org.apache.logging.log4j:log4j-to-slf4j:$log4j_version",
42 | //"org.apache.logging.log4j:log4j-web:$log4j_version",
43 | //"org.apache.logging.log4j:log4j-jul:$log4j_version"
44 | ]
45 |
46 | dependencies {
47 | compile logger
48 | compile 'org.jline:jline:3.15.0'
49 | compile 'org.codehaus.groovy:groovy-all:3.0.10'
50 | compile 'com.fasterxml.jackson.core:jackson-databind:2.14.3'
51 | compile 'com.webank:wecross-java-sdk:1.4.0'
52 | compile 'org.apache.commons:commons-compress:1.26.0'
53 | compile 'commons-io:commons-io:2.8.0'
54 | compile 'com.moandjiezana.toml:toml4j:0.7.2'
55 | compile 'com.google.code.gson:gson:2.8.9'
56 | // Use JUnit test framework
57 | testImplementation 'junit:junit:4.13.2'
58 | }
59 |
60 | sourceSets {
61 | main {
62 | resources {
63 | exclude 'contracts/*'
64 | }
65 | }
66 | }
67 | configurations.all {
68 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
69 | exclude module: "testng"
70 | }
71 |
72 | jar {
73 | destinationDir file('dist/apps')
74 | archiveName project.name + "-" + project.version + '.jar'
75 | exclude '**/*.xml'
76 | exclude '**/*.toml'
77 | exclude '**/*.properties'
78 | exclude '**/*.yml'
79 | exclude '**/*.crt'
80 | exclude '**/*.key'
81 |
82 | manifest {
83 | try {
84 | def repo = grgit.open(dir: file('.').canonicalPath)
85 | if (repo != null) {
86 | def date = new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
87 | def branch = repo.branch.getCurrent().getName()
88 | def commit = repo.head().getAbbreviatedId(40)
89 |
90 | attributes(["Implementation-Timestamp": date,
91 | "Git-Branch" : branch,
92 | "Git-Commit" : commit
93 | ])
94 |
95 | logger.info(" Commit : ")
96 | logger.info(" => date: {}", date)
97 | logger.info(" => branch: {}", branch)
98 | logger.info(" => commit: {}", commit)
99 | }
100 | } catch (Exception e) {
101 | // logger.warn(' .git not exist, cannot found commit info')
102 | }
103 | }
104 |
105 | doLast {
106 | copy {
107 | from file('src/main/resources/')
108 | into 'dist/conf'
109 | }
110 | copy {
111 | from configurations.runtime
112 | into 'dist/lib'
113 | }
114 | copy {
115 | from file('.').listFiles().findAll { File f -> (f.name.endsWith('.sh') || f.name.endsWith('.env')) }
116 | into 'dist'
117 | }
118 | copy {
119 | from file('scripts/')
120 | into 'dist'
121 | }
122 | }
123 | }
124 |
125 | test {
126 | testLogging {
127 | showStandardStreams = false
128 | events 'passed', 'skipped', 'failed'
129 | }
130 | }
131 |
132 | jacocoTestReport {
133 | reports {
134 | xml.enabled true
135 | html.enabled false
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/docs/images/menu_logo_wecross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WeBankBlockchain/WeCross-Console/d8b8f82c1cd49356d689f2c16288b8c8ebff434d/docs/images/menu_logo_wecross.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WeBankBlockchain/WeCross-Console/d8b8f82c1cd49356d689f2c16288b8c8ebff434d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=$((i+1))
158 | done
159 | case $i in
160 | (0) set -- ;;
161 | (1) set -- "$args0" ;;
162 | (2) set -- "$args0" "$args1" ;;
163 | (3) set -- "$args0" "$args1" "$args2" ;;
164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=$(save "$@")
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
185 | cd "$(dirname "$0")"
186 | fi
187 |
188 | exec "$JAVACMD" "$@"
189 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/release_note.txt:
--------------------------------------------------------------------------------
1 | v1.4.0
--------------------------------------------------------------------------------
/scripts/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | dirpath="$(cd "$(dirname "$0")" && pwd)"
3 | cd ${dirpath}
4 | export LANG='zh_CN.utf8'
5 |
6 | APPS_FOLDER=$(pwd)/apps
7 | SECURIY_FILE='./.wecross.security'
8 |
9 | LOG_INFO() {
10 | echo -e "\033[32m$@\033[0m"
11 | }
12 |
13 | LOG_ERROR() {
14 | echo -e "\033[31m$@\033[0m"
15 | }
16 |
17 | create_jvm_security() {
18 | if [[ ! -f ${SECURIY_FILE} ]];then
19 | echo "jdk.disabled.namedCurves = " > ${SECURIY_FILE}
20 | # LOG_INFO "create new file ${SECURIY_FILE}"
21 | fi
22 | }
23 |
24 | show_version() {
25 | LOG_INFO "WeCross-Console version: [" $(ls ${APPS_FOLDER} |awk '{gsub(/.jar$/,""); print}') "]"
26 | }
27 |
28 | run_console() {
29 | if [ "$(uname)" == "Darwin" ]; then
30 | # Mac
31 | java -Dfile.encoding=UTF-8 -Djava.security.properties=${SECURIY_FILE} -Djdk.sunec.disableNative="false" -Djdk.tls.namedGroups="secp256k1,x25519,secp256r1,secp384r1,secp521r1,x448,ffdhe2048,ffdhe3072,ffdhe4096,ffdhe6144,ffdhe8192" -cp 'apps/*:lib/*:conf' com.webank.wecross.console.Shell
32 | elif [ "$(uname -s | grep MINGW | wc -l)" != "0" ]; then
33 | # Windows
34 | java -Dfile.encoding=UTF-8 -Djava.security.properties=${SECURIY_FILE} -Djdk.sunec.disableNative="false" -Djdk.tls.namedGroups="secp256k1,x25519,secp256r1,secp384r1,secp521r1,x448,ffdhe2048,ffdhe3072,ffdhe4096,ffdhe6144,ffdhe8192" -cp 'apps/*;lib/*;conf' com.webank.wecross.console.Shell
35 | else
36 | # GNU/Linux
37 | java -Dfile.encoding=UTF-8 -Djava.security.properties=${SECURIY_FILE} -Djdk.sunec.disableNative="false" -Djdk.tls.namedGroups="secp256k1,x25519,secp256r1,secp384r1,secp521r1,x448,ffdhe2048,ffdhe3072,ffdhe4096,ffdhe6144,ffdhe8192" -cp 'apps/*:lib/*:conf' -Djava.security.egd=file:/dev/./urandom com.webank.wecross.console.Shell
38 | fi
39 | }
40 |
41 | create_jvm_security
42 | show_version
43 | run_console
44 |
45 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'wecross-console'
2 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/Initializer.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console;
2 |
3 | import com.webank.wecross.console.custom.BCOSCommand;
4 | import com.webank.wecross.console.custom.FabricCommand;
5 | import com.webank.wecross.console.exception.ErrorCode;
6 | import com.webank.wecross.console.exception.WeCrossConsoleException;
7 | import com.webank.wecross.console.routine.HTLCFace;
8 | import com.webank.wecross.console.routine.HTLCImpl;
9 | import com.webank.wecross.console.routine.XAFace;
10 | import com.webank.wecross.console.routine.XAImpl;
11 | import com.webank.wecross.console.rpc.RPCFace;
12 | import com.webank.wecross.console.rpc.RPCImpl;
13 | import com.webank.wecrosssdk.exception.WeCrossSDKException;
14 | import com.webank.wecrosssdk.rpc.WeCrossRPC;
15 | import com.webank.wecrosssdk.rpc.WeCrossRPCFactory;
16 | import com.webank.wecrosssdk.rpc.service.WeCrossRPCService;
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 |
20 | public class Initializer {
21 |
22 | private Logger logger = LoggerFactory.getLogger(Initializer.class);
23 |
24 | private WeCrossRPC weCrossRPC;
25 | private RPCFace rpcFace;
26 | private XAFace xaFace;
27 | private HTLCFace htlcFace;
28 | private BCOSCommand bcosCommand;
29 | private FabricCommand fabricCommand;
30 |
31 | public void init() throws WeCrossConsoleException {
32 | WeCrossRPCService weCrossRPCService = new WeCrossRPCService();
33 | try {
34 | weCrossRPC = WeCrossRPCFactory.build(weCrossRPCService);
35 | } catch (WeCrossSDKException e) {
36 | logger.error("init wecross service failed: {}", e.getMessage());
37 | throw new WeCrossConsoleException(ErrorCode.INIT_WECROSS_SERVICE_ERROR, e.getMessage());
38 | }
39 | rpcFace = new RPCImpl();
40 | rpcFace.setWeCrossRPC(weCrossRPC);
41 | htlcFace = new HTLCImpl();
42 | htlcFace.setWeCrossRPC(weCrossRPC);
43 | xaFace = new XAImpl();
44 | xaFace.setWeCrossRPC(weCrossRPC);
45 | bcosCommand = new BCOSCommand(weCrossRPC);
46 | fabricCommand = new FabricCommand(weCrossRPC);
47 | }
48 |
49 | public WeCrossRPC getWeCrossRPC() {
50 | return weCrossRPC;
51 | }
52 |
53 | public void setWeCrossRPC(WeCrossRPC weCrossRPC) {
54 | this.weCrossRPC = weCrossRPC;
55 | }
56 |
57 | public RPCFace getRpcFace() {
58 | return rpcFace;
59 | }
60 |
61 | public void setRpcFace(RPCFace rpcFace) {
62 | this.rpcFace = rpcFace;
63 | }
64 |
65 | public HTLCFace getHtlcFace() {
66 | return htlcFace;
67 | }
68 |
69 | public void setHtlcFace(HTLCFace htlcFace) {
70 | this.htlcFace = htlcFace;
71 | }
72 |
73 | public XAFace getXaFace() {
74 | return xaFace;
75 | }
76 |
77 | public void setXaFace(XAFace xaFace) {
78 | this.xaFace = xaFace;
79 | }
80 |
81 | public BCOSCommand getBcosCommand() {
82 | return bcosCommand;
83 | }
84 |
85 | public void setBcosCommand(BCOSCommand bcosCommand) {
86 | this.bcosCommand = bcosCommand;
87 | }
88 |
89 | public FabricCommand getFabricCommand() {
90 | return fabricCommand;
91 | }
92 |
93 | public void setFabricCommand(FabricCommand fabricCommand) {
94 | this.fabricCommand = fabricCommand;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/ConsoleUtils.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import com.google.common.collect.BiMap;
4 | import com.google.common.collect.HashBiMap;
5 | import com.webank.wecross.console.exception.ErrorCode;
6 | import com.webank.wecross.console.exception.WeCrossConsoleException;
7 | import java.net.URL;
8 | import java.util.*;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 | import java.util.stream.Collectors;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 |
15 | public class ConsoleUtils {
16 | public static ThreadLocal runtimeUsernameThreadLocal = new ThreadLocal<>();
17 | public static ThreadLocal runtimePasswordThreadLocal = new ThreadLocal<>();
18 |
19 | public static final String fabricType = "Fabric1.4";
20 | public static final String fabricType2 = "Fabric2.0";
21 | public static final String BCOSType = "BCOS2.0";
22 | public static final String BCOSGMType = "GM_BCOS2.0";
23 | public static final String BCOSType3 = "BCOS3_ECDSA_EVM";
24 | public static final String BCOSGMType3 = "BCOS3_GM_EVM";
25 | public static final String BCOSWASMType3 = "BCOS3_ECDSA_WASM";
26 | public static final String BCOSWASMGMType3 = "BCOS3_GM_WASM";
27 | public static final List bcosChainList =
28 | Arrays.asList(
29 | BCOSType, BCOSGMType, BCOSType3, BCOSGMType3, BCOSWASMType3, BCOSWASMGMType3);
30 | public static final List supportChainList =
31 | Arrays.asList(
32 | fabricType,
33 | BCOSType,
34 | BCOSGMType,
35 | fabricType2,
36 | BCOSType3,
37 | BCOSGMType3,
38 | BCOSWASMType3,
39 | BCOSWASMGMType3);
40 | private static final Logger logger = LoggerFactory.getLogger(ConsoleUtils.class);
41 |
42 | public static boolean isValidPath(String path) {
43 | if (path == null || path.length() == 0 || path.charAt(0) == '.' || path.endsWith(".")) {
44 | return false;
45 | }
46 | String[] unit = path.split("\\.");
47 | if (unit.length == 3) {
48 | String templateUrl = "http://127.0.0.1:8080/" + path.replace('.', '/');
49 | try {
50 | new URL(templateUrl);
51 | } catch (Exception e) {
52 | return false;
53 | }
54 | return true;
55 | }
56 | return false;
57 | }
58 |
59 | public static boolean isValidPathVar(String path, Map pathMaps) {
60 | return pathMaps.containsKey(path);
61 | }
62 |
63 | public static boolean isNaturalInteger(String seq) {
64 | try {
65 | int s = Integer.parseInt(seq);
66 | return s >= 0;
67 | } catch (Exception e) {
68 | return false;
69 | }
70 | }
71 |
72 | public static boolean isNumeric(String str) {
73 | Pattern p = Pattern.compile("[0-9]*");
74 | return p.matcher(str).matches();
75 | }
76 |
77 | // parse variables and save path variables
78 | public static Boolean parseVars(
79 | String[] params,
80 | List resourceVars,
81 | List pathVars,
82 | Map pathMaps) {
83 | int length = params.length;
84 | if (length < 3 || params[0].contains("\"") || params[0].contains("'")) {
85 | return false;
86 | }
87 | if (params[1].equals("=")) {
88 | if (params[2].equals("WeCross.getResource")) {
89 | if (length != 4) {
90 | return false;
91 | }
92 | if (pathMaps.keySet().contains(params[3])) {
93 | resourceVars.add(params[0]);
94 | return true;
95 | }
96 | String path = parseString(params[3]);
97 | if (ConsoleUtils.isValidPath(path)) {
98 | pathVars.add(path);
99 | resourceVars.add(params[0]);
100 | return true;
101 | }
102 | } else {
103 | if (length != 3) {
104 | return false;
105 | }
106 | String path = parseString(params[2]);
107 | if (ConsoleUtils.isValidPath(path)) {
108 | pathVars.add(params[0]);
109 | pathMaps.put(params[0], path);
110 | return true;
111 | }
112 | }
113 | }
114 | return false;
115 | }
116 |
117 | // remove "" or '' of string
118 | public static String parseString(String input) {
119 | int len = input.length();
120 | if (len < 2) {
121 | return input;
122 | }
123 | if (input.charAt(0) == '\"' && input.charAt(len - 1) == '\"'
124 | || input.charAt(0) == '\'' && input.charAt(len - 1) == '\'') {
125 | return input.substring(1, len - 1);
126 | }
127 | return input;
128 | }
129 |
130 | public static String[] parseArgs(String[] args) {
131 | String[] result = new String[args.length];
132 | for (int i = 0; i < args.length; i++) {
133 | result[i] = parseString(args[i]);
134 | }
135 | return result;
136 | }
137 |
138 | public static void printJson(String jsonStr) {
139 | System.out.println(formatJson(jsonStr));
140 | }
141 |
142 | public static String formatJson(String jsonStr) {
143 | if (null == jsonStr || "".equals(jsonStr)) {
144 | return "";
145 | }
146 | jsonStr = jsonStr.replace("\\n", "");
147 | StringBuilder sb = new StringBuilder();
148 | char last = '\0';
149 | char current = '\0';
150 | int indent = 0;
151 | boolean isInQuotationMarks = false;
152 | for (int i = 0; i < jsonStr.length(); i++) {
153 | last = current;
154 | current = jsonStr.charAt(i);
155 | switch (current) {
156 | case '"':
157 | if (last != '\\') {
158 | isInQuotationMarks = !isInQuotationMarks;
159 | }
160 | sb.append(current);
161 | break;
162 | case '{':
163 | case '[':
164 | sb.append(current);
165 | if (!isInQuotationMarks) {
166 | sb.append('\n');
167 | indent++;
168 | addIndentBlank(sb, indent);
169 | }
170 | break;
171 | case '}':
172 | case ']':
173 | if (!isInQuotationMarks) {
174 | sb.append('\n');
175 | indent--;
176 | addIndentBlank(sb, indent);
177 | }
178 | sb.append(current);
179 | break;
180 | case ',':
181 | sb.append(current);
182 | if (last != '\\' && !isInQuotationMarks) {
183 | sb.append('\n');
184 | addIndentBlank(sb, indent);
185 | }
186 | break;
187 | case ' ':
188 | if (',' != jsonStr.charAt(i - 1)) {
189 | sb.append(current);
190 | }
191 | break;
192 | case '\\':
193 | break;
194 | default:
195 | if (!(current == " ".charAt(0))) sb.append(current);
196 | }
197 | }
198 | return sb.toString();
199 | }
200 |
201 | private static void addIndentBlank(StringBuilder sb, int indent) {
202 | for (int i = 0; i < indent; i++) {
203 | sb.append(" ");
204 | }
205 | }
206 |
207 | public static String parsePath(String[] params, Map pathMaps) {
208 | String path = parseString(params[1]);
209 | if (!isValidPath(path)) {
210 | if (!isValidPathVar(params[1], pathMaps)) {
211 | System.out.println("Please provide a valid path");
212 | return null;
213 | }
214 | path = pathMaps.get(params[1]);
215 | }
216 | return path;
217 | }
218 |
219 | public static String[] tokenizeCommand(String line) {
220 | // example: callByCNS HelloWorld.sol set"Hello" parse [callByCNS, HelloWorld.sol,
221 | // set"Hello"]
222 |
223 | BiMap tokens = HashBiMap.create();
224 |
225 | tokens.put('"', '"');
226 | tokens.put('\'', '\'');
227 | tokens.put('{', '}');
228 | tokens.put('[', ']');
229 | tokens.put('(', ')');
230 |
231 | String trimLine = line.trim();
232 |
233 | LinkedList items = new LinkedList();
234 | items.add(new StringBuffer());
235 |
236 | boolean isEscape = false;
237 | Stack tokenStack = new Stack();
238 |
239 | for (int i = 0; i < trimLine.length(); ++i) {
240 | Character c = trimLine.charAt(i);
241 |
242 | if (!isEscape) {
243 | if (c == '\\') {
244 | isEscape = true;
245 | continue;
246 | }
247 |
248 | if ((c == ' ' || c == '\t') && tokenStack.isEmpty()) {
249 | if (items.getLast().length() > 0) {
250 | items.add(new StringBuffer());
251 | }
252 |
253 | continue;
254 | }
255 |
256 | Character token = tokens.get(c);
257 | if (token == null) {
258 | token = tokens.inverse().get(c);
259 | }
260 |
261 | if (token != null) {
262 | if (!tokenStack.isEmpty() && tokenStack.peek().equals(token)) {
263 | tokenStack.pop();
264 | } else {
265 | tokenStack.add(c);
266 | }
267 | }
268 | }
269 |
270 | items.getLast().append(c);
271 | }
272 |
273 | return items.stream()
274 | .map(StringBuffer::toString)
275 | .collect(Collectors.toList())
276 | .toArray(new String[] {});
277 | }
278 |
279 | public static String parseCommand(String[] params) throws WeCrossConsoleException {
280 | StringBuilder result = new StringBuilder();
281 | boolean isArgs = false;
282 | int length = params.length;
283 | int start = 0;
284 | if (length != 0) {
285 | if (params[0].endsWith(".call") || params[0].endsWith(".sendTransaction")) {
286 | isArgs = true;
287 | if (length < 2) {
288 | throw new WeCrossConsoleException(
289 | ErrorCode.METHOD_MISSING, "Method is missing");
290 | }
291 | start = 1;
292 | result = new StringBuilder(params[0] + " ");
293 | } else if (params[0].endsWith(".status") || params[0].endsWith(".detail")) {
294 | if (length != 1) {
295 | throw new WeCrossConsoleException(
296 | ErrorCode.ILLEGAL_PARAM, "Redundant parameters");
297 | }
298 | result = new StringBuilder(params[0] + "()");
299 | return result.toString();
300 | } else if (length > 3 && params[2].equals("WeCross.getResource")) {
301 | if (length != 4) {
302 | throw new WeCrossConsoleException(
303 | ErrorCode.ILLEGAL_PARAM, "Parameter:q error: [path]");
304 | }
305 | result = new StringBuilder(params[0] + " " + params[1] + " " + params[2] + " ");
306 | String path = params[3];
307 | if (ConsoleUtils.isValidPath(parseString(params[3]))) {
308 | path = "\"" + path + "\"";
309 | }
310 | result.append(path);
311 | return result.toString();
312 | }
313 | for (; start < length; ++start) {
314 | String temp = parseString(params[start]);
315 | if (!isArgs && ConsoleUtils.isValidPath(temp)) {
316 | result.append("\"").append(temp).append("\"").append(" ");
317 | } else if (isArgs) {
318 | result.append("\"").append(parseString(params[start])).append("\"").append(",");
319 | } else {
320 | result.append(params[start]).append(" ");
321 | }
322 | }
323 | result = new StringBuilder(result.substring(0, result.length() - 1));
324 | }
325 | // System.out.println(result);
326 | return result.toString();
327 | }
328 |
329 | public static List parseArrayInParams(String params) {
330 | // pathString => paths[]
331 | List pathList = new ArrayList<>();
332 | // [a.b.c] or [a.b.c,a.b.d]
333 | Pattern pattern =
334 | Pattern.compile(
335 | "^\\[(([\\u4e00-\\u9fa5\\w-]+\\.){2}[\\u4e00-\\u9fa5\\w-]+\\,){0,}(([\\u4e00-\\u9fa5\\w-]+\\.){2}[\\u4e00-\\u9fa5\\w-]+)\\]$");
336 | Matcher matcher = pattern.matcher(params);
337 | if (matcher.find()) {
338 | String pathString = params.substring(1, params.length() - 1);
339 | pathString = pathString.replaceAll(" ", "");
340 | Collections.addAll(pathList, pathString.split(","));
341 | }
342 | return pathList;
343 | }
344 |
345 | public static void singleLine() {
346 | System.out.println(
347 | "---------------------------------------------------------------------------------------------");
348 | }
349 |
350 | public static void doubleLine() {
351 | System.out.println(
352 | "=============================================================================================");
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import com.moandjiezana.toml.Toml;
4 | import com.moandjiezana.toml.TomlWriter;
5 | import com.webank.wecross.console.exception.ErrorCode;
6 | import com.webank.wecross.console.exception.WeCrossConsoleException;
7 | import com.webank.wecross.console.routine.XAFace;
8 | import com.webank.wecrosssdk.rpc.common.TransactionContext;
9 | import java.io.File;
10 | import java.io.FileWriter;
11 | import java.io.IOException;
12 | import java.nio.charset.StandardCharsets;
13 | import java.nio.file.Files;
14 | import java.nio.file.Path;
15 | import java.nio.file.Paths;
16 | import java.util.Base64;
17 | import java.util.List;
18 | import java.util.Scanner;
19 | import java.util.Set;
20 | import java.util.regex.Matcher;
21 | import java.util.regex.Pattern;
22 | import org.jline.reader.Completer;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
26 |
27 | public class FileUtils {
28 |
29 | public static final String TRANSACTION_LOG_TOML = "transactionLog.toml";
30 | public static final String CONF = "conf";
31 | private static final Logger logger = LoggerFactory.getLogger(FileUtils.class);
32 |
33 | public static Toml getToml(String fileName) throws WeCrossConsoleException {
34 | try {
35 | Path path;
36 | if (fileName.indexOf("classpath:") != 0) {
37 | path = Paths.get(fileName);
38 | } else {
39 | PathMatchingResourcePatternResolver resolver =
40 | new PathMatchingResourcePatternResolver();
41 | if (!resolver.getResource(fileName).exists()) {
42 | throw new WeCrossConsoleException(
43 | ErrorCode.TX_LOG_NOT_EXIST,
44 | TRANSACTION_LOG_TOML + " doesn't exist, clean transaction context.");
45 | }
46 | path = Paths.get(resolver.getResource(fileName).getURI());
47 | }
48 | return new Toml().read(path.toFile());
49 | } catch (IOException e) {
50 | throw new WeCrossConsoleException(
51 | ErrorCode.INTERNAL_ERROR,
52 | "Something wrong with parsing " + fileName + ": " + e);
53 | }
54 | }
55 |
56 | public static String mergeSource(
57 | String currentDir,
58 | String sourceFile,
59 | PathMatchingResourcePatternResolver resolver,
60 | Set dependencies)
61 | throws Exception {
62 | StringBuffer sourceBuffer = new StringBuffer();
63 |
64 | String fullPath = currentDir + sourceFile;
65 | String dir = fullPath.substring(0, fullPath.lastIndexOf(File.separator)) + File.separator;
66 |
67 | org.springframework.core.io.Resource sourceResource =
68 | resolver.getResource("file:" + fullPath);
69 | if (!sourceResource.exists()) {
70 | logger.error("Source file: {} not found!", fullPath);
71 |
72 | throw new IOException("Source file:" + fullPath + " not found");
73 | }
74 |
75 | Pattern pattern = Pattern.compile("^\\s*import\\s+[\"'](.+)[\"']\\s*;\\s*$");
76 | try (Scanner scanner = new Scanner(sourceResource.getInputStream(), "UTF-8")) {
77 | while (scanner.hasNextLine()) {
78 | String line = scanner.nextLine();
79 | if (line.contains("pragma experimental ABIEncoderV2;")) {
80 | if (!dependencies.contains("pragma experimental ABIEncoderV2;")) {
81 | dependencies.add("pragma experimental ABIEncoderV2;");
82 | sourceBuffer.append(line);
83 | sourceBuffer.append(System.lineSeparator());
84 | }
85 | continue;
86 | }
87 |
88 | Matcher matcher = pattern.matcher(line);
89 | if (matcher.find()) {
90 | String depSourcePath = matcher.group(1);
91 | String nextPath = dir + depSourcePath;
92 | if (!dependencies.contains(nextPath)) {
93 | dependencies.add(nextPath);
94 | sourceBuffer.append(
95 | mergeSource(dir, depSourcePath, resolver, dependencies));
96 | }
97 | } else {
98 | sourceBuffer.append(line);
99 | sourceBuffer.append(System.lineSeparator());
100 | }
101 | }
102 | }
103 |
104 | return sourceBuffer.toString();
105 | }
106 |
107 | public static String readFileContent(String fileName) throws IOException {
108 | try {
109 | // to avoid path manipulation
110 | fileName = fileName.replace("..", "");
111 | Path path;
112 |
113 | if (fileName.indexOf("classpath:") != 0) {
114 | path = Paths.get(fileName);
115 | } else {
116 | // Start with "classpath:"
117 | PathMatchingResourcePatternResolver resolver =
118 | new PathMatchingResourcePatternResolver();
119 | path = Paths.get(resolver.getResource(fileName).getURI());
120 | }
121 | return new String(Files.readAllBytes(path));
122 | } catch (Exception e) {
123 | logger.error("Read file error: ", e);
124 | throw new IOException("Read file error: " + e);
125 | }
126 | }
127 |
128 | public static String readFileContentToHexString(String fileName) throws IOException {
129 | try {
130 | // to avoid path manipulation
131 | fileName = fileName.replace("..", "");
132 | Path path;
133 |
134 | if (fileName.indexOf("classpath:") != 0) {
135 | path = Paths.get(fileName);
136 | } else {
137 | // Start with "classpath:"
138 | PathMatchingResourcePatternResolver resolver =
139 | new PathMatchingResourcePatternResolver();
140 | path = Paths.get(resolver.getResource(fileName).getURI());
141 | }
142 | return byteArrayToHex(Files.readAllBytes(path));
143 | } catch (Exception e) {
144 | logger.error("Read file error: ", e);
145 | throw new IOException("Read file error: " + e);
146 | }
147 | }
148 |
149 | public static String readFileToBytesString(String filePath) throws Exception {
150 | String content = readFileContent(filePath);
151 | return Base64.getEncoder().encodeToString(content.getBytes(StandardCharsets.UTF_8));
152 | }
153 |
154 | static String byteArrayToHex(byte[] bytes) {
155 | StringBuilder result = new StringBuilder();
156 | for (int index = 0, len = bytes.length; index <= len - 1; index += 1) {
157 | int char1 = ((bytes[index] >> 4) & 0xF);
158 | char chara1 = Character.forDigit(char1, 16);
159 | int char2 = ((bytes[index]) & 0xF);
160 | char chara2 = Character.forDigit(char2, 16);
161 | result.append(chara1);
162 | result.append(chara2);
163 | }
164 | return result.toString();
165 | }
166 |
167 | public static String getTransactionID(Toml toml) throws WeCrossConsoleException {
168 | String transactionID = toml.getString("transactionID");
169 | if (transactionID == null) {
170 | String errorMessage =
171 | "Something wrong with parsing [transactionID], please check configuration";
172 | throw new WeCrossConsoleException(ErrorCode.INVALID_TXID, errorMessage);
173 | }
174 |
175 | return transactionID;
176 | }
177 |
178 | public static List getTransactionPath(Toml toml) throws WeCrossConsoleException {
179 | List transactionPath = toml.getList("paths");
180 | if (transactionPath == null) {
181 | String errorMessage =
182 | "Something wrong with parsing [paths], please check configuration";
183 | throw new WeCrossConsoleException(ErrorCode.INVALID_PATH, errorMessage);
184 | }
185 |
186 | return transactionPath;
187 | }
188 |
189 | public static void loadTransactionLog(List completers, XAFace xaFace) {
190 | try {
191 | Toml toml = getToml("classpath:" + TRANSACTION_LOG_TOML);
192 | String transactionID = getTransactionID(toml);
193 | List transactionPath = getTransactionPath(toml);
194 |
195 | if (!xaFace.isTransactionInfoExist(
196 | transactionID, transactionPath.toArray(new String[0]))) {
197 | logger.error(
198 | "loadTransactionLog error: the transaction in toml file had already been committed/rollbacked or even doesn't exist.");
199 | FileUtils.cleanFile(FileUtils.CONF, FileUtils.TRANSACTION_LOG_TOML);
200 | return;
201 | }
202 | TransactionContext.txThreadLocal.set(transactionID);
203 | TransactionContext.pathInTransactionThreadLocal.set(transactionPath);
204 | } catch (WeCrossConsoleException e) {
205 | if (e.getErrorCode() == ErrorCode.TX_LOG_NOT_EXIST) {
206 | logger.info("Load transactionLog Toml file fail, {}", e.getMessage());
207 | } else {
208 | logger.warn("Load transactionLog Toml file fail, error: {}.", e.getMessage());
209 | }
210 | } catch (Exception e) {
211 | logger.warn("Load transactionLog Toml file fail, error: {}", e.getMessage());
212 | }
213 | }
214 |
215 | public static void writeTransactionLog() {
216 | TomlWriter writer = new TomlWriter();
217 | TransactionInfo transactionInfo =
218 | new TransactionInfo(
219 | TransactionContext.currentXATransactionID(),
220 | TransactionContext.pathInTransactionThreadLocal.get());
221 | try {
222 | writer.write(transactionInfo, new File(CONF, TRANSACTION_LOG_TOML));
223 | } catch (IOException e) {
224 | logger.error("Write TransactionLogTOML file error: {}", e.getMessage());
225 | }
226 | }
227 |
228 | public static void cleanFile(String prefix, String filename) throws WeCrossConsoleException {
229 | File file = new File(prefix, filename);
230 | if (!file.exists()) {
231 | logger.error("Cannot find file: {}", filename);
232 | return;
233 | }
234 | if (!file.delete()) {
235 | logger.error("Cannot delete file: {}", filename);
236 | throw new WeCrossConsoleException(
237 | ErrorCode.INTERNAL_ERROR, "Cannot delete file: " + filename);
238 | }
239 | }
240 |
241 | public static void writeFile(String fileName, String content, boolean append)
242 | throws WeCrossConsoleException {
243 | try (FileWriter writer = new FileWriter(fileName, append)) {
244 | writer.write(content + "\n");
245 | } catch (IOException e) {
246 | throw new WeCrossConsoleException(
247 | ErrorCode.INTERNAL_ERROR, "Load file " + fileName + " fail, error: " + e);
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/Hash.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import java.nio.charset.StandardCharsets;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.security.SecureRandom;
7 |
8 | public class Hash {
9 | public String getRandom(int numBytes) {
10 | SecureRandom random = new SecureRandom();
11 | return bytesToHex(random.generateSeed(numBytes));
12 | }
13 |
14 | public String sha256(String msg) throws NoSuchAlgorithmException {
15 | MessageDigest messageDigest;
16 | String encodestr;
17 | messageDigest = MessageDigest.getInstance("SHA-256");
18 | messageDigest.update(msg.getBytes(StandardCharsets.UTF_8));
19 | encodestr = bytesToHex(messageDigest.digest());
20 | return encodestr;
21 | }
22 |
23 | private String bytesToHex(byte[] bytes) {
24 | StringBuilder stringBuffer = new StringBuilder();
25 | String temp;
26 | for (int i = 0; i < bytes.length; i++) {
27 | temp = Integer.toHexString(bytes[i] & 0xFF);
28 | if (temp.length() == 1) {
29 | stringBuffer.append("0");
30 | }
31 | stringBuffer.append(temp);
32 | }
33 | return stringBuffer.toString();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/IgnoreCaseCompleter.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Collection;
6 | import java.util.Iterator;
7 | import java.util.List;
8 | import org.jline.reader.Buffer;
9 | import org.jline.reader.Candidate;
10 | import org.jline.reader.Completer;
11 | import org.jline.reader.LineReader;
12 | import org.jline.reader.ParsedLine;
13 | import org.jline.utils.AttributedString;
14 |
15 | public class IgnoreCaseCompleter implements Completer {
16 |
17 | protected final Collection candidates = new ArrayList<>();
18 |
19 | public IgnoreCaseCompleter() {}
20 |
21 | public IgnoreCaseCompleter(String... strings) {
22 | this(Arrays.asList(strings));
23 | }
24 |
25 | public IgnoreCaseCompleter(Iterable strings) {
26 | assert strings != null;
27 | for (String string : strings) {
28 | candidates.add(
29 | new Candidate(
30 | AttributedString.stripAnsi(string),
31 | string,
32 | null,
33 | null,
34 | null,
35 | null,
36 | true));
37 | }
38 | }
39 |
40 | public IgnoreCaseCompleter(Candidate... candidates) {
41 | assert candidates != null;
42 | this.candidates.addAll(Arrays.asList(candidates));
43 | }
44 |
45 | public void complete(
46 | LineReader reader, final ParsedLine commandLine, final List candidates) {
47 | assert commandLine != null;
48 | assert candidates != null;
49 |
50 | Buffer buffer = reader.getBuffer();
51 | String start = (buffer == null) ? "" : buffer.toString();
52 | int index = start.lastIndexOf(" ");
53 | String tmp = start.substring(index + 1).toLowerCase();
54 |
55 | for (Iterator iter = this.candidates.iterator(); iter.hasNext(); ) {
56 | Candidate candidate = iter.next();
57 | String candidateStr = candidate.value().toLowerCase();
58 | if (candidateStr.startsWith(tmp)) {
59 | candidates.add(candidate);
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/JlineUtils.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.Paths;
5 | import java.util.*;
6 | import org.jline.builtins.Completers.DirectoriesCompleter;
7 | import org.jline.builtins.Completers.FilesCompleter;
8 | import org.jline.reader.Completer;
9 | import org.jline.reader.LineReader;
10 | import org.jline.reader.LineReaderBuilder;
11 | import org.jline.reader.impl.completer.AggregateCompleter;
12 | import org.jline.reader.impl.completer.ArgumentCompleter;
13 | import org.jline.reader.impl.completer.NullCompleter;
14 | import org.jline.reader.impl.completer.StringsCompleter;
15 | import org.jline.terminal.Attributes;
16 | import org.jline.terminal.Attributes.ControlChar;
17 | import org.jline.terminal.Terminal;
18 | import org.jline.terminal.TerminalBuilder;
19 |
20 | public class JlineUtils {
21 |
22 | private static Set paths = new HashSet<>();
23 | private static Set pathVars = new HashSet<>();
24 | private static Set resourceVars = new HashSet<>();
25 | private static Set contractMethods = new HashSet<>();
26 | private static Set orgs = new HashSet<>();
27 | private static final List pathVarSupportedCommands =
28 | Arrays.asList("detail", "call", "sendTransaction");
29 |
30 | private static final List callContractCommands =
31 | Arrays.asList("call", "sendTransaction");
32 |
33 | private static final List pathVarNotSupportedCommands =
34 | Arrays.asList(
35 | "bcosDeploy",
36 | "bcosRegister",
37 | "fabricInstall",
38 | "fabricInstantiate",
39 | "fabricUpgrade",
40 | "login",
41 | "registerAccount",
42 | "logout",
43 | "addChainAccount",
44 | "setDefaultAccount");
45 |
46 | private static final List fabricCommands =
47 | Arrays.asList("fabricInstall", "fabricInstantiate", "fabricUpgrade");
48 |
49 | private static final List bcosCommands = Arrays.asList("bcosDeploy", "bcosRegister");
50 |
51 | private static final List allCommands =
52 | Arrays.asList(
53 | "help",
54 | "quit",
55 | "supportedStubs",
56 | "listAccount",
57 | "listLocalResources",
58 | "listResources",
59 | "detail",
60 | "call",
61 | "invoke",
62 | "sendTransaction",
63 | "newHTLCProposal",
64 | "genTimelock",
65 | "checkTransferStatus",
66 | "genSecretAndHash",
67 | "callTransaction",
68 | "execTransaction",
69 | "startTransaction",
70 | "commitTransaction",
71 | "rollbackTransaction",
72 | "getXATransaction",
73 | "listXATransactions",
74 | "loadTransaction",
75 | "bcosDeploy",
76 | "bcosRegister",
77 | "fabricInstall",
78 | "fabricInstantiate",
79 | "fabricUpgrade",
80 | "login",
81 | "registerAccount",
82 | "logout",
83 | "getBlock",
84 | "addChainAccount",
85 | "setDefaultAccount",
86 | "setDefaultChainAccount",
87 | "getCurrentTransactionID");
88 |
89 | public static void addCommandCompleters(List completers) {
90 | // commands
91 | for (String command : allCommands) {
92 | completers.add(
93 | new ArgumentCompleter(
94 | new IgnoreCaseCompleter(command), NullCompleter.INSTANCE));
95 | }
96 | }
97 |
98 | public static List getNoAuthCompleters() {
99 | List completers = new ArrayList<>();
100 | addCommandCompleters(completers);
101 | return completers;
102 | }
103 |
104 | public static void updateCompleters(
105 | List completers,
106 | Set paths,
107 | Set resourceVars,
108 | Set pathVars) {
109 | if (!completers.isEmpty()) {
110 | completers.clear();
111 | }
112 |
113 | JlineUtils.paths.addAll(paths);
114 | JlineUtils.pathVars.addAll(pathVars);
115 | JlineUtils.resourceVars.addAll(resourceVars);
116 |
117 | addCommandCompleters(completers);
118 | addPathsCompleters(completers, paths);
119 | addVarsCompleters(completers, resourceVars, pathVars);
120 |
121 | ArgumentCompleter argumentCompleter1 =
122 | new ArgumentCompleter(
123 | new StringsCompleter(),
124 | new StringsCompleter("="),
125 | new StringsCompleter("WeCross.getResource"),
126 | NullCompleter.INSTANCE);
127 | argumentCompleter1.setStrict(false);
128 | completers.add(argumentCompleter1);
129 |
130 | ArgumentCompleter addChainAccountCompleter =
131 | new ArgumentCompleter(
132 | new StringsCompleter("addChainAccount"),
133 | new StringsCompleter(ConsoleUtils.supportChainList),
134 | new FilesCompleter(Paths.get(System.getProperty("user.dir")), true),
135 | new FilesCompleter(Paths.get(System.getProperty("user.dir")), true),
136 | NullCompleter.INSTANCE);
137 | completers.add(addChainAccountCompleter);
138 |
139 | ArgumentCompleter setDefaultAccountCompleter =
140 | new ArgumentCompleter(
141 | new StringsCompleter("setDefaultAccount"),
142 | new StringsCompleter(ConsoleUtils.supportChainList),
143 | NullCompleter.INSTANCE);
144 | completers.add(setDefaultAccountCompleter);
145 |
146 | ArgumentCompleter setDefaultChainAccountCompleter =
147 | new ArgumentCompleter(
148 | new StringsCompleter("setDefaultChainAccount"),
149 | new StringsCompleter(ConsoleUtils.supportChainList),
150 | NullCompleter.INSTANCE);
151 | completers.add(setDefaultChainAccountCompleter);
152 | }
153 |
154 | public static void addPathsCompleters(List completers, Set paths) {
155 | for (String path : paths) {
156 | addPathCompleters(completers, path);
157 | }
158 | }
159 |
160 | public static void addVarsCompleters(
161 | List completers, Set resourceVars, Set pathVars) {
162 |
163 | for (String var : resourceVars) {
164 | addResourceVarCompleters(completers, var);
165 | }
166 |
167 | for (String var : pathVars) {
168 | addPathVarCompleters(completers, var);
169 | }
170 | }
171 |
172 | public static void updatePathsCompleters(List completers, Set paths) {
173 | for (String path : paths) {
174 | if (!JlineUtils.paths.contains(path)) {
175 | addPathCompleters(completers, path);
176 | }
177 | }
178 | }
179 |
180 | public static void addPathCompleters(List completers, String path) {
181 | JlineUtils.paths.add(path);
182 |
183 | ArgumentCompleter argumentCompleter1 =
184 | new ArgumentCompleter(
185 | new StringsCompleter(),
186 | new StringsCompleter("="),
187 | new StringsCompleter(path),
188 | NullCompleter.INSTANCE);
189 | argumentCompleter1.setStrict(false);
190 | completers.add(argumentCompleter1);
191 |
192 | ArgumentCompleter argumentCompleter2 =
193 | new ArgumentCompleter(
194 | new StringsCompleter(),
195 | new StringsCompleter("="),
196 | new StringsCompleter("WeCross.getResource"),
197 | new StringsCompleter(path),
198 | NullCompleter.INSTANCE);
199 | argumentCompleter2.setStrict(false);
200 | completers.add(argumentCompleter2);
201 |
202 | completers.add(
203 | new ArgumentCompleter(
204 | new StringsCompleter(pathVarSupportedCommands),
205 | new StringsCompleter(path),
206 | NullCompleter.INSTANCE));
207 |
208 | completers.add(
209 | new ArgumentCompleter(
210 | new StringsCompleter(pathVarNotSupportedCommands),
211 | new StringsCompleter(path),
212 | NullCompleter.INSTANCE));
213 |
214 | ArgumentCompleter bcosArgumentCompleter =
215 | new ArgumentCompleter(
216 | new StringsCompleter(bcosCommands),
217 | new StringsCompleter(path),
218 | new FilesCompleter(Paths.get(System.getProperty("user.dir"), "conf")),
219 | NullCompleter.INSTANCE);
220 | completers.add(bcosArgumentCompleter);
221 |
222 | ArgumentCompleter fabricArgumentCompleter =
223 | new ArgumentCompleter(
224 | new StringsCompleter(fabricCommands),
225 | new StringsCompleter(path),
226 | new StringsCompleter(orgs),
227 | new DirectoriesCompleter(Paths.get(System.getProperty("user.dir"), "conf")),
228 | new StringsCompleter(),
229 | new StringsCompleter("GO_LANG", "JAVA"),
230 | NullCompleter.INSTANCE);
231 | fabricArgumentCompleter.setStrict(false);
232 | completers.add(fabricArgumentCompleter);
233 | }
234 |
235 | public static void addResourceVarCompleters(List completers, String resourceVar) {
236 | completers.add(
237 | new ArgumentCompleter(
238 | new StringsCompleter(resourceVar + ".call"), NullCompleter.INSTANCE));
239 | completers.add(
240 | new ArgumentCompleter(
241 | new StringsCompleter(resourceVar + ".sendTransaction"),
242 | NullCompleter.INSTANCE));
243 |
244 | completers.add(
245 | new ArgumentCompleter(
246 | new StringsCompleter(resourceVar + ".detail"), NullCompleter.INSTANCE));
247 | }
248 |
249 | public static void addPathVarCompleters(List completers, String pathVar) {
250 | ArgumentCompleter argumentCompleter2 =
251 | new ArgumentCompleter(
252 | new StringsCompleter(),
253 | new StringsCompleter("="),
254 | new StringsCompleter("WeCross.getResource"),
255 | new StringsCompleter(pathVar),
256 | NullCompleter.INSTANCE);
257 | argumentCompleter2.setStrict(false);
258 | completers.add(argumentCompleter2);
259 |
260 | completers.add(
261 | new ArgumentCompleter(
262 | new StringsCompleter(pathVarSupportedCommands),
263 | new StringsCompleter(pathVar),
264 | NullCompleter.INSTANCE));
265 | }
266 |
267 | public static void addOrgCompleters(List completers, String org) {
268 | if (!JlineUtils.orgs.contains(org)) {
269 | JlineUtils.orgs.add(org);
270 | completers.add(
271 | new ArgumentCompleter(
272 | new StringsCompleter(fabricCommands),
273 | new StringsCompleter(paths),
274 | new StringsCompleter(org),
275 | new DirectoriesCompleter(
276 | Paths.get(System.getProperty("user.dir"), "conf"), true),
277 | new StringsCompleter(contractMethods),
278 | NullCompleter.INSTANCE));
279 | }
280 | }
281 |
282 | public static void addContractMethodCompleters(
283 | List completers, String contractMethod) {
284 | if (!JlineUtils.contractMethods.contains(contractMethod)) {
285 | JlineUtils.contractMethods.add(contractMethod);
286 | completers.add(
287 | new ArgumentCompleter(
288 | new StringsCompleter(callContractCommands),
289 | new StringsCompleter(paths),
290 | new StringsCompleter(contractMethod),
291 | NullCompleter.INSTANCE));
292 | }
293 | }
294 |
295 | public static LineReader getLineReader(List completers) throws IOException {
296 |
297 | Terminal terminal =
298 | TerminalBuilder.builder()
299 | .nativeSignals(true)
300 | .signalHandler(Terminal.SignalHandler.SIG_IGN)
301 | .build();
302 | Attributes termAttribs = terminal.getAttributes();
303 |
304 | // disable CTRL+D shortcut to exit
305 | // disable CTRL+C shortcut
306 | termAttribs.setControlChar(ControlChar.VEOF, 0);
307 | termAttribs.setControlChar(ControlChar.VINTR, 0);
308 |
309 | terminal.setAttributes(termAttribs);
310 | return LineReaderBuilder.builder()
311 | .terminal(terminal)
312 | .completer(new AggregateCompleter(completers))
313 | .build()
314 | .option(LineReader.Option.HISTORY_IGNORE_SPACE, false)
315 | .option(LineReader.Option.HISTORY_REDUCE_BLANKS, false);
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/PrintUtils.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import com.webank.wecross.console.exception.ErrorCode;
5 | import com.webank.wecross.console.exception.WeCrossConsoleException;
6 | import com.webank.wecrosssdk.common.StatusCode;
7 | import com.webank.wecrosssdk.rpc.common.TransactionContext;
8 | import com.webank.wecrosssdk.rpc.methods.response.*;
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | public class PrintUtils {
15 | private static Logger logger = LoggerFactory.getLogger(PrintUtils.class);
16 |
17 | public static void printTransactionResponse(TransactionResponse response, boolean isCall)
18 | throws WeCrossConsoleException {
19 | if (response == null) {
20 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
21 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
22 | throw new WeCrossConsoleException(
23 | ErrorCode.INTERNAL_ERROR,
24 | "Error: code("
25 | + response.getErrorCode()
26 | + "), message("
27 | + response.getMessage()
28 | + ")");
29 | } else if (response.getReceipt().getErrorCode() != StatusCode.SUCCESS) {
30 | logger.warn("TxError: " + response.getReceipt().toString());
31 | throw new WeCrossConsoleException(
32 | ErrorCode.INTERNAL_ERROR,
33 | "Error: code("
34 | + response.getReceipt().getErrorCode()
35 | + "), message("
36 | + response.getReceipt().getMessage()
37 | + ")");
38 | } else {
39 | if (!isCall) {
40 | System.out.println("Txhash : " + response.getReceipt().getHash());
41 | System.out.println("BlockNum: " + response.getReceipt().getBlockNumber());
42 | System.out.println(
43 | "Result : " + stringArraysToString(response.getReceipt().getResult()));
44 | } else {
45 | System.out.println(
46 | "Result : " + stringArraysToString(response.getReceipt().getResult()));
47 | }
48 | }
49 | }
50 |
51 | public static void printRoutineResponse(XAResponse response) throws WeCrossConsoleException {
52 | if (response == null) {
53 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
54 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
55 | TransactionContext.txThreadLocal.remove();
56 | TransactionContext.pathInTransactionThreadLocal.remove();
57 | FileUtils.cleanFile(FileUtils.CONF, FileUtils.TRANSACTION_LOG_TOML);
58 | throw new WeCrossConsoleException(
59 | ErrorCode.INTERNAL_ERROR,
60 | "Error: code("
61 | + response.getErrorCode()
62 | + "), message("
63 | + response.getMessage()
64 | + ")");
65 | } else if (response.getXARawResponse().getStatus() != StatusCode.SUCCESS) {
66 | TransactionContext.txThreadLocal.remove();
67 | TransactionContext.pathInTransactionThreadLocal.remove();
68 | FileUtils.cleanFile(FileUtils.CONF, FileUtils.TRANSACTION_LOG_TOML);
69 | throw new WeCrossConsoleException(
70 | ErrorCode.INTERNAL_ERROR,
71 | Arrays.toString(response.getXARawResponse().getChainErrorMessages().toArray()));
72 | } else {
73 | System.out.println("Result: success!");
74 | }
75 | }
76 |
77 | public static void printRollbackResponse(XAResponse response) throws WeCrossConsoleException {
78 | if (response == null) {
79 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
80 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
81 | throw new WeCrossConsoleException(
82 | ErrorCode.INTERNAL_ERROR,
83 | "Error: code("
84 | + response.getErrorCode()
85 | + "), message("
86 | + response.getMessage()
87 | + ")");
88 | } else if (response.getXARawResponse().getStatus() != StatusCode.SUCCESS) {
89 | System.out.println(
90 | Arrays.toString(response.getXARawResponse().getChainErrorMessages().toArray()));
91 | } else {
92 | System.out.println("Result: success!");
93 | }
94 | }
95 |
96 | public static void printRoutineInfoResponse(XATransactionResponse response, List paths)
97 | throws Exception {
98 | if (response == null) {
99 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
100 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
101 | throw new WeCrossConsoleException(
102 | ErrorCode.INTERNAL_ERROR,
103 | "Error: code("
104 | + response.getErrorCode()
105 | + "), message("
106 | + response.getMessage()
107 | + ")");
108 | } else if (response.getRawXATransactionResponse().getXaResponse().getStatus()
109 | != StatusCode.SUCCESS) {
110 | throw new WeCrossConsoleException(
111 | ErrorCode.INTERNAL_ERROR,
112 | Arrays.toString(
113 | response.getRawXATransactionResponse()
114 | .getXaResponse()
115 | .getChainErrorMessages()
116 | .toArray()));
117 | } else {
118 | List pathList =
119 | response.getRawXATransactionResponse().getXaTransaction().getPaths();
120 | boolean checkPathFlag = true;
121 | if (pathList.size() != paths.size()) {
122 | checkPathFlag = false;
123 | } else {
124 | for (String path : paths) {
125 | if (!pathList.contains(path)) {
126 | checkPathFlag = false;
127 | break;
128 | }
129 | }
130 | }
131 | if (!checkPathFlag) {
132 | System.out.println(
133 | "ERROR: path not fit in response, please use command 'listXATransactions' to check correct transaction path.");
134 | } else {
135 | ConsoleUtils.printJson(
136 | response.getRawXATransactionResponse().getXaTransaction().toString());
137 | }
138 | }
139 | }
140 |
141 | public static void printRoutineIDResponse(XATransactionListResponse response) throws Exception {
142 | if (response == null) {
143 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
144 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
145 | throw new WeCrossConsoleException(
146 | ErrorCode.INTERNAL_ERROR,
147 | "Error: code("
148 | + response.getErrorCode()
149 | + "), message("
150 | + response.getMessage()
151 | + ")");
152 | } else {
153 | ObjectMapper objectMapper = new ObjectMapper();
154 | System.out.println(
155 | "Result: "
156 | + objectMapper
157 | .writerWithDefaultPrettyPrinter()
158 | .writeValueAsString(
159 | response.getRawXATransactionListResponse()
160 | .getXaList()));
161 | }
162 | }
163 |
164 | public static void printCommandResponse(CommandResponse response)
165 | throws WeCrossConsoleException {
166 | logger.debug("response: {}", response.getResult());
167 | if (response == null) {
168 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
169 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
170 | throw new WeCrossConsoleException(
171 | ErrorCode.INTERNAL_ERROR,
172 | "Error: code("
173 | + response.getErrorCode()
174 | + "), message("
175 | + response.getMessage()
176 | + ")");
177 | } else {
178 | System.out.println("Result: " + response.getResult());
179 | }
180 | }
181 |
182 | public static void printUAResponse(UAResponse response) throws WeCrossConsoleException {
183 | if (response == null) {
184 | throw new WeCrossConsoleException(ErrorCode.NO_RESPONSE, "Error: no response");
185 | } else if (response.getErrorCode() != StatusCode.SUCCESS) {
186 | throw new WeCrossConsoleException(
187 | ErrorCode.INTERNAL_ERROR,
188 | "Error: code("
189 | + response.getErrorCode()
190 | + "), message("
191 | + response.getMessage()
192 | + ")");
193 | } else if (response.getUAReceipt().getErrorCode() != StatusCode.SUCCESS) {
194 | logger.warn("UAResponse: " + response.getUAReceipt().toString());
195 | throw new WeCrossConsoleException(
196 | ErrorCode.INTERNAL_ERROR,
197 | "Error: code("
198 | + response.getUAReceipt().getErrorCode()
199 | + "), message("
200 | + response.getUAReceipt().getMessage()
201 | + ")");
202 | } else {
203 | System.out.println("Result: " + response.getUAReceipt().getMessage());
204 | if (response.getUAReceipt().getUniversalAccount() != null) {
205 | ConsoleUtils.doubleLine();
206 | System.out.println(response.getUAReceipt().getUniversalAccount().toFormatString());
207 | }
208 | }
209 | }
210 |
211 | /**
212 | * specific string arrays toString method, empty string "" should be shown
213 | *
214 | * @param a array to print
215 | * @return string format of a
216 | */
217 | public static String stringArraysToString(String[] a) {
218 | if (a == null) return "null";
219 |
220 | int iMax = a.length - 1;
221 | if (iMax == -1) return "[]";
222 |
223 | StringBuilder b = new StringBuilder();
224 | b.append('[');
225 | for (int i = 0; ; i++) {
226 | if ("".equals(a[i])) {
227 | b.append("\"\"");
228 | } else {
229 | b.append(a[i]);
230 | }
231 | if (i == iMax) return b.append(']').toString();
232 | b.append(", ");
233 | }
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/TarUtils.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.nio.file.Paths;
9 | import java.util.Base64;
10 | import java.util.Collection;
11 | import org.apache.commons.compress.archivers.ArchiveEntry;
12 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
13 | import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
14 | import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
15 | import org.apache.commons.io.FilenameUtils;
16 | import org.apache.commons.io.IOUtils;
17 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
18 |
19 | public class TarUtils {
20 |
21 | // Huuugggeee hole here!!! the path in tar.gz must start with src/ and then with pathPrefix
22 | public static final String goPrefix = "src/chaincode";
23 |
24 | /**
25 | * Generate a targz inputstream from source folder.
26 | *
27 | * @param src Source location
28 | * @param pathPrefix prefix to add to the all files found.
29 | * @return return inputstream.
30 | * @throws IOException
31 | */
32 | private static byte[] generateTarGzInputStreamBytes(File src, String pathPrefix)
33 | throws IOException {
34 |
35 | File sourceDirectory = src;
36 |
37 | ByteArrayOutputStream bos = new ByteArrayOutputStream(500000);
38 |
39 | String sourcePath = sourceDirectory.getAbsolutePath();
40 |
41 | TarArchiveOutputStream archiveOutputStream =
42 | new TarArchiveOutputStream(
43 | new GzipCompressorOutputStream(new BufferedOutputStream(bos)));
44 | archiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
45 |
46 | try {
47 | Collection childrenFiles =
48 | org.apache.commons.io.FileUtils.listFiles(sourceDirectory, null, true);
49 |
50 | ArchiveEntry archiveEntry;
51 | FileInputStream fileInputStream;
52 | for (File childFile : childrenFiles) {
53 | String childPath = childFile.getAbsolutePath();
54 | String relativePath =
55 | childPath.substring((sourcePath.length() + 1), childPath.length());
56 |
57 | if (pathPrefix != null) {
58 | relativePath = Paths.get(pathPrefix, relativePath).toString();
59 | }
60 |
61 | relativePath = FilenameUtils.separatorsToUnix(relativePath);
62 |
63 | archiveEntry = new TarArchiveEntry(childFile, relativePath);
64 | fileInputStream = new FileInputStream(childFile);
65 | archiveOutputStream.putArchiveEntry((TarArchiveEntry) archiveEntry);
66 |
67 | try {
68 | IOUtils.copy(fileInputStream, archiveOutputStream);
69 | } finally {
70 | IOUtils.closeQuietly(fileInputStream);
71 | archiveOutputStream.closeArchiveEntry();
72 | }
73 | }
74 | } finally {
75 | IOUtils.closeQuietly(archiveOutputStream);
76 | }
77 |
78 | return bos.toByteArray();
79 | }
80 |
81 | public static byte[] generateTarGzInputStreamBytes(String path, String pathPrefix)
82 | throws IOException {
83 | System.out.println("path: " + path);
84 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
85 |
86 | File file = resolver.getResource(path).getFile();
87 | return generateTarGzInputStreamBytes(
88 | file, pathPrefix); // Inside tar.gz is: src/chaincode/
89 | }
90 |
91 | public static byte[] generateTarGzInputStreamBytesFoGoChaincode(String path)
92 | throws IOException {
93 | System.out.println("path: " + path);
94 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
95 |
96 | File file = resolver.getResource(path).getFile();
97 | return generateTarGzInputStreamBytes(
98 | file, goPrefix); // Inside tar.gz is: src/chaincode/
99 | }
100 |
101 | public static String generateTarGzInputStreamEncodedString(String path) throws IOException {
102 | return Base64.getEncoder().encodeToString(generateTarGzInputStreamBytes(path, ""));
103 | }
104 |
105 | public static String generateTarGzInputStreamEncodedStringFoGoChaincode(String path)
106 | throws IOException {
107 |
108 | return Base64.getEncoder().encodeToString(generateTarGzInputStreamBytes(path, goPrefix));
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/TransactionInfo.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | import java.util.List;
4 |
5 | public class TransactionInfo {
6 | String transactionID;
7 | List paths;
8 |
9 | public TransactionInfo(String transactionID, List paths) {
10 | this.transactionID = transactionID;
11 | this.paths = paths;
12 | }
13 |
14 | public TransactionInfo() {}
15 |
16 | public String getTransactionID() {
17 | return transactionID;
18 | }
19 |
20 | public void setTransactionID(String transactionID) {
21 | this.transactionID = transactionID;
22 | }
23 |
24 | public List getPaths() {
25 | return paths;
26 | }
27 |
28 | public void setPaths(List paths) {
29 | this.paths = paths;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | StringBuilder sb = new StringBuilder();
35 | sb.append(transactionID).append(" ");
36 | for (String path : paths) {
37 | sb.append(path).append(" ");
38 | }
39 | return sb.toString();
40 | }
41 |
42 | public String toPathString() {
43 | StringBuilder sb = new StringBuilder();
44 | for (String path : paths) {
45 | sb.append(path).append(" ");
46 | }
47 | return sb.toString();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/Version.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | public class Version {
4 |
5 | public static final String Version = "v1.4.0";
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/common/WelcomeInfo.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.common;
2 |
3 | public class WelcomeInfo {
4 |
5 | public static void welcome() {
6 | ConsoleUtils.doubleLine();
7 | System.out.println("Welcome to WeCross console(" + Version.Version + ")!");
8 | System.out.println("Type 'help' or 'h' for help. Type 'quit' or 'q' to quit console.");
9 | System.out.println();
10 | ConsoleUtils.doubleLine();
11 | }
12 |
13 | public static void help(String[] params) {
14 | if (HelpInfo.promptNoParams(params, "help")) {
15 | return;
16 | }
17 | if (params.length > 2) {
18 | HelpInfo.promptHelp("help");
19 | return;
20 | }
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(
23 | "------------------------------------------ Account ------------------------------------------\n");
24 | sb.append("login Login SDK if you have already registered.\n");
25 | sb.append("logout Logout SDK.\n");
26 | sb.append("listAccount List your Universal Account's information.\n");
27 | sb.append("registerAccount Register a Universal Account.\n");
28 | sb.append(
29 | "addChainAccount Add a Chain Account to your Universal Account.\n");
30 | sb.append(
31 | "setDefaultAccount Set the chain account to be the default account to send transaction.\n");
32 |
33 | sb.append(
34 | "\n------------------------------------ Resource Operation -------------------------------------\n");
35 | sb.append(
36 | "listResources List all resources including remote resources.\n");
37 | sb.append(
38 | "listLocalResources List local resources configured by WeCross server.\n");
39 | sb.append("detail Get resource information.\n");
40 |
41 | sb.append("call Call constant method of smart contract.\n");
42 | sb.append("sendTransaction Call non-constant method of smart contract.\n");
43 | sb.append(
44 | "WeCross.getResource Init resource by path, and assign it to a custom variable.\n");
45 | sb.append("[resource].[command] Equal to: command [path].\n");
46 |
47 | sb.append(
48 | "\n---------------------------------------- XA Routine -----------------------------------------\n");
49 | sb.append("startTransaction Start an xa transaction.\n");
50 | sb.append(
51 | "invoke Call non-constant method of smart contract, will auto-transfer to command execTransaction during transaction.\n");
52 | sb.append(
53 | "callTransaction Call constant method of smart contract during transaction.\n");
54 | sb.append(
55 | "execTransaction Call non-constant method of smart contract during transaction.\n");
56 | sb.append("commitTransaction Commit an xa transaction.\n");
57 | sb.append("rollbackTransaction Rollback an xa transaction.\n");
58 | sb.append("loadTransaction Load a specified transaction context.\n");
59 | sb.append("getXATransaction Get info of specified XA transaction.\n");
60 | sb.append("listXATransactions List XA transactions in route.\n");
61 |
62 | sb.append(
63 | "\n--------------------------------------- HTLC Routine ----------------------------------------\n");
64 | sb.append("genTimelock Generate two valid timelocks.\n");
65 | sb.append("genSecretAndHash Generate a secret and its hash.\n");
66 | sb.append("newHTLCProposal Create a htlc transfer proposal .\n");
67 | sb.append("checkTransferStatus Check htlc transfer status by hash.\n");
68 | sb.append("getCurrentTransactionID Get Current xa Transaction ID.\n");
69 |
70 | sb.append(
71 | "\n----------------------- Extended commands only used for certain chain -----------------------\n");
72 | sb.append("bcosDeploy Deploy contract in BCOS chain.\n");
73 | sb.append("bcosRegister Register contract abi in BCOS chain.\n");
74 | sb.append("fabricInstall Install chaincode in fabric chain.\n");
75 | sb.append("fabricInstantiate Instantiate chaincode in fabric chain.\n");
76 | sb.append("fabricUpgrade Upgrade chaincode in fabric chain.\n");
77 |
78 | sb.append(
79 | "\n------------------------------------------ Others -------------------------------------------\n");
80 | sb.append("supportedStubs List supported stubs of WeCross router.\n");
81 | sb.append("quit Quit console.\n");
82 |
83 | System.out.println(sb.toString());
84 | ConsoleUtils.singleLine();
85 | System.out.println();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/webank/wecross/console/custom/BCOSCommand.java:
--------------------------------------------------------------------------------
1 | package com.webank.wecross.console.custom;
2 |
3 | import com.webank.wecross.console.common.ConsoleUtils;
4 | import com.webank.wecross.console.common.FileUtils;
5 | import com.webank.wecross.console.common.HelpInfo;
6 | import com.webank.wecross.console.common.PrintUtils;
7 | import com.webank.wecross.console.exception.ErrorCode;
8 | import com.webank.wecross.console.exception.WeCrossConsoleException;
9 | import com.webank.wecrosssdk.rpc.WeCrossRPC;
10 | import com.webank.wecrosssdk.rpc.common.ResourceDetail;
11 | import com.webank.wecrosssdk.rpc.methods.response.CommandResponse;
12 | import com.webank.wecrosssdk.rpc.methods.response.ResourceResponse;
13 | import com.webank.wecrosssdk.utils.RPCUtils;
14 | import java.io.File;
15 | import java.util.*;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
19 |
20 | public class BCOSCommand {
21 | private static final Logger logger = LoggerFactory.getLogger(BCOSCommand.class);
22 | private WeCrossRPC weCrossRPC;
23 |
24 | public BCOSCommand(WeCrossRPC weCrossRPC) {
25 | this.weCrossRPC = weCrossRPC;
26 | }
27 |
28 | /**
29 | * deploy contract
30 | *
31 | * @params BCOSDeploy [path] [filePath] [className] [version]
32 | */
33 | public void deploy(String[] params) throws Exception {
34 | if (params.length == 1) {
35 | throw new WeCrossConsoleException(ErrorCode.PARAM_MISSING, "bcosDeploy");
36 | }
37 | if ("-h".equals(params[1]) || "--help".equals(params[1])) {
38 | HelpInfo.BCOSDeployHelp();
39 | return;
40 | }
41 | if (params.length < 4) {
42 | throw new WeCrossConsoleException(ErrorCode.PARAM_MISSING, "bcosDeploy");
43 | }
44 |
45 | String path = params[1];
46 | String chain = path.substring(0, path.lastIndexOf('.') + 1);
47 | RPCUtils.checkPath(path);
48 | String stubType = "";
49 | ResourceResponse resources = weCrossRPC.listResources(false).send();
50 | for (ResourceDetail resourceDetail : resources.getResources().getResourceDetails()) {
51 | if (resourceDetail.getPath().startsWith(chain)) {
52 | stubType = resourceDetail.getStubType();
53 | break;
54 | }
55 | }
56 | if (stubType.equals("")) {
57 | throw new WeCrossConsoleException(ErrorCode.INVALID_PATH, path);
58 | }
59 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
60 | List