(2022年11月版) Ethereum GoerliテストネットのValidatorになる

# 概要
- 2022年11月時点（The Merge以降）のEthereum Goerliテストネット用Validatorクライアントをセットアップする手順をまとめました。
- 本記事の内容はほとんどそのままMainnetにも適用できる前提で作っていますが、試していません。（お金がない）
- プラットフォームは`Ubuntu server 20.04.1 LTS`
- Execution Clientは`Geth 1.10.26`、Consensus ClientとValidatorは`Prysm 3.1.2`を使用します。
- 本記事に係る内容は全て自己責任で実施をお願いします。


# 1.準備するもの

### マシン１(Ethereum Node用)
推奨スペックは下記参照

https://ethereum.org/en/run-a-node/

常時稼働を見越して小型静音のミニPCなどが理想です。少なくとも電源は安定してないとキツイ。
SSDは必須。かつNVMeが推奨されています。容量は現時点のGoerliなら500GBあれば足ります。

### マシン２(監視ノード用)
`Prometheus`と`Grafana`を動かしてEthereum Nodeをリモート監視します。
Validator運用には迅速な異常検知が必須なので別にマシンを用意する方が望ましいです。
常時監視に使うので軽量なものが理想ですね。信頼性はそこまで高くなくても割り切れる。ラズパイあたりが最適解。

### マシン３(鍵生成用)：★Air Gapped★
Validator Keyを生成する用です。
これは（OSの生涯を通して）絶対にネットワークに接続してはいけません。LAN接続すら禁止です。鉄の掟なので順守しましょう。
お金がない人はUSBメモリを用意して永続データを持たないBootable Linux機を作ることで代替するなどしましょう。

### USBメモリ(鍵運搬用)
マシン３で生成した鍵をマシン１に運搬するために使用します。使用前・使用後はFormatを忘れずに。

### 作業用PC
もろもろのオペレーションを行うためのPC。この記事では
Windows
Google Chrome
VisualStudioCode
あたりの環境使用を前提にしますが何でもいいです。お好みで。

### Goerli EOA (Goerli Ethereumアカウント)
EOAはEthereum Owned Accountのことです。Execution LayerのETHを扱うアカウントです。
EOAは各自が秘密鍵を管理して運用します。
アカウントの作り方はいろいろありますが、よく分からない人はとりあえずMetamaskでウォレットを作成しましょう。
アドレスを作る際にMainnetではなくgoerli testnetを選択することを忘れないでください。
Google Chromeの拡張機能としてインストールするところから始めてください↓

https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=ja

### goETH(少額可)
goETH(=goerli ETH)はgoerliテストネット内でのみ通用する通貨です。
PoW終了後は入手難度が上がっています。
Faucetで少しずつ集めるほか、ステーブルコインで販売しているサイトを見つけて購入する必要があります。
Validatorになるためには32goETHをStakingする必要がありますが、不足している場合でも、正規の手続きではありませんがValidatorになる方法はいちおうあります。本記事ではその方法を扱いValidatorになるところまで紹介しますが、この記事を読まれている時点でまだActiveであるという保証はありません。

ここではとりあえずFaucetで0.1goETHだけでもいいので既に入手済の前提で話を進めます。

