Skip to content

Commit

Permalink
Initial support for Grandine
Browse files Browse the repository at this point in the history
  • Loading branch information
sauliusgrigaitis committed Apr 21, 2022
1 parent 30c509f commit efb7015
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 2 deletions.
6 changes: 6 additions & 0 deletions default.env
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ EC_NETWORK=goerli
# Some clients suggest adjusting to higher (or lower) peer count. Adjust here, per client
PRYSM_PEER_COUNT=45
LH_PEER_COUNT=80
GRANDINE_PEER_COUNT=50
TEKU_PEER_COUNT=74
# Nimbus peer count should not be set below 70
NIM_PEER_COUNT=160
Expand Down Expand Up @@ -111,6 +112,11 @@ LH_SRC_BUILD_TARGET=stable
LH_DOCKER_TAG=latest-modern
LH_DOCKERFILE=Dockerfile.binary

# Grandine
GRANDINE_SRC_BUILD_TARGET=stable
GRANDINE_DOCKER_TAG=latest
GRANDINE_DOCKERFILE=Dockerfile.binary

# Prysm
PRYSM_SRC_BUILD_TARGET=$(git describe --tags $(git rev-list --tags --max-count=1))
PRYSM_DOCKER_TAG=stable
Expand Down
8 changes: 6 additions & 2 deletions ethd
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ envmigrate() {
return
fi
ALL_VARS=( COMPOSE_FILE EC_NODE EC_FALLBACK_NODE1 EC_FALLBACK_NODE2 GRAFFITI NETWORK EC_NETWORK \
PRYSM_PEER_COUNT LH_PEER_COUNT TEKU_PEER_COUNT NIM_PEER_COUNT DOMAIN ACME_EMAIL \
PRYSM_PEER_COUNT LH_PEER_COUNT GRANDINE_PEER_COUNT TEKU_PEER_COUNT NIM_PEER_COUNT DOMAIN ACME_EMAIL \
CF_EMAIL CF_API_TOKEN AWS_PROFILE AWS_HOSTED_ZONE_ID GRAFANA_HOST PROM_HOST PRYSM_HOST \
EC_HOST EC_WS_HOST CC_HOST DDNS_SUBDOMAIN DDNS_PROXY TEKU_RAPID_SYNC LH_RAPID_SYNC LS_RAPID_SYNC \
NIMBUS_RAPID_SYNC CC_NODE BEACON_STATS_API BEACON_STATS_MACHINE EC_P2P_PORT CC_P2P_PORT PRYSM_PORT \
Expand All @@ -345,7 +345,7 @@ envmigrate() {
OE_SRC_BUILD_TARGET OE_DOCKER_TAG OE_DOCKERFILE GETH_SRC_BUILD_TARGET GETH_DOCKER_TAG \
GETH_DOCKERFILE NM_SRC_BUILD_TARGET NM_DOCKER_TAG NM_DOCKERFILE BESU_SRC_BUILD_TARGET \
BESU_DOCKER_TAG BESU_DOCKERFILE SSV_NODE_TAG DEPCLI_SRC_BUILD_TARGET DEPCLI_DOCKER_TAG DEPCLI_LOCALDIR \
NODE_EXPORTER_IGNORE_MOUNT_REGEX )
NODE_EXPORTER_IGNORE_MOUNT_REGEX GRANDINE_SRC_BUILD_TARGET GRANDINE_DOCKER_TAG GRANDINE_DOCKERFILE )
OLD_VARS=( LH_PORT PRYSM_WEB_PORT )
NEW_VARS=( CC_P2P_PORT KEY_API_PORT )

Expand Down Expand Up @@ -501,13 +501,15 @@ query_consensus_client() {
"Which consensus client do you want to run?" 10 65 3 \
"lh-base.yml" "Lighthouse (Rust) - consensus and validator client" \
"nimbus-base.yml" "Nimbus (Nim) - consensus and validator client" \
"grandine-base.yml" "Grandine (Rust) - consensus and validator client" \
"teku-base.yml" "Teku (Java) - consensus and validator client" 3>&1 1>&2 2>&3)
else
CONSENSUS_CLIENT=$(whiptail --notags --title "Select consensus client" --menu \
"Which consensus client do you want to run?" 12 65 5 \
"teku-base.yml" "Teku (Java) - consensus and validator client" \
"lh-base.yml" "Lighthouse (Rust) - consensus and validator client" \
"nimbus-base.yml" "Nimbus (Nim) - consensus and validator client" \
"grandine-base.yml" "Grandine (Rust) - consensus and validator client" \
"lodestar-base.yml" "Lodestar (Javascript) - consensus and validator client" \
"prysm-base.yml" "Prysm (Go) - consensus and validator client" 3>&1 1>&2 2>&3)
fi
Expand All @@ -527,13 +529,15 @@ query_consensus_only_client() {
"Which consensus client do you want to run?" 10 65 3 \
"lh-consensus.yml" "Lighthouse (Rust) - consensus client" \
"nimbus-consensus.yml" "Nimbus (Nim) - consensus client" \
"grandine-consensus.yml" "Grandine (Rust) - consensus client" \
"teku-consensus.yml" "Teku (Java) - consensus client" 3>&1 1>&2 2>&3)
else
CONSENSUS_CLIENT=$(whiptail --notags --title "Select consensus client" --menu \
"Which consensus client do you want to run?" 12 65 5 \
"teku-consensus.yml" "Teku (Java) - consensus client" \
"lh-consensus.yml" "Lighthouse (Rust) - consensus client" \
"nimbus-consensus.yml" "Nimbus (Nim) - consensus client" \
"grandine-consensus.yml" "Grandine (Rust) - consensus client" \
"lodestar-consensus.yml" "Lodestar (Javascript) - consensus client" \
"prysm-consensus.yml" "Prysm (Go) - consensus client" 3>&1 1>&2 2>&3)
fi
Expand Down
73 changes: 73 additions & 0 deletions grandine-base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
version: "3.4"
x-logging: &logging
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}'

