├── .gitignore ├── LICENSE ├── README.md ├── clean.sh ├── config ├── dev.json ├── docker │ ├── authority.yml │ ├── chain.yml │ ├── client.yml │ └── instantseal.yml ├── spec │ ├── accounts │ │ ├── aura │ │ ├── instantseal │ │ ├── tendermint │ │ └── validatorset │ ├── authcodes │ ├── authority_round.toml │ ├── chain_footer │ ├── chain_header │ ├── client.toml │ ├── engine │ │ ├── aura │ │ ├── instantseal │ │ ├── tendermint │ │ └── validatorset │ ├── example.spec │ ├── genesis │ │ ├── aura │ │ ├── instantseal │ │ └── tendermint │ ├── instant_seal.toml │ ├── name │ └── params │ │ ├── aura │ │ ├── instantseal │ │ ├── tendermint │ │ └── validatorset └── utils │ ├── keygen.sh │ └── pwdgen.sh ├── customchain ├── README.md ├── config │ ├── example.toml │ ├── keys │ │ ├── 1 │ │ ├── 2 │ │ ├── 3 │ │ └── address_book.json │ ├── node.yml │ └── password └── generate.py ├── dashboard └── ws_secret.json ├── include ├── docker-compose.yml └── ethstats.yml ├── load_tests ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── personal_sendTransaction_1500.jmx ├── src │ └── test │ │ ├── groovy │ │ └── EthSendRawTransactionBasic10000SpockTest.groovy │ │ └── resources │ │ └── eth_sendRawTransaction_basic_10000.rpc └── submit_corpus.sh ├── monitor └── app.json └── parity-deploy.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff: 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/dictionaries 10 | 11 | # Sensitive or high-churn files: 12 | .idea/**/dataSources/ 13 | .idea/**/dataSources.ids 14 | .idea/**/dataSources.xml 15 | .idea/**/dataSources.local.xml 16 | .idea/**/sqlDataSources.xml 17 | .idea/**/dynamic.xml 18 | .idea/**/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/**/gradle.xml 22 | .idea/**/libraries 23 | 24 | # Mongo Explorer plugin: 25 | .idea/**/mongoSettings.xml 26 | 27 | ## File-based project format: 28 | *.iws 29 | 30 | ## Plugin-specific files: 31 | 32 | # IntelliJ 33 | /out/ 34 | 35 | # mpeltonen/sbt-idea plugin 36 | .idea_modules/ 37 | 38 | # JIRA plugin 39 | atlassian-ide-plugin.xml 40 | 41 | # Crashlytics plugin (for Android Studio and IntelliJ) 42 | com_crashlytics_export_strings.xml 43 | crashlytics.properties 44 | crashlytics-build.properties 45 | fabric.properties 46 | 47 | .env 48 | .gitignore 49 | .idea/ 50 | .vagrant/ 51 | Vagrantfile 52 | data/ 53 | deployment/ 54 | docker-compose.yml 55 | jmeter.log 56 | parity-deploy.iml 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parity Deploy 2 | The parity deploy script is used to generate parity deployment configurations. These can range from a single instance development node to a proof of authority network with an arbitrary amount of authority nodes. 3 | 4 | # Requirements 5 | 6 | There are multiple dependencies for this script to work. Most modern operating systems should have the base of these already installed. On Ubuntu systems these will automatically be installed if not already present on the system. 7 | 8 | Requires: 9 | 1. openssl (which supports secp256k1 curves) 10 | 2. python pip 11 | 3. docker 12 | 4. docker-compose 13 | 5. ethkey (or this can be downloaded dynamically by the key generation script) 14 | 15 | # CLI Usage Options 16 | 17 | There are currently three main options which can be used with the parity-deploy tool. They are: 18 | 19 | Required: 20 | 21 | ```--config``` This option allows you to set the conensus engine of the chain. Multiple methods are supported: 22 | * instantseal - Instant sealing of blocks for development mode. Expected to be run on a single node. 23 | * aura - Authority Round consensus engine, where all the authorities take a turn being the block created, based on unix/linux epoch, so the time need to be syncronized between hosts. 24 | * tendermint - Tendermint is another consensus engine that can be used with parity, however not as well tested as Authority Round. 25 | * validatorset - Validtor Set is used to transition a chain from one validator to another at a certain block. 26 | * input.json - Use a custom input chain spec file used on all of the nodes. 27 | 28 | Optional: 29 | 30 | ```--name``` This option allows you to set the name of the chain in use. Default chain name is parity. 31 | 32 | ```--nodes``` The amount of nodes that will be used with an aura or tendermint network. By default one non-authority node is also created. Default value is 2 nodes. 33 | 34 | ```--ethstats``` This option will start an ethstats monitoring instance that can be connected to on http://localhost:3001 35 | 36 | ```--expose``` This option will expose ports 8080, 8180, 8545 and 30303 on the container name given as an argument. 37 | 38 | ```--release``` This option will let you select the release of the docker image. 39 | 40 | ```--entrypoint``` This option will override the default entrypoint in the docker image. 41 | 42 | 43 | # Using the tool 44 | 45 | Currently this scripts supports two types of chains, either instant sealing for development and aura for proof of authority with multiple validators. 46 | 47 | Some examples of using the script are: 48 | 49 | A single node instant seal node, accessible via 127.0.0.1:8180: 50 | ``` 51 | ./parity-deploy.sh --config dev 52 | ``` 53 | 54 | A three node proof of authority chain with one client acessable via 127.0.0.1:8180: 55 | ``` 56 | ./parity-deploy.sh --config aura 57 | ``` 58 | 59 | The output of this tool are two main items: 60 | 1. A docker-compose.yml file which can be used with docker-compose to bring up and down the host(s). 61 | 2. A deployments directory which will contain the keys, spec files and everything else required to configure the chain. 62 | 63 | # Launch the parity chain 64 | 65 | Once the configuration is created you just need to run the docker-compose command to launch the machine or machines. This can be done via: 66 | ``` 67 | docker-compose up -d 68 | ``` 69 | 70 | You will then be able to see the logs by running: 71 | ``` 72 | docker-compose logs -f 73 | ``` 74 | 75 | In these logs you should see a token being generated to login to parity. Alternatively you can run the command: 76 | ``` 77 | docker-compose logs | grep token 78 | ``` 79 | 80 | Once you are logged into the web interface if you go to Add Accounts, then select the option recovery phrase and enter the account recovery phrase as ```password``` 81 | 82 | You now have an account with lots of ether to send around. 83 | 84 | To stop the containers run: 85 | ``` 86 | docker-compose down 87 | ``` 88 | 89 | # Configuration of parity deploy 90 | 91 | Once parity-deploy has been run it will generate configuration files which are kept in the ```deployment``` folder. There are a few subdirectories that may exist in this location: 92 | 93 | 1. deployment/chain - this contains chain information such as spec file (spec.json) and other files like the reserved_peers file. 94 | 95 | 2. deployment/is_authority - this directory contains the configuration for an instant sealing authority. It has key.priv (private key file), key.pub (public key file), address.txt (pre-created authority address), password (plain text password file) and authority.toml (authority's parity config file). 96 | 97 | 3. deployment/client - this directory contains the configuration for an instant sealing client. It has key.priv (private key file), key.pub (public key file), address.txt (pre-created client address), password (plain text password file) and client.toml (client's parity config file). 98 | 99 | 4. deployment/[1/2/3] - these directories are used when you are using multiple aura validators - It has key.priv (private key file), key.pub (public key file), address.txt (pre-created authority address), password (plain text password file) and authority.toml (authority's parity config file). 100 | 101 | All of these nodes are then added to the to the chains/reserved_peers file. 102 | 103 | # Customisation of the chain configs. 104 | 105 | All of the chains are templated from the config directory. Inside the config directory there are multiple possible sources of templates: 106 | 107 | 1. config/docker - This contains three example yml template files. 108 | * config/docker/authority.yml is a config file used for an aura authority. 109 | * config/docker/client.yml is a config file used to connect a client to the authority nodes. 110 | * config/docker/instantseal.yml is a config file used for an instantseal authority node. 111 | 112 | 2. config/spec/acccounts - This directory contains the accounts that will be added to the spec files. 113 | * config/specs/accounts/aura - This file contains the accounts that will be added to the default aura chain. 114 | * config/specs/accounts/instantseal - This file contains accounts that will be added to the default instantseal chain. 115 | * config/specs/accounts/tendermint - This file contains accounts that will be added to the default tendermint chain. 116 | 117 | 3. config/spec/engine - This directory contains the consensus engine information for each chain. 118 | * config/spec/engine/aura - This file contains the engine information for the aura chain. 119 | * config/spec/engine/instantseal - This file contains the engine information for the instantseal chain. 120 | * config/spec/engine/tendermint - This file contains the engine information for the tendermint chain. 121 | * config/spec/engine/validatorset - This file contains the engine information for the validator set example chain. 122 | 123 | 124 | 4. config/spec/genesis - This directory contains genesis information for each chain. 125 | * config/spec/genesis/aura - This file contains genesis information for the aura chain. 126 | * config/spec/genesis/instantseal - This file contains genesis information for the instant seal chain. 127 | * config/spec/genesis/tendermint - This file contains genesis information for the tendermint chain. 128 | 129 | 130 | 5. config/spec/params - This directory contains additional parameters for each chain. 131 | * config/spec/params/aura - This file contains additional parameters for the aura chain. 132 | * config/spec/params/instantseal - This file contains additional parameters for the instantseal chain. 133 | * config/spec/params/tendermint - This file contains additional parameters for the tendermint chain. 134 | 135 | 6. config/spec - This directory contains some toml spec files that are used as parity configurations. 136 | * config/spec/authority_round.toml - An example toml file for an aura chain. 137 | * config/spec/instantseal.toml - An example toml file for an instantseal chain. 138 | * config/spec/tendermint.tml - An example toml file for a tendermint chain. 139 | * config/spec/chain_header - An example header for the chain spec file. 140 | * config/spec/chain_footer - An example footer for the chain spec file. 141 | 142 | 143 | # Adding custom containers 144 | 145 | You can also include custom containers (e.g. ethstats monitoring) by including the docker-compose configuration in include/docker-compose.yml. To add Ethstats monitoring you would need to include this in the file: 146 | ``` 147 | monitor: 148 | image: buythewhale/ethstats_monitor 149 | volumes: 150 | - ./monitor/app.json:/home/ethnetintel/eth-net-intelligence-api/app.json:ro 151 | dashboard: 152 | image: buythewhale/ethstats 153 | volumes: 154 | - ./dashboard/ws_secret.json:/eth-netstats/ws_secret.json:ro 155 | ports: 156 | - 3001:3000 157 | ``` 158 | 159 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf deployment 3 | rm -rf data 4 | rm -rf docker-compose.yml 5 | rm -rf .env 6 | -------------------------------------------------------------------------------- /config/dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "8923b5b4-74a1-7065-2860-d3b1576ca9ba", 3 | "version": 3, 4 | "crypto": { 5 | "cipher": "aes-128-ctr", 6 | "cipherparams": { 7 | "iv": "91b6f9053a255c7a8d56a16af9319477" 8 | }, 9 | "ciphertext": "a4e71b6d76d8ea369cdf6925ed8343c98763faf39fd60535788f23e5bfa6fcb7", 10 | "kdf": "pbkdf2", 11 | "kdfparams": { 12 | "c": 10240, 13 | "dklen": 32, 14 | "prf": "hmac-sha256", 15 | "salt": "aea8ab45f8c89ed5454e4b431befda1eb208edda27f4c03f467cc97314c38956" 16 | }, 17 | "mac": "a4d01eff44659abc18a48d2784b42a28b53bdf436626db98aeaceb584070719e" 18 | }, 19 | "address": "00ea169ce7e0992960d3bde6f5d539c955316432", 20 | "name": "", 21 | "meta": { 22 | "description": "", 23 | "passwordHint": "", 24 | "timestamp": 1495730764711 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /config/docker/authority.yml: -------------------------------------------------------------------------------- 1 | hostNODE_NAME: 2 | container_name: hostNODE_NAME 3 | image: parity/parity:stable 4 | user: root 5 | working_dir: /home/parity' 6 | volumes: 7 | - ./deployment/chain/spec.json:/home/parity/spec.json:ro 8 | - ./deployment/chain/reserved_peers:/home/parity/reserved_peers:ro 9 | - ./deployment/NODE_NAME/password:/home/parity/password:ro 10 | - ./deployment/NODE_NAME/authority.toml:/home/parity/authority.toml:ro 11 | - ./deployment/NODE_NAME/${NETWORK_NAME}:/home/parity/data/keys/${NETWORK_NAME} 12 | - ./config/dev.json:/home/parity/data/keys/${NETWORK_NAME}/dev.json 13 | - ./deployment/NODE_NAME/key.priv:/home/parity/data/network/key 14 | - ./data/NODE_NAME:/home/parity/data 15 | command: --chain /home/parity/spec.json --config /home/parity/authority.toml -d /home/parity/data 16 | -------------------------------------------------------------------------------- /config/docker/chain.yml: -------------------------------------------------------------------------------- 1 | client: 2 | container_name: client 3 | image: parity/parity:stable 4 | user: root 5 | working_dir: /home/parity' 6 | 7 | ports: 8 | - 8080:8080 9 | - 8180:8180 10 | - 8545:8545 11 | - 30303:30303 12 | volumes: 13 | - ./deployment/chain/spec.json:/home/parity/spec.json:ro 14 | - ./deployment/chain/reserved_peers:/home/parity/reserved_peers:ro 15 | - ./deployment/client/password:/home/parity/password:ro 16 | - ./deployment/client/client.toml:/home/parity/client.toml:ro 17 | - ./deployment/client/${NETWORK_NAME}:/home/parity/data/keys/${NETWORK_NAME} 18 | - ./config/dev.json:/home/parity/data/keys/${NETWORK_NAME}/dev.json 19 | - ./deployment/NODE_NAME/key.priv:/home/parity/data/network/key 20 | - ./data/client:/home/parity/data 21 | command: --chain CHAIN_NAME -d /home/parity/data 22 | -------------------------------------------------------------------------------- /config/docker/client.yml: -------------------------------------------------------------------------------- 1 | client: 2 | container_name: client 3 | image: parity/parity:stable 4 | user: root 5 | working_dir: /home/parity' 6 | ports: 7 | - 8080:8080 8 | - 8180:8180 9 | - 8545:8545 10 | - 8546:8546 11 | - 30303:30303 12 | volumes: 13 | - ./deployment/chain/spec.json:/home/parity/spec.json:ro 14 | - ./deployment/chain/reserved_peers:/home/parity/reserved_peers:ro 15 | - ./deployment/client/password:/home/parity/password:ro 16 | - ./deployment/client/client.toml:/home/parity/client.toml:ro 17 | - ./deployment/client/${NETWORK_NAME}:/home/parity/data/keys/${NETWORK_NAME} 18 | - ./config/dev.json:/home/parity/data/keys/${NETWORK_NAME}/dev.json 19 | - ./deployment/NODE_NAME/key.priv:/home/parity/data/network/key 20 | - ./data/client:/home/parity/data 21 | command: --chain /home/parity/spec.json --config /home/parity/client.toml -d /home/parity/data 22 | -------------------------------------------------------------------------------- /config/docker/instantseal.yml: -------------------------------------------------------------------------------- 1 | version: '2.0' 2 | services: 3 | host1: 4 | container_name: host1 5 | image: parity/parity:stable 6 | user: root 7 | working_dir: /home/parity' 8 | 9 | volumes: 10 | - ./deployment/chain/spec.json:/home/parity/spec.json:ro 11 | - ./deployment/chain/reserved_peers:/home/parity/reserved_peers:ro 12 | - ./deployment/chain/authcodes:/home/parity/data/authcodes 13 | - ./deployment/is_authority/password:/home/parity/password:ro 14 | - ./deployment/is_authority/authority.toml:/home/parity/authority.toml:ro 15 | - ./deployment/is_authority/${NETWORK_NAME}:/home/parity/data/keys/DevelopmentChain 16 | - ./data/is_authority:/home/parity/data 17 | command: --chain dev --config /home/parity/authority.toml -d /home/parity/data 18 | -------------------------------------------------------------------------------- /config/spec/accounts/aura: -------------------------------------------------------------------------------- 1 | "accounts": { 2 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 3 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 4 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 5 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 6 | "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, 7 | "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, 8 | "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, 9 | "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, 10 | "0x00Ea169ce7e0992960D3BdE6F5D539C955316432": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } 11 | } 12 | -------------------------------------------------------------------------------- /config/spec/accounts/instantseal: -------------------------------------------------------------------------------- 1 | "accounts": { 2 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 3 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 4 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 5 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 6 | "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, 7 | "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, 8 | "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, 9 | "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, 10 | "0x00Ea169ce7e0992960D3BdE6F5D539C955316432": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } 11 | } 12 | -------------------------------------------------------------------------------- /config/spec/accounts/tendermint: -------------------------------------------------------------------------------- 1 | "accounts": { 2 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 3 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 4 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 5 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 6 | "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, 7 | "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, 8 | "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, 9 | "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, 10 | "0x00Ea169ce7e0992960D3BdE6F5D539C955316432": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } 11 | } 12 | -------------------------------------------------------------------------------- /config/spec/accounts/validatorset: -------------------------------------------------------------------------------- 1 | "accounts": { 2 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 3 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 4 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 5 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 6 | "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } }, 7 | "0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x0", "pricing": { "linear": { "base": 500, "word": 0 } } } }, 8 | "0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x0", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, 9 | "0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x0", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, 10 | "0x00Ea169ce7e0992960D3BdE6F5D539C955316432": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } 11 | } 12 | -------------------------------------------------------------------------------- /config/spec/authcodes: -------------------------------------------------------------------------------- 1 | 1111222233334444; 2 | -------------------------------------------------------------------------------- /config/spec/authority_round.toml: -------------------------------------------------------------------------------- 1 | [parity] 2 | chain = "/home/parity/chain.json" 3 | 4 | [account] 5 | password = ["/home/parity/password"] 6 | 7 | [network] 8 | reserved_peers = "/home/parity/reserved_peers" 9 | 10 | [rpc] 11 | interface = "0.0.0.0" 12 | cors = ["all"] 13 | hosts = ["all"] 14 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "personal", "parity_accounts", "signer", "parity_set"] 15 | 16 | [mining] 17 | reseal_on_txs = "none" 18 | engine_signer = "ENGINE_SIGNER" 19 | 20 | [websockets] 21 | disable = false 22 | port = 8546 23 | interface = "all" 24 | origins = ["http://127.0.0.1:8180"] 25 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] 26 | hosts = ["all"] 27 | -------------------------------------------------------------------------------- /config/spec/chain_footer: -------------------------------------------------------------------------------- 1 | } 2 | -------------------------------------------------------------------------------- /config/spec/chain_header: -------------------------------------------------------------------------------- 1 | { 2 | 3 | -------------------------------------------------------------------------------- /config/spec/client.toml: -------------------------------------------------------------------------------- 1 | [parity] 2 | chain = "/home/parity/spec.json" 3 | 4 | [account] 5 | password = ["/home/parity/password"] 6 | 7 | [network] 8 | reserved_peers = "/home/parity/reserved_peers" 9 | 10 | [websockets] 11 | disable = false 12 | port = 8546 13 | interface = "all" 14 | origins = ["http://127.0.0.1:8180"] 15 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] 16 | hosts = ["all"] 17 | 18 | [rpc] 19 | interface = "0.0.0.0" 20 | cors = ["all"] 21 | hosts = ["all"] 22 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "personal", "parity_accounts", "signer", "parity_set"] 23 | -------------------------------------------------------------------------------- /config/spec/engine/aura: -------------------------------------------------------------------------------- 1 | "engine": { 2 | "authorityRound": { 3 | "params": { 4 | "stepDuration": "2", 5 | "validators" : { 6 | "list": [ 0x0000000000000000000000000000000000000000 ] 7 | } 8 | } 9 | } 10 | }, 11 | -------------------------------------------------------------------------------- /config/spec/engine/instantseal: -------------------------------------------------------------------------------- 1 | "engine": { 2 | "instantSeal": null 3 | }, 4 | -------------------------------------------------------------------------------- /config/spec/engine/tendermint: -------------------------------------------------------------------------------- 1 | "engine": { 2 | "tendermint": { 3 | "params": { 4 | "validators" : { 5 | "list": [ 0x0000000000000000000000000000000000000000 6 | ] 7 | }, 8 | "timeoutPropose": 10000, 9 | "timeoutPrevote": 10000, 10 | "timeoutPrecommit": 10000, 11 | "timeoutCommit": 10000 12 | } 13 | } 14 | }, 15 | -------------------------------------------------------------------------------- /config/spec/engine/validatorset: -------------------------------------------------------------------------------- 1 | "engine": { 2 | "authorityRound": { 3 | "params": { 4 | "stepDuration": "2", 5 | "validators" : { 6 | "multi": { 7 | "0": { 8 | "list": [ 0x0000000000000000000000000000000000000000 ] 9 | }, 10 | "5": { 11 | "list": [ 0x0000000000000000000000000000000000000001 ] 12 | } 13 | 14 | } 15 | } 16 | } 17 | } 18 | }, 19 | -------------------------------------------------------------------------------- /config/spec/example.spec: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CHAIN_NAME", 3 | "engine": { 4 | "authorityRound": { 5 | "params": { 6 | "stepDuration": "2", 7 | "validators" : { 8 | "list": [ "0x0000000000000000000000000000000000000000" ] 9 | } 10 | } 11 | } 12 | }, 13 | "params": { 14 | "maximumExtraDataSize": "0x20", 15 | "minGasLimit": "0x1388", 16 | "gasLimitBoundDivisor": "0x400", 17 | "networkID" : "0x11" 18 | }, 19 | "genesis": { 20 | "seal": { 21 | "authorityRound": { 22 | "step": "0x0", 23 | "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 24 | } 25 | }, 26 | "difficulty": "0x20000", 27 | "gasLimit": "0x1312D00" 28 | }, 29 | "accounts": { 30 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 31 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 32 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 33 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/spec/genesis/aura: -------------------------------------------------------------------------------- 1 | "genesis": { 2 | "seal": { 3 | "authorityRound": { 4 | "step": "0x0", 5 | "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 6 | } 7 | }, 8 | "difficulty": "0x20000", 9 | "gasLimit": "0x2625A00" 10 | }, 11 | -------------------------------------------------------------------------------- /config/spec/genesis/instantseal: -------------------------------------------------------------------------------- 1 | "genesis": { 2 | "seal": { 3 | "generic": "0x0" 4 | }, 5 | "difficulty": "0x20000", 6 | "author": "0x0000000000000000000000000000000000000000", 7 | "timestamp": "0x00", 8 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 9 | "extraData": "0x", 10 | "gasLimit": "0x1312D00" 11 | }, 12 | -------------------------------------------------------------------------------- /config/spec/genesis/tendermint: -------------------------------------------------------------------------------- 1 | "genesis": { 2 | "seal": { 3 | "authorityRound": { 4 | "step": "0x0", 5 | "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 6 | } 7 | }, 8 | "difficulty": "0x20000", 9 | "gasLimit": "0x1312D00" 10 | }, 11 | -------------------------------------------------------------------------------- /config/spec/instant_seal.toml: -------------------------------------------------------------------------------- 1 | [parity] 2 | chain = "/home/parity/chain.json" 3 | 4 | [account] 5 | password = ["/home/parity/password"] 6 | 7 | [network] 8 | reserved_peers = "/home/parity/reserved_peers" 9 | 10 | [rpc] 11 | interface = "0.0.0.0" 12 | cors = ["all"] 13 | hosts = ["all"] 14 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "personal", "parity_accounts", "signer", "parity_set"] 15 | 16 | [websockets] 17 | disable = false 18 | port = 8546 19 | interface = "all" 20 | origins = ["http://127.0.0.1:8180"] 21 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] 22 | hosts = ["all"] 23 | -------------------------------------------------------------------------------- /config/spec/name: -------------------------------------------------------------------------------- 1 | "name": "CHAIN_NAME", 2 | -------------------------------------------------------------------------------- /config/spec/params/aura: -------------------------------------------------------------------------------- 1 | "params": { 2 | "maximumExtraDataSize": "0x20", 3 | "minGasLimit": "0x1388", 4 | "gasLimitBoundDivisor": "0x400", 5 | "networkID" : "0x11", 6 | "eip140Transition": "0x0", 7 | "eip211Transition": "0x0", 8 | "eip214Transition": "0x0", 9 | "eip658Transition": "0x0", 10 | "wasmActivationTransition": "0x0", 11 | "eip145Transition": "0x0", 12 | "eip1014Transition": "0x0", 13 | "eip1052Transition": "0x0", 14 | "eip1283Transition": "0x0", 15 | "kip4Transition": "0x0", 16 | "kip6Transition": "0x0" 17 | }, 18 | -------------------------------------------------------------------------------- /config/spec/params/instantseal: -------------------------------------------------------------------------------- 1 | "params": { 2 | "accountStartNonce": "0x0", 3 | "maximumExtraDataSize": "0x20", 4 | "minGasLimit": "0x1388", 5 | "networkID" : "0x11", 6 | "eip140Transition": "0x0", 7 | "eip211Transition": "0x0", 8 | "eip214Transition": "0x0", 9 | "eip658Transition": "0x0", 10 | "wasmActivationTransition": "0x0", 11 | "eip145Transition": "0x0", 12 | "eip1014Transition": "0x0", 13 | "eip1052Transition": "0x0", 14 | "eip1283Transition": "0x0", 15 | "kip4Transition": "0x0", 16 | "kip6Transition": "0x0" 17 | }, 18 | -------------------------------------------------------------------------------- /config/spec/params/tendermint: -------------------------------------------------------------------------------- 1 | "params": { 2 | "maximumExtraDataSize": "0x20", 3 | "minGasLimit": "0x1388", 4 | "networkID" : "0x11", 5 | "gasLimitBoundDivisor": "0x0400", 6 | "eip140Transition": "0x0", 7 | "eip211Transition": "0x0", 8 | "eip214Transition": "0x0", 9 | "eip658Transition": "0x0", 10 | "wasmActivationTransition": "0x0", 11 | "eip145Transition": "0x0", 12 | "eip1014Transition": "0x0", 13 | "eip1052Transition": "0x0", 14 | "eip1283Transition": "0x0", 15 | "kip4Transition": "0x0", 16 | "kip6Transition": "0x0" 17 | }, 18 | -------------------------------------------------------------------------------- /config/spec/params/validatorset: -------------------------------------------------------------------------------- 1 | "params": { 2 | "maximumExtraDataSize": "0x20", 3 | "minGasLimit": "0x1388", 4 | "gasLimitBoundDivisor": "0x400", 5 | "networkID" : "0x11", 6 | "eip140Transition": "0x0", 7 | "eip211Transition": "0x0", 8 | "eip214Transition": "0x0", 9 | "eip658Transition": "0x0", 10 | "wasmActivationTransition": "0x0", 11 | "eip145Transition": "0x0", 12 | "eip1014Transition": "0x0", 13 | "eip1052Transition": "0x0", 14 | "eip1283Transition": "0x0", 15 | "kip4Transition": "0x0", 16 | "kip6Transition": "0x0" 17 | }, 18 | -------------------------------------------------------------------------------- /config/utils/keygen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TMPFILE=`mktemp` 3 | export PATH=$PATH:. 4 | 5 | if [ ! $(type -P $PWD/ethkey) ]; then 6 | ARCH=`uname -m` 7 | ETHKEY_URL=`curl -sS "https://vanity-service.parity.io/parity-binaries?version=stable&format=markdown&os=linux&architecture=$ARCH" | grep ethkey | awk {'print $5'} | cut -d"(" -f2 | cut -d")" -f1` 8 | wget -q $ETHKEY_URL 9 | chmod +x ethkey 10 | fi 11 | 12 | if [ ! $(type -P $PWD/ethstore) ]; then 13 | ARCH=`uname -m` 14 | ETHSTORE_URL=`curl -sS "https://vanity-service.parity.io/parity-binaries?version=stable&format=markdown&os=linux&architecture=$ARCH" | grep ethstore | awk {'print $5'} | cut -d"(" -f2 | cut -d")" -f1` 15 | wget -q $ETHSTORE_URL 16 | chmod +x ethstore 17 | fi 18 | 19 | 20 | # Generate the private and public keys 21 | ./ethkey generate random > $TMPFILE 22 | 23 | cat $TMPFILE | grep public | awk {'print $2'} > $1/key.pub 24 | cat $TMPFILE | grep secret | awk {'print $2'} > $1/key.priv 25 | cat $TMPFILE | grep address | awk {'print $2'} > $1/address.txt 26 | 27 | rm -rf $TMPFILE 28 | 29 | -------------------------------------------------------------------------------- /config/utils/pwdgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This help script generate paswwords for nodes in a file : password. 4 | # You can set the number of password nodes you wanted to generate : -n | --nodes REQUIRED 5 | # This password file is store in the given output folder : -o | --output. OPTIONAL. Default: deployment 6 | # You can choose the password length : -l | --length. OPTIONAL. Default: 12 7 | # You can force to reset the passord file if already exist in the target folder : -f | --force. OPTIONAL. Default: 0(false) 8 | 9 | help() { 10 | 11 | echo "pwdgen.sh OPTIONS 12 | Usage: 13 | REQUIRED: 14 | -n | --nodes number_of_nodes 15 | 16 | OPTIONAL: 17 | -l | --length password_length. Default: 12 18 | -o | --output output folder. Default: deployment 19 | -f | --force reset passord file if exist. Default: 0(false) 20 | 21 | -h | --help 22 | " 23 | 24 | } 25 | 26 | check_packages() { 27 | OPENSSL_INSTALLED=$(which openssl | wc -l) 28 | if [ ! 1 -eq $OPENSSL_INSTALLED ] 29 | then 30 | echo "ERROR : openssl not installed " 31 | exit 1 32 | fi 33 | } 34 | 35 | 36 | genpw() { 37 | openssl rand -base64 ${PASSWORD_LENGTH} 38 | } 39 | 40 | create_node_pwd() { 41 | 42 | DEST_DIR_NODE=$DEST_DIR/$1 43 | if [ ! -d $DEST_DIR_NODE ] ; then 44 | mkdir -p $DEST_DIR_NODE 45 | if [ ! $? -eq 0 ] ; then 46 | echo "ERROR : cannot access output folder $DEST_DIR_NODE " 47 | exit 1 48 | fi 49 | fi 50 | 51 | 52 | if [ ! -f $DEST_DIR_NODE/password ] 53 | then 54 | echo "generate password in $DEST_DIR_NODE" 55 | echo ${PASSWORD_LENGTH} 56 | genpw > $DEST_DIR_NODE/password 57 | else 58 | echo "$DEST_DIR_NODE/password file already exist" 59 | if [ $FORCED -eq 1 ] 60 | then 61 | echo "forced mode. Erase current password" 62 | echo "generate password in $DEST_DIR_NODE" 63 | echo ${PASSWORD_LENGTH} 64 | genpw > $DEST_DIR_NODE/password 65 | else 66 | echo "no forced mode. Do nothing : do not erase current password" 67 | fi 68 | fi 69 | 70 | 71 | } 72 | 73 | isInteger() { 74 | if test ${1} -eq ${1} 2>/dev/null; then 75 | return 0 76 | fi 77 | return 1 78 | } 79 | 80 | 81 | #### MAIN 82 | 83 | #default values 84 | FORCED=0 85 | CHAIN_NODES="" 86 | PASSWORD_LENGTH=12 87 | DEST_DIR="deployment" 88 | 89 | ARGS="$@" 90 | 91 | if [ $# -lt 1 ] 92 | then 93 | echo "No arguments supplied" 94 | help 95 | exit 1 96 | fi 97 | 98 | while [ "$1" != "" ]; do 99 | case $1 in 100 | -n | --nodes ) shift 101 | CHAIN_NODES=$1 102 | ;; 103 | -l | --length) shift 104 | PASSWORD_LENGTH=$1 105 | ;; 106 | -o | --output ) shift 107 | DEST_DIR="$1" 108 | ;; 109 | -f | --force) FORCED=1 110 | ;; 111 | -h | --help ) help 112 | exit 113 | ;; 114 | esac 115 | shift 116 | done 117 | 118 | #check ${PASSWORD_LENGTH} integer 119 | isInteger ${PASSWORD_LENGTH} 120 | if [ $? -eq 1 ] 121 | then 122 | echo "PASSWORD_LENGTH ${PASSWORD_LENGTH} must be an integer." 123 | exit 1 124 | fi 125 | 126 | #check mandatory 127 | if [ -z $CHAIN_NODES ] ; then 128 | echo "-n | --nodes arg is mandatory" 129 | help 130 | exit 1 131 | fi 132 | 133 | #check ${CHAIN_NODES} integer 134 | isInteger ${CHAIN_NODES} 135 | if [ $? -eq 1 ] 136 | then 137 | echo "CHAIN_NODES ${CHAIN_NODES} must be an integer." 138 | exit 1 139 | fi 140 | 141 | ## check permission 142 | mkdir -p $DEST_DIR 143 | if [ ! $? -eq 0 ] ; then 144 | echo "ERROR : cannot access output folder $DEST_DIR " 145 | exit 1 146 | fi 147 | 148 | 149 | check_packages 150 | if [ ! $? -eq 0 ] ; then 151 | echo "ERROR : openssl lib nedded " 152 | exit 1 153 | fi 154 | 155 | if [ $CHAIN_NODES ] ; then 156 | for x in ` seq $CHAIN_NODES ` ; do 157 | create_node_pwd $x 158 | done 159 | fi 160 | -------------------------------------------------------------------------------- /customchain/README.md: -------------------------------------------------------------------------------- 1 | # Example of nested chain configuration 2 | 3 | This is an example of a nested chain configuration to be integrated into parity-deploy. This script will run with a custom chain option is given to parity deploy. 4 | 5 | # Quickstart 6 | 7 | Ensure the python package contoml is installed, you can install this using ```pip install contoml```. 8 | 9 | ``` 10 | ./generate.py 11 | docker-compose up 12 | ``` 13 | 14 | 15 | # Editing the configuration 16 | 17 | Edit the file config/config.toml ... there are two main sections. 18 | 19 | The first is for the spec file, just paste the whole spec file in. 20 | 21 | The second is for the containers to be created, they should be created in the format: 22 | 23 | hostname = ``` 24 | parity-toml-file-goes-here 25 | 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /customchain/config/example.toml: -------------------------------------------------------------------------------- 1 | # Configuration for chain spec 2 | [spec] 3 | config = ''' 4 | { 5 | 6 | "name": "parity", 7 | "engine": { 8 | "authorityRound": { 9 | "params": { 10 | "gasLimitBoundDivisor": "0x400", 11 | "stepDuration": "5", 12 | "validators" : { 13 | "list": [ "0x830ac6153fcd2123459ebec27e1376eb90f9d616" ] 14 | } 15 | } 16 | } 17 | }, 18 | 19 | "params": { 20 | "maximumExtraDataSize": "0x20", 21 | "minGasLimit": "0x1388", 22 | "networkID" : "0x8888" 23 | }, 24 | "genesis": { 25 | "seal": { 26 | "authorityRound": { 27 | "step": "0x0", 28 | "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 29 | } 30 | }, 31 | "difficulty": "0x20000", 32 | "gasLimit": "0x5B8D80" 33 | }, 34 | "accounts": { 35 | "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 36 | "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 37 | "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 38 | "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 39 | "0x00Ea169ce7e0992960D3BdE6F5D539C955316432": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } 40 | } 41 | } 42 | ''' 43 | 44 | # Default toml file for hosts unless overridden. 45 | default_config = ''' 46 | [parity] 47 | chain = "/home/parity/chain.json" 48 | ''' 49 | 50 | 51 | # Add host entry and toml information for each container you want created 52 | [toml] 53 | 54 | # Container for example host 5 55 | # 56 | host5 = ''' 57 | 58 | [parity] 59 | chain = "/home/parity/chain.json" 60 | 61 | [account] 62 | unlock = ["0x830ac6153fcd2123459ebec27e1376eb90f9d616"] 63 | password = ["/home/parity/password"] 64 | 65 | 66 | [rpc] 67 | interface = "0.0.0.0" 68 | cors = "all" 69 | hosts = ["all"] 70 | apis = ["web3", "eth", "net", "parity", "traces", "rpc", "personal", "parity_accounts", "signer", "parity_set"] 71 | 72 | [mining] 73 | reseal_on_txs = "none" 74 | engine_signer = "0x830ac6153fcd2123459ebec27e1376eb90f9d616" 75 | force_sealing = true 76 | 77 | ''' 78 | 79 | # Container for example host 311 80 | # 81 | host311 = "default" 82 | 83 | # Container for example host 3178 84 | # 85 | host3178 = "default" 86 | 87 | 88 | -------------------------------------------------------------------------------- /customchain/config/keys/1: -------------------------------------------------------------------------------- 1 | {"id":"f4d426e5-abd6-1538-bf3e-02b9d8778afe","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"5295f82ed64e7bd3559dc8a39e7e29e2"},"ciphertext":"9ebd740ad3be79806cd9450dde07275a66ac9b14f1ec3618cede0fe99e3b8b4e","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"e650a2304b5f7854d0b37dc9a4c0aaf429b7b301c2f68b2c8388e7ad291b7324"},"mac":"fff76e2fd65c89d65dbb2446f6392ba52571f600d6c0385c264c019448c89c5e"},"address":"830ac6153fcd2123459ebec27e1376eb90f9d616","name":"","meta":"{}"} -------------------------------------------------------------------------------- /customchain/config/keys/2: -------------------------------------------------------------------------------- 1 | {"id":"ca7a498f-e9ba-8bda-c5a8-e0f0b882ed13","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"d370a872ea1ec289425581a4a7488cfa"},"ciphertext":"14c4bfaa0bb0f3366170987bea7e4ccbe4f41220b9aa1dddc3818afada25f746","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"58ab572be9a1086c800a9caca2a67fbfcec22d3de743f119f664447e81267d90"},"mac":"1efc7bfd03514f7491a97b65bb71d2232b0a5e26e17823756d2684d7feda76ea"},"address":"edbe00d29e9b66beee76a04722ac5a79364d4710","name":"","meta":"{}"} -------------------------------------------------------------------------------- /customchain/config/keys/3: -------------------------------------------------------------------------------- 1 | {"id":"f2111e9f-fd50-bcdc-36f6-fdc9ea06032f","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"f80d0b13d363b3ebb7a185b76ef6eb77"},"ciphertext":"2a65d4285066b8b42e1aae73c76bcd88505f079e31d2763e49129458b00fcb45","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"200cde3c9615edda3f028940d04823058435c9d3c4fc910f33c643ecef07db5d"},"mac":"4f7e841fd6bb66af1e76aaa3d36b2ee37366d916be10ca326d647a80b5b4d83a"},"address":"5d6a3e7dced39510b2155d714c7e7f5b8fe7e1c2","name":"","meta":"{}"} -------------------------------------------------------------------------------- /customchain/config/keys/address_book.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /customchain/config/node.yml: -------------------------------------------------------------------------------- 1 | NODE_NAME: 2 | container_name: NODE_NAME 3 | image: parity/parity:beta 4 | volumes: 5 | - ./deployment/NODE_NAME.toml:/home/parity/config.toml:ro 6 | - ./deployment/spec.json:/home/parity/spec.json:ro 7 | - ./deployment/reserved_peers:/home/parity/reserved_peers 8 | - ./customchain/config/password:/home/parity/password:ro 9 | - ./customchain/config/keys:/home/parity/data/keys/parity 10 | - ./data/NODE_NAME:/home/parity/data 11 | command: --chain /home/parity/spec.json --reserved-peers /home/parity/reserved_peers --config /home/parity/config.toml -d /home/parity/data 12 | -------------------------------------------------------------------------------- /customchain/config/password: -------------------------------------------------------------------------------- 1 | password 2 | -------------------------------------------------------------------------------- /customchain/generate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import contoml 3 | import os 4 | import subprocess 5 | import time 6 | import sys 7 | from shutil import copyfile 8 | 9 | docker_template = "customchain/config/node.yml" 10 | compose_file = "docker-compose.yml" 11 | 12 | def generate_docker_compose_header(): 13 | f = open(compose_file,"w") 14 | f.write("version: '2.0'\nservices:\n") 15 | f.close() 16 | 17 | def generate_docker_compose(hosts): 18 | f = open(docker_template,"r") 19 | spec = f.read() 20 | f.close() 21 | output = "" 22 | for host in hosts: 23 | node_info = spec 24 | output = output + node_info.replace("NODE_NAME",host) 25 | f = open(compose_file,"a") 26 | f.write(output) 27 | f.close() 28 | 29 | def generate_toml_files(hosts): 30 | copyfile("/dev/null","deployment/reserved_peers") 31 | for host in hosts: 32 | f = open("deployment/" + host + ".toml","w") 33 | if mainconfig['toml'][host] == "default": 34 | f.write(mainconfig['spec']['default_config']) 35 | else: 36 | f.write(mainconfig['toml'][host]) 37 | f.close() 38 | 39 | def capture_enodes(): 40 | print("Bringing up containers to grab enode information") 41 | os.system("docker-compose up -d ") 42 | time.sleep(20) 43 | cmd = ("docker-compose logs | grep enode | awk {'print $9'}") 44 | p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 45 | f = open("deployment/reserved_peers","w") 46 | for line in p.stdout.readlines(): 47 | f.write(line) 48 | f.close() 49 | os.system("docker-compose down") 50 | 51 | def chain_spec(): 52 | spec = mainconfig['spec']['config'] 53 | f = open("deployment/spec.json","w") 54 | f.write(spec) 55 | f.close() 56 | 57 | if not os.path.exists("deployment/"): 58 | os.mkdir("deployment/") 59 | 60 | 61 | hosts = [] 62 | 63 | 64 | print("Generating custom configuration from toml input...") 65 | mainconfig = contoml.load(sys.argv[1]) 66 | 67 | for host in mainconfig['toml'].items(): 68 | 69 | hosts.append(host[0]) 70 | chain_spec() 71 | generate_docker_compose_header() 72 | generate_docker_compose(hosts) 73 | generate_toml_files(hosts) 74 | capture_enodes() 75 | 76 | print("All done, run 'docker-compose up -d' to start containers") 77 | 78 | -------------------------------------------------------------------------------- /dashboard/ws_secret.json: -------------------------------------------------------------------------------- 1 | ["OurDashSecret93%"] 2 | -------------------------------------------------------------------------------- /include/docker-compose.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | myapp: 3 | #driver: local 4 | driver_opts: 5 | o: uid=1000,gid=1000 6 | -------------------------------------------------------------------------------- /include/ethstats.yml: -------------------------------------------------------------------------------- 1 | monitor: 2 | image: buythewhale/ethstats_monitor 3 | volumes: 4 | - ./monitor/app.json:/home/ethnetintel/eth-net-intelligence-api/app.json:ro 5 | dashboard: 6 | image: buythewhale/ethstats 7 | volumes: 8 | - ./dashboard/ws_secret.json:/eth-netstats/ws_secret.json:ro 9 | ports: 10 | - 3001:3000 11 | -------------------------------------------------------------------------------- /load_tests/README.md: -------------------------------------------------------------------------------- 1 | ## Jmeter Load tests 2 | 3 | [Download Jmeter](https://jmeter.apache.org/download_jmeter.cgi) 4 | 5 | `personal_sendTransaction_1500.jmx` is set up to use 150 concurrent clients with 10 loops to hit the `personal_sendTransaction` method. 6 | 7 | In the second thread group a call is being made to `eth_getBlockByNumber` to check latest block number until it reaches 0x5dc or 1500 concluding that all transactions have been processed 8 | 9 | Resultant TPS is 1500 divided by time taken to finish the test 10 | 11 | ## Run Parity 12 | 13 | It is assumed that you are running parity somewhere and the test is configured to point at it. It is configured for localhost by default. 14 | 15 | An easy way to run parity with docker would be for example 16 | ``` docker run -ti -p 8180:8180 -p 8545:8545 -p 30303:30303 parity/parity:nightly --config dev-insecure --ui-interface "0.0.0.0" --ui-no-validation ui --fast-unlock``` 17 | 18 | ## Standard RPC corpora 19 | 20 | Files can be found [here](https://drive.google.com/open?id=0Bxc6z62kZCsAZUNxUmsySGhZVjg). Each line in those `.rpc` files contains a JSON object to be fed to a standard RPC interface (IPC or HTTP). One way is presented in the simple `submit_corpus.sh` script, which can be ran like so 21 | ``` 22 | ./submit_corpus.sh eth_sendRawTransaction_basic_10000.rpc 23 | ``` 24 | 25 | Different options might be required to run different tests: 26 | - `eth_sendRawTransaction` does not require any special options 27 | ``` 28 | parity --config dev 29 | ``` 30 | - `eth_sendTransaction` and `eth_signTransaction` require the account to be unlocked 31 | ``` 32 | parity --config dev --unlock 0x00a329c0648769a73afac7f9381e08fb43dbea72 --password empty.file --fast-unlock 33 | ``` 34 | - `personal_sendTransaction` requires `personal` RPC API 35 | ``` 36 | parity --config dev --jsonrpc-apis personal 37 | ``` 38 | 39 | ## [Gradle](https://gradle.org/) build system 40 | [Gradle](https://gradle.org/) is used to run Spock tests. Run ```./gradlew test``` in the load_tests directory to run the load tests 41 | 42 | ## [Spock](http://spockframework.org/spock/docs/1.1/index.html) test benchmark 43 | 44 | [Spock Framework](http://spockframework.org/spock/docs/1.1/index.html) is an eye friendly BDD style test framework based on a Groovy DSL. This means you need to have Java installed. The build script is a gradle build and so can be started with the wrapper shell script ./gradlew in the directory containg the build.gradle file. 45 | Open load_tests/build/reports/tests/test/index.html to view the test results. The CLI output where benchmark times are recorded is under the Standard Output after clicking on a particular test 46 | 47 | -------------------------------------------------------------------------------- /load_tests/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "de.qaware.cloud.deployer" version "0.9.2" 3 | } 4 | 5 | apply plugin: 'java' 6 | apply plugin: 'groovy' 7 | 8 | 9 | repositories { 10 | jcenter() 11 | } 12 | 13 | dependencies { 14 | ext { 15 | groovyAll = '2.4.6' 16 | hamcrest = '1.4-atlassian-1' 17 | objenesis = '2.2' 18 | seleniumSupport = '2.52.0' 19 | spockCore = '1.1-groovy-2.4' 20 | webdriverHtmlunit = '0.9.7376' 21 | } 22 | 23 | compile ( 24 | 'org.slf4j:slf4j-api:1.7.21', 25 | "org.codehaus.groovy:groovy-all:$groovyAll", 26 | "org.codehaus.gpars:gpars:1.2.1" 27 | ) 28 | 29 | testCompile( 30 | 'joda-time:joda-time:2.3', 31 | 'org.codehaus.groovy.modules.http-builder:http-builder:0.7', 32 | "org.hamcrest:hamcrest-library:$hamcrest", 33 | 'javax.servlet:javax.servlet-api:4.0.0-b07', 34 | 'javax.ws.rs:javax.ws.rs-api:2.1-m09', 35 | 'junit:junit:4.12', 36 | "org.spockframework:spock-core:$spockCore" 37 | ) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /load_tests/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openethereum/parity-deploy/4050ea19f2262d636fcbb698bdd911c6748f34b1/load_tests/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /load_tests/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Aug 07 12:54:04 BST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip 7 | -------------------------------------------------------------------------------- /load_tests/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /load_tests/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /load_tests/personal_sendTransaction_1500.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | vhost 18 | localhost 19 | = 20 | 21 | 22 | passphrase 23 | 0 24 | = 25 | 26 | 27 | last_block 28 | 0x5dc 29 | = 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Content-Type 38 | application/json 39 | 40 | 41 | 42 | 43 | 44 | continue 45 | 46 | false 47 | 10 48 | 49 | 150 50 | 0 51 | 1363247040000 52 | 1363247040000 53 | false 54 | 0 55 | 0 56 | 57 | 58 | 59 | 0 60 | 9999999999999 61 | 1 62 | ctr 63 | 64 | false 65 | 66 | 67 | 68 | 0 69 | 999999999999 70 | 1 71 | account_ctr 72 | 73 | false 74 | 75 | 76 | 77 | true 78 | 79 | 80 | 81 | false 82 | {"method":"personal_sendTransaction", 83 | "params":[ 84 | { 85 | "from":"0x00a329c0648769a73afac7f9381e08fb43dbea72", 86 | "to":"0x0000000000000000000000000000000000000000", 87 | "value":"0x1"}, 88 | ""], 89 | "id":${ctr}, 90 | "jsonrpc":"2.0"} 91 | = 92 | 93 | 94 | 95 | localhost 96 | 8545 97 | http 98 | 99 | 100 | POST 101 | true 102 | false 103 | true 104 | false 105 | true 106 | true 107 | 2 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Host 117 | ${vhost} 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | continue 126 | 127 | false 128 | 1 129 | 130 | 1 131 | 10 132 | 1363247040000 133 | 1363247040000 134 | false 135 | 0 136 | 0 137 | true 138 | 139 | 140 | 141 | 0 142 | 9999999999999 143 | 1 144 | blockid 145 | 146 | false 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | true 155 | 156 | 157 | 158 | false 159 | {"method":"eth_getBlockByNumber", 160 | "params": [ 161 | "latest", 162 | false 163 | ], 164 | "id":1, 165 | "jsonrpc":"2.0"} 166 | = 167 | 168 | 169 | 170 | localhost 171 | 8545 172 | http 173 | 174 | 175 | POST 176 | true 177 | false 178 | true 179 | false 180 | true 181 | true 182 | 2 183 | 184 | 185 | 186 | 187 | 188 | 189 | $.result.number 190 | ${last_block} 191 | true 192 | false 193 | true 194 | false 195 | 196 | 197 | 198 | 199 | 200 | false 201 | 202 | saveConfig 203 | 204 | 205 | true 206 | true 207 | true 208 | 209 | true 210 | true 211 | true 212 | true 213 | false 214 | true 215 | true 216 | false 217 | false 218 | false 219 | true 220 | false 221 | false 222 | false 223 | true 224 | 0 225 | true 226 | true 227 | true 228 | true 229 | true 230 | 231 | 232 | 233 | 234 | 235 | 236 | false 237 | 238 | saveConfig 239 | 240 | 241 | true 242 | true 243 | true 244 | 245 | true 246 | true 247 | true 248 | true 249 | false 250 | true 251 | true 252 | false 253 | false 254 | false 255 | true 256 | false 257 | false 258 | false 259 | true 260 | 0 261 | true 262 | true 263 | true 264 | true 265 | true 266 | 267 | 268 | 269 | 270 | 271 | 272 | false 273 | 274 | saveConfig 275 | 276 | 277 | true 278 | true 279 | true 280 | 281 | true 282 | true 283 | true 284 | true 285 | false 286 | true 287 | true 288 | false 289 | false 290 | false 291 | true 292 | false 293 | false 294 | false 295 | true 296 | 0 297 | true 298 | true 299 | true 300 | true 301 | true 302 | 303 | 304 | 305 | 306 | 307 | 308 | false 309 | 310 | saveConfig 311 | 312 | 313 | true 314 | true 315 | true 316 | 317 | true 318 | true 319 | true 320 | true 321 | false 322 | true 323 | true 324 | false 325 | false 326 | false 327 | true 328 | false 329 | false 330 | false 331 | true 332 | 0 333 | true 334 | true 335 | true 336 | true 337 | true 338 | 339 | 340 | 341 | 342 | 343 | 344 | false 345 | 346 | saveConfig 347 | 348 | 349 | true 350 | true 351 | true 352 | 353 | true 354 | true 355 | true 356 | true 357 | false 358 | true 359 | true 360 | false 361 | false 362 | false 363 | true 364 | false 365 | false 366 | false 367 | true 368 | 0 369 | true 370 | true 371 | true 372 | true 373 | true 374 | 375 | 376 | 377 | 378 | 379 | 380 | false 381 | 382 | saveConfig 383 | 384 | 385 | true 386 | true 387 | true 388 | 389 | true 390 | true 391 | true 392 | true 393 | false 394 | true 395 | true 396 | false 397 | false 398 | false 399 | true 400 | false 401 | false 402 | false 403 | true 404 | 0 405 | true 406 | true 407 | true 408 | true 409 | true 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | true 418 | 419 | 420 | 421 | 422 | -------------------------------------------------------------------------------- /load_tests/src/test/groovy/EthSendRawTransactionBasic10000SpockTest.groovy: -------------------------------------------------------------------------------- 1 | import groovy.json.JsonSlurper 2 | import groovyx.gpars.ParallelEnhancer 3 | import groovyx.net.http.HTTPBuilder 4 | import org.joda.time.DateTime 5 | import org.joda.time.Period 6 | import org.joda.time.PeriodType 7 | import spock.lang.Ignore 8 | import spock.lang.Shared 9 | import spock.lang.Specification 10 | import spock.lang.Unroll 11 | 12 | import java.util.concurrent.ConcurrentHashMap 13 | 14 | import static groovyx.gpars.GParsPool.withPool 15 | import static groovyx.net.http.ContentType.JSON 16 | import static groovyx.net.http.Method.POST 17 | 18 | class EthSendRawTransactionBasic10000SpockTest extends Specification { 19 | 20 | JsonRpcClient jsonRpcClient = new JsonRpcClient("http://localhost:8545/") 21 | @Shared 22 | String fileContents = new File('src/test/resources/eth_sendRawTransaction_basic_10000.rpc').getText('UTF-8') 23 | 24 | @Ignore("Useful for development, but not enough for stable results, use Submit 10k Transactions") 25 | @Unroll("Transactions #from to #to eth_sendRawTransaction over JSON-RPC should return zero #errorResults errors and throughput should be better that #throughputEst TPS") 26 | def "Submit 100 Transactions"() { 27 | expect: 28 | def lines = fileContents.readLines().subList(from, to) 29 | ConcurrentHashMap errors = new ConcurrentHashMap() 30 | ConcurrentHashMap results = new ConcurrentHashMap() 31 | ArrayList blockTimes = new ArrayList() 32 | ParallelEnhancer.enhanceInstance(lines) 33 | long start 34 | long now 35 | 36 | def benchmark = { closure -> 37 | start = System.currentTimeMillis() 38 | withPool(clientThreads) { 39 | lines.each { 40 | def json = new JsonSlurper().parseText(it) 41 | def result = jsonRpcClient.eth_sendRawTransaction(json.params[0]) 42 | if (result.error) { 43 | errors.put(json.id, result.error) 44 | } else { 45 | results.put(json.id, result.result) 46 | } 47 | } 48 | } 49 | now = System.currentTimeMillis() 50 | now - start 51 | } 52 | 53 | def duration = benchmark { 54 | (0..10000).inject(0) { sum, item -> 55 | sum + item 56 | } 57 | } 58 | println "Transactions submitted in ${duration} ms with ${errors.size()} errors" 59 | 60 | errors.size() == 0 61 | results.size() == 100 62 | 63 | def (Period blockPeriodMillis, throughputTps) = getResults(results, blockTimes) 64 | 65 | blockPeriodMillis.seconds <= submitTime 66 | throughputTps >= throughputEst 67 | 68 | where: 69 | from | to | clientThreads | submitTime | throughputEst 70 | 100 | 200 | 3 | 10 | 1 71 | 200 | 300 | 3 | 10 | 1 72 | 300 | 400 | 3 | 10 | 1 73 | 400 | 500 | 3 | 10 | 1 74 | } 75 | 76 | def "Submit 10k Transactions"() { 77 | expect: 78 | def lines = fileContents.readLines().subList(from, to) 79 | ConcurrentHashMap errors = new ConcurrentHashMap() 80 | ConcurrentHashMap results = new ConcurrentHashMap() 81 | ArrayList blockTimes = new ArrayList() 82 | ParallelEnhancer.enhanceInstance(lines) 83 | long start 84 | long now 85 | 86 | def benchmark = { closure -> 87 | start = System.currentTimeMillis() 88 | withPool(clientThreads) { 89 | lines.each { 90 | def json = new JsonSlurper().parseText(it) 91 | def result = jsonRpcClient.eth_sendRawTransaction(json.params[0]) 92 | if (result.error) { 93 | errors.put(json.id, result.error) 94 | } else { 95 | results.put(json.id, result.result) 96 | } 97 | } 98 | } 99 | now = System.currentTimeMillis() 100 | now - start 101 | } 102 | 103 | def duration = benchmark { 104 | (0..10000).inject(0) { sum, item -> 105 | sum + item 106 | } 107 | } 108 | println "Transactions submitted in ${duration} ms with ${errors.size()} errors" 109 | 110 | errors.size() == 0 111 | 112 | def (Period blockPeriodMillis, throughputTps) = getResults(results, blockTimes) 113 | 114 | blockPeriodMillis.seconds <= submitTime 115 | throughputTps >= throughputEst 116 | 117 | where: 118 | from | to | clientThreads | submitTime | throughputEst 119 | 0 | 10000 | 3 | 10 | 1 120 | } 121 | 122 | List getResults(ConcurrentHashMap results, ArrayList blockTimes) { 123 | results.each { 124 | def blockHash = jsonRpcClient.eth_getTransactionByHash(it.value).result.blockHash 125 | def transactionBlockTimeStamp = jsonRpcClient.eth_getBlockByHash(blockHash, true).result.timestamp 126 | blockTimes.add(new DateTime((new BigInteger(transactionBlockTimeStamp.substring(2), 16) as long) * 1000L)) 127 | } 128 | 129 | Collections.sort(blockTimes) 130 | Period blockPeriodMillis = new Period(blockTimes.first(), blockTimes.last(), PeriodType.millis()); 131 | Period blockPeriodSecs = new Period(blockTimes.first(), blockTimes.last(), PeriodType.seconds()); 132 | def throughputTps = (to - from) / blockPeriodSecs.seconds 133 | 134 | println "first block time ${blockTimes.first()}, last block time ${blockTimes.last()} \n" 135 | println "time to process all blocks ${blockPeriodSecs.seconds} s \n" 136 | println "Average throughput ${throughputTps} TPS \n" 137 | [blockPeriodMillis, throughputTps] 138 | } 139 | } 140 | 141 | class JsonRpcClient extends HTTPBuilder { 142 | JsonRpcClient(String uri) { 143 | super(uri) 144 | } 145 | 146 | def methodMissing(String name, args) { 147 | def result 148 | request(POST, JSON) { req -> 149 | body = [ 150 | "jsonrpc": "2.0", 151 | "method" : name, 152 | "params" : args, "id": 1] 153 | response.success = { resp, json -> result = json } 154 | } 155 | return result 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /load_tests/submit_corpus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while read obj; do 3 | curl -H "Content-Type: application/json" -X POST localhost:8545 --data $obj 4 | done < $1 5 | -------------------------------------------------------------------------------- /monitor/app.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name" : "host1", 4 | "script" : "app.js", 5 | "log_date_format" : "YYYY-MM-DD HH:mm Z", 6 | "merge_logs" : false, 7 | "watch" : true, 8 | "max_restarts" : 10, 9 | "exec_interpreter" : "node", 10 | "exec_mode" : "fork_mode", 11 | "env": 12 | { 13 | "NODE_ENV" : "production", 14 | "RPC_HOST" : "host1", 15 | "RPC_PORT" : "8545", 16 | "LISTENING_PORT" : "30303", 17 | "INSTANCE_NAME" : "host1", 18 | "WS_SERVER" : "ws://dashboard:3000", 19 | "WS_SECRET" : "OurDashSecret93%", 20 | "VERBOSITY" : 3 21 | } 22 | }, 23 | { 24 | "name" : "host2", 25 | "script" : "app.js", 26 | "log_date_format" : "YYYY-MM-DD HH:mm Z", 27 | "merge_logs" : false, 28 | "watch" : true, 29 | "max_restarts" : 10, 30 | "exec_interpreter" : "node", 31 | "exec_mode" : "fork_mode", 32 | "env": 33 | { 34 | "NODE_ENV" : "production", 35 | "RPC_HOST" : "host2", 36 | "RPC_PORT" : "8545", 37 | "LISTENING_PORT" : "30303", 38 | "INSTANCE_NAME" : "host2", 39 | "WS_SERVER" : "ws://dashboard:3000", 40 | "WS_SECRET" : "OurDashSecret93%", 41 | "VERBOSITY" : 3 42 | } 43 | }, 44 | { 45 | "name" : "host3", 46 | "script" : "app.js", 47 | "log_date_format" : "YYYY-MM-DD HH:mm Z", 48 | "merge_logs" : false, 49 | "watch" : true, 50 | "max_restarts" : 10, 51 | "exec_interpreter" : "node", 52 | "exec_mode" : "fork_mode", 53 | "env": 54 | { 55 | "NODE_ENV" : "production", 56 | "RPC_HOST" : "host3", 57 | "RPC_PORT" : "8545", 58 | "LISTENING_PORT" : "30303", 59 | "INSTANCE_NAME" : "host3", 60 | "WS_SERVER" : "ws://dashboard:3000", 61 | "WS_SECRET" : "OurDashSecret93%", 62 | "VERBOSITY" : 3 63 | } 64 | } 65 | 66 | ] 67 | -------------------------------------------------------------------------------- /parity-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Parity Technologies (UK) Ltd. 3 | CHAIN_NAME="parity" 4 | CHAIN_NODES="1" 5 | CLIENT="0" 6 | DOCKER_INCLUDE="include/docker-compose.yml" 7 | help() { 8 | 9 | echo "parity-deploy.sh OPTIONS 10 | Usage: 11 | REQUIRED: 12 | --config dev / aura / tendermint / validatorset / input.json / custom_chain.toml 13 | 14 | OPTIONAL: 15 | --name name_of_chain. Default: parity 16 | --nodes number_of_nodes (if using aura / tendermint) Default: 2 17 | --ethstats - Enable ethstats monitoring of authority nodes. Default: Off 18 | --expose - Expose a specific container on ports 8180 / 8545 / 30303. Default: Config specific 19 | --entrypoint - Use custom entrypoint for docker container e.g. /home/parity/bin/parity 20 | 21 | NOTE: 22 | input.json - Custom spec files can be inserted by specifiying the path to the json file. 23 | custom_chain.toml - Custom toml file defining multiple nodes. See customchain/config/example.toml for an example. 24 | " 25 | 26 | } 27 | 28 | check_packages() { 29 | 30 | if [ $(grep -i debian /etc/*-release | wc -l) -gt 0 ]; then 31 | if [ ! -f /usr/bin/docker ]; then 32 | sudo apt-get -y install docker.io python-pip 33 | fi 34 | 35 | if [ ! -f /usr/local/bin/docker-compose ]; then 36 | sudo pip install docker-compose 37 | fi 38 | fi 39 | } 40 | 41 | genpw() { 42 | 43 | openssl rand -base64 12 44 | 45 | } 46 | 47 | create_node_params() { 48 | 49 | local DEST_DIR=deployment/$1 50 | if [ ! -d $DEST_DIR ]; then 51 | mkdir -p $DEST_DIR 52 | fi 53 | 54 | if [ ! -f $DEST_DIR/password ]; then 55 | openssl rand -base64 12 >$DEST_DIR/password 56 | fi 57 | ./config/utils/keygen.sh $DEST_DIR 58 | 59 | PASSWORD=$(cat $DEST_DIR/password) 60 | PRIV_KEY=$(cat $DEST_DIR/key.priv) 61 | ./ethstore insert ${PRIV_KEY} $DEST_DIR/password --dir $DEST_DIR/parity >$DEST_DIR/address.txt 62 | 63 | echo "NETWORK_NAME=$CHAIN_NAME" >.env 64 | 65 | } 66 | 67 | create_reserved_peers_poa() { 68 | 69 | PUB_KEY=$(cat deployment/$1/key.pub) 70 | echo "enode://$PUB_KEY@host$1:30303" >>deployment/chain/reserved_peers 71 | } 72 | 73 | create_reserved_peers_instantseal() { 74 | 75 | PUB_KEY=$(cat deployment/$1/key.pub) 76 | echo "enode://$PUB_KEY@127.0.0.1:30303" >>deployment/chain/reserved_peers 77 | 78 | } 79 | 80 | build_spec() { 81 | 82 | display_header 83 | display_name 84 | display_engine 85 | display_params 86 | display_genesis 87 | display_accounts 88 | display_footer 89 | 90 | } 91 | 92 | build_docker_config_poa() { 93 | 94 | echo "version: '2.0'" >docker-compose.yml 95 | echo "services:" >>docker-compose.yml 96 | 97 | for x in $(seq 1 $CHAIN_NODES); do 98 | cat config/docker/authority.yml | sed -e "s/NODE_NAME/$x/g" | sed -e "s@-d /home/parity/data@-d /home/parity/data $PARITY_OPTIONS@g" >>docker-compose.yml 99 | mkdir -p data/$x 100 | done 101 | 102 | build_docker_config_ethstats 103 | 104 | cat $DOCKER_INCLUDE >>docker-compose.yml 105 | 106 | chown -R $USER data/ 107 | 108 | } 109 | 110 | build_docker_config_ethstats() { 111 | 112 | if [ "$ETHSTATS" == "1" ]; then 113 | cat include/ethstats.yml >>docker-compose.yml 114 | fi 115 | } 116 | 117 | build_docker_config_instantseal() { 118 | 119 | cat config/docker/instantseal.yml | sed -e "s@-d /home/parity/data@-d /home/parity/data $PARITY_OPTIONS@g" >docker-compose.yml 120 | 121 | build_docker_config_ethstats 122 | 123 | cat $DOCKER_INCLUDE >>docker-compose.yml 124 | 125 | mkdir -p data/is_authority 126 | 127 | chown -R $USER data/ 128 | } 129 | 130 | build_docker_client() { 131 | 132 | if [ "$CLIENT" == "1" ]; then 133 | create_node_params client 134 | cp config/spec/client.toml deployment/client/ 135 | cat config/docker/client.yml >>docker-compose.yml 136 | 137 | # writing client dependencies 138 | if [ "$CHAIN_NODES" -gt "0" ]; then 139 | echo " depends_on:" >>docker-compose.yml 140 | 141 | for x in $(seq 1 $CHAIN_NODES); do 142 | echo " - \"host${x}\"" >>docker-compose.yml 143 | done 144 | fi 145 | fi 146 | } 147 | 148 | build_custom_chain() { 149 | 150 | if [ -z "$CUSTOM_CHAIN" ]; then 151 | echo "Must specify argument for custom chain option." 152 | exit 1 153 | fi 154 | 155 | ./customchain/generate.py "$CUSTOM_CHAIN" 156 | 157 | exit 0 158 | } 159 | 160 | display_header() { 161 | 162 | cat config/spec/chain_header 163 | 164 | } 165 | 166 | display_footer() { 167 | 168 | cat config/spec/chain_footer 169 | } 170 | 171 | display_name() { 172 | 173 | cat config/spec/name | sed -e "s/CHAIN_NAME/$CHAIN_NAME/g" 174 | } 175 | 176 | create_node_config_poa() { 177 | 178 | ENGINE_SIGNER=$(cat deployment/$1/address.txt) 179 | cat config/spec/authority_round.toml | sed -e "s/ENGINE_SIGNER/$ENGINE_SIGNER/g" >deployment/$1/authority.toml 180 | 181 | } 182 | 183 | create_node_config_instantseal() { 184 | 185 | ENGINE_SIGNER=$(cat deployment/$1/address.txt) 186 | cat config/spec/instant_seal.toml | sed -e "s/ENGINE_SIGNER/$ENGINE_SIGNER/g" >deployment/$1/authority.toml 187 | 188 | } 189 | 190 | expose_container() { 191 | 192 | sed -i "s@container_name: $1@&\n ports:\n - 8080:8080\n - 8180:8180\n - 8545:8545\n - 8546:8546\n - 30303:30303@g" docker-compose.yml 193 | 194 | } 195 | 196 | select_exposed_container() { 197 | 198 | if [ -n "$EXPOSE_CLIENT" ]; then 199 | expose_container $EXPOSE_CLIENT 200 | else 201 | if [ "$CLIENT" == "0" ]; then 202 | expose_container host1 203 | fi 204 | fi 205 | 206 | } 207 | 208 | display_engine() { 209 | 210 | case $CHAIN_ENGINE in 211 | dev) 212 | cat config/spec/engine/instantseal 213 | ;; 214 | aura | validatorset | tendermint) 215 | for x in $(seq 1 $CHAIN_NODES); do 216 | VALIDATOR=$(cat deployment/$x/address.txt) 217 | RESERVED_PEERS="$RESERVED_PEERS $VALIDATOR" 218 | VALIDATORS="$VALIDATORS \"$VALIDATOR\"," 219 | done 220 | # Remove trailing , from validator list 221 | VALIDATORS=$(echo $VALIDATORS | sed 's/\(.*\),.*/\1/') 222 | cat config/spec/engine/$CHAIN_ENGINE | sed -e "s/0x0000000000000000000000000000000000000000/$VALIDATORS/g" 223 | ;; 224 | *) 225 | echo "Unknown engine: $CHAIN_ENGINE" 226 | ;; 227 | esac 228 | 229 | } 230 | 231 | display_params() { 232 | 233 | cat config/spec/params/$CHAIN_ENGINE 234 | 235 | } 236 | 237 | display_genesis() { 238 | 239 | cat config/spec/genesis/$CHAIN_ENGINE 240 | 241 | } 242 | 243 | display_accounts() { 244 | 245 | cat config/spec/accounts/$CHAIN_ENGINE 246 | 247 | } 248 | 249 | ARGS="$@" 250 | 251 | while [ "$1" != "" ]; do 252 | case $1 in 253 | --name) 254 | shift 255 | CHAIN_NAME=$1 256 | ;; 257 | -c | --config) 258 | shift 259 | CHAIN_ENGINE=$1 260 | ;; 261 | -n | --nodes) 262 | shift 263 | CHAIN_NODES=$1 264 | ;; 265 | -r | --release) 266 | shift 267 | PARITY_RELEASE=$1 268 | ;; 269 | -e | --ethstats) 270 | ETHSTATS=1 271 | ;; 272 | --enable-client) 273 | CLIENT=1 274 | ;; 275 | --expose) 276 | shift 277 | EXPOSE_CLIENT="$1" 278 | ;; 279 | --chain) 280 | shift 281 | CHAIN_NETWORK=$1 282 | ;; 283 | --entrypoint) 284 | shift 285 | ENTRYPOINT=$1 286 | ;; 287 | -h | --help) 288 | help 289 | exit 290 | ;; 291 | *) PARITY_OPTIONS="$PARITY_OPTIONS $1 " ;; 292 | esac 293 | shift 294 | done 295 | 296 | if [ -z "$CHAIN_ENGINE" ] && [ -z "$CHAIN_NETWORK" ]; then 297 | echo "No chain argument, exiting..." 298 | exit 1 299 | fi 300 | 301 | mkdir -p deployment/chain 302 | check_packages 303 | 304 | echo $CHAIN_ENGINE | grep -q toml 305 | if [ $? -eq 0 ]; then 306 | ./customchain/generate.py "$CHAIN_ENGINE" 307 | exit 0 308 | fi 309 | 310 | if [ ! -z "$CHAIN_NETWORK" ]; then 311 | if [ ! -z "$PARITY_OPTIONS" ]; then 312 | cat config/docker/chain.yml | sed -e "s/CHAIN_NAME/$CHAIN_NETWORK/g" | sed -e "s@-d /home/parity/data@-d /home/parity/data $PARITY_OPTIONS@g" >docker-compose.yml 313 | 314 | else 315 | cat config/docker/chain.yml | sed -e "s/CHAIN_NAME/$CHAIN_NETWORK/g" >docker-compose.yml 316 | fi 317 | 318 | elif [ "$CHAIN_ENGINE" == "dev" ]; then 319 | echo "using instantseal" 320 | create_node_params is_authority 321 | create_reserved_peers_instantseal is_authority 322 | create_node_config_instantseal is_authority 323 | build_docker_config_instantseal 324 | 325 | elif [ "$CHAIN_ENGINE" == "aura" ] || [ "$CHAIN_ENGINE" == "validatorset" ] || [ "$CHAIN_ENGINE" == "tendermint" ] || [ -f "$CHAIN_ENGINE" ]; then 326 | if [ $CHAIN_NODES ]; then 327 | for x in $(seq $CHAIN_NODES); do 328 | create_node_params $x 329 | create_reserved_peers_poa $x 330 | create_node_config_poa $x 331 | done 332 | build_docker_config_poa 333 | build_docker_client 334 | fi 335 | 336 | if [ "$CHAIN_ENGINE" == "aura" ] || [ "$CHAIN_ENGINE" == "validatorset" ] || [ "$CHAIN_ENGINE" == "tendermint" ]; then 337 | build_spec >deployment/chain/spec.json 338 | else 339 | mkdir -p deployment/chain 340 | cp $CHAIN_ENGINE deployment/chain/spec.json 341 | fi 342 | 343 | else 344 | 345 | echo "Could not find spec file: $CHAIN_ENGINE" 346 | fi 347 | 348 | if [ ! -z $PARITY_RELEASE ]; then 349 | echo "Custom release ${PARITY_RELEASE} selected. WARNING: This may not be compatible with all parity docker images" 350 | DOCKER_TMP=$(mktemp) 351 | cat docker-compose.yml | sed -e "s@image: parity/parity:stable@image: parity/parity:${PARITY_RELEASE}@g" > $DOCKER_TMP 352 | mv $DOCKER_TMP docker-compose.yml 353 | fi 354 | 355 | if [ ! -z $ENTRYPOINT ]; then 356 | ENTRYPOINT_TMP=$(mktemp) 357 | cat docker-compose.yml | sed -e "s@user: root@user: root\n entrypoint: ${ENTRYPOINT}@g" > $ENTRYPOINT_TMP 358 | mv $ENTRYPOINT_TMP docker-compose.yml 359 | fi 360 | 361 | select_exposed_container 362 | --------------------------------------------------------------------------------