まだの人は下記LinkからFaucetを辿って入手しておきましょう。
[Faucet Link Directory For Ethereum Testnets](https://faucetlink.to/goerli)


### Discordアカウント

記事中でDiscordを使う場面があるためアカウントを取得しておいてください。






# 2.Ubuntuセットアップ

`Ubuntu server 20.04.1 LTS`インストールと作業PCからのSSHログインまで完了した状態からスタートします。

## SSHを鍵認証にする

#### 作業PCで鍵生成

- Windowsならコマンドプロンプト
 
```
ssh-keygen -t ecdsa -b 521
```

`C:\Users\<user>\.ssh` に鍵ペアが生成されるので公開鍵`*.pub`の方をUbuntuに転送しておく

- VisualStudioCode設定

```config:C:\Users\<user>\.ssh\config
Host EthNode_KeyAuth
    HostName <target IP address>
    User <username>
    port 22522
    IdentityFile C:\Users\<user>\.ssh\id_ecdsa_ethnode
```

ポート番号は22から適当に変えておきます。

#### マシン１(Ubuntu Server)

- `~/.ssh/authorized_keys`に公開鍵を書き加える

```
~/.ssh$ cat id_ecdsa_ethnode.pub > authorized_keys
```

- `sshd_config`の設定

```config:/etc/ssh/sshd_config
Port 22522
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
```

- 再起動

```bash
$ service ssh restart
```

変更したポートで再接続します。現セッションは切断するまで有効ですが、万一設定が間違っていた場合は再接続できなくなりますので別にセッション開くのがおススメです。


## SSDを容量一杯まで拡張する

大容量のSSDを使っている場合、論理ボリュームがMAXまで認識してくれないことがある。
というか、実際にそうなってしまったので、対策します。

```bash
$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
<snip>
nvme0n1                   259:0    0  1.8T  0 disk 
├─nvme0n1p1               259:1    0    1G  0 part /boot/efi
├─nvme0n1p2               259:2    0    2G  0 part /boot
└─nvme0n1p3               259:3    0  1.8T  0 part 
  └─ubuntu--vg-ubuntu--lv 253:0    0  100G  0 lvm  /
```

PV(物理ボリューム)`/dev/nvme0n1p3`は1.8Tなのに
LV(論理ボリューム)`ubuntu--vg-ubuntu--lv`が100Gしかマウントされていません。
以下のコマンドでも確認可能

```bash
$ sudo pvs
  PV             VG        Fmt  Attr PSize  PFree 
  /dev/nvme0n1p3 ubuntu-vg lvm2 a--  <1.82t <1.72t

$ sudo lvs
  LV        VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ubuntu-lv ubuntu-vg -wi-ao---- 100.00g
```

>pvsコマンドはPVとVG(Vomume Group)の対応関係を出力
lvsコマンドはLVとVGの対応関係を出力
pvsの結果から1.72Tが未使用の状態ということがわかります。

- `lvextend -l +100%FREE`で未使用領域を全てLVにアサインします

```bash
$ sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
  Size of logical volume ubuntu-vg/ubuntu-lv changed from 100.00 GiB (25600 extents) to <1.82 TiB (476150 extents).
  Logical volume ubuntu-vg/ubuntu-lv successfully resized.
```

```bash
$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
<snip>
nvme0n1                   259:0    0  1.8T  0 disk 
├─nvme0n1p1               259:1    0    1G  0 part /boot/efi
├─nvme0n1p2               259:2    0    2G  0 part /boot
└─nvme0n1p3               259:3    0  1.8T  0 part 
  └─ubuntu--vg-ubuntu--lv 253:0    0  1.8T  0 lvm  /
```

しかしこの状態ではまだFile Systemには反映されていません。
`resize2fs`コマンドにより反映します。

```bash
$ sudo resize2fs /dev/ubuntu-vg/ubuntu-lv 
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/ubuntu-vg/ubuntu-lv is mounted on /; on-line resizing required
old_desc_blocks = 13, new_desc_blocks = 233
The filesystem on /dev/ubuntu-vg/ubuntu-lv is now 487577600 (4k) blocks long.
```

```bash
$ df -h
Filesystem                         Size  Used Avail Use% Mounted on
<snip>
/dev/mapper/ubuntu--vg-ubuntu--lv  1.8T  5.2G  1.8T   1% /

```

以上で完了です。


# 3.セキュリティアップデート自動更新

セキュリティアップデートがあれば自動的に更新されるように設定

```bash
$ sudo apt update && sudo apt upgrade -y
$ sudo apt install unattended-upgrades
$ sudo dpkg-reconfigure -plow unattended-upgrades
```

# 4.IPv6無効化

敢えて有効化する必要は今のところないので無効化しておく

```bash:/etc/default/grub
GRUB CMDLINE LINUX="ipv6.disable=1"
```

- 設定反映

```bash
$ sudo update-grub
```

# 5.Explicit Congestion Notificationの無効化

Explicit Congestion Notification（ECN）は、ネットワーク上の特定の端末からの制御フラグを用いて、パケットが送信される際に、帯域幅の制限を超えている場合や、ネットワークが混雑している場合に、送信元の端末に対して通知するためのプロトコルです。
ひとまず無効化が無難。

```bash:/etc/sysctl.conf
net.ipv4.tcp_ecn=0
```

- 設定反映

```bash
$ sudo sysctl -p
```

# 6.パブリックDNSを参照

好みかも。解説は省略。

```bash:/etc/systemd/resolved.conf
DNS=8.8.8.8 8.8.4.4
```

```bash
$ cd /etc
$ sudo ln -sf ../run/systemd/resolve/resolv.conf resolv.conf
$ ls -la resolv.conf
```

- 設定反映

```bash
$ sudo systemctl restart systemd-resolved
```

# 7.ethereumユーザ作成

基本的にオペレーションはethereumユーザを通して行います。
sudoを使えるようにしておきます

```bash
$ sudo useradd -m -s /bin/bash ethereum
$ sudo passwd ethereum
$ sudo usermod -aG sudo ethereum
```

- rootはロックしておきます

```bash
$ sudo passwd -l root
```

# 8.Firewall設定

IPv6無効化します

`sudo vim /etc/default/ufw`

```bash:/etc/default/ufw
IPV6=no
```

各種プロトコルを許可します

`sudo ufw allow 22522` SSH
`sudo ufw allow 30303` Execution Client(Geth) TCP/UDP
`sudo ufw allow 13000/tcp` Consensus Client (Prysm) TCP
`sudo ufw allow 12000/udp` Consensus Client (Prysm) UDP
`sudo ufw allow 6060` Geth Metrics
`sudo ufw allow 9100` Node-exporter ※Prometheusからの接続をListen
`sudo ufw allow 8080` Prysm（Beacon Node） ※Prometheusからの接続をListen
`sudo ufw allow 8081` Prysm（Validator） ※Prometheusからの接続をListen

- ufw有効化

```bash
$ sudo ufw enable
```

- 設定確認

```bash
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22522                      ALLOW IN    Anywhere                  
30303                      ALLOW IN    Anywhere                  
13000/tcp                  ALLOW IN    Anywhere                  
12000/udp                  ALLOW IN    Anywhere                  
9100                       ALLOW IN    Anywhere                  
6060                       ALLOW IN    Anywhere                  
8080                       ALLOW IN    Anywhere                  
8081                       ALLOW IN    Anywhere
```

- 併せて以下のポートをルータでポート開放しEthereum NodeにForwardingしておくこと（LAN環境の場合）
30303/tcp&udp
13000/tcp                
12000/udp



# 9.時刻設定

Ubuntu標準であるtimesyncdを使います

systemd-timesyncdがネットワーク時刻同期する機能
timedatectlはsystemd-timesyncdを管理するコントローラーとなります

```bash
$ sudo apt install systemd-timesyncd 
$ timedatectl set-ntp true
$ timedatectl
```

- NICTを参照するように設定
`sudo vim /etc/systemd/timesyncd.conf`

```bash:/etc/systemd/timesyncd.conf
NTP=ntp.nict.jp
```

- 設定反映

```bash
$ sudo systemctl restart systemd-timesyncd.service
```

- ハードウェアクロックを時刻合わせ

```bash
$ sudo hwclock -w
$ sudo hwclock -r
```

- タイムゾーン設定

```bash
$ timedatectl set-timezone Asia/Tokyo
$ timedatectl #確認
$ date #確認
```

# 10. JSON Web Token のキー作成

JWT(JSON Web Token)を作成します。
これはExecution ClientとConsensus Clientが安全に通信するための共通キーとして作用します。
ここではopensslで乱数を生成することでJWTを作成します。

```bash
$ sudo mkdir -p /var/lib/jwtsecret
$ openssl rand -hex 32 | sudo tee /var/lib/jwtsecret/jwt.hex > /dev/null
```

`sudo vim /var/lib/jwtsecret/jwt.hex`で中身を確認してそれらしい文字列が生成できていればOKです。


## 閑話休題

Execution ClientとConsensus Clientはそれぞれマルチクライアントとなっており、代表的なものとして以下のラインナップがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484220/0b677825-f159-df96-fb7f-73ab04a90679.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484220/5011db8d-9be1-7902-422c-2c21b5077833.png)

