Skip to content
This repository has been archived by the owner on Jun 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #9 from dappnode/pablo/load-keys-on-the-fly
Browse files Browse the repository at this point in the history
Implement load keystores on the fly on web3signer
  • Loading branch information
pablomendezroyo authored May 19, 2022
2 parents 5b765a6 + 9fca6fd commit 9bfd401
Show file tree
Hide file tree
Showing 12 changed files with 4,094 additions and 255 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/auto_check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Bump upstream version

on:
schedule:
- cron: "00 */4 * * *"
push:
branches:
- "master"
- "main"

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npx @dappnode/dappnodesdk github-action bump-upstream
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PINATA_API_KEY: ${{ secrets.PINATA_API_KEY }}
PINATA_SECRET_API_KEY: ${{ secrets.PINATA_SECRET_API_KEY }}
31 changes: 31 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "Main"
on:
pull_request:
push:
branches:
- "master"
- "main"
- "v[0-9]+.[0-9]+.[0-9]+"
paths-ignore:
- "README.md"

jobs:
build-test:
runs-on: ubuntu-latest
name: Build test
if: github.event_name != 'push'
steps:
- uses: actions/checkout@v2
- run: npx @dappnode/dappnodesdk build --skip_save

release:
name: Release
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v2
- name: Publish
run: npx @dappnode/dappnodesdk publish patch --dappnode_team_preset
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEVELOPER_ADDRESS: "0xf35960302a07022aba880dffaec2fdd64d5bf1c1"
39 changes: 4 additions & 35 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,42 +1,11 @@
ARG UPSTREAM_VERSION

###########
# BUILDER #
###########
# Get jq binaries (curl is already in the consensys image)
FROM debian:bullseye-slim as builder
RUN apt update && apt install cron jq curl --yes
FROM statusim/nimbus-eth2:multiarch-${UPSTREAM_VERSION}

FROM statusim/nimbus-eth2:multiarch-v1.7.0

# Copy curl binary
COPY --from=builder /usr/bin/curl /usr/bin/curl
COPY --from=builder /usr/lib/x86_64-linux-gnu/libcurl* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libng* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/librtmp* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libssh2* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libpsl* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libldap* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/liblber* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libbrotlidec* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libsasl2* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libbrotlicommon* /usr/lib/x86_64-linux-gnu/
# Copy jq binary
COPY --from=builder /usr/bin/jq /usr/bin/jq
COPY --from=builder /usr/lib/x86_64-linux-gnu/libjq* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libonig* /usr/lib/x86_64-linux-gnu/
# Copy crontab and cron binary
COPY --from=builder /usr/sbin/cron /usr/sbin/cron
COPY --from=builder /usr/bin/crontab /usr/bin/crontab
COPY --from=builder /var/spool/cron /var/spool/cron

# Setup cronjob
COPY get-keys-cron /etc/cron.d/
COPY get-keys.sh /usr/local/bin/get-keys.sh

# Apply cron job
RUN crontab /etc/cron.d/get-keys-cron
USER root
RUN apt update && apt install curl jq -y

COPY entrypoint.sh /usr/bin/entrypoint.sh
COPY auth-token /home/user/nimbus-eth2/build/data/auth-token

ENTRYPOINT [ "entrypoint.sh" ]
1 change: 1 addition & 0 deletions build/auth-token
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.MxwOozSH-TLbW_XKepjyYDHm2IT8Ki0tD3AHuajfNMg
159 changes: 51 additions & 108 deletions build/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,119 +1,62 @@
#!/bin/bash
#
# 1. Fetches the public keys from the web3signer API
# 2. Checks if the public keys are valid
# 3. CUSTOM: create string with public keys comma separated
# 4. Starts the validator

ERROR="[ ERROR ]"
WARN="[ WARN ]"
INFO="[ INFO ]"

# Var used to start the teku validator: pubkeys must be comma separated
PUBLIC_KEYS_COMMA_SEPARATED=""