services:
consensus:
restart: "${RESTART}"
build:
context: ./grandine
dockerfile: Dockerfile.binary
args:
- BUILD_TARGET=${GRANDINE_SRC_BUILD_TARGET}
- DOCKER_TAG=${GRANDINE_DOCKER_TAG}
image: grandine:local
user: grandine
stop_grace_period: 1m
volumes:
- grandine-data:/var/lib/grandine
- /etc/localtime:/etc/localtime:ro
ports:
- ${CC_P2P_PORT:-9000}:${CC_P2P_PORT:-9000}/tcp
- ${CC_P2P_PORT:-9000}:${CC_P2P_PORT:-9000}/udp
expose:
- 9001/tcp
networks:
default:
aliases:
- eth2
<<: *logging
entrypoint:
- grandine
- --data-dir
- /var/lib/grandine
- --http-address
- 0.0.0.0
- --http-port
- "9001"
- --network
- ${NETWORK}
- --libp2p-port
- ${CC_P2P_PORT:-9000}
- --eth1-rpc-urls
- ${EC_NODE}
- --metrics
- --graffiti
- ${GRAFFITI}
- --keystore-dir
- /var/lib/grandine/validator-keys
- --keystore-password-file
- /var/lib/grandine/validator-passwords
validator-import:
restart: "no"
image: grandine:local
user: root
volumes:
- grandine-data:/var/lib/grandine
- ${DEPCLI_LOCALDIR}/validator_keys:/validator_keys
- /etc/localtime:/etc/localtime:ro
environment:
- KEYSTORE_PASSWORD=${KEYSTORE_PASSWORD:-''}
entrypoint: /usr/local/bin/validator-import.sh
eth:
image: tianon/true
restart: "no"
depends_on:
- consensus
volumes:
grandine-data:
57 changes: 57 additions & 0 deletions grandine-consensus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
version: "3.4"
x-logging: &logging
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}'

services:
consensus:
restart: "${RESTART}"
build:
context: ./grandine
dockerfile: Dockerfile.binary
args:
- BUILD_TARGET=${GRANDINE_SRC_BUILD_TARGET}
- DOCKER_TAG=${GRANDINE_DOCKER_TAG}
image: grandine:local
user: grandine
stop_grace_period: 1m
volumes:
- grandineconsensus-data:/var/lib/grandine
- /etc/localtime:/etc/localtime:ro
ports:
- ${CC_P2P_PORT:-9000}:${CC_P2P_PORT:-9000}/tcp
- ${CC_P2P_PORT:-9000}:${CC_P2P_PORT:-9000}/udp
expose:
- 9001/tcp
networks:
default:
aliases:
- eth2
<<: *logging
entrypoint:
- grandine
- --data-dir
- /var/lib/grandine
- --http-address
- 0.0.0.0
- --http-port
- "9001"
- --network
- ${NETWORK}
- --libp2p-port
- ${CC_P2P_PORT:-9000}
- --eth1-rpc-urls
- ${EC_NODE}
- --metrics
- --subscribe-all-subnets
eth:
image: tianon/true
restart: "no"
depends_on:
- consensus
volumes:
grandineconsensus-data:
39 changes: 39 additions & 0 deletions grandine/Dockerfile.binary
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
ARG DOCKER_TAG