各ソフトウェアの通信ポートは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484220/70ecbddd-4a79-dbb8-41e1-7ff21d212edc.png)

本記事ではGeth&Prysmを使用していきます。

# 11. Execution Clientのインストール（Geth:Go Ethereum）

- 下記リンクから最新版をダウンロードする

https://geth.ethereum.org/downloads/

```bash
$ curl -LO https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.26-e5eb32ac.tar.gz
$ tar xvf geth-linux-amd64-1.10.26-e5eb32ac.tar.gz 
$ cd geth-linux-amd64-1.10.26-e5eb32ac/

geth-linux-amd64-1.10.26-e5eb32ac$ ll
total 42300
drwxr-xr-x 2 ethereum ethereum     4096 Nov  3 20:19 ./
drwxrwxr-x 3 ethereum ethereum     4096 Nov  4 14:41 ../
-rw-rw-r-- 1 ethereum ethereum    35149 Nov  3 20:16 COPYING
-rwxrwxr-x 1 ethereum ethereum 43269776 Nov  3 20:19 geth*

geth-linux-amd64-1.10.26-e5eb32ac$ sudo cp geth /usr/local/bin/
```

- version確認 `$ /usr/local/bin/geth version`

```go
Geth
Version: 1.10.26-stable
Git Commit: e5eb32acee19cc9fca6a03b10283b7484246b15a
Git Commit Date: 20221103
Architecture: amd64
Go Version: go1.18.5
Operating System: linux
GOPATH=
GOROOT=go
```

