first commit
This commit is contained in:
commit
8019ef9ccf
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@ -0,0 +1,3 @@
|
||||
.git
|
||||
examples/
|
||||
rsync.sh
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
config/
|
||||
/rsync.sh
|
||||
*.pyc
|
||||
__pycache__
|
139
Dockerfile
Normal file
139
Dockerfile
Normal file
@ -0,0 +1,139 @@
|
||||
from debian:stable-slim
|
||||
LABEL maintainer="dro@arrakis.it"
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y automake build-essential pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev libsystemd-dev zlib1g-dev make g++ tmux git jq wget libncursesw5 libtool autoconf libsqlite3-dev m4 ca-certificates gcc libc6-dev \
|
||||
&& apt-get clean
|
||||
|
||||
# Install rust
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH \
|
||||
RUST_VERSION=1.47.0
|
||||
|
||||
RUN set -eux; \
|
||||
dpkgArch="$(dpkg --print-architecture)"; \
|
||||
case "${dpkgArch##*-}" in \
|
||||
amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='49c96f3f74be82f4752b8bffcf81961dea5e6e94ce1ccba94435f12e871c3bdb' ;; \
|
||||
armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='5a2be2919319e8778698fa9998002d1ec720efe7cb4f6ee4affb006b5e73f1be' ;; \
|
||||
arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='d93ef6f91dab8299f46eef26a56c2d97c66271cea60bf004f2f088a86a697078' ;; \
|
||||
i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='e3d0ae3cfce5c6941f74fed61ca83e53d4cd2deb431b906cbd0687f246efede4' ;; \
|
||||
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
|
||||
esac; \
|
||||
url="https://static.rust-lang.org/rustup/archive/1.22.1/${rustArch}/rustup-init"; \
|
||||
wget "$url"; \
|
||||
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
|
||||
chmod +x rustup-init; \
|
||||
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
|
||||
rm rustup-init; \
|
||||
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
|
||||
rustup --version; \
|
||||
cargo --version; \
|
||||
rustc --version; \
|
||||
rm -rf /var/lib/apt/lists/*;
|
||||
|
||||
# Install cabal
|
||||
ENV PATH="/root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH"
|
||||
RUN wget https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz \
|
||||
&& tar -xf cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz \
|
||||
&& rm cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz cabal.sig \
|
||||
&& mkdir -p ~/.local/bin \
|
||||
&& mv cabal ~/.local/bin/ \
|
||||
&& cabal update && cabal --version
|
||||
|
||||
# Install GHC
|
||||
RUN wget https://downloads.haskell.org/ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz \
|
||||
&& tar -xf ghc-8.10.2-x86_64-deb9-linux.tar.xz \
|
||||
&& rm ghc-8.10.2-x86_64-deb9-linux.tar.xz \
|
||||
&& cd ghc-8.10.2 \
|
||||
&& ./configure \
|
||||
&& make install \
|
||||
&& cd / \
|
||||
&& rm -rf /ghc-8.10.2
|
||||
|
||||
# Install libsodium
|
||||
RUN git clone https://github.com/input-output-hk/libsodium \
|
||||
&& cd libsodium \
|
||||
&& git checkout 66f017f1 \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure \
|
||||
&& make \
|
||||
&& make install \
|
||||
&& cd .. && rm -rf libsodium
|
||||
ENV LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
# Install cardano-node
|
||||
ARG VERSION
|
||||
RUN echo "Building tags/$VERSION..." \
|
||||
&& echo tags/$VERSION > /CARDANO_BRANCH \
|
||||
&& git clone https://github.com/input-output-hk/cardano-node.git \
|
||||
&& cd cardano-node \
|
||||
&& git fetch --all --recurse-submodules --tags \
|
||||
&& git tag \
|
||||
&& git checkout tags/$VERSION \
|
||||
&& cabal configure --with-compiler=ghc-8.10.2 \
|
||||
&& echo "package cardano-crypto-praos" >> cabal.project.local \
|
||||
&& echo " flags: -external-libsodium-vrf" >> cabal.project.local \
|
||||
&& cabal build all \
|
||||
&& mkdir -p /root/.local/bin/ \
|
||||
&& cp -p dist-newstyle/build/x86_64-linux/ghc-8.10.2/cardano-node-${VERSION}/x/cardano-node/build/cardano-node/cardano-node /root/.local/bin/ \
|
||||
&& cp -p dist-newstyle/build/x86_64-linux/ghc-8.10.2/cardano-cli-${VERSION}/x/cardano-cli/build/cardano-cli/cardano-cli /root/.local/bin/ \
|
||||
&& rm -rf /root/.cabal/packages \
|
||||
&& rm -rf /usr/local/lib/ghc-8.6.5/ \
|
||||
&& rm -rf /cardano-node/dist-newstyle/ \
|
||||
&& rm -rf /root/.cabal/store/ghc-8.6.5
|
||||
|
||||
# Install cncli
|
||||
#RUN git clone https://github.com/AndrewWestberg/cncli \
|
||||
# && cd cncli \
|
||||
# && cargo install --path . --force \
|
||||
# && cncli -V \
|
||||
# && cd / && rm -rf cncli
|
||||
|
||||
# Install tools
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y vim procps dnsutils bc curl nano cron python3 python3-pip \
|
||||
&& apt-get clean
|
||||
RUN pip3 install pytz
|
||||
|
||||
# Expose ports
|
||||
## cardano-node, EKG, Prometheus
|
||||
EXPOSE 3000 12788 12798
|
||||
|
||||
# ENV variables
|
||||
ENV NODE_PORT="3000" \
|
||||
NODE_NAME="node1" \
|
||||
NODE_TOPOLOGY="" \
|
||||
NODE_RELAY="False" \
|
||||
CARDANO_NETWORK="main" \
|
||||
EKG_PORT="12788" \
|
||||
PROMETHEUS_HOST="127.0.0.1" \
|
||||
PROMETHEUS_PORT="12798" \
|
||||
RESOLVE_HOSTNAMES="False" \
|
||||
REPLACE_EXISTING_CONFIG="False" \
|
||||
POOL_PLEDGE="100000000000" \
|
||||
POOL_COST="10000000000" \
|
||||
POOL_MARGIN="0.05" \
|
||||
METADATA_URL="" \
|
||||
PUBLIC_RELAY_IP="TOPOLOGY" \
|
||||
WAIT_FOR_SYNC="True" \
|
||||
AUTO_TOPOLOGY="True" \
|
||||
PATH="/root/.local/bin/:/scripts/:/scripts/functions/:/cardano-node/scripts/:${PATH}" \
|
||||
LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}" \
|
||||
CARDANO_NODE_SOCKET_PATH="DEFAULT"
|
||||
|
||||
# Add config
|
||||
ADD cfg-templates/ /cfg-templates/
|
||||
RUN mkdir -p /config/
|
||||
VOLUME /config/
|
||||
|
||||
# Add scripts
|
||||
RUN echo "source /scripts/init_node_vars" >> /root/.bashrc
|
||||
ADD scripts/ /scripts/
|
||||
RUN chmod -R +x /scripts/
|
||||
|
||||
ENTRYPOINT ["/scripts/start-cardano-node"]
|
300
README.md
Normal file
300
README.md
Normal file
@ -0,0 +1,300 @@
|
||||
# Running a Cardano Stake Pool
|
||||
|
||||
Visit my stake pool @ [ada.arrakis.it](https://ada.arrakis.it).
|
||||
|
||||
From the official [cardano-node setup](https://docs.cardano.org/projects/cardano-node/en/latest/) tutorials from IOHK.
|
||||
The container downloads and builds the [cardano-node](https://github.com/input-output-hk/cardano-node.git).
|
||||
It can start either a block-producing node or a relay node, or both, and connect to the cardano network. By default it will connect to the test network, you can run on other networks using the CARDANO_NETWORK environment variable, See the [Environment variables](#environment) section.
|
||||
If you want to run a stake pool, the block-producing container can take all the required steps to set up and register the stake pool.
|
||||
|
||||
|
||||
## Steps in Running a Stake Pool
|
||||
|
||||
### Reasonably secure
|
||||
|
||||
This is an example on how to run your staking pool in a reasonably securely way, by keeping your `cold-keys` and `wallets` away from the online block-producing node. It is always a trade-off between security and convenience, but I find this method to be reasonably secure, if you can some precautions, as described in the below setup.
|
||||
|
||||
For this setup you will need 3 hosts.
|
||||
`host1` for running the relay node.
|
||||
`host2` host for running the block-producing node.
|
||||
`host3` host for generating and registering all the keys, addresses and certificates and storing the cold-keys for refreshing the KES keys and certificates. This can be a host you are running locally, for example a secure linux live boot, with all incoming traffic completely shut off. **Warning:** If you run on a Linux live boot, with no persistant storage, it is EXTREMELY important that you backup your staking directory containing all the private keys, before you shut it off, otherwise your wallets will be lost.
|
||||
|
||||
1. Upload your stake-pool metadata json file ([See example](#metadata-example)) to a host so it is accessible to the public. For example as a [github gist](https://gist.github.com/).
|
||||
2. Start a relay node on `host1` and make it connect to the block-producing node on `host2`. See the [relay node example](#relay-example2).
|
||||
3. Start a registration node on `host3`, with the `--staking` and`--create` arguments, and make it connect to the relay node on `host1`. See the [registration node example](#registration-example2).
|
||||
4. Fund your payment address generated and displayed in Step 3 to finalize the registration.
|
||||
5. Wait for the registration node on `host3` to setup and register your pool.
|
||||
6. Create Firewall rules for your block-producing node on `host2` to only accept incoming traffic from your relay node on `host1`.
|
||||
7. Copy the `config/staking/pool-keys` directory from the registration node on `host3` to the `config/staking/pool-keys` directory on `host2`.
|
||||
8. Start a block-producing node on `host2`, with the `--start` and `--staking` arguments, and make it connect to the relay node on `host1`. See the [block-producing node example](#producing-example2).
|
||||
|
||||
|
||||
#### Renewing KES keys and certificates
|
||||
|
||||
To renew your KES keys and certificates you have to run the `generate_operational_certificate` command in the registration container on `host3`
|
||||
The status window in the block-producing container will tell you when you have to generate new keys.
|
||||
|
||||
1. Start the command-line interface in the registration container, containing the `cold-keys` directory, on `host3`. Using `docker exec -it main-registration bash`.
|
||||
2. Run the `generate_operational_certificate` command and wait for it to complete.
|
||||
3. Copy the `config/staking/pool-keys/` directory on `host3` to the `config/staking/pool-keys/` directory on `host2`
|
||||
4. Restart the block-producing container on `host2`.
|
||||
|
||||
|
||||
#### relay node on mainnet <a id="relay-example2"></a>
|
||||
|
||||
Step 1. Run on `host1`. See `examples/main-relay1.sh`.
|
||||
|
||||
```
|
||||
docker network create -d bridge cardano
|
||||
docker run -it \
|
||||
--restart=unless-stopped \
|
||||
--network=cardano \
|
||||
--name main-relay1 \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-p 3000:3000 \
|
||||
-p 12798:12798 \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="relay1" \
|
||||
-e NODE_TOPOLOGY="<IP-address of block-producing node>:3000/1" \
|
||||
-e NODE_RELAY="True" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e PROMETHEUS_PORT="12798" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start
|
||||
```
|
||||
|
||||
|
||||
#### registration node on mainnet <a id="registration-example2"></a>
|
||||
|
||||
Step 2. Run on `host3`. See `examples/main-registration.sh`.
|
||||
|
||||
```
|
||||
docker network create -d bridge cardano
|
||||
docker run -it --rm \
|
||||
--name main-registration \
|
||||
--network=cardano \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="registration" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay1 node>:3000/1" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e CREATE_STAKEPOOL="True" \
|
||||
-e POOL_PLEDGE="100000000000" \
|
||||
-e POOL_COST="340000000" \
|
||||
-e POOL_MARGIN="0.05" \
|
||||
-e METADATA_URL="<URL of metadata.json>" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start --staking
|
||||
```
|
||||
|
||||
|
||||
#### block-producing node on mainnet <a id="producing-example2"></a>
|
||||
|
||||
Step 5. Run on `host2`. See `examples/main-producing.sh`.
|
||||
|
||||
```
|
||||
docker network create -d bridge cardano
|
||||
docker run -it --rm \
|
||||
--network=cardano \
|
||||
--name main-producing \
|
||||
-p 3000:3000 \
|
||||
-p 12798:12798 \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="block-producing" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay1 node>:3000/1" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e PROMETHEUS_PORT="12798" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start --staking
|
||||
```
|
||||
|
||||
|
||||
### Best practice
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
This is an example on how to run your staking pool in a completely secure way, by only keeping your `cold-keys` and `wallets` on a completely offline node, and then transfer all relevant registration transactions and `pool-keys` to the online block-producing node. This requires a bit more steps than the reasonably secure method.
|
||||
|
||||
For this setup you will need 3 hosts.
|
||||
`host1` for running the relay node.
|
||||
`host2` host for running the block-producing node and submitting the registration transactions.
|
||||
`host3` host for generating all the keys, addresses, certificates and transactions, and storing the cold-keys for refreshing the KES keys and certificates. This must be an completely offline host running locally.
|
||||
|
||||
1. Upload your stake-pool metadata json file ([See example](#metadata-example)) to a host so it is accessible to the public. For example as a [github gist](https://gist.github.com/).
|
||||
2. Start a relay node on `host1` and make it connect to the block-producing node on `host2`.
|
||||
3. Generate `protocol.json` on `host1` by running `get_protocol`.
|
||||
4. Transfer the `protocol.json` from `host1` to the staking directory of `host3`.
|
||||
5. Add the `metadata.json` file to `config/staking` directory the on `host3`
|
||||
6. Start a cold-creation node `host3` using the `--create-cold` argument, and follow steps.
|
||||
7. Fund your owners payment address(es) created on `host3`, make sure you send to the correct addresses.
|
||||
8. Get UTXO and TXIX for funded owners payment address(es) by quering the address(es) on `host1` or `host2`.
|
||||
9. Input the relevant UTXO and TXIX values when promted on `host3`.
|
||||
10. Find the slot tip of the blockchain by running `get_slot` on `host1` or `host2`.
|
||||
11. Input the slot tip on `host3` when prompted.
|
||||
12. Create Firewall rules for your block-producing node on `host2` to only accept incoming traffic from your relay node on `host1`.
|
||||
13. Upload staking-hot.tar.gz on `host2`
|
||||
14. Start a block-producing node on `host2`, with the `--start`, `--staking` and `--register-cold` arguments, and make it connect to the relay node on `host1`.
|
||||
15. Wait for the block-producing node on `host2` to register your pool and start staking.
|
||||
|
||||
See examples of the containers in `examples/best-practice/`.
|
||||
</details>
|
||||
|
||||
|
||||
### Test setup
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
**Warning:** These examples are ONLY for demonstration. The examples will run the nodes on the same server, using the `host` network, and connects to eachother using the localhost IP-address. This is not recommended. It is recommended to run the nodes on seperate servers and connect them using their public or local network IP-addresses, if they run within the same network. The idea is to keep the block-producing node completely locked off from anything other than the relay node. The block-producing node will also initialize and register the stake pool automatically, which is better to do on a seperate node, to keep the `cold-keys` directory and `wallets` secret key files (`wallets/*/*.skey`) completely away from the online nodes.
|
||||
|
||||
1. Upload your stake-pool metadata json file ([See example](#metadata-example)) to a host so it is accessible to the public. For example as a [github gist](https://gist.github.com/).
|
||||
2. Start a relay node and make it connect to the block-producing node. See the `examples/mc4-relay1.sh` example file.
|
||||
3. Start a block-producing node with the `--start`, `--staking` and `--create` arguments, and make it connect to the relay node. See the `examples/mc4-producing.sh` example file.
|
||||
4. Wait for the block-producing node to setup and register your pool.
|
||||
5. Fund your payment address generated and displayed in Step 4 to finalize the registration.
|
||||
|
||||
The docker-compose file `examples/test/mc4-docker-compose.yaml` will run these 2 containers automatically. Use the command `docker-compose -f mc4-docker-compose.yaml up` to start them.
|
||||
</details>
|
||||
|
||||
## Monitoring
|
||||
|
||||
If you want to monitor your nodes using prometheus across different hosts, you can set the environment variable `PROMETHEUS_HOST=0.0.0.0`. This makes the Prometheus service accessible to other hosts. So you can for example run a Prometheus+Grafana service on your relay node, scraping data from the block-producing and relay nodes.
|
||||
If you do this, it is EXTREMELY important that you set up a Firewall rule ONLY allowing traffic from your relay nodes host on the Prometheus port, otherwise everyone will be able to monitor your node.
|
||||
|
||||
|
||||
## Metadata example <a id="metadata-example"></a>
|
||||
|
||||
The `examples/metadata.json` file is the file that holds metadata about your pool.
|
||||
|
||||
It looks like the following, and has to be upload to a host so it is accessible to the public via. an URL.
|
||||
You can for example upload it as a [github gist](https://gist.github.com).
|
||||
|
||||
```
|
||||
{
|
||||
"name": "Example Pool",
|
||||
"description": "Cardano stakepool example",
|
||||
"ticker": "TEST",
|
||||
"homepage": "https://github.com/abracadaniel/cardano-node-docker"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Arguments
|
||||
|
||||
You can pass the following arguments to the start up script.
|
||||
|
||||
| Argument | Function |
|
||||
| :-- | -- |
|
||||
| --start | Start node. |
|
||||
| --create | Start Stakepool creation. Initializes Stake Pool keys, addresses and certificates, and sends them to the blockchain, when starting as a stakepool, if it is not already initialized. |
|
||||
| --cold-create | Initializes Stake Pool keys, addresses and certificates, and sign registration transactions. Registation transactions has to be sent using the `--cold-register` argument. |
|
||||
| --cold-register | Submits the address and pool registration transactions to the blockchain created using the `--cold-create` argument. |
|
||||
| --staking | Start as a staking node (Requires the `--start` argument) |
|
||||
| --cli | Start command-line interface. |
|
||||
| --update | Update the node software. |
|
||||
| --init_config | Initialize config. |
|
||||
| --help | see this message. |
|
||||
|
||||
|
||||
## Environment variables <a id="environment"></a>
|
||||
|
||||
You can pass the following environment variables to the container.
|
||||
|
||||
| Variable | Function |
|
||||
| :-- | -- |
|
||||
| NODE_PORT | Port of node. Default: 3000. |
|
||||
| NODE_NAME | Name of node. Default: node1. |
|
||||
| NODE_TOPOLOGY | Topology of the node. Should be comma separated for each individual node to add, on the form: \<ip\>:\<port\>/\<valency\>. So for example: 127.0.0.1:3001/1,127.0.0.1:3002/1. |
|
||||
| NODE_RELAY | Set to True if default IOHK relay should be added to the network topology. Default: False. |
|
||||
| HOST_ADDR | Set cardano-node host address. Defaults to public IP address. |
|
||||
| CARDANO_NETWORK | Carano network to use (main, test, pioneer). Default: main. |
|
||||
| EKG_PORT | Port of EKG monitoring. Default: 12788. |
|
||||
| PROMETHEUS_HOST | Host of Prometheus monitoring. Default: 127.0.0.1. |
|
||||
| PROMETHEUS_PORT | Port of Prometheus monitoring. Default: 12798. |
|
||||
| RESOLVE_HOSTNAMES | Resolve topology hostnames to IP-addresses. Default: False. |
|
||||
| REPLACE_EXISTING_CONFIG | Reset and replace existing configs. Default: False. |
|
||||
| POOL_PLEDGE | Pledge (lovelace). Default: 100000000000 |
|
||||
| POOL_COST | Operational costs per epoch (lovelace). Default: 10000000000 |
|
||||
| POOL_MARGIN | Operator margin. Default: 0.05 |
|
||||
| METADATA_URL | URL for file containing stake pool metadata information. See \`examples/metadata.json\` for examle. The file be uploaded to an URL accessible to public. |
|
||||
| MULTI_OWNERS | Define multiple stakepool owner wallets which participates in the stakepool pledge. Comma separated values. Example: owner2,owner3. If the wallets do not exist they will automatically be created. Default: None. |
|
||||
| PUBLIC_RELAY_IP | Public IP address of Relay node. <br/><br/>Values:<br/>\<Any IP address\><br/>TOPOLOGY: Use first entry of the topology.<br/>PUBLIC: Use public IP of node.<br/>Default: TOPOLOGY. |
|
||||
| PUBLIC_RELAY_PORT | Public port of Relay node. <br/><br/>Values:<br/>\<Any Port\><br/>If PUBLIC_RELAY_IP=TOPOLOGY the PUBLIC_RELAY_PORT will also be updated accordingly.<br/>Default: First entry of the topology. |
|
||||
| AUTO_TOPOLOGY | Automatically update topology.json. Default: True |
|
||||
|
||||
|
||||
## Commands
|
||||
|
||||
These commands can be run from the command-line interface of the container.
|
||||
|
||||
| Command | Description |
|
||||
| :-- | -- |
|
||||
| create_stakepool | Take all the steps to initialize and register the stakepool from scratch. |
|
||||
| generate_stake_address | Generate payment and stake keys and addresses. |
|
||||
| generate_registration_certificates | Generates stakepool registration certificates. |
|
||||
| generate_operational_certificates | Generates stakepool cold-keys, and VRF and KES keys, and the node certificates. |
|
||||
| register_stake_address | Registers your stake address in the blockchain. |
|
||||
| register_stake_pool | Registers your stake pool in the blockchain. |
|
||||
| sync_status | Display node synchronization status. |
|
||||
|
||||
|
||||
## Supported Networks
|
||||
|
||||
Use the CARDANO_NETWORK environment variable to change this.
|
||||
The latest supported networks can be found at [https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/index.html](https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/index.html)
|
||||
|
||||
| Network | CARDANO_NETWORK value |
|
||||
| :-- | -- |
|
||||
| mainnet | main |
|
||||
| mainnet-candidate4 | mc4 |
|
||||
|
||||
|
||||
## Ports
|
||||
|
||||
| Port | Function |
|
||||
| :-- | -- |
|
||||
| 3000 | Default port cardano-node. |
|
||||
| 12798 | Default port for Prometheus monitoring. |
|
||||
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Function |
|
||||
| :-- | -- |
|
||||
| /config | Specify a folder to store the configuration and database of the nodes, for persistent data. |
|
||||
|
||||
|
||||
## Example scripts
|
||||
|
||||
Use these example scripts to see how the nodes can be started.
|
||||
|
||||
| Script | Description |
|
||||
| :-- | -- |
|
||||
| test/mc4-docker-compose.yaml | docker compose file for running relay node and block-producing node locally on mainnet-candidate4, and initialize and register the stakepool |
|
||||
| best-practice/mc4-relay1.sh | Run relay node locally on mainnet-candidate4. |
|
||||
| best-practice/mc4-producing.sh | Run block-producing node locally on mainnet-candidate4 and initialize and register the it as a stakepool. |
|
||||
| best-practice/mc4-cold-create.sh | Local cold creation on mainnet-candidate4. |
|
||||
| main-relay1.sh | Run relay node locally on mainnet. |
|
||||
| main-producing.sh | Run block-producing node on mainnet. |
|
||||
| main-registration.sh | Run block-producing node on mainnet and initialize and register the it as a stakepool. |
|
||||
|
||||
|
||||
## Docker hub
|
||||
Image can be found [here](https://hub.docker.com/repository/docker/arradev/cardano-node).
|
||||
|
||||
|
||||
## Building locally
|
||||
|
||||
If you want to make local modifications to these images for development purposes or just to customize the logic.
|
||||
|
||||
```
|
||||
git clone https://github.com/abracadaniel/cardano-node-docker.git
|
||||
cd cardano-node-docker
|
||||
./build.sh
|
||||
```
|
||||
|
||||
|
||||
## Thank you
|
||||
|
||||
I hope you will find this useful. If you like the work please consider delegating to my pool:
|
||||
`[ARRA1] Arrakis (c65ca06828caa8fc9b0bb015af93ef71685544c6ed2abbb7c59b0e62)`
|
||||
|
||||
or donating a few ADA to:
|
||||
`addr1qyfdc9rkw2njpevpene998w93uyghftspnv6muxkwt82tyyjn4up3dddmmul3a5p98996dyd5nhn2mwthwce6rjrp0espmglvg`
|
7
build.sh
Normal file
7
build.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION="1.25.1"
|
||||
docker build \
|
||||
--build-arg VERSION=${VERSION} \
|
||||
--tag arradev/cardano-node:${VERSION} \
|
||||
--tag arradev/cardano-node:latest .
|
1
cfg-templates/crontab
Normal file
1
cfg-templates/crontab
Normal file
@ -0,0 +1 @@
|
||||
30 * * * * /scripts/topology_submit
|
2
cfg-templates/main/VARS
Normal file
2
cfg-templates/main/VARS
Normal file
@ -0,0 +1,2 @@
|
||||
export NETWORK_ARGUMENT="--mainnet"
|
||||
export HARDFORK_EPOCH=208
|
14572
cfg-templates/main/byron-genesis.json
Normal file
14572
cfg-templates/main/byron-genesis.json
Normal file
File diff suppressed because it is too large
Load Diff
155
cfg-templates/main/config.json
Normal file
155
cfg-templates/main/config.json
Normal file
@ -0,0 +1,155 @@
|
||||
{
|
||||
"ApplicationName": "cardano-sl",
|
||||
"ApplicationVersion": 1,
|
||||
"ByronGenesisFile": "mainnet-byron-genesis.json",
|
||||
"ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb",
|
||||
"LastKnownBlockVersion-Alt": 0,
|
||||
"LastKnownBlockVersion-Major": 3,
|
||||
"LastKnownBlockVersion-Minor": 0,
|
||||
"MaxKnownMajorProtocolVersion": 2,
|
||||
"Protocol": "Cardano",
|
||||
"RequiresNetworkMagic": "RequiresNoMagic",
|
||||
"ShelleyGenesisFile": "mainnet-shelley-genesis.json",
|
||||
"ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81",
|
||||
"TraceBlockFetchClient": false,
|
||||
"TraceBlockFetchDecisions": false,
|
||||
"TraceBlockFetchProtocol": false,
|
||||
"TraceBlockFetchProtocolSerialised": false,
|
||||
"TraceBlockFetchServer": false,
|
||||
"TraceChainDb": true,
|
||||
"TraceChainSyncBlockServer": false,
|
||||
"TraceChainSyncClient": false,
|
||||
"TraceChainSyncHeaderServer": false,
|
||||
"TraceChainSyncProtocol": false,
|
||||
"TraceDNSResolver": true,
|
||||
"TraceDNSSubscription": true,
|
||||
"TraceErrorPolicy": true,
|
||||
"TraceForge": true,
|
||||
"TraceHandshake": false,
|
||||
"TraceIpSubscription": true,
|
||||
"TraceLocalChainSyncProtocol": false,
|
||||
"TraceLocalErrorPolicy": true,
|
||||
"TraceLocalHandshake": false,
|
||||
"TraceLocalTxSubmissionProtocol": false,
|
||||
"TraceLocalTxSubmissionServer": false,
|
||||
"TraceMempool": true,
|
||||
"TraceMux": false,
|
||||
"TraceTxInbound": false,
|
||||
"TraceTxOutbound": false,
|
||||
"TraceTxSubmissionProtocol": false,
|
||||
"TracingVerbosity": "NormalVerbosity",
|
||||
"TurnOnLogMetrics": true,
|
||||
"TurnOnLogging": true,
|
||||
"defaultBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"defaultScribes": [
|
||||
[
|
||||
"StdoutSK",
|
||||
"stdout"
|
||||
]
|
||||
],
|
||||
"hasEKG": 12788,
|
||||
"hasPrometheus": [
|
||||
"127.0.0.1",
|
||||
12798
|
||||
],
|
||||
"minSeverity": "Info",
|
||||
"options": {
|
||||
"mapBackends": {
|
||||
"cardano.node-metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.BlockFetchDecision.peers": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.ChainDB.metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.Forge.metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.resources": [
|
||||
"EKGViewBK"
|
||||
]
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"#ekgview": {
|
||||
"contents": [
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": ".monoclock.basic.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.cpuNs.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "#ekgview.#aggregation.cardano.epoch-validation.benchmark",
|
||||
"tag": "StartsWith"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.gcNum.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
"subtrace": "FilterTrace"
|
||||
},
|
||||
"benchmark": {
|
||||
"contents": [
|
||||
"GhcRtsStats",
|
||||
"MonotonicClock"
|
||||
],
|
||||
"subtrace": "ObservableTrace"
|
||||
},
|
||||
"cardano.epoch-validation.utxo-stats": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"cardano.node-metrics": {
|
||||
"subtrace": "Neutral"
|
||||
},
|
||||
"cardano.node.metrics": {
|
||||
"subtrace": "Neutral"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rotation": {
|
||||
"rpKeepFilesNum": 10,
|
||||
"rpLogLimitBytes": 5000000,
|
||||
"rpMaxAgeHours": 24
|
||||
},
|
||||
"setupBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScText",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
]
|
||||
}
|
121
cfg-templates/main/db-sync-config.json
Normal file
121
cfg-templates/main/db-sync-config.json
Normal file
@ -0,0 +1,121 @@
|
||||
{
|
||||
"ByronGenesisFile": "/nix/store/3678ccikas3q16jcqcghwviqsd5k9wjx-mainnet-byron-genesis.json",
|
||||
"ByronGenesisHash": "5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb",
|
||||
"EnableLogMetrics": false,
|
||||
"EnableLogging": true,
|
||||
"NetworkName": "mainnet",
|
||||
"Protocol": "Cardano",
|
||||
"RequiresNetworkMagic": "RequiresNoMagic",
|
||||
"ShelleyGenesisFile": "/nix/store/hxgam7f415s8b0j6c3qwakgkzd0pr5h4-mainnet-shelley-genesis.json",
|
||||
"ShelleyGenesisHash": "1a3be38bcbb7911969283716ad7aa550250226b76a61fc51cc9a9a35d9276d81",
|
||||
"defaultBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"defaultScribes": [
|
||||
[
|
||||
"StdoutSK",
|
||||
"stdout"
|
||||
]
|
||||
],
|
||||
"hasPrometheus": [
|
||||
"127.0.0.1",
|
||||
12698
|
||||
],
|
||||
"minSeverity": "Info",
|
||||
"options": {
|
||||
"cfokey": {
|
||||
"value": "Release-1.0.0"
|
||||
},
|
||||
"mapBackends": {},
|
||||
"mapSeverity": {
|
||||
"db-sync-node": "Info",
|
||||
"db-sync-node.Mux": "Error",
|
||||
"db-sync-node.Subscription": "Error"
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"#ekgview": {
|
||||
"contents": [
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": ".monoclock.basic.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.cpuNs.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "#ekgview.#aggregation.cardano.epoch-validation.benchmark",
|
||||
"tag": "StartsWith"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.gcNum.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
"subtrace": "FilterTrace"
|
||||
},
|
||||
"#messagecounters.aggregation": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.ekgview": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.katip": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.monitoring": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.switchboard": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"benchmark": {
|
||||
"contents": [
|
||||
"GhcRtsStats",
|
||||
"MonotonicClock"
|
||||
],
|
||||
"subtrace": "ObservableTrace"
|
||||
},
|
||||
"cardano.epoch-validation.utxo-stats": {
|
||||
"subtrace": "NoTrace"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rotation": {
|
||||
"rpKeepFilesNum": 10,
|
||||
"rpLogLimitBytes": 5000000,
|
||||
"rpMaxAgeHours": 24
|
||||
},
|
||||
"setupBackends": [
|
||||
"AggregationBK",
|
||||
"KatipBK"
|
||||
],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScText",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
]
|
||||
}
|
114
cfg-templates/main/rest-config.json
Normal file
114
cfg-templates/main/rest-config.json
Normal file
@ -0,0 +1,114 @@
|
||||
{
|
||||
"EnableLogMetrics": false,
|
||||
"EnableLogging": true,
|
||||
"defaultBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"defaultScribes": [
|
||||
[
|
||||
"StdoutSK",
|
||||
"stdout"
|
||||
]
|
||||
],
|
||||
"hasPrometheus": [
|
||||
"127.0.0.1",
|
||||
12698
|
||||
],
|
||||
"minSeverity": "Info",
|
||||
"options": {
|
||||
"cfokey": {
|
||||
"value": "Release-1.0.0"
|
||||
},
|
||||
"mapBackends": {},
|
||||
"mapSeverity": {
|
||||
"db-sync-node": "Info",
|
||||
"db-sync-node.Mux": "Error",
|
||||
"db-sync-node.Subscription": "Error"
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"#ekgview": {
|
||||
"contents": [
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": ".monoclock.basic.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.cpuNs.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "#ekgview.#aggregation.cardano.epoch-validation.benchmark",
|
||||
"tag": "StartsWith"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.gcNum.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
"subtrace": "FilterTrace"
|
||||
},
|
||||
"#messagecounters.aggregation": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.ekgview": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.katip": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.monitoring": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"#messagecounters.switchboard": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"benchmark": {
|
||||
"contents": [
|
||||
"GhcRtsStats",
|
||||
"MonotonicClock"
|
||||
],
|
||||
"subtrace": "ObservableTrace"
|
||||
},
|
||||
"cardano.epoch-validation.utxo-stats": {
|
||||
"subtrace": "NoTrace"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rotation": {
|
||||
"rpKeepFilesNum": 10,
|
||||
"rpLogLimitBytes": 5000000,
|
||||
"rpMaxAgeHours": 24
|
||||
},
|
||||
"setupBackends": [
|
||||
"AggregationBK",
|
||||
"KatipBK"
|
||||
],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScText",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
]
|
||||
}
|
68
cfg-templates/main/shelley-genesis.json
Normal file
68
cfg-templates/main/shelley-genesis.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"activeSlotsCoeff": 0.05,
|
||||
"protocolParams": {
|
||||
"protocolVersion": {
|
||||
"minor": 0,
|
||||
"major": 2
|
||||
},
|
||||
"decentralisationParam": 1,
|
||||
"eMax": 18,
|
||||
"extraEntropy": {
|
||||
"tag": "NeutralNonce"
|
||||
},
|
||||
"maxTxSize": 16384,
|
||||
"maxBlockBodySize": 65536,
|
||||
"maxBlockHeaderSize": 1100,
|
||||
"minFeeA": 44,
|
||||
"minFeeB": 155381,
|
||||
"minUTxOValue": 1000000,
|
||||
"poolDeposit": 500000000,
|
||||
"minPoolCost": 340000000,
|
||||
"keyDeposit": 2000000,
|
||||
"nOpt": 150,
|
||||
"rho": 0.003,
|
||||
"tau": 0.20,
|
||||
"a0": 0.3
|
||||
},
|
||||
"genDelegs": {
|
||||
"ad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950c": {
|
||||
"delegate": "d9e5c76ad5ee778960804094a389f0b546b5c2b140a62f8ec43ea54d",
|
||||
"vrf": "64fa87e8b29a5b7bfbd6795677e3e878c505bc4a3649485d366b50abadec92d7"
|
||||
},
|
||||
"b9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497": {
|
||||
"delegate": "855d6fc1e54274e331e34478eeac8d060b0b90c1f9e8a2b01167c048",
|
||||
"vrf": "66d5167a1f426bd1adcc8bbf4b88c280d38c148d135cb41e3f5a39f948ad7fcc"
|
||||
},
|
||||
"60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1": {
|
||||
"delegate": "7f72a1826ae3b279782ab2bc582d0d2958de65bd86b2c4f82d8ba956",
|
||||
"vrf": "c0546d9aa5740afd569d3c2d9c412595cd60822bb6d9a4e8ce6c43d12bd0f674"
|
||||
},
|
||||
"f7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757": {
|
||||
"delegate": "69ae12f9e45c0c9122356c8e624b1fbbed6c22a2e3b4358cf0cb5011",
|
||||
"vrf": "6394a632af51a32768a6f12dac3485d9c0712d0b54e3f389f355385762a478f2"
|
||||
},
|
||||
"162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82": {
|
||||
"delegate": "4485708022839a7b9b8b639a939c85ec0ed6999b5b6dc651b03c43f6",
|
||||
"vrf": "aba81e764b71006c515986bf7b37a72fbb5554f78e6775f08e384dbd572a4b32"
|
||||
},
|
||||
"2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6": {
|
||||
"delegate": "6535db26347283990a252313a7903a45e3526ec25ddba381c071b25b",
|
||||
"vrf": "fcaca997b8105bd860876348fc2c6e68b13607f9bbd23515cd2193b555d267af"
|
||||
},
|
||||
"268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819b": {
|
||||
"delegate": "1d4f2e1fda43070d71bb22a5522f86943c7c18aeb4fa47a362c27e23",
|
||||
"vrf": "63ef48bc5355f3e7973100c371d6a095251c80ceb40559f4750aa7014a6fb6db"
|
||||
}
|
||||
},
|
||||
"updateQuorum": 5,
|
||||
"networkId": "Mainnet",
|
||||
"initialFunds": {},
|
||||
"maxLovelaceSupply": 45000000000000000,
|
||||
"networkMagic": 764824073,
|
||||
"epochLength": 432000,
|
||||
"systemStart": "2017-09-23T21:44:51Z",
|
||||
"slotsPerKESPeriod": 129600,
|
||||
"slotLength": 1,
|
||||
"maxKESEvolutions": 62,
|
||||
"securityParam": 2160
|
||||
}
|
9
cfg-templates/main/topology-relay.json
Normal file
9
cfg-templates/main/topology-relay.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Producers": [
|
||||
{
|
||||
"addr": "relays-new.cardano-mainnet.iohk.io",
|
||||
"port": 3001,
|
||||
"valency": 2
|
||||
}
|
||||
]
|
||||
}
|
3
cfg-templates/main/topology.json
Normal file
3
cfg-templates/main/topology.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Producers": []
|
||||
}
|
2
cfg-templates/mc4/VARS
Normal file
2
cfg-templates/mc4/VARS
Normal file
@ -0,0 +1,2 @@
|
||||
export NETWORK_ARGUMENT="--testnet-magic 42"
|
||||
export HARDFORK_EPOCH=1
|
63
cfg-templates/mc4/byron-genesis.json
Normal file
63
cfg-templates/mc4/byron-genesis.json
Normal file
@ -0,0 +1,63 @@
|
||||
{ "bootStakeholders":
|
||||
{ "473cfa74426964f50d93973de6b0f2e40f3320fe9e670ed1e891de10": 1
|
||||
, "c1b2ae2a90a808788615fa96a01ced3a6e67e669348efded4eaed473": 1
|
||||
, "da379ef48add30b195d9b8bdafc2fdf5998753a7959ad26320bf2ebe": 1
|
||||
}
|
||||
, "heavyDelegation":
|
||||
{ "473cfa74426964f50d93973de6b0f2e40f3320fe9e670ed1e891de10":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"5jlrrnjBpWzFOE84xc6uh8Ke1Be/NEcIYW3f0n1C8zGDSCZwNd1xm40Zu7Ri+6hcCScaa93KA39gNFn0mtZOSw=="
|
||||
, "delegatePk":
|
||||
"gPSUJ9TxeDi3mn8pWrztZvChWsDIqkuuwVxfU6cm2CwP8vFNgfBo7mMFJwxdsG08xraJ4qXbIWynAmTfeHL0Tg=="
|
||||
, "cert":
|
||||
"5544f210551803bfbcffbeeb807503d2cfa3909131248c12594a0feaf13b939d2e9eb81d8e8e667a688659d7714cbf3b16841b264b393de32b6f3d0f2a041307"
|
||||
}
|
||||
, "c1b2ae2a90a808788615fa96a01ced3a6e67e669348efded4eaed473":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"RYaRZCsjTNYMojPGW1hAGZcYaWY84stEXQd95FqVyLxU0iDoEHP1Oh9+5xxyPEGZ9z5jxCva0WpE+4AVtyQy4Q=="
|
||||
, "delegatePk":
|
||||
"CswJCLqUCrDQa5pb4NX8uQlv8uy7ZxbjnD5cSAIvgf4G9Ql0ZaA7wnS4yjJysi5uZyV2qnwwt3koP6djhvwuJQ=="
|
||||
, "cert":
|
||||
"25cade766847eabc070cf8dee62bfbf315676a7805fb2d5058c981edab1150f2e24ad9f8a64a1f178076955506e1920d10564637852561ba821c231aa0478d03"
|
||||
}
|
||||
, "da379ef48add30b195d9b8bdafc2fdf5998753a7959ad26320bf2ebe":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"g4lK99OuTyyRDTCK4772Z56CM+KsLX5PIDkd5wBRhEHvbFBiPVno3o+5HZ07wZrKRDCdYH4NINuJ8WR7oSRsIQ=="
|
||||
, "delegatePk":
|
||||
"+lqfLp1qM/vGMJvmeRgpl82ECWFzvKR5JulHnjrkfhg0Cn2LK/4c+IQrtp/zu4dzHOaCHj+zqmunrdomMlgNug=="
|
||||
, "cert":
|
||||
"cc6d1fd828841c47adbb9968f7cfd86770380001762b354a09fc84a6d17d05c116e8723f90b70469a5231a7f35851b79b2ed9f1526ade3f1f5c65ae9def56a09"
|
||||
}
|
||||
}
|
||||
, "startTime": 1595682000
|
||||
, "nonAvvmBalances":
|
||||
{ "Ae2tdPwUPEYyv5UFN9PSgqfquhfkpxsv6M8h7K223pSL4JAnxGCGSGJq6wU":
|
||||
"33000000000000000"
|
||||
}
|
||||
, "blockVersionData":
|
||||
{ "scriptVersion": 0
|
||||
, "slotDuration": "20000"
|
||||
, "maxBlockSize": "2000000"
|
||||
, "maxHeaderSize": "2000000"
|
||||
, "maxTxSize": "4096"
|
||||
, "maxProposalSize": "700"
|
||||
, "mpcThd": "20000000000000"
|
||||
, "heavyDelThd": "300000000000"
|
||||
, "updateVoteThd": "1000000000000"
|
||||
, "updateProposalThd": "100000000000000"
|
||||
, "updateImplicit": "10000"
|
||||
, "softforkRule":
|
||||
{ "initThd": "900000000000000"
|
||||
, "minThd": "600000000000000"
|
||||
, "thdDecrement": "50000000000000"
|
||||
}
|
||||
, "txFeePolicy":
|
||||
{ "summand": "155381000000000" , "multiplier": "43946000000" }
|
||||
, "unlockStakeEpoch": "18446744073709551615"
|
||||
}
|
||||
, "protocolConsts": { "k": 108 , "protocolMagic": 42 }
|
||||
, "avvmDistr": {}
|
||||
}
|
171
cfg-templates/mc4/config.json
Normal file
171
cfg-templates/mc4/config.json
Normal file
@ -0,0 +1,171 @@
|
||||
{
|
||||
"ApplicationName": "cardano-sl",
|
||||
"ApplicationVersion": 0,
|
||||
"ByronGenesisFile": "mainnet_candidate_4-byron-genesis.json",
|
||||
"ByronGenesisHash": "406bd7edfa14db46edb367d18f5b3dba8d0c626b7c1c19f283867a70d05945c9",
|
||||
"LastKnownBlockVersion-Alt": 0,
|
||||
"LastKnownBlockVersion-Major": 2,
|
||||
"LastKnownBlockVersion-Minor": 0,
|
||||
"MaxKnownMajorProtocolVersion": 2,
|
||||
"PBftSignatureThreshold": 0.9,
|
||||
"Protocol": "Cardano",
|
||||
"RequiresNetworkMagic": "RequiresNoMagic",
|
||||
"ShelleyGenesisFile": "mainnet_candidate_4-shelley-genesis.json",
|
||||
"ShelleyGenesisHash": "ef8a74ab8587db4c95a7b98cd15406faf7044d9ff47b977f54053f7ad4fd9e59",
|
||||
"TestShelleyHardForkAtEpoch": 1,
|
||||
"TraceBlockFetchClient": false,
|
||||
"TraceBlockFetchDecisions": false,
|
||||
"TraceBlockFetchProtocol": false,
|
||||
"TraceBlockFetchProtocolSerialised": false,
|
||||
"TraceBlockFetchServer": false,
|
||||
"TraceChainDb": true,
|
||||
"TraceChainSyncBlockServer": false,
|
||||
"TraceChainSyncClient": false,
|
||||
"TraceChainSyncHeaderServer": false,
|
||||
"TraceChainSyncProtocol": false,
|
||||
"TraceDNSResolver": true,
|
||||
"TraceDNSSubscription": true,
|
||||
"TraceErrorPolicy": true,
|
||||
"TraceForge": true,
|
||||
"TraceHandshake": false,
|
||||
"TraceIpSubscription": true,
|
||||
"TraceLocalChainSyncProtocol": false,
|
||||
"TraceLocalErrorPolicy": true,
|
||||
"TraceLocalHandshake": false,
|
||||
"TraceLocalTxSubmissionProtocol": false,
|
||||
"TraceLocalTxSubmissionServer": false,
|
||||
"TraceMempool": true,
|
||||
"TraceMux": false,
|
||||
"TraceTxInbound": false,
|
||||
"TraceTxOutbound": false,
|
||||
"TraceTxSubmissionProtocol": false,
|
||||
"TracingVerbosity": "NormalVerbosity",
|
||||
"TurnOnLogMetrics": true,
|
||||
"TurnOnLogging": true,
|
||||
"ViewMode": "SimpleView",
|
||||
"defaultBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"defaultScribes": [
|
||||
[
|
||||
"StdoutSK",
|
||||
"stdout"
|
||||
]
|
||||
],
|
||||
"hasEKG": 12788,
|
||||
"hasPrometheus": [
|
||||
"127.0.0.1",
|
||||
12798
|
||||
],
|
||||
"minSeverity": "Info",
|
||||
"options": {
|
||||
"mapBackends": {
|
||||
"cardano.node-metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.BlockFetchDecision.peers": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.ChainDB.metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.Forge.metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"#ekgview": {
|
||||
"contents": [
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": ".monoclock.basic.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.cpuNs.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "#ekgview.#aggregation.cardano.epoch-validation.benchmark",
|
||||
"tag": "StartsWith"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.gcNum.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
"subtrace": "FilterTrace"
|
||||
},
|
||||
"benchmark": {
|
||||
"contents": [
|
||||
"GhcRtsStats",
|
||||
"MonotonicClock"
|
||||
],
|
||||
"subtrace": "ObservableTrace"
|
||||
},
|
||||
"cardano.epoch-validation.utxo-stats": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"cardano.node-metrics": {
|
||||
"subtrace": "Neutral"
|
||||
},
|
||||
"cardano.node.metrics": {
|
||||
"subtrace": "Neutral"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rotation": {
|
||||
"rpKeepFilesNum": 10,
|
||||
"rpLogLimitBytes": 5000000,
|
||||
"rpMaxAgeHours": 24
|
||||
},
|
||||
"setupBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScText",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
]
|
||||
}
|
52
cfg-templates/mc4/shelley-genesis.json
Normal file
52
cfg-templates/mc4/shelley-genesis.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"activeSlotsCoeff": 0.05,
|
||||
"protocolParams": {
|
||||
"protocolVersion": {
|
||||
"minor": 0,
|
||||
"major": 2
|
||||
},
|
||||
"decentralisationParam": 1,
|
||||
"eMax": 18,
|
||||
"extraEntropy": {
|
||||
"tag": "NeutralNonce"
|
||||
},
|
||||
"maxTxSize": 16384,
|
||||
"maxBlockBodySize": 65536,
|
||||
"maxBlockHeaderSize": 1100,
|
||||
"minFeeA": 44,
|
||||
"minFeeB": 155381,
|
||||
"minUTxOValue": 1000000,
|
||||
"poolDeposit": 500000000,
|
||||
"minPoolCost": 340000000,
|
||||
"keyDeposit": 2000000,
|
||||
"nOpt": 150,
|
||||
"rho": 0.003,
|
||||
"tau": 0.20,
|
||||
"a0": 0.3
|
||||
},
|
||||
"genDelegs": {
|
||||
"42d339844d4593edc456d1c80b256fa57e9b4b4dccda5b587ea7a958": {
|
||||
"delegate": "53465dff1bf47517a5b354888b32972647d208cac07907aa8efa5a03",
|
||||
"vrf": "61e67274fe923060e82635768ec21e62846023804cc0f080c5c2b475151c2770"
|
||||
},
|
||||
"95dbfe2cf93a2db109863659c10dd5785201d71eb43ae4a264d2b731": {
|
||||
"delegate": "2ca5c291c7f00776e8c6a2482198bb03ff90abd638dc650936739b8d",
|
||||
"vrf": "7b6a8ba747c498db386227fe0747dba44197816d82bc662e92c32a00f0e4906e"
|
||||
},
|
||||
"28466494f218d24d9627c4ffcf55671f894f775ee782bfd61ca3a4e8": {
|
||||
"delegate": "bd4a372503f35313c4f17e3cdc012f460119af1841c509c763218fc8",
|
||||
"vrf": "4c6d14ca2697dd446d4963c99dcb2a02419052beaad3c9aa7e37c261c8138c94"
|
||||
}
|
||||
},
|
||||
"updateQuorum": 3,
|
||||
"networkId": "Mainnet",
|
||||
"initialFunds": {},
|
||||
"maxLovelaceSupply": 45000000000000000,
|
||||
"networkMagic": 42,
|
||||
"epochLength": 21600,
|
||||
"systemStart": "2020-07-25T13:00:00Z",
|
||||
"slotsPerKESPeriod": 7200,
|
||||
"slotLength": 1,
|
||||
"maxKESEvolutions": 62,
|
||||
"securityParam": 108
|
||||
}
|
9
cfg-templates/mc4/topology-relay.json
Normal file
9
cfg-templates/mc4/topology-relay.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Producers": [
|
||||
{
|
||||
"addr": "relays-new.mainnet-candidate-4.dev.cardano.org",
|
||||
"port": 3001,
|
||||
"valency": 2
|
||||
}
|
||||
]
|
||||
}
|
3
cfg-templates/mc4/topology.json
Normal file
3
cfg-templates/mc4/topology.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Producers": []
|
||||
}
|
2
cfg-templates/test/VARS
Normal file
2
cfg-templates/test/VARS
Normal file
@ -0,0 +1,2 @@
|
||||
export NETWORK_ARGUMENT="--testnet-magic 1097911063"
|
||||
export HARDFORK_EPOCH=1
|
481
cfg-templates/test/byron-genesis.json
Normal file
481
cfg-templates/test/byron-genesis.json
Normal file
@ -0,0 +1,481 @@
|
||||
{ "bootStakeholders":
|
||||
{ "182822494f30b89a5cb9a6d845d9733a1831eb4e5ebc8faca89becc4": 1
|
||||
, "37ec19ad6c732dea93f8b39e0dcbef7d45044983d99195eb7034901c": 1
|
||||
, "3c1c3b43032f1f7a346cb8070c75474715ec8f1d301411a69def9ab2": 1
|
||||
, "6275f793595cae0761f13ecd054a0f01d0f57726ade0933e88a05749": 1
|
||||
, "9a804607ce670b2d5e60e9b4fdc54b99acf6d66837132e6bdc621ba5": 1
|
||||
, "9bfb38ba283fb3c8e552b440c17d0ef32725c39219565e9190454a57": 1
|
||||
, "e471e138c71dfff3d326b75548a1c518e694d13e85a3b0ae91df9941": 1
|
||||
}
|
||||
, "heavyDelegation":
|
||||
{ "9bfb38ba283fb3c8e552b440c17d0ef32725c39219565e9190454a57":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"y1HSmrlOUNmhRNT0JlZM7HAN7k2ehXqs+R07aJN02B90KkUoGM8kicFt/Bhvbpx2t99AhFt8RQeF8C2ICXZ1dQ=="
|
||||
, "delegatePk":
|
||||
"fsJJ2JDQqvmoEgeWDBY64tasXnFcprltWGDlDZ8rKyodVo+qh8nMi/1DOjIkqW7F0QG0tunbAI24hX9JuuKUsg=="
|
||||
, "cert":
|
||||
"a304bf45b44fbccc78f54b9014a6b2d4354631ebff235aebb2e71a15bdd582be3794384c1ba713b99ef05766e92b8f438b2fc5af349f2bb16e85e3780aa84c07"
|
||||
}
|
||||
, "37ec19ad6c732dea93f8b39e0dcbef7d45044983d99195eb7034901c":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"nw+fw9f3biUiBZVS6H4G2vlAtFgaF5rsd/OQVmKkGGWv2lr820QVemFc7G/xmtOZ2bAyjcgrx/NRPUCRC3+TSg=="
|
||||
, "delegatePk":
|
||||
"MqlUtSHAsZUUQIllgx72g5Y33noaYWi8+EVcUEupO5yFNJi9rgYKb8mUXXIxrgjRMXq7szMGyTRl5e8RjuvHGA=="
|
||||
, "cert":
|
||||
"3fbff2edf71960355b30d89b946d4732c88e66dfb859bb143d2cd368b923cdf7d9bd22c4901cb47bade479a7c0eda08470cc9f3a2cb20c92b3a20974fc066900"
|
||||
}
|
||||
, "9a804607ce670b2d5e60e9b4fdc54b99acf6d66837132e6bdc621ba5":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"KedfHXp2SA8aETBEmrXZoOAUwJiFDKFSA3gq3rdWGoG7Mid0F0kSWzK3C6Y8QDIvRnao1lfZpXmghht8L0wCcg=="
|
||||
, "delegatePk":
|
||||
"52SwNA17NT9fdFiRAzd05L6raqFFilT/KaEyTAW7mHa1dM9ZKg+G/dH7+vvt3p4izpUiWy8RhRYpOszYygswFg=="
|
||||
, "cert":
|
||||
"06682af4df67b2037337187f9397bb8042e37308da1429ec9063e42480f9da60379d929f705140f05f1d014f19c668071824c0d86b616794e544d935e379c80e"
|
||||
}
|
||||
, "182822494f30b89a5cb9a6d845d9733a1831eb4e5ebc8faca89becc4":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"U6JXlR27xStIbWOjpfzqVVy5rp73La1i5znqNsI94+xYpOzGmlOVYiYF88N5OZ82wDBtl1UB9A+bWXNa0oCapg=="
|
||||
, "delegatePk":
|
||||
"5bwhqDYWvMz+ND7Da53EwGyQ6RPfHYoLBGAIZR9CyqlKrob7/cRYbavVR6fpLQdwLjMrzJ5911MjncgNAzxZwg=="
|
||||
, "cert":
|
||||
"d173106bfaab665a30e71633719754e0416927cfdadd6fbf7013590ddc9843083e18efcd08e4c7c366f4c4fff257177c87a502913f35bb1a07e45607c5d1fa0a"
|
||||
}
|
||||
, "e471e138c71dfff3d326b75548a1c518e694d13e85a3b0ae91df9941":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"HISQWQHTy1IdXEM7sTpZDNIQO0alFI++YFE6sAD5lN1BNDzTDSzDfUeaoAVWBvT/L5LcHdRzsjRgnPcOOm28gg=="
|
||||
, "delegatePk":
|
||||
"T011I+QeBYpsve+1U4ZU/8KlNBan9buZ9+rGmdQtXB8TdXbpwo6fFLPG4IIS8jjYbW4BrPJpf3teR9qWOSZeMQ=="
|
||||
, "cert":
|
||||
"018a7ee167602da08bf7d6903c37d2524ebe2a5daad83f9bf25f6011622932e72fc7c48027b9d4efaef521c911ec9eebaa38ddf88e6ae27c9bb823770fcd2600"
|
||||
}
|
||||
, "3c1c3b43032f1f7a346cb8070c75474715ec8f1d301411a69def9ab2":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"276WEVFXba36w7tXnsKxwUfACqTO4Dx+vvSVoOo4KUCqBgPahpnaCca9yjIPzWhVC6iyrHkZ570z7VjF2drNRA=="
|
||||
, "delegatePk":
|
||||
"c65B7KK+N/wVxVpQ1mjIZH4QvyIhcsLVir+m6TEOWWI/jyb47cHOj2mL1dyf6qMay8Nkv/b7gdND/zgm692NVQ=="
|
||||
, "cert":
|
||||
"b2c8e6ff8fc380c4a4c4e16f909803e786ccfbf4267e5016e24a34a843093b4d81736939500fb6fdd358d2be2b255858ea1abc35f62d381d6c62d111d1f0c80d"
|
||||
}
|
||||
, "6275f793595cae0761f13ecd054a0f01d0f57726ade0933e88a05749":
|
||||
{ "omega": 0
|
||||
, "issuerPk":
|
||||
"bO9W1q+IRfMXlJvN/5I1jxOU/hG0XAKyjh1YVMD6E/jgeWRN/FBBr7D8vR9H7HzgZPN7fsXAcMeEpWGeuuKqYA=="
|
||||
, "delegatePk":
|
||||
"37YVphVo1oZ/RahcMiJ/JwJRgNc4qKPX/TySn2JNcjkpgBs0NkHxSAh7EX6H6WlfIV28+DD/DVigZmgsdgP2QQ=="
|
||||
, "cert":
|
||||
"a9c6e4abf95755084a86625a98e185de75d4d33d557284d3aa67ecff3dcfd8e77994fc8b3fc4c2762879ca0c15458ade936db0977ae10dd01291cf3241b9530e"
|
||||
}
|
||||
}
|
||||
, "startTime": 1563999616
|
||||
, "vssCerts":
|
||||
{ "60214fff2df8faabc7da2dc99c07d2e3ade761b6bfe6a5a94b44c3dc":
|
||||
{ "vssKey": "WCECGkF8Ipu3QuaaTiSnA/wmf//wmVhFM2rIVUupnP9fdGM="
|
||||
, "expiryEpoch": 3
|
||||
, "signature":
|
||||
"ff0972de56a180ae5a452680f7c6c464d07cd539804930b1d2f815b9a9bcc652c8d7adf875e4435ee116b16d194e35acfc752cc14c2e9c46bd00f74ec363a502"
|
||||
, "signingKey":
|
||||
"fsJJ2JDQqvmoEgeWDBY64tasXnFcprltWGDlDZ8rKyodVo+qh8nMi/1DOjIkqW7F0QG0tunbAI24hX9JuuKUsg=="
|
||||
}
|
||||
, "e0c9e75ffe8065e50563f9ec256c2b442a121d602c495cd305fb3cc4":
|
||||
{ "vssKey": "WCEDBRKTUNRUx1VFORWuoqqMSwPYKXgkeO2e+LTbc8jxm7U="
|
||||
, "expiryEpoch": 4
|
||||
, "signature":
|
||||
"4d0aa42d1a15decec74c117b9b3e76178155c58ec373d2535005b4a3b0fae0ca4dd1c089b5272036f642aea27dc835e91de73d12fc25c027a8ef73991c139407"
|
||||
, "signingKey":
|
||||
"5bwhqDYWvMz+ND7Da53EwGyQ6RPfHYoLBGAIZR9CyqlKrob7/cRYbavVR6fpLQdwLjMrzJ5911MjncgNAzxZwg=="
|
||||
}
|
||||
, "fe299fde9afe6467393772f49e1f8d646d6788400c0acffdfb5eea24":
|
||||
{ "vssKey": "WCEDT9Z69y24Jbc4x/MlaC33mB/yaZ4ljIMNAfl9l7njWFE="
|
||||
, "expiryEpoch": 1
|
||||
, "signature":
|
||||
"0efc47d2ed049a72896a4db314a3b00b31b849c753eaa2e3172337a8439a9160eba6bc164f57819df6580140fe3c7f52cec98161596c452d7ced3b0881638a09"
|
||||
, "signingKey":
|
||||
"MqlUtSHAsZUUQIllgx72g5Y33noaYWi8+EVcUEupO5yFNJi9rgYKb8mUXXIxrgjRMXq7szMGyTRl5e8RjuvHGA=="
|
||||
}
|
||||
, "837bd45aa9cdb656f538a4e46236ba9eb4c89890bc9191df096e30ba":
|
||||
{ "vssKey": "WCEDKi5sm8Wu7tUrjSehtCBsEMXSpX+h87zNRJcE4Mx/Nj4="
|
||||
, "expiryEpoch": 1
|
||||
, "signature":
|
||||
"991e11c37f235c8c8d4aa846a564da38027f739f34ab97087ab436cce84d9297b2951455d5a8e2a562ab11db6a321c36d7498de3a1f776ad8eeb4dc5293b2b0f"
|
||||
, "signingKey":
|
||||
"52SwNA17NT9fdFiRAzd05L6raqFFilT/KaEyTAW7mHa1dM9ZKg+G/dH7+vvt3p4izpUiWy8RhRYpOszYygswFg=="
|
||||
}
|
||||
, "304889400de0859e03daea8bcf42779a14540b7c067f42f04ee1284e":
|
||||
{ "vssKey": "WCEDOgMx00aA40zA9oi0rN61TB6OxUcTvYq+8CyJjrObO3s="
|
||||
, "expiryEpoch": 5
|
||||
, "signature":
|
||||
"10eca6d26d44eb52ed11ae633c410866bd6e01411ad64068331c7b8f92da9c8b9a7bed1772b6bf00910d322e659e23f2f867c4cf4e757cdbfbfb1fc97ba5a004"
|
||||
, "signingKey":
|
||||
"c65B7KK+N/wVxVpQ1mjIZH4QvyIhcsLVir+m6TEOWWI/jyb47cHOj2mL1dyf6qMay8Nkv/b7gdND/zgm692NVQ=="
|
||||
}
|
||||
, "73c89ad521f5786011201377e1ec8305e82aa985998f40307fa927d1":
|
||||
{ "vssKey": "WCEDLPG8x46r/wCR3hoHLeS+h/1Bu5x0MWXHDoJhM++fEfw="
|
||||
, "expiryEpoch": 2
|
||||
, "signature":
|
||||
"98b48773afad287dbcd25915ee6b297b09d1204feb3a5793e91e438a1cce31a226f28b0c5b5ccdcde6a11f64665cbd867213cadbc57ec722c242def811f6e806"
|
||||
, "signingKey":
|
||||
"37YVphVo1oZ/RahcMiJ/JwJRgNc4qKPX/TySn2JNcjkpgBs0NkHxSAh7EX6H6WlfIV28+DD/DVigZmgsdgP2QQ=="
|
||||
}
|
||||
, "06216081b85063b2c7e33172b87663511fb7be35b23bc383881d60bc":
|
||||
{ "vssKey": "WCEDExIpntsz081SiKqeAg2o9W+wLy6lmD0dfp1sesQMj/E="
|
||||
, "expiryEpoch": 5
|
||||
, "signature":
|
||||
"2b7fb3aab3a23d72cac699c4ef97d7f90ca4dd0b06c2413962b6430583b9814b6549806e90ecfd44da05819b655ff975797a6df23dde2aa1c625ab5079825f03"
|
||||
, "signingKey":
|
||||
"T011I+QeBYpsve+1U4ZU/8KlNBan9buZ9+rGmdQtXB8TdXbpwo6fFLPG4IIS8jjYbW4BrPJpf3teR9qWOSZeMQ=="
|
||||
}
|
||||
}
|
||||
, "nonAvvmBalances":
|
||||
{ "2cWKMJemoBajGgvgVVziaKmUFa4LwJnAHffmuaSJBMDqethwJVQsyBsTSfFhp5jFpkVQM":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KEg6anTcJ9E4EAvYtNV9xXL6LNpA15YLhgvm9zJ1D2jwme574HikZ36rKdTwaUmpEicCoL1bDw4CtH5PNcFnTRGQNaFd5ai6Wvo6CZsi":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCRtni6YrG77RLPosnDqtEYoAD5xLdKYkWgnLqGa8yuXDUQd3psHrfxqaRcvNTsAW4ngUe6bzstbzSUJtwoaKbYaL8zjFAJJsZkQ42ti":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGDMix4Uj5opvbMDgjZYUjeARAqTEFEbgLUH3qyju9gkBpcm2fVWgkcNgK3xFsQgWm1w8zxqvm9P6xJj9mHqLeMJPwDMUKUGPcDyUaDS":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEkSeCVx985rXc38DCud2AW4LdasNmyoPLbtDGcDCyYVdf8BzxvDnzPehv4kyVBkzThjVEkSpGTv8PGQs4yRUgiCaKa7PTtBY4ohNGqR":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFGS7upvgJHtmp7y7EFB67utzaHf7PM8y8U4tNkpmARNwiD7seN4NSAceHmj64KLGgh9qn1BpYF49NyWxocBHn1N533qBUYfhQar9ceu":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCfir7GrvC6Y5kBNjeakZNd5po62AzQQ85SGkBB4QfXibC4fSNK5YvNeVgmPc8WbEeSUHRjoiqhJ4HDtinK2deBHSdCH6Cw8k2u92rdh":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGAExHTQjLUHJBksSXGTomjgNsw8a4KepCgQYk4gxacKb84vGpPSv9Pjt3gdgMjA1nB67Pq3XyJpTDk8kLcXpJawCe6SCJf5jUowvAz8":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCE1qeEoUh9b8CpcZcJ794Di14AxAELGoppJNVdB79nnuKcgRut566MdDkxTqravFaDSD9iwAvDByUHi59xocCY3ButEjmCQeLTLZXQ7":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGGSGD8KgQD6qUBaSjxy5JRtsmMSHEGGAZqA29ULGwci8TcM16vBhywuBw54izQtpAqXeyUnbjh56hCgoqGZp9tHTMLLkEgLzwxVCZ4N":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KG5ZZfwwiQuhAGWiNJ2FhXP3oAuiq75qknCz4CZWNMVY4B9BmiHRHnWfhUbkLHUqfabCYASUk2V1qGuDw97x1gdf871aFY7Lpz3N1NvT":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFtDHT2vDtMvQbLBgfH5hnpyVTTqqpPsieykukuxrDShHNccAEEj7M87UuV2GJ5pPA7YJ4JPjSokA99XaDgLmeaAumhZPHMwzg2Laspr":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDHFyvvKb29RD53ebt6N8kpbL41J4VxWpiFC4FnxxybP33M9tBbdqfMXvSvyTQpv4dULXf5B838kEWXSJ24bpHtFgcbRkiHQwqWFQ5du":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFh7jhHCtWxW942ceq7Xhxay8FZ7GkEBezGyFm3wJcVBGy1YYJDZ4Z7GbrFZmHLSe47zFs8Rjxk8rveoRpo1s43HXrMrhd4ijim4jJVP":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFhYgC9Lr4Se7C1gL39d5WBVADyUyQZz2BfG4BZxczyW827JRQR5enyWaoj6NnA5NyKsheV6Eb7WvQtbN8D6116HTknHhEb5jh1yUU6Z":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDLtM8HUJsBwergjZUj4DcMfkFmbV4bXUFGJk815o9nowX9ndPPVAeSNjAFYqJeFwTiMa9Ka8LqBnqFZgPpacyx9LrQLoXVMjvvLB7DK":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDec7E64byKc4XjmmCRDaTGQYgHJTPDijZVr7NwZSP8g7ienzTLx5Z1quaQRhJqqAyV8Z2QdkzXvjTTRiVDCqps78uGp3uuth4wEJKP9":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KF5R1LEsaQgjWFWXwbgJ51naDEaCRG23KiAN3UtGzaT5PvUANtFBgjmcCtPLMBYMTGL4S8px4HyQMLAyF4fakYoFAJC3PkxCWMUatGWD":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFB5Tmw1wsLmuv17Q6y8i6HGpVxbW8k4bevmob3DcdbH6jzrAtUrBpKgfTGgPMpLAbJcpaByGGJErkXQWFwrNMW35S79hxFvAN2GTXVQ":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDEX2XToMQoi1No3YdREgZWzrf1xQPbfhbZTZnprFwDsRMiBxqUrA7p4BwjxXHDyqAccPwyX8iWWquz2CrLazJMR4s8AMz2US1D1ffJL":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFTKCoqtZBdbh7LtJ9mRR1nbkX7ggP6a7AwvkSDxUN6U5GJWfuRXnL3a5x5e16uQwyjC6PoPVQ7VLdJXr8Kd3eFknLu6NDf2ey4AaJo2":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCHCpiGd1J2GtVjP4KxEWP7RE6K6yxHzE97cbDgFD63fUFygbni8jKw1N37nGsT43KBvBn5w9ee8sVegr6Tg8fAr52mUkhdvTZYJV52T":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGLRpX3uQfSeLovpMTcWfVZSM5RCufYvy2tyCMwrLXyHKCM9VqQh8dCQA6WcTrViaxqpvBSeKreHFL4CftfJU1z7CjHAze236NLesbL8":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEdwV1MS3Pjek1HjLN2CSq3SJZGFBbZctkGLz569i9RWN15bAvCcZ8R5dgEi8iYjpmMVKioufoGv3issZQvVtzPz38pWHBViyRK2how5":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KD1x4cqHfGxrvBubZ8pSM8Jmw15UiHpy77eMsqpMewGND2GdvAwTBZhf4KA4uypBJnuUPbPYFovpRVJ92BUaMBHfQnAD3i15DAzD8EvL":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBait15xg1M73WAvWafoieg2GrcykbRk6J1QC2jMUXn7LpXf4mk5RUeu8qYeG":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KC3HyNR82Bj2Sr9o6CF9o3J5hBNycGb9JwrHggTYUHfivi87akkYDv8ayepMkM4mNvxTKvoVdMHFkMnZZgrk5qobwPKM8idSnYYmvTRU":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCmCLYttFEWLNQc1MRbV1NyhhssRioZ5CgkqHgYUTT1pPSr2hrfevSe8bSwLiPsLnaCbsxJQc5SWgWYEJDPWuUA1s4AotQxERNbT9ReA":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBahLnFCQ8wrTuZ3sMyiCeEkUZDYLNucPiVTJr8UU3BgADsKtqosDYNFXzeiw":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KDHDPBVenqrh8tUTVNYX5ZGwjd4r3svqdnwWicGnMZZV1E7nBJVQsDY69co936H9onHpmA3PYSabYH4ibbULphL1CitDgArH9KknBARc":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KD9Z53z9qD7gTWMHr22e8jDcpCHgJFQaGQsvnNkycRehAaxLAnufNRjhLzQ57XVGJnR6mcsk6MorapLpADT77tyTaX9xfUSZyTA32ZAy":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCsozLcUUHR8GyVG7erY6j9zehKTADn3e5xpRJtu1YgfJzSmAyERBHUXa5LGWY2aR2KqcssnRjwugh1bGjxc6U6ZrePJnALYTw2TR3yh":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEDBSAmNtUBy6pfXesvTvtrDZQsSYcyo7SUwjLkhoSaPDCsNqMmoGbqzFQyEe9DNwK59BMudtdkzFPBpbgiEWx5SZr6vVMbpe86qsQJV":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFf5NQ1DuNoAP4phRomqdEUmtFb6sWcDHkizGj56dwn54LfKrfWa6Er5sxDXYrzpWwS56PKmKaBjJtn1JqN67K3CihFXXospn8B2TDz2":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBPHxFJqCekpPztGnLgbVsUA46Q8Lj2LKbFJL5Nqk5LgP2u28eBJAxkkU2r118ARdXW7fXLPQgctwK22L4N3zc6XeoDqkadGmTd4s8a1":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBYe4RSCngNCgVMAeMJkRQqoJs8t6t9e9BHcNvvT6awv4CruMWH2FyiudxcGfZHmjghDvqk39iFrmCt4XE2XDuYzyo97BxwS6MngfeWp":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KF3MxxJBeJqCPFgHyUsSDkrDqoctSSVi9h7F4Wj9zFKcPVuVju76KYhdp7nJhy44512Wjhw7WH4sed3MMSh1HYnKUfjZXGkoZXMajaye":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDsi9fc3RfExWLumjkp2YrcMjZpew19Z92kZnjPy5Xa84KY2WZw6xmjJA7AXFJCBWtrF9RFw1BjCewEqK77CVYj2s7bk9aAA7yyZARRz":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBaj34AMeqLspGBgX1PVc7z6VkALK3rtVd8iFgCtMUenNoHhVRnjeGfYVQJM1":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KDpppzxzoaPgnstPejNxGaSZ3Vh22Qd2DWGrwfLJ2tizs33Y5Yjya1U6TXPzVX2PT5g1PXMy4jR4aWZRGZqYJk4Uw9p1h6BhEa189eiN":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEXaPVoMuKpnVEKKLMFuGSvYL7YMAD529yxeK8Y1zqnbh5FQ8GMYpJwARugWmzaXdJ1gopgsxziC4e5wgjf3zkp7RH41KTJ73xLyfrFP":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBrhG1yaBVY3X1ZoTCjUH7gbiA4qSFsMGgtLUBgwHiMZPiAJ3kQrRiboPV3s7eYXZD9fnd27qRb1cCEMc4oU57aPn2cYcEdAEJHrsyLB":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEC4vC63KNqRBD7RX1KBwWDdPDE6oXGxP8x5aKrbVTALaq4XBdak8F47Kt9VcsQvVsKZfAit8vBtZpG2mc6VKUXCFv8pTYWwQMnABckB":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFPbetkmdvqD8nLRFsUVL4HsVUYmgaZhAmBXcr78M3XoZkptjuszd2T1FNr1fGZApkZFZXikGtyhCc7jH5JYD1q8csTNSWQn4Us3nzX9":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDfwNJcNMYsyEDVHWrGrNAPBwF9FGEnm5j2XFs4BeGdiSPqPtqCjWCvcRYBfY5EoDjRBhjsTrr2HjB1jw8XZ9Hy8wd9gz4KkCbMugSgf":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEgvmzjLT7R9xHg1vNob6vCf999UFuG4qfTpHGZufdhbkUogSFJXtQXnCcJDHJ6xuZt92H6VgxGdhSLQ9gmWZy4zCJEVu8Nj8NashVQY":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KAtY8hCobTmAB36dzosSo644ZrzATKQhP1AsnM6BAVfTWwMX5BGXhigxLm5hk4beodymyjivxrH7ZY6BZjMu3AtafB5guvagxEZM7vJq":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCRMJDqQ3iK4M19XhWGWpFbCoxjgeDB7ZqUhgW7jSYLEk5oVL4okVPVx5rXCgoK2ND9kAWnNU5QncJp1qvuCngRdJaLrvFwp4boE56VR":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBTRHUnz17FQNFzHR8PpoGGwuNQZauAUxmvTb1o7Ragv9Zvyiv6Cb3rnrmYY1PGtVFTmom3TGg4mK5XpkRyf7PnnCG5EQM69i7MViLpU":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBam1WPtZrz3Fi4EMUDao74k9Xn4fhyVYLqK4o1VRzoxPFU91QBRToLbVyrjX":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KBUH8nDpwtt3sSc6rJ7AkYjmnqvt1tJ4J8ZKCuqPrEuEioJJZXeD9aohveoB9zhRWru6oM5zyBcgMtkA26HLtTDKsSVwzoqugfftbiPu":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCgWqZ8sJW46mQGdZS9wKW2TEQesyCoRScUxvisbdvEkfsxYLR49i6wE6uP1BBgPX9eg8cxKHPuNyKpStwf5UVmRCXD2ahotjamotMwV":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCR9vZcXetWv4QdP4jPSH4msGeXs8DUBUMVYJHgD62etfv2jiD7gmLbLezCAiGTQu9JvrHd9Wfu74wguKgkX1vCUQkzcWsn4rVWsKCyt":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFV3TiBqtLDN3oHQr5NrA8ouAAqasFU4ZuB9W13xgcgWsSy5fUtbNL4imCruQz19hjzBzykxGxCAarrviCUBh3sxWbvvTTHdvpyWGgXc":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGM5rFFreGtZAs4PFB2Drb37uXRHebh8rCeVWFkW8De8XAbYqvfQrAqVthfJp9Qy2YzbzNhWSiUGY3D7yJkRkChyMveKCWT8qUTNEu6e":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBahEJS9xuB3R1ofSgtG621enmfpxfx9Unpo2K26wJPioaA4tizZrNMACNoQb":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KFGV8HUDv7S5E8CSBV3pQLgGFt5HXa2jb9ofbAo3gTxcaQ4So84mHsNk9mhAybq6miH2VZU3iz7cqCd74gPMyn3zdUsrF1u2rib7HSXq":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCF4JTyyC27XuFmcrn9Nxj1DmM4G5BKnf8F8F8BSpvn3PnsLRNH2RZJoajmg4yqHnwMXpUnbb7sFSuthjXv6YUenX8EWsApQUzAm77Dm":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KD5zMmtnD3jWpX3TSJnZJ8jMzCFQHYa3HcHNXxdAnK5A88SiWncRpJQxesMDrYgzPHk7SnFNag5teaFELV6hE9opnJpJzMGpVicDDRX4":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDTABtj2RScLVCLVyFhxcURYUZNVta8CghbH5Edz32XSP79NHc28QTkKLMNUBupRnJXs4zcZt8C2fiPFGZfgSBMqMGMidWc2zo9piRb4":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCGn7x5G6obn9NPNoTuv25LrBcqK9wHCm3XbrhxqycSQrbPfsDxgDp2M8pqTjCk8cVEG2fRxWrTjfG4q71MtyMo6nt8WG11kJzdQQSNL":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEhnv3cCqP8jzRBbwE5v6ymPkBjTexHCcCgYJarjHHaxipJvz4aaXc5Xmp5KXxnC3SoE1oqR8sdGHobyfsAqJy7DwejZWpkkoYD7LJsS":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDvKgSbCTx1gwwZFGe5DZaXyGwTYGGnJNCQ9C61XP4n1pKFQtNbYEowGeRoKHCGUvuU8Ebz2vQwN7YhcJ9bSb5oNpAoCe8UxX5KK5C3e":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KB6yr5YozXGqSKemHyZfsgiRQFX3VdJBKx7waoSaScNWc2dNvhNp6HSnXMxUwDtBvicXDWdpoJ7cKLWAwqEYki5azdt1qDP4sHXh8XhJ":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCqRLQRj8svdZGGLQDZGdXztzeC15Vvt6uZWg23QAdfL1dMc52dpc8jqKquWNj6xjyLnLciVnRxzEq1kiq54ssmc6h7V5xK1cqqKJWBT":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEW3PG2LAJNwmok2H6i149HetvT6fYrPsqPGpUkucNkA4b5TQmv896EF44UmcCAXDycfxFB7GcVefBCgk9cZffVUdX3kri3i5TEqSjKm":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDdgCo1a7URfpQVFoTJEUcn4LqWpAtCeLaW7NeGMJtecsahTJM7886BjLcnhU2CboLSUojCPcab3WNTmXFDrRMHMHdmWefCAyYA7QaaL":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KG5vwKTPpCSQ14a7Cv4TESosSVoFVRHsw1vHj7Tpb7N4j1U5dtFcY7L3MWsH9BJqQjU9NxwaHpbHCJAhmsLi2mC2BE8k8Rj7zcjiiVhR":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KAr171Hd3fu65bbtKxqwktHGwY9kNanPYGXQcFKA8d9Hp1RgLrxzU1AdJCJbJDByTnHdDmtA7pm985tKK8hr5JdHPXFfSvkkYZn3kb9G":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEZWqFxGYhFuLE23i92B8BiLRwwFUdnjmM24KHCNuWik5dc6MJqz7GxupgKGK5zzbYSXJyA8DQVDszyFmJuoxgzPn2GSnfBoREZ82ZdF":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDB6sZamEoJWYBLoDWucRdDtRXCuQvLCoVoHPNjrywJKDz8PQg65ZtLvYvREwAK9oLzGGb6UcdAf9zwQcFaKRRHhLzCZxwTsRDVyPkSy":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDJc8Af5dfJY2jcFbtkofFL6qXBxWnk2kHzCE63qAQR9Ynnk1XkfUrcnBrN7EEyvxmUDEFdNFfZHzXKhmkSQht3b6Y5rHHmuFYYoKdZz":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDjPpuxBuJM1Ma5NGBqriSEAcozZMqYkWEkoJ3GgR8MAy3Zeb8q5BvtsWGEpSFQ69znPuaX4kVCcnEiEMDp91A6EL8A5YM12cpYYogLm":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDmCmpc6FutA3PbQmWxcsbzZsFEdMKhHxrJVtGkmaiWd18dKmiaRA6o4Y2sAjDwjFozKzNzQg3dp8CXVSPpWgDLAXaozoRyPanW7UM8B":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCLfSBFhCBdrb72YBNJkKcDCqpdxf3k7iwJTj7M3txxiq3fcam7Nyi8sLcJNSfgnUrh8C7RKEMN5wWpku7HLdZqZVuPRjeihhgXmEpCe":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KF3ZQhHTvVH3L7jNYoZ3XWK6SWpqZKiu9AGz6qNtxoxhAmmJpenFMA6fedYDT3Lt7cihgc1q4pE2GJXvPuknAkjvESmPxhhzkBzuiRis":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KF9xNLdS47pRBLB8e8bQLuvrBiGJbnHPNCbKU4wrMerJztEtYJdHayvaoUEmJ1vc3aiq9Z3UgP83Y1b4rpiyrGeYjzQhhDgB6DW8sWJm":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KC4LdZLvrexUgAntpySomDAPVwdMEnz1cP9pZxsxZqVYzM6zPPWAhc7byfwsLdgW8GEMTuTUagYFAKEmYgaDmYxK7cHxtWJG3hiMHxVU":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFfXPG5GDEc4tLyVUSepKD9GGXZcSuP1xtLLRQnQr4wSXawT62bSJsiPzS25kdADKh94V3iDksm9nq5fhV4jixCnpNjsn7k2hSkwrAUa":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KC1L9MsZ8htPomWp4FV4hULeBVT6jf3GGqmDcw3k9tPn6pnfqGTWowQDvqVr7BqtQ5rcQ7gc5z41qh9vyBV7Ds83bRsndDbTAwkEUJ21":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBtLs3NwnoLkyVx9ZxSoQ7mQx2ZvzanG7PGWWdMA9ksXqZxakLxdj9MAPKw7eQoZJWHxJJCsd7MeWj7ujfXtPsthGhcURT3Hste4Kr4n":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCaYYFDdnbHEdBzpDPcL5iH98AGF8J5avuweDHwKChDq9mBvLKVJS6F4YTuAVDigPjMnAcuYUJ2UUbvDPePFZBhLhBrFUKeauoKC8X5z":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFfnmiGpxNSGQVMfmFpAFrEAEhZwGPQDutSHnZqQXPhcXxDNcbdoKiztyQHpTA3jSmVowZCxcaJMS1k1wu8U6nXTzejgh7wYZjycamU6":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCTVE8b2UitH791rYrkSrHG9u449h6JHKotuPWRsdVZQfP1jXrs4ygSxAnG1rM5mGFM6cmUqA44e9fenjbVC1QFYyn3R4CaptVZypKgW":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDaKs8A6CU8Lrzxpr3WNM1kDdd4CPe66TqSP2ehHexrAuZ3ykMmhkaUZEHUEiq78ELQx5vpSFGHXFKbyGgrWa8rokqamCV8bSKiqsqVt":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCdPziHrv1QgXL5zMy3KYxr7zPqoRd96iz3LNrkWbobRmPswTpRKgCQEkZcEnipiNJ5UoULAc33mbR44MchdHT5vLNYT9sPxwzpgNUWj":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KGAZJWCpicgRkb9ijP3Jnv6y9EYvnpMqkPdBZ2d6fdnCa9C97HUmfHLWF846AKjViPvnY7MbSM8mTM3VDx5RazBFxA7C7mZ9CyM48AW9":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFfgfRyETGNXNXm6gAxNpTQSxr6bM7T6yZE1ibiZBovxG52PioVmLRnPYxs4wYddAfgTH4mbmtLFnwuZYSBh2eNsdLdc6vWb4AdJNNym":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBsV28Wce4x44WsTVoXa5s4zaBKALWXxMQ2MtfVgB8LJJW34QFpvjrxKmheLtpcLyVqaeu36oB6ZcgQPppFN4oqhdueoKBEpn8dfQUVF":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBEKzyCGqao8GmErVER19oBH3L8xVNCSZs8tCVd53iV5FXZAZ7bNCT67bKoasGeiYZxEoDzGBsKxb4uJxStU1e9wkaPo6BxUEErZG7LD":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCi8WRzrkFiE1AVYbSiXBzMRTuTLv8DAchfg4tPaDgHRuDN6m4dq4VkA17pkWwCoa2NmvNb5sGeU1ZkjcqFuYrWPK2C5a3TLBfx64uLs":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDz8QGqk9LJ9kSsSd1zKgqfTuiTKbL92b4aDSXmRPyrFZp3VPEwhMyEmwCiSkpd7KQztirmU6CGwiphhiHoXbbZjkbfiHN5Mq1y7fmJM":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEcCa8yc1d8Zrne1hRtedHQQGPbkRJcvHak2ygcCndPfSqWwb2L59ERxhtqsMJLdS1fPQPs2vcJcQCvB52tCm4rGCDwUmRG51PUzjSVh":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEhvykuoQZKWdNKFgTrugRUSV66yr8GCXREuaX2PfVQJeuXS4h1bNP8SeUxHAG2J6RfK35YnsZj5qkWQCWV7tVYMVokU5bw9y8CcmqPy":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDsFS7rbQjZQGX6Fz53u76NF2hF9iqRhfbx8ePmjJKCsv5rZV1hhtP6DHdKwLAf5zkVH9FE51xYuCvJzNppSn1tgExVQJpuTwKmyTekT":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFtfVixJcJdD27YZfXfRM5diZFj4TEazkCAhF8KyztTbe67zQpBc1RTjruHNvefdJ9Jtr7u5rebR71tGrGtKioSSGKy2hMKd6GUVFkEg":
|
||||
"19999999999999"
|
||||
, "2cWKMJemoBaiXc4dYCHfDyvy3LcqPebJ8zfRJsZZoHDqik2SzK9Be73YQ5W9u5jEiMPXa":
|
||||
"5428571428571429"
|
||||
, "37btjrVyb4KFNpxUYvzqFKsRfRYJKHjEuFfgy6rpoGq29dcMrNhbKTvqNr719U282rp9PcnFonAENkUdv2nE36wZmyNkj8JVQJL1TLu25SKjGFNzVs":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KFYnqsKFfMwj4S3PcCxwxutoiUubHazLfw4wJc5bfrQgpNEpRnGCS2UUfzvMWRRV2vy4wzPKE7tshLS2YEW219R6QfAenXzktMoXCmuU":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEbo96SLroMfZB11rEvztPswgdqC5ESkHXc4EaFdAhsDQ24vJK23XsjTJzpPS3ZcDWiHiFVtmp5wkJrcnRcMe74s88eTy8YLvLL7EBRj":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBcyGa22cYKz3Xo9UnB2kzZg4nqVX863JCAvUd54ehdg94DWwnBasCv6sUdbKdh9t4tf48oaXokeoms1HDNuegsmRjVntHBX3Z2hnrV7":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDHmdZ8ewhythkmGaUzLCwME5pGtWR7nPhE9nCjLMcKstQFyKq1vTSagA2BXtiopfGwtLq2e1jhUVKsw1Z8Me6XTmLm5C9MzRYCZCd3n":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KBGJtifVyePJjSHTno1XNBeTcqmSqEhyUznts9KGQTsvCd9Hq6zM2w29njvmJYCtWmNkUXvayfqyv7epN1awWkKK1WUFQKJsjtevSKz7":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KEwqVLa1yaRPdDUctf525DovPsxoXZfqNp26eXQnmTSFwY3Q3rgPsjRfTKHKtjFpxPy6XYvjzscccsZYfXSaL9MmgrKAaeQgQhCtoXih":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDxRyqtP9nWyEd7sfzdB8Xgh2egCATJAVtvxM2LhKLp1ALCE714vMCsbQZ5SwvVgiAvmieJTkae865ycwU39JN4pgt27pqEuB8uvi947":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KDA9F68PUv9efaoQHTvacu98Dk6Zx3784ADx4SDnwMfDt3uRfJwqBELeVuis5UEqsf9u4zAD9YC82s6YNmQu43avWDqrQq9Z4hHkEVrL":
|
||||
"19999999999999"
|
||||
, "37btjrVyb4KCjschbSccsYGDJo1rVBjdVrpH27iRtc5h1q4XRqpQJTma1NA9t9t8PrTsJjFE7WzNCczJHQR1RGXW1jDNEiEqNa6xctAZ4ZBtXKHVtp":
|
||||
"19999999999999"
|
||||
}
|
||||
, "blockVersionData":
|
||||
{ "scriptVersion": 0
|
||||
, "slotDuration": "20000"
|
||||
, "maxBlockSize": "2000000"
|
||||
, "maxHeaderSize": "2000"
|
||||
, "maxTxSize": "65536"
|
||||
, "maxProposalSize": "70000"
|
||||
, "mpcThd": "20000000000000"
|
||||
, "heavyDelThd": "300000000000"
|
||||
, "updateVoteThd": "1000000000000"
|
||||
, "updateProposalThd": "100000000000000"
|
||||
, "updateImplicit": "10000"
|
||||
, "softforkRule":
|
||||
{ "initThd": "900000000000000"
|
||||
, "minThd": "600000000000000"
|
||||
, "thdDecrement": "50000000000000"
|
||||
}
|
||||
, "txFeePolicy":
|
||||
{ "summand": "155381000000000" , "multiplier": "43946000000" }
|
||||
, "unlockStakeEpoch": "18446744073709551615"
|
||||
}
|
||||
, "protocolConsts":
|
||||
{ "k": 2160
|
||||
, "protocolMagic": 1097911063
|
||||
, "vssMaxTTL": 6
|
||||
, "vssMinTTL": 2
|
||||
}
|
||||
, "avvmDistr":
|
||||
{ "CWJf8Kl8Gp-DhcWKuhNRUU9P0_CVI2LmpR1MIMxVgGQ=": "20000000000000"
|
||||
, "h48-GEVDKf_0_vGKzmGOuAOhhIm2uc0OEDSNwFayV28=": "20000000000000"
|
||||
, "PO1Kz9bpAowfWD8u9Ial2OkmxDiw6bK_ICDPvuHshJM=": "20000000000000"
|
||||
, "mqJXwreGLRzV9a--egcVvKN4hzIcNUULsXqcPWe3YXI=": "20000000000000"
|
||||
, "ENoYC3dNAtKL-lvjCTZDVhQYmfyWVtI0GNbz4QKqVdY=": "20000000000000"
|
||||
, "o0O4s8YkitBZPeZLVyjn8pjtpBoncr-H9mbtAJS_KfE=": "20000000000000"
|
||||
, "1XEVfDyaheIAeQICkHlwmvEuY9A7E50hA1v_E_QB3Fg=": "20000000000000"
|
||||
, "OKVfmKrrzY0-10uxl9IxlYA6CFWwOU1dN-NyUI0bobU=": "20000000000000"
|
||||
, "LYOSBM00cdDToqHepveoat2SN6vdPntA0nSFXRch83Q=": "20000000000000"
|
||||
, "3Z-Z3rLCxLt0C3KgagBq3wOXrfm68_zh2st5Bi6Covs=": "20000000000000"
|
||||
, "VTx9H6wpJNMC-H-pThklJ9uCllwqXaU0WXHcVTEFAIU=": "20000000000000"
|
||||
, "beyF5mz8icvrBvM-mvQzLfbnHCmxOOg8Z7kJs7nySZs=": "20000000000000"
|
||||
, "rs_VPO7SNO2YlSY2N881xHFeBnW_Sn2o4uSfuGpq9cc=": "20000000000000"
|
||||
, "5RZPTI9FoSvLmiXjKYtUdkrqoMg99tIw8k4enSB1qlQ=": "20000000000000"
|
||||
, "QRBLXNJdJCVDjbwPvQmg_liOcYIWfvoKf7Ns5w_RDvU=": "20000000000000"
|
||||
, "YG9mVGb_MAvTSdFgOUV8JbRBxnj3sPELZxQNVup_X18=": "20000000000000"
|
||||
, "7dEmv0hdv1a7imviD3q3p9pFBFMC77Byx9oinyGwdIQ=": "20000000000000"
|
||||
, "H_Qs3m89FGw8QxVTUGuPjdbOPQyP8vzcD8I37BkRAXY=": "20000000000000"
|
||||
, "pa6NZ1j_bs8kezg23cUQiba3UyLxLiGDQfDXMQmuPSE=": "20000000000000"
|
||||
, "Qi5VCXOUdP-U-Pd--boAii_-gwMpB0IRfibzxWEN53s=": "20000000000000"
|
||||
, "cLJrI380JOISi9A14PYTRmClcxPNQS3_GIZdqcXC1JQ=": "20000000000000"
|
||||
, "BVY8wsqEPXPQ7DPTvnvat7GRiwxFPHC4jY1x3ZvY1PE=": "20000000000000"
|
||||
, "FBlBD9ykcwuFmoogsVjRCUag9xpkwCAgbYDNazT1oY4=": "20000000000000"
|
||||
, "KHwUZRYdwRs5UYIhOO9ycjucY8WvTzpkZgZ4PSbDDPI=": "20000000000000"
|
||||
, "ED2RmO7Wfad2p4gxyzhr4gqlhavksgHEg1acZiKMQF4=": "20000000000000"
|
||||
, "BOjqPWCmGewTKqKekH0HSgpnOEYT8g0qV4t4t6Nj7-c=": "20000000000000"
|
||||
, "b-8mgbBV-r9bqufItyyPp2WLitNhBjaMAajl3GfteeE=": "20000000000000"
|
||||
, "JW_kuEdd0TkJEUA35YUbf_K9C4OlpZd83iTUqrD0q0g=": "20000000000000"
|
||||
, "IF7PMOFaXdwztrj1j_yx_YBafdZpb3pc5EF6y822KgI=": "20000000000000"
|
||||
, "r9HNGwms9l0cMBuT8CznPoadXKbzLPceo4-vDydXUwE=": "20000000000000"
|
||||
, "rM0RFpsVm738CCDdzBhrEz8Q0CLIqiBKMl5rtdFlWmA=": "20000000000000"
|
||||
, "jFyHtgHVcd70V1SZ7O55mo8yvYw5KsijV6fMQEWkJaE=": "20000000000000"
|
||||
, "qWmtDqvA3KZyySJLRPFPO2TiOZh3Dpv1FCJTdEilJvc=": "20000000000000"
|
||||
, "5YYkqAleNp8VXGYiD7WsXvWZQwybkqAUR9xMf5lLvzs=": "20000000000000"
|
||||
, "bi2YeYdi2W2r7IDYToq_N0RR1k3z4GYsRo2xddi2Y7I=": "20000000000000"
|
||||
, "vENWfzLRm1wwHYWTUIOznVCXC3ISPt8J6n3gYFrwfpg=": "20000000000000"
|
||||
, "G71fGc7_2IoExvY8VctjxMCd7lJsTWgvWzg__lF4qcY=": "20000000000000"
|
||||
, "pFzX1lvX3LPolGCv8TQXfWAZupMZEjVlMWmT7nUV70I=": "20000000000000"
|
||||
, "pE7umM4kIaTYqKOviWvgTb34xky-kpbN7VvSzhOT8wo=": "20000000000000"
|
||||
, "P6J7kBAlCPD4wxAnzuzlqTBWMyqI1zVkqVWM5kKoCwg=": "20000000000000"
|
||||
, "CmwjLeSIEKfLzd5ks16QoGCtYNc--wiGsgWWM4OKsco=": "20000000000000"
|
||||
, "-RTrh8sxu9mOYYpcfmyod8-v1Z0nqxMunwK-_NFDzYQ=": "20000000000000"
|
||||
, "EnoSKFBfSJ_l7RXMglXTSolDt6VeNRMay4soxkUmk0E=": "20000000000000"
|
||||
, "VzxlTAQWmOH7ALIXviuXH2pjjYmtW77r9ypeEZlg4mc=": "20000000000000"
|
||||
, "93QRpWUE-Yqthy85Y8poB_WeWdG8A_9nnq4HJiMfJQc=": "20000000000000"
|
||||
, "H7YIN-FF0kUawzVnhQpCoMLuOJkLzYAtZ2xof7vhtPs=": "20000000000000"
|
||||
, "a9_Q5Pzte2G7wXujwVBaAzLcMki6_UjKrxvWzayJ3gY=": "20000000000000"
|
||||
, "O4h-7y-2Izq3ojxailZAbMd0VCq78-kIMv8gIcaA6cA=": "20000000000000"
|
||||
, "mlzqpS0hE6s7apMGRQP4Cx5Fc380yt9gQX7XVcVrmQQ=": "20000000000000"
|
||||
, "aK-WCeAwKHQE9H02zvRLRdoMPIsZWiOfKkbA6yTyMxs=": "20000000000000"
|
||||
, "b3fq65eebunM4fM3AQubawjF6Mt9v9jyEXF5f3hewbo=": "20000000000000"
|
||||
, "ZbZ7v6OcrjZ3vqPFVzaHOK2A5UzRYy-wm0C-ngebU_s=": "20000000000000"
|
||||
, "zXza46kY7Gs5cJEoN2TUwAaXth5W7uUKQfNiaPyWDSc=": "20000000000000"
|
||||
, "5q5RzTcpFFUne5AKkua3DJO1IFQEOGyb2jQvV4DmDT8=": "20000000000000"
|
||||
, "5CzeQFC__uUi8TRPuWVgsUeJauYR3i1f3rvD0CrC34o=": "20000000000000"
|
||||
, "KOp96-E17RXmCf0_vEOcecpTmY8W0wpbpBwFuPwFbKM=": "20000000000000"
|
||||
, "EFK3F4mO823aCcko3QmFJ3Klm7glGs8a0f_f6WVIwdg=": "20000000000000"
|
||||
, "e4TOcy9Qp5BQ8tXkEXaWpuHRmAVcJRfPEV3sVCOKZsQ=": "20000000000000"
|
||||
, "w-2bM_wksghmtHp4ZB2ZOQ-V9Dw1ZivS7RwxgY-DsB4=": "20000000000000"
|
||||
, "9pKGBzQJLoqY6vcOM_OqHRgq9KIdO3ovCBp1mBEFKek=": "20000000000000"
|
||||
, "TMFEEMjP7q64-Liae7CEG0ELKtEC2e2vDuCpMItyfzU=": "20000000000000"
|
||||
, "nrRREQUC1zKTpQRRNDzO-NiQh6DJahitvTk0SWLkc8g=": "20000000000000"
|
||||
, "9xnVxPVNI9fdN5zGa5Fa3HcIwof5T-2lMbdLh3_Nbpk=": "20000000000000"
|
||||
, "NqOaYkD2B5yTFQ1dHMY7X2LmV0Q9tZI6KYR1-dFW_z8=": "20000000000000"
|
||||
, "zhXX6D5r4CDjlLLQiC87LZZL2zWUIYaXhxbcgq_Ww3w=": "20000000000000"
|
||||
, "CXMg_ROxPjiJAyxUpBlUepLDhcdhMffR89izVr9vcRU=": "20000000000000"
|
||||
, "vfTTtqpmg_3jQ7zWV3XhNfmtbtn32Z0fcfNc6_Cx-4E=": "20000000000000"
|
||||
, "3UAwyThFcR1vKSBpktCSkJg3NpMQhL1z4l46NHpfJkY=": "20000000000000"
|
||||
, "K4m8Vu1qtFRavgx0jrctVErZf6VbKDfBnigjQef6k-o=": "20000000000000"
|
||||
, "rmyqI_SuwRsbR4rG1Uk6bUlSJRvo004w5SeejGQERT4=": "20000000000000"
|
||||
, "oo8sxwl7TO2JP-QfW3_aQbE9zZCLBogFPnwEMPUBuYs=": "20000000000000"
|
||||
, "lif3znin9EWfZBoYZ9Ta1c69eINSJNmaqkKJVpFuF2U=": "20000000000000"
|
||||
, "kMAvVvgk0sEf3kHXyfb8gQ6H4gWaFBDSUwms4IFs2jo=": "20000000000000"
|
||||
, "8CMex0Km9bk2J1r4FaSD_FSwlGRgh1e8C1-7fCGUAJE=": "20000000000000"
|
||||
, "pUliJY_tq41pTdo5VJISdWbGGBnL_82pupm4AjZF-y0=": "20000000000000"
|
||||
, "E7dg9_nI8tY9CXli9OyIHtx0FUsq0QZKLBVx9Cr8Daw=": "20000000000000"
|
||||
, "cpO_GBP5qVwOCGxws6oGvgZszu7jy_LwbKZj_f2pg8o=": "20000000000000"
|
||||
, "n8MZ16U_jB4Vg4BPZHGorDzVO7dC9qOfAdYhAluKD4Y=": "20000000000000"
|
||||
, "hqzkwiRusxDSgY-MyqmCyTC0VxELSFdJKJVpzBGOdQM=": "20000000000000"
|
||||
, "QCiQStlI-PWCbwclsM8ZvfrmP49kql7lAwJjgzZ_OvI=": "20000000000000"
|
||||
, "7prDyNFRXierLX1UE26h-TSO0fmfC2lFHQoelogU3hg=": "20000000000000"
|
||||
, "32mL1n7cF_xLIjWAGTC6vISGcafcJe0EgXaxaQNtrzQ=": "20000000000000"
|
||||
, "H94Fk3T5fiEXPd1eGYfpwPP4_y9FVQWsi2bhIAf9hFE=": "20000000000000"
|
||||
, "YLQqBDTjfVrQJcqCzgn0js4ScjJpbh3_dGRmg_wQ9WM=": "20000000000000"
|
||||
, "Ctfg-00LO1JetbfqwOOIwrm56xdZSzzZRccGW52eCps=": "20000000000000"
|
||||
, "GCkRs5Iqi5jyzRhF-Z5B4-EzgCRAb55pJK8a3kmrbwU=": "20000000000000"
|
||||
, "975KNlfAi1B-u2Q0X0qBZpuZNLCUNnKnX-jvBzah3pE=": "20000000000000"
|
||||
, "SrxXeNRxF0accD3dsKoj8ymSQeJoUVs78Llsy-4ZIO0=": "20000000000000"
|
||||
, "m5zF99P2vG3cqGrG17VvRti7d2XRi3fuUHfec-jM6tQ=": "20000000000000"
|
||||
, "A-w4r_kJIZpI8TqDAY-F44cR0lhZtnB25UhT0NXM6Zc=": "20000000000000"
|
||||
, "7mglsAKSgUEkAyA6C5Ni-v_1xoGNPCN_cj7ctQZGZqg=": "20000000000000"
|
||||
, "x3DrzZ_Yp8df2EGsGlwNAnclV2Tv3lcdqnI3Lk_0bF4=": "20000000000000"
|
||||
, "GWoauU1tVb37fjs6mPrxXiBoy9HarPqyGI8zj1mc7cw=": "20000000000000"
|
||||
, "op9p-7Xy9fBmzrjLbMD1jEuW1QVXTOsXSIwgaFN3sDk=": "20000000000000"
|
||||
, "KC7yE_m_JSiWGVP9cpcfYTLF77taAPTgveRKEiIPg1A=": "20000000000000"
|
||||
, "6V6sxoH3dMLw8vWcH0NQF2SZNPDzmtULTX4vxkeCQd4=": "20000000000000"
|
||||
, "y0DLZDhvfU-M5MvdhoyxEFp811PWFfrAdIfDVhYCMzE=": "20000000000000"
|
||||
, "wCHhA7PS7wdfEuMpzrOJfdGyF2uIChR2LnnAcQE3hHI=": "20000000000000"
|
||||
, "s4iYnscFXdEK56b7o4ZvKpgN0YoKchpR-U9MZEqbGb8=": "20000000000000"
|
||||
, "WkMPzKKtocKcbc7_fsFND1oln6gAfWJspg9REi75pMw=": "20000000000000"
|
||||
}
|
||||
, "ftsSeed":
|
||||
"76617361206f7061736120736b6f766f726f64612047677572646120626f726f64612070726f766f6461"
|
||||
}
|
169
cfg-templates/test/config.json
Normal file
169
cfg-templates/test/config.json
Normal file
@ -0,0 +1,169 @@
|
||||
{
|
||||
"ApplicationName": "cardano-sl",
|
||||
"ApplicationVersion": 0,
|
||||
"ByronGenesisFile": "testnet-byron-genesis.json",
|
||||
"ByronGenesisHash": "96fceff972c2c06bd3bb5243c39215333be6d56aaf4823073dca31afe5038471",
|
||||
"LastKnownBlockVersion-Alt": 0,
|
||||
"LastKnownBlockVersion-Major": 2,
|
||||
"LastKnownBlockVersion-Minor": 0,
|
||||
"MaxKnownMajorProtocolVersion": 2,
|
||||
"Protocol": "Cardano",
|
||||
"RequiresNetworkMagic": "RequiresMagic",
|
||||
"ShelleyGenesisFile": "testnet-shelley-genesis.json",
|
||||
"ShelleyGenesisHash": "9f9afb65aa682b19ff484a00baf7e21dcea965d85f72da85957b8405fd78b41c",
|
||||
"TraceBlockFetchClient": false,
|
||||
"TraceBlockFetchDecisions": false,
|
||||
"TraceBlockFetchProtocol": false,
|
||||
"TraceBlockFetchProtocolSerialised": false,
|
||||
"TraceBlockFetchServer": false,
|
||||
"TraceChainDb": true,
|
||||
"TraceChainSyncBlockServer": false,
|
||||
"TraceChainSyncClient": false,
|
||||
"TraceChainSyncHeaderServer": false,
|
||||
"TraceChainSyncProtocol": false,
|
||||
"TraceDNSResolver": true,
|
||||
"TraceDNSSubscription": true,
|
||||
"TraceErrorPolicy": true,
|
||||
"TraceForge": true,
|
||||
"TraceHandshake": false,
|
||||
"TraceIpSubscription": true,
|
||||
"TraceLocalChainSyncProtocol": false,
|
||||
"TraceLocalErrorPolicy": true,
|
||||
"TraceLocalHandshake": false,
|
||||
"TraceLocalTxSubmissionProtocol": false,
|
||||
"TraceLocalTxSubmissionServer": false,
|
||||
"TraceMempool": true,
|
||||
"TraceMux": false,
|
||||
"TraceTxInbound": false,
|
||||
"TraceTxOutbound": false,
|
||||
"TraceTxSubmissionProtocol": false,
|
||||
"TracingVerbosity": "NormalVerbosity",
|
||||
"TurnOnLogMetrics": true,
|
||||
"TurnOnLogging": true,
|
||||
"ViewMode": "SimpleView",
|
||||
"defaultBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"defaultScribes": [
|
||||
[
|
||||
"StdoutSK",
|
||||
"stdout"
|
||||
]
|
||||
],
|
||||
"hasEKG": 12788,
|
||||
"hasPrometheus": [
|
||||
"127.0.0.1",
|
||||
12798
|
||||
],
|
||||
"minSeverity": "Info",
|
||||
"options": {
|
||||
"mapBackends": {
|
||||
"cardano.node-metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.BlockFetchDecision.peers": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.ChainDB.metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
],
|
||||
"cardano.node.Forge.metrics": [
|
||||
"EKGViewBK"
|
||||
],
|
||||
"cardano.node.metrics": [
|
||||
"EKGViewBK",
|
||||
{
|
||||
"kind": "UserDefinedBK",
|
||||
"name": "LiveViewBackend"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mapSubtrace": {
|
||||
"#ekgview": {
|
||||
"contents": [
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": ".monoclock.basic.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "cardano.epoch-validation.benchmark",
|
||||
"tag": "Contains"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.cpuNs.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
{
|
||||
"contents": "#ekgview.#aggregation.cardano.epoch-validation.benchmark",
|
||||
"tag": "StartsWith"
|
||||
},
|
||||
[
|
||||
{
|
||||
"contents": "diff.RTS.gcNum.timed.",
|
||||
"tag": "Contains"
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
"subtrace": "FilterTrace"
|
||||
},
|
||||
"benchmark": {
|
||||
"contents": [
|
||||
"GhcRtsStats",
|
||||
"MonotonicClock"
|
||||
],
|
||||
"subtrace": "ObservableTrace"
|
||||
},
|
||||
"cardano.epoch-validation.utxo-stats": {
|
||||
"subtrace": "NoTrace"
|
||||
},
|
||||
"cardano.node-metrics": {
|
||||
"subtrace": "Neutral"
|
||||
},
|
||||
"cardano.node.metrics": {
|
||||
"subtrace": "Neutral"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rotation": {
|
||||
"rpKeepFilesNum": 10,
|
||||
"rpLogLimitBytes": 5000000,
|
||||
"rpMaxAgeHours": 24
|
||||
},
|
||||
"setupBackends": [
|
||||
"KatipBK"
|
||||
],
|
||||
"setupScribes": [
|
||||
{
|
||||
"scFormat": "ScText",
|
||||
"scKind": "StdoutSK",
|
||||
"scName": "stdout",
|
||||
"scRotation": null
|
||||
}
|
||||
]
|
||||
}
|
68
cfg-templates/test/shelley-genesis.json
Normal file
68
cfg-templates/test/shelley-genesis.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"activeSlotsCoeff": 0.05,
|
||||
"protocolParams": {
|
||||
"protocolVersion": {
|
||||
"minor": 0,
|
||||
"major": 2
|
||||
},
|
||||
"decentralisationParam": 1,
|
||||
"eMax": 18,
|
||||
"extraEntropy": {
|
||||
"tag": "NeutralNonce"
|
||||
},
|
||||
"maxTxSize": 16384,
|
||||
"maxBlockBodySize": 65536,
|
||||
"maxBlockHeaderSize": 1100,
|
||||
"minFeeA": 44,
|
||||
"minFeeB": 155381,
|
||||
"minUTxOValue": 1000000,
|
||||
"poolDeposit": 500000000,
|
||||
"minPoolCost": 340000000,
|
||||
"keyDeposit": 2000000,
|
||||
"nOpt": 150,
|
||||
"rho": 0.003,
|
||||
"tau": 0.20,
|
||||
"a0": 0.3
|
||||
},
|
||||
"genDelegs": {
|
||||
"2f56e87d67b8e5216582cfeb95dbdc9083110a3ef68faaa51bef3a80": {
|
||||
"delegate": "bd5933d3c5417f17a64c7214711a26abc3bc03e2c90dc1bb38e0c39f",
|
||||
"vrf": "9a0b0f537874d089cedfa9e250150405e47ea29acee87c40a223ae0a175d26f8"
|
||||
},
|
||||
"514e81afb082fce01678809eebd90eda4f7918354ec7d0433ad16274": {
|
||||
"delegate": "eff1b5b26e65b791d6f236c7c0264012bd1696759d22bdb4dd0f6f56",
|
||||
"vrf": "e6f70fb10c7523aa76648e20d17e65fd9b2ed53960fbd20b308f223b703f2e23"
|
||||
},
|
||||
"2fca486b4d8f1a0432f5bf18ef473ee4294c795a1a32e3132bc6b90f": {
|
||||
"delegate": "de665a71064706f946030505eae950583f08c316f0f58997961092b1",
|
||||
"vrf": "c3fde629add60e30142cd7ef3c680610975208b08aee42203a5c40ad5992e8f6"
|
||||
},
|
||||
"4ee98623920698b77c1c7f77288cbdac5f9011ff8970b1f507567d0d": {
|
||||
"delegate": "bf07107c6f632de95e34af7e009d2aafa19916c7ba89b944fbedcd72",
|
||||
"vrf": "9d7d12e3d6b02835be3e76cfc6ae93d937035ee0e006d04a0eef9dea19754e21"
|
||||
},
|
||||
"0d06d2547ed371fdf95fb5c4c735eecdd53e6a5bb831561bd0fcfd3d": {
|
||||
"delegate": "6df3e1b4b8a84c63c805076a85e5aa00924997a4eae85fddf0aee3ca",
|
||||
"vrf": "0774e5810fe02a014ec97ef424797172f2b8c5dcfb6e4cfc98b411c31d5096d8"
|
||||
},
|
||||
"581e23030b6038bae716e5d64b9e053db10541b12e6b0b4eff485454": {
|
||||
"delegate": "b0dca078b823cde627da136200d6618c49ad712b77972a1c5e135763",
|
||||
"vrf": "16a4e883b72ddbd09a4f8a1170fc346ab11e4202f814faa73e9d2433ee03e7b0"
|
||||
},
|
||||
"e5f27655371b54aed91cc916b2569060978be80056768fee2cc5ce1b": {
|
||||
"delegate": "b3873a254459f506e47b9a252ee7912e538b364447f31576a170db65",
|
||||
"vrf": "cc5c897fdf5db0017326656fe35aeb20c72b175540793f9b9b8dc9ade001bbc4"
|
||||
}
|
||||
},
|
||||
"updateQuorum": 5,
|
||||
"networkId": "Testnet",
|
||||
"initialFunds": {},
|
||||
"maxLovelaceSupply": 45000000000000000,
|
||||
"networkMagic": 1097911063,
|
||||
"epochLength": 432000,
|
||||
"systemStart": "2019-07-22T20:20:16Z",
|
||||
"slotsPerKESPeriod": 129600,
|
||||
"slotLength": 1,
|
||||
"maxKESEvolutions": 62,
|
||||
"securityParam": 2160
|
||||
}
|
9
cfg-templates/test/topology-relay.json
Normal file
9
cfg-templates/test/topology-relay.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Producers": [
|
||||
{
|
||||
"addr": "relays-new.cardano-testnet.iohkdev.io",
|
||||
"port": 3001,
|
||||
"valency": 2
|
||||
}
|
||||
]
|
||||
}
|
3
cfg-templates/test/topology.json
Normal file
3
cfg-templates/test/topology.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Producers": []
|
||||
}
|
2
examples/best-practice/README.md
Normal file
2
examples/best-practice/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Best Practice example
|
||||
Running on the mainnet-candidate4 for testing purposes.
|
14
examples/best-practice/mc4-block-producing.sh
Normal file
14
examples/best-practice/mc4-block-producing.sh
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
|
||||
docker run -it --rm \
|
||||
--name mc4-block-producing \
|
||||
--network=cardano \
|
||||
-e CARDANO_NETWORK="mc4" \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="block-producing" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay node>:3001/1" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --cold-register --start --staking
|
17
examples/best-practice/mc4-cold-create.sh
Normal file
17
examples/best-practice/mc4-cold-create.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
|
||||
docker run -it --rm \
|
||||
--name mc4-cold-create \
|
||||
--network=cardano \
|
||||
-e CARDANO_NETWORK="mc4" \
|
||||
-e NODE_NAME="cold-create" \
|
||||
-e POOL_PLEDGE="100000000000" \
|
||||
-e POOL_COST="1000000000" \
|
||||
-e POOL_MARGIN="0.05" \
|
||||
-e METADATA_URL="<URL of metadata.json>" \
|
||||
-e PUBLIC_RELAY_IP="<Public IP-address of relay node>" \
|
||||
-e PUBLIC_RELAY_PORT="3000" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --cold-create
|
18
examples/best-practice/mc4-relay1.sh
Normal file
18
examples/best-practice/mc4-relay1.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
|
||||
docker run -it --rm \
|
||||
--network=cardano \
|
||||
--name mc4-relay1 \
|
||||
-p 3001:3001 \
|
||||
-p 12798:12798 \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-e NODE_PORT="3001" \
|
||||
-e NODE_NAME="relay1" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay node>:3000/1" \
|
||||
-e NODE_RELAY="True" \
|
||||
-e CARDANO_NETWORK="mc4" \
|
||||
-e PROMETHEUS_PORT="12798" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start
|
16
examples/main-producing.sh
Normal file
16
examples/main-producing.sh
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
docker run -it --rm \
|
||||
--network=cardano \
|
||||
--name main-producing \
|
||||
-p 3000:3000 \
|
||||
-p 12798:12798 \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="block-producing" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay1 node>:3000/1" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e PROMETHEUS_PORT="12798" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start --staking
|
17
examples/main-registration.sh
Normal file
17
examples/main-registration.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
docker run -it --rm \
|
||||
--name main-registration \
|
||||
--network=cardano \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="registration" \
|
||||
-e NODE_TOPOLOGY="<IP-address of relay1 node>:3000/1" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e CREATE_STAKEPOOL="True" \
|
||||
-e POOL_PLEDGE="100000000000" \
|
||||
-e POOL_COST="340000000" \
|
||||
-e POOL_MARGIN="0.05" \
|
||||
-e METADATA_URL="<URL of metadata.json>" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start --staking
|
18
examples/main-relay1.sh
Normal file
18
examples/main-relay1.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker network create -d bridge cardano
|
||||
docker run -it \
|
||||
--restart=unless-stopped \
|
||||
--network=cardano \
|
||||
--name main-relay1 \
|
||||
-p 3000:3000 \
|
||||
-p 12798:12798 \
|
||||
-e HOST_ADDR="0.0.0.0" \
|
||||
-e NODE_PORT="3000" \
|
||||
-e NODE_NAME="relay1" \
|
||||
-e NODE_TOPOLOGY="<IP-address of block-producing node>:3000/1" \
|
||||
-e NODE_RELAY="True" \
|
||||
-e CARDANO_NETWORK="main" \
|
||||
-e PROMETHEUS_PORT="12798" \
|
||||
-v $PWD/config/:/config/ \
|
||||
arradev/cardano-node:latest --start
|
6
examples/metadata.json
Normal file
6
examples/metadata.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Example Pool",
|
||||
"description": "Cardano stakepool example",
|
||||
"ticker": "TEST",
|
||||
"homepage": "https://github.com/abracadaniel/cardano-node-docker"
|
||||
}
|
49
examples/test/mc4-docker-compose.yaml
Normal file
49
examples/test/mc4-docker-compose.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
version: "3.3"
|
||||
services:
|
||||
mc4-producing: # block-producing node
|
||||
image: arradev/cardano-node:latest
|
||||
stdin_open: true # docker run -i
|
||||
tty: true # docker run -t
|
||||
container_name: mc4-producing
|
||||
network_mode: host
|
||||
volumes:
|
||||
- $PWD/config/local/:/config
|
||||
environment:
|
||||
- HOST_ADDR=0.0.0.0
|
||||
- NODE_PORT=3000
|
||||
- NODE_NAME=mc4-block-producing
|
||||
- NODE_TOPOLOGY=127.0.0.1:3001/1
|
||||
- NODE_RELAY=False
|
||||
- CARDANO_NETWORK=mc4
|
||||
- EKG_PORT=12888
|
||||
- PROMETHEUS_PORT=12898
|
||||
- PROMETHEUS_HOST=127.0.0.1
|
||||
- POOL_PLEDGE=100000000000
|
||||
- POOL_COST=1000000000
|
||||
- POOL_MARGIN=0.05
|
||||
- CREATE_STAKEPOOL=True
|
||||
- METADATA_URL=https://gist.githubusercontent.com/abracadaniel/58dfa2cfe0f986c7f445deb151ed1b49/raw/4bb8155af7be65d7e9869f0923c7ce778c75368b/metadata.json
|
||||
- PUBLIC_RELAY_IP=PUBLIC
|
||||
command: --start
|
||||
restart: unless-stopped
|
||||
mc4-relay1: # relay node
|
||||
image: arradev/cardano-node:latest
|
||||
stdin_open: true # docker run -i
|
||||
tty: true # docker run -t
|
||||
container_name: mc4-relay1
|
||||
network_mode: host
|
||||
volumes:
|
||||
- $PWD/config/local/:/config
|
||||
environment:
|
||||
- HOST_ADDR=0.0.0.0
|
||||
- NODE_PORT=3001
|
||||
- NODE_NAME=mc4-relay1
|
||||
- NODE_TOPOLOGY=127.0.0.1:3000/1
|
||||
- NODE_RELAY=True
|
||||
- CARDANO_NETWORK=mc4
|
||||
- EKG_PORT=12889
|
||||
- PROMETHEUS_PORT=12899
|
||||
- PROMETHEUS_HOST=127.0.0.1
|
||||
- AUTO_TOPOLOGY=False
|
||||
command: --start
|
||||
restart: unless-stopped
|
5
monitoring/README.md
Normal file
5
monitoring/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Work in progress
|
||||
|
||||
See
|
||||
https://docs.cardano.org/projects/cardano-node/en/latest/logging-monitoring/prometheus.html
|
||||
https://docs.cardano.org/projects/cardano-node/en/latest/logging-monitoring/grafana.html
|
15
monitoring/nginx/Dockerfile
Normal file
15
monitoring/nginx/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM nginx:alpine
|
||||
LABEL maintainer="dro@arrakis.it"
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
ENV PROMETHEUS_HOST="prometheus" \
|
||||
USER="" \
|
||||
PASSWORD=""
|
||||
|
||||
RUN apk add --no-cache apache2-utils
|
||||
RUN mkdir -p /config/
|
||||
ADD nginx.tmpl.conf /nginx.tmpl.conf
|
||||
ADD entrypoint.sh entrypoint.sh
|
||||
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
7
monitoring/nginx/README.md
Normal file
7
monitoring/nginx/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# prometheus-nginx proxy
|
||||
|
||||
For securing the prometheus endpoint by adding a nginx reverse proxy with basic auth and tls encryption
|
||||
|
||||
See
|
||||
https://prometheus.io/docs/guides/tls-encryption/
|
||||
https://prometheus.io/docs/guides/basic-auth/
|
3
monitoring/nginx/build.sh
Normal file
3
monitoring/nginx/build.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker build -t arrakis/nginx-prometheus .
|
14
monitoring/nginx/entrypoint.sh
Normal file
14
monitoring/nginx/entrypoint.sh
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Init config
|
||||
echo "Generating config"
|
||||
cp /nginx.tmpl.conf /config/nginx.conf
|
||||
sed -i "s/\[PROMETHEUS_HOST\]/${PROMETHEUS_HOST}/g" /config/nginx.conf
|
||||
cat /config/nginx.conf
|
||||
echo ""
|
||||
|
||||
# Generate password
|
||||
htpasswd -b -c /config/htpasswd ${USER} ${PASSWORD}
|
||||
|
||||
echo "Starting nginx"
|
||||
nginx -g "daemon off;" -c /config/nginx.conf
|
32
monitoring/nginx/nginx.tmpl.conf
Normal file
32
monitoring/nginx/nginx.tmpl.conf
Normal file
@ -0,0 +1,32 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen 9091;
|
||||
|
||||
location / {
|
||||
auth_basic "Prometheus";
|
||||
auth_basic_user_file /config/htpasswd;
|
||||
|
||||
proxy_pass http://[PROMETHEUS_HOST]:9090/;
|
||||
}
|
||||
}
|
||||
}
|
15
monitoring/prometheus/Dockerfile
Normal file
15
monitoring/prometheus/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM prom/prometheus:latest
|
||||
LABEL maintainer="dro@arrakis.it"
|
||||
|
||||
EXPOSE 9090
|
||||
|
||||
#alias/host:port
|
||||
ENV TARGETS="relay1/relay1:12798,producing1/producing1:12798"
|
||||
|
||||
USER root
|
||||
ADD config.tmpl.yml /config.tmpl.yml
|
||||
ADD entrypoint.sh /entrypoint.sh
|
||||
RUN chmod 755 /entrypoint.sh
|
||||
RUN mkdir /config/
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
6
monitoring/prometheus/README.md
Normal file
6
monitoring/prometheus/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# cardano-node prometheus
|
||||
|
||||
To connect to and scrape data from the prometheus services in the cardano-nodes.
|
||||
|
||||
## Environment Variables
|
||||
TARGETS="ALIAS1/IP:PORT,ALIAS2/IP:PORT"
|
3
monitoring/prometheus/build.sh
Normal file
3
monitoring/prometheus/build.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker build -t arrakis/cardano-prometheus .
|
22
monitoring/prometheus/config.tmpl.yml
Normal file
22
monitoring/prometheus/config.tmpl.yml
Normal file
@ -0,0 +1,22 @@
|
||||
global:
|
||||
scrape_interval: 15s # By default, scrape targets every 15 seconds.
|
||||
|
||||
# Attach these labels to any time series or alerts when communicating with
|
||||
# external systems (federation, remote storage, Alertmanager).
|
||||
external_labels:
|
||||
monitor: 'codelab-monitor'
|
||||
|
||||
# A scrape configuration containing exactly one endpoint to scrape:
|
||||
# Here it's Prometheus itself.
|
||||
scrape_configs:
|
||||
# The job name is added as a label job=<job_name> to any timeseries scraped from this config.
|
||||
- job_name: 'prometheus'
|
||||
|
||||
# Override the global default and scrape targets from this job every 5 seconds.
|
||||
scrape_interval: 5s
|
||||
|
||||
static_configs:
|
||||
- targets: ['[NODE_HOST]:[NODE_PORT]']
|
||||
labels:
|
||||
alias: '[NODE_ALIAS]'
|
||||
type: 'cardano-node'
|
18
monitoring/prometheus/config.yml
Normal file
18
monitoring/prometheus/config.yml
Normal file
@ -0,0 +1,18 @@
|
||||
global:
|
||||
external_labels:
|
||||
monitor: codelab-monitor
|
||||
scrape_interval: 15s
|
||||
scrape_configs:
|
||||
- job_name: prometheus
|
||||
scrape_interval: 5s
|
||||
static_configs:
|
||||
- labels:
|
||||
alias: relay1
|
||||
type: cardano-node
|
||||
targets:
|
||||
- relay1:12798
|
||||
- labels:
|
||||
alias: producing1
|
||||
type: cardano-node
|
||||
targets:
|
||||
- producing1:12798
|
9
monitoring/prometheus/entrypoint.sh
Normal file
9
monitoring/prometheus/entrypoint.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Init config
|
||||
mkdir -p /config/
|
||||
if [ ! -f "/config/config.yml" ]; then
|
||||
python /init_config.py /config.tmpl.yml /config/config.yml
|
||||
fi
|
||||
|
||||
prometheus --config.file=/config/config.yml --storage.tsdb.path=/config/data/
|
35
monitoring/prometheus/init_config.py
Normal file
35
monitoring/prometheus/init_config.py
Normal file
@ -0,0 +1,35 @@
|
||||
import os
|
||||
import yaml
|
||||
import sys
|
||||
|
||||
|
||||
def parse_targets(targets_str):
|
||||
if not targets_str: return None
|
||||
|
||||
output = []
|
||||
targets = targets_str.split(',')
|
||||
for target in targets:
|
||||
alias, host = target.split('/')
|
||||
addr, port = host.split(':')
|
||||
|
||||
output.append({
|
||||
'targets': ['%s:%s' % (addr, port)],
|
||||
'labels': {
|
||||
'alias': alias,
|
||||
'type': 'cardano-node'
|
||||
}
|
||||
})
|
||||
return output
|
||||
|
||||
in_file = sys.argv[1]
|
||||
out_file = sys.argv[2]
|
||||
targets = parse_targets(os.environ.get('TARGETS'))
|
||||
if targets:
|
||||
with open(in_file) as file:
|
||||
config = yaml.full_load(file)
|
||||
print(config)
|
||||
print(targets)
|
||||
config['scrape_configs'][0]['static_configs'] = targets
|
||||
|
||||
with open(out_file, 'w') as _file:
|
||||
documents = yaml.dump(config, _file)
|
1
monitoring/prometheus/requirements.txt
Normal file
1
monitoring/prometheus/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
pyyaml
|
41
scripts/cold_create
Normal file
41
scripts/cold_create
Normal file
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/init_node_vars
|
||||
export WAIT_FOR_SYNC=False
|
||||
|
||||
echo "Creating Stake Pool addresses, keys and certificates, to be submitted to the blockchain."
|
||||
|
||||
# If staking/ directory exists create a backup
|
||||
if [ -d "${NODE_PATH}/staking/" ]; then
|
||||
TIMESTAMP=$(date +%s)
|
||||
BACKUPNAME="staking.${TIMESTAMP}.tar.gz"
|
||||
echo "staking directory already exists."
|
||||
echo "Backing up to ${BACKUPNAME}."
|
||||
mkdir -p ${NODE_PATH}/backups/
|
||||
tar -zcvf ${NODE_PATH}/backups/${BACKUPNAME} ${NODE_PATH}/staking/ > /dev/null
|
||||
fi
|
||||
|
||||
# Start creation
|
||||
generate_wallet owner
|
||||
register_stake_address owner --cold-create
|
||||
|
||||
tar -zcvf wallets-hot.tar.gz --exclude='*.skey' staking/wallets/
|
||||
|
||||
## Generate wallets for multiple owners
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
generate_wallet $i
|
||||
register_stake_address $i --cold-create
|
||||
done
|
||||
fi
|
||||
|
||||
generate_operational_certificate
|
||||
generate_registration_certificates --cold-create
|
||||
register_stake_pool --cold-create
|
||||
|
||||
echo "Archiving required files"
|
||||
cd ${NODE_PATH} && tar -zcvf staking-hot.tar.gz --exclude='cold-keys' --exclude='wallets/*/*.skey' staking/
|
||||
|
||||
echo "Created all addresses, certificates and transactions. Upload the \`staking-hot.tar.gz\` file to your live node, and submit the registration transaction by running with the \`--cold-register\`."
|
||||
read
|
110
scripts/cold_register
Normal file
110
scripts/cold_register
Normal file
@ -0,0 +1,110 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/check_address_registration
|
||||
source /scripts/functions/wait_for_address_registration
|
||||
source /scripts/functions/wait_for_pool_registration
|
||||
source /scripts/functions/wait_for_slot
|
||||
source /scripts/functions/wait_for_sync
|
||||
|
||||
if [ -f "${NODE_PATH}/staking/POOL_VARS" ]; then
|
||||
source ${NODE_PATH}/staking/POOL_VARS
|
||||
if [ -n "${REGISTERED_COLD}" ]; then
|
||||
echo "Registration is already done."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
function submit_stake_addr {
|
||||
WALLET=$1
|
||||
cd ${NODE_PATH}/staking/wallets/${WALLET}/
|
||||
STAKE_ADDR=$(cat stake.addr)
|
||||
|
||||
echo "Submitting stake address for wallet ${WALLET}"
|
||||
if [ -n "$(check_address_registration ${STAKE_ADDR})" ]; then
|
||||
echo "Your stake address for ${WALLET} has already been registered in the blockchain."
|
||||
return
|
||||
fi
|
||||
|
||||
OUT=$(cardano-cli shelley transaction submit \
|
||||
--tx-file transactions/register_stake_address.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
exit
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
|
||||
echo "Wait for the blockchain to register the address."
|
||||
wait_for_address_registration ${STAKE_ADDR}
|
||||
echo "Your stake address is now registered in the blockchain."
|
||||
touch transactions/register_stake_address.submitted
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for staking-hot.tar.gz
|
||||
if [ ! -f "${NODE_PATH}/staking-hot.tar.gz" ]; then
|
||||
echo "Missing required ${NODE_PATH}staking-hot.tar.gz file. First run with the \`--cold-register\` argument on a secure offline node."
|
||||
read -n 1 -r -s -p "If you already have generated the file, please place it in its correct place, and press ENTER to continue."
|
||||
fi
|
||||
|
||||
# Backup staking/ directory
|
||||
if [ -d "${NODE_PATH}/staking/" ]; then
|
||||
TIMESTAMP=$(date +%s)
|
||||
BACKUPNAME="staking.${TIMESTAMP}.tar.gz"
|
||||
echo "staking directory already exists."
|
||||
echo "Backing up to ${BACKUPNAME}."
|
||||
mkdir -p ${NODE_PATH}/backups/
|
||||
tar -zcvf ${NODE_PATH}/backups/${BACKUPNAME} ${NODE_PATH}/staking/ > /dev/null
|
||||
fi
|
||||
|
||||
# Unpack staking-hot.tar.gz
|
||||
cd ${NODE_PATH} && tar -xvf staking-hot.tar.gz
|
||||
source ${NODE_PATH}/staking/POOL_VARS
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
# Submit the stake address transaction
|
||||
submit_stake_addr owner
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
submit_stake_addr $i
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Submit the pool transaction
|
||||
read -n 1 -r -s -p $'Press enter to submit the stake pool registration transaction...\n'
|
||||
|
||||
echo "Submitting transaction"
|
||||
OUT=$(cardano-cli shelley transaction submit \
|
||||
--tx-file cold-registration/register_stake_pool.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
exit
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
|
||||
echo "Wait for blockchain to register the pool"
|
||||
wait_for_pool_registration
|
||||
echo "Your stake pool registration has been sent to the blockchain."
|
||||
fi
|
||||
|
||||
echo "Press any key to continue."
|
||||
echo "export REGISTERED_COLD=True" >> ${NODE_PATH}/staking/POOL_VARS
|
||||
read
|
35
scripts/create_stakepool
Normal file
35
scripts/create_stakepool
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# We run a syncing node which is needed to query the blockchain for creating and registering the keys and certificates.
|
||||
# Then synchronously we start creating and registering the keys.
|
||||
mkdir -p ${NODE_PATH}/logs/
|
||||
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
--cold-create)
|
||||
COLD_CREATE=1
|
||||
break
|
||||
;;
|
||||
--cold-register)
|
||||
COLD_REGISTER=1
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -n "$COLD_CREATE" ]; then
|
||||
cold_create |& tee ${NODE_PATH}/logs/create_stakepool.$(date +%s).log
|
||||
elif [ -n "$COLD_REGISTER" ]; then
|
||||
tmux \
|
||||
new-session "source /scripts/functions/run_node; run_node" \; \
|
||||
split-window "cold_register |& tee ${NODE_PATH}/logs/register_stakepool.$(date +%s).log" \; \
|
||||
select-layout even-horizontal
|
||||
else
|
||||
tmux \
|
||||
new-session "source /scripts/functions/run_node; run_node" \; \
|
||||
split-window "source /scripts/functions/create_and_register_pool; create_and_register_pool |& tee ${NODE_PATH}/logs/create_stakepool.$(date +%s).log" \; \
|
||||
select-layout even-horizontal
|
||||
fi
|
10
scripts/functions/auto_topology_start
Normal file
10
scripts/functions/auto_topology_start
Normal file
@ -0,0 +1,10 @@
|
||||
function auto_topology_start {
|
||||
# Add topology_submit to crontab
|
||||
echo "Starting crontab."
|
||||
cp /cfg-templates/crontab /crontab
|
||||
service cron start
|
||||
crontab /crontab
|
||||
|
||||
# Update topology.json
|
||||
topology_update 1
|
||||
}
|
6
scripts/functions/check_address_registration
Normal file
6
scripts/functions/check_address_registration
Normal file
@ -0,0 +1,6 @@
|
||||
function check_address_registration {
|
||||
source /scripts/init_node_vars
|
||||
|
||||
STAKE_ADDR=$1
|
||||
cardano-cli query stake-address-info --address ${STAKE_ADDR} ${NETWORK_ARGUMENT} --allegra-era | grep -v {}
|
||||
}
|
58
scripts/functions/check_balance
Normal file
58
scripts/functions/check_balance
Normal file
@ -0,0 +1,58 @@
|
||||
function check_balance {
|
||||
PRICE=$1
|
||||
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
while true; do
|
||||
echo ""
|
||||
echo "Checking balance for address ${ADDRESS}."
|
||||
echo ""
|
||||
|
||||
TOTAL_LOVELACE=0
|
||||
cardano-cli query utxo ${NETWORK_ARGUMENT} --allegra-era --address ${ADDRESS}
|
||||
|
||||
UTXOS=$(cardano-cli query utxo ${NETWORK_ARGUMENT} --allegra-era --address ${ADDRESS} | tail -n +3)
|
||||
echo "UTXO#TXIX: LOVELACE"
|
||||
while IFS= read -r line ; do
|
||||
arr=(${line})
|
||||
LOVELACE=${arr[2]}
|
||||
TOTAL_LOVELACE=$(expr ${TOTAL_LOVELACE} + ${LOVELACE})
|
||||
|
||||
if [ -n "${LOVELACE}" ]; then
|
||||
echo "${arr[0]}#${arr[1]}: ${arr[2]}"
|
||||
if [ "$LOVELACE" -ge "$PRICE" ]; then
|
||||
UTXO=${arr[0]}
|
||||
TXIX=${arr[1]}
|
||||
LOVELACE_FOR_UTXO_TXIX=$LOVELACE
|
||||
fi
|
||||
fi
|
||||
done <<< "${UTXOS}"
|
||||
|
||||
if [ -n "${UTXO}" ]; then
|
||||
LOVELACE=$LOVELACE_FOR_UTXO_TXIX
|
||||
echo "Address is successfully funded."
|
||||
echo ""
|
||||
echo "Got UTXO"
|
||||
echo "UTXO: ${UTXO}#${TXIX}"
|
||||
echo "Lovelace Holding: ${LOVELACE}"
|
||||
break
|
||||
fi
|
||||
|
||||
echo "You need to fund your address with atleast ${PRICE} Lovelace to continue with the transaction."
|
||||
echo "Your payment address is:"
|
||||
echo "${ADDRESS}"
|
||||
echo ""
|
||||
echo "If you have funded your address, you need to wait for the transaction to be processed and your node to synchronize."
|
||||
sync_status
|
||||
echo ""
|
||||
|
||||
sleep 10
|
||||
done
|
||||
else
|
||||
echo "Find UTXO and TXIX containing atleast ${PRICE} Lovelace for address ${ADDRESS} (Wallet ${WALLET})"
|
||||
echo "Run \`cardano-cli query utxo ${NETWORK_ARGUMENT} --allegra-era --address ${ADDRESS}\`, on online node to find the values."
|
||||
read -p "Enter the UTXO: " UTXO
|
||||
read -p "Enter the TXIX: " TXIX
|
||||
LOVELACE=0
|
||||
fi
|
||||
}
|
||||
|
13
scripts/functions/check_kes_status
Normal file
13
scripts/functions/check_kes_status
Normal file
@ -0,0 +1,13 @@
|
||||
function check_kes_status {
|
||||
source /scripts/init_node_vars
|
||||
source ${NODE_PATH}/staking/pool-keys/KESPERIOD
|
||||
|
||||
if [ -n "$EXPIRESLOT" ]; then
|
||||
CURRENT_SLOT=$(get_slot)
|
||||
SLOTS_LEFT=$(expr ${EXPIRESLOT} - ${CURRENT_SLOT})
|
||||
|
||||
echo ${SLOTS_LEFT}
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
6
scripts/functions/check_pool_registration
Normal file
6
scripts/functions/check_pool_registration
Normal file
@ -0,0 +1,6 @@
|
||||
function check_pool_registration {
|
||||
source /scripts/init_node_vars
|
||||
|
||||
POOL_ID=$(cat ${NODE_PATH}/staking/POOL_ID)
|
||||
cardano-cli query ledger-state --allegra-era ${NETWORK_ARGUMENT} | grep publicKey | grep ${POOL_ID}
|
||||
}
|
39
scripts/functions/create_and_register_pool
Normal file
39
scripts/functions/create_and_register_pool
Normal file
@ -0,0 +1,39 @@
|
||||
function create_and_register_pool {
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/wait_for_socket
|
||||
|
||||
echo "Creating Stake Pool addresses, keys and certificates, and submits to the blockchain."
|
||||
|
||||
# If staking/ directory exists create a backup
|
||||
if [ -d "${NODE_PATH}/staking/" ]; then
|
||||
TIMESTAMP=$(date +%s)
|
||||
BACKUPNAME="staking.${TIMESTAMP}.tar.gz"
|
||||
echo "staking directory already exists."
|
||||
echo "Backing up to ${BACKUPNAME}."
|
||||
mkdir -p backups/
|
||||
tar -zcvf ${NODE_PATH}/backups/${BACKUPNAME} ${NODE_PATH}/staking/ > /dev/null
|
||||
fi
|
||||
|
||||
# Wait for database to load (wait_for_socket in loop)
|
||||
wait_for_socket
|
||||
|
||||
# Start creation
|
||||
generate_wallet owner
|
||||
register_stake_address owner
|
||||
|
||||
## Generate wallets for multiple owners
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
generate_wallet $i
|
||||
register_stake_address $i
|
||||
done
|
||||
fi
|
||||
|
||||
generate_operational_certificate LIVE
|
||||
generate_registration_certificates
|
||||
register_stake_pool
|
||||
|
||||
# Stop syncing cardano-node so block-producing node can be started
|
||||
killall -9 cardano-node
|
||||
}
|
10
scripts/functions/current_epoch
Normal file
10
scripts/functions/current_epoch
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
GENESIS=${NODE_PATH}/shelley-genesis.json
|
||||
|
||||
startTimeGenesis=$(cat ${GENESIS} | jq -r .systemStart)
|
||||
startTimeSec=$(date --date=${startTimeGenesis} +%s) #in seconds (UTC)
|
||||
currentTimeSec=$(date -u +%s) #in seconds (UTC)
|
||||
epochLength=$(cat ${GENESIS} | jq -r .epochLength)
|
||||
currentEPOCH=$(( (${currentTimeSec}-${startTimeSec}) / ${epochLength} )) #returns a integer number, we like that
|
||||
echo ${currentEPOCH}
|
7
scripts/functions/get_block
Normal file
7
scripts/functions/get_block
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Init vars
|
||||
source /scripts/init_node_vars
|
||||
|
||||
BLOCK=$(cardano-cli query tip ${NETWORK_ARGUMENT} | jq -r '.blockNo')
|
||||
echo "${BLOCK}"
|
6
scripts/functions/get_protocol
Normal file
6
scripts/functions/get_protocol
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Init vars
|
||||
source /scripts/init_node_vars
|
||||
|
||||
cardano-cli query protocol-parameters ${NETWORK_ARGUMENT} --allegra-era --out-file protocol.json
|
3
scripts/functions/get_public_ip
Normal file
3
scripts/functions/get_public_ip
Normal file
@ -0,0 +1,3 @@
|
||||
function get_public_ip {
|
||||
echo $(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}')
|
||||
}
|
7
scripts/functions/get_slot
Normal file
7
scripts/functions/get_slot
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Init vars
|
||||
source /scripts/init_node_vars
|
||||
|
||||
SLOT=$(cardano-cli query tip ${NETWORK_ARGUMENT} | jq -r '.slotNo')
|
||||
echo "${SLOT}"
|
3
scripts/functions/init_config
Normal file
3
scripts/functions/init_config
Normal file
@ -0,0 +1,3 @@
|
||||
function init_config {
|
||||
python3 /scripts/init_config.py
|
||||
}
|
20
scripts/functions/node_info
Normal file
20
scripts/functions/node_info
Normal file
@ -0,0 +1,20 @@
|
||||
function node_info {
|
||||
STAKEPOOL=$1
|
||||
if [ -n "$STAKEPOOL" ]; then
|
||||
POOL_ID=$(cat ${NODE_PATH}/staking/POOL_ID)
|
||||
source ${NODE_PATH}/staking/POOL_VARS
|
||||
source /scripts/functions/stakepool_info
|
||||
|
||||
echo "Pool ID: ${POOL_ID}"
|
||||
stakepool_info
|
||||
fi
|
||||
echo "Node name: ${NODE_NAME}"
|
||||
echo "Network: ${CARDANO_NETWORK}"
|
||||
echo "Host Address: ${HOST_ADDR}"
|
||||
echo "Public IP: ${PUBLIC_IP}"
|
||||
echo "Node Port: ${NODE_PORT}"
|
||||
echo "Node path: ${NODE_PATH}"
|
||||
echo "EKG Port: ${EKG_PORT}"
|
||||
echo "Prometheus Port: ${PROMETHEUS_PORT}"
|
||||
|
||||
}
|
17
scripts/functions/run_node
Normal file
17
scripts/functions/run_node
Normal file
@ -0,0 +1,17 @@
|
||||
function run_node {
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/node_info
|
||||
|
||||
# Running in loop allows for restarting without restarting the container
|
||||
while true; do
|
||||
echo "Starting cardano-node"
|
||||
node_info
|
||||
cardano-node run \
|
||||
--topology ${NODE_PATH}/topology.json \
|
||||
--database-path ${NODE_PATH}/db \
|
||||
--socket-path ${CARDANO_NODE_SOCKET_PATH} \
|
||||
--host-addr ${HOST_ADDR} \
|
||||
--port ${NODE_PORT} \
|
||||
--config ${NODE_PATH}/config.json
|
||||
done
|
||||
}
|
21
scripts/functions/run_stakingnode
Normal file
21
scripts/functions/run_stakingnode
Normal file
@ -0,0 +1,21 @@
|
||||
function run_stakingnode {
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/node_info
|
||||
|
||||
echo "Starting cardano-node as a staking node."
|
||||
node_info 1
|
||||
|
||||
# Running in loop allows for restarting without restarting the container
|
||||
while true; do
|
||||
cardano-node run \
|
||||
--topology ${NODE_PATH}/topology.json \
|
||||
--database-path ${NODE_PATH}/db \
|
||||
--socket-path ${CARDANO_NODE_SOCKET_PATH} \
|
||||
--host-addr ${HOST_ADDR} \
|
||||
--port ${NODE_PORT} \
|
||||
--config ${NODE_PATH}/config.json \
|
||||
--shelley-kes-key ${NODE_PATH}/staking/pool-keys/kes.skey \
|
||||
--shelley-vrf-key ${NODE_PATH}/staking/pool-keys/vrf.skey \
|
||||
--shelley-operational-certificate ${NODE_PATH}/staking/pool-keys/node.cert
|
||||
done
|
||||
}
|
19
scripts/functions/stakepool_info
Normal file
19
scripts/functions/stakepool_info
Normal file
@ -0,0 +1,19 @@
|
||||
function stakepool_info {
|
||||
if [ -f "${NODE_PATH}/staking/metadata.json" ]; then
|
||||
METADATA=${NODE_PATH}/staking/metadata.json
|
||||
|
||||
POOL_NAME=$(jq -r '.name' $METADATA)
|
||||
POOL_DESCRIPTION=$(jq -r '.description' $METADATA)
|
||||
POOL_TICKER=$(jq -r '.ticker' $METADATA)
|
||||
POOL_HOMEPAGE=$(jq -r '.homepage' $METADATA)
|
||||
|
||||
echo "Pool Name: ${POOL_NAME}"
|
||||
echo "Pool Description: ${POOL_DESCRIPTION}"
|
||||
echo "Pool Ticker: ${POOL_TICKER}"
|
||||
echo "Pool Homepage: ${POOL_HOMEPAGE}"
|
||||
fi
|
||||
|
||||
echo "Pool Pledge: ${POOL_PLEDGE}"
|
||||
echo "Pool Cost: ${POOL_COST}"
|
||||
echo "Pool Margin: ${POOL_MARGIN}"
|
||||
}
|
16
scripts/functions/status
Normal file
16
scripts/functions/status
Normal file
@ -0,0 +1,16 @@
|
||||
function status {
|
||||
source /scripts/functions/wait_for_socket
|
||||
source /scripts/functions/check_kes_status
|
||||
|
||||
wait_for_socket
|
||||
|
||||
while true; do
|
||||
KES_SLOTS_LEFT=$(check_kes_status)
|
||||
echo "Your KES and VRF keys and node certificate has to be renewed in ${KES_SLOTS_LEFT} slots."
|
||||
echo "To renew run \`generate_operational_certificate\`"
|
||||
echo ""
|
||||
echo "Node sync status:"
|
||||
sync_status
|
||||
sleep 60
|
||||
done
|
||||
}
|
26
scripts/functions/sync_status
Normal file
26
scripts/functions/sync_status
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# Thanks to Smaug from https://t.me/CardanoStakePoolWorkgroup
|
||||
|
||||
source /scripts/functions/wait_for_socket
|
||||
wait_for_socket
|
||||
|
||||
GENESIS=${NODE_PATH}/shelley-genesis.json
|
||||
BYRON_GENESIS=${NODE_PATH}/byron-genesis.json
|
||||
#HARDFORK_EPOCH=208 # Defines the epoch which the hardfork happened in. 1 for MC4, 208 for mainnet. This is set in the network VARS file
|
||||
NETWORK="${NETWORK_ARGUMENT}" # replace by --mainnet for mainnet
|
||||
|
||||
epoch_length=$(jq -r .epochLength $GENESIS)
|
||||
slot_length=$(jq -r .slotLength $GENESIS)
|
||||
byron_slot_length=$(( $(jq -r .blockVersionData.slotDuration $BYRON_GENESIS) / 1000 ))
|
||||
byron_epoch_length=$(( $(jq -r .protocolConsts.k $BYRON_GENESIS) * 10 ))
|
||||
|
||||
byron_start=$(jq -r .startTime $BYRON_GENESIS)
|
||||
byron_end=$((byron_start + HARDFORK_EPOCH * byron_epoch_length * byron_slot_length))
|
||||
byron_slots=$(($HARDFORK_EPOCH * byron_epoch_length))
|
||||
now=$(date +'%s')
|
||||
|
||||
expected_slot=$((byron_slots + (now - byron_end) / slot_length))
|
||||
current_slot=$(cardano-cli query tip $NETWORK | jq -r '.slotNo')
|
||||
percent=$(echo -e "scale=2\n$current_slot * 100 / $expected_slot" | bc)
|
||||
|
||||
echo "slot ${current_slot}/${expected_slot} ${percent}%"
|
27
scripts/functions/topology_submit
Normal file
27
scripts/functions/topology_submit
Normal file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/functions/get_public_ip
|
||||
source /scripts/functions/wait_for_sync
|
||||
|
||||
echo "Submitting IP to topology updater."
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.98
|
||||
fi
|
||||
|
||||
cd ${NODE_PATH}
|
||||
mkdir -p ${NODE_PATH}/logs/
|
||||
|
||||
NWMAGIC=$(jq -r .networkMagic < ${NODE_PATH}/shelley-genesis.json)
|
||||
TIMESTAMP=$(date +%s)
|
||||
BLOCK=$(get_block)
|
||||
PUBLIC_IP=$(get_public_ip)
|
||||
|
||||
echo "Network Magic: ${NWMAGIC}"
|
||||
echo "Block: ${BLOCK}"
|
||||
echo "IP: ${PUBLIC_IP}"
|
||||
echo "Port: ${NODE_PORT}"
|
||||
echo "Submitting..."
|
||||
|
||||
curl -s "https://api.clio.one/htopology/v1/?port=${NODE_PORT}&blockNo=${BLOCK}&valency=1&magic=${NWMAGIC}${T_HOSTNAME}" | tee -a ${NODE_PATH}/logs/update_topology.${TIMESTAMP}.json
|
35
scripts/functions/topology_update
Normal file
35
scripts/functions/topology_update
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/functions/get_public_ip
|
||||
|
||||
cd ${NODE_PATH}
|
||||
|
||||
echo "Updating topology.json using topology updater."
|
||||
|
||||
RETRY=$1
|
||||
NWMAGIC=$(jq -r .networkMagic < ${NODE_PATH}/shelley-genesis.json)
|
||||
CUSTOM_PEERS=$(python3 /scripts/get_topology_str.py)
|
||||
|
||||
curl -s -o ${NODE_PATH}/topology.auto.json "https://api.clio.one/htopology/v1/fetch/?max=14&magic=${NWMAGIC}&customPeers=${CUSTOM_PEERS}"
|
||||
PRODUCERS=$(jq -r .Producers < ${NODE_PATH}/topology.auto.json)
|
||||
|
||||
if [[ "${PRODUCERS}" == "null" ]]; then
|
||||
echo "Update of topology.json was unsuccessful."
|
||||
cat ${NODE_PATH}/topology.auto.json
|
||||
|
||||
if [[ -n "$RETRY" ]]; then
|
||||
echo "Submitting IP to topology updater database and retrying fetching the topology."
|
||||
topology_submit
|
||||
topology_update
|
||||
fi
|
||||
else
|
||||
# Replace topology
|
||||
mv ${NODE_PATH}/topology.json ${NODE_PATH}/topology.backup.json
|
||||
mv -f ${NODE_PATH}/topology.auto.json ${NODE_PATH}/topology.json
|
||||
|
||||
# Restart cardano-node
|
||||
echo "Restarting cardano-node"
|
||||
killall -9 cardano-node
|
||||
|
||||
read
|
||||
fi
|
13
scripts/functions/wait_for_address_registration
Normal file
13
scripts/functions/wait_for_address_registration
Normal file
@ -0,0 +1,13 @@
|
||||
function wait_for_address_registration {
|
||||
source /scripts/functions/check_address_registration
|
||||
|
||||
STAKE_ADDR=$1
|
||||
echo "Waiting for the blockchain to register the address."
|
||||
while true; do
|
||||
if [ -n "$(check_address_registration ${STAKE_ADDR})" ]; then
|
||||
break
|
||||
fi
|
||||
echo "Blockchain has not yet registered the address. Waiting.."
|
||||
sleep 10
|
||||
done
|
||||
}
|
5
scripts/functions/wait_for_file
Normal file
5
scripts/functions/wait_for_file
Normal file
@ -0,0 +1,5 @@
|
||||
function wait_for_file {
|
||||
FILE=$1
|
||||
|
||||
while [ ! -f ${FILE} ]; do sleep 1; done
|
||||
}
|
12
scripts/functions/wait_for_pool_registration
Normal file
12
scripts/functions/wait_for_pool_registration
Normal file
@ -0,0 +1,12 @@
|
||||
function wait_for_pool_registration {
|
||||
source /scripts/functions/check_pool_registration
|
||||
|
||||
echo "Waiting for the blockchain to register the pool."
|
||||
while true; do
|
||||
if [ -n "$(check_pool_registration)" ]; then
|
||||
break
|
||||
fi
|
||||
echo "Blockchain has not yet registered the pool. Waiting.."
|
||||
sleep 10
|
||||
done
|
||||
}
|
15
scripts/functions/wait_for_slot
Normal file
15
scripts/functions/wait_for_slot
Normal file
@ -0,0 +1,15 @@
|
||||
function wait_for_slot {
|
||||
WAIT_FOR_SLOT=$1
|
||||
|
||||
echo "Waiting for slot ${WAIT_FOR_SLOT}"
|
||||
while true; do
|
||||
SLOT=$(get_slot)
|
||||
|
||||
if [ "$SLOT" -ge "$WAIT_FOR_SLOT" ]; then
|
||||
echo "Reached slot ${WAIT_FOR_SLOT}"
|
||||
break
|
||||
fi
|
||||
echo "Slot: ${SLOT}/${WAIT_FOR_SLOT}"
|
||||
sleep 10
|
||||
done
|
||||
}
|
17
scripts/functions/wait_for_socket
Normal file
17
scripts/functions/wait_for_socket
Normal file
@ -0,0 +1,17 @@
|
||||
function wait_for_socket {
|
||||
source /scripts/init_node_vars
|
||||
|
||||
while true; do
|
||||
OUT=$(get_slot)
|
||||
if [[ -z "$OUT" ]]; then
|
||||
echo ""
|
||||
echo "Waiting for cardano-node to read the blockchain and start the socket. May take a while."
|
||||
echo "Trying again..."
|
||||
|
||||
sleep 10
|
||||
else
|
||||
echo "Socket to node is functional."
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
16
scripts/functions/wait_for_sync
Normal file
16
scripts/functions/wait_for_sync
Normal file
@ -0,0 +1,16 @@
|
||||
function wait_for_sync {
|
||||
source /scripts/functions/wait_for_socket
|
||||
wait_for_socket
|
||||
WAIT_FOR_SYNC=$1
|
||||
|
||||
echo "Waiting for node to sync to atleast ${WAIT_FOR_SYNC}%"
|
||||
while true; do
|
||||
SYNC_PCT=$(sync_status | tr ' ' '\n' | tail -1 | sed 's/%//g' | bc)
|
||||
sync_status
|
||||
if [[ (($SYNC_PCT > $WAIT_FOR_SYNC)) ]]; then
|
||||
echo "Reached ${SYNC_PCT}%"
|
||||
break
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
}
|
111
scripts/generate_operational_certificate
Normal file
111
scripts/generate_operational_certificate
Normal file
@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
|
||||
# From Documentation
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/060_node_keys.md
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/080_register_stakepool.md
|
||||
|
||||
# Init vars
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/wait_for_sync
|
||||
|
||||
# Enter staking directory
|
||||
mkdir -p ${NODE_PATH}/staking/pool-keys
|
||||
mkdir -p ${NODE_PATH}/staking/cold-keys
|
||||
cd ${NODE_PATH}/staking/
|
||||
|
||||
echo ""
|
||||
echo "Generate operational certificates"
|
||||
|
||||
if [ -d "pool-keys/" ]; then
|
||||
source pool-keys/KESPERIOD
|
||||
BACKUPNAME=pool-keys.$(date +%s).tar.gz
|
||||
echo "pool-keys already exist."
|
||||
echo "Created at slot: ${KESSLOT}"
|
||||
echo "Backing up to ${BACKUPNAME} before creating new KES keys."
|
||||
mkdir -p ../backups/
|
||||
tar -zcvf ../backups/${BACKUPNAME} pool-keys/ > /dev/null
|
||||
fi
|
||||
|
||||
if [ -d "cold-keys/" ]; then
|
||||
BACKUPNAME=cold-keys.$(date +%s).tar.gz
|
||||
echo "Backing up to ${BACKUPNAME} before creating new KES keys."
|
||||
mkdir -p ../backups/
|
||||
tar -zcvf ../backups/${BACKUPNAME} cold-keys/ > /dev/null
|
||||
fi
|
||||
|
||||
# Create cold key
|
||||
if [ ! -f "cold-keys/cold.skey" ]; then
|
||||
echo "Creating cold keys."
|
||||
echo "Warning: The cold keys should NOT be kept on your server. You should backup your cold keys and delete them from the server."
|
||||
echo "Alternatively you can generate the keys on a seperate offline node, and move all the neccessary certificates and keys to the active staking node."
|
||||
|
||||
cardano-cli node key-gen \
|
||||
--cold-verification-key-file cold-keys/cold.vkey \
|
||||
--cold-signing-key-file cold-keys/cold.skey \
|
||||
--operational-certificate-issue-counter-file cold-keys/cold.counter
|
||||
|
||||
cardano-cli stake-pool id --verification-key-file cold-keys/cold.vkey > ${NODE_PATH}/staking/POOL_ID
|
||||
else
|
||||
echo "Cold keys already exists."
|
||||
fi
|
||||
|
||||
# Create Verifiable Random Function key
|
||||
if [ ! -f "pool-keys/vrf.vkey" ]; then
|
||||
echo "Generating VRF key"
|
||||
cardano-cli node key-gen-VRF \
|
||||
--verification-key-file pool-keys/vrf.vkey \
|
||||
--signing-key-file pool-keys/vrf.skey
|
||||
fi
|
||||
|
||||
# Create Key Evolving Signature key
|
||||
if [ ! -f "pool-keys/kes.vkey" ]; then
|
||||
echo "Generating KES key"
|
||||
cardano-cli node key-gen-KES \
|
||||
--verification-key-file pool-keys/kes.vkey \
|
||||
--signing-key-file pool-keys/kes.skey
|
||||
fi
|
||||
|
||||
# Get tip
|
||||
TIP=$1
|
||||
if [ -z "$TIP" ]; then
|
||||
echo "You need to find the current tip of the blockchain. To get the current tip you can run the command \`get_slot\` in the your relay container."
|
||||
read -p "Enter the current tip slot: " TIP
|
||||
elif [ "$TIP" == "LIVE" ]; then
|
||||
echo "Getting slot from live socket"
|
||||
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
TIP=$(get_slot)
|
||||
fi
|
||||
|
||||
# Get KESPeriod
|
||||
SLOTSPERKESPERIOD=$(jq -r '.slotsPerKESPeriod' ${NODE_PATH}/shelley-genesis.json)
|
||||
MAXKESEVOLUTIONS=$(jq -r '.maxKESEvolutions' ${NODE_PATH}/shelley-genesis.json)
|
||||
MAXKESSLOTS=$(expr ${SLOTSPERKESPERIOD} \* ${MAXKESEVOLUTIONS})
|
||||
KESPERIOD=$(expr ${TIP} / ${SLOTSPERKESPERIOD})
|
||||
#KESPERIOD=$(expr ${KESPERIOD} - 1) # Because of bug in 1.19.0
|
||||
EXPIRESLOT=$(expr ${TIP} + ${MAXKESSLOTS})
|
||||
echo "export SLOTSPERKESPERIOD=${SLOTSPERKESPERIOD}" > pool-keys/KESPERIOD
|
||||
echo "export KESSLOT=${TIP}" >> pool-keys/KESPERIOD
|
||||
echo "export MAXKESEVOLUTIONS=${MAXKESEVOLUTIONS}" >> pool-keys/KESPERIOD
|
||||
echo "export MAXKESSLOTS=${MAXKESSLOTS}" >> pool-keys/KESPERIOD
|
||||
echo "export KESPERIOD=${KESPERIOD}" >> pool-keys/KESPERIOD
|
||||
echo "export EXPIRESLOT=${EXPIRESLOT}" >> pool-keys/KESPERIOD
|
||||
|
||||
echo "Current slot: ${TIP}"
|
||||
echo "slotsPerKesPeriod: ${SLOTSPERKESPERIOD}"
|
||||
echo "KESPeriod: ${KESPERIOD}"
|
||||
echo "MaxKESSlots: ${MAXKESSLOTS}"
|
||||
echo "KESExpireSlot: ${EXPIRESLOT}"
|
||||
|
||||
# Create an operational node certificate
|
||||
cardano-cli node issue-op-cert \
|
||||
--kes-verification-key-file pool-keys/kes.vkey \
|
||||
--cold-signing-key-file cold-keys/cold.skey \
|
||||
--operational-certificate-issue-counter cold-keys/cold.counter \
|
||||
--kes-period ${KESPERIOD} \
|
||||
--out-file pool-keys/node.cert
|
||||
|
||||
echo "Successfully created node operational keys."
|
167
scripts/generate_registration_certificates
Normal file
167
scripts/generate_registration_certificates
Normal file
@ -0,0 +1,167 @@
|
||||
#!/bin/bash
|
||||
|
||||
# From Documentation
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/ecbfd0ec06e0515701ee3749ce96780c27d2249d/node-setup/080_register_stakepool.md
|
||||
|
||||
# Init vars
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/get_public_ip
|
||||
source /scripts/functions/stakepool_info
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
# Enter staking directory
|
||||
cd ${NODE_PATH}/staking/
|
||||
|
||||
echo ""
|
||||
echo "Generate registration certificates"
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "wallets/owner/stake.vkey" ]; then
|
||||
echo "Missing required staking/stake.vkey. You need to run \`generate_waller owner\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "cold-keys/cold.vkey" ]; then
|
||||
echo "Missing required staking/cold-keys/cold.vkey. You need to run \`generate_operational_certificate\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "pool-keys/vrf.vkey" ]; then
|
||||
echo "Missing required staking/pool-keys/vrf.vkey. You need to run \`generate_operational_certificate\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -z "$METADATA_URL" ]; then
|
||||
echo "Missing METADATA_URL You need to upload your metadata.json file at pass the URL to the METADATA_URL variable."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Handle arguments
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
--update)
|
||||
UPDATE_CERT=1
|
||||
;;
|
||||
--cold-create)
|
||||
COLD_CREATE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 1. Create a JSON file with your pool's metadata
|
||||
if [ ! -f "metadata.json" ] || [ -n "$UPDATE_CERT" ]; then
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
echo "Getting metadata file from ${METADATA_URL}"
|
||||
wget -O metadata.json ${METADATA_URL}
|
||||
else
|
||||
read -n 1 -r -s -p "Missing ${NODE_PATH}/staking/metadata.json. Please add this file, and ENTER when you have placed the file and are ready to continue."
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2. get hash of file
|
||||
echo "Getting hash of metadata.json"
|
||||
METADATA_HASH=$(cardano-cli stake-pool metadata-hash --pool-metadata-file metadata.json)
|
||||
echo "metadata.json hash: ${METADATA_HASH}"
|
||||
|
||||
# 3. Generate Stake pool registration certificate
|
||||
if [ ! -f "pool.cert" ] || [ -n "$UPDATE_CERT" ]; then
|
||||
if [ -f "pool.cert" ]; then
|
||||
echo "backing up pool.cert."
|
||||
cp pool.cert pool.${TIMESTAMP}.cert
|
||||
fi
|
||||
|
||||
if [ "${PUBLIC_RELAY_IP}" == "TOPOLOGY" ]; then
|
||||
PUBLIC_RELAY_IP=$(jq -r ".Producers[0].addr" ${NODE_PATH}/topology.json)
|
||||
PUBLIC_RELAY_PORT=$(jq -r ".Producers[0].port" ${NODE_PATH}/topology.json)
|
||||
fi
|
||||
if [ "${PUBLIC_RELAY_IP}" == "PUBLIC" ]; then
|
||||
PUBLIC_RELAY_IP=$(get_public_ip)
|
||||
fi
|
||||
if [ -z "$PUBLIC_RELAY_PORT" ]; then
|
||||
PUBLIC_RELAY_PORT=$(jq -r ".Producers[0].port" ${NODE_PATH}/topology.json)
|
||||
fi
|
||||
|
||||
echo "Generating pool.cert"
|
||||
stakepool_info
|
||||
echo "Public Relay IP: ${PUBLIC_RELAY_IP}"
|
||||
echo "Public Relay Port: ${PUBLIC_RELAY_PORT}"
|
||||
|
||||
# Multiple owners
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
echo "Multiple owners"
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
echo "$i"
|
||||
MULTIOWNERS_STRING="${MULTIOWNERS_STRING} --pool-owner-stake-verification-key-file wallets/${i}/stake.vkey"
|
||||
done
|
||||
echo $MULTIOWNERS_STRING
|
||||
echo ""
|
||||
fi
|
||||
|
||||
cardano-cli stake-pool registration-certificate \
|
||||
--cold-verification-key-file cold-keys/cold.vkey \
|
||||
--vrf-verification-key-file pool-keys/vrf.vkey \
|
||||
--pool-pledge ${POOL_PLEDGE} \
|
||||
--pool-cost ${POOL_COST} \
|
||||
--pool-margin ${POOL_MARGIN} \
|
||||
--pool-reward-account-verification-key-file wallets/owner/stake.vkey \
|
||||
--pool-owner-stake-verification-key-file wallets/owner/stake.vkey \
|
||||
${MULTIOWNERS_STRING} \
|
||||
--pool-relay-port ${PUBLIC_RELAY_PORT} \
|
||||
--pool-relay-ipv4 ${PUBLIC_RELAY_IP} \
|
||||
--metadata-url ${METADATA_URL} \
|
||||
--metadata-hash ${METADATA_HASH} \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--out-file pool.cert \
|
||||
&& echo "Generated pool.cert"
|
||||
|
||||
PAYMENT_ADDR=$(cat ${NODE_PATH}/staking/wallets/owner/payment.addr)
|
||||
STAKE_ADDR=$(cat ${NODE_PATH}/staking/wallets/owner/stake.addr)
|
||||
POOL_ID=$(cat ${NODE_PATH}/staking/POOL_ID)
|
||||
|
||||
echo "export POOL_PLEDGE=${POOL_PLEDGE}" > POOL_VARS
|
||||
echo "export POOL_COST=${POOL_COST}" >> POOL_VARS
|
||||
echo "export POOL_MARGIN=${POOL_MARGIN}" >> POOL_VARS
|
||||
echo "export POOL_MARGIN=${POOL_MARGIN}" >> POOL_VARS
|
||||
echo "export PAYMENT_ADDR=${PAYMENT_ADDR}" >> POOL_VARS
|
||||
echo "export STAKE_ADDR=${STAKE_ADDR}" >> POOL_VARS
|
||||
echo "export POOL_ID=${POOL_ID}" >> POOL_VARS
|
||||
echo "export MULTI_OWNERS=${MULTI_OWNERS}" >> POOL_VARS
|
||||
echo ""
|
||||
else
|
||||
echo "pool.cert already exists."
|
||||
fi
|
||||
|
||||
# 2. Generate delegation certificate (pledge)
|
||||
if [ ! -f "wallets/owner/delegation.cert" ]; then
|
||||
cardano-cli stake-address delegation-certificate \
|
||||
--stake-verification-key-file wallets/owner/stake.vkey \
|
||||
--cold-verification-key-file cold-keys/cold.vkey \
|
||||
--out-file wallets/owner/delegation.cert \
|
||||
&& echo "Generated delegation.cert"
|
||||
else
|
||||
echo "delegation.cert already exists."
|
||||
fi
|
||||
|
||||
# Multiple owners
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
echo "Generating delegation certificates for multiple owners"
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
echo "- $i"
|
||||
if [ ! -f "wallets/$i/delegation.cert" ]; then
|
||||
cardano-cli stake-address delegation-certificate \
|
||||
--stake-verification-key-file wallets/$i/stake.vkey \
|
||||
--cold-verification-key-file cold-keys/cold.vkey \
|
||||
--out-file wallets/$i/delegation.cert \
|
||||
&& echo "Generated delegation.cert"
|
||||
else
|
||||
echo "-- delegation.cert already exists."
|
||||
fi
|
||||
done
|
||||
fi
|
66
scripts/generate_wallet
Normal file
66
scripts/generate_wallet
Normal file
@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Following guide:
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/020_keys_and_addresses.md
|
||||
|
||||
# Init node vars
|
||||
source /scripts/init_node_vars
|
||||
|
||||
WALLET=$1
|
||||
mkdir -p ${NODE_PATH}/staking/wallets/${WALLET}
|
||||
cd ${NODE_PATH}/staking/wallets/${WALLET}
|
||||
|
||||
echo ""
|
||||
echo "Generate stake addresses"
|
||||
|
||||
# Generate key & address
|
||||
## Generate Payment key pair
|
||||
if [ ! -f "payment.skey" ]; then
|
||||
cardano-cli address key-gen \
|
||||
--verification-key-file payment.vkey \
|
||||
--signing-key-file payment.skey
|
||||
echo "Generated payment.vkey and payment.skey."
|
||||
else
|
||||
echo "Payment key pair already exists."
|
||||
fi
|
||||
|
||||
## Generate Stake key pair
|
||||
if [ ! -f "stake.skey" ]; then
|
||||
cardano-cli stake-address key-gen \
|
||||
--verification-key-file stake.vkey \
|
||||
--signing-key-file stake.skey
|
||||
echo "Generated stake.vkey and stake.skey."
|
||||
else
|
||||
|
||||
echo "Stake key pair already exists."
|
||||
fi
|
||||
|
||||
## Generate Payment address
|
||||
if [ ! -f "payment.addr" ]; then
|
||||
cardano-cli address build \
|
||||
--payment-verification-key-file payment.vkey \
|
||||
--stake-verification-key-file stake.vkey \
|
||||
--out-file payment.addr \
|
||||
--mainnet
|
||||
echo "Generated payment.addr."
|
||||
PAYMENT_ADDR=$(cat payment.addr)
|
||||
echo "Payment address: ${PAYMENT_ADDR}."
|
||||
else
|
||||
PAYMENT_ADDR=$(cat payment.addr)
|
||||
echo "Payment address already exists: ${PAYMENT_ADDR}."
|
||||
fi
|
||||
|
||||
## Generate Stake address
|
||||
if [ ! -f "stake.addr" ]; then
|
||||
cardano-cli stake-address build \
|
||||
--stake-verification-key-file stake.vkey \
|
||||
--out-file stake.addr \
|
||||
--mainnet
|
||||
|
||||
echo "Generated stake.addr."
|
||||
STAKE_ADDR=$(cat stake.addr)
|
||||
echo "Stake address: ${STAKE_ADDR}."
|
||||
else
|
||||
STAKE_ADDR=$(cat stake.addr)
|
||||
echo "Stake address already exists: ${STAKE_ADDR}."
|
||||
fi
|
10
scripts/get_topology_str.py
Normal file
10
scripts/get_topology_str.py
Normal file
@ -0,0 +1,10 @@
|
||||
import os
|
||||
from init_config import parse_topology_str
|
||||
|
||||
if __name__ == '__main__':
|
||||
topology = parse_topology_str(os.environ.get('NODE_TOPOLOGY', ''))
|
||||
|
||||
_topology = []
|
||||
for t in topology:
|
||||
_topology.append('%s:%s:%s' % (t.get('addr'), t.get('port'), t.get('valency')))
|
||||
print('|'.join(_topology))
|
166
scripts/init_config.py
Normal file
166
scripts/init_config.py
Normal file
@ -0,0 +1,166 @@
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
import argparse
|
||||
import json
|
||||
import socket
|
||||
import time
|
||||
|
||||
CONFIG_TEMPLATES_ROOT_PATH = '/cfg-templates/'
|
||||
CONFIG_OUTPUT_ROOT_PATH = '/config/'
|
||||
|
||||
def slugify(value):
|
||||
"""
|
||||
Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||
and converts spaces to hyphens.
|
||||
"""
|
||||
value = re.sub('[^-a-zA-Z0-9_.]+', '', value)
|
||||
|
||||
return value
|
||||
|
||||
def str2bool(v:str):
|
||||
"""Converts string to boolean"""
|
||||
return v.lower() in ('yes', 'true', 't', '1')
|
||||
|
||||
def save_json(path:str, data):
|
||||
with open(path, 'w') as outfile:
|
||||
json.dump(data, outfile, indent=1)
|
||||
|
||||
def load_json(path:str):
|
||||
with open(path, 'r') as inputfile:
|
||||
return json.load(inputfile)
|
||||
|
||||
def init_args():
|
||||
# Parse arguments
|
||||
parser = argparse.ArgumentParser(description='Cardano Configurator')
|
||||
parser.add_argument('--node-port', dest='node_port', help='Port of node. Defaults to 3000.', type=int, default=os.environ.get('NODE_PORT', 3000))
|
||||
parser.add_argument('--node-name', dest='name', help='Name of node. Defaults to node1.', type=slugify, default=os.environ.get('NODE_NAME', 'node1'))
|
||||
parser.add_argument('--node-topology', dest='topology', help='Topology of the node. Should be comma separated for each individual node to add, on the form: <ip>:<port>/<valency>. So for example: 127.0.0.1:3001/1,127.0.0.1:3002/1.', type=str, default=os.environ.get('NODE_TOPOLOGY', ''))
|
||||
parser.add_argument('--node-relay', dest='relay', help='Set to 1 if default IOHK relay should be added to the network topology.', type=str2bool, default=os.environ.get('NODE_RELAY', False))
|
||||
parser.add_argument('--cardano-network', dest='network', help='Carano network to use (main, test, pioneer). Defaults to main.', type=str, default=os.environ.get('CARDANO_NETWORK', 'main'))
|
||||
parser.add_argument('--ekg-port', dest='ekg_port', help='Port of EKG monitoring. Defaults to 12788.', type=int, default=os.environ.get('EKG_PORT', 12788))
|
||||
parser.add_argument('--prometheus-host', dest='prometheus_host', help='Host of Prometheus monitoring. Defaults to 127.0.0.1.', type=str, default=os.environ.get('PROMETHEUS_HOST', '127.0.0.1'))
|
||||
parser.add_argument('--prometheus-port', dest='prometheus_port', help='Port of Prometheus monitoring. Defaults to 12798.', type=int, default=os.environ.get('PROMETHEUS_PORT', 12798))
|
||||
parser.add_argument('--resolve-hostnames', dest='resolve_hostnames', help='Resolve hostnames in topology to IP-addresses.', type=str2bool, default=os.environ.get('RESOLVE_HOSTNAMES', False))
|
||||
parser.add_argument('--replace-existing', dest='replace_existing', help='Replace existing configs.', type=str2bool, default=os.environ.get('REPLACE_EXISTING_CONFIG', False))
|
||||
args = parser.parse_args()
|
||||
|
||||
# Init network specific paths
|
||||
args.CONFIG_TEMPLATES_PATH = os.path.join(CONFIG_TEMPLATES_ROOT_PATH, args.network)
|
||||
CONFIG_NAME = args.network+'-'+args.name
|
||||
args.CONFIG_OUTPUT_PATH = os.path.join(CONFIG_OUTPUT_ROOT_PATH, CONFIG_NAME)
|
||||
args.BYRON_GENESIS_PATH = os.path.join(args.CONFIG_OUTPUT_PATH, 'byron-genesis.json')
|
||||
args.SHELLEY_GENESIS_PATH = os.path.join(args.CONFIG_OUTPUT_PATH, 'shelley-genesis.json')
|
||||
args.TOPOLOGY_PATH = os.path.join(args.CONFIG_OUTPUT_PATH, 'topology.json')
|
||||
args.CONFIG_PATH = os.path.join(args.CONFIG_OUTPUT_PATH, 'config.json')
|
||||
args.VARS_PATH = os.path.join(args.CONFIG_OUTPUT_PATH, 'VARS')
|
||||
|
||||
return args
|
||||
|
||||
def init_folder(args):
|
||||
"""Creates network/node config folders"""
|
||||
if not os.path.exists(args.CONFIG_OUTPUT_PATH):
|
||||
os.makedirs(args.CONFIG_OUTPUT_PATH)
|
||||
|
||||
def init_genesis(args):
|
||||
"""Initializes the genesis file"""
|
||||
|
||||
SHELLEY_SRC = os.path.join(args.CONFIG_TEMPLATES_PATH, 'shelley-genesis.json')
|
||||
BYRON_SRC = os.path.join(args.CONFIG_TEMPLATES_PATH, 'byron-genesis.json')
|
||||
|
||||
if not os.path.exists(args.SHELLEY_GENESIS_PATH) or args.replace_existing:
|
||||
print('Generating new shelley genesis file %s from template %s' % (args.SHELLEY_GENESIS_PATH, SHELLEY_SRC))
|
||||
shutil.copy(SHELLEY_SRC, args.SHELLEY_GENESIS_PATH)
|
||||
|
||||
if not os.path.exists(args.BYRON_GENESIS_PATH) or args.replace_existing:
|
||||
print('Generating new byron genesis file %s from template %s' % (args.BYRON_GENESIS_PATH, BYRON_SRC))
|
||||
shutil.copy(BYRON_SRC, args.BYRON_GENESIS_PATH)
|
||||
|
||||
|
||||
def resolve_hostname(hostname, tries=0):
|
||||
"""Resolve IP from hostname"""
|
||||
try:
|
||||
return socket.gethostbyname(hostname)
|
||||
except:
|
||||
if tries<10:
|
||||
time.sleep(1)
|
||||
|
||||
return resolve_hostname(hostname, tries=tries+1)
|
||||
else:
|
||||
return hostname
|
||||
|
||||
def parse_topology_str(s) -> list:
|
||||
"""Parses node-topology string and returns list of dicts"""
|
||||
topology = []
|
||||
|
||||
if s:
|
||||
for a in s.split(','):
|
||||
(ip_port, valency) = a.split('/')
|
||||
(ip, port) = ip_port.split(':')
|
||||
|
||||
#if resolve_hostname: ip = resolve_hostname(ip)
|
||||
|
||||
topology.append({
|
||||
'addr': str(ip),
|
||||
'port': int(port),
|
||||
'valency': int(valency)
|
||||
})
|
||||
|
||||
return topology
|
||||
|
||||
|
||||
def init_topology(args):
|
||||
"""Initializes the topology file"""
|
||||
|
||||
if args.relay:
|
||||
INPUT_PATH = os.path.join(args.CONFIG_TEMPLATES_PATH, 'topology-relay.json')
|
||||
else:
|
||||
INPUT_PATH = os.path.join(args.CONFIG_TEMPLATES_PATH, 'topology.json')
|
||||
|
||||
if not os.path.exists(args.TOPOLOGY_PATH) or args.replace_existing:
|
||||
print('Generating new topology %s from template %s' % (args.TOPOLOGY_PATH, INPUT_PATH))
|
||||
print('Topology: ', args.topology)
|
||||
|
||||
# Load template file
|
||||
data = load_json(INPUT_PATH)
|
||||
|
||||
# Parse topology string
|
||||
topology = parse_topology_str(args.topology)
|
||||
|
||||
# Add default IOHK relay
|
||||
|
||||
data['Producers'] = data['Producers']+topology
|
||||
save_json(args.TOPOLOGY_PATH, data)
|
||||
|
||||
def init_config(args):
|
||||
"""Initializes the config file"""
|
||||
|
||||
INPUT_PATH = os.path.join(args.CONFIG_TEMPLATES_PATH, 'config.json')
|
||||
|
||||
if not os.path.exists(args.CONFIG_PATH) or args.replace_existing:
|
||||
print('Generating new config file %s from template %s' % (args.CONFIG_PATH, INPUT_PATH))
|
||||
|
||||
data = load_json(INPUT_PATH)
|
||||
data['hasEKG'] = args.ekg_port
|
||||
data['hasPrometheus'] = [args.prometheus_host, args.prometheus_port]
|
||||
data['ShelleyGenesisFile'] = args.SHELLEY_GENESIS_PATH
|
||||
data['ByronGenesisFile'] = args.BYRON_GENESIS_PATH
|
||||
save_json(args.CONFIG_PATH, data)
|
||||
|
||||
def init_vars(args):
|
||||
INPUT_PATH = os.path.join(args.CONFIG_TEMPLATES_PATH, 'VARS')
|
||||
|
||||
if not os.path.exists(args.VARS_PATH) or args.replace_existing:
|
||||
print('Generating new VARS %s from template %s' % (args.VARS_PATH, INPUT_PATH))
|
||||
|
||||
# Just copy it
|
||||
shutil.copy(INPUT_PATH, args.VARS_PATH)
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = init_args()
|
||||
|
||||
init_folder(args)
|
||||
init_genesis(args)
|
||||
init_topology(args)
|
||||
init_config(args)
|
||||
init_vars(args)
|
7
scripts/init_node_vars
Normal file
7
scripts/init_node_vars
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
export NODE_PATH=/config/${CARDANO_NETWORK}-${NODE_NAME}/
|
||||
if [[ "${CARDANO_NODE_SOCKET_PATH}" == "DEFAULT" ]]; then
|
||||
export CARDANO_NODE_SOCKET_PATH=${NODE_PATH}node.socket
|
||||
fi
|
||||
source ${NODE_PATH}VARS
|
26
scripts/leaderlogs.sh
Normal file
26
scripts/leaderlogs.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/init_node_vars
|
||||
|
||||
# Init vars
|
||||
POOL_ID=$(cat ${NODE_PATH}staking/POOL_ID)
|
||||
TZ=$(cat /etc/timezone)
|
||||
VRF=${NODE_PATH}staking/pool-keys/vrf.skey
|
||||
|
||||
echo "Dumping ledger.json"
|
||||
cardano-cli query ledger-state --allegra-era ${NETWORK_ARGUMENT} --out-file ${NODE_PATH}ledger.json
|
||||
|
||||
echo "Calculating sigma"
|
||||
SIGMA=$(python3 /scripts/pooltool.io/leaderLogs/getSigma.py --pool-id ${POOL_ID} --ledger ${NODE_PATH}ledger.json | tail -1 | awk '{print $2}')
|
||||
|
||||
# Print vars
|
||||
echo "POOL_ID: ${SIGMA}"
|
||||
echo "TZ: ${TZ}"
|
||||
echo "VRF: ${VRF}"
|
||||
echo "SIGMA: ${SIGMA}"
|
||||
|
||||
# Get leaderlogs
|
||||
python3 /scripts/pooltool.io/leaderLogs/leaderLogs.py \
|
||||
--vrf-skey ${VRF} \
|
||||
--sigma ${SIGMA} \
|
||||
--tz ${TZ}
|
195
scripts/register_stake_address
Normal file
195
scripts/register_stake_address
Normal file
@ -0,0 +1,195 @@
|
||||
#!/bin/bash
|
||||
|
||||
# From Documentation
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/040_transactions.md
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/050_register_key.md
|
||||
|
||||
# Init functions and vars
|
||||
|
||||
source /scripts/functions/check_balance
|
||||
source /scripts/functions/check_address_registration
|
||||
source /scripts/functions/wait_for_address_registration
|
||||
source /scripts/functions/wait_for_slot
|
||||
source /scripts/functions/wait_for_sync
|
||||
source /scripts/init_node_vars
|
||||
|
||||
# Define wallet
|
||||
WALLET=$1
|
||||
|
||||
if [ -z "$WALLET" ]; then
|
||||
echo "Wallet is undefined."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Enter staking directory
|
||||
cd ${NODE_PATH}/staking/wallets/${WALLET}
|
||||
STAKE_ADDR=$(cat ${NODE_PATH}/staking/wallets/${WALLET}/stake.addr)
|
||||
|
||||
echo ""
|
||||
echo "Submitting staking addresses for $WALLET to the blockchain."
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "stake.vkey" ]; then
|
||||
echo "Missing required wallets/${WALLET}/stake.vkey. You need to run \`generate_wallet ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "stake.skey" ]; then
|
||||
echo "Missing required wallets/${WALLET}/stake.skey. You need to run \`generate_wallet ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "payment.skey" ]; then
|
||||
echo "Missing required wallets/${WALLET}/payment.skey. You need to run \`generate_wallet ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "payment.addr" ]; then
|
||||
echo "Missing required wallets/${WALLET}/payment.addr. You need to run \`generate_wallet ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Handle arguments
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
--cold-create)
|
||||
COLD_CREATE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p transactions
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
if [ -n "$(check_address_registration ${STAKE_ADDR})" ]; then
|
||||
echo "Your stake address has already been registered in the blockchain."
|
||||
touch transactions/register_stake_address.submitted
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create an address registration certificate
|
||||
if [ ! -f "stake.cert" ]; then
|
||||
cardano-cli stake-address registration-certificate \
|
||||
--staking-verification-key-file stake.vkey \
|
||||
--out-file stake.cert
|
||||
echo "Created stake.cert"
|
||||
else
|
||||
echo "stake.cert certificate already exists."
|
||||
fi
|
||||
|
||||
# Generate protocol
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
cardano-cli query protocol-parameters \
|
||||
${NETWORK_ARGUMENT} --allegra-era \
|
||||
--out-file ${NODE_PATH}/staking/protocol.json
|
||||
else
|
||||
if [ ! -f "${NODE_PATH}/staking/protocol.json" ]; then
|
||||
read -n 1 -r -s -p "Missing ${NODE_PATH}/staking/protocol.json. You must transfer this file from an online node. Press ENTER when you have placed the file and are ready to continue."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get key-deposit
|
||||
KEY_DEPOSIT=$(jq -r .keyDeposit ${NODE_PATH}/staking/protocol.json)
|
||||
POOL_DEPOSIT=$(jq -r .poolDeposit ${NODE_PATH}/staking/protocol.json)
|
||||
MIN_HOLDING=$(expr $KEY_DEPOSIT + $POOL_DEPOSIT + $POOL_PLEDGE)
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
ADDRESS=$(cat payment.addr)
|
||||
check_balance ${KEY_DEPOSIT}
|
||||
|
||||
# Draft transaction
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+0 \
|
||||
--ttl 0 \
|
||||
--fee 0 \
|
||||
--out-file transactions/register_stake_address.draft \
|
||||
--certificate-file stake.cert
|
||||
|
||||
# Calculate fees
|
||||
FEE=$(cardano-cli transaction calculate-min-fee \
|
||||
--tx-body-file transactions/register_stake_address.draft \
|
||||
--tx-in-count 1 \
|
||||
--tx-out-count 1 \
|
||||
--witness-count 1 \
|
||||
--byron-witness-count 0 \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--protocol-params-file ${NODE_PATH}/staking/protocol.json | tr ' ' '\n' | head -1)
|
||||
|
||||
TOTAL_PRICE=$(expr ${FEE} + ${KEY_DEPOSIT})
|
||||
echo "Fee is: ${FEE} Lovelace"
|
||||
echo "Key-Deposit: ${KEY_DEPOSIT} Lovelace"
|
||||
echo "Total Price is: ${TOTAL_PRICE}"
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
check_balance ${TOTAL_PRICE}
|
||||
SLOT=$(get_slot)
|
||||
else
|
||||
read -p "Enter the current tip slot: " SLOT
|
||||
fi
|
||||
|
||||
# Get slot and TTL
|
||||
TTL=$(expr ${SLOT} + 500)
|
||||
|
||||
# Display transaction info
|
||||
REMAINING_AFTER_TX=$(expr ${LOVELACE} - ${TOTAL_PRICE})
|
||||
echo "Creating transaction"
|
||||
echo "Lovelace after transaction: ${REMAINING_AFTER_TX}"
|
||||
echo "Current slot: ${SLOT}"
|
||||
echo "TTL: ${TTL}"
|
||||
|
||||
#
|
||||
# Create the transaction
|
||||
#
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+${REMAINING_AFTER_TX} \
|
||||
--ttl ${TTL} \
|
||||
--fee ${FEE} \
|
||||
--out-file transactions/register_stake_address.raw \
|
||||
--certificate-file stake.cert
|
||||
|
||||
# Sign the transaction
|
||||
cardano-cli transaction sign \
|
||||
--tx-body-file transactions/register_stake_address.raw \
|
||||
--signing-key-file payment.skey \
|
||||
--signing-key-file stake.skey \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--out-file transactions/register_stake_address.signed
|
||||
|
||||
|
||||
# Submit the transaction
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
read -n 1 -r -s -p $'Press enter to submit the stake address certificate...\n'
|
||||
|
||||
OUT=$(cardano-cli transaction submit \
|
||||
--tx-file transactions/register_stake_address.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
|
||||
# Wait for blockchain to register the address
|
||||
wait_for_slot ${TTL}
|
||||
wait_for_address_registration ${STAKE_ADDR}
|
||||
echo "Your stake address is now registered in the blockchain."
|
||||
touch transactions/register_stake_address.submitted
|
||||
fi
|
||||
fi
|
225
scripts/register_stake_pool
Normal file
225
scripts/register_stake_pool
Normal file
@ -0,0 +1,225 @@
|
||||
#!/bin/bash
|
||||
|
||||
# From Documentation
|
||||
# https://github.com/input-output-hk/cardano-tutorials/blob/master/node-setup/080_register_stakepool.md
|
||||
|
||||
# Init vars
|
||||
source /scripts/functions/check_balance
|
||||
source /scripts/functions/check_pool_registration
|
||||
source /scripts/functions/wait_for_pool_registration
|
||||
source /scripts/functions/wait_for_slot
|
||||
source /scripts/functions/wait_for_sync
|
||||
source /scripts/init_node_vars
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
# Enter staking directory
|
||||
cd ${NODE_PATH}/staking/
|
||||
mkdir -p wallets/owner/transactions
|
||||
|
||||
echo ""
|
||||
echo "Submitting stake pool certificates to the blockchain."
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "wallets/owner/stake.skey" ]; then
|
||||
echo "Missing required wallets/${WALLET}/stake.skey. You need to run \`generate_waller owner\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "wallets/owner/payment.skey" ]; then
|
||||
echo "Missing required wallets/${WALLET}/payment.skey. You need to run \`generate_waller owner\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "wallets/owner/payment.addr" ]; then
|
||||
echo "Missing required wallets/${WALLET}/payment.addr. You need to run \`generate_waller owner\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "cold-keys/cold.skey" ]; then
|
||||
echo "Missing required staking/cold-keys/cold.skey. You need to run \`generate_operational_certificate\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "pool.cert" ]; then
|
||||
echo "Missing required staking/pool.cert. You need to run \`generate_registration_certificate\` to generate this certificate."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "wallets/owner/delegation.cert" ]; then
|
||||
echo "Missing required staking/wallets/owner/delegation.cert. You need to run \`generate_registration_certificate\` to generate this certificate."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Handle arguments
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
--update)
|
||||
UPDATE=1
|
||||
;;
|
||||
--no_deleg)
|
||||
NO_DELEG=1
|
||||
;;
|
||||
--cold-create)
|
||||
COLD_CREATE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
EXTRA_FEE=9000
|
||||
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
if [ -z "$UPDATE" ]; then
|
||||
if [ -n "$(check_pool_registration)" ]; then
|
||||
echo "Your stake pool has already been registered in the blockchain."
|
||||
touch ${NODE_PATH}/staking/wallets/owner/transactions/register_stake_pool.submitted
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if [ -z "$(check_pool_registration)" ]; then
|
||||
echo "Pool is not registered in the blockchain. You cannot update the certificates. Register the stakepool first."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
# Generate protocol
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
cardano-cli query protocol-parameters \
|
||||
${NETWORK_ARGUMENT} --allegra-era \
|
||||
--out-file ${NODE_PATH}/staking/protocol.json
|
||||
else
|
||||
if [ ! -f "${NODE_PATH}/staking/protocol.json" ]; then
|
||||
read -n 1 -r -s -p "Missing ${NODE_PATH}/staking/protocol.json. You must transfer this file from an online node. Press ENTER when you have placed the file and is ready to continue."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get pool-deposit
|
||||
if [ -z "$UPDATE" ]; then
|
||||
POOL_DEPOSIT=$(jq -r .poolDeposit protocol.json)
|
||||
else
|
||||
POOL_DEPOSIT=0
|
||||
fi
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
ADDRESS=$(cat wallets/owner/payment.addr)
|
||||
check_balance $(expr ${POOL_DEPOSIT} + ${EXTRA_FEE})
|
||||
|
||||
# Multiowners delegation certificates
|
||||
if [ -n "$MULTI_OWNERS" ]; then
|
||||
echo "Multiple owner delegation certificates"
|
||||
for i in $(echo ${MULTI_OWNERS} | sed "s/,/ /g")
|
||||
do
|
||||
echo "$i"
|
||||
MULTIOWNERS_CERT_STRING="${MULTIOWNERS_STRING} --certificate-file wallets/$i/delegation.cert"
|
||||
MULTIOWNERS_SIGN="${MULTIOWNERS_SIGN} --signing-key-file wallets/$i/stake.skey"
|
||||
done
|
||||
echo $MULTIOWNERS_STRING
|
||||
fi
|
||||
|
||||
if [ -z "$NO_DELEG" ]; then
|
||||
DELEG_CERTS="--certificate-file wallets/owner/delegation.cert ${MULTIOWNERS_CERT_STRING}"
|
||||
fi
|
||||
|
||||
# Draft transaction
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+0 \
|
||||
--ttl 0 \
|
||||
--fee 0 \
|
||||
--out-file wallets/owner/transactions/register_stake_pool.draft \
|
||||
--certificate-file pool.cert ${DELEG_CERTS}
|
||||
|
||||
|
||||
## Calculate the fee
|
||||
FEE=$(cardano-cli transaction calculate-min-fee \
|
||||
--tx-body-file wallets/owner/transactions/register_stake_pool.draft \
|
||||
--tx-in-count 1 \
|
||||
--tx-out-count 1 \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--witness-count 1 \
|
||||
--byron-witness-count 0 \
|
||||
--protocol-params-file protocol.json | tr ' ' '\n' | head -1)
|
||||
FEE=$(expr ${FEE} + ${EXTRA_FEE}) # FEE IS TOO SMALL?
|
||||
TOTAL_PRICE=$(expr ${FEE} + ${POOL_DEPOSIT})
|
||||
|
||||
echo "Fee is: ${FEE} Lovelace"
|
||||
echo "Pool-Deposit: ${POOL_DEPOSIT} Lovelace"
|
||||
echo "Total Price is: ${TOTAL_PRICE} Lovelace"
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
check_balance ${TOTAL_PRICE}
|
||||
SLOT=$(get_slot)
|
||||
else
|
||||
read -p "Enter the current tip slot: " SLOT
|
||||
fi
|
||||
TTL=$(expr ${SLOT} + 500)
|
||||
|
||||
# Display transaction info
|
||||
REMAINING_AFTER_TX=$(expr ${LOVELACE} - ${TOTAL_PRICE})
|
||||
echo "Creating transaction"
|
||||
echo "Lovelace after transaction: ${REMAINING_AFTER_TX}"
|
||||
echo "Current tip Slot: ${SLOT}"
|
||||
echo "TTL: ${TTL}"
|
||||
|
||||
#
|
||||
# Create the transaction
|
||||
#
|
||||
echo "Create transaction"
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+${REMAINING_AFTER_TX} \
|
||||
--ttl ${TTL} \
|
||||
--fee ${FEE} \
|
||||
--out-file wallets/owner/transactions/register_stake_pool.raw \
|
||||
--certificate-file pool.cert \
|
||||
--certificate-file wallets/owner/delegation.cert \
|
||||
${MULTIOWNERS_CERT_STRING}
|
||||
|
||||
# Sign the transaction
|
||||
echo "Sign transaction"
|
||||
cardano-cli transaction sign \
|
||||
--tx-body-file wallets/owner/transactions/register_stake_pool.raw \
|
||||
--signing-key-file wallets/owner/payment.skey \
|
||||
--signing-key-file wallets/owner/stake.skey \
|
||||
${MULTIOWNERS_SIGN} \
|
||||
--signing-key-file cold-keys/cold.skey \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--out-file wallets/owner/transactions/register_stake_pool.signed
|
||||
|
||||
|
||||
# Submit the transaction
|
||||
if [ -z "$COLD_CREATE" ]; then
|
||||
read -n 1 -r -s -p $'Press enter to submit the certificates...\n'
|
||||
|
||||
echo "Submit transaction"
|
||||
OUT=$(cardano-cli transaction submit \
|
||||
--tx-file wallets/owner/transactions/register_stake_pool.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
|
||||
# Wait for blockchain to register the pool
|
||||
wait_for_slot ${TTL}
|
||||
wait_for_pool_registration
|
||||
echo "Your stake pool registration has been sent to the blockchain."
|
||||
touch ${NODE_PATH}/staking/wallets/owner/transactions/register_stake_pool.submitted
|
||||
fi
|
||||
fi
|
136
scripts/send_ada
Normal file
136
scripts/send_ada
Normal file
@ -0,0 +1,136 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/functions/check_balance
|
||||
|
||||
WALLET=$1
|
||||
TO_ADDR=$2
|
||||
SEND_ADA=$3
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
if [ -z "$WALLET" ]; then
|
||||
echo "Invalid wallet."
|
||||
MISSING_ARG=1
|
||||
fi
|
||||
|
||||
if [ -z "$TO_ADDR" ]; then
|
||||
echo "Invalid recipient address."
|
||||
MISSING_ARG=1
|
||||
fi
|
||||
|
||||
if [ -z "$SEND_ADA" ]; then
|
||||
echo "Missing ADA amount."
|
||||
MISSING_ARG=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_ARG" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/payment.skey" ]; then
|
||||
echo "Missing required payment.skey. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/payment.addr" ]; then
|
||||
echo "Missing required payment.addr. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
cd ${NODE_PATH}/staking/wallets/${WALLET}/
|
||||
mkdir -p transactions/
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
cardano-cli query protocol-parameters \
|
||||
${NETWORK_ARGUMENT} --allegra-era \
|
||||
--out-file ${NODE_PATH}/staking/protocol.json
|
||||
|
||||
ADDRESS=$(cat payment.addr)
|
||||
SEND_LOVELACE=$(expr ${SEND_ADA} \* 1000000) # Convert ADA to Lovelace
|
||||
check_balance $SEND_LOVELACE
|
||||
|
||||
# Draft transaction
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${TO_ADDR}+0 \
|
||||
--tx-out ${ADDRESS}+0 \
|
||||
--ttl 0 \
|
||||
--fee 0 \
|
||||
--out-file transactions/tx.${TIMESTAMP}.draft
|
||||
|
||||
FEE=$(cardano-cli transaction calculate-min-fee \
|
||||
--tx-body-file transactions/tx.${TIMESTAMP}.draft \
|
||||
--tx-in-count 1 \
|
||||
--tx-out-count 2 \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--witness-count 1 \
|
||||
--byron-witness-count 0 \
|
||||
--protocol-params-file ${NODE_PATH}/staking/protocol.json | tr ' ' '\n' | head -1)
|
||||
|
||||
TOTAL_PRICE=$(expr ${FEE} + ${SEND_LOVELACE})
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
check_balance ${TOTAL_PRICE}
|
||||
|
||||
# Update slot and TTL
|
||||
SLOT=$(get_slot)
|
||||
TTL=$(expr ${SLOT} + 500)
|
||||
|
||||
# Display transaction info
|
||||
REMAINING_AFTER_TX=$(expr ${LOVELACE} - ${TOTAL_PRICE})
|
||||
echo "Creating transaction"
|
||||
echo "Current tip Slot: ${SLOT}"
|
||||
echo "TTL: ${TTL}"
|
||||
echo ""
|
||||
echo "$SEND_ADA ADA is ${SEND_LOVELACE} Lovelace"
|
||||
echo "From wallet: ${WALLET}"
|
||||
echo "From address: ${ADDRESS}"
|
||||
echo "To address: ${TO_ADDR}"
|
||||
echo "Send amount: ${SEND_LOVELACE} Lovelace"
|
||||
echo "Fee is: ${FEE} Lovelace"
|
||||
echo "Total amount is: ${TOTAL_PRICE} Lovelace"
|
||||
echo "Balance after transaction: ${REMAINING_AFTER_TX} Lovelace"
|
||||
|
||||
#
|
||||
# Create the transaction
|
||||
#
|
||||
echo "Create transaction"
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${TO_ADDR}+${SEND_LOVELACE} \
|
||||
--tx-out ${ADDRESS}+${REMAINING_AFTER_TX} \
|
||||
--ttl ${TTL} \
|
||||
--fee ${FEE} \
|
||||
--out-file transactions/tx.${TIMESTAMP}.raw
|
||||
|
||||
cardano-cli transaction sign \
|
||||
--tx-body-file transactions/tx.${TIMESTAMP}.raw \
|
||||
--signing-key-file payment.skey \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--out-file transactions/tx.${TIMESTAMP}.signed
|
||||
|
||||
# Submit the transaction
|
||||
read -n 1 -r -s -p $'Press enter to submit the transaction...\n'
|
||||
|
||||
echo "Submit transaction"
|
||||
OUT=$(cardano-cli transaction submit \
|
||||
--tx-file transactions/tx.${TIMESTAMP}.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
fi
|
128
scripts/start-cardano-node
Normal file
128
scripts/start-cardano-node
Normal file
@ -0,0 +1,128 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Include functions
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/run_node
|
||||
source /scripts/functions/get_public_ip
|
||||
source /scripts/functions/init_config
|
||||
|
||||
function help {
|
||||
echo "Arguments:"
|
||||
echo "--start Start basic node."
|
||||
echo "--staking Start as a staking node (Also requires the \`--start\` argument)"
|
||||
echo "--create Start Stakepool creation. Initializes Stake Pool keys, addresses and certificates, and sends them to the blockchain, when starting as a stakepool, if it is not already initialized."
|
||||
echo "--cold-create Initializes Stake Pool keys, addresses and certificates, and sign registration transactions. Registation transactions has to be sent using the \`--cold-register\` argument."
|
||||
echo "--cold-register Submits the address and pool registration transactions to the blockchain created using the \`--cold-create\` argument."
|
||||
echo "--cli Start command-line interface."
|
||||
echo "--update Update the node software."
|
||||
echo "--init_config Initialize config."
|
||||
echo "--help Display this message."
|
||||
echo "Environment variables:"
|
||||
echo "NODE_PORT Port of node. Default: 3000."
|
||||
echo "NODE_NAME Name of node. Default: node1."
|
||||
echo "NODE_TOPOLOGY Topology of the node. Should be comma separated for each individual node to add, on the form: <ip>:<port>/<valency>. So for example: 127.0.0.1:3001/1,127.0.0.1:3002/1."
|
||||
echo "NODE_RELAY Set to True if default IOHK relay should be added to the network topology. Default: False."
|
||||
echo "METADATA_URL URL for file containing stake pool metadata information. See \`examples/metadata.json\` for examle. The file be uploaded to an URL accessible to public."
|
||||
echo "PUBLIC_RELAY_PORT Public port of Relay node."
|
||||
echo "PUBLIC_RELAY_IP Public IP address of Relay node."
|
||||
echo " Values:"
|
||||
echo " <Any IP address>"
|
||||
echo " TOPOLOGY: Use first entry of the topology."
|
||||
echo " PUBLIC: Use public IP of node."
|
||||
echo " Default: TOPOLOGY."
|
||||
echo "HOST_ADDR Set cardano-node host address. Defaults to public IP address."
|
||||
echo "CARDANO_NETWORK Carano network to use (main, test, pioneer). Default: main."
|
||||
echo "EKG_PORT Port of EKG monitoring. Default: 12788."
|
||||
echo "PROMETHEUS_HOST Host of Prometheus monitoring. Default: 127.0.0.1."
|
||||
echo "PROMETHEUS_PORT Port of Prometheus monitoring. Default: 12798."
|
||||
echo "RESOLVE_HOSTNAMES Resolve topology hostnames to IP-addresses. Default: False."
|
||||
echo "REPLACE_EXISTING_CONFIG Reset and replace existing configs. Default: False."
|
||||
echo "POOL_PLEDGE Pledge (lovelace). Default: 100000000000"
|
||||
echo "POOL_COST Operational costs per epoch (lovelace). Default: 10000000000"
|
||||
echo "POOL_MARGIN Operator margin. Default: 0.05"
|
||||
echo "AUTO_TOPOLOGY Automatically update topology.json. Default: True"
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
--help)
|
||||
help
|
||||
break
|
||||
;;
|
||||
--update)
|
||||
/scripts/update-cardano-node
|
||||
;;
|
||||
--cli)
|
||||
/bin/bash
|
||||
break
|
||||
;;
|
||||
--init_config)
|
||||
init_config
|
||||
;;
|
||||
--start)
|
||||
START_NODE=1
|
||||
;;
|
||||
--staking)
|
||||
STAKING=1
|
||||
;;
|
||||
--create)
|
||||
CREATE=1
|
||||
;;
|
||||
--cold-create)
|
||||
CREATE=1
|
||||
COLD_CREATE=1
|
||||
COLD="${COLD} --cold-create"
|
||||
;;
|
||||
--cold-register)
|
||||
CREATE=1
|
||||
COLD="${COLD} --cold-register"
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$1" ]; then
|
||||
help
|
||||
fi
|
||||
|
||||
|
||||
# Init config on first run
|
||||
if [[ ! -f "${NODE_PATH}/VARS" || "$REPLACE_EXISTING_CONFIG" == "True" ]]; then
|
||||
init_config
|
||||
fi
|
||||
|
||||
|
||||
# If not doing cold-create
|
||||
if [ -z "${COLD_CREATE}" ]; then
|
||||
# Handle IP addresses
|
||||
export PUBLIC_IP=$(get_public_ip)
|
||||
if [ -z "${HOST_ADDR}" ]; then
|
||||
export HOST_ADDR=${PUBLIC_IP}
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -n "$CREATE" ]; then
|
||||
create_stakepool ${COLD}
|
||||
fi
|
||||
|
||||
|
||||
if [ -n "$START_NODE" ]; then
|
||||
if [ -n "$STAKING" ]; then
|
||||
# Start as staking node
|
||||
/scripts/start-stakenode
|
||||
else
|
||||
# Update topology
|
||||
if [[ "${AUTO_TOPOLOGY}" == "True" ]]; then
|
||||
tmux \
|
||||
new-session "source /scripts/functions/run_node; run_node" \; \
|
||||
split-window "source /scripts/functions/auto_topology_start; auto_topology_start" \; \
|
||||
select-layout even-horizontal
|
||||
else
|
||||
run_node
|
||||
fi
|
||||
fi
|
||||
fi
|
39
scripts/start-stakenode
Normal file
39
scripts/start-stakenode
Normal file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/init_node_vars
|
||||
source /scripts/functions/check_pool_registration
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "${NODE_PATH}/staking/pool-keys/kes.skey" ]; then
|
||||
echo "Missing required pool-keys/kes.skey."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/pool-keys/vrf.skey" ]; then
|
||||
echo "Missing required pool-keys/vrf.skey."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/pool-keys/node.cert" ]; then
|
||||
echo "Missing required pool-keys/node.cert."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/POOL_ID" ]; then
|
||||
echo "Missing required POOL_ID."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
echo "You are missing required files to start."
|
||||
echo "You need to initialize the stake pool keys, addresses and certificates and submit them to the blockchain first."
|
||||
echo "You can do that by running \`create_stakepool\`"
|
||||
read
|
||||
|
||||
exit
|
||||
else
|
||||
tmux \
|
||||
new-session "source /scripts/functions/run_stakingnode; run_stakingnode" \; \
|
||||
split-window "source /scripts/functions/status; status" \; \
|
||||
select-layout even-horizontal
|
||||
fi
|
32
scripts/wallet_balance
Normal file
32
scripts/wallet_balance
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
WALLET=$1
|
||||
|
||||
if [ -z "$WALLET" ]; then
|
||||
echo "Invalid wallet."
|
||||
MISSING_ARG=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_ARG" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/payment.addr" ]; then
|
||||
echo "Missing required payment.addr. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
ADDRESS=$(cat ${NODE_PATH}/staking/wallets/${WALLET}/payment.addr)
|
||||
|
||||
cardano-cli query utxo ${NETWORK_ARGUMENT} --allegra-era --address ${ADDRESS}
|
132
scripts/withdraw_rewards
Normal file
132
scripts/withdraw_rewards
Normal file
@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
source /scripts/functions/check_balance
|
||||
|
||||
WALLET=$1
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
if [ -z "$WALLET" ]; then
|
||||
echo "Invalid wallet."
|
||||
MISSING_ARG=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_ARG" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check for required files
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/payment.skey" ]; then
|
||||
echo "Missing required payment.skey. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/payment.addr" ]; then
|
||||
echo "Missing required payment.addr. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/stake.addr" ]; then
|
||||
echo "Missing required stake.addr. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ ! -f "${NODE_PATH}/staking/wallets/${WALLET}/stake.skey" ]; then
|
||||
echo "Missing required stake.skey. You need to run \`generate_waller ${WALLET}\` to generate this key."
|
||||
MISSING_FILES=1
|
||||
fi
|
||||
|
||||
if [ -n "$MISSING_FILES" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
cd ${NODE_PATH}/staking/wallets/${WALLET}/
|
||||
mkdir -p transactions/
|
||||
|
||||
# Wait for node to sync
|
||||
if [[ "${WAIT_FOR_SYNC}" == "True" ]]; then
|
||||
wait_for_sync 99.90
|
||||
fi
|
||||
|
||||
cardano-cli query protocol-parameters \
|
||||
${NETWORK_ARGUMENT} --allegra-era \
|
||||
--out-file ${NODE_PATH}/staking/protocol.json
|
||||
|
||||
ADDRESS=$(cat payment.addr)
|
||||
STAKE_ADDRESS=$(cat stake.addr)
|
||||
REWARD_BALANCE=$(cardano-cli query stake-address-info ${NETWORK_ARGUMENT} --allegra-era --address $(cat stake.addr) | jq -r ".[0].rewardAccountBalance")
|
||||
check_balance 200000 # Dummy transaction fee
|
||||
|
||||
# Draft transaction
|
||||
echo "Draft transaction"
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+0 \
|
||||
--withdrawal ${STAKE_ADDRESS}+${REWARD_BALANCE} \
|
||||
--ttl 0 \
|
||||
--fee 0 \
|
||||
--out-file transactions/tx.${TIMESTAMP}.draft
|
||||
|
||||
echo "Calculate fee"
|
||||
FEE=$(cardano-cli transaction calculate-min-fee \
|
||||
--tx-body-file transactions/tx.${TIMESTAMP}.draft \
|
||||
--tx-in-count 1 \
|
||||
--tx-out-count 1 \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--witness-count 1 \
|
||||
--byron-witness-count 0 \
|
||||
--protocol-params-file ${NODE_PATH}/staking/protocol.json | tr ' ' '\n' | head -1)
|
||||
|
||||
# Find UTXO in address with enough lovelace to do the transaction
|
||||
check_balance ${FEE}
|
||||
|
||||
# Update slot and TTL
|
||||
SLOT=$(get_slot)
|
||||
TTL=$(expr ${SLOT} + 500)
|
||||
|
||||
# Display transaction info
|
||||
BALANCE_AFTER_TX=$(expr ${LOVELACE} + ${REWARD_BALANCE} - ${FEE})
|
||||
echo "Creating rewards withdrawal transaction"
|
||||
echo "Current tip Slot: ${SLOT}"
|
||||
echo "TTL: ${TTL}"
|
||||
echo "Withdrawing rewards from: ${STAKE_ADDRESS}"
|
||||
echo "Withdrawing rewards to: ${ADDRESS}"
|
||||
echo "Fee is: ${FEE} Lovelace"
|
||||
echo "Rewards amount: ${REWARD_BALANCE} Lovelace"
|
||||
echo "Lovelace before withdrawal: ${LOVELACE}"
|
||||
echo "Lovelace after withdrawal: ${BALANCE_AFTER_TX}"
|
||||
|
||||
#
|
||||
# Create the transaction
|
||||
#
|
||||
cardano-cli transaction build-raw \
|
||||
--tx-in "${UTXO}#${TXIX}" \
|
||||
--tx-out ${ADDRESS}+${BALANCE_AFTER_TX} \
|
||||
--withdrawal ${STAKE_ADDRESS}+${REWARD_BALANCE} \
|
||||
--ttl ${TTL} \
|
||||
--fee ${FEE} \
|
||||
--out-file transactions/tx.${TIMESTAMP}.raw
|
||||
|
||||
cardano-cli transaction sign \
|
||||
--tx-body-file transactions/tx.${TIMESTAMP}.raw \
|
||||
--signing-key-file payment.skey \
|
||||
--signing-key-file stake.skey \
|
||||
${NETWORK_ARGUMENT} \
|
||||
--out-file transactions/tx.${TIMESTAMP}.signed
|
||||
|
||||
# Submit the transaction
|
||||
read -n 1 -r -s -p $'Press enter to submit the transaction...\n'
|
||||
|
||||
echo "Submit transaction"
|
||||
OUT=$(cardano-cli transaction submit \
|
||||
--tx-file transactions/tx.${TIMESTAMP}.signed \
|
||||
${NETWORK_ARGUMENT} 2>&1)
|
||||
|
||||
if [[ $OUT =~ "Error" ]]
|
||||
then
|
||||
echo "An error occoured."
|
||||
echo ${OUT}
|
||||
read
|
||||
else
|
||||
echo "Transaction has been submitted to the blockchain."
|
||||
echo ${OUT}
|
||||
fi
|
Loading…
Reference in New Issue
Block a user