# Checks the following vars exist or exits:
# - BEACON_API_PORT
# - HTTP_WEB3PROVIDER
# - HTTP_WEB3SIGNER
# - PUBLIC_KEYS_FILE
function ensure_envs_exist() {
[ -z "${BEACON_API_PORT}" ] && echo "${ERROR} BEACON_API_PORT is not set" && exit 1
[ -z "${HTTP_WEB3PROVIDER}" ] && echo "${ERROR} HTTP_WEB3PROVIDER is not set" && exit 1
[ -z "${HTTP_WEB3SIGNER}" ] && echo "${ERROR} HTTP_WEB3SIGNER is not set" && exit 1
[ -z "${PUBLIC_KEYS_FILE}" ] && echo "${ERROR} PUBLIC_KEYS_FILE is not set" && exit 1
}

# Get public keys from API keymanager: BASH ARRAY OF STRINGS
# - Endpoint: http://web3signer.web3signer-prater.dappnode:9000/eth/v1/keystores
# - Returns:
# { "data": [{
# "validating_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
# "derivation_path": "m/12381/3600/0/0/0",
# "readonly": true
# }]
# }
function get_public_keys() {
if PUBLIC_KEYS_API=$(curl -s -X GET \
-H "Content-Type: application/json" \
--max-time 10 \
--retry 2 \
--retry-delay 2 \
--retry-max-time 40 \
"${HTTP_WEB3SIGNER}/eth/v1/keystores"); then
if PUBLIC_KEYS_API=($(echo ${PUBLIC_KEYS_API} | jq -r '.data[].validating_pubkey')); then
if [ ! -z "$PUBLIC_KEYS_API" ]; then
echo "${INFO} found public keys: $PUBLIC_KEYS_API"
else
echo "${WARN} no public keys found"
fi
else
echo "${WARN} something wrong happened parsing the public keys"
fi
else
echo "${WARN} web3signer not available"
CLIENT="nimbus"
NETWORK="prater"
VALIDATOR_PORT=3500
WEB3SIGNER_API="http://web3signer.web3signer-${NETWORK}.dappnode:9000"

WEB3SIGNER_RESPONSE=$(curl -s -w "%{http_code}" -X GET -H "Content-Type: application/json" -H "Host: beacon-validator.${CLIENT}-${NETWORK}.dappnode" "${WEB3SIGNER_API}/eth/v1/keystores")
HTTP_CODE=${WEB3SIGNER_RESPONSE: -3}
CONTENT=$(echo "${WEB3SIGNER_RESPONSE}" | head -c-4)
if [ "${HTTP_CODE}" == "403" ] && [ "${CONTENT}" == "*Host not authorized*" ]; then
echo "${CLIENT} is not authorized to access the Web3Signer API. Start without pubkeys"
elif [ "$HTTP_CODE" != "200" ]; then
echo "Failed to get keystores from web3signer, HTTP code: ${HTTP_CODE}, content: ${CONTENT}"
else
PUBLIC_KEYS_WEB3SIGNER=($(echo "${CONTENT}" | jq -r 'try .data[].validating_pubkey'))
if [ ${#PUBLIC_KEYS_WEB3SIGNER[@]} -gt 0 ]; then
echo "found validators in web3signer, starting vc with pubkeys: ${PUBLIC_KEYS_WEB3SIGNER[*]}"
for PUBLIC_KEY in "${PUBLIC_KEYS_WEB3SIGNER[@]}"; do
# Docs: https://github.com/status-im/nimbus-eth2/pull/3077#issue-1049195359
# create a keystore file with the following format
# {
# "version": "1",
# "description": "This is simple remote keystore file",
# "type": "web3signer",
# "pubkey": "0x8107ff6a5cfd1993f0dc19a6a9ec7dc742a528dd6f2e3e10189a4a6fc489ae6c7ba9070ea4e2e328f0d20b91cc129733",
# "remote": "http://127.0.0.1:15052",
# "ignore_ssl_verification": true
# }

echo "creating keystore for pubkey: ${PUBLIC_KEY}"
mkdir -p validators/${PUBLIC_KEY}
echo "{\"version\":\"1\",\"description\":\"This is simple remote keystore file\",\"type\":\"web3signer\",\"pubkey\":\"${PUBLIC_KEY}\",\"remote\":\"${WEB3SIGNER_API}\",\"ignore_ssl_verification\":true}" >/home/user/nimbus-eth2/build/data/validators/${PUBLIC_KEY}/remote_keystore.json
done
fi
}

# Clean old file and writes new public keys file
# - by new line separated
# - creates file if it does not exist
function write_public_keys() {
# Clean file
rm -rf ${PUBLIC_KEYS_FILE}
touch ${PUBLIC_KEYS_FILE}

echo "${INFO} writing public keys to file"
for PUBLIC_KEY in ${PUBLIC_KEYS_API}; do
if [ ! -z "${PUBLIC_KEY}" ]; then
echo "${INFO} adding public key: $PUBLIC_KEY"
echo "${PUBLIC_KEY}" >> ${PUBLIC_KEYS_FILE}
else
echo "${WARN} empty public key"
fi
done
}

########
# MAIN #
########

# Check if the envs exist
ensure_envs_exist

# Get public keys from API keymanager
get_public_keys

if [ ! -z "${PUBLIC_KEYS_API}" ]; then
# Write public keys to file
echo "${INFO} writing public keys file"
write_public_keys
fi

echo "${INFO} starting cronjob"
cron

# Concatenate EXTRA_OPTS string
[ ! -z "$INITIAL_STATE" ] && EXTRA_OPTS="${EXTRA_OPTS} --initial-state=${INITIAL_STATE}"

exec /home/user/nimbus-eth2/build/nimbus_beacon_node \
--network=prater \
--data-dir=/home/user/nimbus-eth2/build/data/shared_prater_0 \
--web3-url=wss://goerli.infura.io/ws/v3/3731cbfad17c4afcbc56ab89d5316f82 \
--nat=extip:88.4.184.189 \
# Run checkpoint sync script if provided
[[ -n $CHECKPOINT_SYNC_URL ]] &&
/home/user/nimbus-eth2/build/nimbus_beacon_node trustedNodeSync \
--network=${NETWORK} \
--trusted-node-url=${CHECKPOINT_SYNC_URL} \
--backfill=false \
--data-dir=//home/user/nimbus-eth2/build/data
[[ -n $WEB3_BACKUP_URL ]] && EXTRA_OPTS="--web3-url=${WEB3_BACKUP_URL} ${EXTRA_OPTS}"

exec -c /home/user/nimbus-eth2/build/nimbus_beacon_node \
--network=${NETWORK} \
--data-dir=/home/user/nimbus-eth2/build/data \
--log-level=info \
--tcp-port=9000 \
--udp-port=9000 \
--rpc \
--rpc-address=0.0.0.0 \
--rpc-port=9190 \
--rest \
--rest-port=4500 \
--rest-address=0.0.0.0 \
--metrics \
--metrics-address=0.0.0.0 \
--metrics-port=8008 \
--rest \
--rest-port=5052 \
--rest-address=0.0.0.0 \
--keymanager \
--keymanager-port=5052 \
--keymanager-port=${VALIDATOR_PORT} \
--keymanager-address=0.0.0.0 \
--keymanager-token-file=/home/user/nimbus-eth2/build/data/api_token \
--keymanager-token-file=/home/user/nimbus-eth2/build/data/auth-token \
--graffiti=\"$GRAFFITI\" \
$EXTRA_OPTS
2 changes: 0 additions & 2 deletions build/get-keys-cron

This file was deleted.

97 changes: 0 additions & 97 deletions build/get-keys.sh

This file was deleted.

Loading

0 comments on commit 9bfd401

Please sign in to comment.