- Gethユーザ作成＆dataディレクトリ作成

```bash
$ sudo useradd --no-create-home --shell /bin/false geth
$ sudo mkdir -p /var/lib/geth
$ sudo chown -R geth:geth /var/lib/geth
```

- systemdに登録
`sudo vim /etc/systemd/system/geth.service`

```s:/etc/systemd/system/geth.service
[Unit]
Description=Geth Execution Client (Goerli Testnet)
After=network.target
Wants=network.target

[Service]
User=geth
Group=geth
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/geth \
  --goerli \
  --datadir /var/lib/geth \
  --authrpc.jwtsecret /var/lib/jwtsecret/jwt.hex \
  --metrics \
  --metrics.addr=<host IP address>

[Install]
WantedBy=default.target
```

`--metrics.addr`はPrometheusから見て到達性のある自身のIPアドレスを設定します。

- service起動

```bash
$ sudo systemctl daemon-reload 
$ sudo systemctl start geth
$ sudo systemctl status geth`
#ActiveになっていればOKです

#自動起動有効化
$ sudo systemctl enable geth
```

- ログ確認

```bash
$sudo journalctl -fu geth
```



## メモ：Gethコンソール操作

GethにはコンソールとしてjavascriptによるIPCが用意されている。
以下のコマンドで接続可能。

```bash
geth attach ipc:geth-tutorial/geth.ipc
```

- Sync状況`eth.syncing`
- peer接続数`net.peerCount`
- peer情報`admin.peers`

などを参照することが出来ます。

# 12. Validator Keyを生成

後に必要となるValidator keyを生成します。
ここではCLIツール `staking_deposit_cli` を使う方法を用います。

### マシン1

- ツールをダウンロードします

```bash
curl -LO https://github.com/ethereum/staking-deposit-cli/releases/download/v2.3.0/staking_deposit-cli-76ed782-linux-amd64.tar.gz
```

- USBメモリを挿入し、フォーマットしてマウント

```bash:USBメモリを挿入し、それらしいデバイスを探す
$ sudo fdisk -l

<snip>
Disk /dev/sda: 7.21 GiB, 7743995904 bytes, 15124992 sectors
Disk model: Silicon-Power8G 
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x500a0dff
<snip>
```

```bash:探す
$ sudo lsblk -f
NAME                 FSTYPE      FSVER    LABEL UUID                                   FSAVAIL FSUSE% MOUNTPOINTS
<snip>
sda                  vfat        FAT32    default E481-3F56                                             
<snip>
```

```bash:USBメモリをフォーマット
$ sudo mkfs.vfat -F 32 -n 'MyEth' /dev/sda
mkfs.fat 4.2 (2021-01-31)
```

>mkfs.vfatは指定したデバイスにFATファイルシステムを作成するために使用されます。
mkfs.vfatコマンドを使用することで、USBメモリや外付けHDDなど、WindowsやMacOSとのデータのやり取りが可能なデバイスを作成することができます。

```bash:USBメモリをマウント
$ sudo mkdir /media/external
$ sudo mount /dev/sda /media/external/
$ sudo df -h
Filesystem                         Size  Used Avail Use% Mounted on
<snip>
/dev/sda                           7.2G  4.0K  7.2G   1% /media/external
```

- `staking_deposit_cli`をUSBメモリにコピーしてアンマウント

```bash
$ sudo cp -r staking_deposit-cli-76ed782-linux-amd64 /media/external/
$ sudo umount /media/external
```

### マシン３

- USBメモリを挿入＆マウントし、`staking_deposit_cli`を$HOMEにコピー、解凍。
- 下記のコマンドによりvalidator-keyを生成する（今回は2 validator分のkeyを作成します）

```bash
$ chmod 755 deposit
$ sudo ./deposit new-mnemonic --num_validators 2 --chain goerli
```

- `keystore password`を考えて入力してください → 後ほどマシン１へimportする際に必要になります。
- `mnemonic(seed phrase)`を紙にメモる　★安全かつ確実に保管してください★
- 出来上がった`validator_keys`ディレクトリをUSBメモリに移します


### マシン1

戻ってきて三度USBメモリを挿入しマウントし、`validator_keys`をコピーして持ってきます

```bash
$ sudo mount /dev/sda /media/external/
$ mkdir ~/testnet_keys
$ sudo cp -r /media/external/ /home/ethereum/testnet_keys/

