이 문서는 Ethereum PoS Private Network 를 구성하고, 스테이킹을 실습하는 내용을 담고 있습니다.
2025-10-21 기준, Pectra 하드포크까지 대응되어 있습니다.
실습 과정 중 Tx 전송용도로 아래 Genesis 지갑을 사용합니다.
0x9F39d0203939B4814Acd739015359DCDD181103a
- PK: 0x7f1d861692e78341d5da1c6f45aa7159af233cfba232c76b5dea3fdea19e67c0
아래 도구들을 설치합니다. (bin/ 디렉토리의 바이너리는 별도 설치 불필요)
| 도구 | 용도 |
|---|---|
| Homebrew | macOS 패키지 설치 |
| OrbStack | 컨테이너 실행 (docker compose) |
| Geth | 실행계층 Genesis 초기화 (geth init) |
| direnv | .envrc 활성화로 ./bin 경로 자동 추가 |
| curl | Foundry installer 다운로드 |
| jq | staking 스크립트에서 deposit_data-*.json 파싱 |
| Foundry | staking 스크립트에서 Deposit Contract 호출 (cast send) |
brew install --cask orbstack
brew install ethereum direnv curl jq
curl -L https://foundry.paradigm.xyz | bash
foundryupdirenv 셸 훅 등록 (최초 1회)
# ~/.zshrc 또는 ~/.bashrc 에 추가 eval "$(direnv hook zsh)" # zsh 사용 시 eval "$(direnv hook bash)" # bash 사용 시이후 이 디렉토리에서
direnv allow를 실행하면./bin경로가 자동으로 PATH 에 추가됩니다.
- direnv 를 통해
.envrc를 활성화합니다.direnv allow
init를 실행해 Genesis 를 구성합니다.docker compose up으로 네트워크를 시작합니다.
Consensus : Prysm v6.0.4
Execution : Geth v1.16.2
Blockscout : v9
- consensus
- 합의계층이며, https://github.com/OffchainLabs/prysm 을 사용합니다.
- execution
- 실행계층이며, https://github.com/ethereum/go-ethereum 를 사용합니다.
- validator
- consensus 와 연결된 검증자 클라이언트이며, https://github.com/OffchainLabs/prysm 을 사용합니다.
- 스테이킹 없이 체인이 작동할 수 있도록 Dummy Validator Key 로 검증하도록 구성되어있습니다.
- practice-validator
- 직접 Validator Key 를 생성하고, Import 하여 스테이킹 실습을 진행할 Client 입니다.
- validator 와 동일한 검증자 클라이언트 입니다.
- 24Words Mnemonic 생성하기 (ex https://iancoleman.io/bip39/)
create-validator-key로 Validator Key 를 생성합니다.- 생성 과정중에서 Mnemonic 을 요구하면, 1번에서 생성한 Mnemonic 을 입력합니다.
./validator_keys하위에 아래 두개 파일이 생성되었는지 확인합니다.deposit_data-*.jsonkeystore-*.json
practice-validator컨테이너의 로그를 확인합니다.- 로그 중,
http://0.0.0.0:7500/initialize?token=…URL 을 복사해 브라우저에서 접속합니다. - Import Keystores > Browse Files 로 Validator Key file 을 선택합니다.
- Validator Key 생성과정에서 만든
keystore-*.json를 선택합니다.
- Validator Key 생성과정에서 만든
- Key 생성과정에서 입력했던 비밀번호를 입력합니다.
Import slashing protection data?는 no 를 선택 후, 다음단계로 이동합니다.- Wallet Password 는 헷갈리지 않도록 기존 비밀번호와 동일하게 입력합니다.
- Validator Client 에서 해당 Key 를 파일시스템에 암호화 하여 보관시에 사용할 비밀번호입니다.
아래 두 가지 방법 중 하나를 선택해 Deposit 을 진행합니다.
Staking Script (Recommended)방식을 권장합니다.
staking스크립트는 Foundry 의cast를 사용해 Deposit Contract 를 호출합니다.RPC, Private Key, Deposit Contract, Gas 설정은
.envrc에서 관리합니다.
- Validator Key 생성 과정에서
./validator_keys/deposit_data-*.json파일이 생성되어 있는지 확인합니다. - 아래 명령어를 실행합니다.
staking
- 기본값으로 최신
./validator_keys/deposit_data-*.json파일을 사용합니다. - Tx 가 전송되면 Transaction Hash 를 출력하고, Receipt 가 생성될 때까지 주기적으로 대기 메시지를 출력합니다.
- 기본값으로 최신
- Pending Tx 를 더 높은 Gas 로 대체해야 하는 경우 nonce 를 지정해서 다시 실행합니다.
NONCE=0 staking
Explorer 로 직접 Write Contract 를 실행하고 싶다면 먼저 아래의
Explorer 구성하기 (Optional)을 완료합니다.
- Explorer 검색창에
0x00000000219ab540356cbb839cbe05303d7705fa를 검색합니다.- 이 과정을 생략하는 경우 Verify Contract 과정에서
알 수 없는 주소에러가 발생하므로, 꼭 진행합니다.
- 이 과정을 생략하는 경우 Verify Contract 과정에서
- Explorer > 좌측 톱니바퀴 (Other) > Verify Contract
- 아래 정보를 기입후
Verify & publish를 실행합니다.아래 정보는 Mainnet Etherscan 데이터를 기준으로 합니다.
이 과정 중 발생한 에러가 아래와 같다면, 다음 과정으로 넘어가도 무방합니다.
Cannot update partially verified smart contract with another partially verified contract- Contract Address :
0x00000000219ab540356cbb839cbe05303d7705fa - Contract License :
No License - Verify Method :
Solidity (Single file) - Compiler :
v0.6.11+commit.5ef660b1 - EVM Version :
istanbul - Optimization enabled :
체크 및 5000000 기입 - Contract Code :
DepositContract.sol확인
- Contract Address :
-
0x00000000219ab540356cbb839cbe05303d7705fa주소를 검색해 Contract Details 로 이동합니다. - Contract 탭 >
Read/Write contract>deposit을 선택합니다. - Validator Key 생성 과정에서 생성된
deposit_data*.json파일을 열어 값을 채워 넣습니다.- 모두
0xprefix 를 추가하여 입력해야합니다. ex)abcd1234→0xabcd1234 - Send native ETH 는
32를 입력 후, 우측$10^{18}$ 버튼을 눌러 Wei 단위로 변환합니다.
- 모두
-
Write를 눌러 Tx 를 전송합니다. - Validator 가 활성화 될때까지 기다립니다. 🔃
Explorer 는 필수 구성요소가 아닙니다.
Deposit 은 기본적으로
staking스크립트로 진행하고, Explorer UI 를 통해 Deposit 하고 싶은 경우에만 구성합니다.
-
Blockscout 를 Clone 받습니다.
-
docker-compose/common-frontend.env를 아래와 같이 수정합니다.- 예시를 사용하거나, Docs 를 참고해 원하는 값으로 변경해도 무방합니다 🙂
common-frontend.env예시NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID 는 아래 메뉴얼에 따라 프로젝트 생성 후 채워넣습니다.
NEXT_PUBLIC_API_HOST=localhost NEXT_PUBLIC_API_PROTOCOL=http NEXT_PUBLIC_STATS_API_HOST=http://localhost:8080 NEXT_PUBLIC_NETWORK_NAME=Private Local Chain NEXT_PUBLIC_NETWORK_SHORT_NAME=Private Local Chain NEXT_PUBLIC_NETWORK_ID=123456 NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18 NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_APP_HOST=localhost NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] NEXT_PUBLIC_VISUALIZE_API_HOST=http://localhost:8081 NEXT_PUBLIC_IS_TESTNET=true NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=<WALLET_CONNECT_PROJECT_ID> NEXT_PUBLIC_NETWORK_RPC_URL=http://localhost:8545 NEXT_PUBLIC_AD_BANNER_PROVIDER=none NEXT_PUBLIC_AD_TEXT_PROVIDER=none NEXT_PUBLIC_HAS_BEACON_CHAIN=true
-
./docker-compose위치에서 아래 명령어를 통해 Explorer 를 구동합니다.docker compose -f geth.yml up -d
-
브라우저에서
http://localhost에 접속해 Explorer 를 확인해봅니다. -
메인화면 우측 상단
Connect를 클릭해 Metamask 등을 통해 지갑을 연결합니다.- 연결 하는 지갑은 문서 도입부에서 안내된 Genesis Wallet 을 사용합니다.
- Validator Web UI > 좌측 Wallet & Accounts > Exit Validators 과정으로 언스테이킹 진행
- Beacon node 의 Validator 상태 조회 API 를 호출해서 Validator 상태가 변경되는것을 확인
- http://localhost:3500/eth/v1/beacon/states/finalized/validators/:pubkey
- 상태는
active_ongoing→active_exiting→exited_unslashed→withdrawal_possible→withdrawal_done순으로 변화 - 각 상태별 의미는 https://docs.figment.io/docs/lifecycle-eth-validator 에서 확인