├── .gitignore ├── LICENSE ├── README.md ├── base-build ├── Dockerfile.botnet ├── Dockerfile.mwixnet ├── Dockerfile.node.master └── Dockerfile.wallet ├── base-olivetin ├── Dockerfile └── owner_api_client │ ├── package.json │ └── src │ ├── create_wallet.js │ ├── owner_api_client.js │ ├── wallet_info.js │ └── wallet_txs.js ├── botnet ├── botnet.md ├── docker-compose.yml └── sample_start.json ├── client ├── .eslintrc.json ├── .tern-project ├── client.js ├── grinapi.js └── package.json ├── controller ├── .eslintrc.json ├── .tern-project ├── package.json └── server.js ├── devnet ├── docker-compose.yml ├── send_miner_to_wallet_2.sh ├── wallet_info_2.sh └── wallet_info_miner.sh ├── monitor ├── config │ └── combined.yaml ├── json-rpc │ └── node │ │ ├── execute_get_block.sh │ │ ├── execute_get_outputs.sh │ │ ├── execute_get_status.sh │ │ ├── get_block.json │ │ ├── get_outputs.json │ │ ├── get_status.json │ │ └── get_tip.json ├── main │ └── docker-compose.yml └── test │ └── docker-compose.yml ├── mwixnet ├── main │ └── docker-compose.yml ├── scripts │ └── mwixnet-first-run.sh └── test │ └── docker-compose.yml ├── mwixnetx3 ├── config │ └── olivetin.yaml └── test │ ├── compose.override.yaml │ └── docker-compose.yml ├── node ├── configs │ ├── mainnet │ │ └── grin-server.toml │ └── testnet │ │ └── grin-server.toml ├── main │ └── docker-compose.yml └── test │ └── docker-compose.yml ├── scripts └── docker_cleanup.sh └── wallet ├── main └── contracts │ └── docker-compose.yml ├── scripts └── wallet-first-run.sh └── test └── contracts └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json -------------------------------------------------------------------------------- /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 | # Grin Docker images 2 | 3 | ## Please note that these images are currently leaving wallet and mwixnet passwords blank, and it's not yet advised to use these images for production nodes. (This should be addressed in a future update) 4 | 5 | # Build and testing 6 | 7 | ## Basic usage 8 | 9 | Install docker. Docker images first need to be build using *docker-compose build* and subsequently can be run using *docker-compose up -d* 10 | To build a docker image, go to a directory that contains a *docker-compose.yml* file and run *docker-compose* within that directory. 11 | The list of directories below contain a *docker-compose.yml* to build you docker image from. 12 | 13 | `node/main` -> Builds and deploys a mainnet node from grin latest master 14 | `node/test` -> Builds and deploys a testnet node from grin latest master 15 | `wallet/main/contracts` -> Builds and deploys a mainnet wallet communicating with a node deployed by `node/main` 16 | `monitor/main` -> Build and deploys an monitor node based on OliveTin allowing user to run node commands via a web gui 17 | `monitor/test` -> As above, but against testnet. 18 | `mwixnet/test` -> Runs an mwixnet node against a node and wallet 19 | `mwixnetx3/test` -> Runs a testnet node, three wallets, three linked mwixnet nodes and a monitor for testing 20 | 21 | Images are in the middle of being updated to 'modern Grin' (5.4.0+), and currently working compose files are: 22 | For now, a typical workflow would be: 23 | 24 | ``` 25 | cd node/main 26 | docker-compose build 27 | docker-compose up -d 28 | cd ../../monitor/node/main 29 | docker-compose up -d 30 | ``` 31 | 32 | This will start a mainnet node, and present a (still rudimentary) web interface allowing the user to check the node sync status at `http://localhost:1337/` 33 | 34 | The docker file at `wallet/main/contracts` currently runs a wallet built with the contracts branch, and exposes the owner and foreign APIs to other services in the docker context. Samples of how to access this are in `monitor/wallet/owner_api_client`, and these services will be built into an OliveTin monitor application to allow deployers to create, manage and query wallet instances. 35 | 36 | ## Other Notes 37 | 38 | * All containers are stateless, containing no user-specific data within the images themselves. The docker-compose files create separate volumes for user-specific data such as node sync and wallet data. Other deployments in the context can then mount these volumes to share api secrets, etc. This also means that data on volumes persists unless explicitly deleted (so no need to re-sync if you delete and rebuild a container.) 39 | * All compose files currently assume they're running in the same docker context, next steps will be using Kubernetes to allow deployments in more flexible configuations. 40 | * Containers for running mwmixnet nodes will be added shortly, allowing for quick startup and teardown of testing mwixnet networks, (which require 3 separate instances ideally talking to 3 separate wallets). 41 | 42 | ## Handy Commands 43 | 44 | To build images, as defined by the docker compose files in these directories 45 | ``` 46 | docker-compose build 47 | ``` 48 | This will build a docker image called grin-min 49 | 50 | To run (attached to terminal) 51 | 52 | ``` 53 | docker-compose up 54 | ``` 55 | 56 | This will start networks, containers using the images, and log everything to the console. 57 | 58 | To run detached: 59 | ``` 60 | docker-compose up -d 61 | ``` 62 | Then check logs with 63 | ``` 64 | docker-compose logs 65 | ``` 66 | 67 | Detaching from the console via ctrl-c (when not running with -d) will stop the containers. Another 68 | docker-compose up command will continue where they left off. 69 | 70 | ``` 71 | docker-compose down 72 | ``` 73 | 74 | Will reset and remove all containers. Volumes should be maintained. 75 | 76 | ## other handy commands 77 | 78 | Execute and attach to a shell inside a particular container as root: 79 | ``` 80 | docker exec -u 0 -it grindocker_grin-wallet_1 /bin/bash 81 | ``` 82 | 83 | Delete all images (to rebuild from scratch): 84 | ``` 85 | docker rmi $(docker images -q) 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /base-build/Dockerfile.botnet: -------------------------------------------------------------------------------- 1 | ####################### 2 | # BUILD # 3 | ####################### 4 | # Base build of grin docker image 5 | 6 | #use official rust docker image (debian based) 7 | FROM rust:1.24-stretch as grin_build 8 | #needs cmake, node packages (for controller) 9 | RUN apt-get update && apt-get -y install cmake clang 10 | #checkout source fresh and build 11 | WORKDIR /usr/src 12 | RUN git clone https://github.com/mimblewimble/grin.git 13 | WORKDIR /usr/src/grin 14 | RUN cargo build 15 | 16 | ####################### 17 | # DEPLOY # 18 | ####################### 19 | #Deploy binaries to a minimal image 20 | 21 | FROM debian:stretch 22 | #FROM rust:1.21-stretch 23 | MAINTAINER yeastplume version:0.1 24 | COPY --from=grin_build /usr/src/grin/target/debug/grin /usr/bin/grin 25 | COPY --from=grin_build /usr/src/grin/target/debug/plugins/ /usr/lib/grin/plugins 26 | RUN apt-get update && apt-get -y install curl \ 27 | && apt-get install -y gnupg \ 28 | && curl -sL https://deb.nodesource.com/setup_6.x | bash - \ 29 | && apt install -y nodejs \ 30 | && apt install -y build-essential libssl-dev \ 31 | && apt install -y procps \ 32 | && useradd -m grinuser \ 33 | && mkdir /home/grinuser/wallet \ 34 | && chown -R grinuser:grinuser /home/grinuser/wallet 35 | COPY --from=grin_build /usr/src/grin/grin.toml /home/grinuser/.grin/grin.toml 36 | COPY controller/*.js controller/package.json /home/grinuser/controller/ 37 | RUN sed -i 's/.*cuckoo_miner_plugin_dir.*/cuckoo_miner_plugin_dir = "\/usr\/lib\/grin\/plugins"/g' /home/grinuser/.grin/grin.toml \ 38 | && sed -i 's/.*file_log_level.*/file_log_level = "Debug"/g' /home/grinuser/.grin/grin.toml \ 39 | && sed -i 's/.*api_http_addr.*/api_http_addr = "0.0.0.0:13413"/g' /home/grinuser/.grin/grin.toml \ 40 | && sed -i 's/.*host.*=.*/host = "0.0.0.0"/g' /home/grinuser/.grin/grin.toml \ 41 | # && sed -i 's/.*mining_parameter_mode.*/mining_parameter_mode = "Production"/g' /home/grinuser/.grin/grin.toml 42 | && chown -R grinuser:grinuser /home/grinuser/.grin \ 43 | && chown -R grinuser:grinuser /home/grinuser/controller 44 | USER grinuser 45 | WORKDIR /home/grinuser/controller 46 | RUN npm install 47 | WORKDIR /home/grinuser 48 | ENTRYPOINT ["node", "controller/server.js" ] 49 | # forward grin logs to docker log collector on stdout 50 | RUN ln -sf /proc/1/fd/1 /home/grinuser/grin.log \ 51 | && ln -sf /proc/1/fd/1 /home/grinuser/wallet/grin.log 52 | -------------------------------------------------------------------------------- /base-build/Dockerfile.mwixnet: -------------------------------------------------------------------------------- 1 | ####################### 2 | # BUILD # 3 | ####################### 4 | 5 | # Base build of mwixnet build docker image, from master at the moment 6 | 7 | #use official rust docker image (debian based) 8 | FROM rust:latest as grin_mwixnet_build 9 | 10 | # Mwixnet 11 | # needs cmake 12 | RUN apt-get update && apt-get -y install cmake clang && apt-get -y install tor 13 | #RUN apt-get -y install libreadline-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev 14 | #checkout source fresh and build 15 | WORKDIR /usr/src 16 | RUN git clone https://github.com/mimblewimble/mwixnet.git 17 | 18 | ####################### 19 | # DEPLOY # 20 | ####################### 21 | #Deploy binaries to a minimal image 22 | 23 | FROM grin_mwixnet_build as grin_mwixnet_master 24 | WORKDIR /usr/src/mwixnet 25 | RUN cargo build --release 26 | LABEL maintainer="yeastplume" description="Grin Mwixnet - Build from master branch" 27 | RUN cp /usr/src/mwixnet/target/release/mwixnet /usr/bin/mwixnet 28 | RUN useradd -m grinuser 29 | USER grinuser 30 | RUN mkdir -p /home/grinuser/.grin/main 31 | RUN mkdir -p /home/grinuser/.grin/test 32 | WORKDIR /home/grinuser 33 | ENTRYPOINT ["/home/grinuser/mwixnet-first-run.sh"] -------------------------------------------------------------------------------- /base-build/Dockerfile.node.master: -------------------------------------------------------------------------------- 1 | ####################### 2 | # BUILD # 3 | ####################### 4 | 5 | # Base build of grin docker image 6 | 7 | #use official rust docker image (debian based) 8 | FROM rust:latest as grin_build 9 | 10 | # Grin node 11 | # needs cmake 12 | RUN apt-get update && apt-get -y install cmake clang curl 13 | #RUN apt-get -y install libreadline-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev 14 | #checkout source fresh and build 15 | WORKDIR /usr/src 16 | RUN git clone https://github.com/yeastplume/grin.git 17 | RUN git checkout cursive_update 18 | WORKDIR /usr/src/grin 19 | RUN cargo build --release 20 | 21 | ####################### 22 | # DEPLOY # 23 | ####################### 24 | #Deploy binaries to a minimal image 25 | 26 | FROM grin_build as grin_node_master 27 | LABEL maintainer="yeastplume" description="Minimal Grin Node - Build from master" 28 | COPY --from=grin_build /usr/src/grin/target/release/grin /usr/bin/grin 29 | RUN useradd -m grinuser 30 | USER grinuser 31 | RUN mkdir -p /home/grinuser/.grin/main 32 | RUN mkdir -p /home/grinuser/.grin/test 33 | 34 | WORKDIR /home/grinuser 35 | 36 | ENTRYPOINT ["/usr/bin/grin"] -------------------------------------------------------------------------------- /base-build/Dockerfile.wallet: -------------------------------------------------------------------------------- 1 | ####################### 2 | # BUILD # 3 | ####################### 4 | 5 | # Base build of grin docker image 6 | 7 | #use official rust docker image (debian based) 8 | FROM rust:latest as grin_wallet_build 9 | 10 | # Grin node 11 | # needs cmake 12 | RUN apt-get update && apt-get -y install cmake clang curl 13 | #RUN apt-get -y install libreadline-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev 14 | #checkout source fresh and build 15 | WORKDIR /usr/src 16 | RUN git clone https://github.com/mimblewimble/grin-wallet.git 17 | 18 | ####################### 19 | # DEPLOY # 20 | ####################### 21 | #Deploy binaries to a minimal image 22 | 23 | FROM grin_wallet_build as grin_wallet_contracts 24 | WORKDIR /usr/src/grin-wallet 25 | RUN git checkout contracts 26 | RUN cargo build --release 27 | LABEL maintainer="yeastplume" description="Grin Wallet - Build from contracts branch" 28 | RUN cp /usr/src/grin-wallet/target/release/grin-wallet /usr/bin/grin-wallet 29 | RUN useradd -m grinuser 30 | USER grinuser 31 | #RUN mkdir -p /home/grinuser/.grin/main 32 | #RUN mkdir -p /home/grinuser/.grin/test 33 | WORKDIR /home/grinuser 34 | ENTRYPOINT ["/home/grinuser/wallet-first-run.sh"] 35 | 36 | FROM grin_wallet_build as grin_wallet_master 37 | WORKDIR /usr/src/grin-wallet 38 | RUN git checkout master 39 | RUN cargo build --release 40 | LABEL maintainer="yeastplume" description="Grin Wallet - Build from master" 41 | RUN cp /usr/src/grin-wallet/target/release/grin-wallet /usr/bin/grin-wallet 42 | RUN useradd -m grinuser 43 | USER grinuser 44 | #RUN mkdir -p /home/grinuser/.grin/main 45 | #RUN mkdir -p /home/grinuser/.grin/test 46 | WORKDIR /home/grinuser 47 | ENTRYPOINT ["/home/grinuser/wallet-first-run.sh"] -------------------------------------------------------------------------------- /base-olivetin/Dockerfile: -------------------------------------------------------------------------------- 1 | ####################### 2 | # BUILD # 3 | ####################### 4 | 5 | # Olivetin - for basic web gui to run simple monitoring commands 6 | 7 | FROM debian:latest as olivetin_grin_build 8 | 9 | RUN apt-get update && apt-get -y install curl && apt-get -y install wget && apt-get -y install gettext-base 10 | RUN wget https://github.com/OliveTin/OliveTin/releases/latest/download/OliveTin_linux_amd64.deb 11 | RUN dpkg -i OliveTin_linux_amd64.deb 12 | 13 | ####################### 14 | # DEPLOY CONFIG # 15 | ####################### 16 | 17 | ENTRYPOINT ["/usr/local/bin/OliveTin"] 18 | 19 | FROM olivetin_grin_build as olivetin_grin_combined_build 20 | RUN apt-get -y install nodejs npm 21 | COPY /base-olivetin/owner_api_client /etc/OliveTin/owner_api_client 22 | WORKDIR /etc/OliveTin/owner_api_client 23 | RUN npm install 24 | -------------------------------------------------------------------------------- /base-olivetin/owner_api_client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-sample", 3 | "version": "0.0.1", 4 | "description": "Sample of connecting to the secure OwnerAPI via node", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "npm test" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "jayson": "^3.2.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /base-olivetin/owner_api_client/src/create_wallet.js: -------------------------------------------------------------------------------- 1 | const ownerClient = require('./owner_api_client.js'); 2 | 3 | 4 | const address = process.env.OWNER_API_ADDRESS || 'host.docker.internal:3415'; 5 | const password = process.env.WALLET_PASSWORD || ''; 6 | 7 | async function main() { 8 | let client = ownerClient.initClient('http://' + address + '/v3/owner'); 9 | let shared_key = await ownerClient.initSecure(); 10 | 11 | let response = await new ownerClient.JSONRequestEncrypted(1, 'create_wallet', { 12 | "name": null, 13 | "mnemonic": null, 14 | "mnemonic_length": 32, 15 | "password": password 16 | }).send(shared_key); 17 | 18 | console.log("Response: ", response); 19 | } 20 | 21 | 22 | 23 | main(); 24 | 25 | 26 | -------------------------------------------------------------------------------- /base-olivetin/owner_api_client/src/owner_api_client.js: -------------------------------------------------------------------------------- 1 | /* Sample Code for connecting to the V3 Secure API via Node 2 | * 3 | * With thanks to xiaojay of Niffler Wallet: 4 | * https://github.com/grinfans/Niffler/blob/gw3/src/shared/walletv3.js 5 | * 6 | */ 7 | 8 | const jayson = require('jayson/promise'); 9 | const crypto = require('crypto'); 10 | 11 | var client;// = jayson.client.http('http://localhost:3415/v3/owner'); 12 | 13 | const initClient = (url) => { 14 | client = jayson.client.http(url); 15 | } 16 | 17 | // Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib. 18 | const aes256gcm = (shared_secret) => { 19 | const ALGO = 'aes-256-gcm'; 20 | 21 | // encrypt returns base64-encoded ciphertext 22 | const encrypt = (str, nonce) => { 23 | let key = Buffer.from(shared_secret, 'hex') 24 | const cipher = crypto.createCipheriv(ALGO, key, nonce) 25 | const enc = Buffer.concat([cipher.update(str, 'utf8'), cipher.final()]) 26 | const tag = cipher.getAuthTag() 27 | return Buffer.concat([enc, tag]).toString('base64') 28 | }; 29 | 30 | // decrypt decodes base64-encoded ciphertext into a utf8-encoded string 31 | const decrypt = (enc, nonce) => { 32 | //key,nonce is all buffer type; data is base64-encoded string 33 | let key = Buffer.from(shared_secret, 'hex') 34 | const data_ = Buffer.from(enc, 'base64') 35 | const decipher = crypto.createDecipheriv(ALGO, key, nonce) 36 | const len = data_.length 37 | const tag = data_.slice(len-16, len) 38 | const text = data_.slice(0, len-16) 39 | decipher.setAuthTag(tag) 40 | const dec = decipher.update(text, 'binary', 'utf8') + decipher.final('utf8'); 41 | return dec 42 | }; 43 | 44 | return { 45 | encrypt, 46 | decrypt, 47 | }; 48 | }; 49 | 50 | class JSONRequestEncrypted { 51 | constructor(id, method, params, url) { 52 | this.jsonrpc = '2.0' 53 | this.method = method 54 | this.id = id 55 | this.params = params 56 | } 57 | 58 | async send(key){ 59 | const aesCipher = aes256gcm(key); 60 | const nonce = new Buffer.from(crypto.randomBytes(12)); 61 | let enc = aesCipher.encrypt(JSON.stringify(this), nonce); 62 | let params = { 63 | 'nonce': nonce.toString('hex'), 64 | 'body_enc': enc, 65 | } 66 | let response = await client.request('encrypted_request_v3', params); 67 | 68 | if (response.err) { 69 | throw response.err 70 | } 71 | 72 | const nonce2 = Buffer.from(response.result.Ok.nonce, 'hex'); 73 | const data = Buffer.from(response.result.Ok.body_enc, 'base64'); 74 | 75 | let dec = aesCipher.decrypt(data, nonce2) 76 | return dec 77 | } 78 | } 79 | 80 | async function initSecure() { 81 | let ecdh = crypto.createECDH('secp256k1') 82 | ecdh.generateKeys() 83 | let publicKey = ecdh.getPublicKey('hex', 'compressed') 84 | const params = { 85 | 'ecdh_pubkey': publicKey 86 | } 87 | let response = await client.request('init_secure_api', params); 88 | if (response.err) { 89 | throw response.err 90 | } 91 | 92 | return ecdh.computeSecret(response.result.Ok, 'hex', 'hex') 93 | } 94 | 95 | async function openWallet(password, shared_key) { 96 | let response = await new JSONRequestEncrypted(1, 'open_wallet', { 97 | "name": null, 98 | "password": password, 99 | }).send(shared_key); 100 | 101 | let token = null; 102 | 103 | try { 104 | token = JSON.parse(response).result.Ok; 105 | return token 106 | //let result = JSON.parse(info_response).result.Ok; 107 | //console.log(result); 108 | } catch (e) { 109 | console.log(JSON.parse(response)) 110 | return null 111 | } 112 | } 113 | 114 | async function closeWallet(shared_key, sequence) { 115 | info_response = await new JSONRequestEncrypted(sequence, 'close_wallet', { 116 | "name": null, 117 | }).send(shared_key) 118 | } 119 | 120 | function sleep(ms) { 121 | return new Promise(resolve => setTimeout(resolve, ms)); 122 | } 123 | 124 | module.exports = { 125 | initClient, 126 | initSecure, 127 | openWallet, 128 | closeWallet, 129 | JSONRequestEncrypted, 130 | } 131 | 132 | -------------------------------------------------------------------------------- /base-olivetin/owner_api_client/src/wallet_info.js: -------------------------------------------------------------------------------- 1 | const ownerClient = require('./owner_api_client.js'); 2 | 3 | // read value of env var OWNER_API_PORT or default to 3415 4 | const address = process.env.OWNER_API_ADDRESS || 'host.docker.internal:3415'; 5 | const password = process.env.WALLET_PASSWORD || ''; 6 | 7 | async function main() { 8 | ownerClient.initClient('http://' + address + '/v3/owner'); 9 | let shared_key = await ownerClient.initSecure(); 10 | 11 | let token = await ownerClient.openWallet(password, shared_key); 12 | if (token == null) { 13 | return 14 | } 15 | 16 | let info_response = await new ownerClient.JSONRequestEncrypted(2, 'retrieve_summary_info', { 17 | "token": token, 18 | "refresh_from_node": true, 19 | "minimum_confirmations": 1, 20 | }).send(shared_key) 21 | 22 | try { 23 | let result = JSON.parse(info_response).result.Ok; 24 | console.log(result); 25 | } catch (e) { 26 | console.log(JSON.parse(info_response)) 27 | } 28 | 29 | await ownerClient.closeWallet(shared_key, 3) 30 | } 31 | 32 | main(); 33 | 34 | 35 | -------------------------------------------------------------------------------- /base-olivetin/owner_api_client/src/wallet_txs.js: -------------------------------------------------------------------------------- 1 | const ownerClient = require('./owner_api_client.js'); 2 | 3 | const address = process.env.OWNER_API_ADDRESS || 'host.docker.internal:3415'; 4 | const password = process.env.WALLET_PASSWORD || ''; 5 | 6 | async function main() { 7 | ownerClient.initClient('http://' + address + '/v3/owner'); 8 | let shared_key = await ownerClient.initSecure(); 9 | 10 | let token = await ownerClient.openWallet(password, shared_key); 11 | if (token == null) { 12 | return 13 | } 14 | 15 | let info_response = await new ownerClient.JSONRequestEncrypted(2, 'retrieve_txs', { 16 | "token": token, 17 | "tx_id": null, 18 | "tx_slate_id": null, 19 | "refresh_from_node": true 20 | }).send(shared_key) 21 | 22 | try { 23 | let result = JSON.parse(info_response).result.Ok; 24 | console.log(result); 25 | } catch (e) { 26 | console.log(JSON.parse(info_response)) 27 | } 28 | 29 | await ownerClient.closeWallet(shared_key, 3) 30 | } 31 | 32 | 33 | 34 | main(); 35 | 36 | 37 | -------------------------------------------------------------------------------- /botnet/botnet.md: -------------------------------------------------------------------------------- 1 | # Botnet - alternate way of controlling grin docker instances 2 | 3 | This approach uses an alternate approach that enables more control over each running grin instance. Rather than 4 | specify running paramters at the docker level, this just uses a single docker container that can be spawned 5 | multiple times. Starting/stopping the server and wallet is done via POSTS to a listening node.js control server. 6 | 7 | Idea here is that by controlling each grin instance manually, it will be easier to script a 'live' 8 | network where nodes are constantly running, joining, leaving, etc. as well as check on their status 9 | via grin's API commands. Additionally, it should be easy enough to build a pretty-UI on top of 10 | the test net if so desired by adding a 'control' node that runs a simple control web-app. 11 | 12 | Prereqs: 13 | docker 14 | docker-compose 15 | node 8+ (npm: request) 16 | 17 | Build via: 18 | ``` 19 | docker-compose build 20 | ``` 21 | 22 | And launch the same number of instances as match what's specified in ../client/client.js 23 | 24 | ``` 25 | docker-compose up --scale grin-bot-node=6 26 | ``` 27 | 28 | This won't start grin automatically on each node, just a control server on each server, which will be accessed by the control client. 29 | 30 | Wait for the nodes to come up, then to start the network simulation, from the ../client directory: 31 | 32 | ``` 33 | node client.js 34 | ``` 35 | 36 | This will start up the clients at intervals and start/stop them, or send transactions at intervals defined by the rules in client.js, 37 | as well as periodically poll, collect and compare stats from each running server via their grin APIs. 38 | 39 | To modify values or the frequency at which events have a chance of occurring, refer to the 'tweak_servers' function in client.js 40 | 41 | Other misc: (Older, just here for testing and debugging reference) 42 | 43 | To start a server, POST via curl as follows 44 | 45 | ``` 46 | curl -X POST -d @sample_start.json 172.26.0.2:8000/start 47 | ``` 48 | 49 | Check parameter values in [sample_start.json](sample_start.json). You can choose to run either a wallet server, 50 | a regular server or both on the same instance. 51 | 52 | To stop running servers: 53 | 54 | ``` 55 | curl -X POST 172.26.0.2:8000/stop 56 | ``` 57 | 58 | To check the status of grin instances on a server 59 | ``` 60 | curl 172.26.0.2:8000/status 61 | ``` 62 | 63 | All commands will return a json result with the status of the previous command. 64 | -------------------------------------------------------------------------------- /botnet/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | #All nodes have same basic build, but can be controlled externally 4 | grin-bot-node: 5 | build: 6 | context: .. 7 | dockerfile: base-build/Dockerfile.botnet 8 | image: grin-bot 9 | environment: 10 | - RUST_BACKTRACE=1 11 | expose: 12 | - "13413" 13 | - "13414" 14 | - "13415" 15 | - "8000" 16 | networks: 17 | botnet: 18 | 19 | networks: 20 | botnet: 21 | driver: bridge 22 | ipam: 23 | config: 24 | - subnet: 172.26.0.0/24 25 | -------------------------------------------------------------------------------- /botnet/sample_start.json: -------------------------------------------------------------------------------- 1 | { 2 | "runserver": true, 3 | "runwallet": true, 4 | "serverargs": ["--mine", "run"], 5 | "walletargs": ["-p", "password", "listen"] 6 | } 7 | -------------------------------------------------------------------------------- /client/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "ecmaVersion" : 8, 9 | "sourceType": "module" 10 | }, 11 | "rules": { 12 | "indent": [ 13 | "error", 14 | "tab" 15 | ], 16 | "linebreak-style": [ 17 | "error", 18 | "unix" 19 | ], 20 | "quotes": [ 21 | "error", 22 | "single" 23 | ], 24 | "semi": [ 25 | "error", 26 | "always" 27 | ], 28 | "no-console":0 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs": [ 3 | ], 4 | "loadEagerly": [ 5 | "server.js" 6 | ], 7 | "plugins": { 8 | "requirejs": { 9 | "baseURL": "./", 10 | "paths": {} 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/client.js: -------------------------------------------------------------------------------- 1 | const grinAPI = require('./grinapi'); 2 | let server_index=2; 3 | const num_servers = 6; 4 | const subnet = '172.26.0'; 5 | let server_containers = []; 6 | let cur_tick=0; 7 | const tick_length_ms = 1000; 8 | //how frequently to check the head on all servers 9 | const head_check_frequency = 60; 10 | let next_head_check = head_check_frequency; 11 | 12 | 13 | class ServerContainer { 14 | constructor(){ 15 | this.ip = subnet+'.'+server_index; 16 | server_index++; 17 | this.start_params = grinAPI.serverStartParams(); 18 | this.start_tick = 5; 19 | this.started=false; 20 | //percent chance of taking a break each tick 21 | this.break_chance=0; 22 | this.break_length=60; 23 | //percent chance of trying to send some coins each tick 24 | this.coin_send_chance=0; 25 | this.coin_send_amount=50000; 26 | this.coin_send_destination='172.26.0.2:13415'; 27 | //wait a while before sending coins 28 | this.coin_send_min_tick = 60; 29 | this.coin_send_cooldown = 60; 30 | } 31 | 32 | start(){ 33 | let ip = this.ip; 34 | let start_params = this.start_params; 35 | console.log('Attempting to start server at %s with params: %s', ip, JSON.stringify(start_params)); 36 | let impl = function(){ 37 | grinAPI.startServer(ip, start_params).then(function(res){ 38 | console.log('Start server at %s. Response is: {%s} ', ip, res); 39 | }, function(err){ 40 | console.log('Error contacting server at %s: %s', ip, err); 41 | }).catch(function(err){ 42 | console.log('Client error: %s', err); 43 | }); 44 | }; 45 | impl(); 46 | } 47 | 48 | stop(){ 49 | let ip = this.ip; 50 | let impl = function(){ 51 | grinAPI.stopServer(ip).then(function(res){ 52 | console.log('Stopping server at %s. Response is: {%s} ', ip, res); 53 | }, function(err){ 54 | console.log('Error contacting server at %s: %s', ip, err); 55 | }).catch(function(err){ 56 | console.log('Client error: %s', err); 57 | }); 58 | }; 59 | impl(); 60 | } 61 | 62 | queryChain(){ 63 | let ip =this.ip; 64 | let impl = function(){ 65 | return new Promise((resolve, reject) => { 66 | grinAPI.getChainState(ip).then(function(res){ 67 | //console.log('Chain state at %s is: %s ', ip, res); 68 | resolve(JSON.parse(JSON.stringify(JSON.parse(res)))); 69 | }, function(err){ 70 | console.log('Error getting chain state: %s', err); 71 | reject(err); 72 | }).catch(function(err){ 73 | console.log('Client error: %s', err); 74 | reject(err); 75 | }); 76 | }); 77 | }; 78 | return impl(); 79 | } 80 | 81 | //Main update function.... server will decide to do on any given 82 | //tick based on simple rules 83 | update(){ 84 | // start when scheduled 85 | if (!this.started){ 86 | if (cur_tick > this.start_tick){ 87 | this.start(); 88 | this.started=true; 89 | } 90 | } 91 | //To simulate nodes randomly joining and leaving 92 | if (this.started && this.break_chance > 0){ 93 | let roll = Math.random()*100; 94 | //console.log('%s break roll: %d', this.ip, roll); 95 | if (roll < this.break_chance){ 96 | console.log('%s shutting down for %d seconds', this.ip, this.break_length); 97 | this.stop(); 98 | this.started=false; 99 | this.start_tick=cur_tick+this.break_length; 100 | } 101 | } 102 | //To simulate nodes sending coins to other nodes 103 | if (this.started && this.coin_send_chance > 0 && cur_tick>=this.coin_send_min_tick){ 104 | let roll = Math.random()*100; 105 | //console.log('%s break roll: %d', this.ip, roll); 106 | if (roll < this.coin_send_chance){ 107 | console.log('%s sending %d nanogrins to %s', this.ip, this.coin_send_amount, this.coin_send_destination); 108 | let params = grinAPI.walletSendParams(); 109 | params.amount = this.coin_send_amount; 110 | params.destination = this.coin_send_destination; 111 | grinAPI.sendCoins(this.ip, params); 112 | //cool down before allowing again 113 | this.coin_send_min_tick += this.coin_send_cooldown; 114 | } 115 | } 116 | } 117 | } 118 | 119 | // Create references to servers 120 | for (let i = 0; i { 175 | console.log(values); 176 | let control_height = values[0].height; 177 | let control_block = values[0].last_block_pushed; 178 | for (let i in values) { 179 | let v = values[i]; 180 | if (v.height!=control_height || control_block!=v.last_block_pushed){ 181 | console.log ('WARNING - - - differences found in server heights and/or last block pushed'); 182 | break; 183 | } 184 | } 185 | }); 186 | } 187 | 188 | function tick() { 189 | for (let server of server_containers){ 190 | server.update(); 191 | } 192 | if (cur_tick==next_head_check){ 193 | checkHeads(); 194 | next_head_check = cur_tick+head_check_frequency; 195 | } 196 | cur_tick++; 197 | } 198 | 199 | // Tick once a second 200 | function run() { 201 | console.log('Applying server settings'); 202 | tweak_servers(); 203 | console.log('Starting main loop'); 204 | setInterval(tick, tick_length_ms); 205 | } 206 | 207 | run(); 208 | 209 | -------------------------------------------------------------------------------- /client/grinapi.js: -------------------------------------------------------------------------------- 1 | var request=require('request'); 2 | 3 | class ServerStartParams { 4 | constructor(){ 5 | this.runserver = true; 6 | this.runwallet = true; 7 | this.serverargs = ['--mine', 'run'], 8 | this.walletargs = ['-p', 'password', 'listen']; 9 | } 10 | } 11 | 12 | class WalletSendParams { 13 | constructor(){ 14 | this.amount=2000; 15 | this.destination = 'http://172.128.0.2:13415'; 16 | } 17 | 18 | as_grin_args(){ 19 | return ['-p', 'password', 'send', this.amount, '-d', this.destination]; 20 | } 21 | } 22 | 23 | class PostOptions { 24 | constructor(){ 25 | this.url= 'http://172.26.0.2:8000/start'; 26 | this.method= 'POST'; 27 | this.headers= { 28 | 'Accept': 'application/json', 29 | 'Accept-Charset': 'utf-8', 30 | 'User-Agent': 'grin-client' 31 | }, 32 | this.body=JSON.stringify(new ServerStartParams()); 33 | } 34 | } 35 | 36 | const serverStartParams = function(){ 37 | return new ServerStartParams(); 38 | }; 39 | 40 | const walletSendParams = function(){ 41 | return new WalletSendParams(); 42 | }; 43 | 44 | const startServer = function(ip, server_params){ 45 | var post_options = new PostOptions(); 46 | post_options.url = 'http://'+ip+':8000/start'; 47 | post_options.body = JSON.stringify(server_params); 48 | return new Promise(function(resolve, reject) { 49 | request(post_options, function (err, res, body) { 50 | if (err) { 51 | reject(Error(err)); 52 | } 53 | resolve(body); 54 | }); 55 | }); 56 | }; 57 | 58 | const stopServer = function(ip){ 59 | var post_options = new PostOptions(); 60 | post_options.url = 'http://'+ip+':8000/stop'; 61 | return new Promise(function(resolve, reject) { 62 | request(post_options, function (err, res, body) { 63 | if (err) { 64 | reject(Error(err)); 65 | } 66 | resolve(body); 67 | }); 68 | }); 69 | }; 70 | 71 | const sendCoins = function(ip, wallet_send_params){ 72 | var post_options = new PostOptions(); 73 | post_options.url = 'http://'+ip+':8000/send'; 74 | post_options.body = JSON.stringify(wallet_send_params.as_grin_args()); 75 | return new Promise(function(resolve, reject) { 76 | request(post_options, function (err, res, body) { 77 | if (err) { 78 | reject(Error(err)); 79 | } 80 | resolve(body); 81 | }); 82 | }); 83 | }; 84 | 85 | const getChainState = function(ip){ 86 | var post_options = new PostOptions(); 87 | post_options.url = 'http://'+ip+':13413/v1/chain'; 88 | post_options.method = 'GET'; 89 | return new Promise(function(resolve, reject) { 90 | request(post_options, function (err, res, body) { 91 | if (err) { 92 | reject(Error(err)); 93 | } 94 | resolve(body); 95 | }); 96 | }); 97 | }; 98 | 99 | module.exports = function(){ 100 | return { 101 | serverStartParams : serverStartParams, 102 | walletSendParams : walletSendParams, 103 | startServer : startServer, 104 | stopServer : stopServer, 105 | sendCoins : sendCoins, 106 | getChainState : getChainState, 107 | }; 108 | }(); 109 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "description": "test client", 5 | "main": "client.js", 6 | "scripts": { 7 | "test": "npm test", 8 | "start": "node client.js" 9 | }, 10 | "author": "yeastplume", 11 | "license": "MIT", 12 | "devDependencies": {}, 13 | "dependencies": { 14 | "request": "^2.83.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /controller/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "sourceType": "module" 9 | }, 10 | "rules": { 11 | "indent": [ 12 | "error", 13 | "tab" 14 | ], 15 | "linebreak-style": [ 16 | "error", 17 | "unix" 18 | ], 19 | "quotes": [ 20 | "error", 21 | "single" 22 | ], 23 | "semi": [ 24 | "error", 25 | "always" 26 | ], 27 | "no-console":0 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /controller/.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs": [ 3 | ], 4 | "loadEagerly": [ 5 | "server.js" 6 | ], 7 | "plugins": { 8 | "requirejs": { 9 | "baseURL": "./", 10 | "paths": {} 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /controller/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "controller", 3 | "version": "0.1.0", 4 | "description": "Controller to allow for external processes to control the grin server instance running on docker containers", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "npm test", 8 | "start": "node server.js" 9 | }, 10 | "author": "yeastplume", 11 | "license": "MIT", 12 | "devDependencies": {}, 13 | "dependencies": { 14 | "httpdispatcher": "^2.1.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /controller/server.js: -------------------------------------------------------------------------------- 1 | var HttpDispatcher = require('httpdispatcher'); 2 | var http = require('http'); 3 | var dispatcher = new HttpDispatcher(); 4 | const {exec, spawn} = require('child_process'); 5 | 6 | // define the port of access for the server 7 | const PORT = 8000; 8 | const GRIN_CMD = 'grin'; 9 | //const GRIN_CMD = '../../grin/target/debug/grin'; 10 | 11 | // global handle for the running grin instance 12 | var server_process; 13 | var wallet_process; 14 | var send_process; 15 | 16 | // We need a function which handles requests and send response 17 | function handleRequest(request, response){ 18 | try { 19 | // log the request on console 20 | console.log(request.url); 21 | // Dispatch 22 | dispatcher.dispatch(request, response); 23 | } catch(err) { 24 | console.log(err); 25 | } 26 | } 27 | 28 | // Create a server 29 | var grinControlServer = http.createServer(handleRequest); 30 | 31 | var CommandResult = function(){ 32 | return { 33 | command: 'none', 34 | result: 'failure' 35 | }; 36 | }; 37 | 38 | var GrinStatus = function(){ 39 | return { 40 | server_process: 'stopped', 41 | wallet_process: 'stopped' 42 | }; 43 | }; 44 | 45 | var killGrin = function(){ 46 | if (server_process!=null){ 47 | server_process.kill('SIGINT'); 48 | console.log('SIGINT sent to grin server process'); 49 | } 50 | if (wallet_process!=null){ 51 | wallet_process.kill('SIGINT'); 52 | console.log('SIGINT sent to grin wallet process'); 53 | } 54 | server_process=null; 55 | wallet_process=null; 56 | }; 57 | 58 | var sendResponse = function(res, result){ 59 | res.writeHead(200, {'Content-Type': 'application/json'}); 60 | res.end(JSON.stringify(result)); 61 | }; 62 | 63 | dispatcher.onPost('/start', function(req, res) { 64 | killGrin(); 65 | try { 66 | var args=JSON.parse(req.body); 67 | if (args.runserver){ 68 | console.log('Starting server'); 69 | args.serverargs.unshift('server'); 70 | server_process = spawn(GRIN_CMD, args.serverargs, {env: {RUST_BACKTRACE: '1'}}); 71 | server_process.stdout.on('data', function(data) { 72 | console.log(data); 73 | }); 74 | server_process.stderr.on('readable', function() { 75 | var chunk; 76 | while ((chunk = this.read()) !== null) { 77 | console.log('%s', chunk); 78 | } 79 | }); 80 | server_process.on('exit', function(code) { 81 | console.log('Server Exited with exit code: '+code); 82 | server_process=null; 83 | }); 84 | server_process.on('error', function(err){ 85 | console.log(err); 86 | }); 87 | } 88 | if (args.runwallet){ 89 | console.log('Starting wallet'); 90 | args.walletargs.unshift('wallet'); 91 | wallet_process = spawn(GRIN_CMD, args.walletargs, {cwd: './wallet', env: {RUST_BACKTRACE: '1'}}); 92 | wallet_process.stdout.on('data', function(data) { 93 | console.log(data); 94 | }); 95 | wallet_process.stderr.on('readable', function() { 96 | var chunk; 97 | while ((chunk = this.read()) !== null) { 98 | console.log('%s', chunk); 99 | } 100 | }); 101 | wallet_process.on('exit', function(code) { 102 | console.log('Wallet exited with exit code: '+code); 103 | server_process=null; 104 | }); 105 | wallet_process.on('error', function(err){ 106 | console.log(err); 107 | }); 108 | } 109 | var result = CommandResult(); 110 | result.command='start'; 111 | result.result='issued'; 112 | sendResponse(res, result); 113 | } catch (err){ 114 | var result_err = CommandResult(); 115 | result_err.command='start'; 116 | result_err.result='error'; 117 | sendResponse(res, result_err); 118 | console.log(err); 119 | } 120 | }); 121 | 122 | dispatcher.onPost('/stop', function(req, res) { 123 | killGrin(); 124 | var result = CommandResult(); 125 | result.command='stop grin'; 126 | result.result='issued'; 127 | sendResponse(res, result); 128 | }); 129 | 130 | dispatcher.onPost('/send', function(req, res) { 131 | try { 132 | var args=JSON.parse(req.body); 133 | console.log('Sending Coins'); 134 | args.unshift('wallet'); 135 | console.log(args); 136 | send_process = spawn(GRIN_CMD, args, {cwd: './wallet', env: {RUST_BACKTRACE: '1'}}); 137 | send_process.stdout.on('data', function(data) { 138 | console.log(data); 139 | }); 140 | send_process.stderr.on('readable', function() { 141 | var chunk; 142 | while ((chunk = this.read()) !== null) { 143 | console.log('%s', chunk); 144 | } 145 | }); 146 | send_process.on('exit', function(code) { 147 | console.log('Wallet send exited with exit code: '+code); 148 | send_process=null; 149 | }); 150 | send_process.on('error', function(err){ 151 | console.log(err); 152 | }); 153 | var result = CommandResult(); 154 | result.command='send'; 155 | result.result='issued'; 156 | sendResponse(res, result); 157 | } catch (err){ 158 | var result_err = CommandResult(); 159 | result_err.command='send'; 160 | result_err.result='error'; 161 | sendResponse(res, result_err); 162 | console.log(err); 163 | } 164 | }); 165 | 166 | dispatcher.onGet('/status', function(req, res) { 167 | var result = GrinStatus(); 168 | if (server_process!=null&&server_process.exit_code==null){ 169 | result.server_process='running'; 170 | } 171 | if (wallet_process!=null&&wallet_process.exit_code==null){ 172 | result.wallet_process='running'; 173 | } 174 | sendResponse(res, result); 175 | }); 176 | 177 | dispatcher.onError(function(req, res) { 178 | res.writeHead(404); 179 | res.end('Error, the URL doesn\'t exist'); 180 | }); 181 | 182 | // Start the server ! 183 | grinControlServer.listen(PORT, '0.0.0.0', function(){ 184 | // Init the wallet seed 185 | exec(GRIN_CMD + " wallet init", {cwd: './wallet', env: {RUST_BACKTRACE: '1'}}); 186 | // Callback triggered when server is successfully listening. Hurray! 187 | console.log('Control server listening on: http://' + grinControlServer.address().address + ':' + PORT); 188 | }); 189 | -------------------------------------------------------------------------------- /devnet/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | #Node 1: genesis and miner from build.md example 4 | grin-genesis-miner: 5 | build: 6 | context: .. 7 | dockerfile: base-build/Dockerfile 8 | image: grin-min 9 | command: ["server", "--mine", "-w", "http://grin-genesis-wallet:13416", "run"] 10 | environment: 11 | - RUST_BACKTRACE=1 12 | expose: 13 | - "13413" 14 | - "13414" 15 | networks: 16 | testnet: 17 | ipv4_address: 172.25.0.2 18 | depends_on: 19 | - grin-genesis-wallet 20 | 21 | grin-genesis-wallet: 22 | image: grin-min 23 | command: ["wallet", "-p", "password", "receive"] 24 | expose: 25 | - "13416" 26 | networks: 27 | testnet: 28 | ipv4_address: 172.25.0.3 29 | 30 | 31 | #Node 2: Regular node (not mining) 32 | grin-regular-1: 33 | image: grin-min 34 | environment: 35 | - RUST_BACKTRACE=1 36 | command: ["server", "--seed=172.25.0.2:13414", "run"] 37 | expose: 38 | - "13414" 39 | - "13415" 40 | depends_on: 41 | - grin-genesis-miner 42 | networks: 43 | testnet: 44 | ipv4_address: 172.25.0.4 45 | 46 | #Node 3: regular node and wallet listener 47 | grin-regular-2: 48 | image: grin-min 49 | command: ["server", "--seed=172.25.0.2:13414", "run"] 50 | expose: 51 | - "13414" 52 | - "13415" 53 | depends_on: 54 | - grin-regular-2-wallet 55 | - grin-genesis-miner 56 | networks: 57 | testnet: 58 | ipv4_address: 172.25.0.5 59 | 60 | grin-regular-2-wallet: 61 | image: grin-min 62 | command: ["wallet", "-p", "password", "-a", "http://grin-genesis-miner:13413", "receive"] 63 | expose: 64 | - "13416" 65 | networks: 66 | testnet: 67 | ipv4_address: 172.25.0.6 68 | depends_on: 69 | - grin-genesis-miner 70 | 71 | networks: 72 | testnet: 73 | driver: bridge 74 | ipam: 75 | config: 76 | - subnet: 172.25.0.0/24 77 | -------------------------------------------------------------------------------- /devnet/send_miner_to_wallet_2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker exec -e RUST_BACKTRACE=1 devnet_grin-genesis-wallet_1 grin wallet -p "password" -a "http://grin-regular-1:13413" send 20000 -d "http://grin-regular-2-wallet:13416" 3 | -------------------------------------------------------------------------------- /devnet/wallet_info_2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker exec devnet_grin-regular-2-wallet_1 grin wallet -p "password" -a "http://grin-regular-1:13413" info 3 | -------------------------------------------------------------------------------- /devnet/wallet_info_miner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker exec devnet_grin-genesis-wallet_1 grin wallet -p "password" -a "http://grin-genesis-miner:13413" info 3 | -------------------------------------------------------------------------------- /monitor/config/combined.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | - title: Node Sync Status 3 | popupOnStart: execution-dialog-stdout-only 4 | shell: /etc/OliveTin/json-rpc/node/execute_get_status.sh 5 | icon: ping 6 | timeout: 5 7 | 8 | - title: Get Block 9 | popupOnStart: execution-dialog-stdout-only 10 | shell: /etc/OliveTin/json-rpc/node/execute_get_block.sh 11 | icon: ping 12 | timeout: 5 13 | arguments: 14 | - name: block_number 15 | type: ascii_sentence 16 | description: Block Number 17 | 18 | - title: Get Outputs 19 | popupOnStart: execution-dialog-stdout-only 20 | shell: /etc/OliveTin/json-rpc/node/execute_get_outputs.sh 21 | icon: ping 22 | timeout: 5 23 | arguments: 24 | - name: commits 25 | type: very_dangerous_raw_string 26 | description: Commits 27 | 28 | - title: Create Wallet 29 | popupOnStart: execution-dialog-stdout-only 30 | shell: node /etc/OliveTin/owner_api_client/src/create_wallet.js 31 | arguments: 32 | - name: wallet_password 33 | type: ascii_sentence 34 | description: Wallet Password 35 | - title: Wallet Summary Info 36 | popupOnStart: execution-dialog-stdout-only 37 | shell: node /etc/OliveTin/owner_api_client/src/wallet_info.js 38 | arguments: 39 | - name: wallet_password 40 | type: ascii_sentence 41 | description: Wallet Password 42 | - title: Wallet Txs 43 | popupOnStart: execution-dialog-stdout-only 44 | shell: node /etc/OliveTin/owner_api_client/src/wallet_txs.js 45 | arguments: 46 | - name: wallet_password 47 | type: ascii_sentence 48 | description: Wallet Password 49 | 50 | dashboards: 51 | - title: All Processes 52 | type: fieldset 53 | contents: 54 | - title: Grin Node 55 | type: fieldset 56 | contents: 57 | - title: Node Sync Status 58 | - title: Get Block 59 | - title: Get Outputs 60 | - title: Grin Wallet 61 | type: fieldset 62 | contents: 63 | - title: Create Wallet 64 | - title: Wallet Summary Info 65 | - title: Wallet Txs 66 | -------------------------------------------------------------------------------- /monitor/json-rpc/node/execute_get_block.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | GET_BLOCK_REQ=$(/usr/bin/envsubst < /etc/OliveTin/json-rpc/node/get_block.json) 3 | curl -s -X POST $NODE_API_ADDR/v2/foreign -u grin:`cat /grin-node-home/.grin/$NODE_CHAIN_TYPE/.foreign_api_secret` --data "${GET_BLOCK_REQ}" -------------------------------------------------------------------------------- /monitor/json-rpc/node/execute_get_outputs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | GET_OUTPUTS_REQ=$(/usr/bin/envsubst < /etc/OliveTin/json-rpc/node/get_outputs.json) 3 | curl -s -X POST $NODE_API_ADDR/v2/foreign -u grin:`cat /grin-node-home/.grin/$NODE_CHAIN_TYPE/.foreign_api_secret` --data "${GET_OUTPUTS_REQ}" -------------------------------------------------------------------------------- /monitor/json-rpc/node/execute_get_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -s -X POST $NODE_API_ADDR/v2/owner -u grin:`cat /grin-node-home/.grin/$NODE_CHAIN_TYPE/.api_secret` -d @/etc/OliveTin/json-rpc/node/get_status.json -------------------------------------------------------------------------------- /monitor/json-rpc/node/get_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "method": "get_block", 4 | "params": [$BLOCK_NUMBER, null, null], 5 | "id": 1 6 | } -------------------------------------------------------------------------------- /monitor/json-rpc/node/get_outputs.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "method": "get_outputs", 4 | "params": [$COMMITS, null, null, true, true], 5 | "id": 1 6 | } -------------------------------------------------------------------------------- /monitor/json-rpc/node/get_status.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "method": "get_status", 4 | "params": [], 5 | "id": 1 6 | } -------------------------------------------------------------------------------- /monitor/json-rpc/node/get_tip.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "method": "get_tip", 4 | "params": [], 5 | "id": 1 6 | } -------------------------------------------------------------------------------- /monitor/main/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | grin-olivetin: 3 | build: 4 | context: ../../ 5 | dockerfile: base-olivetin/Dockerfile 6 | target: olivetin_grin_combined_build 7 | container_name: grin-main-monitor-container 8 | networks: 9 | - grin-mainnet-network 10 | image: grin-olivetin-mainnnet 11 | environment: 12 | - PORT=1337 13 | - NODE_API_ADDR=grin-node-mainnet-master-container:3413 14 | - NODE_CHAIN_TYPE=main 15 | - OWNER_API_ADDRESS=grin-wallet-testnet-contracts-container:3415 16 | volumes: 17 | - ../config/combined.yaml:/etc/OliveTin/config.yaml 18 | - ../json-rpc/node:/etc/OliveTin/json-rpc/node 19 | - main_grin-home-mainnet-master:/grin-node-home 20 | ports: 21 | - "1337:1337" 22 | restart: unless-stopped 23 | 24 | volumes: 25 | main_grin-home-mainnet-master: 26 | external: true 27 | 28 | networks: 29 | grin-mainnet-network: 30 | name: grin_mainnet_network 31 | external: true -------------------------------------------------------------------------------- /monitor/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | grin-olivetin: 3 | build: 4 | context: ../../ 5 | dockerfile: base-olivetin/Dockerfile 6 | target: olivetin_grin_combined_build 7 | container_name: grin-test-monitor-container 8 | networks: 9 | - grin-testnet-network 10 | image: grin-olivetin-testnet 11 | environment: 12 | - PORT=11337 13 | - NODE_API_ADDR=grin-node-testnet-master-container:13413 14 | - NODE_CHAIN_TYPE=test 15 | - OWNER_API_ADDRESS=grin-wallet-testnet-contracts-container:13415 16 | volumes: 17 | - ../config/combined.yaml:/etc/OliveTin/config.yaml 18 | - ../json-rpc/node:/etc/OliveTin/json-rpc/node 19 | - grin-home-testnet-master:/grin-node-home 20 | ports: 21 | - "11337:11337" 22 | restart: unless-stopped 23 | 24 | volumes: 25 | grin-home-testnet-master: 26 | external: true 27 | 28 | networks: 29 | grin-testnet-network: 30 | name: grin_testnet_network 31 | external: true -------------------------------------------------------------------------------- /mwixnet/main/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Testnet Node - Built from master 3 | grin-mwixnet-testnet: 4 | build: 5 | context: ../../ 6 | dockerfile: ./base-build/Dockerfile.mwixnet 7 | target: grin_mwixnet_master 8 | image: grin-mwixnet-master 9 | environment: 10 | - RUST_BACKTRACE=1 11 | expose: 12 | - "3000" 13 | ports: 14 | - "3000" 15 | volumes: 16 | # - ../configs/testnet/grin-server.toml:/home/grinuser/.grin/test/grin-server.toml 17 | - grin-home-testnet-master:/home/grinuser 18 | 19 | volumes: 20 | grin-home-testnet-master: -------------------------------------------------------------------------------- /mwixnet/scripts/mwixnet-first-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is run once on first boot of the image 3 | CONTAINER_ALREADY_STARTED="MWIXNET_FIRST_RUN_DONE" 4 | if [ ! -e $CONTAINER_ALREADY_STARTED ]; then 5 | touch $CONTAINER_ALREADY_STARTED 6 | echo "-- First container startup --" 7 | CONFIG_FILE="/home/grinuser/.grin/$GRIN_CHAIN_TYPE/mwixnet-config.toml" 8 | if [ -e $CONFIG_FILE ]; then 9 | rm $CONFIG_FILE 10 | fi 11 | if [ $GRIN_CHAIN_TYPE == "test" ]; 12 | then 13 | mwixnet --testnet init-config 14 | mwixnet --testnet pubkey -o /home/grinuser/.grin/$GRIN_CHAIN_TYPE/pubkey.txt 15 | else 16 | mwixnet init-config 17 | mwixnet pubkey -o /home/grinuser/.grin/$GRIN_CHAIN_TYPE/pubkey.txt 18 | fi 19 | 20 | if test -d "/home/prevnode"; then 21 | echo "prev_server = \"\"" >> $CONFIG_FILE 22 | fi 23 | if test -d "/home/nextnode"; then 24 | echo "next_server = \"\"" >> $CONFIG_FILE 25 | fi 26 | fi 27 | 28 | GRIN_NODE_URL_REPLACED=$(echo "$GRIN_NODE_URL" | sed 's/\//\\\//g') 29 | GRIN_WALLET_URL_REPLACED=$(echo "$WALLET_OWNER_URL" | sed 's/\//\\\//g') 30 | sed -i "s/.*grin_node_url.*/grin_node_url = \"$GRIN_NODE_URL_REPLACED\"/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/mwixnet-config.toml 31 | sed -i "s/.*wallet_owner_url.*/wallet_owner_url = \"$GRIN_WALLET_URL_REPLACED\"/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/mwixnet-config.toml 32 | sed -i 's/.*grin_node_secret_path.*/grin_node_secret_path = "\/grin-node-home\/.grin\/test\/.foreign_api_secret"/g' /home/grinuser/.grin/$GRIN_CHAIN_TYPE/mwixnet-config.toml 33 | sed -i 's/.*wallet_owner_secret_path.*/#wallet_owner_secret_path = "\/grin-wallet-home\/.grin\/test\/.owner_api_secret"/g' /home/grinuser/.grin/$GRIN_CHAIN_TYPE/mwixnet-config.toml 34 | 35 | if test -d "/home/prevnode"; then 36 | PREV_SERVER_FILE="/home/prevnode/.grin/$GRIN_CHAIN_TYPE/pubkey.txt" 37 | until [ -f $PREV_SERVER_FILE ]; do 38 | sleep 1 39 | done 40 | PREV_SERVER_ADDR=$(cat $PREV_SERVER_FILE | tr -d [:blank:]) 41 | sed -i "s/.*prev_server.*/prev_server = \"$PREV_SERVER_ADDR\"/g" $CONFIG_FILE 42 | fi 43 | 44 | if test -d "/home/nextnode"; then 45 | NEXT_SERVER_FILE="/home/nextnode/.grin/$GRIN_CHAIN_TYPE/pubkey.txt" 46 | until [ -f $NEXT_SERVER_FILE ]; do 47 | sleep 1 48 | done 49 | NEXT_SERVER_ADDR=$(cat $NEXT_SERVER_FILE | tr -d [:blank:]) 50 | sed -i "s/.*next_server.*/next_server = \"$NEXT_SERVER_ADDR\"/g" $CONFIG_FILE 51 | fi 52 | 53 | if [ $GRIN_CHAIN_TYPE == "test" ]; then 54 | RUST_BACKTRACE=full mwixnet --testnet --wallet_pass=$WALLET_PASSWORD 55 | else 56 | mwixnet --wallet_pass=$WALLET_PASSWORD 57 | fi 58 | -------------------------------------------------------------------------------- /mwixnet/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Mwixnet node - testnet 3 | grin-mwixnet-testnet: 4 | build: 5 | context: ../../ 6 | dockerfile: ./base-build/Dockerfile.mwixnet 7 | target: grin_mwixnet_master 8 | image: grin-mwixnet-master 9 | container_name: grin_test_mwixnet_container 10 | networks: 11 | - grin-testnet-network 12 | environment: 13 | - RUST_BACKTRACE=1 14 | - GRIN_CHAIN_TYPE=test 15 | - GRIN_NODE_URL=grin-node-testnet-master-container:13413 16 | - WALLET_OWNER_URL=grin-wallet-testnet-contracts-container:13415 17 | - WALLET_PASSWORD= 18 | expose: 19 | - "3000" 20 | ports: 21 | - "3000" 22 | volumes: 23 | - ../scripts/mwixnet-first-run.sh:/home/grinuser/mwixnet-first-run.sh 24 | - grin-mwixnet-home-testnet-master:/home/grinuser 25 | - grin-home-testnet-master:/grin-node-home 26 | - grin-wallet-home-testnet-contracts:/grin-wallet-home 27 | 28 | volumes: 29 | grin-mwixnet-home-testnet-master: 30 | name: grin-mwixnet-home-testnet-master 31 | grin-home-testnet-master: 32 | external: true 33 | grin-wallet-home-testnet-contracts: 34 | external: true 35 | 36 | networks: 37 | grin-testnet-network: 38 | name: grin_testnet_network 39 | external: true -------------------------------------------------------------------------------- /mwixnetx3/config/olivetin.yaml: -------------------------------------------------------------------------------- 1 | actions: 2 | - title: Node Sync Status 3 | popupOnStart: execution-dialog-stdout-only 4 | shell: /etc/OliveTin/json-rpc/node/execute_get_status.sh 5 | icon: ping 6 | timeout: 5 7 | 8 | - title: Get Block 9 | popupOnStart: execution-dialog-stdout-only 10 | shell: /etc/OliveTin/json-rpc/node/execute_get_block.sh 11 | icon: ping 12 | timeout: 5 13 | arguments: 14 | - name: block_number 15 | type: ascii_sentence 16 | description: Block Number 17 | 18 | - title: Get Outputs 19 | popupOnStart: execution-dialog-stdout-only 20 | shell: /etc/OliveTin/json-rpc/node/execute_get_outputs.sh 21 | icon: ping 22 | timeout: 5 23 | arguments: 24 | - name: commits 25 | type: very_dangerous_raw_string 26 | description: Commits 27 | - title: Wallet Summary Info 28 | popupOnStart: execution-dialog-stdout-only 29 | shell: node /etc/OliveTin/owner_api_client/src/wallet_info.js 30 | arguments: 31 | - name: OWNER_API_ADDRESS 32 | choices: 33 | - title: Wallet 1 34 | value: grin-wallet-testnet-contracts-container:13415 35 | - title: Wallet 2 36 | value: grin-wallet-testnet-contracts-container-2:23415 37 | - title: Wallet 3 38 | value: grin-wallet-testnet-contracts-container-3:33415 39 | - title: Wallet Txs 40 | popupOnStart: execution-dialog-stdout-only 41 | shell: node /etc/OliveTin/owner_api_client/src/wallet_txs.js 42 | arguments: 43 | - name: OWNER_API_ADDRESS 44 | choices: 45 | - title: Wallet 1 46 | value: grin-wallet-testnet-contracts-container:13415 47 | - title: Wallet 2 48 | value: grin-wallet-testnet-contracts-container-2:23415 49 | - title: Wallet 3 50 | value: grin-wallet-testnet-contracts-container-3:33415 51 | 52 | dashboards: 53 | - title: All Processes 54 | type: fieldset 55 | contents: 56 | - title: Grin Node 57 | type: fieldset 58 | contents: 59 | - title: Node Sync Status 60 | - title: Get Block 61 | - title: Get Outputs 62 | - title: Grin Wallet(s) x 3 63 | type: fieldset 64 | contents: 65 | - title: Wallet Summary Info 66 | - title: Wallet Txs 67 | -------------------------------------------------------------------------------- /mwixnetx3/test/compose.override.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimblewimble/grin-docker/09d9b3a1123d5d126381998537d9b6cba3b2e940/mwixnetx3/test/compose.override.yaml -------------------------------------------------------------------------------- /mwixnetx3/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | grin-node-testnet-master: 3 | extends: 4 | file: ../../node/test/docker-compose.yml 5 | service: grin-node-testnet-master 6 | grin-wallet-testnet-contracts: 7 | extends: 8 | file: ../../wallet/test/contracts/docker-compose.yml 9 | service: grin-wallet-testnet-contracts 10 | volumes: 11 | - grin-home-testnet-master:/grin-node-home 12 | depends_on: 13 | grin-node-testnet-master: 14 | condition: service_healthy 15 | grin-wallet-testnet-contracts-2: 16 | extends: 17 | file: ../../wallet/test/contracts/docker-compose.yml 18 | service: grin-wallet-testnet-contracts 19 | container_name: grin-wallet-testnet-contracts-container-2 20 | environment: 21 | - WALLET_API_LISTEN_PORT=23415 22 | - OWNER_API_LISTEN_PORT=23415 23 | volumes: 24 | - grin-home-testnet-master:/grin-node-home 25 | - grin-wallet-home-testnet-contracts-2:/home/grinuser 26 | healthcheck: 27 | test: ["CMD", "curl", "-s", "-X", "POST", "grin-wallet-testnet-contracts-container-2:23415/v2/foreign", "-u", "grin:`cat /home/grinuser/.grin/test/.api_secret`", "-d", '{"jsonrpc": "2.0", "method": "check_version", "params": {}, "id": 1}'] 28 | interval: 5s 29 | retries: 5 30 | start_period: 30s 31 | timeout: 5s 32 | expose: 33 | - "23415" 34 | ports: !override 35 | - "23415:23415" 36 | depends_on: 37 | grin-node-testnet-master: 38 | condition: service_healthy 39 | grin-wallet-testnet-contracts-3: 40 | extends: 41 | file: ../../wallet/test/contracts/docker-compose.yml 42 | service: grin-wallet-testnet-contracts 43 | container_name: grin-wallet-testnet-contracts-container-3 44 | environment: 45 | - WALLET_API_LISTEN_PORT=33415 46 | - OWNER_API_LISTEN_PORT=33415 47 | volumes: 48 | - grin-home-testnet-master:/grin-node-home 49 | - grin-wallet-home-testnet-contracts-3:/home/grinuser 50 | healthcheck: 51 | test: ["CMD", "curl", "-s", "-X", "POST", "grin-wallet-testnet-contracts-container-3:33415/v2/foreign", "-u", "grin:`cat /home/grinuser/.grin/test/.api_secret`", "-d", '{"jsonrpc": "2.0", "method": "check_version", "params": {}, "id": 1}'] 52 | interval: 5s 53 | retries: 5 54 | start_period: 30s 55 | timeout: 5s 56 | expose: 57 | - "33415" 58 | ports: !override 59 | - "33415:33415" 60 | depends_on: 61 | grin-node-testnet-master: 62 | condition: service_healthy 63 | grin-olivetin-test: 64 | extends: 65 | file: ../../monitor/test/docker-compose.yml 66 | service: grin-olivetin 67 | environment: 68 | - NODE_CHAIN_TYPE=test 69 | volumes: 70 | - ../config/olivetin.yaml:/etc/OliveTin/config.yaml 71 | depends_on: 72 | grin-wallet-testnet-contracts: 73 | condition: service_healthy 74 | grin-wallet-testnet-contracts-2: 75 | condition: service_healthy 76 | grin-wallet-testnet-contracts-3: 77 | condition: service_healthy 78 | grin-mwixnet-testnet-node-1: 79 | extends: 80 | file: ../../mwixnet/test/docker-compose.yml 81 | service: grin-mwixnet-testnet 82 | depends_on: 83 | grin-wallet-testnet-contracts: 84 | condition: service_healthy 85 | volumes: 86 | - grin-mwixnet-home-testnet-master-2:/home/nextnode 87 | grin-mwixnet-testnet-node-2: 88 | extends: 89 | file: ../../mwixnet/test/docker-compose.yml 90 | service: grin-mwixnet-testnet 91 | container_name: grin_test_mwixnet_container_2 92 | environment: 93 | - WALLET_OWNER_URL=grin-wallet-testnet-contracts-container-2:23415 94 | volumes: 95 | - grin-mwixnet-home-testnet-master-2:/home/grinuser 96 | - grin-mwixnet-home-testnet-master:/home/prevnode 97 | - grin-mwixnet-home-testnet-master-3:/home/nextnode 98 | depends_on: 99 | grin-wallet-testnet-contracts-2: 100 | condition: service_healthy 101 | grin-mwixnet-testnet-node-3: 102 | extends: 103 | file: ../../mwixnet/test/docker-compose.yml 104 | service: grin-mwixnet-testnet 105 | container_name: grin_test_mwixnet_container_3 106 | environment: 107 | - WALLET_OWNER_URL=grin-wallet-testnet-contracts-container-3:33415 108 | volumes: 109 | - grin-mwixnet-home-testnet-master-2:/home/prevnode 110 | - grin-mwixnet-home-testnet-master-3:/home/grinuser 111 | depends_on: 112 | grin-wallet-testnet-contracts: 113 | condition: service_healthy 114 | 115 | volumes: 116 | grin-home-testnet-master: 117 | name: grin-home-testnet-master 118 | grin-wallet-home-testnet-contracts: 119 | name: grin-wallet-home-testnet-contracts 120 | grin-wallet-home-testnet-contracts-2: 121 | name: grin-wallet-home-testnet-contracts-2 122 | grin-wallet-home-testnet-contracts-3: 123 | name: grin-wallet-home-testnet-contracts-3 124 | grin-mwixnet-home-testnet-master: 125 | name: grin-mwixnet-home-testnet-master 126 | grin-mwixnet-home-testnet-master-2: 127 | name: grin-mwixnet-home-testnet-master-2 128 | grin-mwixnet-home-testnet-master-3: 129 | name: grin-mwixnet-home-testnet-master-3 130 | 131 | networks: 132 | grin-testnet-network: 133 | name: grin_testnet_network -------------------------------------------------------------------------------- /node/configs/mainnet/grin-server.toml: -------------------------------------------------------------------------------- 1 | 2 | # Generated Server Configuration File for Grin 3 | # 4 | # When running the grin executable without specifying any command line 5 | # arguments, it will look for this file in two places, in the following 6 | # order: 7 | # 8 | # -The working directory 9 | # -[user home]/.grin 10 | # 11 | 12 | config_file_version = 2 13 | 14 | ######################################### 15 | ### SERVER CONFIGURATION ### 16 | ######################################### 17 | 18 | #Server connection details 19 | [server] 20 | 21 | #the directory, relative to current, in which the grin blockchain 22 | #is stored 23 | db_root = "/home/grinuser/.grin/main/chain_data" 24 | 25 | #path of TLS certificate file, self-signed certificates are not supported 26 | #tls_certificate_file = "" 27 | #private key for the TLS certificate 28 | #tls_certificate_key = "" 29 | 30 | #the address on which services will listen, e.g. Transaction Pool 31 | api_http_addr = "0.0.0.0:3413" 32 | 33 | #path of the secret token used by the Rest API and v2 Owner API to authenticate the calls 34 | #comment the it to disable basic auth 35 | api_secret_path = "/home/grinuser/.grin/main/.api_secret" 36 | 37 | #path of the secret token used by the Foreign API to authenticate the calls 38 | #comment the it to disable basic auth 39 | foreign_api_secret_path = "/home/grinuser/.grin/main/.foreign_api_secret" 40 | 41 | #The chain type, which defines the genesis block and the set of cuckoo 42 | #parameters used for mining as well as wallet output coinbase maturity. Can be: 43 | #AutomatedTesting - For CI builds and instant blockchain creation 44 | #UserTesting - For regular user testing (cuckoo 16) 45 | #Testnet - For the long term test network 46 | #Mainnet - For mainnet 47 | chain_type = "Mainnet" 48 | 49 | #The Future Time Limit (FTL) is a limit on how far into the future, 50 | #relative to a node's local time, the timestamp on a new block can be, 51 | #in order for the block to be accepted. 52 | #At Hard Fork 4, this was reduced from 12 minutes down to 5 minutes, 53 | #so as to limit possible timestamp manipulation on the new 54 | #wtema difficulty adjustment algorithm 55 | future_time_limit = 300 56 | 57 | #the chain validation mode, defines how often (if at all) we 58 | #want to run a full chain validation. Can be: 59 | #"EveryBlock" - run full chain validation when processing each block (except during sync) 60 | #"Disabled" - disable full chain validation (just run regular block validation) 61 | chain_validation_mode = "Disabled" 62 | 63 | #run the node in "full archive" mode (default is fast-sync, pruned node) 64 | archive_mode = false 65 | 66 | #skip waiting for sync on startup, (optional param, mostly for testing) 67 | skip_sync_wait = false 68 | 69 | #whether to run the ncurses TUI (Ncurses must be installed) 70 | run_tui = false 71 | 72 | #Whether to run a test miner. This is only for developer testing (chaintype 73 | #usertesting) at cuckoo 16, and will only mine into the default wallet port. 74 | #real mining should use the standalone grin-miner 75 | run_test_miner = false 76 | 77 | #test miner wallet URL (burns if this doesn't exist) 78 | #test_miner_wallet_url = "http://127.0.0.1:3415" 79 | 80 | ######################################### 81 | ### SERVER P2P CONFIGURATION ### 82 | ######################################### 83 | #The P2P server details (i.e. the server that communicates with other 84 | [server.p2p_config] 85 | 86 | #The interface on which to listen. 87 | #0.0.0.0 will listen on all interfaces, allowing others to interact 88 | #127.0.0.1 will listen on the local machine only 89 | host = "0.0.0.0" 90 | 91 | #The port on which to listen. 92 | port = 3414 93 | 94 | #All seeds/peers can be either IP address or DNS names. Port number must always be specified 95 | #how to seed this server, can be None, List or DNSSeed 96 | seeding_type = "DNSSeed" 97 | 98 | #If the seeding type is List, the list of peers to connect to can 99 | #be specified as follows: 100 | #seeds = ["192.168.0.1:3414","192.168.0.2:3414"] 101 | 102 | #hardcoded peer lists for allow/deny 103 | #will *only* connect to peers in allow list 104 | #peers_allow = ["192.168.0.1:3414", "192.168.0.2:3414"] 105 | #will *never* connect to peers in deny list 106 | #peers_deny = ["192.168.0.3:3414", "192.168.0.4:3414"] 107 | #a list of preferred peers to connect to 108 | #peers_preferred = ["192.168.0.1:3414","192.168.0.2:3414"] 109 | 110 | #how long a banned peer should stay banned 111 | #ban_window = 10800 112 | 113 | #maximum number of inbound peer connections 114 | #peer_max_inbound_count = 128 115 | 116 | #maximum number of outbound peer connections 117 | #peer_max_outbound_count = 8 118 | 119 | #preferred minimum number of outbound peers (we'll actively keep trying to add peers 120 | #until we get to at least this number) 121 | #peer_min_preferred_outbound_count = 8 122 | 123 | #amount of incoming connections temporarily allowed to exceed peer_max_inbound_count 124 | #peer_listener_buffer_count = 8 125 | 126 | # A preferred dandelion_peer, mainly used for testing dandelion 127 | # dandelion_peer = "10.0.0.1:13144" 128 | 129 | ######################################### 130 | ### MEMPOOL CONFIGURATION ### 131 | ######################################### 132 | [server.pool_config] 133 | 134 | #base fee that's accepted into the pool 135 | accept_fee_base = 500000 136 | 137 | #reorg cache retention period in minute. 138 | #the reorg cache repopulates local mempool in a reorg scenario. 139 | reorg_cache_period = 30 140 | 141 | #maximum number of transactions allowed in the pool 142 | max_pool_size = 50000 143 | 144 | #maximum number of transactions allowed in the stempool 145 | max_stempool_size = 50000 146 | 147 | #maximum total weight of transactions that can get selected to build a block 148 | mineable_max_weight = 40000 149 | 150 | 151 | ######################################### 152 | ### DANDELION CONFIGURATION ### 153 | ######################################### 154 | [server.dandelion_config] 155 | 156 | #dandelion epoch duration 157 | epoch_secs = 600 158 | 159 | #fluff and broadcast after embargo expires if tx not seen on network 160 | embargo_secs = 180 161 | 162 | #dandelion aggregation period in secs 163 | aggregation_secs = 30 164 | 165 | #dandelion stem probability (stem 90% of the time, fluff 10% of the time) 166 | stem_probability = 90 167 | 168 | #always stem our (pushed via api) txs regardless of stem/fluff epoch (as per Dandelion++ paper) 169 | always_stem_our_txs = true 170 | 171 | 172 | ################################################ 173 | ### STRATUM MINING SERVER CONFIGURATION ### 174 | ################################################ 175 | [server.stratum_mining_config] 176 | 177 | #whether stratum server is enabled 178 | enable_stratum_server = false 179 | 180 | #what port and address for the stratum server to listen on 181 | stratum_server_addr = "127.0.0.1:3416" 182 | 183 | #the amount of time, in seconds, to attempt to mine on a particular 184 | #header before stopping and re-collecting transactions from the pool 185 | attempt_time_per_block = 15 186 | 187 | #the minimum acceptable share difficulty to request from miners 188 | minimum_share_difficulty = 1 189 | 190 | #the wallet receiver to which coinbase rewards will be sent 191 | wallet_listener_url = "http://127.0.0.1:3415" 192 | 193 | #whether to ignore the reward (mostly for testing) 194 | burn_reward = false 195 | 196 | 197 | ######################################### 198 | ### WEBHOOK CONFIGURATION ### 199 | ######################################### 200 | [server.webhook_config] 201 | 202 | #The url where a POST request will be sent when a new block is accepted by our node. 203 | #block_accepted_url = "http://127.0.0.1:8080/acceptedblock" 204 | 205 | #The url where a POST request will be sent when a new transaction is received by a peer. 206 | #tx_received_url = "http://127.0.0.1:8080/tx" 207 | 208 | #The url where a POST request will be sent when a new header is received by a peer. 209 | #header_received_url = "http://127.0.0.1:8080/header" 210 | 211 | #The url where a POST request will be sent when a new block is received by a peer. 212 | #block_received_url = "http://127.0.0.1:8080/block" 213 | 214 | #The number of worker threads that will be assigned to making the http requests. 215 | nthreads = 4 216 | 217 | #The timeout of the http request in seconds. 218 | timeout = 10 219 | 220 | 221 | ######################################### 222 | ### LOGGING CONFIGURATION ### 223 | ######################################### 224 | [logging] 225 | 226 | #whether to log to stdout 227 | log_to_stdout = true 228 | 229 | #log level for stdout: Error, Warning, Info, Debug, Trace 230 | stdout_log_level = "Debug" 231 | 232 | #whether to log to a file 233 | log_to_file = true 234 | 235 | #log level for file: Error, Warning, Info, Debug, Trace 236 | file_log_level = "Info" 237 | 238 | #log file path 239 | log_file_path = "/home/grinuser/.grin/main/grin-server.log" 240 | 241 | #whether to append to the log file (true), or replace it on every run (false) 242 | log_file_append = true 243 | 244 | #maximum log file size in bytes before performing log rotation 245 | #comment it to disable log rotation 246 | log_max_size = 16777216 247 | 248 | #maximum count of the log files to rotate over 249 | log_max_files = 32 250 | 251 | -------------------------------------------------------------------------------- /node/configs/testnet/grin-server.toml: -------------------------------------------------------------------------------- 1 | 2 | # Generated Server Configuration File for Grin 3 | # 4 | # When running the grin executable without specifying any command line 5 | # arguments, it will look for this file in two places, in the following 6 | # order: 7 | # 8 | # -The working directory 9 | # -[user home]/.grin 10 | # 11 | 12 | config_file_version = 2 13 | 14 | ######################################### 15 | ### SERVER CONFIGURATION ### 16 | ######################################### 17 | 18 | #Server connection details 19 | [server] 20 | 21 | #the directory, relative to current, in which the grin blockchain 22 | #is stored 23 | db_root = "/home/grinuser/.grin/test/chain_data" 24 | 25 | #path of TLS certificate file, self-signed certificates are not supported 26 | #tls_certificate_file = "" 27 | #private key for the TLS certificate 28 | #tls_certificate_key = "" 29 | 30 | #the address on which services will listen, e.g. Transaction Pool 31 | api_http_addr = "0.0.0.0:13413" 32 | 33 | #path of the secret token used by the Rest API and v2 Owner API to authenticate the calls 34 | #comment the it to disable basic auth 35 | api_secret_path = "/home/grinuser/.grin/test/.api_secret" 36 | 37 | #path of the secret token used by the Foreign API to authenticate the calls 38 | #comment the it to disable basic auth 39 | foreign_api_secret_path = "/home/grinuser/.grin/test/.foreign_api_secret" 40 | 41 | #The chain type, which defines the genesis block and the set of cuckoo 42 | #parameters used for mining as well as wallet output coinbase maturity. Can be: 43 | #AutomatedTesting - For CI builds and instant blockchain creation 44 | #UserTesting - For regular user testing (cuckoo 16) 45 | #Testnet - For the long term test network 46 | #Mainnet - For mainnet 47 | chain_type = "Testnet" 48 | 49 | #The Future Time Limit (FTL) is a limit on how far into the future, 50 | #relative to a node's local time, the timestamp on a new block can be, 51 | #in order for the block to be accepted. 52 | #At Hard Fork 4, this was reduced from 12 minutes down to 5 minutes, 53 | #so as to limit possible timestamp manipulation on the new 54 | #wtema difficulty adjustment algorithm 55 | future_time_limit = 300 56 | 57 | #the chain validation mode, defines how often (if at all) we 58 | #want to run a full chain validation. Can be: 59 | #"EveryBlock" - run full chain validation when processing each block (except during sync) 60 | #"Disabled" - disable full chain validation (just run regular block validation) 61 | chain_validation_mode = "Disabled" 62 | 63 | #run the node in "full archive" mode (default is fast-sync, pruned node) 64 | archive_mode = false 65 | 66 | #skip waiting for sync on startup, (optional param, mostly for testing) 67 | skip_sync_wait = false 68 | 69 | #whether to run the ncurses TUI (Ncurses must be installed) 70 | run_tui = false 71 | 72 | #Whether to run a test miner. This is only for developer testing (chaintype 73 | #usertesting) at cuckoo 16, and will only mine into the default wallet port. 74 | #real mining should use the standalone grin-miner 75 | run_test_miner = false 76 | 77 | #test miner wallet URL (burns if this doesn't exist) 78 | #test_miner_wallet_url = "http://127.0.0.1:3415" 79 | 80 | ######################################### 81 | ### SERVER P2P CONFIGURATION ### 82 | ######################################### 83 | #The P2P server details (i.e. the server that communicates with other 84 | [server.p2p_config] 85 | 86 | #The interface on which to listen. 87 | #0.0.0.0 will listen on all interfaces, allowing others to interact 88 | #127.0.0.1 will listen on the local machine only 89 | host = "0.0.0.0" 90 | 91 | #The port on which to listen. 92 | port = 13414 93 | 94 | #All seeds/peers can be either IP address or DNS names. Port number must always be specified 95 | #how to seed this server, can be None, List or DNSSeed 96 | seeding_type = "DNSSeed" 97 | 98 | #If the seeding type is List, the list of peers to connect to can 99 | #be specified as follows: 100 | #seeds = ["192.168.0.1:3414","192.168.0.2:3414"] 101 | 102 | #hardcoded peer lists for allow/deny 103 | #will *only* connect to peers in allow list 104 | #peers_allow = ["192.168.0.1:3414", "192.168.0.2:3414"] 105 | #will *never* connect to peers in deny list 106 | #peers_deny = ["192.168.0.3:3414", "192.168.0.4:3414"] 107 | #a list of preferred peers to connect to 108 | #peers_preferred = ["192.168.0.1:3414","192.168.0.2:3414"] 109 | 110 | #how long a banned peer should stay banned 111 | #ban_window = 10800 112 | 113 | #maximum number of inbound peer connections 114 | #peer_max_inbound_count = 128 115 | 116 | #maximum number of outbound peer connections 117 | #peer_max_outbound_count = 8 118 | 119 | #preferred minimum number of outbound peers (we'll actively keep trying to add peers 120 | #until we get to at least this number) 121 | #peer_min_preferred_outbound_count = 8 122 | 123 | #amount of incoming connections temporarily allowed to exceed peer_max_inbound_count 124 | #peer_listener_buffer_count = 8 125 | 126 | # A preferred dandelion_peer, mainly used for testing dandelion 127 | # dandelion_peer = "10.0.0.1:13144" 128 | 129 | ######################################### 130 | ### MEMPOOL CONFIGURATION ### 131 | ######################################### 132 | [server.pool_config] 133 | 134 | #base fee that's accepted into the pool 135 | accept_fee_base = 500000 136 | 137 | #reorg cache retention period in minute. 138 | #the reorg cache repopulates local mempool in a reorg scenario. 139 | reorg_cache_period = 30 140 | 141 | #maximum number of transactions allowed in the pool 142 | max_pool_size = 50000 143 | 144 | #maximum number of transactions allowed in the stempool 145 | max_stempool_size = 50000 146 | 147 | #maximum total weight of transactions that can get selected to build a block 148 | mineable_max_weight = 40000 149 | 150 | 151 | ######################################### 152 | ### DANDELION CONFIGURATION ### 153 | ######################################### 154 | [server.dandelion_config] 155 | 156 | #dandelion epoch duration 157 | epoch_secs = 600 158 | 159 | #fluff and broadcast after embargo expires if tx not seen on network 160 | embargo_secs = 180 161 | 162 | #dandelion aggregation period in secs 163 | aggregation_secs = 30 164 | 165 | #dandelion stem probability (stem 90% of the time, fluff 10% of the time) 166 | stem_probability = 90 167 | 168 | #always stem our (pushed via api) txs regardless of stem/fluff epoch (as per Dandelion++ paper) 169 | always_stem_our_txs = true 170 | 171 | 172 | ################################################ 173 | ### STRATUM MINING SERVER CONFIGURATION ### 174 | ################################################ 175 | [server.stratum_mining_config] 176 | 177 | #whether stratum server is enabled 178 | enable_stratum_server = false 179 | 180 | #what port and address for the stratum server to listen on 181 | stratum_server_addr = "127.0.0.1:3416" 182 | 183 | #the amount of time, in seconds, to attempt to mine on a particular 184 | #header before stopping and re-collecting transactions from the pool 185 | attempt_time_per_block = 15 186 | 187 | #the minimum acceptable share difficulty to request from miners 188 | minimum_share_difficulty = 1 189 | 190 | #the wallet receiver to which coinbase rewards will be sent 191 | wallet_listener_url = "http://127.0.0.1:3415" 192 | 193 | #whether to ignore the reward (mostly for testing) 194 | burn_reward = false 195 | 196 | 197 | ######################################### 198 | ### WEBHOOK CONFIGURATION ### 199 | ######################################### 200 | [server.webhook_config] 201 | 202 | #The url where a POST request will be sent when a new block is accepted by our node. 203 | #block_accepted_url = "http://127.0.0.1:8080/acceptedblock" 204 | 205 | #The url where a POST request will be sent when a new transaction is received by a peer. 206 | #tx_received_url = "http://127.0.0.1:8080/tx" 207 | 208 | #The url where a POST request will be sent when a new header is received by a peer. 209 | #header_received_url = "http://127.0.0.1:8080/header" 210 | 211 | #The url where a POST request will be sent when a new block is received by a peer. 212 | #block_received_url = "http://127.0.0.1:8080/block" 213 | 214 | #The number of worker threads that will be assigned to making the http requests. 215 | nthreads = 4 216 | 217 | #The timeout of the http request in seconds. 218 | timeout = 10 219 | 220 | 221 | ######################################### 222 | ### LOGGING CONFIGURATION ### 223 | ######################################### 224 | [logging] 225 | 226 | #whether to log to stdout 227 | log_to_stdout = true 228 | 229 | #log level for stdout: Error, Warning, Info, Debug, Trace 230 | stdout_log_level = "Debug" 231 | 232 | #whether to log to a file 233 | log_to_file = true 234 | 235 | #log level for file: Error, Warning, Info, Debug, Trace 236 | file_log_level = "Debug" 237 | 238 | #log file path 239 | log_file_path = "/home/grinuser/.grin/test/grin-server.log" 240 | 241 | #whether to append to the log file (true), or replace it on every run (false) 242 | log_file_append = true 243 | 244 | #maximum log file size in bytes before performing log rotation 245 | #comment it to disable log rotation 246 | log_max_size = 16777216 247 | 248 | #maximum count of the log files to rotate over 249 | log_max_files = 32 250 | 251 | -------------------------------------------------------------------------------- /node/main/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Mainnet Node - Built from master 3 | grin-node-mainnet-master: 4 | build: 5 | context: ../../ 6 | dockerfile: base-build/Dockerfile.node.master 7 | target: grin_node_master 8 | container_name: grin-node-mainnet-master-container 9 | networks: 10 | - grin-mainnet-network 11 | image: grin-node-mainnet-master 12 | environment: 13 | - RUST_BACKTRACE=1 14 | expose: 15 | - "3413" 16 | - "3414" 17 | ports: 18 | - "3413:3413" 19 | - "3414:3414" 20 | volumes: 21 | - ../configs/mainnet/grin-server.toml:/home/grinuser/.grin/main/grin-server.toml 22 | - grin-home-mainnet-master:/home/grinuser 23 | 24 | volumes: 25 | grin-home-mainnet-master: 26 | 27 | networks: 28 | grin-mainnet-network: 29 | name: grin_mainnet_network -------------------------------------------------------------------------------- /node/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Testnet Node - Built from master 3 | grin-node-testnet-master: 4 | build: 5 | context: ../../ 6 | dockerfile: ./base-build/Dockerfile.node.master 7 | target: grin_node_master 8 | container_name: grin-node-testnet-master-container 9 | healthcheck: 10 | test: ["CMD", "curl", "-s", "-X", "POST", "grin-node-testnet-master-container:13413/v2/owner", "-u", "grin:`cat /home/grinuser/.grin/test/.api_secret`", "-d", '{"jsonrpc": "2.0", "method": "get_status", "params": [], "id": 1}'] 11 | interval: 5s 12 | retries: 5 13 | start_period: 30s 14 | timeout: 5s 15 | networks: 16 | - grin-testnet-network 17 | image: grin-node-testnet-master 18 | command: ["--testnet"] 19 | environment: 20 | - RUST_BACKTRACE=1 21 | expose: 22 | - "13413" 23 | - "13414" 24 | ports: 25 | - "13413:13413" 26 | - "13414:13414" 27 | volumes: 28 | - ../configs/testnet/grin-server.toml:/home/grinuser/.grin/test/grin-server.toml 29 | - grin-home-testnet-master:/home/grinuser 30 | 31 | volumes: 32 | grin-home-testnet-master: 33 | name: grin-home-testnet-master 34 | 35 | networks: 36 | grin-testnet-network: 37 | name: grin_testnet_network -------------------------------------------------------------------------------- /scripts/docker_cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #just a helper script for cleaning all containers 3 | docker ps -aq | xargs docker stop 4 | docker ps -aq --no-trunc | xargs docker rm 5 | -------------------------------------------------------------------------------- /wallet/main/contracts/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Wallet Listeners - Built from contracts 3 | grin-wallet-mainnet-contracts: 4 | build: 5 | context: ../../../ 6 | dockerfile: base-build/Dockerfile.wallet 7 | target: grin_wallet_contracts 8 | container_name: grin-wallet-mainnet-contracts-container 9 | networks: 10 | - grin-mainnet-network 11 | image: grin-wallet-mainnet-contracts 12 | command: ["owner_api", "--run_foreign"] 13 | environment: 14 | - RUST_BACKTRACE=1 15 | - GRIN_CHAIN_TYPE="Testnet" 16 | - OWNER_API_LISTEN_INTERFACE="0.0.0.0" 17 | - WALLET_API_LISTEN_PORT=13415 18 | - OWNER_API_LISTEN_PORT=13415 19 | - NODE_API_SECRET_PATH="/grin-node-home/.grin/test/.foreign_api_secret" 20 | - NODE_API_HTTP_ADDR="http://grin-node-testnet-master-container:13413" 21 | expose: 22 | - "3415" 23 | ports: 24 | - "3415:3415" 25 | volumes: 26 | - grin-wallet-home-mainnet-contracts:/home/grinuser 27 | - main_grin-home-mainnet-master:/grin-node-home 28 | 29 | volumes: 30 | grin-wallet-home-mainnet-contracts: 31 | main_grin-home-mainnet-master: 32 | external: true 33 | 34 | networks: 35 | grin-mainnet-network: 36 | name: grin_mainnet_network 37 | external: true -------------------------------------------------------------------------------- /wallet/scripts/wallet-first-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is run once on first boot of the image 3 | CONTAINER_ALREADY_STARTED="WALLET_FIRST_RUN_DONE" 4 | if [ ! -e $CONTAINER_ALREADY_STARTED ]; then 5 | touch $CONTAINER_ALREADY_STARTED 6 | echo "-- First container startup --" 7 | if [ $GRIN_CHAIN_TYPE == "test" ]; 8 | then 9 | RUST_BACKTRACE=full grin-wallet --testnet init 10 | else 11 | grin-wallet init 12 | fi 13 | fi 14 | 15 | GRIN_NODE_URL_REPLACED=$(echo "$NODE_API_HTTP_ADDR" | sed 's/\//\\\//g') 16 | NODE_API_SECRET_PATH_REPLACED=$(echo "$NODE_API_SECRET_PATH" | sed 's/\//\\\//g') 17 | sed -i "s/.*check_node_api_http_addr.*/check_node_api_http_addr = \"$GRIN_NODE_URL_REPLACED\"/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 18 | sed -i "s/node_api_secret_path.*/node_api_secret_path = \"$NODE_API_SECRET_PATH_REPLACED\"/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 19 | sed -i "s/.*owner_api_listen_port.*/owner_api_listen_port = $OWNER_API_LISTEN_PORT/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 20 | sed -i "s/^api_secret_path.*/#api_secret_path = $OWNER_API_LISTEN_PORT/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 21 | sed -i "s/^api_listen_port.*/api_listen_port = $WALLET_API_LISTEN_PORT/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 22 | # hack to avoid complicated sed command 23 | sed -i "s/.*#tls_certificate_key.*/owner_api_listen_interface = \"$OWNER_API_LISTEN_INTERFACE\"/g" /home/grinuser/.grin/$GRIN_CHAIN_TYPE/grin-wallet.toml 24 | 25 | if [ $GRIN_CHAIN_TYPE == "test" ]; then 26 | RUST_BACKTRACE=full grin-wallet --testnet owner_api --run_foreign 27 | else 28 | grin-wallet owner_api --run_foreign 29 | fi -------------------------------------------------------------------------------- /wallet/test/contracts/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | # Grin Wallet Listeners - Built from contracts 3 | grin-wallet-testnet-contracts: 4 | build: 5 | context: ../../../ 6 | dockerfile: base-build/Dockerfile.wallet 7 | target: grin_wallet_contracts 8 | container_name: grin-wallet-testnet-contracts-container 9 | healthcheck: 10 | test: ["CMD", "curl", "-s", "-X", "POST", "grin-wallet-testnet-contracts-container:13415/v2/foreign", "-u", "grin:`cat /home/grinuser/.grin/test/.api_secret`", "-d", '{"jsonrpc": "2.0", "method": "check_version", "params": {}, "id": 1}'] 11 | interval: 5s 12 | retries: 5 13 | start_period: 30s 14 | timeout: 5s 15 | networks: 16 | - grin-testnet-network 17 | image: grin-wallet-testnet-contracts 18 | environment: 19 | - RUST_BACKTRACE=1 20 | - WALLET_PASSWORD= 21 | - GRIN_CHAIN_TYPE=test 22 | - OWNER_API_LISTEN_INTERFACE=0.0.0.0 23 | - WALLET_API_LISTEN_PORT=13415 24 | - OWNER_API_LISTEN_PORT=13415 25 | - NODE_API_SECRET_PATH=/grin-node-home/.grin/test/.foreign_api_secret 26 | - NODE_API_HTTP_ADDR=http://grin-node-testnet-master-container:13413 27 | expose: 28 | - "13415" 29 | ports: 30 | - "13415:13415" 31 | volumes: 32 | - ../../scripts/wallet-first-run.sh:/home/grinuser/wallet-first-run.sh 33 | - grin-wallet-home-testnet-contracts:/home/grinuser 34 | - grin-home-testnet-master:/grin-node-home 35 | 36 | volumes: 37 | grin-wallet-home-testnet-contracts: 38 | name: grin-wallet-home-testnet-contracts 39 | grin-home-testnet-master: 40 | external: true 41 | 42 | networks: 43 | grin-testnet-network: 44 | name: grin_testnet_network 45 | external: true 46 | --------------------------------------------------------------------------------