$ sudo ls -l ./
total 20900
-rwxr-xr-x 1 root root 21396536 Nov  4 15:16 deposit
drwxr-xr-x 2 root root     4096 Nov  4 15:16 validator_keys

$ sudo ls -l validator_keys/
total 12
-rwxr-xr-x 1 root root 1410 Nov  4 15:16 deposit_data-1667330975.json
-rwxr-xr-x 1 root root  710 Nov  4 15:16 keystore-m_12381_3600_0_0_0-1667330974.json
-rwxr-xr-x 1 root root  710 Nov  4 15:16 keystore-m_12381_3600_1_0_0-1667330975.json
```

> *keystore-m_.json*がimport対象のJSONファイルです。
*deposit_data-.json*は後述するlaunchpadを経由してdepositコントラクトを発行するために使用します。



# 13. Consensu Client & Validatorのインストール（Prysm）

- 下記リンクから最新版をダウンロードする。手順同じなのでValidatorも一緒にインストールしてしまいます。

https://github.com/prysmaticlabs/prysm/releases

```bash
$ curl -LO https://github.com/prysmaticlabs/prysm/releases/download/v3.1.2/beacon-chain-v3.1.2-linux-amd64
$ curl -LO https://github.com/prysmaticlabs/prysm/releases/download/v3.1.2/validator-v3.1.2-linux-amd64

$ mv beacon-chain-v3.1.2-linux-amd64 beacon-chain
$ mv validator-v3.1.2-linux-amd64  validator

$ chmod +x beacon-chain 
$ chmod +x validator 

$ ll
-rwxrwxr-x  1 ethereum ethereum 103629584 Nov  3 20:41 beacon-chain*
-rwxrwxr-x  1 ethereum ethereum  93784904 Nov  3 20:42 validator*

$ sudo cp beacon-chain /usr/local/bin/
$ sudo cp validator /usr/local/bin/
```

- walletディレクトリ(validator_keyのimport先)を作成します

```bash
$ sudo mkdir -p /var/lib/prysm/validator
$ sudo chown -R ethereum:ethereum /var/lib/prysm/validator/
```

## validator_keyをimport

```bash
$ /usr/local/bin/validator \
 accounts import \
 --keys-dir=/home/ethereum/testnet_keys/validator_keys \
 --wallet-dir=/var/lib/prysm/validator \
 --goerli
```

- 上記コマンドを実行すると確認メッセージが表示されますので`accept`とタイプします。

```bash
Prysmatic Labs Terms of Use

By downloading, accessing or using the Prysm implementation (“Prysm”), you (referenced herein
as “you” or the “user”) certify that you have read and agreed to the terms and conditions below.

TERMS AND CONDITIONS: https://github.com/prysmaticlabs/prysm/blob/master/TERMS_OF_SERVICE.md

Type "accept" to accept this terms and conditions [accept/decline]: (default: decline):
accept
```

- `wallet password`を考えて設定します。
- 続いて、`validator_key`生成時に設定した`keystore password`を入力しimportを実行します。

```bash
[2022-11-04 15:33:33]  WARN flags: Running on the Prater Testnet
Password requirements: at least 8 characters
New wallet password: 
Confirm password: 
[2022-11-04 15:33:45]  INFO accounts: Successfully created new wallet wallet-path=/var/lib/prysm/validator
[2022-11-04 15:33:45]  WARN validator: You are using an insecure gRPC connection. If you are running your beacon node and validator on the same machines, you can ignore this message. If you want to know how to enable secure connections, see: https://docs.prylabs.network/docs/prysm-usage/secure-grpc
Enter the password for your imported accounts: 
Importing accounts, this may take a while...
Importing accounts... 100% [=================================================================================================]  [1s:0s]
Successfully imported 2 accounts, view all of them by running `accounts list`
```

これで2 validator分のvalidator_keyがimportされました。

- `wallet password`をファイル化しておきます。これはprysmがユーザ介助なしにwalletへアクセスするためです。

```bash
$ sudo vim /var/lib/prysm/validator/password.txt
#walletパスワードを手打ちで入力して保存しましょう。
```

- 以下のコマンドで動作確認しましょう。

```bash
$ /usr/local/bin/validator \
 accounts list \
 --wallet-dir=/var/lib/prysm/validator \
 --wallet-password-file=/var/lib/prysm/validator/password.txt \
 --goerli
