├── .circleci ├── config.yml └── test.sh ├── .dockerignore ├── .env ├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── README.md ├── config.beta ├── config.betanet ├── config.dev ├── config.devnet ├── config.mainnet ├── config.nightly ├── config.release ├── config.source ├── config.testnet ├── config ├── beta.config.json ├── config.json ├── kmd_config.json ├── start.sh └── token ├── docker-compose.yml ├── genesis ├── betanet │ └── genesis.json ├── devnet │ └── genesis.json ├── mainnet │ └── genesis.json └── testnet │ └── genesis.json ├── images ├── Dockerfile ├── algod │ ├── DevModeNetwork.json │ ├── Dockerfile │ ├── future_template.json │ ├── install.sh │ ├── setup.py │ ├── template.json │ └── update.sh ├── conduit │ ├── Dockerfile │ ├── disabled.go │ ├── install.sh │ └── start.sh └── indexer │ ├── IndexerDockerfile │ ├── disabled.go │ ├── install.sh │ └── start.sh └── sandbox /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | parameters: 4 | ubuntu_noble_machine: 5 | type: string 6 | default: 'ubuntu-2404:2024.11.1' 7 | ubuntu_jammy_machine: 8 | type: string 9 | default: 'ubuntu-2204:2024.11.1' 10 | workflows: 11 | circleci_build_and_test: 12 | jobs: 13 | - spin_up: 14 | name: 'spin_up_<< matrix.config >>_<< matrix.machine >>' 15 | matrix: 16 | parameters: 17 | config: ['', 'betanet', 'devnet', 'dev', 'beta', 'release', 'nightly'] 18 | machine: [<< pipeline.parameters.ubuntu_noble_machine >>, << pipeline.parameters.ubuntu_jammy_machine >>] 19 | 20 | jobs: 21 | spin_up: 22 | parameters: 23 | config: 24 | type: string 25 | machine: 26 | type: string 27 | machine: 28 | image: << parameters.machine >> 29 | resource_class: medium 30 | steps: 31 | - checkout 32 | - run: 33 | name: Install docker 34 | command: | 35 | sudo apt update 36 | sudo apt -y install ca-certificates curl gnupg lsb-release 37 | sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 38 | sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ 39 | $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 40 | sudo apt update 41 | sudo apt -y install docker-ce docker-ce-cli containerd.io 42 | - run: 43 | name: CircleCI docker download fix 44 | command: sudo iptables -I INPUT -m conntrack --ctstate INVALID -j DROP 45 | - run: 46 | name: Stand up sandbox 47 | # We should remove the no_output_timeout rule once we find a way to 48 | # stop generating 3 million keys for the private network. 49 | no_output_timeout: 30m 50 | environment: 51 | CONFIG: << parameters.config >> 52 | command: | 53 | bash ./.circleci/test.sh 54 | -------------------------------------------------------------------------------- /.circleci/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euxo pipefail 3 | 4 | trap 'catch $?' ERR 5 | 6 | catch() { 7 | echo "============= algod =============" 8 | ./sandbox dump algod 9 | echo "============= conduit =============" 10 | ./sandbox dump conduit 11 | echo "============= indexer =============" 12 | ./sandbox dump indexer 13 | exit $1 14 | } 15 | 16 | ./sandbox up -v $CONFIG 17 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !.env 3 | !config 4 | !images 5 | !genesis 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algorand/sandbox/59803a56a2d254bc49df36e964dc4e4f94435446/.env -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41C Bug report" 3 | about: Report a reproducible bug. 4 | title: '' 5 | labels: new-bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Subject of the issue 11 | 12 | 13 | 14 | ### Your environment 15 | 16 | 22 | 23 | ### Steps to reproduce 24 | 25 | 1. 26 | 2. 27 | 28 | ### Expected behaviour 29 | 30 | ### Actual behaviour 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F514 Feature Request" 3 | about: Suggestions for how we can improve the algorand platform. 4 | title: '' 5 | labels: new-feature-request 6 | assignees: '' 7 | --- 8 | 9 | ## Problem 10 | 11 | 12 | 13 | ## Solution 14 | 15 | 16 | 17 | ## Dependencies 18 | 19 | 20 | 21 | ## Urgency 22 | 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .active_config 2 | .clean 3 | sandbox.log 4 | data 5 | 6 | # emacs backup 7 | *~ 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | conduct@algorand.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorand Sandbox 2 | 3 | This is a fast way to create and configure an Algorand development environment with [Algod](https://github.com/algorand/go-algorand) and [Indexer](https://github.com/algorand/indexer). 4 | 5 | **Docker Compose** _MUST_ be installed. [Instructions](https://docs.docker.com/compose/install/). 6 | 7 | On a _Windows_ machine, **Docker Desktop** comes with the necessary tools. Please see the [Windows](#windows) section in getting started for more details. 8 | 9 | **Warning**: Algorand Sandbox is _not_ meant for production environments and should _not_ be used to store secure Algorand keys. Updates may reset all the data and keys that are stored. 10 | 11 | ## Usage 12 | 13 | Use the **sandbox** command to interact with the Algorand Sandbox. 14 | 15 | ```plain 16 | sandbox commands: 17 | up [config] -> start the sandbox environment. 18 | down -> tear down the sandbox environment. 19 | reset -> reset the containers to their initial state. 20 | clean -> stops and deletes containers and data directory. 21 | test -> runs some tests to demonstrate usage. 22 | enter [algod||conduit||indexer||indexer-db] 23 | -> enter the sandbox container. 24 | dump [algod||conduit||indexer||indexer-db] 25 | -> dump log information for a container. 26 | tail [algod||conduit||indexer||indexer-db] 27 | -> tail log information for a container. 28 | version -> print binary versions. 29 | copyTo -> copy into the algod. Useful for offline transactions, offline LogicSigs & TEAL work. 30 | copyFrom -> copy from the algod. Useful for offline transactions, offline LogicSigs & TEAL work. 31 | 32 | algorand commands: 33 | logs -> stream algorand logs with the carpenter utility. 34 | status -> get node status. 35 | goal (args) -> run goal command like 'goal node status'. 36 | tealdbg (args) -> run tealdbg command to debug program execution. 37 | 38 | special flags for 'up' command: 39 | -v|--verbose -> display verbose output when starting standbox. 40 | -s|--skip-fast-catchup -> skip catchup when connecting to real network. 41 | -i|--interactive -> start docker compose in interactive mode. 42 | ``` 43 | 44 | Sandbox creates the following API endpoints: 45 | 46 | - `algod`: 47 | - address: `http://localhost:4001` 48 | - token: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` 49 | - `kmd`: 50 | - address: `http://localhost:4002` 51 | - token: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` 52 | - `indexer`: 53 | - address: `http://localhost:8980` 54 | - `algod (follower)`: 55 | - address: `http://localhost:3999` 56 | - token: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` 57 | - `conduit`: 58 | - address: `http://localhost:3998/metrics` 59 | 60 | ## Getting Started 61 | 62 | ### Ubuntu and macOS 63 | 64 | Make sure the docker daemon is running and docker-compose is installed. 65 | 66 | Open a terminal and run: 67 | 68 | ```bash 69 | git clone https://github.com/algorand/sandbox.git 70 | ``` 71 | 72 | In whatever local directory the sandbox should reside. Then: 73 | 74 | ```bash 75 | cd sandbox 76 | ./sandbox up 77 | ``` 78 | 79 | This will run the `sandbox` shell script with the default configuration. See the [Basic Configuration](#basic-configuration) for other options. 80 | 81 | 82 | 83 | Note for Ubuntu: You may need to alias `docker` to `sudo docker` or follow the steps in https://docs.docker.com/install/linux/linux-postinstall so that a non-root user can use the command `docker`. 84 | 85 | Run the test command for examples of how to interact with the environment: 86 | 87 | ```bash 88 | ./sandbox test 89 | ``` 90 | 91 | ### Windows 92 | 93 | Note: Be sure to use the latest version of Windows 10. Older versions may not work properly. 94 | 95 | Note: While installing the following programs, several restarts may be required for windows to recognize the new software correctly. 96 | 97 | #### Option 1: Using WSL 2 98 | 99 | The [installation instructions](https://docs.docker.com/desktop/windows/install/) for Docker Desktop contain some of this but are repeated here. 100 | 101 | 1. In order to work with Docker Desktop on windows, a prerequisite is **WSL2** and [install instructions are available here](https://docs.microsoft.com/en-us/windows/wsl/install). 102 | 2. Install **Docker Desktop** using the [instructions available here](https://docs.docker.com/desktop/windows/install/). 103 | 3. We recommend using the official Windows Terminal, [available in the app store here](https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701). 104 | 4. Install whatever distribution of Linux desired. 105 | 5. Open the Windows Terminal with the distribution installed in the previous step and follow the instruction for Ubuntu and macOS above. 106 | 107 | **Tip**: If you are using VSCode, do not forget to use the WSL2 terminal inside VSCode too. You may follow [this Microsoft tutorial](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-vscode). 108 | 109 | #### Option 2: Using Git for Windows/ MSYS 2 (not recommended) 110 | 111 | This option is not fully tested and may cause issues. 112 | It is recommended to use WSL 2. 113 | 114 | 1. Install Git for Windows: https://gitforwindows.org/ 115 | 2. Install and launch Docker for Windows: https://docs.docker.com/get-docker 116 | 3. Open "Git Bash" and follow the instruction for Ubuntu and macOS above, in the "Git Bash" terminal. 117 | 118 | ##### Troubleshooting 119 | 120 | - If you see 121 | 122 | ```plain 123 | the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'. 124 | ``` 125 | 126 | check that you are using the latest versions of: Docker, Git for Windows, and Windows 10. 127 | 128 | If this does not solve the issue, [open an issue](https://github.com/algorand/sandbox/issues) with all the versions with all the software used, as well as all the commands typed. 129 | 130 | - If you see 131 | 132 | ```plain 133 | Error response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file specified. 134 | ``` 135 | 136 | check that Docker is running. 137 | 138 | ## Basic Configuration 139 | 140 | Sandbox supports two primary modes of operation. By default, a [private network](#private-network) will be created, which is only available from the local environment. There are also configurations available for the [public networks](#public-network) which will attempt to connect to one of the long running Algorand networks and allow interaction with it. 141 | 142 | To specify which configuration to run: 143 | 144 | ```sh 145 | ./sandbox up $CONFIG 146 | ``` 147 | 148 | Where `$CONFIG` is specified as one of the configurations in the sandbox directory. 149 | 150 | For example to run a `dev` mode network, run: 151 | 152 | ```sh 153 | ./sandbox up dev 154 | ``` 155 | 156 | To switch the configuration: 157 | 158 | ```sh 159 | ./sandbox down 160 | ./sandbox clean 161 | ./sandbox up $NEW_CONFIG 162 | ``` 163 | 164 | ### Private Network 165 | 166 | If no configuration is specified the sandbox will be started with the `release` configuration which is a private network. The other private network configurations are those not suffixed with `net`. Namely these are `beta`, `dev` and `nightly`. 167 | 168 | The private network environment creates and funds a number of accounts in the algod containers local `kmd` ready to use for testing transactions. These accounts can be reviewed using `./sandbox goal account list`. 169 | 170 | Private networks also include an `Indexer` API service configured to synchronize against the private network. Because it doesn't require catching up to one of the long running networks it also starts very quickly. 171 | 172 | The `dev` configuration starts a private network using the latest release with these algod configuration customizations: 173 | * `"DevMode": true` - In dev mode, every transaction being sent to the node automatically generates a new block, rather than wait for a new round in real time. This is extremely useful for fast e2e testing of an application. 174 | * `"RewardsPoolBalance": 0` - Prevents participation rewards by overriding the initial rewards pool balance. In a variety of test scenarios, participation rewards obscure testing Algo balances. 175 | 176 | It takes a long time to generate participation keys, so the default configurations use the `NETWORK_NUM_ROUNDS` parameter to limit how many are created. Unless the default value is changed, the network will stall after 24 hours. Some configurations have been changed so that they can be run for over a week. Review the setting to make sure it is suitable for how you would like to use the sandbox. 177 | 178 | ### Public Network 179 | 180 | The `mainnet`, `testnet`, `betanet`, and `devnet` configurations configure the sandbox to connect to one of those long running networks. Once started it will automatically attempt to catchup to the latest round. Catchup tends to take a while and a progress bar will be displayed to illustrate of the progress. 181 | 182 | Due to technical limitations, this configuration does not contain preconfigured accounts that may be immediately transact with, and Indexer is not available. A new wallet and accounts may be created or imported at will using the [goal wallet new](https://developer.algorand.org/docs/clis/goal/wallet/new/) command to create a wallet and the [goal account import](https://developer.algorand.org/docs/clis/goal/account/import/) or [goal account new](https://developer.algorand.org/docs/clis/goal/account/new/) commands. If a `testnet` configuration is used, please visit the [TestNet Dispenser](https://bank.testnet.algorand.network/) to fund the newly created account. 183 | 184 | ## Advanced configurations 185 | 186 | The sandbox environment is completely configured using the `config.*` files in the root of this repository. For example, the default configuration for **config.nightly** is: 187 | 188 | ```bash 189 | export ALGOD_CHANNEL="nightly" 190 | export ALGOD_URL="" 191 | export ALGOD_BRANCH="" 192 | export ALGOD_SHA="" 193 | export NETWORK="" 194 | export NETWORK_TEMPLATE="images/algod/future_template.json" 195 | export NETWORK_NUM_ROUNDS=300000 196 | export NETWORK_BOOTSTRAP_URL="" 197 | export NETWORK_GENESIS_FILE="" 198 | export NODE_ARCHIVAL="" 199 | export INDEXER_URL="https://github.com/algorand/indexer" 200 | export INDEXER_BRANCH="develop" 201 | export INDEXER_SHA="" 202 | export INDEXER_DISABLED="" 203 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 204 | export CONDUIT_URL="https://github.com/algorand/conduit" 205 | export CONDUIT_BRANCH="master" 206 | export CONDUIT_SHA="" 207 | export CONDUIT_DISABLED="" 208 | ``` 209 | 210 | Indexer and Conduit are always built from source since these can be done quickly. For most configurations, algod will be installed using our standard release channels, but building from source is also available by setting the git URL, branch and optionally a specific SHA commit hash. 211 | 212 | The **up** command looks for the config extension based on the argument provided. With a custom configuration pointed to a fork, the sandbox will start using the fork: 213 | 214 | ```bash 215 | export ALGOD_CHANNEL="" 216 | export ALGOD_URL="https://github.com//go-algorand" 217 | export ALGOD_BRANCH="my-test-branch" 218 | export ALGOD_SHA="" 219 | export ALGOD_BOOTSTRAP_URL="" 220 | export ALGOD_GENESIS_FILE="" 221 | export INDEXER_URL="https://github.com//indexer" 222 | export INDEXER_BRANCH="develop" 223 | export INDEXER_SHA="" 224 | export INDEXER_DISABLED="" 225 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 226 | export CONDUIT_URL="https://github.com//conduit" 227 | export CONDUIT_BRANCH="master" 228 | export CONDUIT_SHA="" 229 | export CONDUIT_DISABLED="" 230 | ``` 231 | 232 | ### Indexer Query Parameters 233 | 234 | By default Indexer disables many query parameters which are known to have performance problems without specially configured databases. You can identify these parameters if your Indexer calls return a response like the following: 235 | ``` 236 | {"message":"provided disabled parameter: tx-type"} 237 | ``` 238 | 239 | To override the disabled parameters and enable everything, add the following to your `config.` file: 240 | ``` 241 | export INDEXER_ENABLE_ALL_PARAMETERS="true" 242 | ``` 243 | 244 | ## Working with files 245 | 246 | Some Algorand commands require using a file for the input. For example working with TEAL programs. In some other cases like working with Logical signatures or transactions offline the output from a LogicSig or transaction may be needed. 247 | 248 | To stage a file use the `copyTo` command. The file will be placed in the algod data directory, which is where sandbox executes `goal`. This means the files can be used without specifying their full path. 249 | 250 | To copy a file from sandbox (algod instance) use the `copyFrom` command. The file will be copied to sandbox directory on host filesystem. 251 | 252 | ### copyTo example 253 | 254 | these commands will stage two TEAL programs then use them in a `goal` command: 255 | 256 | ```sh 257 | ~$ ./sandbox copyTo approval.teal 258 | ~$ ./sandbox copyTo clear.teal 259 | ~$ ./sandbox goal app create --approval-prog approval.teal --clear-prog clear.teal --creator YOUR_ACCOUNT --global-byteslices 1 --global-ints 1 --local-byteslices 1 --local-ints 1 260 | ``` 261 | 262 | ### copyFrom example 263 | 264 | these commands will create and copy a signed logic transaction file, created by `goal`, to be sent or communicated off the chain (e.g. by email or as a QR Code) and submitted else where: 265 | 266 | ```bash 267 | ~$ ./sandbox goal clerk send -f -t --fee 1000 -a 1000000 -o "unsigned.txn" 268 | ~$ ./sandbox goal clerk sign --infile unsigned.txn --outfile signed.txn 269 | ~$ ./sandbox copyFrom "signed.txn" 270 | ``` 271 | 272 | ## Errors 273 | 274 | If something goes wrong, check the `sandbox.log` file and `./sandbox dump [service]` for details. 275 | 276 | ## Debugging for teal developers 277 | 278 | For detailed information on how to debug smart contracts and use tealdbg CLI,please consult with [Algorand Development Portal :: Debugging smart contracts](https://developer.algorand.org/docs/get-details/dapps/smart-contracts/debugging/). 279 | 280 | Algorand smart contract debugging process uses `tealdbg` command line of algod instance(algod container in sandbox). 281 | 282 | **Note**: Always use `tealdbg` with `--listen 0.0.0.0` or `--listen [IP ADDRESS]` flags, if access is needed to tealdbg from outside of algod docker container! 283 | 284 | ### tealdbg examples 285 | 286 | Debugging smart contract with Chrome Developer Tools (CDT): 287 | `~$ ./sandbox tealdbg debug ${TEAL_PROGRAM} -f cdt -d dryrun.json` 288 | 289 | Debugging smart contract with Web Interface (primal web UI) 290 | `~$ ./sandbox tealdbg debug ${TEAL_PROGRAM} -f web -d dryrun.json` 291 | 292 | The debugging endpoint port (default 9392) is forwarded directly to the host machine and can be used directly by Chrome Dev Tools for debugging Algorand TEAL smart comtracts (Goto url chrome://inspect/ and configure port 9392 before using please). 293 | 294 | Note: If a different port is needed than the default, it may be changed by running `tealdbg --port YOUR_PORT` then modifying the docker-compose.yml file and change all occurances of mapped 9392 port with the desired one. 295 | 296 | ## ADVANCED: Sandbox Interactive Debugging with VSCode's `Remote - Container` Extension 297 | 298 | For those looking to develop or extend **algod** or **indexer** it's highly recommended to test and debug using a realistic environment. Being able to interactively debug code with breakpoints and introspect the stack as the Algorand daemon communicates with a live network is quite useful. Here are steps that you can take if you want to run an interactive debugger with an `indexer` running on the sandbox. Analogous instructions work for `algod` as well. 299 | 300 | Before starting, make sure you have VS-Code and have installed the [Remote - Containers Extension](https://code.visualstudio.com/docs/remote/containers-tutorial). 301 | 302 | 1. Inside [docker_compose.yml](./docker-compose.yml) add the key/val `privileged: true` under the `indexer:` service 303 | 2. Start the sandbox with `./sandbox up YOUR_CONFIG` and wait for it to be fully up and running 304 | 305 | - you may need to run a `./sandbox clean` first 306 | - you can verify by seeing healthy output from `./sandbox test` 307 | 308 | 309 | 3. In VS Code... 310 | 4. Go to the [Command Palette](https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_command-palette) (on a Mac it's **SHIFT-COMMAND-P**) and enter `Remote - Containers: Attach to Running Container` 311 | 5. The container of interest, e.g. `/algorand-sandbox-indexer`, should pop up and you should choose it 312 | 6. The first time you attach to a container, you'll get the option of choosing which top-level directory _inside the container_ to attach the file browser to. The default HOME (`/opt/indexer` in the case of indexer) is usually your best choice 313 | 7. Next, VS Code should auto-detect that you're running a `go` based project and suggest various extensions to add into the container enviroment. You should do this 314 | 8. Now navigate to the file you'd like to debug (e.g. `api/handlers.go`) and add a breakpoint as you usually would 315 | 9. You'll need to identify the PID of the indexer process so you can attach to it. Choose **Terminal** → **New Terminal** from the menu and run `ps | egrep "daemon|PID"`. Note the resulting PID 316 | 10. Now start the debugger with `F5`. It should give you the option to `attach to a process` and generate a `launch.json` with `processId: 0` for you 317 | 11. Modify the `launch.json` with the correct `processId`. Below I provide an example of a `launch.json` 318 | 12. Now you're ready to rumble! If you hit your sandbox endpoint with a well formatted request, you should end up reaching and pausing at your break point. For **indexer**, you would request against port 8980. See the `curl` example below 319 | 320 | ### Example `launch.json` 321 | 322 | ```json 323 | { 324 | // Use IntelliSense to learn about possible attributes. 325 | // Hover to view descriptions of existing attributes. 326 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 327 | "version": "0.2.0", 328 | "configurations": [ 329 | { 330 | "name": "Attach to Process", 331 | "type": "go", 332 | "request": "attach", 333 | "mode": "local", 334 | "processId": YOUR_PID_HERE 335 | } 336 | ] 337 | } 338 | ``` 339 | 340 | ### Example `curl` command 341 | 342 | ```bash 343 | ~$ curl "localhost:8980/v2/accounts" 344 | ``` 345 | 346 | ## Deep technical details 347 | 348 | ### About pseudo-TTY issues or why do we use the `-T` flag in `dc exec -T` everywhere? 349 | 350 | Windows Msys / Git Bash does not have a pseudo-TTY. 351 | Because of that, any time a command requires a pseudo-TTY, it fails with error: 352 | 353 | ```plain 354 | the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'. 355 | ``` 356 | 357 | Unfortunately prefixing all commands with `winpty` is not an option because `winpty` will break when piping or using command substitution (\`...\` and `$()`). 358 | The adopted solution is to use a pseudo-TTY only when absolutely required, that is when executing an interactive command such as `bash` inside `docker`. 359 | 360 | See comments around the commands `dc` and `dc_pty` in the file `sandbox`. 361 | -------------------------------------------------------------------------------- /config.beta: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="beta" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_BOOTSTRAP_URL="" 7 | export NETWORK_GENESIS_FILE="" 8 | export NETWORK_NUM_ROUNDS=300000 9 | export INDEXER_URL="https://github.com/algorand/indexer" 10 | export INDEXER_BRANCH="main" 11 | export INDEXER_SHA="" 12 | export INDEXER_DISABLED="" 13 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 14 | export CONDUIT_URL="https://github.com/algorand/conduit" 15 | export CONDUIT_BRANCH="master" 16 | export CONDUIT_SHA="" 17 | export CONDUIT_DISABLED="" 18 | -------------------------------------------------------------------------------- /config.betanet: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="beta" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="betanet" 6 | export NETWORK_BOOTSTRAP_URL=".algodev.network" 7 | export NETWORK_GENESIS_FILE="genesis/betanet/genesis.json" 8 | export INDEXER_URL="" 9 | export INDEXER_BRANCH="" 10 | export INDEXER_SHA="" 11 | export INDEXER_DISABLED="true" 12 | export CONDUIT_URL="" 13 | export CONDUIT_BRANCH="" 14 | export CONDUIT_SHA="" 15 | export CONDUIT_DISABLED="true" 16 | -------------------------------------------------------------------------------- /config.dev: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="stable" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_TEMPLATE="images/algod/DevModeNetwork.json" 7 | export NETWORK_BOOTSTRAP_URL="" 8 | export NETWORK_GENESIS_FILE="" 9 | export NETWORK_NUM_ROUNDS=30000 10 | export INDEXER_URL="https://github.com/algorand/indexer" 11 | export INDEXER_BRANCH="main" 12 | export INDEXER_SHA="" 13 | export INDEXER_DISABLED="" 14 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 15 | export CONDUIT_URL="https://github.com/algorand/conduit" 16 | export CONDUIT_BRANCH="master" 17 | export CONDUIT_SHA="" 18 | export CONDUIT_DISABLED="" 19 | -------------------------------------------------------------------------------- /config.devnet: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="nightly" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_BOOTSTRAP_URL=".algodev.network" 7 | export NETWORK_GENESIS_FILE="genesis/devnet/genesis.json" 8 | export INDEXER_URL="" 9 | export INDEXER_BRANCH="" 10 | export INDEXER_SHA="" 11 | export INDEXER_DISABLED="true" 12 | export CONDUIT_URL="" 13 | export CONDUIT_BRANCH="" 14 | export CONDUIT_SHA="" 15 | export CONDUIT_DISABLED="true" 16 | -------------------------------------------------------------------------------- /config.mainnet: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="stable" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="mainnet" 6 | export NETWORK_BOOTSTRAP_URL=".algorand.network" 7 | export NETWORK_GENESIS_FILE="genesis/mainnet/genesis.json" 8 | export INDEXER_URL="" 9 | export INDEXER_BRANCH="" 10 | export INDEXER_SHA="" 11 | export INDEXER_DISABLED="true" 12 | export CONDUIT_URL="" 13 | export CONDUIT_BRANCH="" 14 | export CONDUIT_SHA="" 15 | export CONDUIT_DISABLED="true" 16 | -------------------------------------------------------------------------------- /config.nightly: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="nightly" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_TEMPLATE="images/algod/future_template.json" 7 | export NETWORK_BOOTSTRAP_URL="" 8 | export NETWORK_GENESIS_FILE="" 9 | export NETWORK_NUM_ROUNDS=300000 10 | export INDEXER_URL="https://github.com/algorand/indexer" 11 | export INDEXER_BRANCH="main" 12 | export INDEXER_SHA="" 13 | export INDEXER_DISABLED="" 14 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 15 | export CONDUIT_URL="https://github.com/algorand/conduit" 16 | export CONDUIT_BRANCH="master" 17 | export CONDUIT_SHA="" 18 | export CONDUIT_DISABLED="" 19 | -------------------------------------------------------------------------------- /config.release: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="stable" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_BOOTSTRAP_URL="" 7 | export NETWORK_GENESIS_FILE="" 8 | export NETWORK_NUM_ROUNDS=300000 9 | export INDEXER_URL="https://github.com/algorand/indexer" 10 | export INDEXER_BRANCH="main" 11 | export INDEXER_SHA="" 12 | export INDEXER_DISABLED="" 13 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 14 | export CONDUIT_URL="https://github.com/algorand/conduit" 15 | export CONDUIT_BRANCH="master" 16 | export CONDUIT_SHA="" 17 | export CONDUIT_DISABLED="" 18 | -------------------------------------------------------------------------------- /config.source: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="" 2 | export ALGOD_URL="https://github.com/algorand/go-algorand" 3 | export ALGOD_BRANCH="master" 4 | export ALGOD_SHA="" 5 | export NETWORK="" 6 | export NETWORK_TEMPLATE="images/algod/DevModeNetwork.json" 7 | export NETWORK_BOOTSTRAP_URL="" 8 | export NETWORK_GENESIS_FILE="" 9 | export NETWORK_NUM_ROUNDS=30000 10 | export INDEXER_URL="https://github.com/algorand/indexer" 11 | export INDEXER_BRANCH="main" 12 | export INDEXER_SHA="" 13 | export INDEXER_DISABLED="" 14 | export INDEXER_ENABLE_ALL_PARAMETERS="false" 15 | export CONDUIT_URL="https://github.com/algorand/conduit" 16 | export CONDUIT_BRANCH="master" 17 | export CONDUIT_SHA="" 18 | export CONDUIT_DISABLED="" 19 | -------------------------------------------------------------------------------- /config.testnet: -------------------------------------------------------------------------------- 1 | export ALGOD_CHANNEL="stable" 2 | export ALGOD_URL="" 3 | export ALGOD_BRANCH="" 4 | export ALGOD_SHA="" 5 | export NETWORK="testnet" 6 | export NETWORK_BOOTSTRAP_URL=".algorand.network" 7 | export NETWORK_GENESIS_FILE="genesis/testnet/genesis.json" 8 | export INDEXER_URL="" 9 | export INDEXER_BRANCH="" 10 | export INDEXER_SHA="" 11 | export INDEXER_DISABLED="true" 12 | export CONDUIT_URL="" 13 | export CONDUIT_BRANCH="" 14 | export CONDUIT_SHA="" 15 | export CONDUIT_DISABLED="true" 16 | -------------------------------------------------------------------------------- /config/beta.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "EndpointAddress": ":4001", 3 | "DNSBootstrapID": ".algodev.network" 4 | } 5 | -------------------------------------------------------------------------------- /config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "EndpointAddress": ":4001" 3 | } 4 | -------------------------------------------------------------------------------- /config/kmd_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "address":"0.0.0.0:4002", 3 | "allowed_origins":["*"] 4 | } 5 | -------------------------------------------------------------------------------- /config/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | chmod 700 /opt/algorand/node/data/kmd-v0.5 4 | 5 | /opt/algorand/node/goal kmd start -d /opt/algorand/node/data 6 | /opt/algorand/node/algod -d /opt/algorand/node/data 7 | -------------------------------------------------------------------------------- /config/token: -------------------------------------------------------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | algod: 3 | container_name: "${ALGOD_CONTAINER:-algorand-sandbox-algod}" 4 | build: 5 | context: . 6 | dockerfile: ./images/algod/Dockerfile 7 | args: 8 | CHANNEL: "${ALGOD_CHANNEL}" 9 | URL: "${ALGOD_URL}" 10 | BRANCH: "${ALGOD_BRANCH}" 11 | SHA: "${ALGOD_SHA}" 12 | BOOTSTRAP_URL: "${NETWORK_BOOTSTRAP_URL}" 13 | GENESIS_FILE: "${NETWORK_GENESIS_FILE}" 14 | TEMPLATE: "${NETWORK_TEMPLATE:-images/algod/template.json}" 15 | NETWORK_NUM_ROUNDS: "${NETWORK_NUM_ROUNDS:-30000}" 16 | NODE_ARCHIVAL: "${NODE_ARCHIVAL}" 17 | MAX_ACCOUNT_LOOKBACK: "${MAX_ACCOUNT_LOOKBACK:-256}" 18 | TOKEN: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 19 | ALGOD_PORT: "4001" 20 | KMD_PORT: "4002" 21 | CDT_PORT: "9392" 22 | ALGOD_FOLLOWER_PORT: "3999" 23 | ports: 24 | - ${ALGOD_PORT:-4001}:4001 25 | - ${KMD_PORT:-4002}:4002 26 | - ${CDT_PORT:-9392}:9392 27 | - ${ALGOD_FOLLOWER_PORT:-3999}:3999 28 | 29 | indexer: 30 | container_name: "${INDEXER_CONTAINER:-algorand-sandbox-indexer}" 31 | build: 32 | context: . 33 | dockerfile: ./images/indexer/IndexerDockerfile 34 | args: 35 | URL: "${INDEXER_URL}" 36 | BRANCH: "${INDEXER_BRANCH}" 37 | SHA: "${INDEXER_SHA}" 38 | ports: 39 | - ${INDEXER_PORT:-8980}:8980 40 | restart: unless-stopped 41 | environment: 42 | DISABLED: "${INDEXER_DISABLED}" 43 | PORT: "8980" 44 | CONNECTION_STRING: "host=indexer-db port=5432 user=algorand password=algorand dbname=indexer_db sslmode=disable" 45 | INDEXER_ENABLE_ALL_PARAMETERS: "${INDEXER_ENABLE_ALL_PARAMETERS:-false}" 46 | depends_on: 47 | - algod 48 | - conduit 49 | 50 | conduit: 51 | container_name: "${CONDUIT_CONTAINER:-algorand-sandbox-conduit}" 52 | build: 53 | context: . 54 | dockerfile: ./images/conduit/Dockerfile 55 | args: 56 | URL: "${CONDUIT_URL}" 57 | BRANCH: "${CONDUIT_BRANCH}" 58 | SHA: "${CONDUIT_SHA}" 59 | ports: 60 | - ${CONDUIT_PORT:-3998}:3998 61 | restart: unless-stopped 62 | environment: 63 | DISABLED: "${CONDUIT_DISABLED}" 64 | PORT: "3998" 65 | CONNECTION_STRING: "host=indexer-db port=5432 user=algorand password=algorand dbname=indexer_db sslmode=disable" 66 | ALGOD_ADDR: "algod:3999" 67 | ALGOD_ADMIN_TOKEN: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 68 | depends_on: 69 | - indexer-db 70 | - algod 71 | 72 | indexer-db: 73 | image: "postgres:13-alpine" 74 | container_name: "${POSTGRES_CONTAINER:-algorand-sandbox-postgres}" 75 | ports: 76 | - ${POSTGRES_PORT:-5433}:5432 77 | user: postgres 78 | environment: 79 | POSTGRES_USER: algorand 80 | POSTGRES_PASSWORD: algorand 81 | POSTGRES_DB: indexer_db 82 | healthcheck: 83 | test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] 84 | interval: 1s 85 | timeout: 5s 86 | retries: 10 87 | -------------------------------------------------------------------------------- /genesis/betanet/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "alloc": [ 3 | { 4 | "addr": "7777777777777777777777777777777777777777777777777774MSJUVU", 5 | "comment": "RewardsPool", 6 | "state": { 7 | "algo": 125000000000000, 8 | "onl": 2 9 | } 10 | }, 11 | { 12 | "addr": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 13 | "comment": "FeeSink", 14 | "state": { 15 | "algo": 100000, 16 | "onl": 2 17 | } 18 | }, 19 | { 20 | "addr": "E6JSNTY4PVCY3IRZ6XEDHEO6VIHCQ5KGXCIQKFQCMB2N6HXRY4IB43VSHI", 21 | "comment": "Wallet1", 22 | "state": { 23 | "algo": 500000000000000, 24 | "onl": 1, 25 | "sel": "KsJHGwqm40hKgq91j3e5/RgK8XDiWloeN8FfYB4UKHs=", 26 | "vote": "21YWFk+gtv9AP0vXPXHubfXSWwstKfbKwIIPOYB395I=", 27 | "voteKD": 10000, 28 | "voteLst": 3000000 29 | } 30 | }, 31 | { 32 | "addr": "SEMQ3EH6AHVCXZDHCDH3OYBJJGGLHDUFGYVCTJUUJMLO4J5F4E6AIXH3R4", 33 | "comment": "Wallet10", 34 | "state": { 35 | "algo": 500000000000000, 36 | "onl": 1, 37 | "sel": "kRtZiTWtKjFbx58DxEllyZ0/7mQYjT4gdilgNLEEcIQ=", 38 | "vote": "QN1+DlX+2JE8O0NiFTSH+50sXpTYT79HVIYf0YRp1P4=", 39 | "voteKD": 10000, 40 | "voteLst": 3000000 41 | } 42 | }, 43 | { 44 | "addr": "BIKIMTXSESQTR5BMPELZO2TFASGCGSXZ2ZA2MSHEUYLJNNXUGJCX6JV2TU", 45 | "comment": "Wallet11", 46 | "state": { 47 | "algo": 500000000000000, 48 | "onl": 1, 49 | "sel": "GVGFHDix++jaHjeVqHQd2tvlkaJzPpkFOqM/xOV8HEs=", 50 | "vote": "Qb20Au5yVWckwkgLS1VrCA867xrBwMwpWvvdVeOgbfE=", 51 | "voteKD": 10000, 52 | "voteLst": 3000000 53 | } 54 | }, 55 | { 56 | "addr": "7ERQUUQLQ5K6GVYVAFE25Z42OQMI5JCSBOWORHRT4GMSC3GZFWCOBI67YE", 57 | "comment": "Wallet12", 58 | "state": { 59 | "algo": 500000000000000, 60 | "onl": 1, 61 | "sel": "kBuLytQUQIp9NrAyYbXZk4L9Qf7voFh7B3t4zsdX9tc=", 62 | "vote": "SOB4dO+4R93RvzXZop17kn4wS/YjnmELqQapQ0PDFZM=", 63 | "voteKD": 10000, 64 | "voteLst": 3000000 65 | } 66 | }, 67 | { 68 | "addr": "MIZXEAYWBLOMNXCU52OF6ZTYH7LP7W47SKLHIGKLTGEXJHQGD7RHGMUPQQ", 69 | "comment": "Wallet13", 70 | "state": { 71 | "algo": 500000000000000, 72 | "onl": 1, 73 | "sel": "KqpOt2cIsDwGbnNhzRzET4/UR0NhPhKSCG6g86ewFQA=", 74 | "vote": "FIwKS4PBidGgLmAqYMPlxOP0H2LlCF9GC9lWE8Jl4As=", 75 | "voteKD": 10000, 76 | "voteLst": 3000000 77 | } 78 | }, 79 | { 80 | "addr": "77FPBCDQOMSOUWOY47HWPGOKSTLQITEZ7QR7GU4TOV3KVIFV2YS3WQG2OI", 81 | "comment": "Wallet14", 82 | "state": { 83 | "algo": 500000000000000, 84 | "onl": 1, 85 | "sel": "M71rgLk28vIZgk73ag1K+2cH33J9viIzXnsrbISmc4Q=", 86 | "vote": "B7O1giNLhEIJWCcXUmZ9X4j/dsVw9Zm5dmXDbn+3ack=", 87 | "voteKD": 10000, 88 | "voteLst": 3000000 89 | } 90 | }, 91 | { 92 | "addr": "JDTPB2DSAH42CRL6SKZ3BZ37WIGCHAYRO6DT6PBJNV47566EVQLEOINXEY", 93 | "comment": "Wallet15", 94 | "state": { 95 | "algo": 500000000000000, 96 | "onl": 1, 97 | "sel": "sj1Ap7Wz5GmfQfAJTiv1+eoL0q/2IsER14jxMtxsQok=", 98 | "vote": "P1igemO61V2fz9nb4jaiOaFbpnUZPhKuyNx3j09swSY=", 99 | "voteKD": 10000, 100 | "voteLst": 3000000 101 | } 102 | }, 103 | { 104 | "addr": "H6BA5HI7TTKCP76QFTO4EO4MKTOI6XM6R75QRZLGV2H4VAOXIMGCXGIH5Y", 105 | "comment": "Wallet16", 106 | "state": { 107 | "algo": 500000000000000, 108 | "onl": 1, 109 | "sel": "RjsQgzT6eUx88673bdCQm12TmDLi93v92s+E3TK1XWA=", 110 | "vote": "tQtvPw70hZDbrROzsSz27UdN6EIPj2dQFTtzsY6pCVQ=", 111 | "voteKD": 10000, 112 | "voteLst": 3000000 113 | } 114 | }, 115 | { 116 | "addr": "FCHLCNFIQ3L5QELMQDADI6BU2ANK2A2ICKXXG7ACJBNEAB64J7UJUPJHJE", 117 | "comment": "Wallet17", 118 | "state": { 119 | "algo": 500000000000000, 120 | "onl": 1, 121 | "sel": "22Dvgroawrb1g7LotUhbTOV/7g1Rn410I1X8CmDeT0A=", 122 | "vote": "SGXiNwAfMRI00SYVpVClqTNJcwBrQF3X77DsWSAO5jo=", 123 | "voteKD": 10000, 124 | "voteLst": 3000000 125 | } 126 | }, 127 | { 128 | "addr": "LKH4JTUIOE6I4PH4HVJN6PYZ23WGGWDVJGHM2YXI6IYV5TEECQSTNKMQ2E", 129 | "comment": "Wallet18", 130 | "state": { 131 | "algo": 500000000000000, 132 | "onl": 1, 133 | "sel": "uzGW1wXnBiny4kB4JSpEbCVQvKE8BeO+/o/pdkgfFaY=", 134 | "vote": "ahu0YwixBhpEc+Xvw5oqgwDMnemXHWk8g/Uf/EI5nmA=", 135 | "voteKD": 10000, 136 | "voteLst": 3000000 137 | } 138 | }, 139 | { 140 | "addr": "QFH2SS4MGPFNUUDMNLKIUKX5HKAZRXT765WH7WTUBAQNEM7IJAVKAE6NWM", 141 | "comment": "Wallet19", 142 | "state": { 143 | "algo": 400000000000000, 144 | "onl": 1, 145 | "sel": "eE4Wcuz8VeGclgU99Q9rDpehNR+yP2afFYuDAxb/Ebo=", 146 | "vote": "4wsLw785udvYCpn5jzdLqcEHmIQIbRPmbyPt4oTLD2U=", 147 | "voteKD": 10000, 148 | "voteLst": 3000000 149 | } 150 | }, 151 | { 152 | "addr": "6SKIRCMLFSSY3EJUC6QGFM3TFIJH72ZYUHX7GCUBDBUBYCAHJBJ5PWB344", 153 | "comment": "Wallet2", 154 | "state": { 155 | "algo": 500000000000000, 156 | "onl": 1, 157 | "sel": "j7WaD43EwoxM5U18kMWn5HfIdn/ICVuMmsj3O5EbFWM=", 158 | "vote": "jAuOIqeQH81zZs4+6YBircvi63xXMN1MIABcOiuzXXs=", 159 | "voteKD": 10000, 160 | "voteLst": 3000000 161 | } 162 | }, 163 | { 164 | "addr": "OYD4RZDUBQBVQL4WEPTBVLU6YC7HWHDAS4MMTLQ643Q3O7JRQW6FTWXIWQ", 165 | "comment": "Wallet20", 166 | "state": { 167 | "algo": 400000000000000, 168 | "onl": 1, 169 | "sel": "9LdCYfMPglvbManNcmVLztu/yPhPPkaRaSKMzj5E24w=", 170 | "vote": "ZbN0ELPvL5QizuLvVc7oInsju+irjDRcdYDNnKJV2bg=", 171 | "voteKD": 10000, 172 | "voteLst": 3000000 173 | } 174 | }, 175 | { 176 | "addr": "SSKILTKR47YW2IXCJCNUK66ATVLMU53IV5SEC2IXQ4WEPV5EKCAVPCEKMA", 177 | "comment": "Wallet3", 178 | "state": { 179 | "algo": 500000000000000, 180 | "onl": 1, 181 | "sel": "4cxWnAD3DoIel3OuRqOpYgtWP7J873g688P4pXPVhBc=", 182 | "vote": "keW3j4bRW0uvd6ofaDNUuMBdz/v/eWZsLhdFIOlXWCg=", 183 | "voteKD": 10000, 184 | "voteLst": 3000000 185 | } 186 | }, 187 | { 188 | "addr": "FE4FDICQLO63S33NL75GBDKAKPGX7B3UMRBBSM5V2JYO4LCLRSE4HQ4YJI", 189 | "comment": "Wallet4", 190 | "state": { 191 | "algo": 500000000000000, 192 | "onl": 1, 193 | "sel": "AILWKIbgQzCSPaaYAMFek1mu6uWYqm2QoIvP97h9wFg=", 194 | "vote": "YXmnzyrRI4c16DauzENAK9bOqatN7qjLAbWUp0L6qXM=", 195 | "voteKD": 10000, 196 | "voteLst": 3000000 197 | } 198 | }, 199 | { 200 | "addr": "2N3Y42EA3OPXCOFPKRH4HFOF6FX7QUT45A7CZH4WXGGQDDYSHP6NZGNL24", 201 | "comment": "Wallet5", 202 | "state": { 203 | "algo": 500000000000000, 204 | "onl": 1, 205 | "sel": "lOU6PeVi+AT4lc2tj90AoNQyw3un0Smzk9sOpKCWI1k=", 206 | "vote": "PztZkAup9rAMUreL+HQXCy7mbM39PZ5xl+YiTT4L9YE=", 207 | "voteKD": 10000, 208 | "voteLst": 3000000 209 | } 210 | }, 211 | { 212 | "addr": "UJ3HDASRQG2QRPZUS5TOESFIMIDB4ELNE7DO2WGO5LJQ2KT32VGFGGCQKA", 213 | "comment": "Wallet6", 214 | "state": { 215 | "algo": 500000000000000, 216 | "onl": 1, 217 | "sel": "rPMShsyg18Ho9JOQQjcG2yhPMBM0JIgZsr5ndy+0buo=", 218 | "vote": "TFVn1TMHAmcM+St5QLhaFG/dlSGqqlTdGjgjcfSax5M=", 219 | "voteKD": 10000, 220 | "voteLst": 3000000 221 | } 222 | }, 223 | { 224 | "addr": "QBQ5ODCH6PWCB5TFQVCOFLHSJKN6NYYB3E3HPCJJTTNRVM5XD3B3KPWFJA", 225 | "comment": "Wallet7", 226 | "state": { 227 | "algo": 500000000000000, 228 | "onl": 1, 229 | "sel": "cxhpl3wBnc9bVW6G5ePiya8nzPvUUaprIoTWvTXJmpY=", 230 | "vote": "W8tVBEdWGDArQFj43qXDw18LRJKaGjgZWUv54tsus+A=", 231 | "voteKD": 10000, 232 | "voteLst": 3000000 233 | } 234 | }, 235 | { 236 | "addr": "WILFZPBQMJ7GYSPNA6JPXIZZUZ27XWDJ2NKC7WIODXXGOF73C4TEDEHE3U", 237 | "comment": "Wallet8", 238 | "state": { 239 | "algo": 500000000000000, 240 | "onl": 1, 241 | "sel": "SMSZnIm3GSD1Dr5AEq5ksxxCIqPIrn19WSDNtJSJuiM=", 242 | "vote": "absDJtKafyc4KbrB1GnLcFGv8xQjuqB46gPXXTpIsTU=", 243 | "voteKD": 10000, 244 | "voteLst": 3000000 245 | } 246 | }, 247 | { 248 | "addr": "4LSVIF5EY2BQZ6GENL6GT4SQTKX3UVDTBDJXFESGY7GI7FXHZA522KMG5I", 249 | "comment": "Wallet9", 250 | "state": { 251 | "algo": 500000000000000, 252 | "onl": 1, 253 | "sel": "h3aKVPyQSpXAI2zcDD2f1CCBqf9fQd4Z+oJjQ6erFLI=", 254 | "vote": "nNfIrFtpPR6zo4hH6F7HCMA44PDcNOEWtDVRf7dnKe4=", 255 | "voteKD": 10000, 256 | "voteLst": 3000000 257 | } 258 | }, 259 | { 260 | "addr": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", 261 | "comment": "bank", 262 | "state": { 263 | "algo": 100000000000000, 264 | "onl": 1, 265 | "sel": "6Rax2zpOehfDXHyyvMFJwc22A//Pm6rxW4MiEBGIwog=", 266 | "vote": "5JbOqqGn1Ypw+uH3t2i61DcjWYo1AslT0jyOGgcVC6Y=", 267 | "voteKD": 10000, 268 | "voteLst": 3000000 269 | } 270 | }, 271 | { 272 | "addr": "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI", 273 | "comment": "pp1", 274 | "state": { 275 | "algo": 50000000000000 276 | } 277 | }, 278 | { 279 | "addr": "F5FALDSUFYO5LQU4OQY2HPZTXSUPRHUAERZ7IDG5QCBC76AOHEPK2VUJ34", 280 | "comment": "pp2", 281 | "state": { 282 | "algo": 50000000000000 283 | } 284 | } 285 | ], 286 | "fees": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 287 | "id": "v1.0", 288 | "network": "betanet", 289 | "proto": "https://github.com/algorand/spec/tree/a26ed78ed8f834e2b9ccb6eb7d3ee9f629a6e622", 290 | "rwd": "7777777777777777777777777777777777777777777777777774MSJUVU", 291 | "timestamp": 1564572341 292 | } -------------------------------------------------------------------------------- /genesis/devnet/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "alloc": [ 3 | { 4 | "addr": "7777777777777777777777777777777777777777777777777774MSJUVU", 5 | "comment": "RewardsPool", 6 | "state": { 7 | "algo": 125000000000000, 8 | "onl": 2 9 | } 10 | }, 11 | { 12 | "addr": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 13 | "comment": "FeeSink", 14 | "state": { 15 | "algo": 100000, 16 | "onl": 2 17 | } 18 | }, 19 | { 20 | "addr": "E6JSNTY4PVCY3IRZ6XEDHEO6VIHCQ5KGXCIQKFQCMB2N6HXRY4IB43VSHI", 21 | "comment": "Wallet1", 22 | "state": { 23 | "algo": 500000000000000, 24 | "onl": 1, 25 | "sel": "KsJHGwqm40hKgq91j3e5/RgK8XDiWloeN8FfYB4UKHs=", 26 | "vote": "21YWFk+gtv9AP0vXPXHubfXSWwstKfbKwIIPOYB395I=", 27 | "voteKD": 10000, 28 | "voteLst": 3000000 29 | } 30 | }, 31 | { 32 | "addr": "SEMQ3EH6AHVCXZDHCDH3OYBJJGGLHDUFGYVCTJUUJMLO4J5F4E6AIXH3R4", 33 | "comment": "Wallet10", 34 | "state": { 35 | "algo": 500000000000000, 36 | "onl": 1, 37 | "sel": "kRtZiTWtKjFbx58DxEllyZ0/7mQYjT4gdilgNLEEcIQ=", 38 | "vote": "QN1+DlX+2JE8O0NiFTSH+50sXpTYT79HVIYf0YRp1P4=", 39 | "voteKD": 10000, 40 | "voteLst": 3000000 41 | } 42 | }, 43 | { 44 | "addr": "BIKIMTXSESQTR5BMPELZO2TFASGCGSXZ2ZA2MSHEUYLJNNXUGJCX6JV2TU", 45 | "comment": "Wallet11", 46 | "state": { 47 | "algo": 500000000000000, 48 | "onl": 1, 49 | "sel": "GVGFHDix++jaHjeVqHQd2tvlkaJzPpkFOqM/xOV8HEs=", 50 | "vote": "Qb20Au5yVWckwkgLS1VrCA867xrBwMwpWvvdVeOgbfE=", 51 | "voteKD": 10000, 52 | "voteLst": 3000000 53 | } 54 | }, 55 | { 56 | "addr": "7ERQUUQLQ5K6GVYVAFE25Z42OQMI5JCSBOWORHRT4GMSC3GZFWCOBI67YE", 57 | "comment": "Wallet12", 58 | "state": { 59 | "algo": 500000000000000, 60 | "onl": 1, 61 | "sel": "kBuLytQUQIp9NrAyYbXZk4L9Qf7voFh7B3t4zsdX9tc=", 62 | "vote": "SOB4dO+4R93RvzXZop17kn4wS/YjnmELqQapQ0PDFZM=", 63 | "voteKD": 10000, 64 | "voteLst": 3000000 65 | } 66 | }, 67 | { 68 | "addr": "MIZXEAYWBLOMNXCU52OF6ZTYH7LP7W47SKLHIGKLTGEXJHQGD7RHGMUPQQ", 69 | "comment": "Wallet13", 70 | "state": { 71 | "algo": 500000000000000, 72 | "onl": 1, 73 | "sel": "KqpOt2cIsDwGbnNhzRzET4/UR0NhPhKSCG6g86ewFQA=", 74 | "vote": "FIwKS4PBidGgLmAqYMPlxOP0H2LlCF9GC9lWE8Jl4As=", 75 | "voteKD": 10000, 76 | "voteLst": 3000000 77 | } 78 | }, 79 | { 80 | "addr": "77FPBCDQOMSOUWOY47HWPGOKSTLQITEZ7QR7GU4TOV3KVIFV2YS3WQG2OI", 81 | "comment": "Wallet14", 82 | "state": { 83 | "algo": 500000000000000, 84 | "onl": 1, 85 | "sel": "M71rgLk28vIZgk73ag1K+2cH33J9viIzXnsrbISmc4Q=", 86 | "vote": "B7O1giNLhEIJWCcXUmZ9X4j/dsVw9Zm5dmXDbn+3ack=", 87 | "voteKD": 10000, 88 | "voteLst": 3000000 89 | } 90 | }, 91 | { 92 | "addr": "JDTPB2DSAH42CRL6SKZ3BZ37WIGCHAYRO6DT6PBJNV47566EVQLEOINXEY", 93 | "comment": "Wallet15", 94 | "state": { 95 | "algo": 500000000000000, 96 | "onl": 1, 97 | "sel": "sj1Ap7Wz5GmfQfAJTiv1+eoL0q/2IsER14jxMtxsQok=", 98 | "vote": "P1igemO61V2fz9nb4jaiOaFbpnUZPhKuyNx3j09swSY=", 99 | "voteKD": 10000, 100 | "voteLst": 3000000 101 | } 102 | }, 103 | { 104 | "addr": "H6BA5HI7TTKCP76QFTO4EO4MKTOI6XM6R75QRZLGV2H4VAOXIMGCXGIH5Y", 105 | "comment": "Wallet16", 106 | "state": { 107 | "algo": 500000000000000, 108 | "onl": 1, 109 | "sel": "RjsQgzT6eUx88673bdCQm12TmDLi93v92s+E3TK1XWA=", 110 | "vote": "tQtvPw70hZDbrROzsSz27UdN6EIPj2dQFTtzsY6pCVQ=", 111 | "voteKD": 10000, 112 | "voteLst": 3000000 113 | } 114 | }, 115 | { 116 | "addr": "FCHLCNFIQ3L5QELMQDADI6BU2ANK2A2ICKXXG7ACJBNEAB64J7UJUPJHJE", 117 | "comment": "Wallet17", 118 | "state": { 119 | "algo": 500000000000000, 120 | "onl": 1, 121 | "sel": "22Dvgroawrb1g7LotUhbTOV/7g1Rn410I1X8CmDeT0A=", 122 | "vote": "SGXiNwAfMRI00SYVpVClqTNJcwBrQF3X77DsWSAO5jo=", 123 | "voteKD": 10000, 124 | "voteLst": 3000000 125 | } 126 | }, 127 | { 128 | "addr": "LKH4JTUIOE6I4PH4HVJN6PYZ23WGGWDVJGHM2YXI6IYV5TEECQSTNKMQ2E", 129 | "comment": "Wallet18", 130 | "state": { 131 | "algo": 500000000000000, 132 | "onl": 1, 133 | "sel": "uzGW1wXnBiny4kB4JSpEbCVQvKE8BeO+/o/pdkgfFaY=", 134 | "vote": "ahu0YwixBhpEc+Xvw5oqgwDMnemXHWk8g/Uf/EI5nmA=", 135 | "voteKD": 10000, 136 | "voteLst": 3000000 137 | } 138 | }, 139 | { 140 | "addr": "QFH2SS4MGPFNUUDMNLKIUKX5HKAZRXT765WH7WTUBAQNEM7IJAVKAE6NWM", 141 | "comment": "Wallet19", 142 | "state": { 143 | "algo": 400000000000000, 144 | "onl": 1, 145 | "sel": "eE4Wcuz8VeGclgU99Q9rDpehNR+yP2afFYuDAxb/Ebo=", 146 | "vote": "4wsLw785udvYCpn5jzdLqcEHmIQIbRPmbyPt4oTLD2U=", 147 | "voteKD": 10000, 148 | "voteLst": 3000000 149 | } 150 | }, 151 | { 152 | "addr": "6SKIRCMLFSSY3EJUC6QGFM3TFIJH72ZYUHX7GCUBDBUBYCAHJBJ5PWB344", 153 | "comment": "Wallet2", 154 | "state": { 155 | "algo": 500000000000000, 156 | "onl": 1, 157 | "sel": "j7WaD43EwoxM5U18kMWn5HfIdn/ICVuMmsj3O5EbFWM=", 158 | "vote": "jAuOIqeQH81zZs4+6YBircvi63xXMN1MIABcOiuzXXs=", 159 | "voteKD": 10000, 160 | "voteLst": 3000000 161 | } 162 | }, 163 | { 164 | "addr": "OYD4RZDUBQBVQL4WEPTBVLU6YC7HWHDAS4MMTLQ643Q3O7JRQW6FTWXIWQ", 165 | "comment": "Wallet20", 166 | "state": { 167 | "algo": 400000000000000, 168 | "onl": 1, 169 | "sel": "9LdCYfMPglvbManNcmVLztu/yPhPPkaRaSKMzj5E24w=", 170 | "vote": "ZbN0ELPvL5QizuLvVc7oInsju+irjDRcdYDNnKJV2bg=", 171 | "voteKD": 10000, 172 | "voteLst": 3000000 173 | } 174 | }, 175 | { 176 | "addr": "SSKILTKR47YW2IXCJCNUK66ATVLMU53IV5SEC2IXQ4WEPV5EKCAVPCEKMA", 177 | "comment": "Wallet3", 178 | "state": { 179 | "algo": 500000000000000, 180 | "onl": 1, 181 | "sel": "4cxWnAD3DoIel3OuRqOpYgtWP7J873g688P4pXPVhBc=", 182 | "vote": "keW3j4bRW0uvd6ofaDNUuMBdz/v/eWZsLhdFIOlXWCg=", 183 | "voteKD": 10000, 184 | "voteLst": 3000000 185 | } 186 | }, 187 | { 188 | "addr": "FE4FDICQLO63S33NL75GBDKAKPGX7B3UMRBBSM5V2JYO4LCLRSE4HQ4YJI", 189 | "comment": "Wallet4", 190 | "state": { 191 | "algo": 500000000000000, 192 | "onl": 1, 193 | "sel": "AILWKIbgQzCSPaaYAMFek1mu6uWYqm2QoIvP97h9wFg=", 194 | "vote": "YXmnzyrRI4c16DauzENAK9bOqatN7qjLAbWUp0L6qXM=", 195 | "voteKD": 10000, 196 | "voteLst": 3000000 197 | } 198 | }, 199 | { 200 | "addr": "2N3Y42EA3OPXCOFPKRH4HFOF6FX7QUT45A7CZH4WXGGQDDYSHP6NZGNL24", 201 | "comment": "Wallet5", 202 | "state": { 203 | "algo": 500000000000000, 204 | "onl": 1, 205 | "sel": "lOU6PeVi+AT4lc2tj90AoNQyw3un0Smzk9sOpKCWI1k=", 206 | "vote": "PztZkAup9rAMUreL+HQXCy7mbM39PZ5xl+YiTT4L9YE=", 207 | "voteKD": 10000, 208 | "voteLst": 3000000 209 | } 210 | }, 211 | { 212 | "addr": "UJ3HDASRQG2QRPZUS5TOESFIMIDB4ELNE7DO2WGO5LJQ2KT32VGFGGCQKA", 213 | "comment": "Wallet6", 214 | "state": { 215 | "algo": 500000000000000, 216 | "onl": 1, 217 | "sel": "rPMShsyg18Ho9JOQQjcG2yhPMBM0JIgZsr5ndy+0buo=", 218 | "vote": "TFVn1TMHAmcM+St5QLhaFG/dlSGqqlTdGjgjcfSax5M=", 219 | "voteKD": 10000, 220 | "voteLst": 3000000 221 | } 222 | }, 223 | { 224 | "addr": "QBQ5ODCH6PWCB5TFQVCOFLHSJKN6NYYB3E3HPCJJTTNRVM5XD3B3KPWFJA", 225 | "comment": "Wallet7", 226 | "state": { 227 | "algo": 500000000000000, 228 | "onl": 1, 229 | "sel": "cxhpl3wBnc9bVW6G5ePiya8nzPvUUaprIoTWvTXJmpY=", 230 | "vote": "W8tVBEdWGDArQFj43qXDw18LRJKaGjgZWUv54tsus+A=", 231 | "voteKD": 10000, 232 | "voteLst": 3000000 233 | } 234 | }, 235 | { 236 | "addr": "WILFZPBQMJ7GYSPNA6JPXIZZUZ27XWDJ2NKC7WIODXXGOF73C4TEDEHE3U", 237 | "comment": "Wallet8", 238 | "state": { 239 | "algo": 500000000000000, 240 | "onl": 1, 241 | "sel": "SMSZnIm3GSD1Dr5AEq5ksxxCIqPIrn19WSDNtJSJuiM=", 242 | "vote": "absDJtKafyc4KbrB1GnLcFGv8xQjuqB46gPXXTpIsTU=", 243 | "voteKD": 10000, 244 | "voteLst": 3000000 245 | } 246 | }, 247 | { 248 | "addr": "4LSVIF5EY2BQZ6GENL6GT4SQTKX3UVDTBDJXFESGY7GI7FXHZA522KMG5I", 249 | "comment": "Wallet9", 250 | "state": { 251 | "algo": 500000000000000, 252 | "onl": 1, 253 | "sel": "h3aKVPyQSpXAI2zcDD2f1CCBqf9fQd4Z+oJjQ6erFLI=", 254 | "vote": "nNfIrFtpPR6zo4hH6F7HCMA44PDcNOEWtDVRf7dnKe4=", 255 | "voteKD": 10000, 256 | "voteLst": 3000000 257 | } 258 | }, 259 | { 260 | "addr": "IDUTJEUIEVSMXTU4LGTJWZ2UE2E6TIODUKU6UW3FU3UKIQQ77RLUBBBFLA", 261 | "comment": "bank", 262 | "state": { 263 | "algo": 100000000000000, 264 | "onl": 1, 265 | "sel": "6Rax2zpOehfDXHyyvMFJwc22A//Pm6rxW4MiEBGIwog=", 266 | "vote": "5JbOqqGn1Ypw+uH3t2i61DcjWYo1AslT0jyOGgcVC6Y=", 267 | "voteKD": 10000, 268 | "voteLst": 3000000 269 | } 270 | }, 271 | { 272 | "addr": "PNWOET7LLOWMBMLE4KOCELCX6X3D3Q4H2Q4QJASYIEOF7YIPPQBG3YQ5YI", 273 | "comment": "pp1", 274 | "state": { 275 | "algo": 50000000000000 276 | } 277 | }, 278 | { 279 | "addr": "F5FALDSUFYO5LQU4OQY2HPZTXSUPRHUAERZ7IDG5QCBC76AOHEPK2VUJ34", 280 | "comment": "pp2", 281 | "state": { 282 | "algo": 50000000000000 283 | } 284 | } 285 | ], 286 | "fees": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 287 | "id": "v1.0", 288 | "network": "devnet", 289 | "proto": "https://github.com/algorand/spec/tree/a26ed78ed8f834e2b9ccb6eb7d3ee9f629a6e622", 290 | "rwd": "7777777777777777777777777777777777777777777777777774MSJUVU", 291 | "timestamp": 1560210489 292 | } 293 | -------------------------------------------------------------------------------- /genesis/mainnet/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "alloc": [ 3 | { 4 | "addr": "737777777777777777777777777777777777777777777777777UFEJ2CI", 5 | "comment": "RewardsPool", 6 | "state": { 7 | "algo": 10000000000000, 8 | "onl": 2 9 | } 10 | }, 11 | { 12 | "addr": "Y76M3MSY6DKBRHBL7C3NNDXGS5IIMQVQVUAB6MP4XEMMGVF2QWNPL226CA", 13 | "comment": "FeeSink", 14 | "state": { 15 | "algo": 1000000, 16 | "onl": 2 17 | } 18 | }, 19 | { 20 | "addr": "ALGORANDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIN5DNAU", 21 | "comment": "A BIT DOES E NOT BUT E STARTS EVERYTHING LIFE A MANY FORTUNE R BUILD SIMPLER BE THE STARTS PERSEVERES FAVORS A ENOUGH RIPROVANDO POSSIBLE JOURNEY VICTORIA HE BOLD U WITHOUT MEN A K OF BORDERS WHO HE E RACES TOMORROW BUT WHO SINGLE PURPOSE GEOGRAPHICAL PROVANDO A KNOW SUFFOCATES NOT SCIENCE STEP MATHEMATICS OF OR A BRIDGES WALLS TECHNOLOGY TODAY AND WITH AS ET MILES OF THOUSAND VITA SIMPLE TOO MUST AS NOT MADE NOT", 22 | "state": { 23 | "algo": 1000000, 24 | "onl": 2 25 | } 26 | }, 27 | { 28 | "addr": "XQJEJECPWUOXSKMIC5TCSARPVGHQJIIOKHO7WTKEPPLJMKG3D7VWWID66E", 29 | "comment": "AlgorandCommunityAnnouncement", 30 | "state": { 31 | "algo": 10000000, 32 | "onl": 2 33 | } 34 | }, 35 | { 36 | "addr": "VCINCVUX2DBKQ6WP63NOGPEAQAYGHGSGQX7TSH4M5LI5NBPVAGIHJPMIPM", 37 | "comment": "AuctionsMaster", 38 | "state": { 39 | "algo": 1000000000, 40 | "onl": 2 41 | } 42 | }, 43 | { 44 | "addr": "OGP6KK5KCMHT4GOEQXJ4LLNJ7D6P6IH7MV5WZ5EX4ZWACHP75ID5PPEE5E", 45 | "comment": "", 46 | "state": { 47 | "algo": 300000000000000, 48 | "onl": 2 49 | } 50 | }, 51 | { 52 | "addr": "AYBHAG2DAIOG26QEV35HKUBGWPMPOCCQ44MQEY32UOW3EXEMSZEIS37M2U", 53 | "comment": "", 54 | "state": { 55 | "algo": 300000000000000, 56 | "onl": 2 57 | } 58 | }, 59 | { 60 | "addr": "2XKK2L6HOBCYHGIGBS3N365FJKHS733QOX42HIYLSBARUIJHMGQZYAQDRY", 61 | "comment": "", 62 | "state": { 63 | "algo": 300000000000000, 64 | "onl": 2 65 | } 66 | }, 67 | { 68 | "addr": "ZBSPQQG7O5TR5MHPG3D5RS2TIFFD5NMOPR77VUKURMN6HV2BSN224ZHKGU", 69 | "comment": "", 70 | "state": { 71 | "algo": 300000000000000, 72 | "onl": 2 73 | } 74 | }, 75 | { 76 | "addr": "7NQED6NJ4NZU7B5HGGFU2ZEC2UZQYU2SA5S4QOE2EXBVAR4CNAHIXV2XYY", 77 | "comment": "", 78 | "state": { 79 | "algo": 300000000000000, 80 | "onl": 2 81 | } 82 | }, 83 | { 84 | "addr": "RX2ZKVJ43GNYDJNIOB6TIX26U7UEQFUQY46OMHX6CXLMMBHENJIH4YVLUQ", 85 | "comment": "", 86 | "state": { 87 | "algo": 300000000000000, 88 | "onl": 2 89 | } 90 | }, 91 | { 92 | "addr": "RHSKYCCZYYQ2BL6Z63626YUETJMLFGVVV47ED5D55EKIK4YFJ5DQT5CV4A", 93 | "comment": "", 94 | "state": { 95 | "algo": 300000000000000, 96 | "onl": 2 97 | } 98 | }, 99 | { 100 | "addr": "RJS6FDZ46ZZJIONLMMCKDJHYSJNHHAXNABMAVSGH23ULJSEAHZC6AQ6ALE", 101 | "comment": "", 102 | "state": { 103 | "algo": 300000000000000, 104 | "onl": 2 105 | } 106 | }, 107 | { 108 | "addr": "AZ2KKAHF2PJMEEUVN4E2ILMNJCSZLJJYVLBIA7HOY3BQ7AENOVVTXMGN3I", 109 | "comment": "", 110 | "state": { 111 | "algo": 300000000000000, 112 | "onl": 2 113 | } 114 | }, 115 | { 116 | "addr": "CGUKRKXNMEEOK7SJKOGXLRWEZESF24ELG3TAW6LUF43XRT2LX4OVQLU4BQ", 117 | "comment": "", 118 | "state": { 119 | "algo": 300000000000000, 120 | "onl": 2 121 | } 122 | }, 123 | { 124 | "addr": "VVW6BVYHBG7MZQXKAR3OSPUZVAZ66JMQHOBMIBJG6YSPR7SLMNAPA7UWGY", 125 | "comment": "", 126 | "state": { 127 | "algo": 250000000000000, 128 | "onl": 2 129 | } 130 | }, 131 | { 132 | "addr": "N5BGWISAJSYT7MVW2BDTTEHOXFQF4QQH4VKSMKJEOA4PHPYND43D6WWTIU", 133 | "comment": "", 134 | "state": { 135 | "algo": 1740000000000000, 136 | "onl": 2 137 | } 138 | }, 139 | { 140 | "addr": "MKT3JAP2CEI5C4IX73U7QKRUF6JR7KPKE2YD6BLURFVPW6N7CYXVBSJPEQ", 141 | "comment": "", 142 | "state": { 143 | "algo": 158000000000000, 144 | "onl": 2 145 | } 146 | }, 147 | { 148 | "addr": "GVCPSWDNSL54426YL76DZFVIZI5OIDC7WEYSJLBFFEQYPXM7LTGSDGC4SA", 149 | "comment": "", 150 | "state": { 151 | "algo": 49998988000000, 152 | "onl": 1, 153 | "sel": "lZ9z6g0oSlis/8ZlEyOMiGfX0XDUcObfpJEg5KjU0OA=", 154 | "vote": "Kk+5CcpHWIXSMO9GiAvnfe+eNSeRtpDb2telHb6I1EE=", 155 | "voteKD": 10000, 156 | "voteLst": 3000000 157 | } 158 | }, 159 | { 160 | "addr": "M7XKTBQXVQARLS7IVS6NVDHNLJFIAXR2CGGZTUDEKRIHRVLWL5TJFJOL5U", 161 | "comment": "", 162 | "state": { 163 | "algo": 50000000000000, 164 | "onl": 1, 165 | "sel": "Z5gE/m2E/WSuaS5E8aYzO2DugTdSWQdc5W5BroCJdms=", 166 | "vote": "QHHw03LnZQhKvjjIxVj3+qwgohOij2j3TBDMy7V9JMk=", 167 | "voteKD": 10000, 168 | "voteLst": 3000000 169 | } 170 | }, 171 | { 172 | "addr": "QFYWTHPNZBKKZ4XG2OWVNEX6ETBISD2VJZTCMODIZKT3QHQ4TIRJVEDVV4", 173 | "comment": "", 174 | "state": { 175 | "algo": 50000000000000, 176 | "onl": 1, 177 | "sel": "NthIIUyiiRVnU/W13ajFFV4EhTvT5EZR/9N6ZRD/Z7U=", 178 | "vote": "3KtiTLYvHJqa+qkGFj2RcZC77bz9yUYKxBZt8B24Z+c=", 179 | "voteKD": 10000, 180 | "voteLst": 3000000 181 | } 182 | }, 183 | { 184 | "addr": "DPOZQ6HRYLNNWVQL3I4XV4LMK5UZVROKGJBRIYIRNZUBMVHCU4DZWDBHYE", 185 | "comment": "", 186 | "state": { 187 | "algo": 50000000000000, 188 | "onl": 1, 189 | "sel": "PBZ/agWgmwMdmWgt/W0NvdTN/XSTrVhPvRSMjmP5j90=", 190 | "vote": "FDONnMcq1acmIBjJr3vz4kx4Q8ZRZ8oIH8xXRV5c4L8=", 191 | "voteKD": 10000, 192 | "voteLst": 3000000 193 | } 194 | }, 195 | { 196 | "addr": "42GALMKS3HMDB24ZPOR237WQ5QDHL5NIRC3KIA4PCKENJZAD5RP5QPBFO4", 197 | "comment": "", 198 | "state": { 199 | "algo": 50000000000000, 200 | "onl": 1, 201 | "sel": "p7axjoy3Wn/clD7IKoTK2Zahc5ZU+Qkt2POVHKugQU4=", 202 | "vote": "PItHHw+b01XplxRBFmZniqmdm+RyJFYd0fDz+OP4D6o=", 203 | "voteKD": 10000, 204 | "voteLst": 3000000 205 | } 206 | }, 207 | { 208 | "addr": "OXWIMTRZA5TVPABJF534EBBERJG367OLAB6VFN4RAW5P6CQEMXEX7VVDV4", 209 | "comment": "", 210 | "state": { 211 | "algo": 50000000000000, 212 | "onl": 1, 213 | "sel": "RSOWYRM6/LD7MYxlZGvvF+WFGmBZg7UUutdkaWql0Xo=", 214 | "vote": "sYSYFRL7AMJ61egushOYD5ABh9p06C4ZRV/OUSx7o3g=", 215 | "voteKD": 10000, 216 | "voteLst": 3000000 217 | } 218 | }, 219 | { 220 | "addr": "AICDUO6E46YBJRLM4DFJPVRVZGOFTRNPF7UPQXWEPPYRPVGIMQMLY5HLFM", 221 | "comment": "", 222 | "state": { 223 | "algo": 50000000000000, 224 | "onl": 1, 225 | "sel": "0vxjPZqEreAhUt9PHJU2Eerb7gBhMU+PgyEXYLmbifg=", 226 | "vote": "fuc0z/tpiZXBWARCJa4jPdmDvSmun4ShQLFiAxQkOFI=", 227 | "voteKD": 10000, 228 | "voteLst": 3000000 229 | } 230 | }, 231 | { 232 | "addr": "DYATVHCICZA7VVOWZN6OLFFSKUAZ64TZ7WZWCJQBFWL3JL4VBBV6R7Z6IE", 233 | "comment": "", 234 | "state": { 235 | "algo": 50000000000000, 236 | "onl": 1, 237 | "sel": "KO2035CRpp1XmVPOTOF6ICWCw/0I6FgelKxdwPq+gMY=", 238 | "vote": "rlcoayAuud0suR3bvvI0+psi/NzxvAJUFlp+I4ntzkM=", 239 | "voteKD": 10000, 240 | "voteLst": 3000000 241 | } 242 | }, 243 | { 244 | "addr": "6XJH2PJMAXWS4RGE6NBYIS3OZFOPU3LOHYC6MADBFUAALSWNFHMPJUWVSE", 245 | "comment": "", 246 | "state": { 247 | "algo": 50000000000000, 248 | "onl": 1, 249 | "sel": "PgW1dncjs9chAVM89SB0FD4lIrygxrf+uqsAeZw8Qts=", 250 | "vote": "pA4NJqjTAtHGGvZWET9kliq24Go5kEW8w7f1BGAWmKY=", 251 | "voteKD": 10000, 252 | "voteLst": 3000000 253 | } 254 | }, 255 | { 256 | "addr": "EYOZMULFFZZ5QDDMWQ64HKIMUPPNEL3WJMNGAFD43L52ZXTPESBEVJPEZU", 257 | "comment": "", 258 | "state": { 259 | "algo": 50000000000000, 260 | "onl": 1, 261 | "sel": "sfebD2noAbrn1vblMmeCIeGB3BxLGKQDTG4sKSNibFs=", 262 | "vote": "Cuz3REj26J+JhOpf91u6PO6MV5ov5b1K/ii1U1uPD/g=", 263 | "voteKD": 10000, 264 | "voteLst": 3000000 265 | } 266 | }, 267 | { 268 | "addr": "I3345FUQQ2GRBHFZQPLYQQX5HJMMRZMABCHRLWV6RCJYC6OO4MOLEUBEGU", 269 | "comment": "", 270 | "state": { 271 | "algo": 24000000000000, 272 | "onl": 1, 273 | "sel": "MkH9KsdwiFgYtFFWFu48CeejEop1vsyGFG4/kqPIOFg=", 274 | "vote": "RcntidhQqXQIvYjLFtc6HuL335rMnNX92roa2LcC+qQ=", 275 | "voteKD": 10000, 276 | "voteLst": 3000000 277 | } 278 | }, 279 | { 280 | "addr": "6LQH42A4QJ3Y27FGKJWERY3MD65SXM4QQCJJR2HRJYNB427IQ73YBI3YFY", 281 | "comment": "", 282 | "state": { 283 | "algo": 24000000000000, 284 | "onl": 1, 285 | "sel": "nF3mu9Bu0Ad5MIrT31NgTxxrsZOXc4u1+WCvaPQTYEQ=", 286 | "vote": "NaqWR/7FzOq/MiHb3adO6+J+kvnQKat8NSqEmoEkVfE=", 287 | "voteKD": 10000, 288 | "voteLst": 3000000 289 | } 290 | }, 291 | { 292 | "addr": "3V2MC7WJGAFU2EHWBHEETIMJVFJNAT4KKWVPOMJFJIM6ZPWEJRJ4POTXGI", 293 | "comment": "", 294 | "state": { 295 | "algo": 24000000000000, 296 | "onl": 1, 297 | "sel": "3i4K8zdmnf1kxwgcNmI3x50iIwAxDmLMvoQEhjzhado=", 298 | "vote": "wfJWa0kby76rqX2yvCD/aCfJdNt+qItylDPQiuAWFkQ=", 299 | "voteKD": 10000, 300 | "voteLst": 3000000 301 | } 302 | }, 303 | { 304 | "addr": "FTXSKED23VEXNW442T2JKNPPNUC2WKFNRWBVQTFMT7HYX365IVLZXYILAI", 305 | "comment": "", 306 | "state": { 307 | "algo": 24000000000000, 308 | "onl": 1, 309 | "sel": "icuL7ehcGonAcJ02Zy4MIHqcT+Sp1R1UURNCYJQHmo4=", 310 | "vote": "tmFcj3v7X5DDxKI1IDbGdhXh3a5f0Ab1ftltM7TgIDE=", 311 | "voteKD": 10000, 312 | "voteLst": 3000000 313 | } 314 | }, 315 | { 316 | "addr": "IAOW7PXLCDGLKMIQF26IXFF4THSQMU662MUU6W5KPOXHIVKHYFLYRWOUT4", 317 | "comment": "", 318 | "state": { 319 | "algo": 24000000000000, 320 | "onl": 1, 321 | "sel": "zTn9rl/8Y2gokMdFyFP/pKg4eP02arkxlrBZIS94vPI=", 322 | "vote": "a0pX68GgY7u8bd2Z3311+Mtc6yDnESZmi9k8zJ0oHzY=", 323 | "voteKD": 10000, 324 | "voteLst": 3000000 325 | } 326 | }, 327 | { 328 | "addr": "4NRNE5RIGC2UGOMGMDR6L5YMQUV3Q76TPOR7TDU3WEMJLMC6BSBEKPJ2SY", 329 | "comment": "", 330 | "state": { 331 | "algo": 24000000000000, 332 | "onl": 1, 333 | "sel": "orSV2VHPY8m5ckEHGwK0r+SM9jq4BujAICXegAUAecI=", 334 | "vote": "NJ9tisH+7+S29m/uMymFTD8X02/PKU0JUX1ghnLCzkw=", 335 | "voteKD": 10000, 336 | "voteLst": 3000000 337 | } 338 | }, 339 | { 340 | "addr": "E2EIMPLDISONNZLXONGMC33VBYOIBC2R7LVOS4SYIEZYJQK6PYSAPQL7LQ", 341 | "comment": "", 342 | "state": { 343 | "algo": 24000000000000, 344 | "onl": 1, 345 | "sel": "XM2iW9wg9G5TyOfVu9kTS80LDIqcEPkJsgxaZll3SWA=", 346 | "vote": "p/opFfDOsIomj5j7pAYU+G/CNUIwvD2XdEer6dhGquQ=", 347 | "voteKD": 10000, 348 | "voteLst": 3000000 349 | } 350 | }, 351 | { 352 | "addr": "APDO5T76FB57LNURPHTLAGLQOHUQZXYHH2ZKR4DPQRKK76FB4IAOBVBXHQ", 353 | "comment": "", 354 | "state": { 355 | "algo": 24000000000000, 356 | "onl": 1, 357 | "sel": "5k2vclbUQBE6zBl45F3kGSv1PYhE2k9wZjxyxoPlnwA=", 358 | "vote": "3dcLRSckm3wd9KB0FBRxub3meIgT6lMZnv5F08GJgEo=", 359 | "voteKD": 10000, 360 | "voteLst": 3000000 361 | } 362 | }, 363 | { 364 | "addr": "3KJTYHNHK37G2JDZJPV55IHBADU22TX2FPJZJH43MY64IFWKVNMP2F4JZE", 365 | "comment": "", 366 | "state": { 367 | "algo": 24000000000000, 368 | "onl": 1, 369 | "sel": "o5e9VLqMdmJas5wRovfYFHgQ+Z6sQoATf3a6j0HeIXU=", 370 | "vote": "rG7J8pPAW+Xtu5pqMIJOG9Hxdlyewtf9zPHEKR2Q6OE=", 371 | "voteKD": 10000, 372 | "voteLst": 3000000 373 | } 374 | }, 375 | { 376 | "addr": "IVKDCE6MS44YVGMQQFVXCDABW2HKULKIXMLDS2AEOIA6P2OGMVHVJ64MZI", 377 | "comment": "", 378 | "state": { 379 | "algo": 24000000000000, 380 | "onl": 1, 381 | "sel": "XgUrwumD7oin/rG3NKwywBSsTETg/aWg9MjCDG61Ybg=", 382 | "vote": "sBPEGGrEqcQMdT+iq2ududNxCa/1HcluvsosO1SkE/k=", 383 | "voteKD": 10000, 384 | "voteLst": 3000000 385 | } 386 | }, 387 | { 388 | "addr": "2WDM5XFF7ONWFANPE5PBMPJLVWOEN2BBRLSKJ37PQYW5WWIHEFT3FV6N5Y", 389 | "comment": "", 390 | "state": { 391 | "algo": 24000000000000, 392 | "onl": 1, 393 | "sel": "Lze5dARJdb1+Gg6ui8ySIi+LAOM3P9dKiHKB9HpMM6A=", 394 | "vote": "ys4FsqUNQiv+N0RFtr0Hh9OnzVcxXS6cRVD/XrLgW84=", 395 | "voteKD": 10000, 396 | "voteLst": 3000000 397 | } 398 | }, 399 | { 400 | "addr": "EOZWAIPQEI23ATBWQ5J57FUMRMXADS764XLMBTSOLVKPMK5MK5DBIS3PCY", 401 | "comment": "", 402 | "state": { 403 | "algo": 24000000000000, 404 | "onl": 1, 405 | "sel": "jtmLcJhaAknJtA1cS5JPZil4SQ5SKh8P0w1fUw3X0CE=", 406 | "vote": "pyEtTxJAas/j+zi/N13b/3LB4UoCar1gfcTESl0SI2I=", 407 | "voteKD": 10000, 408 | "voteLst": 3000000 409 | } 410 | }, 411 | { 412 | "addr": "REMF542E5ZFKS7SGSNHTYB255AUITEKHLAATWVPK3CY7TAFPT6GNNCHH6M", 413 | "comment": "", 414 | "state": { 415 | "algo": 24000000000000, 416 | "onl": 1, 417 | "sel": "8ggWPvRpSkyrjxoh1SVS9PiSjff2azWtH0HFadwI9Ck=", 418 | "vote": "Ej/dSkWbzRf09RAuWZfC4luRPNuqkLFCSGYXDcOtwic=", 419 | "voteKD": 10000, 420 | "voteLst": 3000000 421 | } 422 | }, 423 | { 424 | "addr": "T4UBSEAKK7JHT7RNLXVHDRW72KKFJITITR54J464CAGE5FGAZFI3SQH3TI", 425 | "comment": "", 426 | "state": { 427 | "algo": 24000000000000, 428 | "onl": 1, 429 | "sel": "eIB8MKaG2lyJyM9spk+b/Ap/bkbo9bHfvF9f8T51OQk=", 430 | "vote": "7xuBsE5mJaaRAdm5wnINVwm4SgPqKwJTAS1QBQV3sEc=", 431 | "voteKD": 10000, 432 | "voteLst": 3000000 433 | } 434 | }, 435 | { 436 | "addr": "YUDNQMOHAXC4B3BAMRMMQNFDFZ7GYO2HUTBIMNIP7YQ4BL57HZ5VM3AFYU", 437 | "comment": "", 438 | "state": { 439 | "algo": 24000000000000, 440 | "onl": 1, 441 | "sel": "CSTCDvvtsJB0VYUcl3oRXyiJfhm3CtqvRIuFYZ69Z68=", 442 | "vote": "uBK1TH4xKdWfv5nnnHkvYssI0tyhWRFZRLHgVt9TE1k=", 443 | "voteKD": 10000, 444 | "voteLst": 3000000 445 | } 446 | }, 447 | { 448 | "addr": "4SZTEUQIURTRT37FCI3TRMHSYT5IKLUPXUI7GWC5DZFXN2DGTATFJY5ABY", 449 | "comment": "", 450 | "state": { 451 | "algo": 24000000000000, 452 | "onl": 1, 453 | "sel": "THGOlrqElX13xMqeLUPy6kooTbXjiyrUoZfVccnHrfI=", 454 | "vote": "k4hde2Q3Zl++sQobo01U8heZd/X0GIX1nyqM8aI/hCY=", 455 | "voteKD": 10000, 456 | "voteLst": 3000000 457 | } 458 | }, 459 | { 460 | "addr": "UEDD34QFEMWRGYCBLKZIEHPKSTNBFSRMFBHRJPY3O2JPGKHQCXH4IY6XRI", 461 | "comment": "", 462 | "state": { 463 | "algo": 24000000000000, 464 | "onl": 1, 465 | "sel": "jE+AUFvtp2NJsfNeUZeXdWt0X6I58YOgY+z/HB17GDs=", 466 | "vote": "lmnYTjg1FhRNAR9TwVmOahVr5Z+7H1GO6McmvOZZRTQ=", 467 | "voteKD": 10000, 468 | "voteLst": 3000000 469 | } 470 | }, 471 | { 472 | "addr": "HHZQOGQKMQDLBEL3HXMDX7AGTNORYVZ4JFDWVSL5QLWMD3EXOIAHDI5L7M", 473 | "comment": "", 474 | "state": { 475 | "algo": 24000000000000, 476 | "onl": 1, 477 | "sel": "Hajdvzem2rR2GjLmCG+98clHZFY5Etlp0n+x/gQTGj0=", 478 | "vote": "2+Ie4MDWC6o/SfFSqev1A7UAkzvKRESI42b4NKS6Iw8=", 479 | "voteKD": 10000, 480 | "voteLst": 3000000 481 | } 482 | }, 483 | { 484 | "addr": "XRTBXPKH3DXDJ5OLQSYXOGX3DJ3U5NR6Y3LIVIWMK7TY33YW4I2NJZOTVE", 485 | "comment": "", 486 | "state": { 487 | "algo": 24000000000000, 488 | "onl": 1, 489 | "sel": "5qe7rVoQfGdIUuDbhP2ABWivCoCstKbUsjdmYY76akA=", 490 | "vote": "3J3O9DyJMWKvACubUK9QvmCiArtZR7yFHWG7k7+apdQ=", 491 | "voteKD": 10000, 492 | "voteLst": 3000000 493 | } 494 | }, 495 | { 496 | "addr": "JJFGCPCZPYRLOUYBZVC4F7GRPZ5CLB6BMTVRGNDP7GRGXL6GG4JEN7DL54", 497 | "comment": "", 498 | "state": { 499 | "algo": 24000000000000, 500 | "onl": 1, 501 | "sel": "YoRFAcTiOgJcLudNScYstbaKJ8anrrHwQMZAffWMqYE=", 502 | "vote": "VQFKlDdxRqqqPUQ/mVoF8xZS9BGxUtTnPUjYyKnOVRA=", 503 | "voteKD": 10000, 504 | "voteLst": 3000000 505 | } 506 | }, 507 | { 508 | "addr": "4VNSA2GZVUD5ZNO62OVVNP4NEL2LIEE5N3MZEK4BKH62KGKRLVINFZYTZM", 509 | "comment": "", 510 | "state": { 511 | "algo": 100000000000000, 512 | "onl": 2 513 | } 514 | }, 515 | { 516 | "addr": "IVCEEIH2Q32DZNRTS5XFVEFFAQGERNZHHQT6S4UPY7ORJMHIQDSTX7YM4E", 517 | "comment": "", 518 | "state": { 519 | "algo": 408400000000000, 520 | "onl": 2 521 | } 522 | }, 523 | { 524 | "addr": "PLFHBIRGM3ZWGAMCXTREX2N537TWOMFIQXHFO2ZGQOEPZU473SYBVGVA5M", 525 | "comment": "", 526 | "state": { 527 | "algo": 1011600000000000, 528 | "onl": 2 529 | } 530 | }, 531 | { 532 | "addr": "KF7X4ZABZUQU7IFMHSKLDKWCS4F3GZLOLJRDAK5KMEMDAGU32CX36CJQ5M", 533 | "comment": "", 534 | "state": { 535 | "algo": 10000000000000, 536 | "onl": 2 537 | } 538 | }, 539 | { 540 | "addr": "BTEESEYQMFLWZKULSKLNDELYJTOOQK6ZT4FBCW3TOZQ55NZYLOO6BRQ5K4", 541 | "comment": "", 542 | "state": { 543 | "algo": 36199095000000, 544 | "onl": 2 545 | } 546 | }, 547 | { 548 | "addr": "E36JOZVSZZDXKSERASLAWQE4NU67HC7Q6YDOCG7P7IRRWCPSWXOI245DPA", 549 | "comment": "", 550 | "state": { 551 | "algo": 20000000000000, 552 | "onl": 2 553 | } 554 | }, 555 | { 556 | "addr": "I5Q6RRN44OZWYMX6YLWHBGEVPL7S3GBUCMHZCOOLJ245TONH7PERHJXE4A", 557 | "comment": "", 558 | "state": { 559 | "algo": 20000000000000, 560 | "onl": 2 561 | } 562 | }, 563 | { 564 | "addr": "2GYS272T3W2AP4N2VX5BFBASVNLWN44CNVZVKLWMMVPZPHVJ52SJPPFQ2I", 565 | "comment": "", 566 | "state": { 567 | "algo": 40000000000000, 568 | "onl": 2 569 | } 570 | }, 571 | { 572 | "addr": "D5LSV2UGT4JJNSLJ5XNIF52WP4IHRZN46ZGWH6F4QEF4L2FLDYS6I6R35Y", 573 | "comment": "", 574 | "state": { 575 | "algo": 20000000000000, 576 | "onl": 2 577 | } 578 | }, 579 | { 580 | "addr": "UWMSBIP2CGCGR3GYVUIOW3YOMWEN5A2WRTTBH6Y23KE3MOVFRHNXBP6IOE", 581 | "comment": "", 582 | "state": { 583 | "algo": 20000000000000, 584 | "onl": 2 585 | } 586 | }, 587 | { 588 | "addr": "OF3MKZZ3L5ZN7AZ46K7AXJUI4UWJI3WBRRVNTDKYVZUHZAOBXPVR3DHINE", 589 | "comment": "", 590 | "state": { 591 | "algo": 40000000000000, 592 | "onl": 2 593 | } 594 | }, 595 | { 596 | "addr": "2PPWE36YUMWUVIFTV2A6U4MLZLGROW4GHYIRVHMUCHDH6HCNVPUKPQ53NY", 597 | "comment": "", 598 | "state": { 599 | "algo": 440343426000000, 600 | "onl": 2 601 | } 602 | }, 603 | { 604 | "addr": "JRGRGRW4HYBNAAHR7KQLLBAGRSPOYY6TRSINKYB3LI5S4AN247TANH5IQY", 605 | "comment": "", 606 | "state": { 607 | "algo": 362684706000000, 608 | "onl": 2 609 | } 610 | }, 611 | { 612 | "addr": "D7YVVQJXJEFOZYUHJLIJBW3ATCAW46ML62VYRJ3SMGLOHMWYH4OS3KNHTU", 613 | "comment": "", 614 | "state": { 615 | "algo": 10000000000000, 616 | "onl": 2 617 | } 618 | }, 619 | { 620 | "addr": "PZJKH2ILW2YDZNUIYQVJZ2MANRSMK6LCHAFSAPYT6R3L3ZCWKYRDZXRVY4", 621 | "comment": "", 622 | "state": { 623 | "algo": 10000000000000, 624 | "onl": 2 625 | } 626 | }, 627 | { 628 | "addr": "3MODEFJVPGUZH3HDIQ6L2MO3WLJV3FK3XSWKFBHUGZDCHXQMUKD4B7XLMI", 629 | "comment": "", 630 | "state": { 631 | "algo": 130000000000000, 632 | "onl": 2 633 | } 634 | }, 635 | { 636 | "addr": "WNSA5P6C5IIH2UJPQWJX6FRNPHXY7XZZHOWLSW5ZWHOEHBUW4AD2H6TZGM", 637 | "comment": "", 638 | "state": { 639 | "algo": 130000000000000, 640 | "onl": 2 641 | } 642 | }, 643 | { 644 | "addr": "OO65J5AIFDS6255WL3AESTUGJD5SUV47RTUDOUGYHEIME327GX7K2BGC6U", 645 | "comment": "", 646 | "state": { 647 | "algo": 40000000000000, 648 | "onl": 2 649 | } 650 | }, 651 | { 652 | "addr": "DM6A24ZWHRZRM2HWXUHAUDSAACO7VKEZAOC2THWDXH4DX5L7LSO3VF2OPU", 653 | "comment": "", 654 | "state": { 655 | "algo": 20000000000000, 656 | "onl": 2 657 | } 658 | }, 659 | { 660 | "addr": "NTJJSFM75RADUOUGOBHZB7IJGO7NLVBWA66EYOOPU67H7LYIXVSPSI7BTA", 661 | "comment": "", 662 | "state": { 663 | "algo": 18099548000000, 664 | "onl": 2 665 | } 666 | }, 667 | { 668 | "addr": "DAV2AWBBW4HBGIL2Z6AAAWDWRJPTOQD6BSKU2CFXZQCOBFEVFEJ632I2LY", 669 | "comment": "", 670 | "state": { 671 | "algo": 1000000000000, 672 | "onl": 2 673 | } 674 | }, 675 | { 676 | "addr": "M5VIY6QPSMALVVPVG5LVH35NBMH6XJMXNWKWTARGGTEEQNQ3BHPQGYP5XU", 677 | "comment": "", 678 | "state": { 679 | "algo": 20000000000000, 680 | "onl": 2 681 | } 682 | }, 683 | { 684 | "addr": "WZZLVKMCXJG3ICVZSVOVAGCCN755VHJKZWVSVQ6JPSRQ2H2OSPOOZKW6DQ", 685 | "comment": "", 686 | "state": { 687 | "algo": 45248869000000, 688 | "onl": 2 689 | } 690 | }, 691 | { 692 | "addr": "XEJLJUZRQOLBHHSOJJUE4IWI3EZOM44P646UDKHS4AV2JW7ZWBWNFGY6BU", 693 | "comment": "", 694 | "state": { 695 | "algo": 20000000000000, 696 | "onl": 2 697 | } 698 | }, 699 | { 700 | "addr": "OGIPDCRJJPNVZ6X6NBQHMTEVKJVF74QHZIXVLABMGUKZWNMEH7MNXZIJ7Q", 701 | "comment": "", 702 | "state": { 703 | "algo": 40000000000000, 704 | "onl": 2 705 | } 706 | }, 707 | { 708 | "addr": "G47R73USFN6FJJQTI3JMYQXO7F6H4LRPBCTTAD5EZWPWY2WCG64AVPCYG4", 709 | "comment": "", 710 | "state": { 711 | "algo": 10000000000000, 712 | "onl": 2 713 | } 714 | }, 715 | { 716 | "addr": "PQ5T65QB564NMIY6HXNYZXTFRSTESUEFIF2C26ZZKIZE6Q4R4XFP5UYYWI", 717 | "comment": "", 718 | "state": { 719 | "algo": 5000000000000, 720 | "onl": 2 721 | } 722 | }, 723 | { 724 | "addr": "R6S7TRMZCHNQPKP2PGEEJ6WYUKMTURNMM527ZQXABTHFT5GBVMF6AZAL54", 725 | "comment": "", 726 | "state": { 727 | "algo": 1000000000000, 728 | "onl": 2 729 | } 730 | }, 731 | { 732 | "addr": "36LZKCBDUR5EHJ74Q6UWWNADLVJOHGCPBBQ5UTUM3ILRTQLA6RYYU4PUWQ", 733 | "comment": "", 734 | "state": { 735 | "algo": 5000000000000, 736 | "onl": 2 737 | } 738 | }, 739 | { 740 | "addr": "JRHPFMSJLU42V75NTGFRQIALCK6RHTEK26QKLWCH2AEEAFNAVEXWDTA5AM", 741 | "comment": "", 742 | "state": { 743 | "algo": 40000000000000, 744 | "onl": 2 745 | } 746 | }, 747 | { 748 | "addr": "64VZVS2LFZXWA5W3S657W36LWGP34B7XLMDIF4ROXBTPADD7SR5WNUUYJE", 749 | "comment": "", 750 | "state": { 751 | "algo": 171945701000000, 752 | "onl": 2 753 | } 754 | }, 755 | { 756 | "addr": "TXDBSEZPFP2UB6BDNFCHCZBTPONIIQVZGABM4UBRHVAAPR5NE24QBL6H2A", 757 | "comment": "", 758 | "state": { 759 | "algo": 60000000000000, 760 | "onl": 2 761 | } 762 | }, 763 | { 764 | "addr": "XI5TYT4XPWUHE4AMDDZCCU6M4AP4CAI4VTCMXXUNS46I36O7IYBQ7SL3D4", 765 | "comment": "", 766 | "state": { 767 | "algo": 40000000000000, 768 | "onl": 2 769 | } 770 | }, 771 | { 772 | "addr": "Y6ZPKPXF2QHF6ULYQXVHM7NPI3L76SP6QHJHK7XTNPHNXDEUTJPRKUZBNE", 773 | "comment": "", 774 | "state": { 775 | "algo": 40000000000000, 776 | "onl": 2 777 | } 778 | }, 779 | { 780 | "addr": "6LY2PGUJLCK4Q75JU4IX5VWVJVU22VGJBWPZOFP3752UEBIUBQRNGJWIEA", 781 | "comment": "", 782 | "state": { 783 | "algo": 40000000000000, 784 | "onl": 2 785 | } 786 | }, 787 | { 788 | "addr": "L7AGFNAFJ6Z2FYCX3LXE4ZSERM2VOJF4KPF7OUCMGK6GWFXXDNHZJBEC2E", 789 | "comment": "", 790 | "state": { 791 | "algo": 10000000000000, 792 | "onl": 2 793 | } 794 | }, 795 | { 796 | "addr": "RYXX5U2HMWGTPBG2UDLDT6OXDDRCK2YGL7LFAKYNBLRGZGYEJLRMGYLSVU", 797 | "comment": "", 798 | "state": { 799 | "algo": 40000000000000, 800 | "onl": 2 801 | } 802 | }, 803 | { 804 | "addr": "S263NYHFQWZYLINTBELLMIRMAJX6J5CUMHTECTGGVZUKUN2XY6ND2QBZVY", 805 | "comment": "", 806 | "state": { 807 | "algo": 21647524000000, 808 | "onl": 2 809 | } 810 | }, 811 | { 812 | "addr": "AERTZIYYGK3Q364M6DXPKSRRNSQITWYEDGAHXC6QXFCF4GPSCCSISAGCBY", 813 | "comment": "", 814 | "state": { 815 | "algo": 19306244000000, 816 | "onl": 2 817 | } 818 | }, 819 | { 820 | "addr": "34UYPXOJA6WRTWRNH5722LFDLWT23OM2ZZTCFQ62EHQI6MM3AJIAKOWDVQ", 821 | "comment": "", 822 | "state": { 823 | "algo": 10000000000000, 824 | "onl": 2 825 | } 826 | }, 827 | { 828 | "addr": "EDVGNQL6APUFTIGFZHASIEWGJRZNWGIKJE64B72V36IQM2SJPOAG2MJNQE", 829 | "comment": "", 830 | "state": { 831 | "algo": 20000000000000, 832 | "onl": 2 833 | } 834 | }, 835 | { 836 | "addr": "RKKLUIIGR75DFWGQOMJB5ZESPT7URDPC7QHGYKM4MAJ4OEL2J5WAQF6Z2Q", 837 | "comment": "", 838 | "state": { 839 | "algo": 40000000000000, 840 | "onl": 2 841 | } 842 | }, 843 | { 844 | "addr": "M4TNVJLDZZFAOH2M24BE7IU72KUX3P6M2D4JN4WZXW7WXH3C5QSHULJOU4", 845 | "comment": "", 846 | "state": { 847 | "algo": 10000000000000, 848 | "onl": 2 849 | } 850 | }, 851 | { 852 | "addr": "WQL6MQS5SPK3CR3XUPYMGOUSCUC5PNW5YQPLGEXGKVRK3KFKSAZ6JK4HXQ", 853 | "comment": "", 854 | "state": { 855 | "algo": 10000000000000, 856 | "onl": 2 857 | } 858 | }, 859 | { 860 | "addr": "36JTK4PKUBJGVCWKXZTAG6VLJRXWZXQVPQQSYODSN6WEGVHOWSVK6O54YU", 861 | "comment": "", 862 | "state": { 863 | "algo": 10000000000000, 864 | "onl": 2 865 | } 866 | }, 867 | { 868 | "addr": "YFOAYI4SNXJR2DBEZ3O6FJOFSEQHWD7TYROCNDWF6VLBGLNJMRRHDXXZUI", 869 | "comment": "", 870 | "state": { 871 | "algo": 30000000000000, 872 | "onl": 2 873 | } 874 | }, 875 | { 876 | "addr": "XASOPHD3KK3NNI5IF2I7S7U55RGF22SG6OEICVRMCTMMGHT3IBOJG7QWBU", 877 | "comment": "", 878 | "state": { 879 | "algo": 40000000000000, 880 | "onl": 2 881 | } 882 | }, 883 | { 884 | "addr": "H2AUGBLVQFHHFLFEPJ6GGJ7PBQITEN2GE6T7JZCALBKNU7Q52AVJM5HOYU", 885 | "comment": "", 886 | "state": { 887 | "algo": 10000000000000, 888 | "onl": 2 889 | } 890 | }, 891 | { 892 | "addr": "GX3XLHSRMFTADVKJBBQBTZ6BKINW6ZO5JHXWGCWB4CPDNPDQ2PIYN4AVHQ", 893 | "comment": "", 894 | "state": { 895 | "algo": 40000000000000, 896 | "onl": 2 897 | } 898 | }, 899 | { 900 | "addr": "VBJBJ4VC3IHUTLVLWMBON36Y5MPAMPV4DNGW5FQ47GRLPT7JR5PQOUST2E", 901 | "comment": "", 902 | "state": { 903 | "algo": 4524887000000, 904 | "onl": 2 905 | } 906 | }, 907 | { 908 | "addr": "7AQVTOMB5DJRSUM4LPLVF6PY3Y5EBDF4RZNDIWNW4Z63JYTAQCPQ62IZFE", 909 | "comment": "", 910 | "state": { 911 | "algo": 50000000000000, 912 | "onl": 2 913 | } 914 | }, 915 | { 916 | "addr": "B4ZIHKD4VYLA4BAFEP7KUHZD7PNWXW4QLCHCNKWRENJ2LYVEOIYA3ZX6IA", 917 | "comment": "", 918 | "state": { 919 | "algo": 40000000000000, 920 | "onl": 2 921 | } 922 | }, 923 | { 924 | "addr": "G5RGT3EENES7UVIQUHXMJ5APMOGSW6W6RBC534JC6U2TZA4JWC7U27RADE", 925 | "comment": "", 926 | "state": { 927 | "algo": 10000000000000, 928 | "onl": 2 929 | } 930 | }, 931 | { 932 | "addr": "5AHJFDLAXVINK34IGSI3JA5OVRVMPCWLFEZ6TA4I7XUZ7I6M34Q56DUYIM", 933 | "comment": "", 934 | "state": { 935 | "algo": 20000000000000, 936 | "onl": 2 937 | } 938 | } 939 | ], 940 | "fees": "Y76M3MSY6DKBRHBL7C3NNDXGS5IIMQVQVUAB6MP4XEMMGVF2QWNPL226CA", 941 | "id": "v1.0", 942 | "network": "mainnet", 943 | "proto": "https://github.com/algorandfoundation/specs/tree/5615adc36bad610c7f165fa2967f4ecfa75125f0", 944 | "rwd": "737777777777777777777777777777777777777777777777777UFEJ2CI", 945 | "timestamp": 1560211200 946 | } -------------------------------------------------------------------------------- /genesis/testnet/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "alloc": [ 3 | { 4 | "addr": "7777777777777777777777777777777777777777777777777774MSJUVU", 5 | "comment": "RewardsPool", 6 | "state": { 7 | "algo": 125000000000000, 8 | "onl": 2 9 | } 10 | }, 11 | { 12 | "addr": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 13 | "comment": "FeeSink", 14 | "state": { 15 | "algo": 100000, 16 | "onl": 2 17 | } 18 | }, 19 | { 20 | "addr": "LHHQJ6UMXRGEPXBVFKT7SY26BQOIK64VVPCLVRL3RNQLX5ZMBYG6ZHZMBE", 21 | "comment": "Wallet1", 22 | "state": { 23 | "algo": 320000000000000, 24 | "onl": 1, 25 | "sel": "h7Ml/mY/PDCPSj33u72quxaMX99n+/VE+wD94/hMdzY=", 26 | "vote": "R9kxsHbji4DlxPOAyLehy8vaiWyLjWdLGWBLnQ5jjY8=", 27 | "voteKD": 10000, 28 | "voteLst": 3000000 29 | } 30 | }, 31 | { 32 | "addr": "CQW2QBBUW5AGFDXMURQBRJN2AM3OHHQWXXI4PEJXRCVTEJ3E5VBTNRTEAE", 33 | "comment": "Wallet10", 34 | "state": { 35 | "algo": 320000000000000, 36 | "onl": 1, 37 | "sel": "p2tiuQ2kqJGG049hHOKNIjid4/u1MqlvgXfbxK4tuEY=", 38 | "vote": "E73cc+KB/LGdDHO1o84440WKCmqvbM4EgROMRyHfjDc=", 39 | "voteKD": 10000, 40 | "voteLst": 3000000 41 | } 42 | }, 43 | { 44 | "addr": "HXPCXKQZF4LDL3CE5ERWC5V2BQZTKXUUT3JE6AXXNKLF3OJL4XUAW5WYXM", 45 | "comment": "Wallet11", 46 | "state": { 47 | "algo": 320000000000000, 48 | "onl": 1, 49 | "sel": "ex32mzy8E94GkHGy+cmkRP5JNqFBKGfHtgyUGNxTiW8=", 50 | "vote": "BtYvtmeEBY2JovHUfePTjo3OtOMrhKp3QMeOYl3JFYM=", 51 | "voteKD": 10000, 52 | "voteLst": 3000000 53 | } 54 | }, 55 | { 56 | "addr": "Y3FSHQ43JWDSJG7LL5FBRTXHEGTPSWEQBO4CO2RO7KS2Z4ZGBUI7LSEDHQ", 57 | "comment": "Wallet12", 58 | "state": { 59 | "algo": 320000000000000, 60 | "onl": 1, 61 | "sel": "+AtsgunCR8dzO9UGUJ6sFtAaX/E+ssK6JNmvAljQG2E=", 62 | "vote": "Rx21vGt6pnixU2g6NS/TknVtAGbf8hWMJiEtNuV5lb4=", 63 | "voteKD": 10000, 64 | "voteLst": 3000000 65 | } 66 | }, 67 | { 68 | "addr": "KXILJUKZJEOS4OCPGENS72JWIZOXGZSK4R235EQPGQ3JLG6R2BBT3ODXEI", 69 | "comment": "Wallet13", 70 | "state": { 71 | "algo": 320000000000000, 72 | "onl": 1, 73 | "sel": "6s09aJVaGfPdbWy5zUSyBJEX/EGVvsn2moUOvakQdBQ=", 74 | "vote": "1oTW6ZpIHhQP6xeNCSqHOZZJYrKiP5D52OHXGzbVz4k=", 75 | "voteKD": 10000, 76 | "voteLst": 3000000 77 | } 78 | }, 79 | { 80 | "addr": "R4DCCBODM4L7C6CKVOV5NYDPEYS2G5L7KC7LUYPLUCKBCOIZMYJPFUDTKE", 81 | "comment": "Wallet14", 82 | "state": { 83 | "algo": 320000000000000, 84 | "onl": 1, 85 | "sel": "XsqeQcLz5nPP316ntIp0X9OfJi5ZSfUNrlRSitWXJRg=", 86 | "vote": "r+e0lAD9FnNqOKoWdYdFko13pm9fk/zCJkxVVCqzjaU=", 87 | "voteKD": 10000, 88 | "voteLst": 3000000 89 | } 90 | }, 91 | { 92 | "addr": "VKM6KSCTDHEM6KGEAMSYCNEGIPFJMHDSEMIRAQLK76CJDIRMMDHKAIRMFQ", 93 | "comment": "Wallet15", 94 | "state": { 95 | "algo": 320000000000000, 96 | "onl": 1, 97 | "sel": "64Xkj7z3rHZT7syihd0OmgNExHfnOLdLojDJZgtB1d8=", 98 | "vote": "um2RrGFmZ5Coned2WSbo/htYMKjW7XFE5h25M2IFsDs=", 99 | "voteKD": 10000, 100 | "voteLst": 3000000 101 | } 102 | }, 103 | { 104 | "addr": "YTOO52XR6UWNM6OUUDOGWVTNJYBWR5NJ3VCJTZUSR42JERFJFAG3NFD47U", 105 | "comment": "Wallet16", 106 | "state": { 107 | "algo": 320000000000000, 108 | "onl": 1, 109 | "sel": "9f9aNsmJxXgMZke5sRYFbfnH5fIFclSosqSl1mK4Vd8=", 110 | "vote": "h8ybeZLDhNG/53oJGAzZ2TFAXDXaslXMzNBOR3Pd+i4=", 111 | "voteKD": 10000, 112 | "voteLst": 3000000 113 | } 114 | }, 115 | { 116 | "addr": "EQ5XMOLC2JY5RNFXM725LRVKSTOHWBOQE344ZC6O2K4NW2S3G4XQIJNKAA", 117 | "comment": "Wallet17", 118 | "state": { 119 | "algo": 320000000000000, 120 | "onl": 1, 121 | "sel": "R2LzBwBOEoMEcN6j2Pq9F1RKgrLrqnTyW/iT/tlIRZg=", 122 | "vote": "FnP52cIaWwqpJ6dE3KuM3WSGaz+TNlb/iM7EO0j7EZQ=", 123 | "voteKD": 10000, 124 | "voteLst": 3000000 125 | } 126 | }, 127 | { 128 | "addr": "3PUAOGK2PIEH6K5JTQ55SCV3E52KSLDPUAWDURMUNST6IIFCH347X5SNAI", 129 | "comment": "Wallet18", 130 | "state": { 131 | "algo": 320000000000000, 132 | "onl": 1, 133 | "sel": "HfTcCIGCoAgUMCHalBv2dSC2L7XCPqPmCmWmxO26Vqo=", 134 | "vote": "knBY5MY9DkIguN41/ZoKvSGAg92/fhw64BLHUw0o1BU=", 135 | "voteKD": 10000, 136 | "voteLst": 3000000 137 | } 138 | }, 139 | { 140 | "addr": "DUQR2JOFHCTNRRI546OZDYLCVBIVRYOSWKNR7A43YKVH437QS3XGJWTQ6I", 141 | "comment": "Wallet19", 142 | "state": { 143 | "algo": 320000000000000, 144 | "onl": 1, 145 | "sel": "DRSm3BAHOXLJLPHwrkKILG/cvHLXuDQYIceHgNPnQds=", 146 | "vote": "9G4AtYrLO26Jc3BsUfNl+0+3IjeHdOOSM+8ASj9x7Tg=", 147 | "voteKD": 10000, 148 | "voteLst": 3000000 149 | } 150 | }, 151 | { 152 | "addr": "NWBZBIROXZQEETCDKX6IZVVBV4EY637KCIX56LE5EHIQERCTSDYGXWG6PU", 153 | "comment": "Wallet2", 154 | "state": { 155 | "algo": 320000000000000, 156 | "onl": 1, 157 | "sel": "0eG0edle+ejWcS4Q8DNlITgqaKqNvOtCxNQs+4AncGo=", 158 | "vote": "V4YUoGYXrgDjCluBBbBx2Kq9kkbCZudsuSwmSlCUnK0=", 159 | "voteKD": 10000, 160 | "voteLst": 3000000 161 | } 162 | }, 163 | { 164 | "addr": "U2573KTKRCC7I47FJUTW6DBEUN2VZQ63ZVYISQMIUEJTWDNOGSUTL67HBE", 165 | "comment": "Wallet20", 166 | "state": { 167 | "algo": 320000000000000, 168 | "onl": 1, 169 | "sel": "cDT+xkHQJ13RgfkAUoNMfGk890z2C1V4HSmkxbm6gRk=", 170 | "vote": "r66g4ULatIt179X+2embK0RgwoLdPEq3R3uTTMfP9Hk=", 171 | "voteKD": 10000, 172 | "voteLst": 3000000 173 | } 174 | }, 175 | { 176 | "addr": "DBGTTXBPXGKL4TBBISC73RMB3NNZIZBSH2EICWZTQRA42QKNA4S2W4SP7U", 177 | "comment": "Wallet3", 178 | "state": { 179 | "algo": 320000000000000, 180 | "onl": 1, 181 | "sel": "DmlAnKrkD8lgUB1ahLsy/FIjbZ0fypaowyDc8GKwWZA=", 182 | "vote": "ROBSmA9EfZitGyubHMTfmw8kSiohADB3n4McvTR8g88=", 183 | "voteKD": 10000, 184 | "voteLst": 3000000 185 | } 186 | }, 187 | { 188 | "addr": "XKZWM4PWPLZZWIANNT4S7LU26SPVIKMCDVQAAYRD4G3QJIOJL2X6RZOKK4", 189 | "comment": "Wallet4", 190 | "state": { 191 | "algo": 320000000000000, 192 | "onl": 1, 193 | "sel": "74a0jcs/Y/uCh24vej1rb6CHu64yvW2nYrM0ZUVEhMo=", 194 | "vote": "rwkur9iwJbzNECWvELxzFeJpbZl7dpiThgPJOHnRykg=", 195 | "voteKD": 10000, 196 | "voteLst": 3000000 197 | } 198 | }, 199 | { 200 | "addr": "LPBKDDUNKPXE7GAICEDXGTNCAJNC6IFJUSD4IK2H2IIB3OAFXLM3RLLIVQ", 201 | "comment": "Wallet5", 202 | "state": { 203 | "algo": 320000000000000, 204 | "onl": 1, 205 | "sel": "V4ldV+IY068YK/h7Wb6aNRIo8pr2bYQg8KDgFd25xVw=", 206 | "vote": "d2KdyajjKvpukuGmM2MxEC9XDEgjjF/Spsevjd877RI=", 207 | "voteKD": 10000, 208 | "voteLst": 3000000 209 | } 210 | }, 211 | { 212 | "addr": "MZZS43WEFY56LV3WXEVLROT3LYFLEBZ536UY3Z3J56S7EI3SYYOJVO6YRM", 213 | "comment": "Wallet6", 214 | "state": { 215 | "algo": 320000000000000, 216 | "onl": 1, 217 | "sel": "BoBmrNpHTxySZ8DIlg5ZlINKwTPd/K75CCdhNzs9alo=", 218 | "vote": "N6v+PVEUn9fLZb+9sQDu5lpCpsXLHY0skx/8bWDqk7Q=", 219 | "voteKD": 10000, 220 | "voteLst": 3000000 221 | } 222 | }, 223 | { 224 | "addr": "RP7BOFGBCPNHWPRJEGPNNQRNC3WXJUUAVSBTHMGUXLF36IEHSBGJOHOYZ4", 225 | "comment": "Wallet7", 226 | "state": { 227 | "algo": 320000000000000, 228 | "onl": 1, 229 | "sel": "n0LW+MxrO2S8/AmPClPaGdTDC5PM/MENdEwrm21KmgU=", 230 | "vote": "/e1z3LMbc8C4m9DZ6NCILpv7bZ/yVdmZUp/M32OSUN4=", 231 | "voteKD": 10000, 232 | "voteLst": 3000000 233 | } 234 | }, 235 | { 236 | "addr": "RDHKWTWXOE5AOWUWTROSR4WFLAHMUCRDZIA7OFBXXMMRBXGQ4BYQRPOXXU", 237 | "comment": "Wallet8", 238 | "state": { 239 | "algo": 320000000000000, 240 | "onl": 1, 241 | "sel": "AGJ4v2nOA62A8rGm4H56VEo/6QdhVVJUuEASUybDPNI=", 242 | "vote": "eL2GxfrIoG2kuknlGa8I6vPtMbpygYflrye0u/hE4Lg=", 243 | "voteKD": 10000, 244 | "voteLst": 3000000 245 | } 246 | }, 247 | { 248 | "addr": "UXPVVSG7EYC7YR7PRVOZKWYYYZPKEXWGYR6XHBMSAV6BHKQEVFYVYJBVQI", 249 | "comment": "Wallet9", 250 | "state": { 251 | "algo": 320000000000000, 252 | "onl": 1, 253 | "sel": "P4tRdjhyJ9dSNItTY+r2+tQmPfHa6oBAzIh4X3df4gM=", 254 | "vote": "VHITXAytk0804xXBLBVKGlRAcAcDSZKcR2fiz4HtWBU=", 255 | "voteKD": 10000, 256 | "voteLst": 3000000 257 | } 258 | }, 259 | { 260 | "addr": "GD64YIY3TWGDMCNPP553DZPPR6LDUSFQOIJVFDPPXWEG3FVOJCCDBBHU5A", 261 | "comment": "bank-testnet", 262 | "state": { 263 | "algo": 200000000000000, 264 | "onl": 1, 265 | "sel": "r6aMJIPeqUPB8u4IvOU/wihF+sgqJVsjibvsYHVqj1s=", 266 | "vote": "mPB1VDBFOPSIEFhXo7VJRLxn45ylDSRnO8J1nXQf4f0=", 267 | "voteKD": 10000, 268 | "voteLst": 3000000 269 | } 270 | }, 271 | { 272 | "addr": "GFICEF3GYRENRQHINLRPG7TS7TUIOARUIN7KWXWFROSG55BWFFRCRX5DAA", 273 | "comment": "n1-testnet", 274 | "state": { 275 | "algo": 150000000000000, 276 | "onl": 1, 277 | "sel": "38qDzZjLPfernXNx7leElHsl39WLXMSgLHbEACeNgn4=", 278 | "vote": "8ITl30j5PTSDjmR26G3/rZL7IQM3cSfqqxnJSZf3X0w=", 279 | "voteKD": 10000, 280 | "voteLst": 3000000 281 | } 282 | }, 283 | { 284 | "addr": "GFY7ND6YSM5OGNSMAJDYCO6O75SWQRCYOJHCWOPYHUYCWQFWML52TWREBQ", 285 | "comment": "n10-testnet", 286 | "state": { 287 | "algo": 150000000000000, 288 | "onl": 1, 289 | "sel": "iwwKBjoUUUePkoG0ldxc0v6i1fIhVySn2l2kWwekn2A=", 290 | "vote": "DaZFFz72XkcUIuPXcEz6VxWj4SVjzMpOwpTfO2k308g=", 291 | "voteKD": 10000, 292 | "voteLst": 3000000 293 | } 294 | }, 295 | { 296 | "addr": "VQFEAD2SXHMLJ3BNSGYUHRZZWBOI7HUQZGFFJEKYD3SGNS667FTMPRDC4Y", 297 | "comment": "n11-testnet", 298 | "state": { 299 | "algo": 50000000000000, 300 | "onl": 1, 301 | "sel": "ckpVY6EaDInNeU1WLHQQXNsAaQnh+bpFhzNWzw0ZirI=", 302 | "vote": "4N1HJ9R2TrTEzLOyO1vUWPYi6sUcdAwQWoHQNBR/CME=", 303 | "voteKD": 10000, 304 | "voteLst": 3000000 305 | } 306 | }, 307 | { 308 | "addr": "6J7K7FIYKWTT3LSOZKYWAMSZC5RDID4CJ24C2S5DBQ5V7YUIHOBHPAO4KY", 309 | "comment": "n12-testnet", 310 | "state": { 311 | "algo": 50000000000000, 312 | "onl": 1, 313 | "sel": "n16osH+x1UIrzDNa7PCZHn/UtheRoLcTBwGRnx0fTa8=", 314 | "vote": "Tj0inLse0V3sQRPw+5rVQTIWOqTxn7/URDzUaWGHftg=", 315 | "voteKD": 10000, 316 | "voteLst": 3000000 317 | } 318 | }, 319 | { 320 | "addr": "G5KCM3LSFV4GHRYQBXGWTNMR5XESE3PIRODD7ZLASPIGOHPV7CO7UKLZFM", 321 | "comment": "n13-testnet", 322 | "state": { 323 | "algo": 50000000000000, 324 | "onl": 1, 325 | "sel": "tveXF/sDXqBXQY52IEMuvTeVguKzPfN8GLdKgtv3gRg=", 326 | "vote": "uwQJnVuqEtdGnWbbfu+TTLe++56z8wQCzv22IDioALE=", 327 | "voteKD": 10000, 328 | "voteLst": 3000000 329 | } 330 | }, 331 | { 332 | "addr": "XNQAMZMMLQV3TGYGJYYLYZUHP4YNEKAJM6RAMJ5SBXFLS3XDBIUVGCZPH4", 333 | "comment": "n14-testnet", 334 | "state": { 335 | "algo": 50000000000000, 336 | "onl": 1, 337 | "sel": "8xotecjUoo1YVzWME3ib9uh+kPUNnzsFcuHrjxxhjZM=", 338 | "vote": "oQ/iakoP5B6gTTm0+xfHHGFS4Ink30I6FWUGkxRNfo8=", 339 | "voteKD": 10000, 340 | "voteLst": 3000000 341 | } 342 | }, 343 | { 344 | "addr": "WXCLU5C6QH6KPVNAHNBGFUMC5JAOQCZP3HF76OT2TH3IAI3XTSPCLVILSU", 345 | "comment": "n15-testnet", 346 | "state": { 347 | "algo": 200000000000000, 348 | "onl": 1, 349 | "sel": "NRxs0rM5dov2oZrf6XrFSmG9CRlS3Bmzt0be7uF/nHw=", 350 | "vote": "R8xKtpYYNuTuTqMui/qzxYpc1m8KpbaK/eizYxVQDaY=", 351 | "voteKD": 10000, 352 | "voteLst": 3000000 353 | } 354 | }, 355 | { 356 | "addr": "7NRVO2ABPGFRX3374TIJZ46BR72CCSHKTR6PG5VVYNLUPWUVXGOU3O5YQA", 357 | "comment": "n16-testnet", 358 | "state": { 359 | "algo": 200000000000000, 360 | "onl": 1, 361 | "sel": "IQG+jgm2daCxMLxm/f9tTVrDk/hD0ZhB5dxDQn47BSE=", 362 | "vote": "CGwAHrq3QFFlsP7NmHed+Xx4BwFsE2f6dB30Os75KxY=", 363 | "voteKD": 10000, 364 | "voteLst": 3000000 365 | } 366 | }, 367 | { 368 | "addr": "537URFEXANB7M6UVND6WDM75DPRRORDXWFLSOG7EGILSKDIU4T32N4KAN4", 369 | "comment": "n17-testnet", 370 | "state": { 371 | "algo": 200000000000000, 372 | "onl": 1, 373 | "sel": "SdLlaWBe8B1JanMq0Y7T1Z9C8dKhI36MQiSffXQt7Lo=", 374 | "vote": "k4Xr6Bg6VpcY0GKwfr6kI89KqOihmCOToLLuIgFjv9c=", 375 | "voteKD": 10000, 376 | "voteLst": 3000000 377 | } 378 | }, 379 | { 380 | "addr": "ZNQXW7V5MISZFOZGVLAHKXS7GLWLXCLRPZTTIAZSTFRZPYTC54NWDZ6XZY", 381 | "comment": "n18-testnet", 382 | "state": { 383 | "algo": 200000000000000, 384 | "onl": 1, 385 | "sel": "TNMELlR1C+r4OmGVp9vc9XlehgD3a0EwfrepuMiDe+c=", 386 | "vote": "060veVAG/L2r2IAjqs2TcYy2cthocqrhgrCCoP5lzZ4=", 387 | "voteKD": 10000, 388 | "voteLst": 3000000 389 | } 390 | }, 391 | { 392 | "addr": "G3WQEPSGZOQVVJ2H3F6ICMHRIE2JL6U3X3JDABWJRN4HNDUJIAT4YTOGXA", 393 | "comment": "n19-testnet", 394 | "state": { 395 | "algo": 300000000000000, 396 | "onl": 1, 397 | "sel": "ktbtHTm1mUU5u/VMrOuMujMgemUf496zilQsGBynsxQ=", 398 | "vote": "XHXYdLvxKIIjtlmwHVqxvtAyRDE+SQR1tpzgXoNo5FA=", 399 | "voteKD": 10000, 400 | "voteLst": 3000000 401 | } 402 | }, 403 | { 404 | "addr": "2YNZ5XDUHYXL2COTVLZBRYV2A7VETFKQZQCPYMQRBOKTAANHP37DUH5BOI", 405 | "comment": "n2-testnet", 406 | "state": { 407 | "algo": 150000000000000, 408 | "onl": 1, 409 | "sel": "u7lR9NcWfssuMvFYuqCi5/nX0Fj9qBKbE0B2OpRhmMg=", 410 | "vote": "/UGQ/1dcp7OTmguYALryqQYRj0oMWhs/ahAbQTL/mRA=", 411 | "voteKD": 10000, 412 | "voteLst": 3000000 413 | } 414 | }, 415 | { 416 | "addr": "IH5Z5UZCZKNAH5OICUGHFEYM2JDMJRUSIUV4TZEQYHRNS3T2ROOV32CDIA", 417 | "comment": "n20-testnet", 418 | "state": { 419 | "algo": 300000000000000, 420 | "onl": 1, 421 | "sel": "Jbcg+BVB6EOTe42U0dq1psQfoFZItb6Phst22z33j60=", 422 | "vote": "8Y1QY+WJIziffLecmnr0ZRGJFKtA3oVALQoD3nVKlt8=", 423 | "voteKD": 10000, 424 | "voteLst": 3000000 425 | } 426 | }, 427 | { 428 | "addr": "FFJZOPQCYSRZISSJF33MBQJGGTIB2JFUEGBJIY6GXRWEU23ONC65GUZXHM", 429 | "comment": "n3-testnet", 430 | "state": { 431 | "algo": 150000000000000, 432 | "onl": 1, 433 | "sel": "+K8AsLfvuTEuHMANNp2LxGuotgEjFtqOjuR/o4KR6LA=", 434 | "vote": "SerMKyY37A1jFkE0BdrP+vuTdVn9oOJc5QjC5f98Dz8=", 435 | "voteKD": 10000, 436 | "voteLst": 3000000 437 | } 438 | }, 439 | { 440 | "addr": "ZWYIEI37V6HI62ZQCPJ5I6AIVKZP6JVCBQJKZEQQCWF4A4G2QGFENKS5XU", 441 | "comment": "n4-testnet", 442 | "state": { 443 | "algo": 150000000000000, 444 | "onl": 1, 445 | "sel": "SmhBpQdh23++6xC01unged2JU1Wgm2zZ8v5LQiG/VqA=", 446 | "vote": "U2lZo9ahjkKBvcS3qSWsmSx+PGI/m6OtnQrQOH1iuII=", 447 | "voteKD": 10000, 448 | "voteLst": 3000000 449 | } 450 | }, 451 | { 452 | "addr": "V32YQ6LMMT7X6MML35KOX4MKY7LXWEH4JETZYKAXQ5RX4ZQQ6FAJJ6EGJQ", 453 | "comment": "n5-testnet", 454 | "state": { 455 | "algo": 150000000000000, 456 | "onl": 1, 457 | "sel": "0yRtE7WSj32D5e/ov4o22ZgipQvqJZ6nx9NX1LdxFJI=", 458 | "vote": "scoN8x6Eq0bV4tBLT5R59jU+8gmHgh/6FX6mfV2tIKY=", 459 | "voteKD": 10000, 460 | "voteLst": 3000000 461 | } 462 | }, 463 | { 464 | "addr": "OEFWPZHFT25CSDHFRFW62JANGQLB5WD25GJBCGYTTPHFUMAYYD7SEAIVDI", 465 | "comment": "n6-testnet", 466 | "state": { 467 | "algo": 150000000000000, 468 | "onl": 1, 469 | "sel": "dWChUcA1ONX3iNEvHu9GST67XRePhAv6jd3XWt5clvI=", 470 | "vote": "rTfQ/l3lEfGQtzwjFii5ir2nCLSU+RT+0xI5af/XDEU=", 471 | "voteKD": 10000, 472 | "voteLst": 3000000 473 | } 474 | }, 475 | { 476 | "addr": "KCQLDL4GCVDLDYW5PYK7GJTUGHYRJ6CZ4QSRIZTXVRUIUAMDKYDFNUIFHU", 477 | "comment": "n7-testnet", 478 | "state": { 479 | "algo": 150000000000000, 480 | "onl": 1, 481 | "sel": "gNXMo6XiZvuQs2mtomJZtra7XiZHySIOWLuWivu4iso=", 482 | "vote": "okgQcI/L7YDAMOyqrLKs6CUB91k+mMFfMTaEb+ixvyY=", 483 | "voteKD": 10000, 484 | "voteLst": 3000000 485 | } 486 | }, 487 | { 488 | "addr": "UMMQNIYQXSI4VBGBXJUQ64ABURY6TPR7F4M5CMCOHYMB7GPVIZETZRNRBM", 489 | "comment": "n8-testnet", 490 | "state": { 491 | "algo": 150000000000000, 492 | "onl": 1, 493 | "sel": "ukzMIkE2U33xKq6LGX19NBLirZNANQAf3oiZtlkn5ls=", 494 | "vote": "HYHBaeVeN0DXYBNjRBuGtZqrBr3bSBC1YDQrv93dNrc=", 495 | "voteKD": 10000, 496 | "voteLst": 3000000 497 | } 498 | }, 499 | { 500 | "addr": "2INEY2MWIWIUNQS24YVXKT4M3RIKMEZGTVAOJG47N7EOJE7MKXOC6GJSMU", 501 | "comment": "n9-testnet", 502 | "state": { 503 | "algo": 150000000000000, 504 | "onl": 1, 505 | "sel": "7aUtPCawOYpPYjVd6oZOnZ+1CZXApr8QR4q1cOkVyWo=", 506 | "vote": "kcq1XWHnMrjbv/fvMmzIfGZzDtJtdL7i70lpWZ0kGi0=", 507 | "voteKD": 10000, 508 | "voteLst": 3000000 509 | } 510 | }, 511 | { 512 | "addr": "IE4C3BNWT4EYKPUZXGWDOOKBTJFVOYAZKBCWFYRC37U7BJKBIUH6NEB7SQ", 513 | "comment": "pp1-testnet", 514 | "state": { 515 | "algo": 50000000000000, 516 | "onl": 1, 517 | "sel": "C3PdYqoDjrjyaGvZ6M/W0E56Mv5BXdtRwj7+4unpxDM=", 518 | "vote": "8fdNikU3nMNyZb3AZlNTnsfsytvrd8bK2b/dYQgJj30=", 519 | "voteKD": 10000, 520 | "voteLst": 3000000 521 | } 522 | }, 523 | { 524 | "addr": "7WCI7XPEMWY6XNWHG2VXGYGDLHPTJ333CZ2WBGGUHCSYPTXPBWYCHZYTSE", 525 | "comment": "pp2-testnet", 526 | "state": { 527 | "algo": 25000000000000, 528 | "onl": 1, 529 | "sel": "l3K4aA15T42mTM+QE7GpOzbOcth6hMljBxna7gSR8IA=", 530 | "vote": "NsjSVQJj4XxK5Tt0R7pvU6wQB0MRKHDwC9F2bfUX/vM=", 531 | "voteKD": 10000, 532 | "voteLst": 3000000 533 | } 534 | }, 535 | { 536 | "addr": "WYX5JGDYM7TBTMBBEE2OI4GC4KVCTLB2P67B3PUQQS4OMUERE7NIIZDWO4", 537 | "comment": "pp3-testnet", 538 | "state": { 539 | "algo": 25000000000000, 540 | "onl": 1, 541 | "sel": "YmLs97jSdlbYU1H0PwZdzo6hlp0eyBwJ+ydM9ggEENI=", 542 | "vote": "GeDnbm9KKEu2dZ1FACwI0NsVWgoU0udpZef06IiTdfQ=", 543 | "voteKD": 10000, 544 | "voteLst": 3000000 545 | } 546 | }, 547 | { 548 | "addr": "2GJF4FEEPNCFKNYSOP6EOQGDQQCGDXPQHWE474DCKP5QO3HFBO73IBLBBY", 549 | "comment": "u1-testnet", 550 | "state": { 551 | "algo": 2000000000000 552 | } 553 | }, 554 | { 555 | "addr": "NHZ3VOL34MVWENM72QB6ZBRDMFJTU6R57HAJALSBERH4BNAGR4QDYYBT7A", 556 | "comment": "u10-testnet", 557 | "state": { 558 | "algo": 2000000000000 559 | } 560 | }, 561 | { 562 | "addr": "PTLGEQAIGTDWHPKA3IC5BL5UQE52XDZHQH7FUXRV4S6ZBRR5HGZENQ7LTQ", 563 | "comment": "u100-testnet", 564 | "state": { 565 | "algo": 2000000000000 566 | } 567 | }, 568 | { 569 | "addr": "3IE2GDYYSI56U53AQ6UUWRGAIGG5D4RHWLMCXJOPWQJA2ABF2X2OLFXGJE", 570 | "comment": "u11-testnet", 571 | "state": { 572 | "algo": 2000000000000 573 | } 574 | }, 575 | { 576 | "addr": "IAMUOCM2SEISQZYZZYTLHKSAALDJIXS2IQRU2GPZUOZWB2NLMFZPJSQ7VQ", 577 | "comment": "u12-testnet", 578 | "state": { 579 | "algo": 2000000000000 580 | } 581 | }, 582 | { 583 | "addr": "54GKXNGS7HNFHZGO7OIWK3H2KPKZYWSARW7PV4ITVTNCA65K6ESRKI6N3U", 584 | "comment": "u13-testnet", 585 | "state": { 586 | "algo": 2000000000000 587 | } 588 | }, 589 | { 590 | "addr": "5ZSFGF66FIJMMRORTYD2PLDAN67FA2J7LF3IYF4ZKD4DJHLEBYJ76DXGVU", 591 | "comment": "u14-testnet", 592 | "state": { 593 | "algo": 2000000000000 594 | } 595 | }, 596 | { 597 | "addr": "DY7K3FLRZTW2ZTYVOC4TCGK4JBL7NSJ4GR4BU252QNAVOCVTGEBCPCSJME", 598 | "comment": "u15-testnet", 599 | "state": { 600 | "algo": 2000000000000 601 | } 602 | }, 603 | { 604 | "addr": "JG4JQZNYP2524UDVRPPIMSFCIVQPVXLB5AKHM76VXIIRFNMIN3ROIYW65E", 605 | "comment": "u16-testnet", 606 | "state": { 607 | "algo": 2000000000000 608 | } 609 | }, 610 | { 611 | "addr": "7J4QX5DVIXSWBC2NJB44LPPUJXOAJQFMBCOS4EDI3XOE5WS76IY7WFTBQI", 612 | "comment": "u17-testnet", 613 | "state": { 614 | "algo": 2000000000000 615 | } 616 | }, 617 | { 618 | "addr": "6SA2WG5XM5Q6SSMBRK3TOHY552A75RVANBQQMKTT67PLUN44T3CJZAQOPM", 619 | "comment": "u18-testnet", 620 | "state": { 621 | "algo": 2000000000000 622 | } 623 | }, 624 | { 625 | "addr": "64DCC5CMTM4SMMO3QRTY3EDCHS73KDSNNH2XZL262DBK2LR4GJRETWUWIE", 626 | "comment": "u19-testnet", 627 | "state": { 628 | "algo": 2000000000000 629 | } 630 | }, 631 | { 632 | "addr": "TQ2B4MTCC6TARNEP4QPPMCKNBBNXKFTQKPVLAFC5XXRR2SWV5DICZELJOY", 633 | "comment": "u2-testnet", 634 | "state": { 635 | "algo": 2000000000000 636 | } 637 | }, 638 | { 639 | "addr": "ATNCIRLQLVZ7I4QBGW54DI6CY4AJVBQBPECVNS645RBMYDTK6VV55HXFUU", 640 | "comment": "u20-testnet", 641 | "state": { 642 | "algo": 2000000000000 643 | } 644 | }, 645 | { 646 | "addr": "4LP77VEVJ7QNESED4GICPRBZUNP7ZLKKLEVBRDSKX5NZSUFXPSEA575K5E", 647 | "comment": "u21-testnet", 648 | "state": { 649 | "algo": 2000000000000 650 | } 651 | }, 652 | { 653 | "addr": "7D34RBEHVI3A7YTQWOUTCSKNQYS5BDBN4E647DOC6WDVOLHPDPSSBY4MWI", 654 | "comment": "u22-testnet", 655 | "state": { 656 | "algo": 2000000000000 657 | } 658 | }, 659 | { 660 | "addr": "UMMKTTPNHIURGX24K7UYJ7T3WBB5J7OYBOQJ5WLPRG3BDYWJAEJLVBNHME", 661 | "comment": "u23-testnet", 662 | "state": { 663 | "algo": 2000000000000 664 | } 665 | }, 666 | { 667 | "addr": "EOPSQC3QTL7QJ4AQ2J4OJIJMKQLTMIEETJI7OFWYADIMHDWMHQ6MWCTUMQ", 668 | "comment": "u24-testnet", 669 | "state": { 670 | "algo": 2000000000000 671 | } 672 | }, 673 | { 674 | "addr": "XT3AVLURALOWTIMGZKB37J2M22NUQCRXTL4DJZHSTPCGLNQKVL7MR3MKFM", 675 | "comment": "u25-testnet", 676 | "state": { 677 | "algo": 2000000000000 678 | } 679 | }, 680 | { 681 | "addr": "WS63FDTLLYHC2NS7NXTEO7RPLNMAFM2D2BPJLTMAQJWPR2JCNYTTRMSOAE", 682 | "comment": "u26-testnet", 683 | "state": { 684 | "algo": 2000000000000 685 | } 686 | }, 687 | { 688 | "addr": "P5S5GGUHOMVOKWOZPJO74MBYVRXQWDBW6AOTHQZVKJKFGM7VBU6CNR4ATI", 689 | "comment": "u27-testnet", 690 | "state": { 691 | "algo": 2000000000000 692 | } 693 | }, 694 | { 695 | "addr": "PXVAI3MUYH4WWJXEQP7XNH3YIMO5ZBAFJWYUL7DOGPAHALE4K6GZBF4THU", 696 | "comment": "u28-testnet", 697 | "state": { 698 | "algo": 2000000000000 699 | } 700 | }, 701 | { 702 | "addr": "VGTKWLFANSULZAFDGBONHF55VVKE4V4F63JRDB66XM4K6KCQX6CL22WPRE", 703 | "comment": "u29-testnet", 704 | "state": { 705 | "algo": 2000000000000 706 | } 707 | }, 708 | { 709 | "addr": "QB2OTQ6DKUEJFP66A37ASIT4O3UZUOX24DAMWU2D3GCBDIYIXSIDHSXO4E", 710 | "comment": "u3-testnet", 711 | "state": { 712 | "algo": 2000000000000 713 | } 714 | }, 715 | { 716 | "addr": "4F6LA64ZLFN33ATWJ74UPAX56OLTXPL74SS5ATXUL7RGX7NKEFKMAWUQYE", 717 | "comment": "u30-testnet", 718 | "state": { 719 | "algo": 2000000000000 720 | } 721 | }, 722 | { 723 | "addr": "3JBNL7BZECXKYWZRPWETNL65XEYMAHLC6G3MZN2YMPFL3V7XSDXZEMBHVQ", 724 | "comment": "u31-testnet", 725 | "state": { 726 | "algo": 2000000000000 727 | } 728 | }, 729 | { 730 | "addr": "4M2QSKTXKPPZMNUAQ4UDS7ASMQCEUE4WTWGV6AM326425IJ64UNZBCIRGA", 731 | "comment": "u32-testnet", 732 | "state": { 733 | "algo": 2000000000000 734 | } 735 | }, 736 | { 737 | "addr": "J37V3LXHPRRKBODXNMNYNUJQIICCFFC4O4XB4YJCPVUAVZNOUG5DWDCEIA", 738 | "comment": "u33-testnet", 739 | "state": { 740 | "algo": 2000000000000 741 | } 742 | }, 743 | { 744 | "addr": "I75JBQHNYEYM3J742RBVW4W6RR3YY3BLG2PKO4PXYLVNEX5L646ASDJOOY", 745 | "comment": "u34-testnet", 746 | "state": { 747 | "algo": 2000000000000 748 | } 749 | }, 750 | { 751 | "addr": "ZHEIOZ7E2BEBCCKK5QM7DCZAOPTTONMQWHNJ6FOLKBHY466VON6DCZERD4", 752 | "comment": "u35-testnet", 753 | "state": { 754 | "algo": 2000000000000 755 | } 756 | }, 757 | { 758 | "addr": "4QMGP4C6OMSCNJI25H7UQGBFHRHL7KXAEQI57JNAXEO2EW3VT6D6LODT5Y", 759 | "comment": "u36-testnet", 760 | "state": { 761 | "algo": 2000000000000 762 | } 763 | }, 764 | { 765 | "addr": "KRED3JOLOJE3SLL5NGHAWSUGEMHCYJLD6PX43SIJYN2GC6MS6HPUPPO2LY", 766 | "comment": "u37-testnet", 767 | "state": { 768 | "algo": 2000000000000 769 | } 770 | }, 771 | { 772 | "addr": "SVFLDISKS4PDMJKOB6DVVVN6NQ776FHZMGWCOUQVQCH6GXTKCXIHTLYRRQ", 773 | "comment": "u38-testnet", 774 | "state": { 775 | "algo": 2000000000000 776 | } 777 | }, 778 | { 779 | "addr": "7IWGAPZ4VWRZLP2IHFSAC3JYOKNAZP6ONBNGGWUWHAUT7F23YFT3XKGNVU", 780 | "comment": "u39-testnet", 781 | "state": { 782 | "algo": 2000000000000 783 | } 784 | }, 785 | { 786 | "addr": "O2QVZMKATOIEU2OD4X42MLXAYVRXLRDKJTDXKBFCN3PCKN2Z3PUS5HKIVA", 787 | "comment": "u4-testnet", 788 | "state": { 789 | "algo": 2000000000000 790 | } 791 | }, 792 | { 793 | "addr": "H2YN73YPRWKY4GT744RRD65CXSQZO7MK72MV4RDHTIBV6YQUB2G56TVF2Y", 794 | "comment": "u40-testnet", 795 | "state": { 796 | "algo": 2000000000000 797 | } 798 | }, 799 | { 800 | "addr": "WGUAFWHRRX7VXPO3XXYCJL5ELO6REUGD57HRMBKTALT2TTXOLSHNOUEQCE", 801 | "comment": "u41-testnet", 802 | "state": { 803 | "algo": 2000000000000 804 | } 805 | }, 806 | { 807 | "addr": "RYHCD7GPAEBRV657FJJAG2ZZUDVPR66IU7CA5Y7UDMYSEEIWR4QDNSPLYQ", 808 | "comment": "u42-testnet", 809 | "state": { 810 | "algo": 2000000000000 811 | } 812 | }, 813 | { 814 | "addr": "BKTO5TKB4L57YWTZKQBOQ37EWH2HVXGJPXP3L6YSYOAWP3CYYBWLZ2PHTQ", 815 | "comment": "u43-testnet", 816 | "state": { 817 | "algo": 2000000000000 818 | } 819 | }, 820 | { 821 | "addr": "FL7LZ57VQQNW5NDJK2IKEAHIXRTB7VFBJEA2MIAEK3QVZPIBGLYW7XSZDY", 822 | "comment": "u44-testnet", 823 | "state": { 824 | "algo": 2000000000000 825 | } 826 | }, 827 | { 828 | "addr": "MXXQXZS2TAMIULLXXLX6MM6AHJAOQLHEIB2U3LR4KYKK7ZKRVUSHTU62QA", 829 | "comment": "u45-testnet", 830 | "state": { 831 | "algo": 2000000000000 832 | } 833 | }, 834 | { 835 | "addr": "UGOPPKTJQ2KPHU5I56733IMT3B7ECT5O44GW2FYX5SNDVIEDG72Z5GC5IA", 836 | "comment": "u46-testnet", 837 | "state": { 838 | "algo": 2000000000000 839 | } 840 | }, 841 | { 842 | "addr": "Y7MGWPRBHQN2PF3I2A3RWCQMVA42VR6FJONJ3W26WGKE4KMCGCVJIDLHEY", 843 | "comment": "u47-testnet", 844 | "state": { 845 | "algo": 2000000000000 846 | } 847 | }, 848 | { 849 | "addr": "NNFIWU43AUEZIUIQQECDXM3HRPUEJMPPZLXTM4ZFJKHWSZ2FEGCVMMJUBQ", 850 | "comment": "u48-testnet", 851 | "state": { 852 | "algo": 2000000000000 853 | } 854 | }, 855 | { 856 | "addr": "RN3HTSJKSUO6OECM3OPDFQQ2FYZWEY2OWAQGSMQSGY4DI7JJ4HBV2OIJJU", 857 | "comment": "u49-testnet", 858 | "state": { 859 | "algo": 2000000000000 860 | } 861 | }, 862 | { 863 | "addr": "OLYQUMZKLYDX2FVHECURBX4SRQSLMIIWN7D7VRJG7B6DS3IU6M5WYVNAAY", 864 | "comment": "u5-testnet", 865 | "state": { 866 | "algo": 2000000000000 867 | } 868 | }, 869 | { 870 | "addr": "PIG4P6JA2WDG7HBBR4FFDMVUCUD5Y5CTQ3K3KY34Y4AMT3CWEMVIKQLZZI", 871 | "comment": "u50-testnet", 872 | "state": { 873 | "algo": 2000000000000 874 | } 875 | }, 876 | { 877 | "addr": "QIDX47JRS37LRIYVY744SV7KTFGYXY5ABEK2VALNZCMN2H4FBLO7WWKYRM", 878 | "comment": "u51-testnet", 879 | "state": { 880 | "algo": 2000000000000 881 | } 882 | }, 883 | { 884 | "addr": "VQZCPUMOYIGCXOK2AK4XYYLWJNRBLS457IL4OSBKGVBHFZ5QPLTCUOTW4A", 885 | "comment": "u52-testnet", 886 | "state": { 887 | "algo": 2000000000000 888 | } 889 | }, 890 | { 891 | "addr": "WE2AIYHXI2LHABITCPTZRBTLFT54HPL4MKIR4HTASARNGCCZLXXDE67H3M", 892 | "comment": "u53-testnet", 893 | "state": { 894 | "algo": 2000000000000 895 | } 896 | }, 897 | { 898 | "addr": "HAIGM3LXXVKDCGCNQELNOBFZKP6C4A2ZY464F4TB7GWSVDN6I4SI7EOZUE", 899 | "comment": "u54-testnet", 900 | "state": { 901 | "algo": 2000000000000 902 | } 903 | }, 904 | { 905 | "addr": "MVZLGPXT6DZQIORE4PIO7NZD7QMJOZZZCOEVPZ3EQX2V4WG3PFU3BXUGDI", 906 | "comment": "u55-testnet", 907 | "state": { 908 | "algo": 2000000000000 909 | } 910 | }, 911 | { 912 | "addr": "MB5XJGVVKQU7NSEWWP65QW6H4JVEQYPA5626J4NGQP2E4BUMXRTEGW5X5Y", 913 | "comment": "u56-testnet", 914 | "state": { 915 | "algo": 2000000000000 916 | } 917 | }, 918 | { 919 | "addr": "EODZLNWFSRYZKLLF2YAOST2CYQCBRQGXPFQJLDW4CCMYFTYKBSWMF6QUAU", 920 | "comment": "u57-testnet", 921 | "state": { 922 | "algo": 2000000000000 923 | } 924 | }, 925 | { 926 | "addr": "LPAMNP7GJC5CNOMWRDII47WWYPF3TOVEIBDSSJA6PKOCPZ5AKRUWMIU2OM", 927 | "comment": "u58-testnet", 928 | "state": { 929 | "algo": 2000000000000 930 | } 931 | }, 932 | { 933 | "addr": "THRYS4MAIMEKG7BSAZ4EOKCVUJ7HA6AOCTK2UOKDGZ4TF7Q4BRVTBOUSYU", 934 | "comment": "u59-testnet", 935 | "state": { 936 | "algo": 2000000000000 937 | } 938 | }, 939 | { 940 | "addr": "7V7YITMPBTJ3IHHS2D35PVWRZGNFYWWQVRMTI4QP2CBPSKNDRGG66W2HFQ", 941 | "comment": "u6-testnet", 942 | "state": { 943 | "algo": 2000000000000 944 | } 945 | }, 946 | { 947 | "addr": "FHA2V46TK5CW66HQPOMLTH5PSKX2JX2IWLWZIYJUZ2RI7SK6HSSBTJBNHM", 948 | "comment": "u60-testnet", 949 | "state": { 950 | "algo": 2000000000000 951 | } 952 | }, 953 | { 954 | "addr": "7EJAXCVH7XLWDCWSXID4FNZ6T2SZRA4S7XIZOWA74ITAB272ZF2T5LSWSE", 955 | "comment": "u61-testnet", 956 | "state": { 957 | "algo": 2000000000000 958 | } 959 | }, 960 | { 961 | "addr": "K5L3YNZPU6SVNJOWAOKULCWBPIBNMR2VBCASVI4NWDM2APZ6GL36DFDR5Y", 962 | "comment": "u62-testnet", 963 | "state": { 964 | "algo": 2000000000000 965 | } 966 | }, 967 | { 968 | "addr": "5BY6RFBNUYHBYH4E4AWVMEOMI7YFKX7X3IPB5GRGAHH4BSXHIL34P3H43A", 969 | "comment": "u63-testnet", 970 | "state": { 971 | "algo": 2000000000000 972 | } 973 | }, 974 | { 975 | "addr": "BX2UBG5VCT2ASTGXHVG5NS6VVCYVB6GLKBN4NAAN7ABSTP7BMYCX2T2WEY", 976 | "comment": "u64-testnet", 977 | "state": { 978 | "algo": 2000000000000 979 | } 980 | }, 981 | { 982 | "addr": "37JPBYKXMWF6DO3FFWW53LBQCG636MTC7WG6DTRAPDFVXUIATFOMFR5ZLQ", 983 | "comment": "u65-testnet", 984 | "state": { 985 | "algo": 2000000000000 986 | } 987 | }, 988 | { 989 | "addr": "ODSPT3NISYMGEE3TJ6U6JCVC44L7DUCPHIV2QMPPRKBWJDALALGVCAPMRE", 990 | "comment": "u66-testnet", 991 | "state": { 992 | "algo": 2000000000000 993 | } 994 | }, 995 | { 996 | "addr": "CQA775B5TCU72Y2BNL6VCURBVJE45QV77RXHQ5KYRMMP6NCQ5BR7XJRYRA", 997 | "comment": "u67-testnet", 998 | "state": { 999 | "algo": 2000000000000 1000 | } 1001 | }, 1002 | { 1003 | "addr": "3Q4SYOBDOAVXUUTKBXEFFSK3BQMUQX5ORZPDA4PHB56KJJONPFFJ7YZ6HU", 1004 | "comment": "u68-testnet", 1005 | "state": { 1006 | "algo": 2000000000000 1007 | } 1008 | }, 1009 | { 1010 | "addr": "K23ME4QVDHSJWMGUHPGCL2OODAGBHIBW2KGYLLIR3UAEFD5ZW2KFB4WJ34", 1011 | "comment": "u69-testnet", 1012 | "state": { 1013 | "algo": 2000000000000 1014 | } 1015 | }, 1016 | { 1017 | "addr": "UD2OLL24RFDFMAKK7CCHKFIABPAP7ET4CYQUEYCJVGEIEJUAMDOGJZT26Y", 1018 | "comment": "u7-testnet", 1019 | "state": { 1020 | "algo": 2000000000000 1021 | } 1022 | }, 1023 | { 1024 | "addr": "KYXWZODLYDHTDMRUBOGOEV42G6H6KJ2JSBFZBP6XNWT42A6QEMEW23JWAM", 1025 | "comment": "u70-testnet", 1026 | "state": { 1027 | "algo": 2000000000000 1028 | } 1029 | }, 1030 | { 1031 | "addr": "V464X6D3XJVVJ372FFC2NBBDZLBNQA6H55J57WJMMSNOLHOJQ5UF3EUGNY", 1032 | "comment": "u71-testnet", 1033 | "state": { 1034 | "algo": 2000000000000 1035 | } 1036 | }, 1037 | { 1038 | "addr": "K27ODRPQARZM3236D2XC27QIV27GO2MUR65RGAJKO7UACIFYHG5QKPOCFU", 1039 | "comment": "u72-testnet", 1040 | "state": { 1041 | "algo": 2000000000000 1042 | } 1043 | }, 1044 | { 1045 | "addr": "FT3JD6TXUZOLOMN4O5CFZYSIHR4T5XJIF2YNV6WGEORNO2X65QW3VUP77I", 1046 | "comment": "u73-testnet", 1047 | "state": { 1048 | "algo": 2000000000000 1049 | } 1050 | }, 1051 | { 1052 | "addr": "WOTGZ4WOQ4S7YWVAOQ52GGOQPYQI2M7EPZENR27AOZLYFIEJDI3RYFB7OU", 1053 | "comment": "u74-testnet", 1054 | "state": { 1055 | "algo": 2000000000000 1056 | } 1057 | }, 1058 | { 1059 | "addr": "46MGTGNCTAC62NVNAVXAGP7PUJJIW5GXYYTSUDURCBSRZEDLGME7ICGE4E", 1060 | "comment": "u75-testnet", 1061 | "state": { 1062 | "algo": 2000000000000 1063 | } 1064 | }, 1065 | { 1066 | "addr": "MBTXWM5M5XQNUEKLBTW7GPU4LFPUETQQPVUBRCOA7FQ47H4J727NFRKKQE", 1067 | "comment": "u76-testnet", 1068 | "state": { 1069 | "algo": 2000000000000 1070 | } 1071 | }, 1072 | { 1073 | "addr": "4MCTFKPQCY25X6QARHGVD75OYUMQAAU5QLWCE2EM37NWOS7IFJSABMGKBI", 1074 | "comment": "u77-testnet", 1075 | "state": { 1076 | "algo": 2000000000000 1077 | } 1078 | }, 1079 | { 1080 | "addr": "PY6K3OGCXZVYQYZVA7W3MVZCAU5AFAWQ5J5THILXYIBYCKCGH4ELFU6TNU", 1081 | "comment": "u78-testnet", 1082 | "state": { 1083 | "algo": 2000000000000 1084 | } 1085 | }, 1086 | { 1087 | "addr": "4ABEMED4I7UYU6CJSLWYQXQHOK2XCQ443BSHR3SL7QJGXNYJ5QCYILSSNU", 1088 | "comment": "u79-testnet", 1089 | "state": { 1090 | "algo": 2000000000000 1091 | } 1092 | }, 1093 | { 1094 | "addr": "AXBINC5KA3I6IF3JAMKYQU3JLYTA5P2U4PUW3M4L53NEBNCRLHDHHOT2HY", 1095 | "comment": "u8-testnet", 1096 | "state": { 1097 | "algo": 2000000000000 1098 | } 1099 | }, 1100 | { 1101 | "addr": "5SXA2C6CGZ63OYDY5G4NFLIPJLKCZAMQWLMD2CBNSHUEXVS3ZYHAQCI5TI", 1102 | "comment": "u80-testnet", 1103 | "state": { 1104 | "algo": 2000000000000 1105 | } 1106 | }, 1107 | { 1108 | "addr": "EVP6MJIZWN6EE64TKEI4ANETP25MHYVXFWESU626TFA5VDVC75KSBGAA54", 1109 | "comment": "u81-testnet", 1110 | "state": { 1111 | "algo": 2000000000000 1112 | } 1113 | }, 1114 | { 1115 | "addr": "QAUV22GPBAOCO2JGAJF7U474S5SKXVWSZ7KG6P22P4MH3GNBGEJXAVDQLM", 1116 | "comment": "u82-testnet", 1117 | "state": { 1118 | "algo": 2000000000000 1119 | } 1120 | }, 1121 | { 1122 | "addr": "4FOOFGIWV4H7AXTEJXV2C4ONZ5NXAMUDKJSZDLSKACZ4JA4SWIU6UTLZAU", 1123 | "comment": "u83-testnet", 1124 | "state": { 1125 | "algo": 2000000000000 1126 | } 1127 | }, 1128 | { 1129 | "addr": "ARUMRBUW3HBQXE4QAL25PPVWAJSKGORTNUIOW3VA5GAMDECOVNYC7GJJS4", 1130 | "comment": "u84-testnet", 1131 | "state": { 1132 | "algo": 2000000000000 1133 | } 1134 | }, 1135 | { 1136 | "addr": "EJGCYTFUZPJDL2JBZJFQXKZIYJUDB7IBF3E2BH6GXWYWXUHSBCKYFJUKSU", 1137 | "comment": "u85-testnet", 1138 | "state": { 1139 | "algo": 2000000000000 1140 | } 1141 | }, 1142 | { 1143 | "addr": "FJMEFROCSGQ7C7IXMAPUST37QTQ2Y4A7RMLGK6YTUGHOCLOEL5BDE4AM2M", 1144 | "comment": "u86-testnet", 1145 | "state": { 1146 | "algo": 2000000000000 1147 | } 1148 | }, 1149 | { 1150 | "addr": "4V635E2WOGIKKWZ6QMYXDWQLYTUKRN7YAYADBQPETS75MKCR66ZC5IEG5M", 1151 | "comment": "u87-testnet", 1152 | "state": { 1153 | "algo": 2000000000000 1154 | } 1155 | }, 1156 | { 1157 | "addr": "AFJB4HWJLTMMA45VZAJJSUOFF7NROAEEMGT4Z3FQI5APWY472SJ6RNBWU4", 1158 | "comment": "u88-testnet", 1159 | "state": { 1160 | "algo": 2000000000000 1161 | } 1162 | }, 1163 | { 1164 | "addr": "BYO56YQOSRBUTNPXYO4XDMG7FU7SIP3QGVKAYQIJVJ4UIIMBRG3E4JMVD4", 1165 | "comment": "u89-testnet", 1166 | "state": { 1167 | "algo": 2000000000000 1168 | } 1169 | }, 1170 | { 1171 | "addr": "FQJO4LDTXEVQ2ZBFYDEAOYPQQZCZTMASMSXJ6V7LBYKOTFSCBUKKIU3DXA", 1172 | "comment": "u9-testnet", 1173 | "state": { 1174 | "algo": 2000000000000 1175 | } 1176 | }, 1177 | { 1178 | "addr": "WUCEVFNJGUNLMNG2AJMVYJRGQUFXRAFVX2ZRT7AC47WS6IRHPXHSUZ4NUA", 1179 | "comment": "u90-testnet", 1180 | "state": { 1181 | "algo": 2000000000000 1182 | } 1183 | }, 1184 | { 1185 | "addr": "5J5Q72IHCVAK5NE54ZI2RUZUF3HN2EAQEYQ674H3VX4UUHBMRYAZFRQDIY", 1186 | "comment": "u91-testnet", 1187 | "state": { 1188 | "algo": 2000000000000 1189 | } 1190 | }, 1191 | { 1192 | "addr": "2LK2SZ3L4PWUXXM4XYFFSCFIV7V5VQJUDFVK7QXK6HJL4OUQKQLWG77EUI", 1193 | "comment": "u92-testnet", 1194 | "state": { 1195 | "algo": 2000000000000 1196 | } 1197 | }, 1198 | { 1199 | "addr": "QUWHMJLFQAIIG5LV7NK5VNESUUW23RINBSHKKKQDIV4AP56RSTYSNZHDRQ", 1200 | "comment": "u93-testnet", 1201 | "state": { 1202 | "algo": 2000000000000 1203 | } 1204 | }, 1205 | { 1206 | "addr": "YJEGUEJ2UW2ABLO6XI5QIHQID5ZKUDUDQPHQEN7MH5SS2FLZ573CHRHCZM", 1207 | "comment": "u94-testnet", 1208 | "state": { 1209 | "algo": 2000000000000 1210 | } 1211 | }, 1212 | { 1213 | "addr": "XOUVBGEZMDVYPES4MGTAEBYU5O6LOCOH27ZJ3ML7ATWEU63N6IWW6F4BLM", 1214 | "comment": "u95-testnet", 1215 | "state": { 1216 | "algo": 2000000000000 1217 | } 1218 | }, 1219 | { 1220 | "addr": "6CFS2YVK2IMVVFBGGHSPUQBIKMNWRRB44EIUUB4EFXAL7IOJXAHRGXKAGA", 1221 | "comment": "u96-testnet", 1222 | "state": { 1223 | "algo": 2000000000000 1224 | } 1225 | }, 1226 | { 1227 | "addr": "W5ITKFRKK265A4WKF7IRCZ4MCC7HM3INCJGKPPH3AEKDFYMOJJ4FDLQWYI", 1228 | "comment": "u97-testnet", 1229 | "state": { 1230 | "algo": 2000000000000 1231 | } 1232 | }, 1233 | { 1234 | "addr": "MBMU3IODI6OFX34MBDMNTD6WSVA6B3XLDVB3IHZJQY3TZUYBPKRNFTUQSM", 1235 | "comment": "u98-testnet", 1236 | "state": { 1237 | "algo": 2000000000000 1238 | } 1239 | }, 1240 | { 1241 | "addr": "CKNVTB7DPRZO3MB64RQFPZIHCHCC4GBSTAAJKVQ2SLYNKVYPK4EJFBCQKM", 1242 | "comment": "u99-testnet", 1243 | "state": { 1244 | "algo": 2000000000000 1245 | } 1246 | } 1247 | ], 1248 | "fees": "A7NMWS3NT3IUDMLVO26ULGXGIIOUQ3ND2TXSER6EBGRZNOBOUIQXHIBGDE", 1249 | "id": "v1.0", 1250 | "network": "testnet", 1251 | "proto": "https://github.com/algorand/spec/tree/a26ed78ed8f834e2b9ccb6eb7d3ee9f629a6e622", 1252 | "rwd": "7777777777777777777777777777777777777777777777777774MSJUVU", 1253 | "timestamp": 1560210455 1254 | } 1255 | -------------------------------------------------------------------------------- /images/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | ARG channel 3 | 4 | ENV DEBIAN_FRONTEND noninteractive 5 | RUN apt-get update && apt-get install -y ca-certificates curl 6 | 7 | # Use a non-privilidged user with a random UID / GID for security reasons 8 | RUN groupadd -g 10353 algorand && \ 9 | useradd -m -u 10353 -g algorand algorand && \ 10 | chown -R algorand:algorand /opt && \ 11 | ls -lha /opt 12 | 13 | USER algorand 14 | 15 | COPY --chown=algorand:algorand ./config/update.sh /tmp 16 | 17 | RUN \ 18 | set -eux; \ 19 | mkdir /opt/installer ; \ 20 | cd /opt/installer ; \ 21 | mv /tmp/update.sh . ; \ 22 | ./update.sh -i -c $channel -p /opt/algorand/node -d /opt/algorand/node/data.tmp -n ; \ 23 | rm -rf /opt/algorand/node/data.tmp ; \ 24 | mkdir /opt/algorand/node/data 25 | 26 | COPY ./config/start.sh /opt/algorand 27 | 28 | VOLUME /opt/algorand/node/data 29 | 30 | # Set up environment variable to make life easier 31 | ENV PATH="/opt/algorand/node:${PATH}" 32 | ENV ALGORAND_DATA="/opt/algorand/node/data" 33 | 34 | ENTRYPOINT [ "/opt/algorand/start.sh" ] 35 | -------------------------------------------------------------------------------- /images/algod/DevModeNetwork.json: -------------------------------------------------------------------------------- 1 | { 2 | "Genesis": { 3 | "NetworkName": "devmodenet", 4 | "FirstPartKeyRound": 0, 5 | "LastPartKeyRound": NETWORK_NUM_ROUNDS, 6 | "Wallets": [ 7 | { 8 | "Name": "Wallet1", 9 | "Stake": 40, 10 | "Online": true 11 | }, 12 | { 13 | "Name": "Wallet2", 14 | "Stake": 40, 15 | "Online": true 16 | }, 17 | { 18 | "Name": "Wallet3", 19 | "Stake": 20, 20 | "Online": true 21 | } 22 | ], 23 | "DevMode": true, 24 | "RewardsPoolBalance": 0 25 | }, 26 | "Nodes": [ 27 | { 28 | "Name": "Node", 29 | "IsRelay": true, 30 | "Wallets": [ 31 | { 32 | "Name": "Wallet1", 33 | "ParticipationOnly": false 34 | }, 35 | { 36 | "Name": "Wallet2", 37 | "ParticipationOnly": false 38 | }, 39 | { 40 | "Name": "Wallet3", 41 | "ParticipationOnly": false 42 | } 43 | ] 44 | }, 45 | { 46 | "Name": "Follower", 47 | "Wallets": [], 48 | "ConfigJSONOverride": "{\"EnableFollowMode\":true,\"CatchupBlockValidateMode\":3,\"EndpointAddress\":\"0.0.0.0:ALGOD_FOLLOWER_PORT\", \"EnableTxnEvalTracer\": true, \"MaxAcctLookback\": 256}" 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /images/algod/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.23.3 2 | FROM golang:$GO_VERSION 3 | 4 | ARG CHANNEL=nightly 5 | ARG URL= 6 | ARG BRANCH= 7 | ARG SHA= 8 | 9 | # When these are set attempt to connect to a network. 10 | ARG GENESIS_FILE="" 11 | ARG BOOTSTRAP_URL="" 12 | 13 | # Options for algod config 14 | ARG ALGOD_PORT="" 15 | ARG ALGOD_FOLLOWER_PORT="" 16 | ARG KMD_PORT="" 17 | ARG TOKEN="" 18 | ARG TEMPLATE="" 19 | ARG NETWORK_NUM_ROUNDS="30000" 20 | ARG NODE_ARCHIVAL="" 21 | ARG MAX_ACCOUNT_LOOKBACK=256 22 | 23 | RUN echo "Installing from source. ${URL} -- ${BRANCH}" 24 | ENV BIN_DIR="$HOME/node" 25 | ENV ALGORAND_DATA="/opt/data" 26 | 27 | # Basic dependencies. 28 | ENV HOME /opt 29 | ENV DEBIAN_FRONTEND noninteractive 30 | RUN apt-get update && apt-get install -y apt-utils curl git git-core bsdmainutils python3 31 | 32 | # Copy lots of things into the container. The gitignore indicates which directories. 33 | COPY . /tmp 34 | 35 | # Install algod binaries. 36 | RUN /tmp/images/algod/install.sh \ 37 | -d "${BIN_DIR}" \ 38 | -c "${CHANNEL}" \ 39 | -u "${URL}" \ 40 | -b "${BRANCH}" \ 41 | -s "${SHA}" 42 | 43 | # Configure network 44 | RUN sed -i \ 45 | -e "s/NETWORK_NUM_ROUNDS/$NETWORK_NUM_ROUNDS/" \ 46 | -e "s/ALGOD_FOLLOWER_PORT/$ALGOD_FOLLOWER_PORT/" \ 47 | "//tmp/${TEMPLATE}" && \ 48 | /tmp/images/algod/setup.py \ 49 | --bin-dir "$BIN_DIR" \ 50 | --data-dir "/opt/data" \ 51 | --start-script "/opt/start_algod.sh" \ 52 | --network-dir "/opt/testnetwork" \ 53 | --network-template "//tmp/${TEMPLATE}" \ 54 | --network-token "${TOKEN}" \ 55 | --algod-port "${ALGOD_PORT}" \ 56 | --kmd-port "${KMD_PORT}" \ 57 | --bootstrap-url "${BOOTSTRAP_URL}" \ 58 | --genesis-file "/tmp/${GENESIS_FILE}" \ 59 | --archival "${NODE_ARCHIVAL}" \ 60 | --max-account-lookback "${MAX_ACCOUNT_LOOKBACK}" 61 | 62 | ENV PATH="$BIN_DIR:${PATH}" 63 | WORKDIR /opt/data 64 | 65 | # Start algod 66 | CMD ["/opt/start_algod.sh"] 67 | -------------------------------------------------------------------------------- /images/algod/future_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Genesis": { 3 | "ConsensusProtocol": "future", 4 | "NetworkName": "", 5 | "FirstPartKeyRound": 0, 6 | "LastPartKeyRound": NETWORK_NUM_ROUNDS, 7 | "Wallets": [ 8 | { 9 | "Name": "Wallet1", 10 | "Stake": 10, 11 | "Online": true 12 | }, 13 | { 14 | "Name": "Wallet2", 15 | "Stake": 40, 16 | "Online": true 17 | }, 18 | { 19 | "Name": "Wallet3", 20 | "Stake": 40, 21 | "Online": false 22 | }, 23 | { 24 | "Name": "Wallet4", 25 | "Stake": 10, 26 | "Online": false 27 | } 28 | ], 29 | "RewardsPoolBalance":0 30 | }, 31 | "Nodes": [ 32 | { 33 | "Name": "Primary", 34 | "IsRelay": true, 35 | "Wallets": [ 36 | { 37 | "Name": "Wallet1", 38 | "ParticipationOnly": false 39 | } 40 | ] 41 | }, 42 | { 43 | "Name": "Node", 44 | "Wallets": [ 45 | { 46 | "Name": "Wallet2", 47 | "ParticipationOnly": false 48 | }, 49 | { 50 | "Name": "Wallet3", 51 | "ParticipationOnly": false 52 | }, 53 | { 54 | "Name": "Wallet4", 55 | "ParticipationOnly": false 56 | } 57 | ] 58 | }, 59 | { 60 | "Name": "Follower", 61 | "Wallets": [], 62 | "ConfigJSONOverride": "{\"EnableFollowMode\":true,\"CatchupBlockValidateMode\":3,\"EndpointAddress\":\"0.0.0.0:ALGOD_FOLLOWER_PORT\", \"EnableTxnEvalTracer\": true, \"MaxAcctLookback\": 256}" 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /images/algod/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to install algod in all sorts of different ways. 4 | # 5 | # Parameters: 6 | # -d : Location where binaries will be installed. 7 | # -c : Channel to install. Mutually exclusive with source options. 8 | # -u : Git repository URL. Mutually exclusive with -c. 9 | # -b : Git branch. Mutually exclusive with -c. 10 | # -s : (optional) Git Commit SHA hash. Mutually exclusive with -c. 11 | 12 | set -e 13 | 14 | rootdir=`dirname $0` 15 | pushd $rootdir 16 | 17 | BINDIR="" 18 | CHANNEL="" 19 | URL="" 20 | BRANCH="" 21 | SHA="" 22 | 23 | while getopts "d:c:u:b:s:" opt; do 24 | case "$opt" in 25 | d) BINDIR=$OPTARG; ;; 26 | c) CHANNEL=$OPTARG; ;; 27 | u) URL=$OPTARG; ;; 28 | b) BRANCH=$OPTARG; ;; 29 | s) SHA=$OPTARG; ;; 30 | esac 31 | done 32 | 33 | if [ -z BINDIR ]; then 34 | echo "-d is required." 35 | exit 1 36 | fi 37 | 38 | if [ ! -z $CHANNEL ] && [ ! -z $BRANCH ]; then 39 | echo "Set only one of -c or -b " 40 | exit 1 41 | fi 42 | 43 | if [ ! -z $BRANCH ] && [ -z $URL ]; then 44 | echo "If using -b , must also set -u " 45 | exit 1 46 | fi 47 | 48 | echo "Installing algod with options:" 49 | echo " BINDIR = ${BINDIR}" 50 | echo " CHANNEL = ${CHANNEL}" 51 | echo " URL = ${URL}" 52 | echo " BRANCH = ${BRANCH}" 53 | echo " SHA = ${SHA}" 54 | 55 | if [ ! -z $CHANNEL ]; then 56 | ./update.sh -i -c $CHANNEL -p $BINDIR -d $BINDIR/data -n 57 | exit 0 58 | fi 59 | 60 | if [ ! -z $BRANCH ]; then 61 | git clone --single-branch --branch "${BRANCH}" "${URL}" 62 | cd go-algorand 63 | if [ "${SHA}" != "" ]; then 64 | echo "Checking out ${SHA}" 65 | git checkout "${SHA}" 66 | fi 67 | 68 | git log -n 5 69 | 70 | ./scripts/configure_dev.sh 71 | make build 72 | ./scripts/dev_install.sh -p $BINDIR 73 | fi 74 | 75 | $BINDIR/algod -v 76 | -------------------------------------------------------------------------------- /images/algod/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Script to help configure and run different algorand configurations. 4 | # Notably this script can configure an algorand installation to run as a 5 | # private network, or as a node connected to a long-running network. 6 | # 7 | # For parameter information run with './setup.py -h' 8 | # 9 | # Parameter error handling is not great with this script. It wont complain 10 | # if you provide arguments unused parameters. 11 | 12 | import argparse 13 | import os 14 | import pprint 15 | import shutil 16 | import subprocess 17 | import tarfile 18 | import time 19 | import json 20 | import urllib.request 21 | from os.path import expanduser, join 22 | 23 | from typing import List 24 | 25 | parser = argparse.ArgumentParser(description='''\ 26 | Configure private network for SDK and prepare it to run. A start script and 27 | symlink to data directory will be generated to make it easier to use.''') 28 | parser.add_argument('--bin-dir', required=True, help='Location to install algod binaries.') 29 | parser.add_argument('--data-dir', required=True, help='Location to place a symlink to the data directory.') 30 | parser.add_argument('--start-script', required=True, help='Path to start script, including the script name.') 31 | parser.add_argument('--network-template', required=True, help='Path to private network template file.') 32 | parser.add_argument('--network-token', required=True, help='Valid token to use for algod/kmd.') 33 | parser.add_argument('--algod-port', required=True, help='Port to use for algod.') 34 | parser.add_argument('--kmd-port', required=True, help='Port to use for kmd.') 35 | parser.add_argument('--network-dir', required=True, help='Path to create network.') 36 | parser.add_argument('--bootstrap-url', required=True, help='DNS Bootstrap URL, empty for private networks.') 37 | parser.add_argument('--genesis-file', required=True, help='Genesis file used by the network.') 38 | parser.add_argument('--archival', type=bool, default=False, help='When True, bootstrap an archival node.') 39 | parser.add_argument('--max-account-lookback', required=True, help='Max account lookback range for account states on the node.') 40 | 41 | pp = pprint.PrettyPrinter(indent=4) 42 | 43 | 44 | def algod_directories(network_dir): 45 | """ 46 | Compute data/kmd directories. 47 | """ 48 | data_dir=join(network_dir, 'Node') 49 | 50 | kmd_dir = None 51 | options = [filename for filename in os.listdir(data_dir) if filename.startswith('kmd')] 52 | 53 | # When setting up the real network the kmd dir doesn't exist yet because algod hasn't been started. 54 | if len(options) == 0: 55 | kmd_dir=join(data_dir, 'kmd-v0.5') 56 | os.mkdir(kmd_dir) 57 | else: 58 | kmd_dir=join(data_dir, options[0]) 59 | 60 | follower_dir=join(network_dir, 'Follower') 61 | 62 | return data_dir, kmd_dir, follower_dir 63 | 64 | 65 | def create_real_network(bin_dir, network_dir, template, genesis_file) -> List[str]: 66 | data_dir_src=join(bin_dir, 'data') 67 | target=join(network_dir, 'Node') 68 | 69 | # Reset in case it exists 70 | if os.path.exists(target): 71 | shutil.rmtree(target) 72 | os.makedirs(target, exist_ok=True) 73 | 74 | # Copy in the genesis file... 75 | shutil.copy(genesis_file, target) 76 | 77 | data_dir, kmd_dir, _ = algod_directories(network_dir) 78 | 79 | return ['%s/goal node start -d %s' % (bin_dir, data_dir), 80 | '%s/kmd start -t 0 -d %s' % (bin_dir, kmd_dir)] 81 | 82 | 83 | def create_private_network(bin_dir, network_dir, template) -> List[str]: 84 | """ 85 | Create a private network. 86 | """ 87 | # Reset network dir before creating a new one. 88 | if os.path.exists(args.network_dir): 89 | shutil.rmtree(args.network_dir) 90 | 91 | # Use goal to create the private network. 92 | subprocess.check_call(['%s/goal network create -n sandnet -r %s -t %s' % (bin_dir, network_dir, template)], shell=True) 93 | 94 | _, kmd_dir, _ = algod_directories(network_dir) 95 | return ['%s/goal network start -r %s' % (bin_dir, network_dir), 96 | '%s/kmd start -t 0 -d %s' % (bin_dir, kmd_dir)] 97 | 98 | 99 | def configure_data_dir(network_dir, token, algod_port, kmd_port, bootstrap_url, archival, max_account_lookback): 100 | node_dir, kmd_dir, follower_dir = algod_directories(network_dir) 101 | 102 | has_follower = os.path.exists(follower_dir) 103 | 104 | # Set tokens 105 | with open(join(node_dir, 'algod.token'), 'w') as f: 106 | f.write(token) 107 | with open(join(node_dir, 'algod.admin.token'), 'w') as f: 108 | f.write(token) 109 | if has_follower: 110 | with open(join(follower_dir, 'algod.token'), 'w') as f: 111 | f.write(token) 112 | with open(join(follower_dir, 'algod.admin.token'), 'w') as f: 113 | f.write(token) 114 | with open(join(kmd_dir, 'kmd.token'), 'w') as f: 115 | f.write(token) 116 | 117 | # Setup config, inject port 118 | node_config_path = join(node_dir, "config.json") 119 | archival = 'true' if archival else 'false' 120 | if has_follower: 121 | node_config = f'{{ "Version": 34, "GossipFanout": 1, "EndpointAddress": "0.0.0.0:{algod_port}", "EnablePrivateNetworkAccessHeader": true, "Archival":{archival}, "EnableDeveloperAPI":true, "NetAddress": "127.0.0.1:0", "DNSBootstrapID": "{bootstrap_url}", "EnableTxnEvalTracer": true, "MaxAcctLookback": {max_account_lookback}}}' 122 | else: 123 | node_config = f'{{ "Version": 34, "GossipFanout": 1, "EndpointAddress": "0.0.0.0:{algod_port}", "EnablePrivateNetworkAccessHeader": true, "DNSBootstrapID": "{bootstrap_url}", "IncomingConnectionsLimit": 0, "Archival":{archival}, "EnableDeveloperAPI":true, "EnableTxnEvalTracer": true, "MaxAcctLookback": {max_account_lookback}}}' 124 | print(f"writing to node_config_path=[{node_config_path}] config json: {node_config}") 125 | with open(node_config_path, "w") as f: 126 | f.write(node_config) 127 | 128 | kmd_config_path = join(kmd_dir, 'kmd_config.json') 129 | kmd_config = f'{{ "address":"0.0.0.0:{kmd_port}", "allowed_origins":["*"], "allow_header_pna": true }}' 130 | print(f"writing to kmd_config_path=[{kmd_config_path}] config json: {kmd_config}") 131 | with open(kmd_config_path, 'w') as f: 132 | f.write(kmd_config) 133 | 134 | if __name__ == '__main__': 135 | args = parser.parse_args() 136 | 137 | print('Configuring network with the following arguments:') 138 | pp.pprint(vars(args)) 139 | 140 | 141 | # Setup network 142 | privateNetworkMode = args.genesis_file == None or args.genesis_file == '' or os.path.isdir(args.genesis_file) 143 | if privateNetworkMode: 144 | print('Creating a private network.') 145 | startCommands = create_private_network(args.bin_dir, args.network_dir, args.network_template) 146 | else: 147 | print('Setting up real retwork.') 148 | startCommands = create_real_network(args.bin_dir, args.network_dir, args.network_template, args.genesis_file) 149 | 150 | # Write start script 151 | print(f'Start commands for {args.start_script}:') 152 | pp.pprint(f'startCommands={startCommands}') 153 | with open(args.start_script, 'w') as f: 154 | f.write('#!/usr/bin/env bash\n') 155 | for line in startCommands: 156 | f.write(f'{line}\n') 157 | f.write('sleep infinity\n') 158 | os.chmod(args.start_script, 0o755) 159 | print(f"Finished preparing start script '{args.start_script}' under /opt/") 160 | 161 | # Create symlink 162 | data_dir, _, _ = algod_directories(args.network_dir) 163 | print(f'Creating symlink {args.data_dir} -> {data_dir}') 164 | os.symlink(data_dir, args.data_dir) 165 | 166 | # Configure network 167 | configure_data_dir( 168 | args.network_dir, 169 | args.network_token, 170 | args.algod_port, 171 | args.kmd_port, 172 | args.bootstrap_url, 173 | args.archival, 174 | args.max_account_lookback, 175 | ) 176 | 177 | -------------------------------------------------------------------------------- /images/algod/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Genesis": { 3 | "NetworkName": "", 4 | "FirstPartKeyRound": 0, 5 | "LastPartKeyRound": NETWORK_NUM_ROUNDS, 6 | "Wallets": [ 7 | { 8 | "Name": "Wallet1", 9 | "Stake": 10, 10 | "Online": true 11 | }, 12 | { 13 | "Name": "Wallet2", 14 | "Stake": 40, 15 | "Online": true 16 | }, 17 | { 18 | "Name": "Wallet3", 19 | "Stake": 40, 20 | "Online": false 21 | }, 22 | { 23 | "Name": "Wallet4", 24 | "Stake": 10, 25 | "Online": false 26 | } 27 | ], 28 | "RewardsPoolBalance":0 29 | }, 30 | "Nodes": [ 31 | { 32 | "Name": "Primary", 33 | "IsRelay": true, 34 | "Wallets": [ 35 | { 36 | "Name": "Wallet1", 37 | "ParticipationOnly": false 38 | } 39 | ] 40 | }, 41 | { 42 | "Name": "Node", 43 | "Wallets": [ 44 | { 45 | "Name": "Wallet2", 46 | "ParticipationOnly": false 47 | }, 48 | { 49 | "Name": "Wallet3", 50 | "ParticipationOnly": false 51 | }, 52 | { 53 | "Name": "Wallet4", 54 | "ParticipationOnly": false 55 | } 56 | ] 57 | }, 58 | { 59 | "Name": "Follower", 60 | "Wallets": [], 61 | "ConfigJSONOverride": "{\"EnableFollowMode\":true,\"CatchupBlockValidateMode\":3,\"EndpointAddress\":\"0.0.0.0:ALGOD_FOLLOWER_PORT\", \"EnableTxnEvalTracer\": true, \"MaxAcctLookback\": 256}" 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /images/algod/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # shellcheck disable=2009,2093,2164 3 | 4 | FILENAME=$(basename -- "$0") 5 | SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" 6 | UPDATETYPE="update" 7 | INSTALLOPT="-u" 8 | RESUME_INSTALL=0 9 | BINDIR="" 10 | CHANNEL="" 11 | DATADIRS=() 12 | NOSTART="" 13 | BINDIRSPEC="-p ${SCRIPTPATH}" 14 | DATADIRSPEC="" 15 | TESTROLLBACK="" 16 | UNKNOWNARGS=() 17 | HOSTEDFLAG="" 18 | HOSTEDSPEC="" 19 | BUCKET="" 20 | GENESIS_NETWORK_DIR="" 21 | GENESIS_NETWORK_DIR_SPEC="" 22 | SKIP_UPDATE=0 23 | TOOLS_OUTPUT_DIR="" 24 | DRYRUN=false 25 | IS_ROOT=false 26 | if [ $EUID -eq 0 ]; then 27 | IS_ROOT=true 28 | fi 29 | 30 | 31 | set -o pipefail 32 | 33 | # If someone set the environment variable asking us to cleanup 34 | # when we're done, install a trap to do so 35 | # We use an environment variable instead of an arg because 36 | # older scripts won't recognize it and will fail (an issue with tests) 37 | if [ "${CLEANUP_UPDATE_TEMP_DIR}" != "" ]; then 38 | trap "rm -rf ${CLEANUP_UPDATE_TEMP_DIR}" 0 39 | fi 40 | 41 | while [ "$1" != "" ]; do 42 | case "$1" in 43 | -i) 44 | UPDATETYPE="install" 45 | INSTALLOPT="-i" 46 | ;; 47 | -u) 48 | UPDATETYPE="update" 49 | INSTALLOPT="-u" 50 | ;; 51 | -m) 52 | UPDATETYPE="migrate" 53 | INSTALLOPT="-m" 54 | ;; 55 | -r) 56 | RESUME_INSTALL=1 57 | ;; 58 | -c) 59 | shift 60 | CHANNEL="$1" 61 | ;; 62 | -d) 63 | shift 64 | THISDIR=$1 65 | mkdir -p "${THISDIR}" >/dev/null 66 | pushd "${THISDIR}" >/dev/null 67 | THISDIR=$(pwd -P) 68 | popd >/dev/null 69 | DATADIRS+=(${THISDIR}) 70 | DATADIRSPEC+="-d ${THISDIR} " 71 | ;; 72 | -p) 73 | shift 74 | BINDIR="$1" 75 | BINDIRSPEC="-p $1" 76 | ;; 77 | -n) 78 | NOSTART="-n" 79 | ;; 80 | -testrollback) 81 | TESTROLLBACK=1 82 | ;; 83 | -hosted) 84 | HOSTEDFLAG="-H" 85 | HOSTEDSPEC="-hosted" 86 | ;; 87 | -g) 88 | shift 89 | GENESIS_NETWORK_DIR=$1 90 | GENESIS_NETWORK_DIR_SPEC="-g $1" 91 | ;; 92 | -b) 93 | shift 94 | BUCKET="-b $1" 95 | ;; 96 | -s) 97 | SKIP_UPDATE=1 98 | ;; 99 | -gettools) 100 | shift 101 | TOOLS_OUTPUT_DIR=$1 102 | ;; 103 | -z) 104 | DRYRUN=true 105 | ;; 106 | *) 107 | echo "Unknown option" "$1" 108 | UNKNOWNARGS+=("$1") 109 | ;; 110 | esac 111 | shift 112 | done 113 | 114 | # If this is an update, we'll validate that before doing anything else. 115 | # If this is an install, we'll create it. 116 | if [ ${RESUME_INSTALL} -eq 0 ] && ! $DRYRUN; then 117 | if [ "${BINDIR}" = "" ]; then 118 | BINDIR="${SCRIPTPATH}" 119 | fi 120 | fi 121 | 122 | # If -d not specified, don't default any more 123 | if [ "${#DATADIRS[@]}" -eq 0 ]; then 124 | echo "You must specify at least one data directory with \`-d\`" 125 | exit 1 126 | fi 127 | 128 | CURRENTVER=0 129 | 130 | ROLLBACK=0 131 | ROLLBACKBIN=0 132 | ROLLBACKDATA=() 133 | NEW_LEDGER=0 134 | RESTART_NODE=0 135 | 136 | function check_install_valid() { 137 | # Check for key files that indicate a valid install that can be updated 138 | if [ ! -f "${BINDIR}/algod" ]; then 139 | echo "Missing ${BINDIR}/algod" 140 | return 1 141 | fi 142 | return 0 143 | } 144 | 145 | function validate_channel_specified() { 146 | if [ "${CHANNEL}" = "" ]; then 147 | CHANNEL="$((${BINDIR}/algod -c) | head -n 1)" 148 | if [ "${CHANNEL}" = "" ]; then 149 | echo "Unable to determine release channel - please run again with -c " 150 | return 1 151 | fi 152 | fi 153 | } 154 | 155 | function determine_current_version() { 156 | CURRENTVER="$(( ${BINDIR}/algod -v 2>/dev/null || echo 0 ) | head -n 1)" 157 | echo Current Version = ${CURRENTVER} 158 | } 159 | 160 | function get_updater_url() { 161 | local UNAME 162 | local OS 163 | local ARCH 164 | UNAME=$(uname) 165 | if [[ "${UNAME}" = "Darwin" ]]; then 166 | OS="darwin" 167 | UNAME=$(uname -m) 168 | if [[ "${UNAME}" = "x86_64" ]]; then 169 | ARCH="amd64" 170 | else 171 | echo "This platform ${UNAME} is not supported by updater." 172 | exit 1 173 | fi 174 | elif [[ "${UNAME}" = "Linux" ]]; then 175 | OS="linux" 176 | UNAME=$(uname -m) 177 | if [[ "${UNAME}" = "x86_64" ]]; then 178 | ARCH="amd64" 179 | elif [[ "${UNAME}" = "armv6l" ]]; then 180 | ARCH="arm" 181 | elif [[ "${UNAME}" = "armv7l" ]]; then 182 | ARCH="arm" 183 | elif [[ "${UNAME}" = "aarch64" ]]; then 184 | ARCH="arm64" 185 | else 186 | echo "This platform ${UNAME} is not supported by updater." 187 | exit 1 188 | fi 189 | else 190 | echo "This operation system ${UNAME} is not supported by updater." 191 | exit 1 192 | fi 193 | UPDATER_FILENAME="install_stable_${OS}-${ARCH}_3.6.2.tar.gz" 194 | UPDATER_URL="https://github.com/algorand/go-algorand/releases/download/v3.6.2-stable/install_stable_${OS}-${ARCH}_3.6.2.tar.gz" 195 | } 196 | 197 | # check to see if the binary updater exists. if not, it will automatically the correct updater binary for the current platform 198 | function check_for_updater() { 199 | # check if the updater binary exist and is not empty. 200 | if [[ -s "${SCRIPTPATH}/updater" && -f "${SCRIPTPATH}/updater" ]]; then 201 | return 0 202 | fi 203 | get_updater_url 204 | 205 | # check the curl is available. 206 | CURL_VER=$(curl -V 2>/dev/null || true) 207 | if [ "${CURL_VER}" = "" ]; then 208 | # no curl is installed. 209 | echo "updater binary is missing and cannot be downloaded since curl is missing." 210 | if [[ "$(uname)" = "Linux" ]]; then 211 | echo "To install curl, run the following command:" 212 | echo "apt-get update; apt-get install -y curl" 213 | fi 214 | exit 1 215 | fi 216 | 217 | # create temporary directory for updater archive 218 | local UPDATER_TEMPDIR="" 219 | UPDATER_TEMPDIR="$(mktemp -d 2>/dev/null || mktemp -d -t "tmp")" 220 | 221 | local UPDATER_ARCHIVE="${UPDATER_TEMPDIR}/${UPDATER_FILENAME}" 222 | 223 | CURL_OUT=$(curl -sSL ${UPDATER_URL} -o "$UPDATER_ARCHIVE") 224 | if [ "$?" != "0" ]; then 225 | echo "failed to download updater binary from ${UPDATER_URL} using curl." 226 | echo "${CURL_OUT}" 227 | exit 1 228 | fi 229 | 230 | if [ ! -f "${UPDATER_ARCHIVE}" ]; then 231 | echo "downloaded file ${UPDATER_ARCHIVE} is missing." 232 | exit 233 | fi 234 | 235 | # extract and install updater 236 | tar -zxf "$UPDATER_ARCHIVE" -C "$UPDATER_TEMPDIR" updater 237 | mv "${UPDATER_TEMPDIR}/updater" "${SCRIPTPATH}" 238 | if [ "$?" != "0" ]; then 239 | echo "failed to extract updater binary from ${UPDATER_ARCHIVE}" 240 | exit 1 241 | fi 242 | 243 | # clean up temp directory 244 | rm -rf "$UPDATER_TEMPDIR" 245 | echo "updater binary was installed at ${SCRIPTPATH}/updater" 246 | } 247 | 248 | function check_for_update() { 249 | determine_current_version 250 | check_for_updater 251 | LATEST="$(${SCRIPTPATH}/updater ver check -c ${CHANNEL} ${BUCKET} | sed -n '2 p')" 252 | if [ $? -ne 0 ]; then 253 | echo "No remote updates found" 254 | return 1 255 | fi 256 | 257 | if [ -z ${LATEST} ]; then 258 | echo "Failed to lookup latest release" 259 | return 1 260 | fi 261 | 262 | echo "Latest Version = ${LATEST}" 263 | 264 | if [ ${CURRENTVER} -ge ${LATEST} ]; then 265 | if [ "${UPDATETYPE}" = "install" ]; then 266 | echo No new version found - forcing install anyway 267 | else 268 | echo No new version found 269 | return 1 270 | fi 271 | fi 272 | 273 | echo New version found 274 | return 0 275 | } 276 | 277 | function download_tools_update() { 278 | local TOOLS_SPECIFIC_VERSION=$1 279 | echo "downloading tools update ${TOOLS_SPECIFIC_VERSION}" 280 | TOOLS_TEMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t "tmp") 281 | export TOOLS_CLEANUP_UPDATE_TEMP_DIR=${TOOLS_TEMPDIR} 282 | trap "rm -rf ${TOOLS_CLEANUP_UPDATE_TEMP_DIR}" 0 283 | 284 | TOOLS_TARFILE=${TOOLS_TEMPDIR}/${LATEST}.tar.gz 285 | 286 | if ( ! "${SCRIPTPATH}"/updater gettools -c "${CHANNEL}" -o "${TOOLS_TARFILE}" "${BUCKET}" "${TOOLS_SPECIFIC_VERSION}" ) ; then 287 | echo "Error downloading tools tarfile" 288 | exit 1 289 | fi 290 | echo "Tools tarfile downloaded to ${TOOLS_TARFILE}" 291 | 292 | mkdir -p "${TOOLS_OUTPUT_DIR}" 293 | if ( ! tar -xf "${TOOLS_TARFILE}" -C "${TOOLS_OUTPUT_DIR}" ) ; then 294 | echo "Error extracting the tools update file ${TOOLS_TARFILE}" 295 | exit 1 296 | fi 297 | echo "Tools extracted to ${TOOLS_OUTPUT_DIR}" 298 | } 299 | 300 | TEMPDIR="" 301 | TARFILE="" 302 | UPDATESRCDIR="" 303 | 304 | function download_update() { 305 | SPECIFIC_VERSION=$1 306 | 307 | if [ -n "${TOOLS_OUTPUT_DIR}" ]; then 308 | download_tools_update "${SPECIFIC_VERSION}" 309 | fi 310 | 311 | TEMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t "tmp") 312 | export CLEANUP_UPDATE_TEMP_DIR=${TEMPDIR} 313 | trap "rm -rf ${CLEANUP_UPDATE_TEMP_DIR}" 0 314 | 315 | TARFILE=${TEMPDIR}/${LATEST}.tar.gz 316 | UPDATESRCDIR=${TEMPDIR}/a 317 | mkdir ${UPDATESRCDIR} 318 | 319 | ${SCRIPTPATH}/updater ver get -c ${CHANNEL} -o ${TARFILE} ${BUCKET} ${SPECIFIC_VERSION} 320 | 321 | if [ $? -ne 0 ]; then 322 | echo Error downloading update file 323 | exit 1 324 | fi 325 | echo Update Downloaded to ${TARFILE} 326 | } 327 | 328 | function check_and_download_update() { 329 | if ! check_for_update; then 330 | return 1 331 | fi 332 | 333 | download_update 334 | } 335 | 336 | function download_update_for_current_version() { 337 | determine_current_version 338 | echo "Downloading update package for current version ${CURRENTVER}..." 339 | download_update "-v ${CURRENTVER}" 340 | } 341 | 342 | function expand_update() { 343 | echo Expanding update... 344 | if ! tar -zxof "${TARFILE}" -C "${UPDATESRCDIR}"; then 345 | return 1 346 | fi 347 | validate_update 348 | } 349 | 350 | function validate_update() { 351 | echo Validating update... 352 | # We should consider including a version.info file 353 | # that we can compare against the expected version 354 | return 0 355 | } 356 | 357 | function check_service() { 358 | local service_type="$1" 359 | local dd="$2" 360 | local path 361 | 362 | if [ "$service_type" = "user" ]; then 363 | path=$(awk -F= '{ print $2 }' <(systemctl --user show -p FragmentPath "algorand@$(systemd-escape "$dd")")) 364 | else 365 | path=$(awk -F= '{ print $2 }' <(systemctl show -p FragmentPath "algorand@$(systemd-escape "$dd")")) 366 | fi 367 | 368 | if [ "$path" != "" ]; then 369 | return 0 370 | fi 371 | 372 | return 1 373 | } 374 | 375 | function run_systemd_action() { 376 | if [ "$(uname)" = "Darwin" ]; then 377 | return 1 378 | fi 379 | 380 | local action=$1 381 | local data_dir=$2 382 | local process_owner 383 | 384 | # If the service is system-level, check if it's root or sudo 385 | if check_service system "$data_dir"; then 386 | process_owner=$(awk '{ print $1 }' <(ps aux | grep "[a]lgod -d ${data_dir}")) 387 | if $IS_ROOT; then 388 | if systemctl "$action" "algorand@$(systemd-escape "$data_dir")"; then 389 | echo "systemd system service: $action" 390 | return 0 391 | fi 392 | elif grep sudo <(groups "$process_owner") &> /dev/null; then 393 | if sudo -n systemctl "$action" "algorand@$(systemd-escape "$data_dir")"; then 394 | echo "sudo -n systemd system service: $action" 395 | return 0 396 | fi 397 | fi 398 | 399 | # If the service is user-level then run systemctl --user 400 | elif check_service user "$data_dir"; then 401 | if systemctl --user "$action" "algorand@$(systemd-escape "${data_dir}")"; then 402 | echo "systemd user service: $action" 403 | return 0 404 | fi 405 | fi 406 | 407 | return 1 408 | } 409 | 410 | function backup_binaries() { 411 | echo Backing up current binary files... 412 | mkdir -p "${BINDIR}/backup" 413 | BACKUPFILES="algod kmd carpenter doberman goal update.sh updater diagcfg" 414 | # add node_exporter to the files list we're going to backup, but only we if had it previously deployed. 415 | [ -f "${BINDIR}/node_exporter" ] && BACKUPFILES="${BACKUPFILES} node_exporter" 416 | tar -zcf "${BINDIR}/backup/bin-v${CURRENTVER}.tar.gz" -C "${BINDIR}" ${BACKUPFILES} >/dev/null 2>&1 417 | } 418 | 419 | function backup_data() { 420 | CURDATADIR=$1 421 | BACKUPDIR="${CURDATADIR}/backup" 422 | 423 | echo "Backing up current data files from ${CURDATADIR}..." 424 | mkdir -p "${BACKUPDIR}" 425 | BACKUPFILES="genesis.json wallet-genesis.id" 426 | tar --no-recursion --exclude='*.log' --exclude='*.log.archive' --exclude='*.tar.gz' -zcf "${BACKUPDIR}/data-v${CURRENTVER}.tar.gz" -C "${CURDATADIR}" ${BACKUPFILES} >/dev/null 2>&1 427 | } 428 | 429 | function backup_current_version() { 430 | backup_binaries 431 | for DD in ${DATADIRS[@]}; do 432 | backup_data "${DD}" 433 | done 434 | } 435 | 436 | function rollback_binaries() { 437 | echo "Rolling back binary files..." 438 | tar -zxof ${BINDIR}/backup/bin-v${CURRENTVER}.tar.gz -C ${BINDIR} 439 | } 440 | 441 | function rollback_data() { 442 | CURDATADIR=$1 443 | BACKUPDIR="${CURDATADIR}/backup" 444 | 445 | echo "Rolling back data files in ${CURDATADIR}..." 446 | rm ${CURDATADIR}/wallet-genesis.id 447 | tar -zxof ${BACKUPDIR}/data-v${CURRENTVER}.tar.gz -C ${CURDATADIR} 448 | } 449 | 450 | function install_new_binaries() { 451 | if [ ! -d ${UPDATESRCDIR}/bin ]; then 452 | return 0 453 | else 454 | echo Installing new binary files... 455 | ROLLBACKBIN=1 456 | rm -rf ${BINDIR}/new 457 | mkdir ${BINDIR}/new 458 | cp ${UPDATESRCDIR}/bin/* ${BINDIR}/new 459 | mv ${BINDIR}/new/* ${BINDIR} 460 | rm -rf ${BINDIR}/new 461 | fi 462 | } 463 | 464 | function reset_wallets_for_new_ledger() { 465 | CURDATADIR=$1 466 | 467 | echo "New Ledger - restoring genesis accounts in ${CURDATADIR}" 468 | pushd ${CURDATADIR} >/dev/null 469 | mkdir -p "${NEW_VER}" 470 | for file in *.partkey *.rootkey; do 471 | if [ -e "${file}" ]; then 472 | cp "${file}" "${NEW_VER}/${file}" 473 | echo 'Installed genesis account file: ' "${file}" 474 | fi 475 | done 476 | popd >/dev/null 477 | } 478 | 479 | function import_rootkeys() { 480 | CURDATADIR=$1 481 | 482 | echo "New Ledger - importing rootkeys for genesis accounts" 483 | ${BINDIR}/goal account importrootkey -u -d ${CURDATADIR} 484 | } 485 | 486 | function install_new_data() { 487 | if [ ! -d ${UPDATESRCDIR}/data ]; then 488 | return 0 489 | else 490 | CURDATADIR=$1 491 | echo "Installing new data files into ${CURDATADIR}..." 492 | ROLLBACKDATA+=(${CURDATADIR}) 493 | cp "${UPDATESRCDIR}/data/"* "${CURDATADIR}" 494 | fi 495 | } 496 | 497 | function copy_genesis_files() { 498 | echo "Copying genesis files locally" 499 | cp -rf ${UPDATESRCDIR}/genesis/ ${BINDIR}/genesisfiles/ 500 | } 501 | 502 | function check_for_new_ledger() { 503 | CURDATADIR=$1 504 | echo "Checking for new ledger in ${CURDATADIR}" 505 | EXISTING_VER=$(${UPDATESRCDIR}/bin/algod -d ${CURDATADIR} -g ${CURDATADIR}/genesis.json -G) 506 | 507 | if [ -z $EXISTING_VER ]; then 508 | if [ -z ${GENESIS_NETWORK_DIR} ]; then 509 | echo "Updating genesis files for default network" 510 | else 511 | echo "Installing genesis files for network ${GENESIS_NETWORK_DIR}" 512 | fi 513 | else 514 | GENESIS_SPLIT=(${EXISTING_VER//-/ }) 515 | GENESIS_NETWORK_DIR=${GENESIS_SPLIT[0]} 516 | echo "Updating genesis files for network ${GENESIS_NETWORK_DIR}" 517 | 518 | # If that genesis dir doesn't exist, use the default file - this is likely a custom network build 519 | if [ ! -d ${UPDATESRCDIR}/genesis/${GENESIS_NETWORK_DIR} ]; then 520 | GENESIS_NETWORK_DIR="" 521 | fi 522 | fi 523 | 524 | NEW_VER=$(${UPDATESRCDIR}/bin/algod -d ${CURDATADIR} -g ${UPDATESRCDIR}/genesis/${GENESIS_NETWORK_DIR}/genesis.json -G) 525 | if [ $? -ne 0 ]; then 526 | echo "Cannot determine new genesis ID. Not updating. This may be a problem!" 527 | return 1 528 | fi 529 | 530 | # Copy new genesis.json even if version didn't change; we might have 531 | # changed the file itself in a compatible way. 532 | cp ${UPDATESRCDIR}/genesis/${GENESIS_NETWORK_DIR}/genesis.json ${CURDATADIR} 533 | 534 | echo ${NEW_VER} > ${CURDATADIR}/wallet-genesis.id 535 | if [ "${NEW_VER}" != "${EXISTING_VER}" ]; then 536 | echo "New genesis ID, resetting wallets" 537 | NEW_LEDGER=1 538 | reset_wallets_for_new_ledger ${CURDATADIR} 539 | 540 | import_rootkeys ${CURDATADIR} 541 | fi 542 | } 543 | 544 | # Delete all logs. 545 | function clean_legacy_logs() { 546 | CURDATADIR=$1 547 | 548 | echo "Deleting existing log files in ${CURDATADIR}" 549 | rm -f ${CURDATADIR}/node-*.log 550 | rm -f ${CURDATADIR}/node-*.log.archive 551 | return 0 552 | } 553 | 554 | function startup_node() { 555 | if [ "${NOSTART}" != "" ]; then 556 | echo Auto-start node disabled - not starting 557 | return 558 | fi 559 | 560 | CURDATADIR=$1 561 | echo Restarting node in ${CURDATADIR}... 562 | 563 | check_install_valid 564 | if [ $? -ne 0 ]; then 565 | fail_and_exit "Installation does not appear to be valid" 566 | fi 567 | 568 | if ! run_systemd_action restart "${CURDATADIR}"; then 569 | echo "No systemd services, restarting node with goal." 570 | ${BINDIR}/goal node restart -d "${CURDATADIR}" ${HOSTEDFLAG} 571 | fi 572 | } 573 | 574 | function startup_nodes() { 575 | for DD in ${DATADIRS[@]}; do 576 | startup_node ${DD} 577 | done 578 | } 579 | 580 | function rollback() { 581 | echo Rolling back from failed update... 582 | if [ ${ROLLBACKBIN} -ne 0 ]; then 583 | rollback_binaries 584 | fi 585 | for ROLLBACKDIR in ${ROLLBACKDATA[@]}; do 586 | rollback_data ${ROLLBACKDIR} 587 | done 588 | } 589 | 590 | function fail_and_exit() { 591 | echo "*** UPDATE FAILED: $1 ***" 592 | if [ ${ROLLBACK} -ne 0 ]; then 593 | ROLLBACK=0 594 | rollback 595 | check_install_valid 596 | if [ ${RESTART_NODE} -ne 0 ]; then 597 | startup_nodes 598 | fi 599 | exit 0 600 | fi 601 | exit 1 602 | } 603 | 604 | function apply_fixups() { 605 | echo "Applying migration fixups..." 606 | 607 | # Delete obsolete algorand binary - renamed to 'goal' 608 | rm "${BINDIR}/algorand" >/dev/null 2>&1 609 | 610 | for DD in ${DATADIRS[@]}; do 611 | clean_legacy_logs "${DD}" 612 | 613 | # Purge obsolete cadaver files (now agreement.cdv[.archive]) 614 | rm -f "${DD}"/service*.cadaver 615 | done 616 | } 617 | 618 | #-------------------------------------------- 619 | # Main Update Driver 620 | 621 | # Need to verify the bindir was specified (with -p) 622 | # and that it's a valid directory. 623 | # Unless it's an install 624 | if [ ! -d "${BINDIR}" ]; then 625 | if [ "${UPDATETYPE}" = "install" ]; then 626 | mkdir -p "${BINDIR}" 627 | else 628 | fail_and_exit "Missing or invalid binaries path specified '${BINDIR}'" 629 | fi 630 | fi 631 | 632 | if [ "${UPDATETYPE}" != "install" ]; then 633 | if ! check_install_valid; then 634 | echo "Unable to perform an update - installation does not appear valid" 635 | exit 1 636 | fi 637 | fi 638 | 639 | # If we're initiating an update/install, check for an update and if we have a new one, 640 | # expand it and invoke the new update.sh script. 641 | if [ ${RESUME_INSTALL} -eq 0 ] && ! $DRYRUN; then 642 | validate_channel_specified 643 | 644 | if [ "${UPDATETYPE}" = "migrate" ]; then 645 | download_update_for_current_version 646 | else 647 | check_and_download_update 648 | fi 649 | 650 | if [ $? -ne 0 ]; then 651 | # No update - stop here 652 | exit $? 653 | fi 654 | 655 | if ! expand_update; then 656 | fail_and_exit "Error expanding update" 657 | fi 658 | 659 | # Spawn the new update script and exit - this allows us to push update.sh changes that take effect immediately 660 | # Note that the SCRIPTPATH we're passing in should be our binaries directory, which is what we expect to be 661 | # passed as the last argument (if any) 662 | echo "Starting the new update script to complete the installation..." 663 | exec "${UPDATESRCDIR}/bin/${FILENAME}" ${INSTALLOPT} -r -c ${CHANNEL} ${DATADIRSPEC} ${NOSTART} ${BINDIRSPEC} ${HOSTEDSPEC} ${GENESIS_NETWORK_DIR_SPEC} ${UNKNOWNARGS[@]} 664 | 665 | # If we're still here, exec failed. 666 | fail_and_exit "Error executing the new update script - unable to continue" 667 | else 668 | # We're running the script from our expanded update, which is located in the last script's ${TEMPDIR}/a/bin 669 | # We need to define our TEMPDIR and UPDATESRCDIR to match those values; we do so by making them relative 670 | # to where our resuming script lives. 671 | TEMPDIR=${SCRIPTPATH}/../.. 672 | UPDATESRCDIR=${SCRIPTPATH}/.. 673 | echo "... Resuming installation from the latest update script" 674 | 675 | determine_current_version 676 | fi 677 | 678 | # Any fail_and_exit beyond this point will run a restart 679 | RESTART_NODE=1 680 | 681 | if ! $DRYRUN; then 682 | if [ ${SKIP_UPDATE} -eq 0 ]; then 683 | backup_current_version 684 | fi 685 | 686 | # We don't care about return code - doesn't matter if we failed to archive 687 | 688 | ROLLBACK=1 689 | 690 | if ! install_new_binaries; then 691 | fail_and_exit "Error installing new files" 692 | fi 693 | 694 | for DD in ${DATADIRS[@]}; do 695 | if ! install_new_data "${DD}"; then 696 | fail_and_exit "Error installing data files into ${DD}" 697 | fi 698 | done 699 | 700 | copy_genesis_files 701 | 702 | for DD in ${DATADIRS[@]}; do 703 | if ! check_for_new_ledger "${DD}"; then 704 | fail_and_exit "Error updating ledger in ${DD}" 705 | fi 706 | done 707 | 708 | if [ "${TESTROLLBACK}" != "" ]; then 709 | fail_and_exit "Simulating update failure - rolling back" 710 | fi 711 | 712 | apply_fixups 713 | fi 714 | 715 | if [ "${NOSTART}" != "" ]; then 716 | echo "Install complete - restart node manually" 717 | else 718 | startup_nodes 719 | fi 720 | 721 | exit 0 722 | -------------------------------------------------------------------------------- /images/conduit/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.23.3 2 | FROM golang:$GO_VERSION-alpine 3 | 4 | # Environment variables used by install.sh 5 | ARG URL=https://github.com/algorand/conduit 6 | ARG BRANCH=master 7 | ARG SHA="" 8 | 9 | ENV HOME /opt/conduit 10 | WORKDIR /opt/conduit 11 | 12 | ENV DEBIAN_FRONTEND noninteractive 13 | RUN apk add --no-cache git make bash 14 | 15 | # Copy files to container. 16 | COPY images/conduit/disabled.go /tmp/disabled.go 17 | COPY images/conduit/start.sh /tmp/start.sh 18 | COPY images/conduit/install.sh /tmp/install.sh 19 | 20 | # Install conduit binaries. 21 | RUN /tmp/install.sh 22 | 23 | CMD ["/tmp/start.sh"] 24 | -------------------------------------------------------------------------------- /images/conduit/disabled.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | 11 | func main() { 12 | var port int 13 | var code int 14 | var message string 15 | 16 | flag.IntVar(&port, "port", 8980, "port to start the server on.") 17 | flag.IntVar(&code, "code", 200, "response code to use.") 18 | flag.StringVar(&message, "message", "this is all that happens", "response message to display.") 19 | 20 | flag.Parse() 21 | 22 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){ 23 | w.WriteHeader(code) 24 | fmt.Fprintf(w, "%s\n", message) 25 | }) 26 | 27 | 28 | fmt.Printf("Starting server at port %d\nResponse code (%d)\nmessage (%s)\n", port, code, message) 29 | if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil { 30 | fmt.Fprintf(os.Stderr, err.Error()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /images/conduit/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Build conduit and put binary in /tmp. 4 | # 5 | # Configured with environment variables: 6 | # URL - Git repository URL. 7 | # BRANCH - Git branch to clone. 8 | # SHA - (optional) Specific commit hash to checkout. 9 | set -e 10 | 11 | START=$(date "+%s") 12 | THIS=$(basename "$0") 13 | 14 | echo "$THIS: starting conduit image install" 15 | 16 | # Sometimes conduit is disabled, detect the missing build config. 17 | if [ -z "${BRANCH}" ] || [ -z "${URL}" ]; then 18 | echo "Missing BRANCH or URL environment variable. Skipping install." 19 | # returning with 0 because it will run the disabled server. 20 | exit 0 21 | fi 22 | 23 | git clone --single-branch --branch "${BRANCH}" "${URL}" /opt/conduit 24 | if [ "${SHA}" != "" ]; then 25 | echo "Checking out ${SHA}" 26 | git checkout "${SHA}"; 27 | fi 28 | make 29 | cp cmd/conduit/conduit /tmp 30 | 31 | echo "$THIS: seconds it took to get to finish conduit image install: $(($(date "+%s") - START))s" 32 | -------------------------------------------------------------------------------- /images/conduit/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Start conduit daemon. There are various configurations controlled by 4 | # environment variables. 5 | # 6 | # Configuration: 7 | # DISABLED - If set start a server that returns an error instead of conduit. 8 | # CONNECTION_STRING - the postgres connection string to use. 9 | # ALGOD_ADDR - host:port to connect to for algod follower. 10 | # ALGOD_ADMIN_TOKEN - the algod admin token. 11 | # PORT - port to start conduit on. 12 | set -e 13 | 14 | THIS=$(basename "$0") 15 | 16 | disabled() { 17 | echo "$THIS: running disabled.go script in lieu of conduit" 18 | go run /tmp/disabled.go -port "$PORT" -code 200 -message "Conduit disabled for this configuration." 19 | } 20 | 21 | echo "$THIS: starting conduit container script" 22 | 23 | # Make sure data directory is available in case we're using a version that requires it. 24 | export CONDUIT_DATA=/tmp/conduit-data 25 | mkdir -p ${CONDUIT_DATA} 26 | 27 | if [ -n "$DISABLED" ]; then 28 | disabled 29 | elif [ ! -f /tmp/conduit ]; then 30 | echo "$THIS: binary not found at /tmp/conduit" 31 | exit 1 32 | else 33 | /tmp/conduit init --importer algod --exporter postgresql > "${CONDUIT_DATA}"/conduit.yaml 34 | sed -i \ 35 | -e "s/netaddr: \".*\"/netaddr: \"$ALGOD_ADDR\"/" \ 36 | -e "s/token: \".*\"/token: \"$ALGOD_ADMIN_TOKEN\"/" \ 37 | -e "s/addr: \":9999\"/addr: \":$PORT\"/" \ 38 | -e "s/mode: OFF/mode: ON/" \ 39 | -e "s/host= port=5432 user= password= dbname=/$CONNECTION_STRING/" \ 40 | -e "s/retry-delay: \"1s\"/retry-delay: \"0s\"/" \ 41 | "${CONDUIT_DATA}"/conduit.yaml 42 | 43 | cat "${CONDUIT_DATA}"/conduit.yaml 44 | 45 | /tmp/conduit -d "${CONDUIT_DATA}" 46 | fi 47 | -------------------------------------------------------------------------------- /images/indexer/IndexerDockerfile: -------------------------------------------------------------------------------- 1 | ARG GO_VERSION=1.23.3 2 | FROM golang:$GO_VERSION-alpine 3 | 4 | # Environment variables used by install.sh 5 | ARG URL=https://github.com/algorand/indexer 6 | ARG BRANCH=main 7 | ARG SHA="" 8 | 9 | ENV HOME /opt/indexer 10 | WORKDIR /opt/indexer 11 | 12 | ENV DEBIAN_FRONTEND noninteractive 13 | RUN apk add --no-cache git make bash 14 | 15 | # Copy files to container. 16 | COPY images/indexer/disabled.go /tmp/disabled.go 17 | COPY images/indexer/start.sh /tmp/start.sh 18 | COPY images/indexer/install.sh /tmp/install.sh 19 | 20 | # Install indexer binaries. 21 | RUN /tmp/install.sh 22 | 23 | CMD ["/tmp/start.sh"] 24 | -------------------------------------------------------------------------------- /images/indexer/disabled.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | 11 | func main() { 12 | var port int 13 | var code int 14 | var message string 15 | 16 | flag.IntVar(&port, "port", 8980, "port to start the server on.") 17 | flag.IntVar(&code, "code", 200, "response code to use.") 18 | flag.StringVar(&message, "message", "this is all that happens", "response message to display.") 19 | 20 | flag.Parse() 21 | 22 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){ 23 | w.WriteHeader(code) 24 | fmt.Fprintf(w, "%s\n", message) 25 | }) 26 | 27 | 28 | fmt.Printf("Starting server at port %d\nResponse code (%d)\nmessage (%s)\n", port, code, message) 29 | if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil { 30 | fmt.Fprintf(os.Stderr, err.Error()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /images/indexer/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Build indexer and put binary in /tmp. 4 | # 5 | # Configured with environment variables: 6 | # URL - Git repository URL. 7 | # BRANCH - Git branch to clone. 8 | # SHA - (optional) Specific commit hash to checkout. 9 | set -e 10 | 11 | START=$(date "+%s") 12 | THIS=$(basename "$0") 13 | 14 | echo "$THIS: starting indexer image install" 15 | 16 | # Sometimes indexer is disabled, detect the missing build config. 17 | if [ -z "${BRANCH}" ] || [ -z "${URL}" ]; then 18 | echo "Missing BRANCH or URL environment variable. Skipping install." 19 | # returning with 0 because it will run the disabled server. 20 | exit 0 21 | fi 22 | 23 | git clone --single-branch --branch "${BRANCH}" "${URL}" /opt/indexer 24 | if [ "${SHA}" != "" ]; then 25 | echo "Checking out ${SHA}" 26 | git checkout "${SHA}"; 27 | fi 28 | make 29 | cp cmd/algorand-indexer/algorand-indexer /tmp 30 | 31 | echo "$THIS: seconds it took to get to finish indexer image install: $(($(date "+%s") - START))s" 32 | -------------------------------------------------------------------------------- /images/indexer/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Start indexer daemon. There are various configurations controlled by 4 | # environment variables. 5 | # 6 | # Configuration: 7 | # DISABLED - If set start a server that returns an error instead of indexer. 8 | # CONNECTION_STRING - the postgres connection string to use. 9 | # PORT - port to start indexer on. 10 | set -e 11 | 12 | THIS=$(basename "$0") 13 | 14 | disabled() { 15 | echo "$THIS: running disabled.go script in lieu of indexer" 16 | go run /tmp/disabled.go -port "$PORT" -code 200 -message "Indexer disabled for this configuration." 17 | } 18 | 19 | echo "$THIS: starting indexer container script" 20 | 21 | # Make sure data directory is available in case we're using a version that requires it. 22 | export INDEXER_DATA=/tmp/indexer-data 23 | mkdir -p ${INDEXER_DATA} 24 | 25 | if [ -n "$DISABLED" ]; then 26 | disabled 27 | elif [ ! -f /tmp/algorand-indexer ]; then 28 | echo "$THIS: binary not found at /tmp/algorand-indexer" 29 | exit 1 30 | else 31 | /tmp/algorand-indexer daemon \ 32 | --dev-mode \ 33 | --enable-private-network-access-header \ 34 | --server ":$PORT" \ 35 | -P "$CONNECTION_STRING" 36 | fi 37 | 38 | sleep infinity 39 | -------------------------------------------------------------------------------- /sandbox: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | ##################### 5 | # Script constants. # 6 | ##################### 7 | DEFAULT_CONFIG='release' 8 | SANDBOX_DIR=$(dirname "$0") 9 | source "$SANDBOX_DIR/.env" 10 | CLEAN_FILE="$SANDBOX_DIR/.clean" 11 | ACTIVE_CONFIG_FILE="$SANDBOX_DIR/.active_config" 12 | SANDBOX_LOG="$SANDBOX_DIR/sandbox.log" 13 | FAST_CATCHUP_URL='https://algorand-catchpoints.s3.us-east-2.amazonaws.com/channel/CHANNEL/latest.catchpoint' 14 | 15 | APORT="${ALGOD_PORT:-4001}" 16 | KPORT="${KMD_PORT:-4002}" 17 | IPORT="${INDEXER_PORT:-8980}" 18 | CPORT="${CONDUIT_PORT:-3998}" 19 | 20 | # Global flags 21 | USE_FAST_CATCHUP=1 22 | INTERACTIVE_MODE=0 23 | VERBOSE_MODE=0 24 | 25 | ######################### 26 | # Config file variables # 27 | ######################### 28 | export ALGOD_CHANNEL="" 29 | export ALGOD_URL="" 30 | export ALGOD_BRANCH="" 31 | export ALGOD_SHA="" 32 | export NETWORK="" 33 | export NETWORK_BOOTSTRAP_URL="" 34 | export NETWORK_GENESIS_FILE="" 35 | export NODE_ARCHIVAL="" 36 | export INDEXER_URL="" 37 | export INDEXER_BRANCH="" 38 | export INDEXER_SHA="" 39 | export INDEXER_DISABLED="" 40 | export CONDUIT_URL="" 41 | export CONDUIT_BRANCH="" 42 | export CONDUIT_SHA="" 43 | export CONDUIT_DISABLED="" 44 | 45 | ################################################## 46 | # Determine the correct docker command (or fail) # 47 | ################################################## 48 | if [ -x "$(command -v docker-compose)" ]; then 49 | DOCKER_COMPOSE="docker-compose" 50 | elif [ "$(docker compose --help &>/dev/null; echo "$?")" -eq 0 ]; then 51 | DOCKER_COMPOSE="docker compose" 52 | else 53 | echo 'Error: docker compose is not installed.' >&2 54 | exit 1 55 | fi 56 | 57 | ###################################### 58 | # Compatibility with Windows / MSYS2 # 59 | ###################################### 60 | 61 | # All commands that use a TTY/pseudo-TTY 62 | # need to be prefixed by "$WINDOWS_PTY_PREFIX" 63 | WINDOWS_PTY_PREFIX= 64 | if [ "$(uname)" == "Darwin" ]; then 65 | true 66 | elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ] || \ 67 | [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then 68 | WINDOWS_PTY_PREFIX="winpty" 69 | fi 70 | 71 | ######################### 72 | # Helpers and utilities # 73 | ######################### 74 | 75 | # Console colorized print helpers 76 | default="\033[0m" 77 | 78 | red="\033[0;31m" 79 | green="\033[0;32m" 80 | blue="\033[0;34m" 81 | teal="\033[0;36m" 82 | 83 | # bold 84 | Bgreen="\033[1;32m" 85 | 86 | 87 | function printc () { 88 | printf "$1$2${default}\n" 89 | } 90 | 91 | function statusline () { 92 | printc "${Bgreen}" "\n$1" 93 | } 94 | 95 | function err_noexit () { 96 | printf "${red}$1${default}\n" 97 | } 98 | 99 | function err () { 100 | err_noexit "$1" 101 | exit 1 102 | } 103 | 104 | # Overwrite the current line on the terminal 105 | function overwrite() { 106 | echo -e "\r\033[1A\033[0K$@"; 107 | } 108 | 109 | # Yes/no prompt around the clean command 110 | function ask_clean () { 111 | if ask "$1" "Y"; then 112 | sandbox clean 113 | else 114 | exit 1 115 | fi 116 | } 117 | 118 | # Interactive yes/no prompt 119 | function ask () { 120 | # https://djm.me/ask 121 | local prompt default reply 122 | 123 | if [ "${2:-}" = "Y" ]; then 124 | prompt="Y/n" 125 | default=Y 126 | elif [ "${2:-}" = "N" ]; then 127 | prompt="y/N" 128 | default=N 129 | else 130 | prompt="y/n" 131 | default= 132 | fi 133 | 134 | while true; do 135 | 136 | # Ask the question (not using "read -p" as it uses stderr not stdout) 137 | echo -n "$1 [$prompt] " 138 | 139 | # Read the answer (use /dev/tty in case stdin is redirected from somewhere else) 140 | read reply /dev/null 2>&1 || true 463 | echo 'clean function executed' > "$CLEAN_FILE"; 464 | } 465 | 466 | # Enter attaches users to a shell in the desired container 467 | enter () { 468 | CONTAINER=${2:-} 469 | if [ -z "$CONTAINER" ]; then 470 | err "'enter' requires a container. Available containers: algod, conduit, indexer, indexer-db" 471 | fi 472 | case $CONTAINER in 473 | algod|indexer|conduit) 474 | statusline "Entering /bin/bash session in the $CONTAINER container..." 475 | dc_pty exec $CONTAINER //bin/bash 476 | return 477 | ;; 478 | indexer-db) 479 | statusline "Entering psql session in the indexer-db container..." 480 | dc_pty exec indexer-db psql -U algorand -d indexer_db 481 | return 482 | ;; 483 | esac 484 | 485 | err "Cannot enter '$CONTAINER'. Available containers: algod, indexer, indexer-db" 486 | } 487 | 488 | 489 | # Logs streams the logs from the container to the shell 490 | logs () { 491 | if [[ $# -gt 1 && $2 == "raw" ]]; then 492 | dc exec -T algod tail -f node.log 493 | else 494 | # We need a PTY with carpenter to have colors 495 | dc_pty exec algod carpenter -D 496 | fi 497 | } 498 | 499 | # One-time dump of logs of a particular service to the shell 500 | dump() { 501 | case $2 in 502 | algod|indexer|conduit|indexer-db) 503 | dc logs "$2" 504 | ;; 505 | 506 | *) 507 | err "Cannot dump '$2'. Available containers: algod, conduit, indexer, indexer-db" 508 | ;; 509 | esac 510 | } 511 | 512 | tail_f() { 513 | case $2 in 514 | algod|indexer|conduit|indexer-db) 515 | dc logs --follow "$2" 516 | ;; 517 | 518 | *) 519 | err "Cannot tail '$2'. Available containers: algod, conduit, indexer, indexer-db" 520 | ;; 521 | esac 522 | } 523 | 524 | set_catchpoint () { 525 | # TODO: Might be useful to allow providing the catchpoint with '-c' 526 | CATCHPOINT=$(curl -s ${FAST_CATCHUP_URL/CHANNEL/$1}) 527 | # If the catchpoint wasn't returned there is a multiline error. 528 | if [[ "$(echo $CATCHPOINT | wc -l | tr -d ' ')" != "1" ]]; then 529 | CATCHPOINT="" 530 | fi 531 | } 532 | 533 | # Start the algorand node 534 | up () { 535 | FRESH_INSTALL=1 536 | 537 | # Grab active config if there is one 538 | ACTIVE_CONFIG="" 539 | if [ -f "$ACTIVE_CONFIG_FILE" ]; then 540 | ACTIVE_CONFIG=$(cat $ACTIVE_CONFIG_FILE) 541 | fi 542 | 543 | # Initialize new config, accounting for no-argument up command. 544 | if [ "$1" = "" ]; then 545 | if [ ! -z $ACTIVE_CONFIG ]; then 546 | statusline "Bringing up existing sandbox: '$ACTIVE_CONFIG'" 547 | FRESH_INSTALL=0 548 | NEW_CONFIG="$ACTIVE_CONFIG" 549 | else 550 | statusline "Starting default sandbox: $DEFAULT_CONFIG" 551 | NEW_CONFIG="$DEFAULT_CONFIG" 552 | fi 553 | else 554 | statusline "Starting sandbox for: $1" 555 | NEW_CONFIG="$1" 556 | fi 557 | CONFIG_FILE="$SANDBOX_DIR/config.$NEW_CONFIG" 558 | 559 | # Verify config exists 560 | if [ ! -f "$CONFIG_FILE" ]; then 561 | SANDBOX_CONFIG_OPTIONS=$(ls "$SANDBOX_DIR"/config.* | sed 's/^.*config\./ /'| paste -sd',' -) 562 | err "Could not find config file for '$NEW_CONFIG'.\nValid options:$SANDBOX_CONFIG_OPTIONS" 563 | fi 564 | 565 | # Handle mismatched argument + active config 566 | if [ ! -z "$ACTIVE_CONFIG" ] && [ "$NEW_CONFIG" != "$ACTIVE_CONFIG" ]; then 567 | err_noexit "Sandbox was already started for '$ACTIVE_CONFIG'." 568 | ask_clean "Would you like to reset the local sandbox with '$NEW_CONFIG'?" 569 | # If we get here the active config was cleared out. 570 | up "$@" 571 | return 572 | fi 573 | 574 | ################# 575 | # START NETWORK # 576 | ################# 577 | 578 | # network configured with the environment exported by $CONFIG_FILE 579 | echo "$NEW_CONFIG" > "$ACTIVE_CONFIG_FILE" 580 | source "$CONFIG_FILE" 581 | if [ $INTERACTIVE_MODE == 1 ]; then 582 | rebuild_if_needed 583 | dc up 584 | elif [ $VERBOSE_MODE == 0 ]; then 585 | echo "see sandbox.log for detailed progress, or use -v." 586 | echo "" # The spinner will rewrite this line. 587 | rebuild_if_needed >> "$SANDBOX_LOG" 2>&1 & spinner 588 | echo "* docker compose up -d" >> "$SANDBOX_LOG" 589 | dc up -d >> "$SANDBOX_LOG" 2>&1 & spinner 590 | overwrite "* docker containers started!" 591 | else 592 | rebuild_if_needed 593 | echo "* running: docker compose up [--verbose] -d" 594 | dc up -d 595 | fi 596 | 597 | echo -e "* waiting for services to initialize." 598 | wait_for_services 599 | echo "* services ready!" 600 | 601 | version_helper 602 | status_helper 603 | 604 | if [ -z $NETWORK_GENESIS_FILE ]; then 605 | ##################### 606 | # PRINT WALLET INFO # 607 | ##################### 608 | goal_helper wallet -f unencrypted-default-wallet > /dev/null 2>&1 609 | 610 | ACCOUNTS_OUTPUT=$(goal_helper account list) 611 | for acct in $(echo "$ACCOUNTS_OUTPUT" | cut -f 3 |tr -s ' '); do 612 | ACCOUNTS+=($acct) 613 | done 614 | 615 | statusline "Available accounts" 616 | printc $default "~$ ${blue}./sandbox ${teal}goal account list" 617 | echo "$ACCOUNTS_OUTPUT" 618 | statusline "Example command to send between two accounts:" 619 | printc $default "~$ ${blue}./sandbox ${teal}goal clerk send -a 123456789 -f ${ACCOUNTS[1]} -t ${ACCOUNTS[2]}" 620 | statusline "Soon after sending the transaction it will appear in indexer:" 621 | printc $default "~$ ${blue}curl ${teal}\"localhost:$IPORT/v2/transactions?pretty\"" 622 | else 623 | ################################ 624 | # FAST CATCHUP (if applicable) # 625 | ################################ 626 | if [ $USE_FAST_CATCHUP == 1 ] && [ $FRESH_INSTALL == 1 ] && [ ! -z "$NETWORK" ]; then 627 | set_catchpoint $NETWORK 628 | 629 | if [ -z $CATCHPOINT ]; then 630 | err_noexit "Fast catchup is not available for $NETWORK, continuing without catchup." 631 | else 632 | statusline "Starting fast-catchup with catchpoint: $CATCHPOINT" 633 | 634 | perform_fast_catchup $CATCHPOINT 635 | 636 | statusline "Fast-catchup complete! Printing status..." 637 | status_helper 638 | fi 639 | else 640 | statusline "Skipping fast catchup" 641 | fi 642 | fi 643 | } 644 | 645 | help () { 646 | cat <<-EOF 647 | sandbox commands: 648 | up [config] -> start the sandbox environment. 649 | down -> tear down the sandbox environment. 650 | reset -> reset the containers to their initial state. 651 | clean -> stops and deletes containers and data directory. 652 | test -> runs some tests to demonstrate usage. 653 | enter [algod||conduit||indexer||indexer-db] 654 | -> enter the sandbox container. 655 | dump [algod||conduit||indexer||indexer-db] 656 | -> dump log information for a container. 657 | tail [algod||conduit||indexer||indexer-db] 658 | -> tail log information for a container. 659 | version -> print binary versions. 660 | copyTo -> copy into the algod. Useful for offline transactions, offline LogicSigs & TEAL work. 661 | copyFrom -> copy from the algod. Useful for offline transactions, offline LogicSigs & TEAL work. 662 | 663 | algorand commands: 664 | logs -> stream algorand logs with the carpenter utility. 665 | status -> get node status. 666 | goal (args) -> run goal command like 'goal node status'. 667 | tealdbg (args) -> run tealdbg command. 668 | 669 | special flags for 'up' command: 670 | -v|--verbose -> display verbose output when starting standbox. 671 | -s|--skip-fast-catchup -> skip catchup when connecting to real network. 672 | -i|--interactive -> start docker compose in interactive mode. 673 | EOF 674 | } 675 | 676 | if [ $# -eq 0 ]; then 677 | help 678 | exit 1 679 | fi 680 | 681 | case $1 in 682 | start|up|resume) 683 | # Remove "up" 684 | shift 685 | 686 | # Process flags 687 | PARAMS=() 688 | while (( "$#" )); do 689 | case "$1" in 690 | -v|--verbose) 691 | VERBOSE_MODE=1 692 | ;; 693 | -s|--skip-fast-catchup) 694 | USE_FAST_CATCHUP=0 695 | ;; 696 | -i|--interactive) 697 | statusline "Note: interactive mode is incompatible with fast-catchup." 698 | INTERACTIVE_MODE=1 699 | ;; 700 | *) # preserve positional arguments 701 | PARAMS+=("$1") 702 | ;; 703 | esac 704 | shift 705 | done 706 | 707 | # Call up with remaining parameters 708 | up "${PARAMS[@]-}" 709 | ;; 710 | 711 | stop|down|pause) 712 | statusline "Stopping sandbox containers..." 713 | dc stop -t 0 714 | ;; 715 | 716 | restart|reset) 717 | # Make sure fast-catchup runs when resetting a real network. 718 | if [ -f "$ACTIVE_CONFIG_FILE" ]; then 719 | ACTIVE_CONFIG=$(cat $ACTIVE_CONFIG_FILE) 720 | # up only runs fast-catchup for fresh installs. 721 | # removing the active config file will trick it. 722 | rm "$ACTIVE_CONFIG_FILE" > /dev/null 2>&1 || true 723 | else 724 | err "No active sandbox to reset." 725 | fi 726 | sandbox down 727 | dc rm -f 728 | sandbox up "$ACTIVE_CONFIG" "$@" 729 | ;; 730 | 731 | clean) 732 | statusline "Cleaning up sandbox environment..." 733 | clean >> "$SANDBOX_LOG" 2>&1 734 | ;; 735 | 736 | test) 737 | statusline "Test command forwarding..." 738 | printc $default "~$ ${blue}docker exec -it algod uname -a" 739 | dc exec -T algod uname -a 740 | 741 | TOKEN=$(cat "$SANDBOX_DIR/config/token") 742 | statusline "Test Algod REST API..." 743 | printc $default "~$ ${blue}curl ${teal}\"localhost:$APORT/v2/status?pretty\" -H \"X-Algo-API-Token: $TOKEN\"" 744 | curl "localhost:$APORT/v2/status?pretty" -H "X-Algo-API-Token: $TOKEN" 745 | 746 | statusline "Test KMD REST API..." 747 | printc $default "~$ ${blue}curl ${teal}\"localhost:$KPORT/v1/wallets\" -H \"X-KMD-API-Token: $TOKEN\"" 748 | curl "localhost:$KPORT/v1/wallets" -H "X-KMD-API-Token: $TOKEN" 749 | 750 | statusline "\nTest Indexer REST API..." 751 | printc $default "~$ ${blue}curl ${teal}\"localhost:$IPORT/health?pretty\"" 752 | curl "localhost:$IPORT/health?pretty" 753 | ;; 754 | 755 | enter) 756 | enter "$@" 757 | ;; 758 | 759 | logs) 760 | logs "$@" 761 | ;; 762 | 763 | dump) 764 | dump "$@" 765 | ;; 766 | 767 | tail) 768 | tail_f "$@" 769 | ;; 770 | 771 | status) 772 | status_helper 773 | ;; 774 | 775 | version) 776 | version_helper 777 | ;; 778 | 779 | goal) 780 | shift 781 | goal_helper "$@" 782 | ;; 783 | 784 | tealdbg) 785 | shift 786 | tealdbg_helper "$@" 787 | ;; 788 | 789 | copyTo|cpt) 790 | shift 791 | statusline "Now copying $1 to Algod container in /opt/data/$1" 792 | docker cp "$1" "$(dc ps -q algod):/opt/data/$(basename $1)" 793 | ;; 794 | 795 | copyFrom|cpf) 796 | shift 797 | statusline "Now copying /opt/data/$1 from Algod container to $SANDBOX_DIR/" 798 | docker cp "$(dc ps -q algod):/opt/data/$(basename $1)" "$1" 799 | ;; 800 | 801 | *) 802 | 803 | help 804 | ;; 805 | esac 806 | } 807 | 808 | ############## 809 | # Entrypoint # 810 | ############## 811 | 812 | sandbox "$@" 813 | --------------------------------------------------------------------------------