FROM sifrai/grandine:${DOCKER_TAG}

# Unused, this is here to avoid build time complaints
ARG BUILD_TARGET

ARG USER=grandine
ARG UID=10002

# See https://stackoverflow.com/a/55757473/12429735RUN
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
"${USER}"

# Create data mount point with permissions
RUN mkdir -p /var/lib/grandine/validator-keys && mkdir -p /var/lib/grandine/validator-passwords && chown ${USER}:${USER} -R /var/lib/grandine && chmod 700 -R /var/lib/grandine

RUN set -eux; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata; \
rm -rf /var/lib/apt/lists/*; \
# verify that the binary works
gosu nobody true

# Scripts that handle permissions
COPY ./validator-import.sh /usr/local/bin/

# For voluntary exit
ENV KEYSTORE=nonesuch

USER grandine

ENTRYPOINT ["grandine"]
97 changes: 97 additions & 0 deletions grandine/validator-import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/bin/bash
set -Eeuo pipefail

# Copy keys, then restart script without root
if [ "$(id -u)" = '0' ]; then
cp /validator_keys/*.json /var/lib/grandine/validator-keys/
chown grandine:grandine /var/lib/grandine/validator-keys/*
chmod 600 /var/lib/grandine/validator-keys/*
echo "Copied validator key(s) from .eth/validator_keys"
echo
exec gosu grandine "$BASH_SOURCE" "$@"
fi

__non_interactive=0
if echo "$@" | grep -q '.*--non-interactive.*' 2>/dev/null ; then
__non_interactive=1
fi
for arg do
shift
[ "$arg" = "--non-interactive" ] && continue
set -- "$@" "$arg"
done

if [ ${__non_interactive} = 1 ]; then
for file in /var/lib/grandine/validator-keys/*.json ; do
filename=$(basename $file .json)
echo "$KEYSTORE_PASSWORD" > "/var/lib/grandine/validator-passwords/$filename.txt"
done
exit 0
fi

# Only reached in interactive mode

# Prompt for password. There's no check that the password is right.

echo "Storing the validator key password(s) in plain text will allow the validator to start automatically without user input."
echo
while true; do
read -rp "Do you wish to store the validator key password(s) inside this container? (y/n) " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) echo "Not storing plaintext validator key password(s)."; echo; echo "Please adjust grandine-base.yml and see instructions in README.md on how to start the client"; exit;;
* ) echo "Please answer yes or no.";;
esac
done
echo
while true; do
read -rp "Do all validator keys have the same password? (y/n) " yn
case $yn in
[Yy]* ) justone=1; break;;
[Nn]* ) justone=0; break;;
* ) echo "Please answer yes or no.";;
esac
done
echo
if [ $justone -eq 1 ]; then
while true; do
read -srp "Please enter the password for your validator key(s): " password1
echo
read -srp "Please re-enter the password: " password2
echo
if [ "$password1" == "$password2" ]; then
break
else
echo "The two entered passwords do not match, please try again."
echo
fi
done
for file in /var/lib/grandine/validator-keys/*.json ; do
filename=$(basename $file .json)
echo "$password1" > "/var/lib/grandine/validator-passwords/$filename.txt"
done
else
for file in /var/lib/grandine/validator-keys/*.json ; do
filename=$(basename $file .json)
while true; do
read -srp "Please enter the password for your validator key stored in $filename: " password1
echo
read -srp "Please re-enter the password: " password2
echo
if [ "$password1" == "$password2" ]; then
break
else
echo "The two entered passwords do not match, please try again."
echo
fi
done
echo "$password1" > "/var/lib/grandine/validator-passwords/$filename.txt"
done
fi

chmod 600 /var/lib/grandine/validator-passwords/*

echo
echo "Validator key password(s) have been stored."
echo "Please note: This tool currently does not verify that the validator key password(s) are correct. If password(s) don't match, just run this routine again."
echo

0 comments on commit efb7015

Please sign in to comment.