```



```bash
[2022-11-05 02:15:41]  WARN flags: Running on the Prater Testnet
[2022-11-05 02:15:41]  WARN validator: You are using an insecure gRPC connection. If you are running your beacon node and validator on the same machines, you can ignore this message. If you want to know how to enable secure connections, see: https://docs.prylabs.network/docs/prysm-usage/secure-grpc
(keymanager kind) local wallet

Showing 2 validator accounts
View the eth1 deposit transaction data for your accounts by running `validator accounts list --show-deposit-data`

Account 0 | grossly-suited-mouse
[validating public key] <snip>

Account 1 | only-expert-lemur
[validating public key] <snip>
```

## beacon nodeを設定

- beacon nodeとはconsensus clientのことbeacon chainを扱うconsensus layerで動作します。具体的にはprysmを構成するモジュールの１つと言えます。
- 専用のユーザ`prysmbeacon`を作成します。

```bash
$ sudo useradd --no-create-home --shell /bin/false prysmbeacon
$ sudo mkdir -p /var/lib/prysm/beacon
$ sudo chown -R prysmbeacon:prysmbeacon /var/lib/prysm/beacon
```

- service設定を行います。

`$ sudo vim /etc/systemd/system/prysmbeacon.service`

```bash:/etc/systemd/system/prysmbeacon.service
[Unit]
Description=Prysm Consensus Beacon Node(Goerli Testnet)
Wants=network-online.target
After=network-online.target
[Service]
User=prysmbeacon
Group=prysmbeacon
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/beacon-chain \
  --goerli \
  --datadir=/var/lib/prysm/beacon \
  --http-web3provider=http://127.0.0.1:8551 \
  --jwt-secret=/var/lib/jwtsecret/jwt.hex \
  --suggested-fee-recipient=<FeeRecipientAddress> \
  --enable-debug-rpc-endpoints \
  --grpc-max-msg-size=65568081 \
  --checkpoint-sync-url=https://goerli.checkpoint-sync.ethdevops.io \
  --genesis-beacon-api-url=https://goerli.checkpoint-sync.ethdevops.io \
  --accept-terms-of-use \
  --monitoring-host=<host IP address>

[Install]
WantedBy=multi-user.target
```

`--suggested-fee-recipient`はTransactionのGas代の一部であるチップ(Priority Fee)が入金されるaddressを指定します。これはExecution Layer(旧ETH1) addressを指定しましょう。特に拘りがなければとりあえず最初に準備したEOAのaddressを指定しておけばいいです。

`--monitoring-host`は後述するPrometheus監視の際に使用する自身のIPアドレスです。Prometheusサーバから見た時に到達性のあるホストIPアドレスを指定してください。

- beacon node起動

```bash
$ sudo systemctl daemon-reload 
$ sudo systemctl start prysmbeacon
$ sudo systemctl status prysmbeacon
#activeになっていればOKです。

#自動起動有効化
$ sudo systemctl enable prysmbeacon
```

- 動作ログ確認

```bash
$ sudo journalctl -fu prysmbeacon
```


### Validatorを設定

- validatorもconsensus layerで動作するprysmソフトウェア群の1つですが、beacon nodeとは別プロセスとなります。
- 実行するユーザ`prysmvalidator`も専用に設けます。

```bash
$ sudo useradd --no-create-home --shell /bin/false prysmvalidator
$ sudo mkdir -p /var/lib/prysm/validator
$ sudo chown -R prysmvalidator:prysmvalidator /var/lib/prysm/validator

