├── .circleci
├── config.yml
└── main.sh
├── .gitignore
├── .idea
└── vcs.xml
├── LICENSE
├── LICENSE-HEADER
├── NETWORK-TOU.md
├── README.md
├── build-binaries.sh
├── build.sh
├── config.go
├── crypto
└── digest
│ └── receipt_proof.go
├── docker.go
├── docker_test.go
├── gammacli-linux-install-v0.7.0.sh
├── go.mod
├── go.sum
├── help.go
├── is_ready.go
├── jsoncodec
├── args.go
├── args_test.go
├── config.go
├── events.go
├── keys.go
├── read.go
├── send_tx.go
├── tx_proof.go
└── tx_status.go
├── keys.go
├── main.go
├── marketplace
├── gamma-devkit-google-deployment-guide.md
├── images
│ ├── step01.png
│ ├── step02.png
│ ├── step03.png
│ ├── step04.png
│ ├── step05.png
│ ├── step06.png
│ ├── step07.png
│ ├── step08.png
│ ├── step09.png
│ ├── step10.png
│ ├── step11.png
│ ├── step12.png
│ ├── step13.png
│ ├── step14.png
│ ├── step15.png
│ ├── step16.png
│ ├── step17.png
│ └── step18.png
└── setup.sh
├── public_api.go
├── test.sh
└── test
├── _arguments
└── arguments.go
├── _corrupt
└── corrupt.go
├── _counter
└── contract.go
├── arguments-check.json
├── arguments-get.json
├── arguments_test.go
├── config_override_test.go
├── counter-add.json
├── counter-get.json
├── deploy_test.go
├── generate_config.py
├── get-balance.json
├── harness.go
├── help_test.go
├── restart_test.go
├── token_test.go
├── transfer-direct.json
├── transfer.json
└── upgrade_test.go
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | machine: true
5 | steps:
6 | - checkout
7 | - run: ./.circleci/main.sh
8 |
9 | workflows:
10 | version: 2
11 | build:
12 | jobs:
13 | - build
14 |
--------------------------------------------------------------------------------
/.circleci/main.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -xe
2 |
3 | PROJ_PATH=`pwd`
4 | GO_VERSION="1.12.6"
5 |
6 | # First let's install Go 1.11
7 | echo "Installing Go $GO_VERSION..."
8 | cd /tmp
9 |
10 | curl -O https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz
11 | sudo tar -xf go${GO_VERSION}.linux-amd64.tar.gz
12 |
13 | # Uninstall older version of Go
14 | sudo rm -rf /usr/local/go
15 | sudo mv go /usr/local
16 |
17 | export GOROOT=/usr/local/go
18 | export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
19 |
20 | cd $PROJ_PATH
21 |
22 | ./test.sh
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Go ###
2 | # Binaries for programs and plugins
3 | *.exe
4 | *.exe~
5 | *.dll
6 | *.so
7 | *.dylib
8 |
9 | # Test binary, build with `go test -c`
10 | *.test
11 |
12 | # Output of the go coverage tool, specifically when used with LiteIDE
13 | *.out
14 |
15 | ### Intellij/GoLand ###
16 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
17 | # Ignore all XML files except run configurations
18 | .idea/**/*.xml
19 | !.idea/runConfigurations/*.xml
20 |
21 | .idea/**/*.iml
22 |
23 | ## To re-enable a specific XML file within .idea, use the following pattern (remove the leading #)
24 | # !.idea/vcs.xml
25 |
26 | # CMake
27 | cmake-build-debug/
28 |
29 | # Mongo Explorer plugin:
30 | .idea/**/mongoSettings.xml
31 |
32 | ## File-based project format:
33 | *.iws
34 |
35 | ## Plugin-specific files:
36 |
37 | # IntelliJ
38 | /out/
39 |
40 | # mpeltonen/sbt-idea plugin
41 | .idea_modules/
42 |
43 | # JIRA plugin
44 | atlassian-ide-plugin.xml
45 |
46 | # Cursive Clojure plugin
47 | .idea/replstate.xml
48 |
49 | # Ruby plugin and RubyMine
50 | /.rakeTasks
51 |
52 | # Crashlytics plugin (for Android Studio and IntelliJ)
53 | com_crashlytics_export_strings.xml
54 | crashlytics.properties
55 | crashlytics-build.properties
56 | fabric.properties
57 |
58 | ### Intellij Patch ###
59 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
60 |
61 | # *.iml
62 | # modules.xml
63 | # .idea/misc.xml
64 | # *.ipr
65 |
66 | # Sonarlint plugin
67 | .idea/sonarlint
68 |
69 | .DS_Store
70 |
71 | # Logs
72 | *.log
73 | logs/
74 |
75 | orbs-test-keys.json
76 | _bin
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Orbs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE-HEADER:
--------------------------------------------------------------------------------
1 | Copyright 2019 the gamma-cli authors
2 | This file is part of the gamma-cli library in the Orbs project.
3 |
4 | This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | The above notice should be included in all copies or substantial portions of the software.
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gamma - Personal Orbs Blockchain for Developers
2 |
3 | [](https://circleci.com/gh/orbs-network/gamma-cli)
4 |
5 | Gamma is a personal Orbs blockchain that allows developers to easily test, run and deploy smart contracts.
6 |
7 | `Gamma server` - runs an in-memory virtual chain on top of an Orbs blockchain with several nodes on your local machine.
8 |
9 | `gamma-cli` - command line tool for developers to interact with a Gamma server instance running on their machine.
10 |
11 |
12 | ## Detailed documentation
13 |
14 | The detailed documentation website for Gamma is available here:
15 |
16 | https://orbs.gitbook.io
17 |
18 | ## Quick start
19 |
20 |
21 | Mac
22 |
23 | ### Prerequisites
24 | * Make sure [brew](https://brew.sh/) is available on your machine.
25 | * Make sure [Docker](https://docs.docker.com/docker-for-mac/install/) is installed on your machine.
26 | * If you're planning to develop your own smart contracts in Go
27 | * Install [Go language](https://golang.org/doc/install#macos)
28 | * Install the [Orbs Smart Contract SDK](https://github.com/orbs-network/orbs-contract-sdk#installation)
29 |
30 | ### Installation
31 | 1. To install the command line tool, run the following command in terminal:
32 | ```
33 | brew install orbs-network/devtools/gamma-cli
34 | ```
35 | > To verify the installation, run in terminal `gamma-cli version`
36 |
37 | 2. Gamma server will automatically be installed the first time you start it with `gamma-cli start-local`
38 |
39 | ### Starting and stopping Gamma server
40 |
41 | * Start Gamma server by running in terminal:
42 | ```
43 | gamma-cli start-local
44 | ```
45 | * When finished working with the server, stop it by running in terminal:
46 | ```
47 | gamma-cli stop-local
48 | ```
49 | > Note: The local blockchain instance is running in-memory. The next time you start the instance, all contracts and state will disappear from memory and you will need to deploy them again.
50 |
51 |
52 |
53 |
54 | Windows
55 |
56 | ### Prerequisites
57 | * Make sure [Docker](https://www.docker.com/products/docker-desktop) is installed on your machine.
58 | * If you're planning to develop your own smart contracts in Go
59 | * Install [Go language](https://golang.org/doc/install#windows)
60 | * Install the [Orbs Smart Contract SDK](https://github.com/orbs-network/orbs-contract-sdk#installation)
61 |
62 | ### Installation
63 | * Download latest version of Gamma from [releases](https://github.com/orbs-network/gamma-cli/releases)
64 | * Extract the archive to `Program Files`
65 | * Edit `$profile` settings of PowerShell
66 | * Create a file: `C:\Users\\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` or edit it.
67 | * Add the following content:
68 | ```bash
69 | Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
70 | New-Alias gamma-cli 'C:\Program Files\gammacli-windows-v0.7.0\_bin\gamma-cli.exe'
71 | ```
72 | * Verify the installation: open PowerShell and run `gamma-cli version`. You should see the current version, e.g. `v0.7.0`
73 |
74 | ### Starting and stopping Gamma server
75 |
76 | * Start Gamma server by running in terminal:
77 | ```
78 | gamma-cli start-local
79 | ```
80 | * When finished working with the server, stop it by running in terminal:
81 | ```
82 | gamma-cli stop-local
83 | ```
84 | > Note: The local blockchain instance is running in-memory. The next time you start the instance, all contracts and state will disappear from memory and you will need to deploy them again.
85 |
86 |
87 |
88 |
89 | ## Commands
90 |
91 | ```
92 | Usage:
93 |
94 | gamma-cli COMMAND [OPTIONS]
95 |
96 | Commands:
97 |
98 | start-local start a local Orbs personal blockchain instance listening on port
99 | options: -port
100 | example: gamma-cli start-local -port 8080
101 |
102 | stop-local stop a locally running Orbs personal blockchain instance
103 |
104 | gen-test-keys generate a new batch of 10 test keys and store in orbs-test-keys.json (default filename)
105 | options: -keys [OUTPUT_FILE]
106 | example: gamma-cli gen-test-keys -keys orbs-test-keys.json
107 |
108 | deploy deploy a smart contract with the code specified in the source file
109 | options: -name [CONTRACT_NAME] -signer [ID_FROM_KEYS_JSON]
110 | example: gamma-cli deploy MyToken.go -signer user1
111 | gamma-cli deploy contract.go -name MyToken
112 |
113 | send-tx sign and send the transaction specified in the JSON file
114 | options: -arg# [OVERRIDE_ARG_#] -signer [ID_FROM_KEYS_JSON]
115 | example: gamma-cli send-tx transfer.json -signer user1
116 | gamma-cli send-tx transfer.json -arg2 0x5B63Ca66637316A0D7f84Ebf60E50963c10059aD
117 |
118 | run-query read state or run a read-only contract method as specified in the JSON file
119 | options: -arg# [OVERRIDE_ARG_#] -signer [ID_FROM_KEYS_JSON]
120 | example: gamma-cli run-query get-balance.json -signer user1
121 | gamma-cli run-query get-balance.json -arg1 0x5B63Ca66637316A0D7f84Ebf60E50963c10059aD
122 |
123 | tx-status get the current status of a sent transaction with txid (from send-tx response)
124 | options:
125 | example: gamma-cli tx-status 0xB68fa95B7f397815Ddf41150d79b27a888448a22e08DeAf8600E7a495c406303659f8C3782614660
126 |
127 | tx-proof get cryptographic proof for transaction receipt with txid (from send-tx response)
128 | options:
129 | example: gamma-cli tx-proof 0xB68fa95B7f397815Ddf41150d79b27a888448a22e08DeAf8600E7a495c406303659f8C3782614660
130 |
131 | upgrade-server upgrade to the latest stable version of Gamma server
132 | example: gamma-cli upgrade-server
133 | gamma-cli upgrade-server -env experimental
134 |
135 | logs streams logs from gamma that are printed by smart contract to stdout (i.e. println())
136 |
137 | version print gamma-cli and Gamma server versions
138 |
139 | help print this help screen
140 |
141 |
142 | Options:
143 |
144 | -config string
145 | path to config file (default "orbs-gamma-config.json")
146 | -env string
147 | environment from config file containing server connection details (default "local")
148 | -keys string
149 | name of the json file containing test keys (default "orbs-test-keys.json")
150 | -name string
151 | name of the smart contract being deployed
152 | -port int
153 | listening port for Gamma server (default "8080")
154 | -signer string
155 | id of the signing key from the test key json (default "user1")
156 | -wait
157 | wait until Gamma server is ready and listening
158 |
159 | Multiple environments (eg. local and testnet) can be defined in orbs-gamma-config.json configuration file.
160 | See https://orbs.gitbook.io for more info.
161 | ```
162 |
163 | ## Upgrading to latest stable versions (Mac)
164 |
165 | * Upgrade to the latest version of `gamma-cli` by running in terminal:
166 |
167 | ```
168 | brew upgrade gamma-cli
169 | ```
170 |
171 | * Upgrade to the latest version of Gamma server by running in terminal:
172 |
173 | ```
174 | gamma-cli upgrade-server
175 | ```
176 |
177 | ## Working with latest dev versions (experimental)
178 |
179 | * Upgrade to the latest dev version of `gamma-cli` by running in terminal:
180 |
181 | ```
182 | brew upgrade gamma-cli --devel
183 | ```
184 |
185 | * Upgrade to the latest dev version of Gamma server by running in terminal:
186 |
187 | ```
188 | gamma-cli upgrade-server -env experimental
189 | ```
190 |
191 | * Start the experimental Gamma server by running in terminal:
192 |
193 | ```
194 | gamma-cli start-local -env experimental
195 | ```
196 |
197 | ## Advanced debugging
198 |
199 | * In order to investigate backend issues in Gamma server itself, gain access to the server logs of the currently running instance by running in terminal:
200 |
201 | ```
202 | docker logs -f orbs-gamma-server
203 | ```
204 |
205 | ## Working with Gamma server using client SDK
206 |
207 | Instead of deploying contracts and sending transactions using `gamma-cli`, you can also use any of the client SDKs (like [JavaScript Client SDK](https://github.com/orbs-network/orbs-client-sdk-javascript), [Go Client SDK](https://github.com/orbs-network/orbs-client-sdk-go)) to communicate with Gamma server.
208 |
209 | Start Gamma server on some port (eg. 8080), and then use the following endpoint in the client SDK:
210 |
211 | ```
212 | http://localhost:8080
213 | VIRTUAL_CHAIN_ID = 42
214 | ```
215 |
216 | Provide the client SDK with virtual chain ID of `42` as this is the pre-defined ID of the virtual chain running inside Gamma server. You can usually see a working example in the [E2E test](https://github.com/orbs-network/orbs-client-sdk-javascript/blob/master/e2e/nodejs/e2e.test.js) of each client SDK.
217 |
218 | ## Installing Gamma Docker image directly
219 |
220 | Instead of installing Gamma server using `gamma-cli`, you can also install Gamma server directly from [Docker Hub](https://hub.docker.com/r/orbsnetwork/gamma/tags). This is particularly useful when running on CI:
221 |
222 | ```
223 | docker pull orbsnetwork/gamma:v1.3.12 # specific version
224 | docker pull orbsnetwork/gamma # latest stable version
225 | docker pull orbsnetwork/gamma:experimental # latest experimental version
226 | ```
227 |
228 |
229 |
230 | ## License
231 |
232 | MIT
233 |
--------------------------------------------------------------------------------
/build-binaries.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | rm -rf ./_bin
3 |
4 | mkdir -p ./_bin
5 |
6 | VERSION="v0.11.1"
7 |
8 | echo "\n\n*** MAC:"
9 | GOOS=darwin GOARCH=amd64 go build -ldflags "-w -extldflags '-static' -X main.GAMMA_CLI_VERSION=$VERSION" -tags "usergo netgo" -o _bin/gamma-cli
10 | tar -zcvf ./_bin/gammacli-mac-$VERSION.tar.gz ./_bin/gamma-cli
11 | rm ./_bin/gamma-cli
12 |
13 | echo "\n\n*** LINUX (x86-64):"
14 | GOOS=linux GOARCH=amd64 go build -ldflags "-w -extldflags '-static' -X main.GAMMA_CLI_VERSION=$VERSION" -tags "usergo netgo" -o _bin/gamma-cli
15 | tar -zcvf ./_bin/gammacli-linux-x86-64-$VERSION.tar.gz ./_bin/gamma-cli
16 | rm ./_bin/gamma-cli
17 |
18 | echo "\n\n*** LINUX (i386):"
19 | GOOS=linux GOARCH=386 go build -ldflags "-w -extldflags '-static' -X main.GAMMA_CLI_VERSION=$VERSION" -tags "usergo netgo" -o _bin/gamma-cli
20 | tar -zcvf ./_bin/gammacli-linux-i386-$VERSION.tar.gz ./_bin/gamma-cli
21 | rm ./_bin/gamma-cli
22 |
23 | echo "\n\n*** WINDOWS:"
24 | GOOS=windows GOARCH=386 go build -ldflags "-w -extldflags '-static' -X main.GAMMA_CLI_VERSION=$VERSION" -tags "usergo netgo" -o _bin/gamma-cli.exe
25 | zip -r ./_bin/gammacli-windows-$VERSION.zip ./_bin/gamma-cli.exe
26 | rm ./_bin/gamma-cli.exe
27 |
28 | cd ./_bin
29 |
30 | openssl sha256 gammacli-mac-$VERSION.tar.gz >> ./checksums.txt
31 | openssl sha256 gammacli-linux-x86-64-$VERSION.tar.gz >> ./checksums.txt
32 | openssl sha256 gammacli-linux-i386-$VERSION.tar.gz >> ./checksums.txt
33 | openssl sha256 gammacli-windows-$VERSION.zip >> ./checksums.txt
34 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -xe
2 | rm -rf ./_bin
3 |
4 | mkdir -p ./_bin
5 | go build -o _bin/gamma-cli
--------------------------------------------------------------------------------
/config.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "github.com/orbs-network/gamma-cli/jsoncodec"
11 | "io/ioutil"
12 | )
13 |
14 | func getDefaultLocalConfig() *jsoncodec.ConfEnv {
15 | return &jsoncodec.ConfEnv{
16 | VirtualChain: 42,
17 | Endpoints: []string{"localhost"},
18 | }
19 | }
20 |
21 | func getDefaultExperimentalConfig() *jsoncodec.ConfEnv {
22 | return &jsoncodec.ConfEnv{
23 | VirtualChain: 42,
24 | Endpoints: []string{"localhost"},
25 | Experimental: true,
26 | }
27 | }
28 |
29 | func getDefaultConfigForEnv(env string) *jsoncodec.ConfEnv {
30 | if env == LOCAL_ENV_ID {
31 | return getDefaultLocalConfig()
32 | }
33 | if env == EXPERIMENTAL_ENV_ID {
34 | return getDefaultExperimentalConfig()
35 | }
36 | return nil
37 | }
38 |
39 | func getEnvironmentFromConfigFile(env string) *jsoncodec.ConfEnv {
40 | bytes, err := ioutil.ReadFile(*flagConfigFile)
41 | if err != nil {
42 | if res := getDefaultConfigForEnv(env); res != nil {
43 | return res
44 | }
45 | die("Could not open config file '%s' containing environment details.\n\n%s", *flagConfigFile, err.Error())
46 | }
47 |
48 | confFile, err := jsoncodec.UnmarshalConfFile(bytes)
49 | if err != nil {
50 | die("Failed parsing config json file '%s'.\n\n%s", *flagConfigFile, err.Error())
51 | }
52 |
53 | if len(confFile.Environments) == 0 {
54 | if res := getDefaultConfigForEnv(env); res != nil {
55 | return res
56 | }
57 | die("Key 'Environments' does not contain data in config file '%s'.", *flagConfigFile)
58 | }
59 |
60 | confEnv, found := confFile.Environments[env]
61 | if !found {
62 | if res := getDefaultConfigForEnv(env); res != nil {
63 | return res
64 | }
65 | die("Environment with id '%s' not found in config file '%s'.", env, *flagKeyFile)
66 | }
67 |
68 | return confEnv
69 | }
70 |
--------------------------------------------------------------------------------
/crypto/digest/receipt_proof.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package digest
8 |
9 | import (
10 | "github.com/orbs-network/lean-helix-go"
11 | "github.com/orbs-network/orbs-spec/types/go/primitives"
12 | "github.com/orbs-network/orbs-spec/types/go/protocol"
13 | "github.com/pkg/errors"
14 | )
15 |
16 | func GetBlockSignersFromReceiptProof(packedProof primitives.PackedReceiptProof) ([]primitives.NodeAddress, error) {
17 | var res []primitives.NodeAddress
18 | receiptProof := protocol.ReceiptProofReader(packedProof)
19 | switch receiptProof.BlockProof().Type() {
20 | case protocol.RESULTS_BLOCK_PROOF_TYPE_LEAN_HELIX:
21 | leanHelixBlockProof := receiptProof.BlockProof().LeanHelix()
22 | memberIds, err := leanhelix.GetMemberIdsFromBlockProof(leanHelixBlockProof)
23 | if err != nil {
24 | return nil, err
25 | }
26 | for _, memberId := range memberIds {
27 | res = append(res, primitives.NodeAddress(memberId))
28 | }
29 | return res, nil
30 | case protocol.RESULTS_BLOCK_PROOF_TYPE_BENCHMARK_CONSENSUS:
31 | benchmarkConsensusBlockProof := receiptProof.BlockProof().BenchmarkConsensus()
32 | iterator := benchmarkConsensusBlockProof.NodesIterator()
33 | for iterator.HasNext() {
34 | res = append(res, iterator.NextNodes().SenderNodeAddress())
35 | }
36 | return res, nil
37 | }
38 | return nil, errors.Errorf("unknown block proof type: %v", receiptProof.BlockProof().Type())
39 | }
40 |
--------------------------------------------------------------------------------
/docker.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "bufio"
11 | "encoding/json"
12 | "fmt"
13 | "github.com/pkg/errors"
14 | "io/ioutil"
15 | "net/http"
16 | "os"
17 | "os/exec"
18 | "regexp"
19 | "runtime"
20 | "strconv"
21 | "strings"
22 | )
23 |
24 | const DOCKER_TAG_NOT_FOUND = "not found"
25 | const DOCKER_TAG_EXPERIMENTAL = "experimental"
26 |
27 | func commandStartLocal(requiredOptions []string) {
28 | commandStartLocalContainer(gammaHandlerOptions(), requiredOptions)
29 |
30 | if prismEnabled() {
31 | commandStartLocalContainer(prismHandlerOptions(), requiredOptions)
32 | }
33 | }
34 |
35 | func commandStopLocal(requiredOptions []string) {
36 | commandStopLocalContainer(gammaHandlerOptions(), requiredOptions)
37 |
38 | if prismEnabled() {
39 | commandStopLocalContainer(prismHandlerOptions(), requiredOptions)
40 | }
41 | }
42 |
43 | func commandUpgrade(requiredOptions []string) {
44 | gammaUpgraded := commandUpgradeImage(gammaHandlerOptions(), requiredOptions)
45 | prismUpgraded := commandUpgradeImage(prismHandlerOptions(), requiredOptions)
46 | if (gammaUpgraded || prismUpgraded) &&
47 | isDockerContainerRunning(gammaHandlerOptions().containerName) {
48 | if !isDockerContainerRunning(prismHandlerOptions().containerName) {
49 | noPrism := true
50 | flagNoUi = &noPrism
51 | }
52 |
53 | commandStopLocal(requiredOptions)
54 | commandStartLocal(requiredOptions)
55 | }
56 | }
57 |
58 | func commandStartLocalContainer(dockerOptions handlerOptions, requiredOptions []string) {
59 | version := verifyDockerInstalled(dockerOptions, dockerOptions.dockerRegistryTagsUrl)
60 |
61 | if !doesFileExist(*flagKeyFile) {
62 | commandGenerateTestKeys(nil)
63 | }
64 |
65 | if isDockerContainerRunning(dockerOptions.containerName) {
66 | log(`
67 | *********************************************************************************
68 | %s is already running!
69 |
70 | Run 'gamma-cli help' in terminal to learn how to interact with this instance.
71 |
72 | **********************************************************************************
73 | `, dockerOptions.name)
74 | exit()
75 | }
76 |
77 | if err := createDockerNetwork(); err != nil {
78 | die("could not create docker network gamma: %s", err)
79 | }
80 |
81 | p := fmt.Sprintf("%d:%d", dockerOptions.port, dockerOptions.containerPort)
82 | run := fmt.Sprintf("%s:%s", dockerOptions.dockerRepo, version)
83 | args := []string {
84 | "run", "-d",
85 | "--name", dockerOptions.containerName,
86 | "-p", p,
87 | "--network", "gamma",
88 | }
89 | for _, value := range dockerOptions.env {
90 | args = append(args, "-e", value)
91 | }
92 | args = append(args, run)
93 | args = append(args, dockerOptions.dockerCmd...)
94 |
95 | out, err := exec.Command("docker", args...).CombinedOutput()
96 | if err != nil {
97 | die("Could not exec 'docker run' command.\n\n%s", out)
98 | }
99 |
100 | if !isDockerContainerRunning(dockerOptions.containerName) {
101 | die("Could not run docker image.")
102 | }
103 |
104 | if *flagWait {
105 | waitUntilDockerIsReadyAndListening(IS_READY_TOTAL_WAIT_TIMEOUT)
106 | }
107 |
108 | log(`
109 | *********************************************************************************
110 | %s %s is running!
111 |
112 | Local blockchain instance started and listening on port %d.
113 | Run 'gamma-cli help' in terminal to learn how to interact with this instance.
114 |
115 | **********************************************************************************
116 | `, dockerOptions.name, version, dockerOptions.port)
117 | }
118 |
119 | func commandStopLocalContainer(dockerOptions handlerOptions, requiredOptions []string) {
120 | verifyDockerInstalled(dockerOptions, dockerOptions.dockerRegistryTagsUrl)
121 |
122 | out, err := exec.Command("docker", "stop", dockerOptions.containerName).CombinedOutput()
123 | if err != nil {
124 | log("%s server is already stopped.\n", dockerOptions.name)
125 | }
126 |
127 | out, err = exec.Command("docker", "rm", "-f", dockerOptions.containerName).CombinedOutput()
128 | if err != nil {
129 | log("Could not remove docker container.\n\n%s", out)
130 | }
131 |
132 | if isDockerContainerRunning(dockerOptions.containerName) {
133 | die("Could not stop docker container.")
134 | }
135 |
136 | log(`
137 | *********************************************************************************
138 | %s stopped.
139 |
140 | A local blockchain instance is running in-memory.
141 | The next time you start the instance, all contracts and state will disappear.
142 |
143 | **********************************************************************************
144 | `, dockerOptions.name)
145 | }
146 |
147 | func commandUpgradeImage(dockerOptions handlerOptions, requiredOptions []string) bool {
148 | currentTag := verifyDockerInstalled(dockerOptions, dockerOptions.dockerRegistryTagsUrl)
149 | latestTag := getLatestDockerTag(dockerOptions.dockerRegistryTagsUrl)
150 |
151 | if !isExperimental() && cmpTags(latestTag, currentTag) <= 0 {
152 | log("Current %s stable version %s does not require upgrade.", dockerOptions.name, currentTag)
153 | } else {
154 | log("Downloading latest %s version %s:\n", dockerOptions.name, latestTag)
155 | cmd := exec.Command("docker", "pull", fmt.Sprintf("%s:%s", dockerOptions.dockerRepo, latestTag))
156 | output, _ := cmd.CombinedOutput()
157 | log(string(output))
158 | if !strings.Contains(string(output), "Image is up to date") {
159 | return true
160 | }
161 | }
162 | return false
163 | }
164 |
165 | func showLogs(requiredOptions []string) {
166 | dockerOptions := gammaHandlerOptions()
167 | verifyDockerInstalled(dockerOptions, dockerOptions.dockerRegistryTagsUrl)
168 |
169 | cmd := exec.Command("docker", "logs", "-f", "--tail=20", dockerOptions.containerName)
170 | stdout, err := cmd.StderrPipe() // println() and print() go to stderr
171 | if err != nil {
172 | die("could not read gamma server docker logs: %s", err)
173 | }
174 |
175 | if err := cmd.Start(); err != nil {
176 | die("could not start docker logs command: %s", err)
177 | }
178 |
179 | scanner := bufio.NewScanner(stdout)
180 | for scanner.Scan() {
181 | fmt.Println(scanner.Text())
182 | }
183 | if err := scanner.Err(); err != nil {
184 | die("error reading gamma server docker logs: %s", err)
185 | }
186 | }
187 |
188 | // TODO remove dockerRegistryUrl as separate parameter
189 | func verifyDockerInstalled(dockerOptions handlerOptions, dockerRegistryTagUrl string) string {
190 | out, err := exec.Command("docker", "images", dockerOptions.dockerRepo).CombinedOutput()
191 | if err != nil {
192 | if runtime.GOOS == "darwin" {
193 | die("Docker is required but not running. Is it installed on your machine?\n\nInstall from: https://docs.docker.com/docker-for-mac/install/")
194 | } else {
195 | die("Docker is required but not running. Is it installed on your machine?\n\nInstall from: https://docs.docker.com/install/")
196 | }
197 | }
198 |
199 | existingTag := extractTagFromDockerImagesOutput(dockerOptions.dockerRepo, string(out))
200 | if existingTag != DOCKER_TAG_NOT_FOUND {
201 | return existingTag
202 | }
203 |
204 | latestTag := getLatestDockerTag(dockerRegistryTagUrl)
205 |
206 | log("%s image is not installed, downloading version %s:\n", dockerOptions.name, latestTag)
207 | cmd := exec.Command("docker", "pull", fmt.Sprintf("%s:%s", dockerOptions.dockerRepo, latestTag))
208 | cmd.Stdout = os.Stdout
209 | cmd.Stderr = os.Stderr
210 | cmd.Run()
211 | log("")
212 |
213 | out, err = exec.Command("docker", "images", dockerOptions.dockerRepo).CombinedOutput()
214 | if err != nil || strings.Count(string(out), "\n") == 1 {
215 | die("Could not download docker image.")
216 | }
217 | return extractTagFromDockerImagesOutput(dockerOptions.dockerRepo, string(out))
218 | }
219 |
220 | func isDockerContainerRunning(containerName string) bool {
221 | out, err := exec.Command("docker", "ps", "-f", fmt.Sprintf("name=%s", containerName)).CombinedOutput()
222 | if err != nil {
223 | return false
224 | }
225 | return strings.Count(string(out), "\n") > 1
226 | }
227 |
228 | func extractTagFromDockerImagesOutput(dockerRepo string, out string) string {
229 | pattern := fmt.Sprintf(`%s\s+(v\S+)`, regexp.QuoteMeta(dockerRepo))
230 | if isExperimental() {
231 | pattern = fmt.Sprintf(`%s\s+(%s)`, regexp.QuoteMeta(dockerRepo), regexp.QuoteMeta(DOCKER_TAG_EXPERIMENTAL))
232 | }
233 | re := regexp.MustCompile(pattern)
234 | res := re.FindStringSubmatch(out)
235 | if len(res) < 2 {
236 | return DOCKER_TAG_NOT_FOUND
237 | }
238 | return res[1]
239 | }
240 |
241 | func getLatestDockerTag(dockerRegistryTagsUrl string) string {
242 | if isExperimental() {
243 | return DOCKER_TAG_EXPERIMENTAL
244 | }
245 | resp, err := http.Get(dockerRegistryTagsUrl)
246 | if err != nil {
247 | die("Cannot connect to docker registry to get image list.")
248 | }
249 | defer resp.Body.Close()
250 | bytes, err := ioutil.ReadAll(resp.Body)
251 | if err != nil || len(bytes) == 0 {
252 | die("Bad image list response from docker registry.")
253 | }
254 | tag, err := extractLatestTagFromDockerHubResponse(bytes)
255 | if err != nil {
256 | die("Cannot parse image list response from docker registry.")
257 | }
258 | return tag
259 | }
260 |
261 | type dockerHubTagsJson struct {
262 | Results []*struct {
263 | Name string
264 | }
265 | }
266 |
267 | func extractLatestTagFromDockerHubResponse(responseBytes []byte) (string, error) {
268 | var response *dockerHubTagsJson
269 | err := json.Unmarshal(responseBytes, &response)
270 | if err != nil {
271 | return "", err
272 | }
273 | maxTag := ""
274 | for _, result := range response.Results {
275 | if cmpTags(result.Name, maxTag) > 0 {
276 | maxTag = result.Name
277 | }
278 | }
279 | if maxTag == "" {
280 | return "", errors.New("no valid tags found")
281 | }
282 | return maxTag, nil
283 | }
284 |
285 | func isExperimental() bool {
286 | if *flagEnv == LOCAL_ENV_ID {
287 | return false
288 | }
289 | if *flagEnv == EXPERIMENTAL_ENV_ID {
290 | return true
291 | }
292 | // allow custom experimental configs (like for docker ci)
293 | return getEnvironmentFromConfigFile(*flagEnv).Experimental
294 | }
295 |
296 | func cmpTags(t1, t2 string) int {
297 | re := regexp.MustCompile(`v(\d+)\.(\d+)\.(\d+)`)
298 | m1 := re.FindStringSubmatch(t1)
299 | if len(m1) < 4 {
300 | return -1
301 | }
302 | m2 := re.FindStringSubmatch(t2)
303 | if len(m2) < 4 {
304 | return 1
305 | }
306 | diff := atoi(m1[1]) - atoi(m2[1])
307 | if diff != 0 {
308 | return diff
309 | }
310 | diff = atoi(m1[2]) - atoi(m2[2])
311 | if diff != 0 {
312 | return diff
313 | }
314 | return atoi(m1[3]) - atoi(m2[3])
315 | }
316 |
317 | func atoi(num string) int {
318 | res, err := strconv.Atoi(num)
319 | if err != nil {
320 | return 0
321 | }
322 | return res
323 | }
324 |
325 | func createDockerNetwork() error {
326 | out, err := exec.Command("docker", "network", "ls", "--filter", "name=gamma", "-q").CombinedOutput()
327 | if err != nil {
328 | return err
329 | }
330 |
331 | if len(out) == 0 {
332 | _, err := exec.Command("docker", "network", "create", "gamma").CombinedOutput()
333 | if err != nil {
334 | return err
335 | }
336 | }
337 |
338 | return nil
339 | }
340 |
341 | func prismEnabled() bool {
342 | return !*flagNoUi
343 | }
--------------------------------------------------------------------------------
/docker_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "testing"
12 | )
13 |
14 | func TestExtractLatestTagFromDockerHubResponse(t *testing.T) {
15 | tests := []struct {
16 | name string
17 | input string
18 | expected string
19 | }{
20 | {
21 | name: "HappyFlow",
22 | input: `{"count": 2, "next": null, "previous": null, "results": [{"name": "v0.4.2", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40717129, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:32.560968Z", "image_id": null, "v2": true}, {"name": "v0.7.0", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40686462, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:27.625449Z", "image_id": null, "v2": true}]}`,
23 | expected: "v0.7.0",
24 | },
25 | {
26 | name: "HappyFlowReversed",
27 | input: `{"count": 2, "next": null, "previous": null, "results": [{"name": "v1.2.3", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40717129, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:32.560968Z", "image_id": null, "v2": true}, {"name": "v0.7.0", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40686462, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:27.625449Z", "image_id": null, "v2": true}]}`,
28 | expected: "v1.2.3",
29 | },
30 | {
31 | name: "Empty",
32 | input: ``,
33 | expected: "",
34 | },
35 | {
36 | name: "NoResults",
37 | input: `{"count": 0, "next": null, "previous": null, "results": []}`,
38 | expected: "",
39 | },
40 | {
41 | name: "Corrupt",
42 | input: `{"count": 2, "next": null, "previous": null, "results": [{"name": "v0.4.2", "full_size": 126289039, "ima`,
43 | expected: "",
44 | },
45 | {
46 | name: "NonSemver",
47 | input: `{"count": 2, "next": null, "previous": null, "results": [{"name": "latest", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40717129, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:32.560968Z", "image_id": null, "v2": true}, {"name": "v0.7.0", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40686462, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:27.625449Z", "image_id": null, "v2": true}]}`,
48 | expected: "v0.7.0",
49 | },
50 | {
51 | name: "Experimental",
52 | input: `{"count": 2, "next": null, "previous": null, "results": [{"name": "experimental", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40717129, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:32.560968Z", "image_id": null, "v2": true}, {"name": "v0.7.0", "full_size": 126289039, "images": [{"size": 126289039, "architecture": "amd64", "variant": null, "features": null, "os": "linux", "os_version": null, "os_features": null}], "id": 40686462, "repository": 6341803, "creator": 4691149, "last_updater": 4691149, "last_updated": "2018-11-26T14:02:27.625449Z", "image_id": null, "v2": true}]}`,
53 | expected: "v0.7.0",
54 | },
55 | }
56 | for _, tt := range tests {
57 | t.Run(tt.name, func(t *testing.T) {
58 | tag, err := extractLatestTagFromDockerHubResponse([]byte(tt.input))
59 | if tt.expected == "" {
60 | require.Error(t, err, "extract should return an error")
61 | } else {
62 | require.NoError(t, err, "extract should not return an error")
63 | require.Equal(t, tt.expected, tag, "extracted tag should match")
64 | }
65 | })
66 | }
67 | }
68 |
69 | func TestCmpTags(t *testing.T) {
70 | tests := []struct {
71 | name string
72 | first string
73 | second string
74 | expected int
75 | }{
76 | {
77 | name: "Equal",
78 | first: "v1.2.3",
79 | second: "v1.2.3",
80 | expected: 0, // latest, current -> no upgrade
81 | },
82 | {
83 | name: "FirstNewer(patch)",
84 | first: "v1.2.3",
85 | second: "v1.2.0",
86 | expected: 1, // latest, current -> upgrade!
87 | },
88 | {
89 | name: "FirstNewer(minor)",
90 | first: "v1.2.3",
91 | second: "v1.1.3",
92 | expected: 1, // latest, current -> upgrade!
93 | },
94 | {
95 | name: "FirstNewer(major)",
96 | first: "v2.1.3",
97 | second: "v1.2.3",
98 | expected: 1, // latest, current -> upgrade!
99 | },
100 | {
101 | name: "FirstOlder(patch)",
102 | first: "v1.2.0",
103 | second: "v1.2.3",
104 | expected: -1, // latest, current -> no upgrade
105 | },
106 | {
107 | name: "FirstOlder(minor)",
108 | first: "v1.1.3",
109 | second: "v1.2.3",
110 | expected: -1, // latest, current -> no upgrade
111 | },
112 | {
113 | name: "FirstOlder(major)",
114 | first: "v1.2.3",
115 | second: "v2.1.3",
116 | expected: -1, // latest, current -> no upgrade
117 | },
118 | {
119 | name: "BothNoSemver",
120 | first: "junk",
121 | second: "junk",
122 | expected: -1, // latest, current -> no upgrade
123 | },
124 | {
125 | name: "BothNoSemverDifferent",
126 | first: "junk2",
127 | second: "junk1",
128 | expected: -1, // latest, current -> no upgrade
129 | },
130 | {
131 | name: "FirstNoSemver",
132 | first: "junk",
133 | second: "v1.2.3",
134 | expected: -1, // latest, current -> no upgrade
135 | },
136 | {
137 | name: "SecondNoSemver",
138 | first: "v1.2.3",
139 | second: "junk",
140 | expected: 1, // latest, current -> upgrade!
141 | },
142 | }
143 | for _, tt := range tests {
144 | t.Run(tt.name, func(t *testing.T) {
145 | result := cmpTags(tt.first, tt.second)
146 | switch tt.expected {
147 | case 1:
148 | require.True(t, result > 0, "result should be positive")
149 | case -1:
150 | require.True(t, result < 0, "result should be negative")
151 | case 0:
152 | require.Equal(t, 0, result, "result should be zero")
153 | }
154 | })
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/gammacli-linux-install-v0.7.0.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # This bash script downloads and installs a release pre-built gamma-cli
3 | # This script assumes you have Docker installed including elevated permissions for your
4 | # user to perform mundane docker tasks such as 'docker ps' (elevated = without the need for sudo)
5 | # Read more at: https://docs.docker.com/v17.12/install/linux/linux-postinstall/
6 | # If you don't have Docker installed, please have a look here on how to install it on Ubuntu Linux:
7 | # https://docs.docker.com/v17.12/install/linux/docker-ce/ubuntu/
8 |
9 | docker ps &> /dev/null
10 |
11 | DOCKER_TEST_EXITCODE=$?
12 |
13 | if [[ $DOCKER_TEST_EXITCODE != 0 ]]; then
14 | echo "Docker is not properly installed"
15 | echo "Read more here: https://docs.docker.com/v17.12/install/linux/linux-postinstall/"
16 | exit 1
17 | fi
18 |
19 | GAMMA_CLI_VERSION="v0.7.0"
20 | GAMMA_CLI_URL="https://github.com/orbs-network/gamma-cli/releases/download/$GAMMA_CLI_VERSION/gammacli-linux-x86-64-$GAMMA_CLI_VERSION.tar.gz"
21 |
22 | echo "Downloading pre-built gamma-cli ($GAMMA_CLI_VERSION) from it's official GitHub release repository.."
23 | wget $GAMMA_CLI_URL
24 | tar -zxvf gammacli*.tar.gz
25 | sudo mv _bin/gamma-cli /usr/bin/gamma-cli
26 |
27 | echo "gamma-cli successfully installed"
28 |
29 | exit 0
30 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/orbs-network/gamma-cli
2 |
3 | go 1.13
4 |
5 | require (
6 | github.com/orbs-network/crypto-lib-go v1.2.0
7 | github.com/orbs-network/lean-helix-go v0.2.7
8 | github.com/orbs-network/orbs-client-sdk-go v0.18.0
9 | github.com/orbs-network/orbs-spec v0.0.0-20200312223140-a78d945bab99
10 | github.com/pkg/errors v0.8.1
11 | github.com/stretchr/testify v1.4.0
12 | )
13 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
4 | cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
5 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
6 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
7 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
8 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
9 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
10 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
11 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
12 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
13 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
14 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
15 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
16 | github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
17 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
18 | github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
19 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
20 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
21 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
22 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
23 | github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
24 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
25 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
26 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
27 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
28 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
29 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
30 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
31 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
32 | github.com/ethereum/go-ethereum v1.9.6/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
33 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
34 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
35 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
36 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
37 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
38 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
39 | github.com/go-playground/ansi v2.1.0+incompatible h1:f9ldskdk1seTFmYjbmPaYB+WYsDKWc4UXcGb+e9JrN8=
40 | github.com/go-playground/ansi v2.1.0+incompatible/go.mod h1:OCdnfTFO/GfFtp+ktUt+PhElbGOwyTRUuRUsA+Y5pSU=
41 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
42 | github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
43 | github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
44 | github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
45 | github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
46 | github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
47 | github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
48 | github.com/gobuffalo/packr/v2 v2.5.2/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08=
49 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
50 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
51 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
52 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
53 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
54 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
55 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
56 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
57 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
58 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
59 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
60 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
61 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
62 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
63 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
64 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
65 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
66 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
67 | github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
68 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
69 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
70 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
71 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
72 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
73 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
74 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
75 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
76 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
77 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
78 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
79 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
80 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
81 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
82 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
83 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
84 | github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
85 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
86 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
87 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
88 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
89 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
90 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
91 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
92 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
93 | github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
94 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
95 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
96 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
97 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
98 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
99 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
100 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
101 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
102 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
103 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
104 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
105 | github.com/orbs-network/crypto-lib-go v1.2.0 h1:ZB+RCD8dPE2di97J5ap/7VX+7yuNNyey5P9p2nSHhvA=
106 | github.com/orbs-network/crypto-lib-go v1.2.0/go.mod h1:2jw6UQyT53aRh425j7mpxaGDhvfGVCfTqqBj22zULOs=
107 | github.com/orbs-network/go-mock v0.0.0-20180813130752-890a1ee8d0a1/go.mod h1:Hfj5NDPp07PIkGv5y8g1C0zsMXbrVTPQVIvSuHSHyvo=
108 | github.com/orbs-network/gojay v1.3.0 h1:TDqmmbgwHum9oXq1iexd+J+IUBm4/gtlyoOP5HV8rvw=
109 | github.com/orbs-network/gojay v1.3.0/go.mod h1:xdSp1mz0+DL+c6OLsbZ5qB/Gtygikcr5NdSsU1GsRC0=
110 | github.com/orbs-network/govnr v0.2.0 h1:Txazgo4Jd29hiARXg6nMqK2pmJA85KeXR+ZjLNy9WZc=
111 | github.com/orbs-network/govnr v0.2.0/go.mod h1:kZctUOFclDbO3Z6w559++l4qh0FPb57XdE5IdOFCbI4=
112 | github.com/orbs-network/lean-helix-go v0.2.3 h1:MwuN27C+y+WsvWcgwXoe0Gvi9p9qNR+a9LvLF7eERXk=
113 | github.com/orbs-network/lean-helix-go v0.2.3/go.mod h1:CYJzVWQROmK7DZGW0cFpNFbqLc8RdwIc8+n8uk3+KbM=
114 | github.com/orbs-network/lean-helix-go v0.2.7 h1:d7k67YUIMqXihIl5x/S9p7VIpBGpBzI1D/xR1x2Y/Ro=
115 | github.com/orbs-network/lean-helix-go v0.2.7/go.mod h1:9E/1sZEMZvNLHrP+nif36bio2zKbCkueji4R9e7vJnI=
116 | github.com/orbs-network/membuffers v0.3.0/go.mod h1:b6+sJ9+pgca7HHle0e85RDd5zL0Hv360Xec7TGVrGFk=
117 | github.com/orbs-network/membuffers v0.3.2 h1:dpUJXBTjvFkNputqIjCfBJnAJszZALtfuWcf9hGvg/4=
118 | github.com/orbs-network/membuffers v0.3.2/go.mod h1:M5ABv0m0XBGoJbX+7UKVY02hLF4XhS2SlZVEVABMc6M=
119 | github.com/orbs-network/membuffers v0.4.0 h1:tqeCLjdXJX3JIGy2mEMroeE+vG5mWTZx1vpwz7sgQKc=
120 | github.com/orbs-network/membuffers v0.4.0/go.mod h1:mhOIfhkMQWKhbQbwD2BoIlV9eAA3LwZXMC0+JIrDmCM=
121 | github.com/orbs-network/orbs-client-sdk-go v0.9.0 h1:tl0wxD8gSCXGO1moMMznqs6RDtHOSD2EbPzWAu++X94=
122 | github.com/orbs-network/orbs-client-sdk-go v0.9.0/go.mod h1:G2CJh+3UoKD1S2Z7Kzdt5cAh+kTinKFHLyGeOEUj1sA=
123 | github.com/orbs-network/orbs-client-sdk-go v0.13.0 h1:RoZ/wyQbnQhr1Pa06k3qFBSMegvlkI/uwXOhGib97Po=
124 | github.com/orbs-network/orbs-client-sdk-go v0.13.0/go.mod h1:1KsIoX5oZrLRwi96bF6k0Dy9dZaym2H88hCDi92R2YM=
125 | github.com/orbs-network/orbs-client-sdk-go v0.18.0 h1:xR/cais6t7SEU7D7GVmGv5rOMQozB0WkUQlKHTcn0Jg=
126 | github.com/orbs-network/orbs-client-sdk-go v0.18.0/go.mod h1:t7iiF0hkB3Grnbsu4yJ05SRsoEmO/fRfqCJK2egNvQ4=
127 | github.com/orbs-network/orbs-contract-sdk v1.0.0/go.mod h1:N+caPmVwyn3p+kgPwfb43bo4qAcRDoiaq/gw/ag1mHo=
128 | github.com/orbs-network/orbs-contract-sdk v1.4.0 h1:lbpo83A4cIQPzvyloVmNk/cVP6MO5BEn+zw0/Vg+OeI=
129 | github.com/orbs-network/orbs-contract-sdk v1.4.0/go.mod h1:N+caPmVwyn3p+kgPwfb43bo4qAcRDoiaq/gw/ag1mHo=
130 | github.com/orbs-network/orbs-spec v0.0.0-20190702065947-c6cfaf7cd01a/go.mod h1:9Bv/kJ/Q7cIlIYmlzsBHelseVJmyw2zywuW3TSvQX5g=
131 | github.com/orbs-network/orbs-spec v0.0.0-20191029121602-b5af15c91a90 h1:q4IQsP6nuxsDZ6WIurB6LjBzdEoUP0iBkffsFJNGTtI=
132 | github.com/orbs-network/orbs-spec v0.0.0-20191029121602-b5af15c91a90/go.mod h1:tun/2f3PycO5lhYQtISnbW3WgGhru1FhpECEg39Or+A=
133 | github.com/orbs-network/orbs-spec v0.0.0-20191114152037-24b26e24030e h1:2uhGT3x5lcuvdX7rkw1nKwPjzgA1bBQ3RzNkWSSPGP0=
134 | github.com/orbs-network/orbs-spec v0.0.0-20191114152037-24b26e24030e/go.mod h1:D4+jHMhQ+mPB4uhqZ2wtzuG8RV2JgltWG1FqAwLIaOw=
135 | github.com/orbs-network/orbs-spec v0.0.0-20200312223140-a78d945bab99 h1:SIM5FvYeayQfRWBTwuPfe/JHI1NrKY7QaTzjfemjAkA=
136 | github.com/orbs-network/orbs-spec v0.0.0-20200312223140-a78d945bab99/go.mod h1:D4+jHMhQ+mPB4uhqZ2wtzuG8RV2JgltWG1FqAwLIaOw=
137 | github.com/orbs-network/pbparser v0.2.0/go.mod h1:WSzcxgH5xzywQm0YSASbD7RcdxBXZgqZaDVK8M+8DJ8=
138 | github.com/orbs-network/pbparser v0.3.0/go.mod h1:WSzcxgH5xzywQm0YSASbD7RcdxBXZgqZaDVK8M+8DJ8=
139 | github.com/orbs-network/scribe v0.1.0 h1:Kn/EQpifQFae+F7HRIoTIipUsSHZNcfQ3HJOhD/b+8M=
140 | github.com/orbs-network/scribe v0.1.0/go.mod h1:FmGcbukz5eolO+mqzxwmuy4RF4UEoLfGJIeEDAoGsBU=
141 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
142 | github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
143 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
144 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
145 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
146 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
147 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
148 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
149 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
150 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
151 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
152 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
153 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
154 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
155 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
156 | github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
157 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
158 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
159 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
160 | github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
161 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
162 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
163 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
164 | github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
165 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
166 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
167 | github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
168 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
169 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
170 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
171 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
172 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
173 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
174 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
175 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
176 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
177 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
178 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
179 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
180 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
181 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
182 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
183 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
184 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
185 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
186 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
187 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
188 | github.com/tallstoat/pbparser v0.2.0/go.mod h1:aUC6W9uQLeAXZkknve8ZDO6InhRYpYHlJ9kvsQh1i2k=
189 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
190 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
191 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
192 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
193 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
194 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
195 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
196 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
197 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
198 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
199 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
200 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
201 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
202 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
203 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
204 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
205 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
206 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
207 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
208 | golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
209 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
210 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
211 | golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
212 | golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
213 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
214 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
215 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
216 | golang.org/x/exp v0.0.0-20190718202018-cfdd5522f6f6/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
217 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
218 | golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
219 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
220 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
221 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
222 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
223 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
224 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
225 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
226 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
227 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
228 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
229 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
230 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
231 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
232 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
233 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
234 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
235 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
236 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
237 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
238 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
239 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
240 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
241 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
242 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
243 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
244 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
245 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
246 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
247 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
248 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
249 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
250 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
251 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
252 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
253 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
254 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
255 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
256 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
257 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
258 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
259 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
260 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
261 | golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
262 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
263 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
264 | golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
265 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
266 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
267 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
268 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
269 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
270 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
271 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
272 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
273 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
274 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
275 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
276 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
277 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
278 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
279 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
280 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
281 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
282 | golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
283 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
284 | golang.org/x/tools v0.0.0-20190723021737-8bb11ff117ca/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
285 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
286 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
287 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
288 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
289 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
290 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
291 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
292 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
293 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
294 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
295 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
296 | google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
297 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
298 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
299 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
300 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
301 | google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
302 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
303 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
304 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
305 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
306 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
307 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
308 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
309 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
310 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
311 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
312 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
313 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
314 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
315 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
316 |
--------------------------------------------------------------------------------
/help.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "flag"
11 | "fmt"
12 | "os"
13 | "reflect"
14 | "strings"
15 | )
16 |
17 | func commandShowHelp(requiredOptions []string) {
18 | fmt.Fprintf(os.Stderr, "Usage:\n\n")
19 | fmt.Fprintf(os.Stderr, "gamma-cli COMMAND [OPTIONS]\n\n")
20 |
21 | fmt.Fprintf(os.Stderr, "Commands:\n\n")
22 | sortedCommands := sortCommands()
23 | for _, name := range sortedCommands {
24 | cmd := commands[name]
25 | fmt.Fprintf(os.Stderr, " %s %s %s\n", name, strings.Repeat(" ", 15-len(name)), cmd.desc)
26 | if cmd.args != "" {
27 | fmt.Fprintf(os.Stderr, " %s options: %s\n", strings.Repeat(" ", 15), cmd.args)
28 | }
29 | if cmd.example != "" {
30 | fmt.Fprintf(os.Stderr, " %s example: %s\n", strings.Repeat(" ", 15), cmd.example)
31 | }
32 | if cmd.example2 != "" {
33 | fmt.Fprintf(os.Stderr, " %s %s\n", strings.Repeat(" ", 15), cmd.example2)
34 | }
35 | fmt.Fprintf(os.Stderr, "\n")
36 | }
37 | fmt.Fprintf(os.Stderr, "\n")
38 |
39 | fmt.Fprintf(os.Stderr, "Options:\n\n")
40 | showOptions()
41 | fmt.Fprintf(os.Stderr, "\n")
42 |
43 | fmt.Fprintf(os.Stderr, "Multiple environments (eg. local and testnet) can be defined in orbs-gamma-config.json configuration file.\n")
44 | fmt.Fprintf(os.Stderr, "See https://orbs.gitbook.io for more info.\n")
45 | fmt.Fprintf(os.Stderr, "\n")
46 |
47 | os.Exit(2)
48 | }
49 |
50 | func commandVersion(requiredOptions []string) {
51 | log("gamma-cli version %s", GAMMA_CLI_VERSION)
52 |
53 | gammaVersion := verifyDockerInstalled(gammaHandlerOptions(), gammaHandlerOptions().dockerRegistryTagsUrl)
54 | log("Gamma server version %s (docker)", gammaVersion)
55 |
56 | prismVersion := verifyDockerInstalled(prismHandlerOptions(), prismHandlerOptions().dockerRegistryTagsUrl)
57 | log("Prism blockchain explorer version %s (docker)", prismVersion)
58 | }
59 |
60 | func sortCommands() []string {
61 | res := make([]string, len(commands))
62 | for name, cmd := range commands {
63 | res[cmd.sort] = name
64 | }
65 | return res
66 | }
67 |
68 | // taken from package flag (func PrintDefaults)
69 | func showOptions() {
70 | flag.VisitAll(func(f *flag.Flag) {
71 | // ignore list
72 | if strings.HasPrefix(f.Name, "arg") {
73 | return
74 | }
75 |
76 | s := fmt.Sprintf(" -%s", f.Name)
77 | name, usage := flag.UnquoteUsage(f)
78 | if len(name) > 0 {
79 | s += " " + name
80 | }
81 | if len(s) <= 4 {
82 | s += "\t"
83 | } else {
84 | s += "\n \t"
85 | }
86 | s += strings.Replace(usage, "\n", "\n \t", -1)
87 |
88 | if !isZeroValue(f, f.DefValue) {
89 | s += fmt.Sprintf(" (default %q)", f.DefValue)
90 | }
91 | fmt.Fprint(os.Stderr, s, "\n")
92 | })
93 | }
94 |
95 | // taken from package flag
96 | func isZeroValue(f *flag.Flag, value string) bool {
97 | typ := reflect.TypeOf(f.Value)
98 | var z reflect.Value
99 | if typ.Kind() == reflect.Ptr {
100 | z = reflect.New(typ.Elem())
101 | } else {
102 | z = reflect.Zero(typ)
103 | }
104 | if value == z.Interface().(flag.Value).String() {
105 | return true
106 | }
107 | switch value {
108 | case "false", "", "0":
109 | return true
110 | }
111 | return false
112 | }
113 |
--------------------------------------------------------------------------------
/is_ready.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "net"
12 | "time"
13 | )
14 |
15 | const IS_READY_TOTAL_WAIT_TIMEOUT = 20 * time.Second
16 | const IS_READY_POLLING_INTERVAL = 500 * time.Millisecond
17 |
18 | const DEPLOY_GET_INFO_SYSTEM_METHOD_NAME = "getInfo"
19 |
20 | func isDockerReadyAndListening() bool {
21 | signer := getTestKeyFromFile(*flagSigner)
22 |
23 | client := createOrbsClient()
24 | payload, err := client.CreateQuery(signer.PublicKey, DEPLOY_SYSTEM_CONTRACT_NAME, DEPLOY_GET_INFO_SYSTEM_METHOD_NAME, DEPLOY_SYSTEM_CONTRACT_NAME)
25 | if err != nil {
26 | die("Could not encode payload of the message about to be sent to server.\n\n%s", err.Error())
27 | }
28 |
29 | response, err := client.SendQuery(payload)
30 | if err != nil {
31 | return false
32 | }
33 |
34 | // the system will not accept new transactions before block 1 is closed under consensus
35 | if response.BlockHeight == 0 {
36 | return false
37 | }
38 |
39 | return true
40 | }
41 |
42 | func waitUntilDockerIsReadyAndListening(timeout time.Duration) {
43 | start := time.Now()
44 | for time.Now().Sub(start) < timeout {
45 | if isDockerReadyAndListening() {
46 | return
47 | }
48 | time.Sleep(IS_READY_POLLING_INTERVAL)
49 | }
50 | }
51 |
52 | func isPortListening(port int) bool {
53 | server, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
54 | if err != nil {
55 | return true // if it fails then the port is likely taken
56 | }
57 | server.Close()
58 | return false
59 | }
60 |
--------------------------------------------------------------------------------
/jsoncodec/args.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "encoding/hex"
11 | "github.com/orbs-network/crypto-lib-go/crypto/encoding"
12 | "github.com/pkg/errors"
13 | "math/big"
14 | "reflect"
15 | "strconv"
16 | "strings"
17 | )
18 |
19 | const supported = "Supported types are: uint32 uint64 uint256 bool string bytes bytes20 bytes32 uint32Array uint64Array uint256Array boolArray stringArray bytesArray bytes20Array bytes32Array gamma:address gamma:keys-file-address"
20 |
21 | type Arg struct {
22 | Type string
23 | Value interface{}
24 | }
25 |
26 | func isArgsInputStructureValid(args []*Arg) error {
27 | for i, arg := range args {
28 | rValue := reflect.TypeOf(arg.Value).String()
29 | if strings.HasSuffix(arg.Type, "Array") {
30 | if rValue != "[]interface {}" {
31 | return errors.Errorf("Argument %d's Type is marked as an Array and it's Value should contain an array of string\nCurrently %s\n", i+1, rValue)
32 | }
33 | } else if rValue != "string" {
34 | return errors.Errorf("Argument %d's Type is marked as a Scalar and it's Value should contain a string", i+1)
35 | }
36 | }
37 | return nil
38 | }
39 |
40 | func unmarshalScalar(argType, value string) (interface{}, error) {
41 | switch argType {
42 | case "uint32":
43 | val, err := strconv.ParseUint(value, 10, 32)
44 | if err != nil {
45 | return nil, errors.Errorf("a numeric value\nCurrent value: '%s'", value)
46 | }
47 | return uint32(val), nil
48 | case "uint64":
49 | val, err := strconv.ParseUint(value, 10, 64)
50 | if err != nil {
51 | return nil, errors.Errorf("a numeric value\nCurrent value: '%s'", value)
52 | }
53 | return val, nil
54 | case "string":
55 | return value, nil
56 | case "bytes":
57 | val, err := simpleDecodeHex(value)
58 | if err != nil {
59 | return nil, errors.Errorf("bytes in hex format\nHex decoder returned error: %s\nCurrent value: '%s'", err.Error(), value)
60 | }
61 | return val, nil
62 | case "bool":
63 | if value == "1" {
64 | return true, nil
65 | } else if value == "0" {
66 | return false, nil
67 | } else {
68 | return nil, errors.Errorf("1 or 0\nCurrent value: '%s'", value)
69 | }
70 | case "uint256":
71 | valBytes, err := simpleDecodeHex(value)
72 | if err != nil {
73 | return nil, errors.Errorf("uint256 value in bytes in a hex format (64 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", err.Error(), value)
74 | }
75 | if len(valBytes) != 32 {
76 | return nil, errors.Errorf("uint256 value in bytes in a hex format (64 hexes)\n Actual size : %d", len(valBytes))
77 | }
78 | val := big.NewInt(0)
79 | val.SetBytes(valBytes)
80 | return val, nil
81 | case "bytes20":
82 | valBytes, err := simpleDecodeHex(value)
83 | if err != nil {
84 | return nil, errors.Errorf("bytes20 in a hex format (40 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", err.Error(), value)
85 | }
86 | if len(valBytes) != 20 {
87 | return nil, errors.Errorf("bytes20 in a hex format (40 hexes)\n Actual size : %d", len(valBytes))
88 | }
89 | var val [20]byte
90 | copy(val[:], valBytes)
91 | return val, nil
92 | case "bytes32":
93 | valBytes, err := simpleDecodeHex(value)
94 | if err != nil {
95 | return nil, errors.Errorf("bytes32 in a hex format (64 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", err.Error(), value)
96 | }
97 | if len(valBytes) != 32 {
98 | return nil, errors.Errorf("bytes32 in a hex format (64 hexes)\n Actual size : %d", len(valBytes))
99 | }
100 | var val [32]byte
101 | copy(val[:], valBytes)
102 | return val, nil
103 | default:
104 | return nil, errors.Errorf("a known type. '%s' is unsupported\n%s", argType, supported)
105 | }
106 | }
107 |
108 | func unmarshalArray(argType string, argValues []interface{}) (interface{}, error) {
109 | switch argType {
110 | case "uint32Array":
111 | var argArrayRes []uint32
112 | for j, argValue := range argValues {
113 | val, err := strconv.ParseUint(argValue.(string), 10, 32)
114 | if err != nil {
115 | return nil, errors.Errorf("element %d should be a string containing a numeric value\nCurrent value: '%s'", j+1, argValue)
116 | }
117 | argArrayRes = append(argArrayRes, uint32(val))
118 | }
119 | return argArrayRes, nil
120 | case "uint64Array":
121 | var argArrayRes []uint64
122 | for j, argValue := range argValues {
123 | val, err := strconv.ParseUint(argValue.(string), 10, 64)
124 | if err != nil {
125 | return nil, errors.Errorf("element %d should be a string containing a numeric value\nCurrent value: '%s'", j+1, argValue)
126 | }
127 | argArrayRes = append(argArrayRes, val)
128 | }
129 | return argArrayRes, nil
130 | case "stringArray":
131 | var argArrayRes []string
132 | for _, argValue := range argValues {
133 | argArrayRes = append(argArrayRes, argValue.(string))
134 | }
135 | return argArrayRes, nil
136 | case "bytesArray":
137 | var argArrayRes [][]byte
138 | for j, argValue := range argValues {
139 | val, err := simpleDecodeHex(argValue.(string))
140 | if err != nil {
141 | return nil, errors.Errorf("element %d should be a string containing bytes in hex format\nHex decoder returned error: %s\nCurrent value: '%s'", j+1, err.Error(), argValue)
142 | }
143 | argArrayRes = append(argArrayRes, val)
144 | }
145 | return argArrayRes, nil
146 | case "boolArray":
147 | var argArrayRes []bool
148 | for j, argValue := range argValues {
149 | s := argValue.(string)
150 | if s == "1" {
151 | argArrayRes = append(argArrayRes, true)
152 | } else if s == "0" {
153 | argArrayRes = append(argArrayRes, false)
154 | } else {
155 | return nil, errors.Errorf("element %d should be a string containing 1 or 0\nCurrent value: '%s'", j+1, argValue)
156 | }
157 | }
158 | return argArrayRes, nil
159 | case "uint256Array":
160 | var argArrayRes []*big.Int
161 | for j, argValue := range argValues {
162 | valBytes, err := simpleDecodeHex(argValue.(string))
163 | if err != nil {
164 | return nil, errors.Errorf("element %d should be a string containing uint256 in hex format (64 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", j+1, err.Error(), argValue)
165 | }
166 | if len(valBytes) != 32 {
167 | return nil, errors.Errorf("element %d should be a string containing uint256 in a hex format (64 hexes)\n Actual size : %d", j+1, len(valBytes))
168 | }
169 | val := big.NewInt(0)
170 | val.SetBytes(valBytes)
171 | argArrayRes = append(argArrayRes, val)
172 | }
173 | return argArrayRes, nil
174 | case "bytes20Array":
175 | var argArrayRes [][20]byte
176 | for j, argValue := range argValues {
177 | valBytes, err := simpleDecodeHex(argValue.(string))
178 | if err != nil {
179 | return nil, errors.Errorf("element %d should be a string containing bytes20 in hex format (40 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", j+1, err.Error(), argValue)
180 | }
181 | if len(valBytes) != 20 {
182 | return nil, errors.Errorf("element %d should be a string containing bytes20 in a hex format (40 hexes)\n Actual size : %d", j+1, len(valBytes))
183 | }
184 | var val [20]byte
185 | copy(val[:], valBytes)
186 | argArrayRes = append(argArrayRes, val)
187 | }
188 | return argArrayRes, nil
189 | case "bytes32Array":
190 | var argArrayRes [][32]byte
191 | for j, argValue := range argValues {
192 | valBytes, err := simpleDecodeHex(argValue.(string))
193 | if err != nil {
194 | return nil, errors.Errorf("element %d should be a string containing bytes32 in hex format (64 hexes)\nHex decoder returned error: %s\nCurrent value: '%s'", j+1, err.Error(), argValue)
195 | }
196 | if len(valBytes) != 32 {
197 | return nil, errors.Errorf("element %d should be a string containing bytes32 in a hex format (64 hexes)\n Actual size : %d", j+1, len(valBytes))
198 | }
199 | var val [32]byte
200 | copy(val[:], valBytes)
201 | argArrayRes = append(argArrayRes, val)
202 | }
203 | return argArrayRes, nil
204 | default:
205 | return nil, errors.Errorf("a known type. '%s' is unsupported\n%s", argType, supported)
206 | }
207 | }
208 |
209 | func UnmarshalArgs(args []*Arg, getTestKeyFromFile func(string) *RawKey) ([]interface{}, error) {
210 | if err := isArgsInputStructureValid(args); err != nil {
211 | return nil, err
212 | }
213 | var res []interface{}
214 | for i, arg := range args {
215 | if arg.Type == "gamma:address" {
216 | val, err := encoding.DecodeHex(arg.Value.(string))
217 | if err != nil {
218 | return nil, errors.Errorf("Value of argument %d should be a string containing the bytes in hex\nHex decoder returned error: %s\n\nCurrent value: '%s'", i+1, err.Error(), arg.Value)
219 | }
220 | res = append(res, val)
221 | } else if arg.Type == "gamma:keys-file-address" {
222 | key := getTestKeyFromFile(arg.Value.(string))
223 | res = append(res, key.Address)
224 | } else if strings.HasSuffix(arg.Type, "Array") {
225 | valArray, err := unmarshalArray(arg.Type, arg.Value.([]interface{}))
226 | if err != nil {
227 | return nil, errors.Errorf("Value of array argument %d, %s", i+1, err.Error())
228 | }
229 | res = append(res, valArray)
230 | } else {
231 | val, err := unmarshalScalar(arg.Type, arg.Value.(string))
232 | if err != nil {
233 | return nil, errors.Errorf("Value of argument %d should be a string containing %s", i+1, err.Error())
234 | }
235 | res = append(res, val)
236 | }
237 | }
238 | return res, nil
239 | }
240 |
241 | func MarshalArgs(arguments []interface{}) ([]*Arg, error) {
242 | var res []*Arg
243 | for i, arg := range arguments {
244 | if reflect.TypeOf(arg).Kind() == reflect.Slice { // all []Type including []byte
245 | var arrArguments []string
246 | switch arg := arg.(type) {
247 | case []byte:
248 | res = append(res, &Arg{"bytes", "0x" + hex.EncodeToString(arg)})
249 | case []uint32:
250 | for _, v := range arg {
251 | arrArguments = append(arrArguments, strconv.FormatUint(uint64(v), 10))
252 | }
253 | res = append(res, &Arg{"uint32Array", arrArguments})
254 | case []uint64:
255 | for _, v := range arg {
256 | arrArguments = append(arrArguments, strconv.FormatUint(v, 10))
257 | }
258 | res = append(res, &Arg{"uint64Array", arrArguments})
259 | case []string:
260 | res = append(res, &Arg{"stringArray", arg})
261 | case [][]byte:
262 | for _, v := range arg {
263 | arrArguments = append(arrArguments, "0x"+hex.EncodeToString(v))
264 | }
265 | res = append(res, &Arg{"bytesArray", arrArguments})
266 | case []bool:
267 | for _, v := range arg {
268 | if v {
269 | arrArguments = append(arrArguments, "1")
270 | } else {
271 | arrArguments = append(arrArguments, "0")
272 | }
273 | }
274 | res = append(res, &Arg{"boolArray", arrArguments})
275 | case []*big.Int:
276 | val := [32]byte{}
277 | for _, v := range arg {
278 | b := v.Bytes()
279 | copy(val[32-len(b):], b)
280 | arrArguments = append(arrArguments, "0x"+hex.EncodeToString(val[:]))
281 | }
282 | res = append(res, &Arg{"uint256Array", arrArguments})
283 | case [][20]byte:
284 | for _, v := range arg {
285 | arrArguments = append(arrArguments, "0x"+hex.EncodeToString(v[:]))
286 | }
287 | res = append(res, &Arg{"bytes20Array", arrArguments})
288 | case [][32]byte:
289 | for _, v := range arg {
290 | arrArguments = append(arrArguments, "0x"+hex.EncodeToString(v[:]))
291 | }
292 | res = append(res, &Arg{"bytes32Array", arrArguments})
293 | default:
294 | return nil, errors.Errorf("Type of argument %d '%T' is unsupported\n\n%s", i+1, arg, supported)
295 | }
296 | } else {
297 | switch arg := arg.(type) {
298 | case uint32:
299 | res = append(res, &Arg{"uint32", strconv.FormatUint(uint64(arg), 10)})
300 | case uint64:
301 | res = append(res, &Arg{"uint64", strconv.FormatUint(arg, 10)})
302 | case string:
303 | res = append(res, &Arg{"string", arg})
304 | case bool:
305 | if arg {
306 | res = append(res, &Arg{"bool", "1"})
307 | } else {
308 | res = append(res, &Arg{"bool", "0"})
309 | }
310 | case *big.Int:
311 | val := [32]byte{}
312 | b := arg.Bytes()
313 | copy(val[32-len(b):], b)
314 | res = append(res, &Arg{"uint256", "0x" + hex.EncodeToString(val[:])})
315 | case [20]byte:
316 | res = append(res, &Arg{"bytes20", "0x" + hex.EncodeToString(arg[:])})
317 | case [32]byte:
318 | res = append(res, &Arg{"bytes32", "0x" + hex.EncodeToString(arg[:])})
319 | default:
320 | return nil, errors.Errorf("Type of argument %d '%T' is unsupported\n\n%s", i+1, arg, supported)
321 | }
322 | }
323 | }
324 | return res, nil
325 | }
326 |
327 | func simpleDecodeHex(value string) ([]byte, error) {
328 | if strings.HasPrefix(value, "0x") {
329 | value = value[2:]
330 | }
331 | return hex.DecodeString(value)
332 | }
333 |
--------------------------------------------------------------------------------
/jsoncodec/args_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "math/big"
12 | "testing"
13 | )
14 |
15 | func TestArgumentsUnMarshalingTypes_InputCorrectlyStructured(t *testing.T) {
16 | expectedBigInt := big.NewInt(0)
17 | expectedBigInt.SetBytes([]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff})
18 |
19 | tests := []struct {
20 | name string
21 | shouldErr bool
22 | arg *Arg
23 | native interface{}
24 | }{
25 | {"uint32", false, &Arg{"uint32", "19480514"}, uint32(19480514)},
26 | {"uint32-fail", true, &Arg{"uint32", "bad text"}, uint32(0)},
27 | {"uint64", false, &Arg{"uint64", "19480514000000000"}, uint64(19480514000000000)},
28 | {"uint64-fail", true, &Arg{"uint64", "bad text"}, uint64(0)},
29 | {"string", false, &Arg{"string", "hello my name is ?"}, "hello my name is ?"},
30 | {"bytes", false, &Arg{"bytes", "ffee00eeff"}, []byte{0xff, 0xee, 0x00, 0xee, 0xff}},
31 | {"bytes-fail", true, &Arg{"bytes", "yyyy"}, []byte{}},
32 | {"bytes", false, &Arg{"bytes", "ffee00eeff"}, []byte{0xff, 0xee, 0x00, 0xee, 0xff}},
33 | {"bool-false", false, &Arg{"bool", "0"}, false},
34 | {"bool-fail", true, &Arg{"bool", "2"}, false},
35 | {"bytes20", false, &Arg{"bytes20", "0011223344556677889900112233445566778899"}, [20]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}},
36 | {"bytes20-fail", true, &Arg{"bytes20", "yyyy"}, [20]byte{}},
37 | {"bytes20-fail-size", true, &Arg{"bytes20", "00112233445566778899001122334455667788"}, [20]byte{}},
38 | {"bytes32", false, &Arg{"bytes32", "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}, [32]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}},
39 | {"bytes32-fail", true, &Arg{"bytes32", "yyyy"}, [32]byte{}},
40 | {"bytes32-fail-size", true, &Arg{"bytes32", "00112233445566778899aabbccddeeff001122334455667788"}, [32]byte{}},
41 | {"bigint", false, &Arg{"uint256", "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}, expectedBigInt},
42 | {"bigint-fail", true, &Arg{"uint256", "yyyy"}, nil},
43 | {"bigint-fail-size", true, &Arg{"uint256", "00112233445566778899aabbccddeeff001122334455667788"}, nil},
44 | {"unknown type string", true, &Arg{"uint8", "19480514"}, uint32(0)},
45 | // not checking internal translation of single array value as it is done by same function internally
46 | {"uint32Array", false, &Arg{"uint32Array", []interface{}{"19480514", "1"}}, []uint32{uint32(19480514), uint32(1)}},
47 | {"uint64Array", false, &Arg{"uint64Array", []interface{}{"19480514000000000", "1"}}, []uint64{uint64(19480514000000000), uint64(1)}},
48 | {"stringArray", false, &Arg{"stringArray", []interface{}{"hello my name is ?", "what?", "who"}}, []string{"hello my name is ?", "what?", "who"}},
49 | {"bytesArray", false, &Arg{"bytesArray", []interface{}{"ffee00eeff", "00001122"}}, [][]byte{{0xff, 0xee, 0x00, 0xee, 0xff}, {0x00, 0x00, 0x11, 0x22}}},
50 | {"boolArray", false, &Arg{"boolArray", []interface{}{"0", "1", "1", "1"}}, []bool{false, true, true, true}},
51 | {"bytes20Array", false, &Arg{"bytes20Array", []interface{}{"0011223344556677889900112233445566778899"}}, [][20]byte{{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}}},
52 | {"bytes32Array", false, &Arg{"bytes32Array", []interface{}{"00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}}, [][32]byte{{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}},
53 | {"bigintArray", false, &Arg{"uint256Array", []interface{}{"00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}}, []*big.Int{expectedBigInt}},
54 | {"unknown type Array", true, &Arg{"uint8Array", []interface{}{"19480514"}}, uint32(0)},
55 | }
56 |
57 | for _, cTest := range tests {
58 | argList := []*Arg{cTest.arg}
59 | nativeList := []interface{}{cTest.native}
60 |
61 | resNativeList, err := UnmarshalArgs(argList, func(string) *RawKey { return nil })
62 | if cTest.shouldErr {
63 | require.Error(t, err, "unmarshal %s should fail", cTest.name)
64 | } else {
65 | require.NoError(t, err, "unmarshal %s should not fail", cTest.name)
66 | require.EqualValues(t, nativeList, resNativeList)
67 | }
68 | }
69 | }
70 |
71 | func TestArgumentsUnMarshalingTypes_IncorrectInputStructure(t *testing.T) {
72 | tests := []struct {
73 | name string
74 | arg *Arg
75 | }{
76 | {"non-array-type with array-input", &Arg{"uint32", []string{"19480514"}}},
77 | {"array-type with non-array-input", &Arg{"uint32Array", "19480514"}},
78 | {"non-array-input is not string", &Arg{"uint64", 19480514000000000}},
79 | {"array input is not string array", &Arg{"uint64Array", []uint32{10, 20}}},
80 | }
81 |
82 | for _, cTest := range tests {
83 | argList := []*Arg{cTest.arg}
84 |
85 | _, err := UnmarshalArgs(argList, func(string) *RawKey { return nil })
86 | require.Error(t, err, "unmarshal %s should fail", cTest.name)
87 | }
88 | }
89 |
90 | func TestArgumentsMarshaling_GoodFlow(t *testing.T) {
91 | aBigInt := big.NewInt(0)
92 | aBigInt.SetBytes([]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff})
93 |
94 | tests := []struct {
95 | name string
96 | arg *Arg
97 | native interface{}
98 | }{
99 | {"uint32", &Arg{"uint32", "19480514"}, uint32(19480514)},
100 | {"uint64", &Arg{"uint64", "19480514000000000"}, uint64(19480514000000000)},
101 | {"string", &Arg{"string", "hello my name is ?"}, "hello my name is ?"},
102 | {"bytes", &Arg{"bytes", "0xffee00eeff"}, []byte{0xff, 0xee, 0x00, 0xee, 0xff}},
103 | {"bool-true", &Arg{"bool", "1"}, true},
104 | {"bool-false", &Arg{"bool", "0"}, false},
105 | {"bytes20", &Arg{"bytes20", "0x0011223344556677889900112233445566778899"}, [20]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}},
106 | {"bytes32", &Arg{"bytes32", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}, [32]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}},
107 | {"bigint", &Arg{"uint256", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}, aBigInt},
108 | {"uint32Array", &Arg{"uint32Array", []string{"19480514", "1"}}, []uint32{19480514, 1}},
109 | {"uint64Array", &Arg{"uint64Array", []string{"19480514000000000", "1"}}, []uint64{19480514000000000, 1}},
110 | {"stringArray", &Arg{"stringArray", []string{"hello", "my", "name"}}, []string{"hello", "my", "name"}},
111 | {"bytesArray", &Arg{"bytesArray", []string{"0xffee00eeff", "0xffee00eeff"}}, [][]byte{{0xff, 0xee, 0x00, 0xee, 0xff}, {0xff, 0xee, 0x00, 0xee, 0xff}}},
112 | {"boolArray", &Arg{"boolArray", []string{"1", "1", "0"}}, []bool{true, true, false}},
113 | {"uint256Array", &Arg{"uint256Array", []string{"0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"}}, []*big.Int{aBigInt}},
114 | {"bytes20Array", &Arg{"bytes20Array", []string{"0x0011223344556677889900112233445566778899", "0xaa112233445566778899001122334455667788ff"}}, [][20]byte{{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}, {0xaa, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xff}}},
115 | {"bytes32Array", &Arg{"bytes32Array", []string{"0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff", "0xaa112233445566778899aabbccddeeff00112233445566778899aabbccddee11"}}, [][32]byte{{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, {0xaa, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11}}},
116 | }
117 |
118 | for _, cTest := range tests {
119 | argList := []*Arg{cTest.arg}
120 | nativeList := []interface{}{cTest.native}
121 |
122 | resArgList, err := MarshalArgs(nativeList)
123 | require.NoError(t, err, "unmarshal %s should not fail", cTest.name)
124 | require.EqualValues(t, argList, resArgList)
125 | }
126 | }
127 |
128 | func TestArgumentsMarshaling_BadFlow(t *testing.T) {
129 | nativeList := []interface{}{1.0}
130 | _, err := MarshalArgs(nativeList)
131 | require.Error(t, err, "unmarshal %s should fail")
132 | }
133 |
--------------------------------------------------------------------------------
/jsoncodec/config.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import "encoding/json"
10 |
11 | type ConfFile struct {
12 | Environments map[string]*ConfEnv
13 | }
14 |
15 | type ConfEnv struct {
16 | VirtualChain uint32
17 | Endpoints []string
18 | Experimental bool
19 | }
20 |
21 | func UnmarshalConfFile(bytes []byte) (*ConfFile, error) {
22 | var confFile *ConfFile
23 | err := json.Unmarshal(bytes, &confFile)
24 | return confFile, err
25 | }
26 |
--------------------------------------------------------------------------------
/jsoncodec/events.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "github.com/orbs-network/orbs-client-sdk-go/codec"
11 | "github.com/pkg/errors"
12 | )
13 |
14 | type Event struct {
15 | ContractName string
16 | EventName string
17 | Arguments []*Arg
18 | }
19 |
20 | func MarshalEvents(events []*codec.Event) ([]*Event, error) {
21 | res := []*Event{}
22 | for i, event := range events {
23 | eventArgs, err := MarshalArgs(event.Arguments)
24 | if err != nil {
25 | return nil, errors.Errorf("Event %d arguments marshaling failed with %s \n", i+1, err.Error())
26 | }
27 | res = append(res, &Event{
28 | ContractName: event.ContractName,
29 | EventName: event.EventName,
30 | Arguments: eventArgs,
31 | })
32 | }
33 | return res, nil
34 | }
35 |
--------------------------------------------------------------------------------
/jsoncodec/keys.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import "encoding/json"
10 |
11 | type Key struct {
12 | PrivateKey string // hex string starting with 0x
13 | PublicKey string // hex string starting with 0x
14 | Address string // hex string starting with 0x
15 | }
16 |
17 | type RawKey struct {
18 | PrivateKey []byte
19 | PublicKey []byte
20 | Address []byte
21 | }
22 |
23 | func UnmarshalKeys(bytes []byte) (map[string]*Key, error) {
24 | keys := make(map[string]*Key)
25 | err := json.Unmarshal(bytes, &keys)
26 | return keys, err
27 | }
28 |
29 | func MarshalKeys(keys map[string]*Key) ([]byte, error) {
30 | return json.MarshalIndent(keys, "", " ")
31 | }
32 |
--------------------------------------------------------------------------------
/jsoncodec/read.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "encoding/json"
11 | "github.com/orbs-network/orbs-client-sdk-go/codec"
12 | "github.com/pkg/errors"
13 | "strconv"
14 | )
15 |
16 | type Read struct {
17 | ContractName string
18 | MethodName string
19 | Arguments []*Arg
20 | }
21 |
22 | func UnmarshalRead(bytes []byte) (*Read, error) {
23 | var read *Read
24 | err := json.Unmarshal(bytes, &read)
25 | return read, err
26 | }
27 |
28 | func MarshalReadResponse(r *codec.RunQueryResponse) ([]byte, error) {
29 | outputArgs, err := MarshalArgs(r.OutputArguments)
30 | if err != nil {
31 | return nil, errors.Errorf("Read response marshaling output arguments failed with %s \n", err.Error())
32 | }
33 | outputEvents, err := MarshalEvents(r.OutputEvents)
34 | if err != nil {
35 | return nil, errors.Errorf("Read response marshaling output events failed with %s \n", err.Error())
36 | }
37 | return json.MarshalIndent(&struct {
38 | RequestStatus codec.RequestStatus
39 | ExecutionResult codec.ExecutionResult
40 | OutputArguments []*Arg
41 | OutputEvents []*Event
42 | BlockHeight string
43 | BlockTimestamp string
44 | }{
45 | RequestStatus: r.RequestStatus,
46 | ExecutionResult: r.ExecutionResult,
47 | OutputArguments: outputArgs,
48 | OutputEvents: outputEvents,
49 | BlockHeight: strconv.FormatUint(r.BlockHeight, 10),
50 | BlockTimestamp: r.BlockTimestamp.UTC().Format(codec.ISO_DATE_FORMAT),
51 | }, "", " ")
52 | }
53 |
--------------------------------------------------------------------------------
/jsoncodec/send_tx.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "encoding/json"
11 | "github.com/orbs-network/orbs-client-sdk-go/codec"
12 | "github.com/pkg/errors"
13 | "strconv"
14 | )
15 |
16 | type SendTx struct {
17 | ContractName string
18 | MethodName string
19 | Arguments []*Arg
20 | }
21 |
22 | func UnmarshalSendTx(bytes []byte) (*SendTx, error) {
23 | var sendTx *SendTx
24 | err := json.Unmarshal(bytes, &sendTx)
25 | return sendTx, err
26 | }
27 |
28 | func MarshalSendTxResponse(r *codec.SendTransactionResponse, txId string) ([]byte, error) {
29 | outputArgs, err := MarshalArgs(r.OutputArguments)
30 | if err != nil {
31 | return nil, errors.Errorf("Send Tx response marshaling output arguments failed with %s \n", err.Error())
32 | }
33 | outputEvents, err := MarshalEvents(r.OutputEvents)
34 | if err != nil {
35 | return nil, errors.Errorf("Send Tx response marshaling output events failed with %s \n", err.Error())
36 | }
37 | return json.MarshalIndent(&struct {
38 | RequestStatus codec.RequestStatus
39 | TxId string
40 | ExecutionResult codec.ExecutionResult
41 | OutputArguments []*Arg
42 | OutputEvents []*Event
43 | TransactionStatus codec.TransactionStatus
44 | BlockHeight string
45 | BlockTimestamp string
46 | }{
47 | RequestStatus: r.RequestStatus,
48 | TxId: txId,
49 | ExecutionResult: r.ExecutionResult,
50 | OutputArguments: outputArgs,
51 | OutputEvents: outputEvents,
52 | TransactionStatus: r.TransactionStatus,
53 | BlockHeight: strconv.FormatUint(r.BlockHeight, 10),
54 | BlockTimestamp: r.BlockTimestamp.UTC().Format(codec.ISO_DATE_FORMAT),
55 | }, "", " ")
56 | }
57 |
--------------------------------------------------------------------------------
/jsoncodec/tx_proof.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "encoding/hex"
11 | "encoding/json"
12 | "github.com/orbs-network/gamma-cli/crypto/digest"
13 | "github.com/orbs-network/orbs-client-sdk-go/codec"
14 | "github.com/pkg/errors"
15 | "strconv"
16 | )
17 |
18 | func MarshalTxProofResponse(r *codec.GetTransactionReceiptProofResponse) ([]byte, error) {
19 | outputArgs, err := MarshalArgs(r.OutputArguments)
20 | if err != nil {
21 | return nil, errors.Errorf("Tx proof response marshaling output arguments failed with %s \n", err.Error())
22 | }
23 | outputEvents, err := MarshalEvents(r.OutputEvents)
24 | if err != nil {
25 | return nil, errors.Errorf("Tx proof response marshaling output events failed with %s \n", err.Error())
26 | }
27 | return json.MarshalIndent(&struct {
28 | RequestStatus codec.RequestStatus
29 | ExecutionResult codec.ExecutionResult
30 | OutputArguments []*Arg
31 | OutputEvents []*Event
32 | TransactionStatus codec.TransactionStatus
33 | BlockHeight string
34 | BlockTimestamp string
35 | PackedProof string
36 | PackedReceipt string
37 | ProofSigners []string
38 | }{
39 | RequestStatus: r.RequestStatus,
40 | ExecutionResult: r.ExecutionResult,
41 | OutputArguments: outputArgs,
42 | OutputEvents: outputEvents,
43 | TransactionStatus: r.TransactionStatus,
44 | BlockHeight: strconv.FormatUint(r.BlockHeight, 10),
45 | BlockTimestamp: r.BlockTimestamp.UTC().Format(codec.ISO_DATE_FORMAT),
46 | PackedProof: "0x" + hex.EncodeToString(r.PackedProof),
47 | PackedReceipt: "0x" + hex.EncodeToString(r.PackedReceipt),
48 | ProofSigners: getProofSignersFromPackedProof(r.PackedProof),
49 | }, "", " ")
50 | }
51 |
52 | func getProofSignersFromPackedProof(packedProof []byte) []string {
53 | nodeAddresses, err := digest.GetBlockSignersFromReceiptProof(packedProof)
54 | if err != nil {
55 | return nil
56 | }
57 | var res []string
58 | for _, nodeAddress := range nodeAddresses {
59 | signerString := "0x" + hex.EncodeToString(nodeAddress)
60 | res = append(res, signerString)
61 | }
62 | return res
63 | }
64 |
--------------------------------------------------------------------------------
/jsoncodec/tx_status.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package jsoncodec
8 |
9 | import (
10 | "encoding/json"
11 | "github.com/orbs-network/orbs-client-sdk-go/codec"
12 | "github.com/pkg/errors"
13 | "strconv"
14 | )
15 |
16 | func MarshalTxStatusResponse(r *codec.GetTransactionStatusResponse) ([]byte, error) {
17 | outputArgs, err := MarshalArgs(r.OutputArguments)
18 | if err != nil {
19 | return nil, errors.Errorf("Tx status response marshaling output arguments failed with %s \n", err.Error())
20 | }
21 | outputEvents, err := MarshalEvents(r.OutputEvents)
22 | if err != nil {
23 | return nil, errors.Errorf("Tx status response marshaling output events failed with %s \n", err.Error())
24 | }
25 | return json.MarshalIndent(&struct {
26 | RequestStatus codec.RequestStatus
27 | ExecutionResult codec.ExecutionResult
28 | OutputArguments []*Arg
29 | OutputEvents []*Event
30 | TransactionStatus codec.TransactionStatus
31 | BlockHeight string
32 | BlockTimestamp string
33 | }{
34 | RequestStatus: r.RequestStatus,
35 | ExecutionResult: r.ExecutionResult,
36 | OutputArguments: outputArgs,
37 | OutputEvents: outputEvents,
38 | TransactionStatus: r.TransactionStatus,
39 | BlockHeight: strconv.FormatUint(r.BlockHeight, 10),
40 | BlockTimestamp: r.BlockTimestamp.UTC().Format(codec.ISO_DATE_FORMAT),
41 | }, "", " ")
42 | }
43 |
--------------------------------------------------------------------------------
/keys.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "github.com/orbs-network/crypto-lib-go/crypto/encoding"
12 | "github.com/orbs-network/gamma-cli/jsoncodec"
13 | "github.com/orbs-network/orbs-client-sdk-go/orbs"
14 | "io/ioutil"
15 | )
16 |
17 | func commandGenerateTestKeys(requiredOptions []string) {
18 | keys := make(map[string]*jsoncodec.Key)
19 | for i := 0; i < 10; i++ {
20 | account, err := orbs.CreateAccount()
21 | if err != nil {
22 | die("Could not create Orbs account.")
23 | }
24 | user := fmt.Sprintf("user%d", i+1)
25 | keys[user] = &jsoncodec.Key{
26 | PrivateKey: encoding.EncodeHex(account.PrivateKey),
27 | PublicKey: encoding.EncodeHex(account.PublicKey),
28 | Address: account.Address,
29 | }
30 | }
31 |
32 | bytes, err := jsoncodec.MarshalKeys(keys)
33 | if err != nil {
34 | die("Could not encode keys to json.\n\n%s", err.Error())
35 | }
36 |
37 | filename := *flagKeyFile
38 | if filename == "" {
39 | filename = TEST_KEYS_FILENAME
40 | }
41 | err = ioutil.WriteFile(filename, bytes, 0644)
42 | if err != nil {
43 | die("Could not write keys to file.\n\n%s", err.Error())
44 | }
45 |
46 | if !doesFileExist(filename) {
47 | die("File not found after write.")
48 | }
49 |
50 | log("10 new test keys written successfully to '%s'.\n", filename)
51 | }
52 |
53 | func getTestKeyFromFile(id string) *jsoncodec.RawKey {
54 | if !doesFileExist(*flagKeyFile) {
55 | commandGenerateTestKeys(nil)
56 | }
57 |
58 | bytes, err := ioutil.ReadFile(*flagKeyFile)
59 | if err != nil {
60 | die("Could not open keys file '%s'.\n\n%s", *flagKeyFile, err.Error())
61 | }
62 |
63 | keys, err := jsoncodec.UnmarshalKeys(bytes)
64 | if err != nil {
65 | die("Failed parsing keys json file '%s'. Try deleting the key file to have it automatically recreated.\n\n%s", *flagKeyFile, err.Error())
66 | }
67 |
68 | key, found := keys[id]
69 | if !found {
70 | die("Key with id '%s' not found in key file '%s'.", id, *flagKeyFile)
71 | }
72 |
73 | privateKey, err := encoding.DecodeHex(key.PrivateKey)
74 | if err != nil {
75 | die("Could not parse hex string '%s'. Try deleting the key file '%s' to have it automatically recreated.\n\n%s", privateKey, *flagKeyFile, err.Error())
76 | }
77 |
78 | publicKey, err := encoding.DecodeHex(key.PublicKey)
79 | if err != nil {
80 | die("Could not parse hex string '%s'. Try deleting the key file '%s' to have it automatically recreated.\n\n%s", publicKey, *flagKeyFile, err.Error())
81 | }
82 |
83 | address, err := encoding.DecodeHex(key.Address)
84 | if err != nil {
85 | die("Could not parse hex string '%s'. Try deleting the key file '%s' to have it automatically recreated.\n\n%s", address, *flagKeyFile, err.Error())
86 | }
87 |
88 | res := &jsoncodec.RawKey{
89 | PrivateKey: privateKey,
90 | PublicKey: publicKey,
91 | Address: address,
92 | }
93 |
94 | return res
95 | }
96 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "flag"
11 | "fmt"
12 | "os"
13 | "strings"
14 | )
15 |
16 | var GAMMA_CLI_VERSION string
17 | const CONFIG_FILENAME = "orbs-gamma-config.json"
18 | const TEST_KEYS_FILENAME = "orbs-test-keys.json"
19 | const LOCAL_ENV_ID = "local"
20 | const EXPERIMENTAL_ENV_ID = "experimental"
21 |
22 | type handlerOptions struct {
23 | name string
24 |
25 | dockerRepo string
26 | dockerCmd []string
27 | containerName string
28 | dockerRegistryTagsUrl string
29 |
30 | env []string
31 |
32 | port int
33 | containerPort int
34 | }
35 |
36 | type handler func([]string)
37 |
38 | type command struct {
39 | desc string
40 | args string
41 | example string
42 | example2 string
43 | handler
44 | sort int
45 | requiredOptions []string
46 | }
47 |
48 | func gammaHandlerOptions() handlerOptions {
49 | return handlerOptions{
50 | name: "Orbs Gamma personal blockchain",
51 | dockerRepo: "orbsnetwork/gamma",
52 | dockerCmd: []string{"./gamma-server", "-override-config", *flagOverrideConfig},
53 | containerName: "orbs-gamma-server",
54 | dockerRegistryTagsUrl: "https://registry.hub.docker.com/v2/repositories/orbsnetwork/gamma/tags/",
55 | port: *flagPort,
56 | containerPort: 8080,
57 | }
58 | }
59 |
60 | func prismHandlerOptions() handlerOptions {
61 | return handlerOptions{
62 | name: "Prism blockchain explorer",
63 | dockerRepo: "orbsnetwork/prism",
64 | containerName: "orbs-prism",
65 | dockerRegistryTagsUrl: "https://registry.hub.docker.com/v2/repositories/orbsnetwork/prism/tags/",
66 | port: *flagPrismPort,
67 | containerPort: 3000,
68 | env: []string{
69 | "ORBS_VIRTUAL_CHAIN_ID=42",
70 | "NODE_ENV=staging",
71 | "DATABASE_TYPE=inmemory",
72 | "GAP_FILLER_ACTIVE=true",
73 | fmt.Sprintf("ORBS_ENDPOINT=http://orbs-gamma-server:8080"),
74 | },
75 | }
76 | }
77 |
78 | var commands = map[string]*command{
79 | "start-local": {
80 | desc: "start a local Orbs personal blockchain instance listening on port",
81 | args: "-port -override-config {json}",
82 | example: "gamma-cli start-local -port 8080",
83 | handler: commandStartLocal,
84 | sort: 0,
85 | requiredOptions: nil,
86 | },
87 | "stop-local": {
88 | desc: "stop a locally running Orbs personal blockchain instance",
89 | handler: commandStopLocal,
90 | sort: 1,
91 | requiredOptions: nil,
92 | },
93 | "gen-test-keys": {
94 | desc: "generate a new batch of 10 test keys and store in " + TEST_KEYS_FILENAME + " (default filename)",
95 | args: "-keys [OUTPUT_FILE]",
96 | example: "gamma-cli gen-test-keys -keys " + TEST_KEYS_FILENAME,
97 | handler: commandGenerateTestKeys,
98 | sort: 2,
99 | requiredOptions: nil,
100 | },
101 | "deploy": {
102 | desc: "deploy a smart contract with the code specified in the source file ",
103 | args: " -name [CONTRACT_NAME] -signer [ID_FROM_KEYS_JSON]",
104 | example: "gamma-cli deploy MyToken.go -signer user1",
105 | example2: "gamma-cli deploy contract.go -name MyToken",
106 | handler: commandDeploy,
107 | sort: 3,
108 | requiredOptions: []string{" - path of file with source code"},
109 | },
110 | "send-tx": {
111 | desc: "sign and send the transaction specified in the JSON file ",
112 | args: " -arg# [OVERRIDE_ARG_#] -signer [ID_FROM_KEYS_JSON]",
113 | example: "gamma-cli send-tx transfer.json -signer user1",
114 | example2: "gamma-cli send-tx transfer.json -arg2 0x5B63Ca66637316A0D7f84Ebf60E50963c10059aD",
115 | handler: commandSendTx,
116 | sort: 4,
117 | requiredOptions: []string{" - path of JSON file with transaction details"},
118 | },
119 | "run-query": {
120 | desc: "read state or run a read-only contract method as specified in the JSON file ",
121 | args: " -arg# [OVERRIDE_ARG_#] -signer [ID_FROM_KEYS_JSON]",
122 | example: "gamma-cli run-query get-balance.json -signer user1",
123 | example2: "gamma-cli run-query get-balance.json -arg1 0x5B63Ca66637316A0D7f84Ebf60E50963c10059aD",
124 | handler: commandRunQuery,
125 | sort: 5,
126 | requiredOptions: []string{" - path of JSON file with query details"},
127 | },
128 | "tx-status": {
129 | desc: "get the current status of a sent transaction with txid (from send-tx response)",
130 | args: "",
131 | example: "gamma-cli tx-status 0xB68fa95B7f397815Ddf41150d79b27a888448a22e08DeAf8600E7a495c406303659f8C3782614660",
132 | handler: commandTxStatus,
133 | sort: 6,
134 | requiredOptions: []string{" - txid of previously sent transaction, from send-tx response"},
135 | },
136 | "tx-proof": {
137 | desc: "get cryptographic proof for transaction receipt with txid (from send-tx response)",
138 | args: "",
139 | example: "gamma-cli tx-proof 0xB68fa95B7f397815Ddf41150d79b27a888448a22e08DeAf8600E7a495c406303659f8C3782614660",
140 | handler: commandTxProof,
141 | sort: 7,
142 | requiredOptions: []string{" - txid of previously sent transaction, from send-tx response"},
143 | },
144 | "upgrade-server": {
145 | desc: "upgrade to the latest stable version of Gamma server",
146 | example: "gamma-cli upgrade-server",
147 | example2: "gamma-cli upgrade-server -env experimental",
148 | handler: commandUpgrade,
149 | sort: 8,
150 | requiredOptions: nil,
151 | },
152 | "logs": {
153 | desc: "streams logs from gamma that are printed by smart contract to stdout (i.e. println())",
154 | handler: showLogs,
155 | sort: 9,
156 | example: "gamma-cli logs",
157 | requiredOptions: nil,
158 | },
159 | "version": {
160 | desc: "print gamma-cli and Gamma server versions",
161 | handler: commandVersion,
162 | sort: 10,
163 | requiredOptions: nil,
164 | },
165 | "help": {
166 | desc: "print this help screen",
167 | sort: 11,
168 | requiredOptions: nil,
169 | },
170 | }
171 |
172 | var (
173 | flagPort = flag.Int("port", 8080, "listening port for Gamma server")
174 | flagPrismPort = flag.Int("prismPort", 3000, "listening port for Prism blockchain explorer")
175 | flagSigner = flag.String("signer", "user1", "id of the signing key from the test key json")
176 | flagContractName = flag.String("name", "", "name of the smart contract being deployed")
177 | flagKeyFile = flag.String("keys", TEST_KEYS_FILENAME, "name of the json file containing test keys")
178 | flagConfigFile = flag.String("config", CONFIG_FILENAME, "path to config file")
179 | flagEnv = flag.String("env", LOCAL_ENV_ID, "environment from config file containing server connection details")
180 | flagWait = flag.Bool("wait", false, "wait until Gamma server is ready and listening")
181 | flagNoUi = flag.Bool("no-ui", false, "do not start Prism blockchain explorer")
182 | flagOverrideConfig = flag.String("override-config", "{}", "option json for overriding config values, same format as file-based config")
183 |
184 | // args (hidden from help)
185 | flagArg1 = flag.String("arg1", "", "")
186 | flagArg2 = flag.String("arg2", "", "")
187 | flagArg3 = flag.String("arg3", "", "")
188 | flagArg4 = flag.String("arg4", "", "")
189 | flagArg5 = flag.String("arg5", "", "")
190 | flagArg6 = flag.String("arg6", "", "")
191 | flagArg7 = flag.String("arg7", "", "")
192 | flagArg8 = flag.String("arg8", "", "")
193 | flagArg9 = flag.String("arg9", "", "")
194 | )
195 |
196 | func main() {
197 | flag.Usage = func() { commandShowHelp(nil) }
198 | commands["help"].handler = commandShowHelp
199 |
200 | if len(os.Args) <= 1 {
201 | commandShowHelp(nil)
202 | }
203 | cmdName := os.Args[1]
204 | cmd, found := commands[cmdName]
205 | if !found {
206 | die("Command '%s' not found, run 'gamma-cli help' to see available commands.", cmdName)
207 | }
208 |
209 | requiredOptions := []string{}
210 | if len(cmd.requiredOptions) > 0 {
211 | if len(os.Args) < 2+len(cmd.requiredOptions) {
212 | die("Command '%s' is missing required arguments %v.", cmdName, cmd.requiredOptions)
213 | }
214 | requiredOptions = os.Args[2 : 2+len(cmd.requiredOptions)]
215 | for i, requiredOption := range requiredOptions {
216 | if strings.HasPrefix(requiredOption, "-") {
217 | die("Command '%s' argument %d should be %s.", cmdName, i+1, cmd.requiredOptions[i])
218 | }
219 | }
220 | }
221 |
222 | os.Args = os.Args[2+len(cmd.requiredOptions)-1:]
223 | flag.Parse()
224 |
225 | cmd.handler(requiredOptions)
226 | }
227 |
228 | func log(format string, args ...interface{}) {
229 | fmt.Fprintf(os.Stdout, format, args...)
230 | fmt.Fprintf(os.Stdout, "\n")
231 | }
232 |
233 | func die(format string, args ...interface{}) {
234 | fmt.Fprintf(os.Stderr, "ERROR:\n ")
235 | fmt.Fprintf(os.Stderr, format, args...)
236 | fmt.Fprintf(os.Stderr, "\n\n")
237 | os.Exit(2)
238 | }
239 |
240 | func exit() {
241 | os.Exit(0)
242 | }
243 |
244 | func doesFileExist(filename string) bool {
245 | _, err := os.Stat(filename)
246 | return !os.IsNotExist(err)
247 | }
248 |
--------------------------------------------------------------------------------
/marketplace/gamma-devkit-google-deployment-guide.md:
--------------------------------------------------------------------------------
1 | # Google Cloud Launcher
2 | This guide will cover the basics (and more!) of deploying the Orbs Gamma Testkit atop Google Cloud Platform from the GCP Marketplace using the Google Cloud Launcher. As a part of this guide, we will be deploying an instance of the kit, verify that it's running correctly and get a taste of how to develop and test your smart contracts using it to emphasize just how easy it is to develop on blockchain with Orbs!
3 |
4 | ## Deploying
5 | First, we're going to deploy an Orbs development kit.
6 | The kit consists of:
7 | * Gamma server - Our development local blockchain which stores our data and answers our calls)
8 | * Gamma CLI - The CLI allows us to easily deploy contracts onto the blockchain and perform calls against our deployed contract.
9 | * Prism - Orbs' block explorer, which provides visibility into blocks and transactions which have been registered on our network.
10 |
11 | Deploying is easy with Cloud Launcher: Go to https://console.cloud.google.com/launcher/details/orbsltd-public/orbs-gamma-devkit
12 |
13 | 
14 |
15 | Click "Launch on Compute Engine"
16 |
17 | 
18 |
19 | You can take the default settings or customize them. When complete click "Deploy"
20 |
21 | 
22 |
23 | That's it! Your development kit is now deploying.
24 |
25 | ## Inspecting the kit once it's running
26 |
27 | When the deployment is complete, you should see:
28 |
29 | 
30 |
31 | Note: Gamma, the development server, is configured to close a block once every 10 minutes or so, OR when at least 1 transaction is pushed through with an API call.
32 |
33 | At this point, you can open a web browser and view Prism to see block activity. Click on the "Visit the site" button.
34 |
35 | 
36 |
37 | Once the browser has finished loading, it should look like:
38 |
39 | 
40 |
41 | You should see a few blocks. That's great as it shows our development kit is working and closing blocks.
42 |
43 | That means we can start to play around with it.
44 |
45 | The next kind of interaction we can have with our development kit is to deploy a smart contract into the blockchain and interact with it.
46 |
47 | ## Developing with the deployed development kit
48 |
49 | At the moment Prism and our Blockchain server are running and looks to be closing blocks, which means it's healthy.
50 |
51 | Next, we connect to the machine running our Gamma server so we can use Gamma CLI and deploy our first contract. We'll do so by clicking on "Connect":
52 |
53 | 
54 |
55 | Google Cloud negotiates the SSH keys between our browser and the target machine in about 10 seconds. There are other means of accessing the machine via SSH. We are merely illustrating the most straightforward approach here for the sake of keeping things simple.
56 |
57 | 
58 |
59 | Once inside the machine, our Terminal (which is in a new pop up window) should look like the following:
60 |
61 | 
62 |
63 | Let's get some example contracts from [Orbs Contract SDK](https://github.com/orbs-network/orbs-contract-sdk) repository by running `git clone https://github.com/orbs-network/orbs-contract-sdk.git` within the terminal window.
64 |
65 | (Tip: you might be prompted to approve the authenticity of github.com. Type `yes` into the Terminal if asked.)
66 |
67 | 
68 |
69 | Let's navigate to the examples folder and into the Counter contract by typing `cd orbs-contract-sdk/go/examples/counter/` into the terminal window. The Counter contract is a very simple contract that initializes an empty state variable, which we can be increased with a call to the `add()` function. In addition, we can also access the current counter value by invoking a call to the contract's `get()` function.
70 |
71 | In the Terminal you should be located at the folder containing the file `contract.go`. Let's verify this by typing `ls -lh` into the Terminal to ensure we can see the file is there.
72 |
73 | 
74 |
75 | Next, we can deploy the contract into our Gamma server by typing the following command: `gamma-cli deploy contract.go -name MyCounter` and wait for it to finish. Once finished, Gamma CLI will return a JSON output object representing the result of our transaction against the server. Which (if all is successful) should look similar to the following
76 |
77 | 
78 |
79 | Please note the 2 most important properties in the JSON object:
80 |
81 | * The `ExecutionResult` provides the most basic kind of proof that the request was successful or not. In this case, we can see that the call was successful.
82 | * The `TransactionStatus` is very important. Since this is a blockchain, our transaction might not have been committed into any block yet which means it is not final, and therefore might be pending (or worse - not accepted at all into the ledger). In our case, we can see it's in the `COMMITTED` state so we can rest assure our contract is deployed successfully!
83 |
84 | Congrats! You have successfully deployed your first smart contract! How easy was that?!?
85 |
86 | Ok so what's next? If we look closely at our smart contract code, we can see it's initializing the counter value with a value of `0`.
87 |
88 | 
89 |
90 | Since our contract is now deployed, let's try and "read" the current value of the counter to make sure we get a value of `0` back.
91 |
92 | Gamma CLI uses a JSON file to represent the action details we're requesting against the blockchain. Our Counter example has JSON files ready for us to experiment with. The `get()` method doesn't need any arguments. The JSON descriptor file is quite easy to understand. Let's have a look at it:
93 |
94 | Type into the terminal window `cat json/get.json` (cat is a command in Linux to view the content of a file)
95 |
96 | 
97 |
98 | Note that this file is specifically asking to invoke the `get()` method of the `MyCounter` contract. That name is important as we used it previously to name our contract upon deployment. If you chose a different name, you have to edit this file before sending a request with Gamma CLI using this file.
99 |
100 | Alright, so now that we have some sense about what gamma is using to send our request to the local blockchain server (Gamma), let's issue a "Query" call and invoke the `get()` command of our contract.
101 |
102 | We do that by typing in the terminal `gamma-cli run-query json/get.json`
103 |
104 | 
105 |
106 | Again, the returned output contains a bit of information. We've highlighted what's most important for us at this stage, and that's the current value of the counter state variable. We know it's supposed to be 0, but we wanted to verify that. Indeed as it appears by the highlighted red rectangle, the value is a `uint64` (a native number) of `0`.
107 |
108 | All looks good so far!
109 |
110 | Now let's make things interesting by running a transaction that adds '25` to that lonely `0` to increase the counter!
111 |
112 | As before, let's view how the JSON file to describe this action is represented for Gamma CLI to use by typing `cat json/add-25.json`
113 |
114 | 
115 |
116 | Notice how we have an argument in this call in the form of a `uint64` (native number) with a value of 25, which will be added to the counter upon running this transaction with Gamma CLI.
117 |
118 | To make this happen, we issue the request with Gamma CLI by typing the following into the Terminal: `gamma-cli send-tx json/add-25.json`
119 |
120 | and the input from this call should look something similar to the following:
121 |
122 | 
123 |
124 | As you can see, the response seems to be successful! We've got an `ExecutionResult` of `SUCCESS`, which is excellent. It means our transaction went through and was also `COMMITTED` into a block which is accepted by the network there being committed to the ledger. That's great news! We've modified the state of our contract now and updated the counter variable in its state to represent a different value (25).
125 |
126 | Let's verify this is indeed the reality by issuing another `get()` call and assert that we get 25 and not 0 as before.
127 |
128 | 
129 |
130 | Yes!
131 | As expected we can see that the blockchain has returned us the current value of the counter, and it's now standing on 25 instead of the previous 0 that it once was. So everything is working!
132 |
133 | ## Next Steps
134 |
135 | You've probably noticed that we've used `send-tx` and `run-query` on some of these calls. The `send-tx` is used for transactions which aim to change the state of a contract and perform and actual action. Whereas the `run-query` calls are usually "reading" information that is already present and doesn't require the heavy lifting of the consensus process to occur between the blockchain nodes as happens on a transaction.
136 |
137 | To read more about this and learn more about blockchain in general and how to move forward into more complex examples using Orbs be sure to [visit our GitBook](https://orbs.gitbook.io/contract-sdk/).
138 |
139 | To learn more about Orbs and it's mission feel free to [visit our website](https://www.orbs.com/).
140 |
--------------------------------------------------------------------------------
/marketplace/images/step01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step01.png
--------------------------------------------------------------------------------
/marketplace/images/step02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step02.png
--------------------------------------------------------------------------------
/marketplace/images/step03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step03.png
--------------------------------------------------------------------------------
/marketplace/images/step04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step04.png
--------------------------------------------------------------------------------
/marketplace/images/step05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step05.png
--------------------------------------------------------------------------------
/marketplace/images/step06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step06.png
--------------------------------------------------------------------------------
/marketplace/images/step07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step07.png
--------------------------------------------------------------------------------
/marketplace/images/step08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step08.png
--------------------------------------------------------------------------------
/marketplace/images/step09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step09.png
--------------------------------------------------------------------------------
/marketplace/images/step10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step10.png
--------------------------------------------------------------------------------
/marketplace/images/step11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step11.png
--------------------------------------------------------------------------------
/marketplace/images/step12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step12.png
--------------------------------------------------------------------------------
/marketplace/images/step13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step13.png
--------------------------------------------------------------------------------
/marketplace/images/step14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step14.png
--------------------------------------------------------------------------------
/marketplace/images/step15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step15.png
--------------------------------------------------------------------------------
/marketplace/images/step16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step16.png
--------------------------------------------------------------------------------
/marketplace/images/step17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step17.png
--------------------------------------------------------------------------------
/marketplace/images/step18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orbs-network/gamma-cli/700a7eff99b768491e35058853a66ae399d778f3/marketplace/images/step18.png
--------------------------------------------------------------------------------
/marketplace/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | # Cleanup a gamma-server container in case there is one
4 | docker rm -fv orbs-gamma-server orbs-prism
5 | docker pull orbsnetwork/gamma:v1.2.2
6 |
7 | GAMMA_CLI_VERSION="v0.9.0"
8 | GAMMA_CLI_URL="https://github.com/orbs-network/gamma-cli/releases/download/$GAMMA_CLI_VERSION/gammacli-linux-x86-64-$GAMMA_CLI_VERSION.tar.gz"
9 |
10 | echo "Downloading pre-built gamma-cli ($GAMMA_CLI_VERSION) from it's official GitHub release repository.."
11 | wget $GAMMA_CLI_URL
12 | tar -zxvf "gammacli-linux-x86-64-$GAMMA_CLI_VERSION.tar.gz"
13 | sudo mv _bin/gamma-cli /usr/bin/gamma-cli
14 |
15 | echo "gamma-cli and gamma-server successfully installed"
16 |
17 | gamma-cli start-local
18 |
--------------------------------------------------------------------------------
/public_api.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "encoding/json"
11 | "fmt"
12 | "github.com/orbs-network/gamma-cli/jsoncodec"
13 | "github.com/orbs-network/orbs-client-sdk-go/codec"
14 | "github.com/orbs-network/orbs-client-sdk-go/orbs"
15 | "github.com/pkg/errors"
16 | "io/ioutil"
17 | "net"
18 | "net/url"
19 | "os"
20 | "path"
21 | "strings"
22 | "syscall"
23 | )
24 |
25 | const DEPLOY_SYSTEM_CONTRACT_NAME = "_Deployments"
26 | const DEPLOY_SYSTEM_METHOD_NAME = "deployService"
27 | const PROCESSOR_TYPE_NATIVE = uint32(1)
28 | const PROCESSOR_TYPE_JAVASCRIPT = uint32(2)
29 |
30 | func _getSource(name string) (code [][]byte, err error) {
31 | if info, err := os.Stat(name); err != nil {
32 | return nil, err
33 | } else if info.IsDir() {
34 | return orbs.ReadSourcesFromDir(name)
35 | } else {
36 | singleFile, err := ioutil.ReadFile(name)
37 | if err != nil {
38 | return nil, err
39 | }
40 |
41 | return [][]byte{singleFile}, err
42 | }
43 | }
44 |
45 | func commandDeploy(requiredOptions []string) {
46 | codeFile := requiredOptions[0]
47 |
48 | if *flagContractName == "" {
49 | *flagContractName = getFilenameWithoutExtension(codeFile)
50 | }
51 |
52 | code, err := _getSource(codeFile)
53 | if err != nil {
54 | die("Could not find path\n\n%s", err.Error())
55 | }
56 |
57 | signer := getTestKeyFromFile(*flagSigner)
58 |
59 | client := createOrbsClient()
60 |
61 | payload, txId, err := client.CreateDeployTransaction(signer.PublicKey, signer.PrivateKey, string(*flagContractName), orbs.PROCESSOR_TYPE_NATIVE, code...)
62 | if err != nil {
63 | die("Could not encode payload of the message about to be sent to server.\n\n%s", err.Error())
64 | }
65 |
66 | response, clientErr := client.SendTransaction(payload)
67 | handleNoConnectionGracefully(clientErr, client)
68 | if response != nil {
69 | output, err := jsoncodec.MarshalSendTxResponse(response, txId)
70 | if err != nil {
71 | die("Could not encode send-tx response to json.\n\n%s", err.Error())
72 | }
73 |
74 | log("%s\n", string(output))
75 | exit()
76 | }
77 |
78 | if clientErr != nil {
79 | die("Request transaction failed on server.\n\n%s", clientErr.Error())
80 | }
81 | }
82 |
83 | func commandSendTx(requiredOptions []string) {
84 | inputFile := requiredOptions[0]
85 |
86 | signer := getTestKeyFromFile(*flagSigner)
87 |
88 | bytes, err := ioutil.ReadFile(inputFile)
89 | if err != nil {
90 | die("Could not open input file.\n\n%s", err.Error())
91 | }
92 |
93 | sendTx, err := jsoncodec.UnmarshalSendTx(bytes)
94 | if err != nil {
95 | die("Failed parsing input json file '%s'.\n\n%s", inputFile, err.Error())
96 | }
97 |
98 | // override contract name
99 | if *flagContractName != "" {
100 | sendTx.ContractName = *flagContractName
101 | }
102 |
103 | overrideArgsWithFlags(sendTx.Arguments)
104 | inputArgs, err := jsoncodec.UnmarshalArgs(sendTx.Arguments, getTestKeyFromFile)
105 | if err != nil {
106 | die(err.Error())
107 | }
108 |
109 | client := createOrbsClient()
110 |
111 | payload, txId, err := client.CreateTransaction(signer.PublicKey, signer.PrivateKey, sendTx.ContractName, sendTx.MethodName, inputArgs...)
112 | if err != nil {
113 | die("Could not encode payload of the message about to be sent to server.\n\n%s", err.Error())
114 | }
115 |
116 | response, clientErr := client.SendTransaction(payload)
117 | handleNoConnectionGracefully(clientErr, client)
118 | if response != nil {
119 | output, err := jsoncodec.MarshalSendTxResponse(response, txId)
120 | if err != nil {
121 | die("Could not encode send-tx response to json.\n\n%s", err.Error())
122 | }
123 |
124 | log("%s\n", string(output))
125 | exit()
126 | }
127 |
128 | if clientErr != nil {
129 | die("Request send-tx failed on server.\n\n%s", clientErr.Error())
130 | }
131 | }
132 |
133 | func commandRunQuery(requiredOptions []string) {
134 | inputFile := requiredOptions[0]
135 |
136 | signer := getTestKeyFromFile(*flagSigner)
137 |
138 | bytes, err := ioutil.ReadFile(inputFile)
139 | if err != nil {
140 | die("Could not open input file.\n\n%s", err.Error())
141 | }
142 |
143 | runQuery, err := jsoncodec.UnmarshalRead(bytes)
144 | if err != nil {
145 | die("Failed parsing input json file '%s'.\n\n%s", inputFile, err.Error())
146 | }
147 |
148 | // override contract name
149 | if *flagContractName != "" {
150 | runQuery.ContractName = *flagContractName
151 | }
152 |
153 | overrideArgsWithFlags(runQuery.Arguments)
154 | inputArgs, err := jsoncodec.UnmarshalArgs(runQuery.Arguments, getTestKeyFromFile)
155 | if err != nil {
156 | die(err.Error())
157 | }
158 |
159 | client := createOrbsClient()
160 |
161 | payload, err := client.CreateQuery(signer.PublicKey, runQuery.ContractName, runQuery.MethodName, inputArgs...)
162 | if err != nil {
163 | die("Could not encode payload of the message about to be sent to server.\n\n%s", err.Error())
164 | }
165 |
166 | response, clientErr := client.SendQuery(payload)
167 | handleNoConnectionGracefully(clientErr, client)
168 | if response != nil {
169 | output, err := jsoncodec.MarshalReadResponse(response)
170 | if err != nil {
171 | die("Could not encode run-query response to json.\n\n%s", err.Error())
172 | }
173 |
174 | log("%s\n", string(output))
175 | exit()
176 | }
177 |
178 | if clientErr != nil {
179 | die("Request run-query failed on server.\n\n%s", clientErr.Error())
180 | }
181 | }
182 |
183 | func commandTxStatus(requiredOptions []string) {
184 | txId := requiredOptions[0]
185 |
186 | client := createOrbsClient()
187 |
188 | response, clientErr := client.GetTransactionStatus(txId)
189 | handleNoConnectionGracefully(clientErr, client)
190 | if response != nil {
191 | output, err := jsoncodec.MarshalTxStatusResponse(response)
192 | if err != nil {
193 | die("Could not encode status response to json.\n\n%s", err.Error())
194 | }
195 |
196 | log("%s\n", string(output))
197 | exit()
198 | }
199 |
200 | if clientErr != nil {
201 | die("Request status failed on server.\n\n%s", clientErr.Error())
202 | }
203 | }
204 |
205 | func commandTxProof(requiredOptions []string) {
206 | txId := requiredOptions[0]
207 |
208 | client := createOrbsClient()
209 |
210 | response, clientErr := client.GetTransactionReceiptProof(txId)
211 | handleNoConnectionGracefully(clientErr, client)
212 | if response != nil {
213 | output, err := jsoncodec.MarshalTxProofResponse(response)
214 | if err != nil {
215 | die("Could not encode tx proof response to json.\n\n%s", err.Error())
216 | }
217 |
218 | log("%s\n", string(output))
219 | exit()
220 | }
221 |
222 | if clientErr != nil {
223 | die("Request status failed on server.\n\n%s", clientErr.Error())
224 | }
225 | }
226 |
227 | func createOrbsClient() *orbs.OrbsClient {
228 | env := getEnvironmentFromConfigFile(*flagEnv)
229 | if len(env.Endpoints) == 0 {
230 | die("Environment Endpoints key does not contain any endpoints.")
231 | }
232 |
233 | endpoint := env.Endpoints[0]
234 | if endpoint == "localhost" {
235 | if !isDockerContainerRunning(gammaHandlerOptions().containerName) && !isPortListening(gammaHandlerOptions().port) {
236 | die("Local Gamma server is not running, use 'gamma-cli start-local' to start it.")
237 | }
238 | endpoint = fmt.Sprintf("http://localhost:%d", gammaHandlerOptions().port)
239 | }
240 |
241 | return orbs.NewClient(endpoint, env.VirtualChain, codec.NETWORK_TYPE_TEST_NET)
242 | }
243 |
244 | // Will get to it when we implement JS
245 | func getProcessorTypeFromFilename(filename string) uint32 {
246 | if strings.HasSuffix(filename, ".go") {
247 | return PROCESSOR_TYPE_NATIVE
248 | }
249 | if strings.HasSuffix(filename, ".js") {
250 | return PROCESSOR_TYPE_JAVASCRIPT
251 | }
252 | die("Unsupported code file type.\n\nSupported code file extensions are: .go .js")
253 | return 0
254 | }
255 |
256 | // TODO: this needs to be simplified
257 | func handleNoConnectionGracefully(err error, client *orbs.OrbsClient) {
258 | msg := fmt.Sprintf("Cannot connect to server at endpoint %s\n\nPlease check that:\n - The server is started and running (if just started, may need a second to initialize).\n - The server is accessible over the network.\n - The endpoint is properly configured if a config file is used.", client.Endpoint)
259 | switch err := errors.Cause(err).(type) {
260 | case *url.Error:
261 | die(msg)
262 | case *net.OpError:
263 | if err.Op == "dial" || err.Op == "read" {
264 | die(msg)
265 | }
266 | case net.Error:
267 | if err.Timeout() {
268 | die(msg)
269 | }
270 | case syscall.Errno:
271 | if err == syscall.ECONNREFUSED {
272 | die(msg)
273 | }
274 | default:
275 | if err == orbs.NoConnectionError {
276 | die(msg)
277 | }
278 | return
279 | }
280 | }
281 |
282 | func getFilenameWithoutExtension(filename string) string {
283 | return strings.Split(path.Base(filename), ".")[0]
284 | }
285 |
286 | func overrideArgWithPossibleArray(arg *jsoncodec.Arg, value string) {
287 | if strings.HasSuffix(arg.Type, "Array") {
288 | var valueAsArray []interface{}
289 | err := json.Unmarshal([]byte(value), &valueAsArray)
290 | if err != nil {
291 | die(fmt.Sprintf("Input is marked as %s but was not set as array of strings\n", arg.Type))
292 | }
293 | arg.Value = valueAsArray
294 | } else {
295 | arg.Value = value
296 | }
297 | }
298 |
299 | func overrideArgsWithFlags(args []*jsoncodec.Arg) {
300 | if *flagArg1 != "" {
301 | overrideArgWithPossibleArray(args[0], *flagArg1)
302 | }
303 | if *flagArg2 != "" {
304 | overrideArgWithPossibleArray(args[1], *flagArg2)
305 | }
306 | if *flagArg3 != "" {
307 | overrideArgWithPossibleArray(args[2], *flagArg3)
308 | }
309 | if *flagArg4 != "" {
310 | overrideArgWithPossibleArray(args[3], *flagArg4)
311 | }
312 | if *flagArg5 != "" {
313 | overrideArgWithPossibleArray(args[4], *flagArg5)
314 | }
315 | if *flagArg6 != "" {
316 | overrideArgWithPossibleArray(args[5], *flagArg6)
317 | }
318 | if *flagArg7 != "" {
319 | overrideArgWithPossibleArray(args[6], *flagArg7)
320 | }
321 | if *flagArg8 != "" {
322 | overrideArgWithPossibleArray(args[7], *flagArg8)
323 | }
324 | if *flagArg9 != "" {
325 | overrideArgWithPossibleArray(args[8], *flagArg9)
326 | }
327 | }
328 |
--------------------------------------------------------------------------------
/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -xe
2 |
3 | go test ./... -v
4 |
--------------------------------------------------------------------------------
/test/_arguments/arguments.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the orbs-network-go authors
2 | // This file is part of the orbs-network-go library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | // Contract that shows that contract with public function that accept and return argument as slices of types
8 | package main
9 |
10 | import (
11 | "bytes"
12 | "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1"
13 | "math/big"
14 | )
15 |
16 | var PUBLIC = sdk.Export(get, check)
17 | var SYSTEM = sdk.Export(_init)
18 |
19 | func _init() {
20 | }
21 |
22 | var boolArray = []bool{true, false, true, false, false, true}
23 | var uint32Array = []uint32{1, 10, 100, 1000, 10000, 100000, 3}
24 | var uint64Array = []uint64{1, 10, 100, 1000, 10000, 100000, 3}
25 | var uint256Array = []*big.Int{big.NewInt(1), big.NewInt(4194304)}
26 | var stringArray = []string{"picture", "yourself", "in", "a", "boat", "on", "a", "river"}
27 | var bytesArray = [][]byte{{0x11, 0x12}, {0xa, 0xb, 0xc, 0xd}, {0x1, 0x2}}
28 | var bytes20Array = [][20]byte{{0xaa, 0xbb}, {0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01,
29 | 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01}, {0x1, 0x2}}
30 | var bytes32Array = [][32]byte{{0x11, 0x12}, {0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x04,
31 | 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x04}, {0xa, 0xb, 0xc, 0xd}}
32 |
33 | func get() ([]bool, []uint32, []uint64, []*big.Int, []string, [][]byte, [][20]byte, [][32]byte) {
34 | return boolArray, uint32Array, uint64Array, uint256Array, stringArray, bytesArray, bytes20Array, bytes32Array
35 | }
36 |
37 | func check(boolsIn []bool, uint32sIn []uint32, uint64sIn []uint64, uint256sIn []*big.Int, stringsIn []string,
38 | bytesIn [][]byte, bytes20In [][20]byte, bytes32In [][32]byte) (bool, string) {
39 | if !checkBools(boolsIn) {
40 | return false, "bools"
41 | }
42 | if !checkUint32s(uint32sIn) {
43 | return false, "uint32s"
44 | }
45 | if !checkUint64s(uint64sIn) {
46 | return false, "uint64s"
47 | }
48 | if !checkUint256s(uint256sIn) {
49 | return false, "uint256s"
50 | }
51 | if !checkStrings(stringsIn) {
52 | return false, "strings"
53 | }
54 | if !checkBytes(bytesIn) {
55 | return false, "bytes"
56 | }
57 | if !checkBytes20s(bytes20In) {
58 | return false, "bytes20s"
59 | }
60 | if !checkBytes32s(bytes32In) {
61 | return false, "bytes32s"
62 | }
63 | return true, ""
64 | }
65 |
66 | func checkBools(in []bool) bool {
67 | if len(in) != len(boolArray) {
68 | return false
69 | }
70 | for i := range boolArray {
71 | if boolArray[i] != in[i] {
72 | return false
73 | }
74 | }
75 | return true
76 | }
77 |
78 | func checkUint32s(in []uint32) bool {
79 | if len(in) != len(uint32Array) {
80 | return false
81 | }
82 | for i := range uint32Array {
83 | if uint32Array[i] != in[i] {
84 | return false
85 | }
86 | }
87 | return true
88 | }
89 |
90 | func checkUint64s(in []uint64) bool {
91 | if len(in) != len(uint64Array) {
92 | return false
93 | }
94 | for i := range uint64Array {
95 | if uint64Array[i] != in[i] {
96 | return false
97 | }
98 | }
99 | return true
100 | }
101 |
102 | func checkUint256s(in []*big.Int) bool {
103 | if len(in) != len(uint256Array) {
104 | return false
105 | }
106 | for i := range uint256Array {
107 | if uint256Array[i].Cmp(in[i]) != 0 {
108 | return false
109 | }
110 | }
111 | return true
112 | }
113 |
114 | func checkStrings(in []string) bool {
115 | if len(in) != len(stringArray) {
116 | return false
117 | }
118 | for i := range stringArray {
119 | if stringArray[i] != in[i] {
120 | return false
121 | }
122 | }
123 | return true
124 | }
125 |
126 | func checkBytes(in [][]byte) bool {
127 | if len(in) != len(bytesArray) {
128 | return false
129 | }
130 | for i := range bytesArray {
131 | if !bytes.Equal(bytesArray[i], in[i]) {
132 | return false
133 | }
134 | }
135 | return true
136 | }
137 |
138 | func checkBytes20s(in [][20]byte) bool {
139 | if len(in) != len(bytes20Array) {
140 | return false
141 | }
142 | for i := range bytes20Array {
143 | if !bytes.Equal(bytes20Array[i][:], in[i][:]) {
144 | return false
145 | }
146 | }
147 | return true
148 | }
149 |
150 | func checkBytes32s(in [][32]byte) bool {
151 | if len(in) != len(bytes32Array) {
152 | return false
153 | }
154 | for i := range bytes32Array {
155 | if !bytes.Equal(bytes32Array[i][:], in[i][:]) {
156 | return false
157 | }
158 | }
159 | return true
160 | }
161 |
--------------------------------------------------------------------------------
/test/_corrupt/corrupt.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
--------------------------------------------------------------------------------
/test/_counter/contract.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package main
8 |
9 | import (
10 | "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1"
11 | "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1/events"
12 | "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1/state"
13 | "strconv"
14 | )
15 |
16 | var PUBLIC = sdk.Export(add, get, start)
17 | var SYSTEM = sdk.Export(_init)
18 | var EVENTS = sdk.Export(Log)
19 |
20 | var COUNTER_KEY = []byte("count")
21 |
22 | func Log(msg string) {}
23 |
24 | func _init() {
25 | state.WriteUint64(COUNTER_KEY, 0)
26 | }
27 |
28 | func add(amount uint64) {
29 | count := state.ReadUint64(COUNTER_KEY)
30 | events.EmitEvent(Log, "previous count is " + strconv.FormatUint(count, 10))
31 | count += amount
32 | state.WriteUint64(COUNTER_KEY, count)
33 | }
34 |
35 | func get() uint64 {
36 | return state.ReadUint64(COUNTER_KEY)
37 | }
38 |
39 | func start() uint64 {
40 | return 0
41 | }
42 |
--------------------------------------------------------------------------------
/test/arguments-check.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "Arguments",
3 | "MethodName": "check",
4 | "Arguments": [
5 | {
6 | "Type": "boolArray",
7 | "Value": ["1", "0", "1", "0", "0", "1"]
8 | },
9 | {
10 | "Type": "uint32Array",
11 | "Value": ["1", "10", "100", "1000", "10000", "100000", "3"]
12 | },
13 | {
14 | "Type": "uint64Array",
15 | "Value": ["1", "10", "100", "1000", "10000", "100000", "3"]
16 | },
17 | {
18 | "Type": "uint256Array",
19 | "Value": ["0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000400000"]
20 | },
21 | {
22 | "Type": "stringArray",
23 | "Value": ["picture", "yourself", "in", "a", "boat", "on", "a", "river"]
24 | },
25 | {
26 | "Type": "bytesArray",
27 | "Value": ["0x1112", "0x0a0b0c0d", "0x0102"]
28 | },
29 | {
30 | "Type": "bytes20Array",
31 | "Value": ["0xaabb000000000000000000000000000000000000", "0x0102030102030102030101020301020301020301", "0x0102000000000000000000000000000000000000"]
32 | },
33 | {
34 | "Type": "bytes32Array",
35 | "Value": ["0x1112000000000000000000000000000000000000000000000000000000000000", "0x0102030102030102030102030102030401020301020301020301020301020304", "0x0a0b0c0d00000000000000000000000000000000000000000000000000000000"]
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/test/arguments-get.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "Arguments",
3 | "MethodName": "get",
4 | "Arguments": [
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/arguments_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "encoding/json"
11 | "github.com/stretchr/testify/require"
12 | "strings"
13 | "testing"
14 | )
15 |
16 | func Test_Arguments(t *testing.T) {
17 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().StartGammaServerAndWait()
18 | defer cli.StopGammaServer()
19 |
20 | outputString, err := cli.Run("deploy", "./_arguments/arguments.go", "-name", "Arguments")
21 | t.Log(outputString)
22 | require.NoError(t, err, "deploy should succeed")
23 | require.True(t, strings.Contains(outputString, `"ExecutionResult": "SUCCESS"`))
24 |
25 | outputString, err = cli.Run("run-query", "arguments-get.json")
26 | // t.Log(outputString) // uncomment to view output if something change
27 | require.NoError(t, err, "get should succeed")
28 | require.True(t, strings.Contains(outputString, `"ExecutionResult": "SUCCESS"`))
29 | outputGetParsed := struct {
30 | OutputArguments []*struct {
31 | Type string
32 | Value []string
33 | }
34 | }{}
35 | err = json.Unmarshal([]byte(outputString), &outputGetParsed)
36 | require.NoError(t, err, "parse should succeed")
37 | require.Len(t, outputGetParsed.OutputArguments, 8, "There should be 8 output arrays")
38 |
39 | outputString, err = cli.Run("run-query", "arguments-check.json")
40 | // t.Log(outputString) // uncomment to view output if something change
41 | require.NoError(t, err, "check should succeed")
42 | require.True(t, strings.Contains(outputString, `"ExecutionResult": "SUCCESS"`))
43 | outputCheckParsed := struct {
44 | OutputArguments []*struct {
45 | Type string
46 | Value string
47 | }
48 | }{}
49 | err = json.Unmarshal([]byte(outputString), &outputCheckParsed)
50 | require.NoError(t, err, "parse should succeed")
51 | require.Len(t, outputCheckParsed.OutputArguments, 2, "There should be 2 output values")
52 | require.Equal(t, "bool", outputCheckParsed.OutputArguments[0].Type)
53 | require.Equal(t, "1", outputCheckParsed.OutputArguments[0].Value)
54 | require.Equal(t, "string", outputCheckParsed.OutputArguments[1].Type)
55 | require.Empty(t, outputCheckParsed.OutputArguments[1].Value)
56 | }
57 |
--------------------------------------------------------------------------------
/test/config_override_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/stretchr/testify/require"
5 | "testing"
6 | )
7 |
8 | func TestGammaCli_StartWithConfigOverrides(t *testing.T) {
9 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().WithConfigOverrides(`{"virtual-chain-id":43}`).StartGammaServerAndWait()
10 | defer cli.StopGammaServer()
11 |
12 | out, _ := cli.Run("deploy", "./_counter/contract.go", "-name", "CounterExample")
13 | require.Contains(t, out, "REJECTED_VIRTUAL_CHAIN_MISMATCH", "transaction was not rejected when sending a transaction for vcid 42 to a container running vcid 43")
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/test/counter-add.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "CounterExample",
3 | "MethodName": "add",
4 | "Arguments": [
5 | {
6 | "Type": "uint64",
7 | "Value": "25"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/counter-get.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "CounterExample",
3 | "MethodName": "get",
4 | "Arguments": []
5 | }
--------------------------------------------------------------------------------
/test/deploy_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "strings"
12 | "testing"
13 | )
14 |
15 | func TestDeployCounter(t *testing.T) {
16 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().StartGammaServerAndWait()
17 | defer cli.StopGammaServer()
18 |
19 | out, err := cli.Run("deploy", "./_counter/contract.go", "-name", "CounterExample")
20 | t.Log(out)
21 | require.NoError(t, err, "deploy should succeed")
22 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
23 |
24 | out, err = cli.Run("run-query", "counter-get.json")
25 | t.Log(out)
26 | require.NoError(t, err, "get should succeed")
27 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
28 | require.True(t, strings.Contains(out, `"Value": "0"`))
29 |
30 | out, err = cli.Run("send-tx", "counter-add.json")
31 | t.Log(out)
32 | require.NoError(t, err, "add should succeed")
33 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
34 | require.True(t, strings.Contains(out, `"Value": "previous count is 0"`))
35 |
36 | out, err = cli.Run("run-query", "counter-get.json")
37 | t.Log(out)
38 | require.NoError(t, err, "get should succeed")
39 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
40 | require.True(t, strings.Contains(out, `"Value": "25"`))
41 | }
42 |
43 | func TestDeployCorruptContract(t *testing.T) {
44 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().StartGammaServerAndWait()
45 | defer cli.StopGammaServer()
46 |
47 | out, err := cli.Run("deploy", "./_corrupt/corrupt.go", "-name", "CounterExample")
48 | t.Log(out)
49 | require.NoError(t, err, "deploy should succeed")
50 | require.True(t, strings.Contains(out, `"ExecutionResult": "ERROR_SMART_CONTRACT"`))
51 | require.True(t, strings.Contains(out, `compilation of deployable contract 'CounterExample' failed`))
52 | }
53 |
54 | func TestDeployOfAlreadyDeployed(t *testing.T) {
55 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().StartGammaServerAndWait()
56 | defer cli.StopGammaServer()
57 |
58 | out, err := cli.Run("deploy", "./_counter/contract.go", "-name", "CounterExample")
59 | t.Log(out)
60 | require.NoError(t, err, "deploy should succeed")
61 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
62 |
63 | out, err = cli.Run("deploy", "./_counter/contract.go", "-name", "CounterExample")
64 | t.Log(out)
65 | require.NoError(t, err, "deploy should succeed")
66 | require.True(t, strings.Contains(out, `"ExecutionResult": "ERROR_SMART_CONTRACT"`))
67 | require.True(t, strings.Contains(out, `a contract with same name (case insensitive) already exists`))
68 | }
69 |
70 | func TestRunMethodWithoutDeploy(t *testing.T) {
71 | cli := GammaCli().WithExperimentalServer().StartGammaServerAndWait()
72 | defer cli.StopGammaServer()
73 |
74 | out, err := cli.Run("send-tx", "counter-add.json")
75 | t.Log(out)
76 | require.NoError(t, err, "add should succeed")
77 | require.True(t, strings.Contains(out, `"RequestStatus": "BAD_REQUEST"`))
78 | require.True(t, strings.Contains(out, `"ExecutionResult": "ERROR_CONTRACT_NOT_DEPLOYED"`))
79 | }
80 |
--------------------------------------------------------------------------------
/test/generate_config.py:
--------------------------------------------------------------------------------
1 | # Copyright 2019 the gamma-cli authors
2 | # This file is part of the gamma-cli library in the Orbs project.
3 | #
4 | # This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | # The above notice should be included in all copies or substantial portions of the software.
6 |
7 | import json
8 | import sys
9 | import socket
10 |
11 | def get_endpoint(ip):
12 | return "http://" + ip + ":8080"
13 |
14 | def get_config(ip):
15 | return {
16 | "Environments": {
17 | "docker": {
18 | "VirtualChain": 42,
19 | "Endpoints": [get_endpoint(ip)]
20 | },
21 | "docker-experimental": {
22 | "VirtualChain": 42,
23 | "Endpoints": [get_endpoint(ip)],
24 | "Experimental": True
25 | },
26 | }
27 | }
28 |
29 | if __name__ == "__main__":
30 | ip = socket.gethostbyname(socket.gethostname())
31 |
32 | if sys.argv[1] == "endpoint":
33 | print get_endpoint(ip)
34 | elif sys.argv[1] == "json":
35 | print json.dumps(get_config(ip))
--------------------------------------------------------------------------------
/test/get-balance.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "BenchmarkToken",
3 | "MethodName": "getBalance",
4 | "Arguments": [
5 | {
6 | "Type": "gamma:keys-file-address",
7 | "Value": "user2"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/test/harness.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "fmt"
11 | "io/ioutil"
12 | "os"
13 | "os/exec"
14 | "path"
15 | "path/filepath"
16 | "regexp"
17 | "runtime"
18 | "time"
19 | )
20 |
21 | const CONFIG_FILENAME = "orbs-gamma-config.json"
22 |
23 | var cachedGammaCliBinaryPath string
24 | var downloadedLatestGammaServer bool
25 |
26 | type gammaCli struct {
27 | port string
28 | experimental bool
29 | configOverrides string
30 | prism bool
31 | }
32 |
33 | func compileGammaCli() string {
34 | if gammaCliPathFromEnv := os.Getenv("GAMMA_CLI_PATH"); gammaCliPathFromEnv != "" {
35 | return gammaCliPathFromEnv
36 | }
37 |
38 | if cachedGammaCliBinaryPath != "" {
39 | return cachedGammaCliBinaryPath // cache compilation once per process
40 | }
41 |
42 | tempDir, err := ioutil.TempDir("", "gamma")
43 | if err != nil {
44 | panic(err)
45 | }
46 |
47 | binaryOutputPath := tempDir + "/gamma-cli"
48 | goCmd := path.Join(runtime.GOROOT(), "bin", "go")
49 | cmd := exec.Command(goCmd, "build", "-o", binaryOutputPath, ".")
50 | cmd.Dir = path.Join(getCurrentSourceFileDirPath(), "..")
51 | out, err := cmd.CombinedOutput()
52 | if err != nil {
53 | panic(fmt.Sprintf("compilation failed: %s\noutput:\n%s\n", err.Error(), out))
54 | } else {
55 | fmt.Printf("compiled gamma-cli successfully:\n %s\n", binaryOutputPath)
56 | }
57 |
58 | cachedGammaCliBinaryPath = binaryOutputPath
59 | return cachedGammaCliBinaryPath
60 | }
61 |
62 | func (g *gammaCli) Run(args ...string) (string, error) {
63 | if len(args) > 0 {
64 | // streamlined supprt for a different port
65 | args = append(args, "-port", g.port)
66 |
67 | // needed for dockerized tests in ci
68 | args = append(args, "-env", g.getGammaEnvironment())
69 | pathToConfig := path.Join(os.Getenv("HOME"), ".orbs", CONFIG_FILENAME)
70 | args = append(args, "-config", pathToConfig)
71 |
72 | if g.configOverrides != "" {
73 | args = append(args, "-override-config", g.configOverrides)
74 | }
75 | }
76 | out, err := exec.Command(compileGammaCli(), args...).CombinedOutput()
77 | return string(out), err
78 | }
79 |
80 | func GammaCli() *gammaCli {
81 | return GammaCliWithPort(8080)
82 | }
83 |
84 | func GammaCliWithPort(port int) *gammaCli {
85 | return &gammaCli{
86 | port: fmt.Sprintf("%d", port),
87 | prism: true,
88 | }
89 | }
90 |
91 | func (g *gammaCli) WithConfigOverrides(override string) *gammaCli {
92 | g.configOverrides = override
93 | return g
94 | }
95 |
96 | func (g *gammaCli) WithStableServer() *gammaCli {
97 | g.experimental = false
98 | return g
99 | }
100 |
101 | func (g *gammaCli) WithExperimentalServer() *gammaCli {
102 | g.experimental = true
103 | return g
104 | }
105 |
106 | func (g *gammaCli) WithNoPrism() *gammaCli {
107 | g.prism = false
108 | return g
109 | }
110 |
111 | func (g *gammaCli) StartGammaServerAndWait() *gammaCli {
112 | return g.startInternal(true)
113 | }
114 |
115 | func (g *gammaCli) StartGammaServer() *gammaCli {
116 | return g.startInternal(false)
117 | }
118 |
119 | func (g *gammaCli) startInternal(shouldWait bool) *gammaCli {
120 | commands := []string{"start-local"}
121 | if shouldWait {
122 | commands = append(commands, "-wait")
123 | }
124 |
125 | if !g.prism {
126 | commands = append(commands, "-no-ui")
127 | }
128 |
129 | out, err := g.Run(commands...)
130 | if err != nil {
131 | panic(fmt.Sprintf("start Gamma server failed: %s\noutput:\n%s\n", err.Error(), out))
132 | }
133 | fmt.Println(out)
134 | return g
135 | }
136 |
137 | func (g *gammaCli) StopGammaServer() {
138 | out, err := g.Run("stop-local")
139 | if err != nil {
140 | panic(fmt.Sprintf("stop Gamma server failed: %s\noutput:\n%s\n", err.Error(), out))
141 | }
142 | }
143 |
144 | func (g *gammaCli) DownloadLatestGammaServer() *gammaCli {
145 | if downloadedLatestGammaServer {
146 | return g
147 | }
148 | downloadedLatestGammaServer = true
149 |
150 | start := time.Now()
151 | out, err := g.Run("upgrade-server")
152 | if err != nil {
153 | panic(fmt.Sprintf("download latest Gamma server failed: %s\noutput:\n%s\n", err.Error(), out))
154 | }
155 | delta := time.Now().Sub(start)
156 | fmt.Printf("upgraded gamma-server to latest version (this took %.3fs)\n", delta.Seconds())
157 | return g
158 | }
159 |
160 | func (g *gammaCli) getGammaEnvironment() string {
161 | if env := os.Getenv("GAMMA_ENVIRONMENT"); env != "" {
162 | if g.experimental {
163 | return env + "-experimental"
164 | }
165 | return env
166 | }
167 |
168 | if g.experimental {
169 | return "experimental"
170 | }
171 | return "local"
172 | }
173 |
174 | func extractTxIdFromSendTxOutput(out string) string {
175 | re := regexp.MustCompile(`\"TxId\":\s+\"(\w+)\"`)
176 | res := re.FindStringSubmatch(out)
177 | return res[1]
178 | }
179 |
180 | func getCurrentSourceFileDirPath() string {
181 | _, filename, _, _ := runtime.Caller(1)
182 | return filepath.Dir(filename)
183 | }
184 |
--------------------------------------------------------------------------------
/test/help_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "strings"
12 | "testing"
13 | )
14 |
15 | func TestHelp(t *testing.T) {
16 | out, err := GammaCli().WithExperimentalServer().Run("help")
17 | t.Log(out)
18 | require.Error(t, err, "help should exit nonzero")
19 | require.NotEmpty(t, out, "help output should not be empty")
20 | require.True(t, strings.Contains(out, "start-local"))
21 | require.True(t, strings.Contains(out, "stop-local"))
22 |
23 | out2, err := GammaCli().WithExperimentalServer().Run()
24 | require.Error(t, err, "run without arguments should exit nonzero")
25 | require.Equal(t, out, out2, "help output should be equal")
26 | }
27 |
28 | func TestVersion(t *testing.T) {
29 | out, err := GammaCli().WithStableServer().Run("version")
30 | t.Log(out)
31 | require.NoError(t, err, "version should succeed")
32 | require.True(t, strings.Contains(out, "Gamma server version"))
33 | require.True(t, strings.Contains(out, "Prism blockchain explorer version"))
34 | require.False(t, strings.Contains(out, `version experimental (docker)`), "started Gamma server should not be experimental")
35 | }
36 |
--------------------------------------------------------------------------------
/test/restart_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "os/exec"
12 | "strings"
13 | "testing"
14 | )
15 |
16 | func TestRestart(t *testing.T) {
17 | cli := GammaCli().WithStableServer()
18 | defer cli.StopGammaServer()
19 |
20 | out, err := cli.Run("start-local")
21 | t.Log(out)
22 | require.NoError(t, err, "start Gamma server should succeed")
23 | require.False(t, strings.Contains(out, `Orbs Gamma experimental personal blockchain`), "started Gamma server should not be experimental")
24 | require.False(t, strings.Contains(out, `Prism blockchain explorer experimental`), "started Prism server should not be experimental")
25 |
26 | _, err = cli.Run("stop-local")
27 | require.NoError(t, err, "stop Gamma server should succeed")
28 |
29 | _, err = cli.Run("stop-local")
30 | require.NoError(t, err, "second stop Gamma server should succeed")
31 |
32 | _, err = cli.Run("start-local")
33 | require.NoError(t, err, "start Gamma server should succeed")
34 | }
35 |
36 | func TestStopAfterCrashOfGammaServer(t *testing.T) {
37 | cli := GammaCli().WithExperimentalServer()
38 | defer cli.StopGammaServer()
39 |
40 | out, err := cli.Run("start-local")
41 | t.Log(out)
42 | require.NoError(t, err, "start Gamma server should succeed")
43 | require.True(t, strings.Contains(out, `Orbs Gamma personal blockchain experimental`), "started Gamma server should be experimental")
44 | require.True(t, strings.Contains(out, `Prism blockchain explorer experimental`), "started Prism server should be experimental")
45 |
46 | // stopping and removing gamma-server
47 | dockerOut, err := exec.Command("docker", "stop", "orbs-gamma-server").CombinedOutput()
48 | if err != nil {
49 | t.Fatalf("%s", dockerOut)
50 | }
51 | dockerOut, err = exec.Command("docker", "rm", "-f", "orbs-gamma-server").CombinedOutput()
52 | if err != nil {
53 | t.Fatalf("Could not remove docker container.\n\n%s", dockerOut)
54 | }
55 |
56 | // running the regular gamma stop
57 | out, err = cli.Run("stop-local")
58 | require.NoError(t, err, "stop Gamma server should succeed")
59 | require.True(t, strings.Contains(out, "Prism blockchain explorer stopped."), "Prism server should stop even if gamma crashed")
60 | }
61 |
--------------------------------------------------------------------------------
/test/token_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "github.com/stretchr/testify/require"
11 | "strings"
12 | "testing"
13 | )
14 |
15 | func TestSimpleTransfer(t *testing.T) {
16 | cli := GammaCli().WithExperimentalServer().DownloadLatestGammaServer().StartGammaServerAndWait()
17 | defer cli.StopGammaServer()
18 |
19 | out, err := cli.Run("run-query", "get-balance.json")
20 | t.Log(out)
21 | require.NoError(t, err, "get balance should not fail (although not deployed)")
22 | require.True(t, strings.Contains(out, `"ExecutionResult": "ERROR_CONTRACT_NOT_DEPLOYED"`))
23 |
24 | out, err = cli.Run("send-tx", "transfer.json")
25 | t.Log(out)
26 | require.NoError(t, err, "transfer should succeed")
27 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
28 |
29 | txId := extractTxIdFromSendTxOutput(out)
30 | t.Log(txId)
31 |
32 | out, err = cli.Run("tx-status", txId)
33 | t.Log(out)
34 | require.NoError(t, err, "get tx status should succeed")
35 | require.True(t, strings.Contains(out, `"RequestStatus": "COMPLETED"`))
36 |
37 | out, err = cli.Run("tx-proof", txId)
38 | t.Log(out)
39 | require.NoError(t, err, "get tx proof should succeed")
40 | require.True(t, strings.Contains(out, `"RequestStatus": "COMPLETED"`))
41 | require.True(t, strings.Contains(out, `"PackedProof": "0x`))
42 | require.True(t, strings.Contains(out, `"PackedReceipt": "0x`))
43 | require.True(t, strings.Contains(out, `"ProofSigners": [`))
44 | require.True(t, strings.Contains(out, `"0xa328846cd5b4979d68a8c58a9bdfeee657b34de7"`))
45 |
46 | out, err = cli.Run("send-tx", "transfer.json", "-arg1", "2")
47 | t.Log(out)
48 | require.NoError(t, err, "transfer should succeed")
49 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
50 |
51 | out, err = cli.Run("run-query", "get-balance.json")
52 | t.Log(out)
53 | require.NoError(t, err, "get balance should succeed")
54 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
55 | require.True(t, strings.Contains(out, `"Value": "19"`))
56 |
57 | out, err = cli.Run("send-tx", "transfer-direct.json")
58 | t.Log(out)
59 | require.NoError(t, err, "transfer should succeed")
60 | require.True(t, strings.Contains(out, `"ExecutionResult": "SUCCESS"`))
61 | }
62 |
--------------------------------------------------------------------------------
/test/transfer-direct.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "BenchmarkToken",
3 | "MethodName": "transfer",
4 | "Arguments": [
5 | {
6 | "Type": "uint64",
7 | "Value": "17"
8 | },
9 | {
10 | "Type": "bytes",
11 | "Value": "0xb011A26EC85d8B2f9deD3A9062BcbDA4Ed38b778"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/test/transfer.json:
--------------------------------------------------------------------------------
1 | {
2 | "ContractName": "BenchmarkToken",
3 | "MethodName": "transfer",
4 | "Arguments": [
5 | {
6 | "Type": "uint64",
7 | "Value": "17"
8 | },
9 | {
10 | "Type": "gamma:keys-file-address",
11 | "Value": "user2"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/test/upgrade_test.go:
--------------------------------------------------------------------------------
1 | // Copyright 2019 the gamma-cli authors
2 | // This file is part of the gamma-cli library in the Orbs project.
3 | //
4 | // This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree.
5 | // The above notice should be included in all copies or substantial portions of the software.
6 |
7 | package test
8 |
9 | import (
10 | "fmt"
11 | "github.com/stretchr/testify/require"
12 | "os/exec"
13 | "regexp"
14 | "strings"
15 | "testing"
16 | )
17 |
18 | func TestUpgradeStableServer(t *testing.T) {
19 | cli := GammaCli().WithStableServer()
20 |
21 | out, err := cli.Run("version")
22 | t.Log(out)
23 | require.NoError(t, err, "version should succeed")
24 | require.True(t, strings.Contains(out, `(docker)`), "version output should show docker")
25 |
26 | out, err = cli.Run("upgrade-server")
27 | t.Log(out)
28 | require.NoError(t, err, "upgrade server stable should succeed")
29 | require.True(t, strings.Contains(out, `does not require upgrade`), "upgrade same tag should not try to pull fresh copy")
30 | require.True(t, strings.Contains(out, `Current Orbs Gamma`), "upgrade worked on gamma-server")
31 | require.True(t, strings.Contains(out, `Current Prism`), "upgrade worked on prism")
32 | }
33 |
34 | func TestUpgradeExperimentalServer(t *testing.T) {
35 | cli := GammaCli().WithExperimentalServer()
36 | defer cli.StopGammaServer()
37 |
38 | out, err := cli.Run("version")
39 | t.Log(out)
40 | require.NoError(t, err, "version experimental should succeed")
41 | require.True(t, strings.Contains(out, `experimental (docker)`), "version output should show experimental docker")
42 |
43 | out, err = cli.Run("upgrade-server")
44 | t.Log(out)
45 | require.NoError(t, err, "upgrade server experimental should succeed")
46 | require.True(t, strings.Contains(out, `experimental: Pulling from orbsnetwork/gamma`), "experimental upgrade should always try to pull fresh copy (gamma)")
47 | require.True(t, strings.Contains(out, `experimental: Pulling from orbsnetwork/prism`), "experimental upgrade should always try to pull fresh copy (prism)")
48 |
49 | out, err = cli.Run("start-local")
50 | t.Log(out)
51 | require.NoError(t, err, "start Gamma server should succeed")
52 | require.True(t, strings.Contains(out, `Orbs Gamma personal blockchain experimental`), "started Gamma server should be experimental")
53 | require.True(t, strings.Contains(out, `Prism blockchain explorer experimental`), "started Prism server should be experimental")
54 | }
55 |
56 | func TestStableServerDoesNotRestartWhenVersionUpgradeNotRequired(t *testing.T) {
57 | cli := GammaCli().WithStableServer()
58 | defer cli.StopGammaServer()
59 |
60 | out, err := cli.Run("version")
61 | t.Log(out)
62 | require.NoError(t, err, "version should succeed")
63 | require.True(t, strings.Contains(out, `(docker)`), "version output should show docker")
64 |
65 | out, err = cli.Run("start-local")
66 | require.NoError(t, err, "start Gamma server should succeed")
67 |
68 | out, err = cli.Run("upgrade-server")
69 | require.NoError(t, err, "upgrade server stable should succeed")
70 | require.True(t, strings.Contains(out, `does not require upgrade`), "upgrade same tag should not try to pull fresh copy")
71 | require.True(t, strings.Contains(out, `Current Orbs Gamma`), "upgrade worked on gamma-server")
72 | require.True(t, strings.Contains(out, `Current Prism`), "upgrade worked on prism")
73 | require.False(t, strings.Contains(out, "Orbs Gamma personal blockchain stopped."), "Gamma should not restart if no upgrade happened")
74 | require.False(t, strings.Contains(out, "Prism blockchain explorer stopped."), "Prism should not restart if no upgrade happened")
75 | }
76 |
77 | func TestExperimentalServerDoesNotRestartWhenVersionUpgradeNotRequired(t *testing.T) {
78 | cli := GammaCli().WithExperimentalServer()
79 | defer cli.StopGammaServer()
80 |
81 | out, err := cli.Run("version")
82 | t.Log(out)
83 | require.NoError(t, err, "version should succeed")
84 | require.True(t, strings.Contains(out, `(docker)`), "version output should show docker")
85 |
86 | out, err = cli.Run("start-local")
87 | require.NoError(t, err, "start Gamma server should succeed")
88 |
89 | out, err = cli.Run("upgrade-server")
90 | require.NoError(t, err, "upgrade server stable should succeed")
91 | require.True(t, strings.Contains(out, `Image is up to date`), "re-upgrade experimental should not try to pull fresh copy")
92 | require.False(t, strings.Contains(out, "Orbs Gamma personal blockchain stopped."), "Gamma should not restart if no upgrade happened")
93 | require.False(t, strings.Contains(out, "Prism blockchain explorer stopped."), "Prism should not restart if no upgrade happened")
94 | }
95 |
96 | func TestPrismNotRestartedOnUpgradeRestartWhenNotRunningBefore(t *testing.T) {
97 | // can only test this with stable, because of how docker/gamma automation works
98 | cli := GammaCli().WithStableServer().WithNoPrism()
99 | defer cli.StopGammaServer()
100 |
101 | out, err := cli.Run("version")
102 | t.Log(out)
103 | require.NoError(t, err, "version should succeed")
104 | require.True(t, strings.Contains(out, `(docker)`), "version output should show docker")
105 |
106 | // get an old version
107 | dockerOut, err := exec.Command("docker", "pull", "orbsnetwork/gamma:v1.1.1").CombinedOutput()
108 | if err != nil {
109 | t.Fatalf("%s", dockerOut)
110 | }
111 |
112 | // get latest tag and remove it (so upgrade will happen)
113 | pattern := fmt.Sprintf(`%s\s+(v\S+)`, regexp.QuoteMeta("Gamma server version"))
114 | re := regexp.MustCompile(pattern)
115 | res := re.FindStringSubmatch(out)
116 | dockerOut, err = exec.Command("docker", "rmi", "orbsnetwork/gamma:"+res[1]).CombinedOutput()
117 | if err != nil {
118 | t.Fatalf("%s", dockerOut)
119 | }
120 |
121 | cli = cli.StartGammaServerAndWait()
122 |
123 | out, err = cli.Run("upgrade-server")
124 | t.Log(out)
125 | require.NoError(t, err, "upgrade server stable should succeed")
126 | require.True(t, strings.Contains(out, `Downloading latest`), "we are forcing an upgrade, it should download something")
127 | require.True(t, strings.Contains(out, "Orbs Gamma personal blockchain stopped."), "Gamma was upgraded and needs to restart")
128 | require.False(t, strings.Contains(out, "Prism blockchain explorer stopped."), "Prism should not restart as it was not running before")
129 | }
--------------------------------------------------------------------------------