$ sudo ls -l /var/lib/prysm/
total 8
drwxr-xr-x 3 prysmbeacon    prysmbeacon    4096 Nov 15 19:19 beacon
drwxr-xr-x 3 prysmvalidator prysmvalidator 4096 Nov  4 15:50 validator
```


- service登録
`$ sudo vim /etc/systemd/system/prysmvalidator.service`

```bash:/etc/systemd/system/prysmvalidator.service
[Unit]
Description=Prysm Consensus Validator Node(Goerli Testnet)
Wants=network-online.target
After=network-online.target
[Service]
User=prysmvalidator
Group=prysmvalidator
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/validator \
  --datadir=/var/lib/prysm/validator \
  --wallet-dir=/var/lib/prysm/validator \
  --wallet-password-file=/var/lib/prysm/validator/password.txt \
  --graffiti="<aaaaaaa>" \
  --accept-terms-of-use \
  --monitoring-host=<host IP address>
[Install]
WantedBy=multi-user.target
```

`--graffiti`はコメントみたいなものらしい（未確認）
`--monitoring-host`は先ほどと同じく自分のIPアドレスを指定します。


```bash
$ sudo systemctl daemon-reload 
$ sudo systemctl start prysmvalidator
$ sudo systemctl status prysmvalidator
#activeになっていればOKです。

#自動起動有効化
$ sudo systemctl enable prysmvalidator
```

- 動作ログ確認

```bash
$ sudo journalctl -fu prysmvalidator
```

この時点ではまだdepositが完了していないので、
`msg="Waiting for deposit to be observed by beacon node"`
といったメッセージが出力され続けます。

# 14.Staking

ここまでで待ちに待ったステーキングの準備が整いました。
さて2022年11月現在、Goerliでステーキングするための手段は大きく分けて2通りあります。

① 32goETHを自分で入手してdepositする
② 0.0001goETHだけ出資して、代理で32goETHをdepositしてもらう

### ① 32goETHを自分で入手してdepositする

goETHはPoW終了後の入手難度が以前に比べると上がっています。
Faucetでの供給は1goETH/dayに満たない所が大半ですので、地道に集めるのはそれなりに労力と時間を要します。
ステーブルコインと交換する売買サイトもありますのでどうしても自分で用意したい方は見つけてください。
存在がグレーかもしれないのでここに掲載するのは控えておきます。


### ② 0.0001goETHだけ出資して、代理で32goETHをdepositしてもらう

本記事ではこちらの方法を紹介します。
こちらの方法もいつまでも持続可能かは不透明です。

以下に箇条書きで手順を列挙します。


1. Discordで[ethstaker](https://discord.com/invite/xcGYmXwG97)サーバに登録します。
2. [/cheap-goerli-validator](https://discord.com/channels/694822223575384095/1026679645808119868) チャンネルに参加します。
3. 24時間くらい寝かします。(Abuse対策による制限のため)
4. `/cheap-goerli-validator`と投稿します。
5. BOTの指示に従い、signer.isに飛んで承諾し、MetaMaskと接続設定を行います。
6. Linkが生成されるのでクリップボードにコピーします。
7. Discordに戻ってきて貼り付けます。
8. 成功すればBOTから`You can now perform 2 cheap deposits on～`と返答があります。
9. 指示に従い専用のLaunchpad`https://goerli.launchpad.ethstaker.cc`へ移動しチュートリアルに従って進めます。見た目は通常のlaunchpadと似ていますが、staking必要量が0.0001goETH/validatorに引き下げられています。
10. depositファイルを求められたら、生成済みの`deposit_data-.json`をD&DしてUploadします。
11. launchpadからdepositコントラクトが発行され、Metamaskが反応します。問題なければConfirmしましょう。EOAから中継CAに0.0001goETH支払います。
12. すると中継CAからInternal Transactionが発行され本来のdeposit-CAへ32goETHが支払われます。差額分は中継CAが負担してくれる仕組みです。

以上で完了です。
繰り返しますが、あくまで自己責任でお願いします。

depositが完了すればBeacon ChainにValidatorアカウントが自動的に払い出されます。
進捗はgoerli用のbeaconcha.inなどで進捗を確認できます。
16時間くらいPendingの状態で待たされた後、Activeに遷移します。

https://goerli.beaconcha.in/

待っている間に、監視ノードのセットアップをしていきます。



# 15.監視ノード(Prometheus + Grafana)設定

### マシン１(Ethereum Node)：Node-exporterインストール

まずはEhtereum Nodeに`node-exporter`をセットアップします。`node-exporter`はPrometheusに各種Metricsを転送するエージェントです。（正確にはPrometheusがPullしに来た時に応答する待ち受けエージェントという表現が正しいです）

- ダウンロード(最新版を探してきましょう)

https://github.com/prometheus/node_exporter

```bash
$ wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz
$ tar xvf node_exporter-1.5.0.linux-amd64.tar.gz
```

- 実行ユーザ作成

```bash
$ sudo useradd --no-create-home --shell /bin/false nodeexporter
$ sudo mkdir -p /var/lib/node_exporter
$ sudo chown -R nodeexporter:nodeexporter /var/lib/node_exporter
```

- /user/local/bin/へ配置

```bash
$ cd node_exporter-1.5.0.linux-amd64/

$ ls -l node_exporter ※実行権限ついてることを確認
-rwxr-xr-x 1 ethereum ethereum 19779640 Nov 30 03:59 node_exporter*

$ sudo cp node_exporter /usr/local/bin/

$ sudo ls -l /usr/local/bin/node_exporter 
-rwxr-xr-x 1 root root 19779640 Nov 30 23:12 /usr/local/bin/node_exporter
```

- service登録
`sudo vim /usr/lib/systemd/system/prometheus_node_exporter.service`

```bash
[Unit]
Description=Node Exporter for Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=nodeexporter
Group=nodeexporter
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/node_exporter
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no
 
[Install]
WantedBy=multi-user.target
```


```bash
$ sudo systemctl daemon-reload

#設定反映を確認
$ sudo systemctl list-unit-files | grep prometheus
prometheus_node_exporter.service           disabled        enabled

#起動
$ sudo systemctl start prometheus_node_exporter.service 
$ sudo systemctl status prometheus_node_exporter.service

#自動起動有効化
$ sudo systemctl enable prometheus_node_exporter.service 
```

- ログ確認

```bash
$ sudo journalctl -fu prometheus_node_exporter
```

### マシン２：Prometheusセットアップ

本記事は監視ノードにラズパイを使います。（なるべくライトに省電力で運用したいので）

https://www.raspberrypi.com/software/

Raspberry Pi OS (64-bit)を選択してセットアップしておきます。
DebianベースなのでUbuntuとコマンド体系が似ています。


-  Prometheusインストール

```bash
$ sudo apt install prometheus
```

`sudo vim /etc/prometheus/prometheus.yml`に下記設定を追記します。

```bash:/etc/prometheus/prometheus.yml
#Ethereum Validator Node
  - job_name: 'ethereum host'
    static_configs:
      - targets: ['<target IP address>:9100']

  - job_name: 'beacon node'
    static_configs:
      - targets: ['<target IP address>:8080']

  - job_name: 'validator'
    static_configs:
      - targets: ['<target IP address>:8081']

  - job_name: 'slasher'
    static_configs:
      - targets: ['<target IP address>:8082']
```

`<target  IP address>`はValidator Node(マシン1)のIPアドレスを設定します。
`ethereum host`がnode-exporterの待ち受けポート9100番と対になります。
`slasher`は今回は運用しませんのでなくてもOKです。

- 起動

```bash
$ sudo systemctl start prometheus
```

作業用PCのブラウザから `http://<監視ノードIP>:9090`で動作確認します。


### マシン２：Grafanaセットアップ

https://grafana.com/tutorials/install-grafana-on-raspberry-pi/

```bash
$ wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
$ echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
$ sudo apt-get update
$ sudo apt-get install -y grafana
$ sudo /bin/systemctl enable grafana-server
$ sudo /bin/systemctl start grafana-server
```

作業用PCのブラウザから `http://<監視ノードIP>:3000`で動作確認します。
usernameは`admin`、初期パスも`admin`です。

- Dashboard設定
Grafanaは好みのDashboardを設定できます。
JSONファイルをダウンロードして、Grafanaの設定画面からImportしましょう。

https://grafana.com/grafana/dashboards/

いくつか列挙しておきます。

prysm用
https://docs.prylabs.network/assets/grafana-dashboards/big_amount_validators.json

Node-exporter用
https://grafana.com/grafana/dashboards/1860-node-exporter-full/

https://grafana.com/grafana/dashboards/16277-ethereum-metrics-exporter-single/



以上で一通り完了です。お疲れ様でした。


# 参考リンク

[Guide to Staking on Ethereum (Ubuntu/Goerli/Prysm)](https://someresat.medium.com/guide-to-staking-on-ethereum-ubuntu-goerli-prysm-4a640794e8b5)