├── .github └── workflows │ ├── deploy-stader-node.yml │ └── go.yml ├── .gitignore ├── .golangci.yml ├── .idea ├── .gitignore ├── modules.xml ├── stader-node.iml └── vcs.xml ├── LICENSE ├── README.md ├── abis ├── NodeElRewardVault.abi.json ├── OperatorRewardsCollector.abi.json ├── Penalty.abi.json ├── PermissionlessNodeRegistry.abi.json ├── PermissionlessPool.abi.json ├── PoolUtils.abi.json ├── SDUtilityPool.abi.json ├── SdCollateral.abi.json ├── SocializingPool.abi.json ├── StaderConfig.abi.json ├── StakePoolManager.abi.json ├── ValidatorWithdrawVault.abi.json └── VaultFactory.abi.json ├── add-gplv3.sh ├── build-builder.sh ├── build-ec-migrate.sh ├── build-release.sh ├── daemon-build.sh ├── daemon-local.sh ├── docker ├── stader-dockerfile ├── stader-ec-migrator ├── stader-node-builder └── stader-prune-provision ├── go.mod ├── go.sum ├── install.sh ├── install ├── addons │ └── gww │ │ └── .ignoreme ├── grafana-prometheus-datasource.yml ├── override │ ├── addons │ │ └── gww │ │ │ └── addon_gww.yml │ ├── api.yml │ ├── eth1.yml │ ├── eth2.yml │ ├── exporter.yml │ ├── grafana.yml │ ├── guardian.yml │ ├── mev-boost.yml │ ├── node.yml │ ├── prometheus.yml │ └── validator.yml ├── prometheus.tmpl ├── scripts │ ├── NethermindPruneStarter │ │ ├── NethermindPruneStarter.deps.json │ │ ├── NethermindPruneStarter.dll │ │ ├── NethermindPruneStarter.runtimeconfig.json │ │ └── Newtonsoft.Json.dll │ ├── restart-vc.sh │ ├── start-bn.sh │ ├── start-ec.sh │ ├── start-mev-boost.sh │ ├── start-vc.sh │ └── stop-validator.sh └── templates │ ├── addons │ └── gww │ │ └── addon_gww.tmpl │ ├── api.tmpl │ ├── eth1.tmpl │ ├── eth2.tmpl │ ├── exporter.tmpl │ ├── grafana-prometheus-datasource.tmpl │ ├── grafana.tmpl │ ├── guardian.tmpl │ ├── mev-boost.tmpl │ ├── node.tmpl │ ├── prometheus.tmpl │ └── validator.tmpl ├── license-short.txt ├── shared ├── services │ ├── bc-manager.go │ ├── beacon │ │ ├── client.go │ │ └── client │ │ │ ├── std-http-client.go │ │ │ └── types.go │ ├── config │ │ ├── besu-params.go │ │ ├── bitfly-beaconchain-config.go │ │ ├── config-legacy.go │ │ ├── consensus-common-config.go │ │ ├── dev-presign-public-key.txt │ │ ├── execution-common-config.go │ │ ├── exporter-config.go │ │ ├── external-configs.go │ │ ├── fallback-configs.go │ │ ├── geth-params.go │ │ ├── grafana-config.go │ │ ├── lighthouse-config.go │ │ ├── lodestar-config.go │ │ ├── mev-boost-config.go │ │ ├── native-config.go │ │ ├── nethermind-params.go │ │ ├── nimbus-config.go │ │ ├── prod-presign-public-key.txt │ │ ├── prometheus-config.go │ │ ├── prysm-config.go │ │ ├── stader-config.go │ │ ├── stadernode-config.go │ │ ├── stage-presign-public-key.txt │ │ └── teku-config.go │ ├── contracts │ │ └── beacon-deposit.go │ ├── ec-manager.go │ ├── eth1.go │ ├── gas │ │ ├── etherchain │ │ │ └── etherchain.go │ │ ├── etherscan │ │ │ └── etherscan.go │ │ └── gas.go │ ├── passwords │ │ └── manager.go │ ├── requirements.go │ ├── services.go │ ├── stader │ │ ├── api.go │ │ ├── client.go │ │ ├── command.go │ │ ├── external-urls.go │ │ ├── fee-recipient.go │ │ ├── gas.go │ │ ├── legacy-client.go │ │ ├── node.go │ │ ├── service.go │ │ └── wallet.go │ ├── state │ │ ├── manager.go │ │ └── network-state.go │ └── wallet │ │ ├── keystore │ │ ├── keystore.go │ │ ├── lighthouse │ │ │ └── keystore.go │ │ ├── lodestar │ │ │ └── keystore.go │ │ ├── nimbus │ │ │ └── keystore.go │ │ ├── prysm │ │ │ └── keystore.go │ │ └── teku │ │ │ └── keystore.go │ │ ├── node.go │ │ ├── validator.go │ │ └── wallet.go ├── types │ ├── api │ │ ├── api.go │ │ ├── node.go │ │ ├── service.go │ │ └── wallet.go │ ├── config │ │ ├── parameter.go │ │ └── types.go │ ├── eth2 │ │ ├── types.go │ │ └── types_encoding.go │ └── stader-backend │ │ ├── merkle-proofs.go │ │ ├── node-diversity.go │ │ └── pre-sign.go ├── utils │ ├── api │ │ ├── response.go │ │ └── utils.go │ ├── arr-utils │ │ └── arr.go │ ├── cli │ │ ├── check_client_status.go │ │ ├── prompt.go │ │ ├── prompt_unix.go │ │ ├── prompt_windows.go │ │ ├── utils.go │ │ └── validation.go │ ├── crypto │ │ ├── base64.go │ │ └── rsa.go │ ├── eth1 │ │ └── eth1.go │ ├── eth2 │ │ └── eth2.go │ ├── hex │ │ └── hex.go │ ├── log │ │ ├── colors.go │ │ └── logger.go │ ├── math │ │ └── math.go │ ├── net │ │ ├── http.go │ │ └── net.go │ ├── stader │ │ ├── merkle-proof-download.go │ │ ├── node-diversity.go │ │ └── pre-signed-flows.go │ ├── stdr │ │ ├── config.go │ │ ├── fee-recipient.go │ │ └── validator-state.go │ ├── string-utils │ │ └── str-convs.go │ ├── sys │ │ └── cpu-flags.go │ ├── term │ │ ├── term_unix.go │ │ └── term_windows.go │ ├── validator │ │ ├── bls.go │ │ ├── deposit-data.go │ │ ├── fee-recipient.go │ │ └── voluntary-exit.go │ └── wallet │ │ └── recover-keys.go └── version.go ├── sszgen.sh ├── stader-cli ├── build.sh ├── node │ ├── approve-sd.go │ ├── claim-rewards.go │ ├── claim-sp-rewards.go │ ├── commands.go │ ├── deposit-sd.go │ ├── download-sp-merkle-proofs.go │ ├── get-contracts-info.go │ ├── register.go │ ├── repay-sd.go │ ├── send-el-rewards.go │ ├── send.go │ ├── sign-message.go │ ├── status.go │ ├── sync.go │ ├── update-operator-name.go │ ├── update-operator-reward-address.go │ ├── update-socialize-el.go │ ├── utilize-sd.go │ └── withdraw-sd.go ├── service │ ├── commands.go │ ├── config.go │ ├── configConsensus.go │ ├── configExecution.go │ ├── configFallback.go │ ├── configMEVBoost.go │ ├── configMonitoring.go │ ├── guardian.tmpl │ ├── migration.go │ └── service.go ├── stader-cli.go ├── validator │ ├── commands.go │ ├── deposit.go │ ├── exit-validator.go │ ├── export.go │ ├── send-cl-rewards.go │ └── status.go └── wallet │ ├── bip39 │ └── mnemonic-validator.go │ ├── commands.go │ ├── export.go │ ├── init.go │ ├── purge.go │ ├── recover.go │ ├── status.go │ └── utils.go ├── stader-lib ├── README.md ├── contracts │ ├── erc20.go │ ├── node-el-reward-vault.go │ ├── operator-rewards-collector.go │ ├── penalty.go │ ├── permissionless-node-registry.go │ ├── permissionless-pool.go │ ├── pool-utils.go │ ├── sd-collateral.go │ ├── sd-utility.go │ ├── socializing-pool.go │ ├── stader-config.go │ ├── stake-pool-manager.go │ ├── validator-withdraw-vault.go │ ├── vault-factory.go │ └── vault-proxy.go ├── node │ ├── node.go │ ├── operator.go │ └── validator.go ├── penalty-tracker │ └── penalty-tracker.go ├── pool-utils │ └── pool-utils.go ├── sd-collateral │ └── sd-deposit.go ├── sdutility │ └── sd-utility.go ├── socializing-pool │ └── rewards.go ├── stader-config │ └── stader-config.go ├── stader │ ├── abi.go │ ├── contract.go │ ├── ec-interface.go │ └── stader.go ├── stake-pool-manager │ └── stake-pool-manager.go ├── tokens │ ├── erc20.go │ └── native.go ├── types │ ├── beacon.go │ ├── operator.go │ ├── pool-utils.go │ ├── sd-collateral.go │ ├── socializing-pool.go │ └── validator.go └── utils │ ├── eth │ ├── transactions.go │ └── units.go │ ├── json │ └── json.go │ ├── sd │ └── sd.go │ └── wait.go ├── stader ├── api │ ├── api.go │ ├── node │ │ ├── claim-rewards.go │ │ ├── claim-sp-rewards.go │ │ ├── commands.go │ │ ├── deposit-sd.go │ │ ├── download-sp-merkle-proofs.go │ │ ├── get-contracts-info.go │ │ ├── register.go │ │ ├── repay-sd.go │ │ ├── sd-status.go │ │ ├── send-el-rewards.go │ │ ├── send.go │ │ ├── sign-message.go │ │ ├── sign.go │ │ ├── status.go │ │ ├── sync.go │ │ ├── update-operator-name.go │ │ ├── update-operator-reward-address.go │ │ ├── update-socialize-el.go │ │ ├── utility-sd.go │ │ └── withdraw-sd.go │ ├── service │ │ ├── commands.go │ │ ├── status.go │ │ └── terminate.go │ ├── validator │ │ ├── commands.go │ │ ├── deposit.go │ │ ├── exit.go │ │ └── send-cl-rewards.go │ └── wallet │ │ ├── commands.go │ │ ├── export.go │ │ ├── init.go │ │ ├── purge.go │ │ ├── recover.go │ │ ├── set-password.go │ │ └── status.go ├── build.sh ├── ec_migrate multi.sh ├── ec_migrate.sh ├── guardian │ ├── collector │ │ ├── beacon-chain-collector.go │ │ ├── constants.go │ │ ├── network-collector.go │ │ ├── operator-collector.go │ │ └── state-locker.go │ ├── guardian.go │ └── metrics-exporter.go ├── node │ ├── manage-fee-recipient.go │ ├── merkle-proofs-download.go │ ├── node.go │ └── node_test.go ├── prune_provision.sh └── stader.go ├── update-abis.sh └── update_package.sh /.github/workflows/deploy-stader-node.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Stader Node 2 | on: 3 | workflow_dispatch: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | id-token: write 10 | contents: read 11 | 12 | jobs: 13 | BUILD_AND_PUBLISH_STADER_PERMISSIONLESS_CLI_NODE: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | env: 18 | AWS_REGION : "us-east-1" 19 | 20 | steps: 21 | 22 | - name: Install binaries to build stader node 23 | uses: awalsh128/cache-apt-pkgs-action@latest 24 | with: 25 | packages: qemu-user-static binfmt-support 26 | 27 | - name: Initializing multiarch build environment. 28 | run: | 29 | docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 30 | 31 | - uses: actions/checkout@v3 32 | 33 | - name: Docker meta 34 | id: meta 35 | uses: yuya-takeyama/docker-tag-from-github-ref-action@v1 36 | with: 37 | remove-version-tag-prefix: false 38 | 39 | - name: Prepare to upload binaries to s3 40 | uses: aws-actions/configure-aws-credentials@v1 41 | with: 42 | role-to-assume: ${{ secrets.ETHX_STADER_NODE_PUBLISH_ROLE_ARN }} 43 | role-duration-seconds: 1200 44 | role-session-name: githubActionsSession 45 | aws-region: ${{ env.AWS_REGION }} 46 | 47 | - name: Login to Docker Hub 48 | uses: docker/login-action@v2 49 | with: 50 | username: ${{ secrets.DOCKERHUB_USERNAME }} 51 | password: ${{ secrets.DOCKERHUB_TOKEN }} 52 | 53 | - name: Build & Release Stader Node CLI 54 | run: | 55 | ./build-release.sh -a -v ${{ steps.meta.outputs.tag }} 56 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: ["main"] 9 | pull_request: 10 | branches: ["main"] 11 | 12 | jobs: 13 | lint: 14 | name: Lint 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Set up Go 1.21 21 | uses: actions/setup-go@v5 22 | with: 23 | go-version: '1.21' 24 | cache: false 25 | 26 | - name: Golangci-lint 27 | uses: golangci/golangci-lint-action@v4 28 | with: 29 | version: latest 30 | args: --timeout 3m --verbose --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number 31 | only-new-issues: true 32 | build: 33 | name: Build 34 | runs-on: ubuntu-latest 35 | steps: 36 | - name: Set up Go 1.x 37 | uses: actions/setup-go@v5 38 | with: 39 | go-version: '1.21' 40 | cache: false 41 | 42 | - name: Check out code into the Go module directory 43 | uses: actions/checkout@v4 44 | 45 | - name: Get dependencies 46 | run: | 47 | go get -v -t -d ./... 48 | - name: Test 49 | run: go test -v ./... 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, built with `go test -c` 8 | *.test 9 | 10 | .idea 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | /build 15 | # Dependency directories (remove the comment below to include it) 16 | # vendor/ 17 | #stader 18 | #stader-cli 19 | #.vscode 20 | .DS_Store 21 | #stader-cli/stader-cli 22 | 23 | *.log 24 | 25 | .vscode/launch.json 26 | stader-cli/stader-cli 27 | stader/__debug_bin 28 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-type-assertions: true 4 | goconst: 5 | min-len: 2 6 | min-occurrences: 3 7 | gocritic: 8 | enabled-tags: 9 | - diagnostic 10 | - experimental 11 | - opinionated 12 | - performance 13 | - style 14 | govet: 15 | check-shadowing: true 16 | nolintlint: 17 | require-explanation: true 18 | require-specific: true 19 | 20 | linters: 21 | disable-all: true 22 | enable: 23 | - bodyclose 24 | - unused 25 | - dogsled 26 | - dupl 27 | - errcheck 28 | - exportloopref 29 | - exhaustive 30 | - goconst 31 | - gocritic 32 | - gofmt 33 | - goimports 34 | # - gocyclo 35 | - gosec 36 | - gosimple 37 | - govet 38 | - ineffassign 39 | - misspell 40 | - nolintlint 41 | - nakedret 42 | - prealloc 43 | - predeclared 44 | - revive 45 | - staticcheck 46 | - thelper 47 | - tparallel 48 | - typecheck 49 | - unconvert 50 | - unparam 51 | - whitespace 52 | - wsl 53 | issues: 54 | new-from-rev: 934d61944a2565b9e099f2cef2702c0937d743ad 55 | run: 56 | issues-exit-code: 0 -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/stader-node.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Stader Node and EthX 2 | 3 | ETHx is an innovative liquid staking token developed by Stader, designed to revolutionize Ethereum staking. Our vision for ETHx is to transform the staking experience, providing users with the unprecedented freedom to move and utilize their staked ETH while continuing to earn rewards and engage with the growing DeFi ecosystem. 4 | 5 | ETHx is built to reduce technical and capital barriers to running nodes on Ethereum and empowering smaller node operators is of the highest importance for Stader. Stader’s ETHx permissionless pool lets anyone operate a node with 4.4 ETH of asset collateral [4 ETH + 0.4ETH worth of SD (Stader’s governance token)]. 6 | 7 | This repo contains code for the stader-cli which allows users to easily join EthX permissionless pool and become a crucial part in Stader's missions to revolutionize Ethereum Staking! 8 | 9 | ## Documentation 10 | 11 | NOs can find documentation w.r.t setting a system requirements, how to set a node up, the latest binaries etc here https://staderlabs.gitbook.io/ethereum/ 12 | 13 | ## Integration testing 14 | 15 | Upcoming 16 | -------------------------------------------------------------------------------- /abis/NodeElRewardVault.abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "inputs": [ 9 | { 10 | "internalType": "address", 11 | "name": "recipient", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "uint256", 16 | "name": "amount", 17 | "type": "uint256" 18 | } 19 | ], 20 | "name": "ETHTransferFailed", 21 | "type": "error" 22 | }, 23 | { 24 | "inputs": [], 25 | "name": "NotEnoughRewardToWithdraw", 26 | "type": "error" 27 | }, 28 | { 29 | "inputs": [], 30 | "name": "TransferFailed", 31 | "type": "error" 32 | }, 33 | { 34 | "anonymous": false, 35 | "inputs": [ 36 | { 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "sender", 40 | "type": "address" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "amount", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "ETHReceived", 50 | "type": "event" 51 | }, 52 | { 53 | "anonymous": false, 54 | "inputs": [ 55 | { 56 | "indexed": false, 57 | "internalType": "address", 58 | "name": "staderConfig", 59 | "type": "address" 60 | } 61 | ], 62 | "name": "UpdatedStaderConfig", 63 | "type": "event" 64 | }, 65 | { 66 | "anonymous": false, 67 | "inputs": [ 68 | { 69 | "indexed": false, 70 | "internalType": "uint256", 71 | "name": "protocolAmount", 72 | "type": "uint256" 73 | }, 74 | { 75 | "indexed": false, 76 | "internalType": "uint256", 77 | "name": "operatorAmount", 78 | "type": "uint256" 79 | }, 80 | { 81 | "indexed": false, 82 | "internalType": "uint256", 83 | "name": "userAmount", 84 | "type": "uint256" 85 | } 86 | ], 87 | "name": "Withdrawal", 88 | "type": "event" 89 | }, 90 | { 91 | "inputs": [], 92 | "name": "withdraw", 93 | "outputs": [], 94 | "stateMutability": "nonpayable", 95 | "type": "function" 96 | }, 97 | { 98 | "stateMutability": "payable", 99 | "type": "receive" 100 | } 101 | ] -------------------------------------------------------------------------------- /add-gplv3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in $(git ls-files | grep "\.go$" ); do 4 | echo "Adding GPL3 header to $i" 5 | cat license-short.txt | sed "s/{open}/\/*/g" | sed "s/{close}/*\//g" | cat - $i > /tmp/temp && mv /tmp/temp $i 6 | done 7 | -------------------------------------------------------------------------------- /build-builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # Print usage 22 | usage() { 23 | echo "Usage: build-release.sh -v " 24 | echo "This script builds the Stader node builder image used to build the daemon binaries." 25 | exit 0 26 | } 27 | 28 | # ================= 29 | # === Main Body === 30 | # ================= 31 | 32 | # Get the version 33 | while getopts "admv:" FLAG; do 34 | case "$FLAG" in 35 | v) VERSION="$OPTARG" ;; 36 | *) usage ;; 37 | esac 38 | done 39 | if [ -z "$VERSION" ]; then 40 | usage 41 | fi 42 | 43 | echo -n "Building Docker image... " 44 | docker build -t staderdev/stader-node-builder:$VERSION -f docker/stader-node-builder . 45 | docker tag staderdev/stader-node-builder:$VERSION staderdev/stader-node-builder:latest 46 | docker push staderdev/stader-node-builder:$VERSION 47 | docker push staderdev/stader-node-builder:latest 48 | echo "done!" -------------------------------------------------------------------------------- /build-ec-migrate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # Print usage 22 | usage() { 23 | echo "Usage: build-ec-migrate.sh -v " 24 | echo "This script builds the EC Migrator image." 25 | exit 0 26 | } 27 | 28 | # ================= 29 | # === Main Body === 30 | # ================= 31 | 32 | # Get the version 33 | while getopts "admv:" FLAG; do 34 | case "$FLAG" in 35 | v) VERSION="$OPTARG" ;; 36 | *) usage ;; 37 | esac 38 | done 39 | if [ -z "$VERSION" ]; then 40 | usage 41 | fi 42 | 43 | echo -n "Building Docker image... " 44 | echo "Building Docker EC Migrator image..." 45 | docker buildx build --platform=linux/amd64 -t staderdev/ec-migrator:$VERSION-amd64 -f docker/stader-ec-migrator --load . || fail "Error building amd64 Docker ec-migrator image." 46 | docker buildx build --platform=linux/arm64 -t staderdev/ec-migrator:$VERSION-arm64 -f docker/stader-ec-migrator --load . || fail "Error building arm64 Docker ec-migrator image." 47 | echo "done!" 48 | 49 | echo -n "Pushing to Docker Hub... " 50 | docker push staderdev/ec-migrator:$VERSION-amd64 || fail "Error pushing amd64 Docker EC Migrator image to Docker Hub." 51 | docker push staderdev/ec-migrator:$VERSION-arm64 || fail "Error pushing arm Docker EC Migrator image to Docker Hub." 52 | echo "done!" 53 | 54 | echo -n "Building Docker manifest... " 55 | rm -f ~/.docker/manifests/docker.io_staderdev_ec-migrator-$VERSION 56 | docker manifest create staderdev/ec-migrator:$VERSION --amend staderdev/ec-migrator:$VERSION-amd64 --amend staderdev/ec-migrator:$VERSION-arm64 57 | echo "done!" 58 | 59 | echo -n "Pushing to Docker Hub... " 60 | docker manifest push --purge staderdev/ec-migrator:$VERSION 61 | echo "done!" -------------------------------------------------------------------------------- /daemon-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # Get the platform type and run the build script if possible 22 | PLATFORM=$(uname -s) 23 | if [ "$PLATFORM" = "Linux" ]; then 24 | docker run --rm -v $PWD:/stader-node staderdev/stader-node-builder:latest /stader-node/stader/build.sh 25 | else 26 | echo "Platform ${PLATFORM} is not supported by this script, please build the daemon manually." 27 | exit 1 28 | fi 29 | -------------------------------------------------------------------------------- /daemon-local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Print usage 4 | usage() { 5 | echo "Usage: daemon-local.sh -v " 6 | exit 0 7 | } 8 | 9 | DOCKER_ACCOUNT=staderlabs 10 | # Parse arguments 11 | while getopts "acpdnlrfv:" FLAG; do 12 | case "$FLAG" in 13 | v) VERSION="$OPTARG" ;; 14 | *) usage ;; 15 | esac 16 | done 17 | if [ -z "$VERSION" ]; then 18 | usage 19 | fi 20 | 21 | # Get CPU architecture 22 | UNAME_VAL=$(uname -m) 23 | ARCH="" 24 | case $UNAME_VAL in 25 | x86_64) ARCH="amd64" ;; 26 | aarch64) ARCH="arm64" ;; 27 | arm64) ARCH="arm64" ;; 28 | *) fail "CPU architecture not supported: $UNAME_VAL" ;; 29 | esac 30 | 31 | 32 | echo "Start buiding: " $VERSION 33 | 34 | docker run --rm -v $PWD:/stader-node staderdev/stader-node-builder:latest /stader-node/stader/build.sh 35 | 36 | cp stader/stader-daemon-* build/$VERSION 37 | 38 | echo "done!" 39 | 40 | docker buildx build --platform=linux/$ARCH -t $DOCKER_ACCOUNT/stader-permissionless:$VERSION -f docker/stader-dockerfile --load . || fail "Error building $ARCH Docker Stader Daemon image." 41 | 42 | echo "done!" 43 | -------------------------------------------------------------------------------- /docker/stader-dockerfile: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | FROM debian:bookworm-slim 20 | 21 | ARG TARGETARCH 22 | COPY ./stader/stader-daemon-linux-${TARGETARCH} /go/bin/stader 23 | 24 | RUN apt update && apt install ca-certificates -y 25 | 26 | # Container entry point 27 | ENTRYPOINT ["/go/bin/stader"] 28 | -------------------------------------------------------------------------------- /docker/stader-ec-migrator: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Start from Alpine image 20 | FROM alpine:latest 21 | 22 | # Install rsync 23 | RUN apk add rsync 24 | 25 | # Copy the provisioning script 26 | COPY stader/ec_migrate.sh /srv 27 | 28 | # Container entry point 29 | ENTRYPOINT ["/srv/ec_migrate.sh"] 30 | -------------------------------------------------------------------------------- /docker/stader-node-builder: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # This image is used to build the Stader and related artifacts 20 | 21 | FROM golang:1.21.10-bookworm 22 | 23 | # Install build tools 24 | RUN dpkg --add-architecture arm64 25 | RUN apt update && apt install -y \ 26 | build-essential \ 27 | gcc-aarch64-linux-gnu \ 28 | libc6-dev-arm64-cross\ 29 | g++-aarch64-linux-gnu \ 30 | wget 31 | 32 | # Cache go dependencies 33 | ADD go.mod /src/go.mod 34 | ADD go.sum /src/go.sum 35 | WORKDIR /src 36 | RUN go mod download all 37 | WORKDIR / 38 | RUN rm -rf /src 39 | -------------------------------------------------------------------------------- /docker/stader-prune-provision: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Start from Alpine image 20 | FROM alpine:latest 21 | 22 | # Copy the provisioning script 23 | COPY stader/prune_provision.sh /srv 24 | 25 | # Container entry point 26 | ENTRYPOINT ["/srv/prune_provision.sh"] 27 | -------------------------------------------------------------------------------- /install/addons/gww/.ignoreme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stader-labs/stader-node/2fd5eddab6360b15017ee77d53ab2964ab58d781/install/addons/gww/.ignoreme -------------------------------------------------------------------------------- /install/grafana-prometheus-datasource.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | apiVersion: 1 20 | 21 | deleteDatasources: 22 | - name: Prometheus 23 | orgId: 1 24 | 25 | datasources: 26 | - name: Prometheus 27 | type: prometheus 28 | access: proxy 29 | orgId: 1 30 | url: http://prometheus:9091 31 | basicAuth: false 32 | isDefault: true 33 | version: 1 34 | editable: true 35 | -------------------------------------------------------------------------------- /install/override/addons/gww/addon_gww.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the Graffiti Wall Addon container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | addon_gww: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/api.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the API container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | api: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/eth1.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the eth1 container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | eth1: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/eth2.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the eth2 container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | eth2: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/exporter.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the node exporter container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | node-exporter: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/grafana.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the Grafana container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | grafana: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/guardian.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the guardian container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | guardian: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/mev-boost.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the MEV Boost container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | mev-boost: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/node.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the node container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | node: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/override/prometheus.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the Prometheus container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | prometheus: 27 | x-comment: Add your customizations below this line 28 | networks: 29 | # Bridge so node-exporter can get the real NIC details 30 | # See https://stackoverflow.com/a/66689508 for more info 31 | monitor-net: 32 | driver: bridge 33 | ipam: 34 | driver: default 35 | config: 36 | - subnet: 172.23.0.0/16 37 | ip_range: 172.23.5.0/24 38 | gateway: 172.23.5.254 -------------------------------------------------------------------------------- /install/override/validator.yml: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Enter your own customizations for the validator container here. These changes will persist after upgrades, so you only need to do them once. 20 | # 21 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 22 | # for more information on overriding specific parameters of docker-compose files. 23 | 24 | version: "3.7" 25 | services: 26 | validator: 27 | x-comment: Add your customizations below this line 28 | -------------------------------------------------------------------------------- /install/prometheus.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Default Prometheus configuration for Stader 20 | 21 | global: 22 | scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. 23 | scrape_timeout: 12s # Timeout must be shorter than the interval 24 | evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. 25 | 26 | scrape_configs: 27 | - job_name: 'prometheus' 28 | static_configs: 29 | - targets: ['localhost:${PROMETHEUS_PORT:-9091}'] 30 | 31 | - job_name: 'node' 32 | static_configs: 33 | # node-exporter is on the host network so it can get access to the actual machine's network info 34 | # We have to use 'hosts.docker.internal' to refer to it due to this configuration 35 | - targets: ['host.docker.internal:${EXPORTER_METRICS_PORT:-9103}'] 36 | 37 | - job_name: 'geth' 38 | static_configs: 39 | - targets: ['${EC_HOSTNAME:-eth1}:${EC_METRICS_PORT:-9105}'] 40 | metrics_path: /debug/metrics/prometheus 41 | 42 | - job_name: 'eth1' 43 | static_configs: 44 | - targets: ['${EC_HOSTNAME:-eth1}:${EC_METRICS_PORT:-9105}'] 45 | 46 | - job_name: 'eth2' 47 | static_configs: 48 | - targets: ['${CC_HOSTNAME:-eth2}:${BN_METRICS_PORT:-9100}'] 49 | 50 | - job_name: 'validator' 51 | static_configs: 52 | - targets: ['validator:${VC_METRICS_PORT:-9101}'] 53 | 54 | - job_name: 'stader' 55 | scrape_interval: 5m 56 | scrape_timeout: 5m 57 | static_configs: 58 | - targets: ['guardian:${NODE_METRICS_PORT:-9104}'] 59 | -------------------------------------------------------------------------------- /install/scripts/NethermindPruneStarter/NethermindPruneStarter.deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeTarget": { 3 | "name": ".NETCoreApp,Version=v8.0", 4 | "signature": "" 5 | }, 6 | "compilationOptions": {}, 7 | "targets": { 8 | ".NETCoreApp,Version=v8.0": { 9 | "NethermindPruneStarter/1.0.1": { 10 | "dependencies": { 11 | "Newtonsoft.Json": "13.0.2" 12 | }, 13 | "runtime": { 14 | "NethermindPruneStarter.dll": {} 15 | } 16 | }, 17 | "Newtonsoft.Json/13.0.2": { 18 | "runtime": { 19 | "lib/net6.0/Newtonsoft.Json.dll": { 20 | "assemblyVersion": "13.0.0.0", 21 | "fileVersion": "13.0.2.27524" 22 | } 23 | } 24 | } 25 | } 26 | }, 27 | "libraries": { 28 | "NethermindPruneStarter/1.0.1": { 29 | "type": "project", 30 | "serviceable": false, 31 | "sha512": "" 32 | }, 33 | "Newtonsoft.Json/13.0.2": { 34 | "type": "package", 35 | "serviceable": true, 36 | "sha512": "sha512-R2pZ3B0UjeyHShm9vG+Tu0EBb2lC8b0dFzV9gVn50ofHXh9Smjk6kTn7A/FdAsC8B5cKib1OnGYOXxRBz5XQDg==", 37 | "path": "newtonsoft.json/13.0.2", 38 | "hashPath": "newtonsoft.json.13.0.2.nupkg.sha512" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /install/scripts/NethermindPruneStarter/NethermindPruneStarter.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stader-labs/stader-node/2fd5eddab6360b15017ee77d53ab2964ab58d781/install/scripts/NethermindPruneStarter/NethermindPruneStarter.dll -------------------------------------------------------------------------------- /install/scripts/NethermindPruneStarter/NethermindPruneStarter.runtimeconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeOptions": { 3 | "tfm": "net8.0", 4 | "framework": { 5 | "name": "Microsoft.NETCore.App", 6 | "version": "8.0.2" 7 | }, 8 | "configProperties": { 9 | "System.Reflection.Metadata.MetadataUpdater.IsSupported": false 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /install/scripts/NethermindPruneStarter/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stader-labs/stader-node/2fd5eddab6360b15017ee77d53ab2964ab58d781/install/scripts/NethermindPruneStarter/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /install/scripts/restart-vc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This work is licensed and released under GNU GPL v3 or any other later versions. 3 | # The full text of the license is below/ found at 4 | 5 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | # This script is used to restart your Validator Client service. 21 | # It is run in Native Mode only when the Stader node needs to restart your Validator Client (for example, to load new validator keys). 22 | # It is not used in standard (docker-based) Stader setups. 23 | 24 | # The command below is an example only. 25 | # Replace it with your own commands to restart your Validator Client service. 26 | 27 | #sudo systemctl restart lighthouse-validator 28 | -------------------------------------------------------------------------------- /install/scripts/start-mev-boost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This work is licensed and released under GNU GPL v3 or any other later versions. 3 | # The full text of the license is below/ found at 4 | 5 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | 21 | # Set up the network-based flag 22 | if [ "$NETWORK" = "mainnet" ]; then 23 | MEV_NETWORK="mainnet" 24 | elif [ "$NETWORK" = "devnet" ]; then 25 | MEV_NETWORK="holesky" 26 | elif [ "$NETWORK" = "holesky" ]; then 27 | MEV_NETWORK="holesky" 28 | else 29 | echo "Unknown network [$NETWORK]" 30 | exit 1 31 | fi 32 | 33 | # Run MEV-boost 34 | exec /app/mev-boost -${MEV_NETWORK} -addr 0.0.0.0:${MEV_BOOST_PORT} -relay-check -relays ${MEV_BOOST_RELAYS} -------------------------------------------------------------------------------- /install/scripts/stop-validator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This work is licensed and released under GNU GPL v3 or any other later versions. 3 | # The full text of the license is below/ found at 4 | 5 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | # This script is used to stop your Validator Client service. 21 | # It is run in Native Mode only when the Stader Node needs to stop your Validator Client because of a misconfiguration or other error. 22 | # It is not used in Docker Mode or Hybrid Mode. 23 | 24 | # The command below is an example only. 25 | # Replace it with your own command to stop your Validator Client service. 26 | 27 | #sudo systemctl stop lighthouse-validator 28 | -------------------------------------------------------------------------------- /install/templates/addons/gww/addon_gww.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/api.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | addon_gww: 29 | image: ${ADDON_GWW_CONTAINER_TAG} 30 | user: root 31 | container_name: ${COMPOSE_PROJECT_NAME}_addon_gww 32 | restart: unless-stopped 33 | volumes: 34 | - ${STADER_FOLDER}/addons/gww:/gww 35 | networks: 36 | - net 37 | entrypoint: 38 | - /go/bin/drawer 39 | - --output_file=/gww/graffiti.txt 40 | - --input_url=${ADDON_GWW_INPUT_URL} 41 | - --consensus_client=${CC_CLIENT} 42 | - --nimbus_url=http://${CC_HOSTNAME:-eth2}:${BN_API_PORT:-5052} 43 | - --graffiti_prefix=${GRAFFITI_PREFIX} 44 | - --network=${NETWORK} 45 | - --update_wall_time=${ADDON_GWW_UPDATE_WALL_TIME} 46 | - --update_input_time=${ADDON_GWW_UPDATE_INPUT_TIME} 47 | - --update_pixel_time=${ADDON_GWW_UPDATE_PIXEL_TIME} 48 | cap_drop: 49 | - all 50 | security_opt: 51 | - no-new-privileges 52 | networks: 53 | net: -------------------------------------------------------------------------------- /install/templates/api.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/api.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | api: 29 | image: ${STADER_NODE_IMAGE} 30 | container_name: ${COMPOSE_PROJECT_NAME}_api 31 | restart: unless-stopped 32 | stop_signal: SIGKILL 33 | stop_grace_period: 1s 34 | volumes: 35 | - /var/run/docker.sock:/var/run/docker.sock 36 | - ${STADER_FOLDER}:/.stader 37 | - ${STADER_DATA_FOLDER}:/.stader/data 38 | networks: 39 | - net 40 | entrypoint: /bin/sleep 41 | command: "infinity" 42 | cap_drop: 43 | - all 44 | cap_add: 45 | - dac_override 46 | security_opt: 47 | - no-new-privileges 48 | networks: 49 | net: -------------------------------------------------------------------------------- /install/templates/exporter.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/exporter.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | node-exporter: 29 | image: ${EXPORTER_CONTAINER_TAG} 30 | container_name: ${COMPOSE_PROJECT_NAME}_exporter 31 | cap_drop: 32 | - ALL 33 | user: "65534:65534" 34 | restart: unless-stopped 35 | command: [ "--path.procfs=/host/proc", "--path.sysfs=/host/sys", "--collector.textfile.directory=/host/textfile_collector", "--web.listen-address=:${EXPORTER_METRICS_PORT:-9103}"${EXPORTER_ROOTFS_COMMAND}${EXPORTER_ADDITIONAL_FLAGS} ] 36 | volumes: [ "/proc:/host/proc:ro,rslave", "/sys:/host/sys:ro,rslave", "/var/lib/node_exporter/textfile_collector:/host/textfile_collector:ro"${EXPORTER_ROOTFS_VOLUME} ] 37 | network_mode: host 38 | networks: 39 | net: -------------------------------------------------------------------------------- /install/templates/grafana-prometheus-datasource.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | apiVersion: 1 20 | 21 | deleteDatasources: 22 | - name: Prometheus 23 | orgId: 1 24 | 25 | datasources: 26 | - name: Prometheus 27 | type: prometheus 28 | access: proxy 29 | orgId: 1 30 | url: http://prometheus:9091 31 | basicAuth: false 32 | isDefault: true 33 | version: 1 34 | editable: true 35 | -------------------------------------------------------------------------------- /install/templates/grafana.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/grafana.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | grafana: 29 | image: ${GRAFANA_CONTAINER_TAG} 30 | container_name: ${COMPOSE_PROJECT_NAME}_grafana 31 | restart: unless-stopped 32 | environment: 33 | - GF_SERVER_HTTP_PORT=${GRAFANA_PORT:-3100} 34 | ports: 35 | - "${GRAFANA_PORT:-3100}:${GRAFANA_PORT:-3100}/tcp" 36 | volumes: 37 | - "${STADER_FOLDER}/grafana-prometheus-datasource.yml:/etc/grafana/provisioning/datasources/prometheus.yml" 38 | - "grafana-storage:/var/lib/grafana" 39 | networks: 40 | - net 41 | networks: 42 | net: 43 | volumes: 44 | grafana-storage: -------------------------------------------------------------------------------- /install/templates/guardian.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/guardian.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | guardian: 29 | image: ${STADER_NODE_IMAGE} 30 | container_name: ${COMPOSE_PROJECT_NAME}_guardian 31 | restart: unless-stopped 32 | ports: [${GUARDIAN_OPEN_PORTS}] 33 | volumes: 34 | - ${STADER_FOLDER}:/.stader 35 | - ${STADER_DATA_FOLDER}:/.stader/data 36 | networks: 37 | - net 38 | command: "-m 0.0.0.0 -r ${NODE_METRICS_PORT:-9104} guardian" 39 | cap_drop: 40 | - all 41 | cap_add: 42 | - dac_override 43 | security_opt: 44 | - no-new-privileges 45 | networks: 46 | net: -------------------------------------------------------------------------------- /install/templates/mev-boost.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/mev-boost.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | mev-boost: 29 | image: ${MEV_BOOST_CONTAINER_TAG} 30 | container_name: ${COMPOSE_PROJECT_NAME}_mev-boost 31 | restart: unless-stopped 32 | ports: [${MEV_BOOST_OPEN_API_PORT}] 33 | volumes: 34 | - ${STADER_FOLDER}/scripts:/setup:ro 35 | networks: 36 | - net 37 | environment: 38 | - NETWORK=${NETWORK} 39 | - MEV_BOOST_PORT=${MEV_BOOST_PORT} 40 | - MEV_BOOST_RELAYS=${MEV_BOOST_RELAYS} 41 | entrypoint: sh 42 | command: "/setup/start-mev-boost.sh" 43 | cap_drop: 44 | - all 45 | cap_add: 46 | - dac_override 47 | security_opt: 48 | - no-new-privileges 49 | networks: 50 | net: -------------------------------------------------------------------------------- /install/templates/node.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/node.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | node: 29 | image: ${STADER_NODE_IMAGE} 30 | container_name: ${COMPOSE_PROJECT_NAME}_node 31 | restart: unless-stopped 32 | volumes: 33 | - /var/run/docker.sock:/var/run/docker.sock 34 | - ${STADER_FOLDER}:/.stader 35 | - ${STADER_DATA_FOLDER}:/.stader/data 36 | networks: 37 | - net 38 | command: "node" 39 | cap_drop: 40 | - all 41 | cap_add: 42 | - dac_override 43 | security_opt: 44 | - no-new-privileges 45 | networks: 46 | net: -------------------------------------------------------------------------------- /install/templates/prometheus.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/prometheus.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | prometheus: 29 | image: ${PROMETHEUS_CONTAINER_TAG} 30 | container_name: ${COMPOSE_PROJECT_NAME}_prometheus 31 | restart: unless-stopped 32 | command: [ "--web.listen-address=:${PROMETHEUS_PORT:-9091}", "--config.file=/etc/prometheus/prometheus.yml"${PROMETHEUS_ADDITIONAL_FLAGS} ] 33 | ports: [${PROMETHEUS_OPEN_PORTS}] 34 | volumes: 35 | - "${STADER_FOLDER}/prometheus.yml:/etc/prometheus/prometheus.yml" 36 | - "prometheus-data:/prometheus" 37 | networks: 38 | - net 39 | - monitor-net 40 | extra_hosts: 41 | - "host.docker.internal:host-gateway" 42 | networks: 43 | # Bridge so node-exporter can get the real NIC details 44 | # See https://stackoverflow.com/a/66689508 for more info 45 | monitor-net: 46 | driver: bridge 47 | ipam: 48 | driver: default 49 | config: 50 | - subnet: 172.23.0.0/16 51 | ip_range: 172.23.5.0/24 52 | gateway: 172.23.5.254 53 | net: 54 | volumes: 55 | prometheus-data: -------------------------------------------------------------------------------- /license-short.txt: -------------------------------------------------------------------------------- 1 | {open} 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | {close} 20 | -------------------------------------------------------------------------------- /shared/services/config/dev-presign-public-key.txt: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF5RTJYV055bW5idEhsTHVhTndyWgpLWG1BcEMvM1JWaVpJSTNhVnhVbzg5T3NjblNxTTdQUmxVbjlSR29BZUdPcVBkVFpRRzliUWRZckxWYXRpTU9QCkRuOU1wT01NcEszRCtpOVcvUC9Fdjc4cGE5MnV3WGR3UTM3Y2F2RmI0ZVFwOU0zR2p5eGlCVjlybzVEVGtmTk8KS1dBWnVnaklGZHFyNXNWVDJiQnhORzJBeTYzQnMzTVVhcGtMNFpYRk1NSEdZa0RWV1pnalE2OEtKc0c1NWdkSgp5RkVFWmUwdGpMSHVzaGszZVlQVzA4S0NRQ25uR1dDYUV4SEFEcnMwU3E0ekJQeEJWMExjV0l4cCt6dHFBVGUyCnYvbSs2RDVKVkFIN0w3S01ZUGZNWXVPUkN1RSsvUkxNU2hXZFp6czErSjI3MWI1b3pUZVhIQTJ6VG5ES3JqNWwKVXZNK0h0dEFQdXpXUTNsTThudG1Ra1JLR3NwekY5bWtkZy95cVNSQ3B2bEtFSjJ3andXTGxjNzA3SldkQXRwbApaU1JiREorYkZMVUZRRy85SnMwSjMzeE96a1RjTmdFNmw0dUFIT1I1OTMvSHU4MzRBbzRub2xHbVpiVjVpNUdRCmo4TTlWdnlEM0JLcExWRTgrYjEzYTc1TXpoZVFTeVlJakRmbjNHZE9ma0tWaGpzWnFSNzRONWRnNE5sejc5amoKazZ3Lzg3bllVTmZMV3NYT1hvTk5aaW82cW1oNXk4ZWZxU0xNbG1YMzRrMHhiNlJ4Z1ArTWwvYkhXMHJqTmRPQgpXbU1lbVcrWk9TOWFQWjA5anpxRkpBcG8wTnF4UGlyMFhHU00yS1c3aG5VM3ZZd1E3NVBGamZuc0cvOVhjQmtaCmxBTHIya21aUEZSNGFQcmpjZ2c5SmxVQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== -------------------------------------------------------------------------------- /shared/services/config/prod-presign-public-key.txt: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFtWHlrVHZ0R0pXZEovR2IxWERxdQpxZWczK3FhbzRjclBYeE12K2xIV0hxbWtERllPaGJYbS82UmI4eVd2WW9VNExnZjhuaHA4UGhFTkdId2lUeks1CjFmL2Y0TzQzUzF3SUxDbE5LVVExNlR1N0ZWRU9Id2V0dXZHTzJFTEtVUHJMRStaWVZIRGF4eGJYZjE0SysxK0gKalh1L0FwMUFzSEJTSCtlbWZ2all4cnNoVUxFRXJXcHZqbWtZZDJVRE1oeUNqUk9zMU9qdThqeU1WODh3M3Z0NwpJYlhIbythNkpNbFRNSXpaWkNVWVhCOXdrOFRVd3ZTbEJ1QzFPU1JjTVFldVpLVU1NVGxzU0JzdXZmM2dwbFFLCnViekRrUlZ6Nk5QeU5zUHBVT2h3bzQvenBFbjk3QlVLUU8wNm1YaEg4SWFKaWtHUmxsZk1OTklGcWd1QXYrangKRzlhbVY5MGNsU1BoaUpoMmJ4TUZQaEJUcThUYVJqelBVZXYvSU1rS0xMVTN5Ukh1LzUyckpUTnl4bnNBZ0s0cwpCK0draXBBbSs0cHROaGFtOHVSOEZhMDQ3czQ5OGJ5ek5PaERHaUJiM0dJM21mZld2T0pNN05KdGpGd0tCOCtrCkx6bEtMMzZjbHUvY2Y2bDJ0OVh1RndIZmhYUWZPZktkSjdzWitsZkJzb1VPcE5pUFpaNzNrSWlnV0sxQi9XVnAKelh0Undic1Fhdkd5em9CVHN5L3VCL054Sm8zaUJVVG1zS1VLa1hLb3loaU5lY2FXbUd1U1lpeTBXRmlpQ3hhRgo0aTExSFYzSk8vcGhyZXpoRHpxK24wWWN5RktEL3BhSE5kTm9EUDFnTEU1eVRpN24rRG1lU2x3aVlRS0g1SVg5CmFiTlZONnRYTlh6b0NLWVVnNklnU2dzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== -------------------------------------------------------------------------------- /shared/services/config/stage-presign-public-key.txt: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUE0T2I4VDZsVmxSRzVhcTZtVGlMUQpCSlNaM0pYQy9xNVVGRnNCc3k2NVVDMlJvUzVDaWdkcWh5SDZPVkJJTVJBVmxqQ3hFQldaeVlRbkNVSHluaXh5CjcrUWhsUFRxZVNwYURnOTZaOWp6NE96RjNEUXpLSkpiZkRlSUp2cGdzblZPU25kWE5tMnlFZzNGL3FGeTdXakUKVHNjb1RRN3hITnB6SzF0elM2SFpodHZUY2hZOXpXaHhzN3htbSttd1FRWnEyZXRsc3l0S1FqT1dvaFdyUzBLcgo1UkNNUXRON0Iva2RJYlljZW5HRlhJSy9IVGhPaDZEdVg2dmlTUDZPclQvSmtRbkEwWTMydzRzWG9mQXNBSHR4Ci9uMVBOUE14SnJvQ08xcTZMVnVuN3QrZEd6Q294bzBCcFZaczk0NHlWQVdrNm5wMmo2UG15NkRMcmpjVndDSTcKdFBlWkRwU0Z3My82ZUg0WGdOT2NHeURqVmFBY3A1VWc3bTE1NU10cElFdG94M21IYk0wWUVVRHVJN0VkK3ZwSApabDdzQmlDbFN5K1pmMTJhb1ZVVWhFVzN4OFM0UnQ2aHlVeWxUV1FmWHFDWE1CS2kzcW5JWkZPYzFQYmNxNTJrCklQZ0d1eFJuN211L1BhaHBFV1U4S3ZmZXJId1BjSEJqdGdrOVZ5YWNOcjZCK0Q3eGYvVFVabC9VNnowRDJyUTgKaG9GTjdueThZWk9GUGczOWFQRUQxR0JMUW5sNmowUVJYSWJQd0svOUxvT1lDSnhiOG5LQ0xPbmxNKzcyQzhLSwpydWpDWk93aXBJY0dvc041M3lNOXdRUzVUVWloWTk2NTB1N0hIbU9nSUJ3Y1BOOEdYVWQwWUVwZWRzQXFYTlRsCmFZNjRvRkRQZThUR3owSGhLand0WWJzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== -------------------------------------------------------------------------------- /shared/services/eth1.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package services 21 | 22 | import ( 23 | "context" 24 | 25 | "github.com/stader-labs/stader-node/stader-lib/stader" 26 | ) 27 | 28 | func GetEthClientLatestBlockTimestamp(ec stader.ExecutionClient) (uint64, error) { 29 | // Get latest block 30 | header, err := ec.HeaderByNumber(context.Background(), nil) 31 | if err != nil { 32 | return 0, err 33 | } 34 | 35 | // Return block timestamp 36 | return header.Time, nil 37 | } 38 | -------------------------------------------------------------------------------- /shared/services/stader/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package stader 21 | 22 | import ( 23 | "encoding/json" 24 | "fmt" 25 | 26 | "github.com/ethereum/go-ethereum/common" 27 | 28 | "github.com/stader-labs/stader-node/shared/types/api" 29 | ) 30 | 31 | // Wait for a transaction 32 | func (c *Client) WaitForTransaction(txHash common.Hash) (api.APIResponse, error) { 33 | responseBytes, err := c.callAPI(fmt.Sprintf("wait %s", txHash.String())) 34 | if err != nil { 35 | return api.APIResponse{}, fmt.Errorf("Error waiting for tx: %w", err) 36 | } 37 | var response api.APIResponse 38 | if err := json.Unmarshal(responseBytes, &response); err != nil { 39 | return api.APIResponse{}, fmt.Errorf("Error decoding wait response: %w", err) 40 | } 41 | if response.Error != "" { 42 | return api.APIResponse{}, fmt.Errorf("Error waiting for tx: %s", response.Error) 43 | } 44 | return response, nil 45 | } 46 | -------------------------------------------------------------------------------- /shared/services/stader/external-urls.go: -------------------------------------------------------------------------------- 1 | package stader 2 | 3 | const PreSignSendApi = "https://stage-ethx-offchain.staderlabs.click/presign" 4 | const PreSignCheckApi = "https://stage-ethx-offchain.staderlabs.click/msgSubmitted" 5 | const PublicKeyApi = "https://stage-ethx-offchain.staderlabs.click/publicKey" 6 | const MerkleProofAggregateGetterApi = "https://stage-ethx-offchain.staderlabs.click/merklesForElRewards/proofs/%s" 7 | -------------------------------------------------------------------------------- /shared/services/stader/gas.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package stader 21 | 22 | import ( 23 | "fmt" 24 | ) 25 | 26 | const ( 27 | colorReset string = "\033[0m" 28 | colorYellow string = "\033[33m" 29 | ) 30 | 31 | // Print a warning about the gas estimate for operations that have multiple transactions 32 | func (sd *Client) PrintMultiTxWarning() { 33 | fmt.Printf("%sNOTE: This operation requires multiple transactions.\n%s", 34 | colorYellow, 35 | colorReset) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /shared/services/stader/legacy-client.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package stader 21 | 22 | import ( 23 | "fmt" 24 | "os" 25 | 26 | "github.com/alessio/shellescape" 27 | "github.com/mitchellh/go-homedir" 28 | "github.com/stader-labs/stader-node/shared/services/config" 29 | ) 30 | 31 | // Config 32 | const ( 33 | LegacyGlobalConfigFile = "config.yml" 34 | LegacyUserConfigFile = "settings.yml" 35 | LegacyComposeFile = "docker-compose.yml" 36 | LegacyMetricsComposeFile = "docker-compose-metrics.yml" 37 | LegacyFallbackComposeFile = "docker-compose-fallback.yml" 38 | ) 39 | 40 | // Load the global config 41 | func (c *Client) LoadGlobalConfig_Legacy(globalConfigPath string) (config.LegacyStaderConfig, error) { 42 | return c.loadConfig_Legacy(globalConfigPath) 43 | } 44 | 45 | // Load/save the user config 46 | func (c *Client) LoadUserConfig_Legacy(userConfigPath string) (config.LegacyStaderConfig, error) { 47 | return c.loadConfig_Legacy(userConfigPath) 48 | } 49 | 50 | // Load the merged global & user config 51 | func (c *Client) LoadMergedConfig_Legacy(globalConfigPath string, userConfigPath string) (config.LegacyStaderConfig, error) { 52 | globalConfig, err := c.LoadGlobalConfig_Legacy(globalConfigPath) 53 | if err != nil { 54 | return config.LegacyStaderConfig{}, err 55 | } 56 | userConfig, err := c.LoadUserConfig_Legacy(userConfigPath) 57 | if err != nil { 58 | return config.LegacyStaderConfig{}, err 59 | } 60 | return config.Merge(&globalConfig, &userConfig) 61 | } 62 | 63 | // Load a config file 64 | func (c *Client) loadConfig_Legacy(path string) (config.LegacyStaderConfig, error) { 65 | expandedPath, err := homedir.Expand(path) 66 | if err != nil { 67 | return config.LegacyStaderConfig{}, err 68 | } 69 | configBytes, err := os.ReadFile(expandedPath) 70 | if err != nil { 71 | return config.LegacyStaderConfig{}, fmt.Errorf("Could not read Stader config at %s: %w", shellescape.Quote(path), err) 72 | } 73 | return config.Parse(configBytes) 74 | } 75 | -------------------------------------------------------------------------------- /shared/services/stader/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package stader 21 | 22 | import ( 23 | "encoding/json" 24 | "fmt" 25 | 26 | "github.com/stader-labs/stader-node/shared/types/api" 27 | ) 28 | 29 | // Deletes the data folder including the wallet file, password file, and all validator keys. 30 | // Don't use this unless you have a very good reason to do it (such as switching from Prater to Mainnet). 31 | func (c *Client) TerminateDataFolder() (api.TerminateDataFolderResponse, error) { 32 | responseBytes, err := c.callAPI("service terminate-data-folder") 33 | if err != nil { 34 | return api.TerminateDataFolderResponse{}, fmt.Errorf("Could not delete data folder: %w", err) 35 | } 36 | var response api.TerminateDataFolderResponse 37 | if err := json.Unmarshal(responseBytes, &response); err != nil { 38 | return api.TerminateDataFolderResponse{}, fmt.Errorf("Could not decode terminate-data-folder response: %w", err) 39 | } 40 | if response.Error != "" { 41 | return api.TerminateDataFolderResponse{}, fmt.Errorf("Could not delete data folder: %s", response.Error) 42 | } 43 | return response, nil 44 | } 45 | 46 | // Gets the status of the configured Execution and Beacon clients 47 | func (c *Client) GetClientStatus() (api.ClientStatusResponse, error) { 48 | responseBytes, err := c.callAPI("service get-client-status") 49 | 50 | if err != nil { 51 | return api.ClientStatusResponse{}, fmt.Errorf("Could not get client status: %w", err) 52 | } 53 | var response api.ClientStatusResponse 54 | if err := json.Unmarshal(responseBytes, &response); err != nil { 55 | return api.ClientStatusResponse{}, fmt.Errorf("Could not decode client status response: %w", err) 56 | } 57 | if response.Error != "" { 58 | return api.ClientStatusResponse{}, fmt.Errorf("Could not get client status: %s", response.Error) 59 | } 60 | return response, nil 61 | } 62 | -------------------------------------------------------------------------------- /shared/services/wallet/keystore/keystore.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package keystore 21 | 22 | import ( 23 | "github.com/sethvargo/go-password/password" 24 | eth2types "github.com/wealdtech/go-eth2-types/v2" 25 | ) 26 | 27 | // Generates a random password 28 | func GenerateRandomPassword() (string, error) { 29 | 30 | // Generate a random 32-character password 31 | password, err := password.Generate(32, 6, 6, false, false) 32 | if err != nil { 33 | return "", err 34 | } 35 | 36 | return password, nil 37 | } 38 | 39 | // Validator keystore interface 40 | type Keystore interface { 41 | StoreValidatorKey(key *eth2types.BLSPrivateKey, derivationPath string) error 42 | GetKeystoreDir() string 43 | } 44 | -------------------------------------------------------------------------------- /shared/types/api/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package api 21 | 22 | type APIResponse struct { 23 | Status string `json:"status"` 24 | Error string `json:"error"` 25 | } 26 | -------------------------------------------------------------------------------- /shared/types/api/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package api 21 | 22 | import "github.com/ethereum/go-ethereum/common" 23 | 24 | type TerminateDataFolderResponse struct { 25 | Status string `json:"status"` 26 | Error string `json:"error"` 27 | FolderExisted bool `json:"folderExisted"` 28 | } 29 | 30 | type CreateFeeRecipientFileResponse struct { 31 | Status string `json:"status"` 32 | Error string `json:"error"` 33 | Distributor common.Address `json:"distributor"` 34 | } 35 | 36 | // This is a wrapper for the EC status report 37 | type ClientStatus struct { 38 | IsWorking bool `json:"isWorking"` 39 | IsSynced bool `json:"isSynced"` 40 | SyncProgress float64 `json:"syncProgress"` 41 | NetworkId uint `json:"networkId"` 42 | Error string `json:"error"` 43 | } 44 | 45 | // This is a wrapper for the manager's overall status report 46 | type ClientManagerStatus struct { 47 | PrimaryClientStatus ClientStatus `json:"primaryEcStatus"` 48 | FallbackEnabled bool `json:"fallbackEnabled"` 49 | FallbackClientStatus ClientStatus `json:"fallbackEcStatus"` 50 | } 51 | 52 | type ClientStatusResponse struct { 53 | Status string `json:"status"` 54 | Error string `json:"error"` 55 | EcManagerStatus ClientManagerStatus `json:"ecManagerStatus"` 56 | BcManagerStatus ClientManagerStatus `json:"bcManagerStatus"` 57 | } 58 | -------------------------------------------------------------------------------- /shared/types/eth2/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package eth2 21 | 22 | // Deposit data (with no signature field) 23 | type DepositDataNoSignature struct { 24 | PublicKey []byte `json:"pubkey" ssz-size:"48"` 25 | WithdrawalCredentials []byte `json:"withdrawal_credentials" ssz-size:"32"` 26 | Amount uint64 `json:"amount"` 27 | } 28 | 29 | // Deposit data (including signature) 30 | type DepositData struct { 31 | PublicKey []byte `json:"pubkey" ssz-size:"48"` 32 | WithdrawalCredentials []byte `json:"withdrawal_credentials" ssz-size:"32"` 33 | Amount uint64 `json:"amount"` 34 | Signature []byte `json:"signature" ssz-size:"96"` 35 | } 36 | 37 | // BLS signing root with domain 38 | type SigningRoot struct { 39 | ObjectRoot []byte `json:"object_root" ssz-size:"32"` 40 | Domain []byte `json:"domain" ssz-size:"32"` 41 | } 42 | 43 | // Voluntary exit transaction 44 | type VoluntaryExit struct { 45 | Epoch uint64 `json:"epoch"` 46 | ValidatorIndex uint64 `json:"validator_index"` 47 | } 48 | 49 | // Withdrawal creds change message 50 | type WithdrawalCredentialsChange struct { 51 | ValidatorIndex uint64 `json:"validator_index"` 52 | FromBLSPubkey [48]byte `json:"from_bls_pubkey" ssz-size:"48"` 53 | ToExecutionAddress [20]byte `json:"to_execution_address" ssz-size:"20"` 54 | } 55 | -------------------------------------------------------------------------------- /shared/types/stader-backend/merkle-proofs.go: -------------------------------------------------------------------------------- 1 | package stader_backend 2 | 3 | type CycleMerkleProofs struct { 4 | Root string `json:"root"` 5 | Eth string `json:"eth"` 6 | Sd string `json:"sd"` 7 | Proof []string `json:"proof"` 8 | Cycle int64 `json:"cycle"` 9 | } 10 | -------------------------------------------------------------------------------- /shared/types/stader-backend/node-diversity.go: -------------------------------------------------------------------------------- 1 | package stader_backend 2 | 3 | type NodeDiversityRequest struct { 4 | Signature string `json:"signature"` 5 | Message *NodeDiversity `json:"message"` 6 | } 7 | 8 | type NodeDiversity struct { 9 | ExecutionClient string `json:"executionClient"` 10 | ConsensusClient string `json:"consensusClient"` 11 | ValidatorClient string `json:"validatorClient"` 12 | TotalNonTerminalKeys uint64 `json:"totalNonTerminalKeys"` 13 | NodeAddress string `json:"nodeAddress"` 14 | NodePublicKey string `json:"nodePublicKey"` 15 | Relays string `json:"relays"` 16 | } 17 | 18 | type NodeDiversityResponseType struct { 19 | Success bool `json:"success"` 20 | Error string `json:"error"` 21 | } 22 | -------------------------------------------------------------------------------- /shared/types/stader-backend/pre-sign.go: -------------------------------------------------------------------------------- 1 | package stader_backend 2 | 3 | import "github.com/stader-labs/stader-node/stader-lib/types" 4 | 5 | type PreSignCheckApiRequestType struct { 6 | ValidatorPublicKey string `json:"validatorPublicKey"` 7 | } 8 | 9 | type PreSignCheckApiResponseType struct { 10 | Value bool `json:"value"` 11 | } 12 | 13 | type PreSignSendApiResponseType struct { 14 | Success bool `json:"success"` 15 | Error string `json:"error"` 16 | } 17 | 18 | type PreSignSendApiRequestType struct { 19 | Message struct { 20 | Epoch string `json:"epoch"` 21 | ValidatorIndex string `json:"validator_index"` 22 | } `json:"message"` 23 | Signature string `json:"signature"` 24 | ValidatorPublicKey string `json:"validatorPublicKey"` 25 | } 26 | 27 | type BulkPreSignSendApiRequestType = []PreSignSendApiRequestType 28 | type BulkPreSignSendApiResponseType = map[string]PreSignSendApiResponseType 29 | 30 | type BulkPreSignCheckApiRequestType struct { 31 | ValidatorPubKeys []types.ValidatorPubkey `json:"pubkeys"` 32 | } 33 | 34 | type BulkPreSignCheckApiResponseType = map[string]bool 35 | 36 | type PublicKeyApiResponse struct { 37 | Value string `json:"value"` 38 | } 39 | -------------------------------------------------------------------------------- /shared/utils/api/response.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package api 21 | 22 | import ( 23 | "encoding/json" 24 | "errors" 25 | "fmt" 26 | "reflect" 27 | 28 | "github.com/stader-labs/stader-node/shared/types/api" 29 | ) 30 | 31 | // Print an API response 32 | // response must be a pointer to a struct type with Error and Status string fields 33 | func PrintResponse(response interface{}, responseError error) { 34 | 35 | // Check response type 36 | r := reflect.ValueOf(response) 37 | if !(r.Kind() == reflect.Ptr && r.Type().Elem().Kind() == reflect.Struct) { 38 | PrintErrorResponse(errors.New("Invalid API response")) 39 | return 40 | } 41 | 42 | // Create zero response value if nil 43 | if r.IsNil() { 44 | response = reflect.New(r.Type().Elem()).Interface() 45 | r = reflect.ValueOf(response) 46 | } 47 | 48 | // Get and check response fields 49 | sf := r.Elem().FieldByName("Status") 50 | ef := r.Elem().FieldByName("Error") 51 | if !(sf.IsValid() && sf.CanSet() && sf.Kind() == reflect.String && ef.IsValid() && ef.CanSet() && ef.Kind() == reflect.String) { 52 | PrintErrorResponse(errors.New("Invalid API response")) 53 | return 54 | } 55 | 56 | // Populate error 57 | if responseError != nil { 58 | ef.SetString(responseError.Error()) 59 | } 60 | 61 | // Set status 62 | if ef.String() == "" { 63 | sf.SetString("success") 64 | } else { 65 | sf.SetString("error") 66 | } 67 | 68 | // Encode 69 | responseBytes, err := json.Marshal(response) 70 | if err != nil { 71 | PrintErrorResponse(fmt.Errorf("Could not encode API response: %w", err)) 72 | return 73 | } 74 | 75 | // Print 76 | fmt.Println(string(responseBytes)) 77 | 78 | } 79 | 80 | // Print an API error response 81 | func PrintErrorResponse(err error) { 82 | PrintResponse(&api.APIResponse{}, err) 83 | } 84 | -------------------------------------------------------------------------------- /shared/utils/arr-utils/arr.go: -------------------------------------------------------------------------------- 1 | package arr_utils 2 | 3 | func ElementExistsInNumArray(arr []int64, element int64) bool { 4 | for _, v := range arr { 5 | if v == element { 6 | return true 7 | } 8 | } 9 | return false 10 | } 11 | -------------------------------------------------------------------------------- /shared/utils/cli/prompt_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | /* 5 | This work is licensed and released under GNU GPL v3 or any other later versions. 6 | The full text of the license is below/ found at 7 | 8 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | */ 23 | 24 | package cli 25 | 26 | import ( 27 | "fmt" 28 | "regexp" 29 | "syscall" 30 | 31 | "golang.org/x/term" 32 | ) 33 | 34 | // Prompt for password input 35 | func PromptPassword(initialPrompt string, expectedFormat string, incorrectFormatPrompt string) string { 36 | 37 | // Print initial prompt 38 | fmt.Println(initialPrompt) 39 | 40 | // Get valid user input 41 | var input string 42 | var init bool 43 | for !init || !regexp.MustCompile(expectedFormat).MatchString(input) { 44 | 45 | // Incorrect format 46 | if init { 47 | fmt.Println("") 48 | fmt.Println(incorrectFormatPrompt) 49 | } else { 50 | init = true 51 | } 52 | 53 | // Read password 54 | if bytes, err := term.ReadPassword(syscall.Stdin); err != nil { 55 | fmt.Println(fmt.Errorf("Could not read password: %w", err)) 56 | } else { 57 | input = string(bytes) 58 | } 59 | 60 | } 61 | fmt.Println("") 62 | 63 | // Return user input 64 | return input 65 | 66 | } 67 | -------------------------------------------------------------------------------- /shared/utils/cli/prompt_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | /* 5 | This work is licensed and released under GNU GPL v3 or any other later versions. 6 | The full text of the license is below/ found at 7 | 8 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | */ 23 | 24 | package cli 25 | 26 | // Prompt for password input 27 | func PromptPassword(initialPrompt string, expectedFormat string, incorrectFormatPrompt string) string { 28 | return Prompt(initialPrompt, expectedFormat, incorrectFormatPrompt) 29 | } 30 | -------------------------------------------------------------------------------- /shared/utils/crypto/base64.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "encoding/base64" 5 | ) 6 | 7 | func DecodeBase64(data string) ([]byte, error) { 8 | res, err := base64.StdEncoding.DecodeString(data) 9 | if err != nil { 10 | return nil, err 11 | } 12 | 13 | return res, nil 14 | } 15 | 16 | func EncodeBase64(data []byte) string { 17 | return base64.StdEncoding.EncodeToString(data) 18 | } 19 | -------------------------------------------------------------------------------- /shared/utils/crypto/rsa.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/sha256" 7 | "crypto/x509" 8 | "encoding/pem" 9 | "fmt" 10 | ) 11 | 12 | func BytesToPublicKey(pub []byte) (*rsa.PublicKey, error) { 13 | block, _ := pem.Decode(pub) 14 | if block == nil { 15 | return nil, fmt.Errorf("failed to parse PEM block containing the key") 16 | } 17 | b := block.Bytes 18 | var err error 19 | 20 | key, err := x509.ParsePKIXPublicKey(b) 21 | if err != nil { 22 | fmt.Printf("Error using x509.ParsePKIXPublicKey %v\n", err) 23 | return nil, err 24 | } 25 | 26 | return key.(*rsa.PublicKey), nil 27 | } 28 | 29 | func EncryptUsingPublicKey(data []byte, publicKey *rsa.PublicKey) ([]byte, error) { 30 | exitMsgEncrypted, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, data, nil) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return exitMsgEncrypted, nil 36 | } 37 | -------------------------------------------------------------------------------- /shared/utils/hex/hex.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package hex 21 | 22 | import ( 23 | "github.com/ethereum/go-ethereum/common/hexutil" 24 | ) 25 | 26 | // Add a prefix to a hex string if not present 27 | func AddPrefix(value string) string { 28 | if len(value) < 2 || value[0:2] != "0x" { 29 | return "0x" + value 30 | } 31 | return value 32 | } 33 | 34 | // Remove a prefix from a hex string if present 35 | func RemovePrefix(value string) string { 36 | if len(value) >= 2 && value[0:2] == "0x" { 37 | return value[2:] 38 | } 39 | return value 40 | } 41 | 42 | func Decode(value string) ([]byte, error) { 43 | return hexutil.Decode(value) 44 | } 45 | -------------------------------------------------------------------------------- /shared/utils/log/colors.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package log 21 | 22 | const ( 23 | ColorBlue string = "\033[36m" 24 | ColorReset string = "\033[0m" 25 | ColorRed string = "\033[31m" 26 | ColorGreen string = "\033[32m" 27 | ColorYellow string = "\033[33m" 28 | ) 29 | -------------------------------------------------------------------------------- /shared/utils/log/logger.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package log 21 | 22 | import ( 23 | "log" 24 | 25 | "github.com/fatih/color" 26 | ) 27 | 28 | // Logger with ANSI color output 29 | type ColorLogger struct { 30 | Color color.Attribute 31 | sprintFunc func(a ...interface{}) string 32 | sprintfFunc func(format string, a ...interface{}) string 33 | } 34 | 35 | // Create new color logger 36 | func NewColorLogger(colorAttr color.Attribute) ColorLogger { 37 | return ColorLogger{ 38 | Color: colorAttr, 39 | sprintFunc: color.New(colorAttr).SprintFunc(), 40 | sprintfFunc: color.New(colorAttr).SprintfFunc(), 41 | } 42 | } 43 | 44 | // Print values 45 | func (l *ColorLogger) Print(v ...interface{}) { 46 | log.Print(l.sprintFunc(v...)) 47 | } 48 | 49 | // Print values with a newline 50 | func (l *ColorLogger) Println(v ...interface{}) { 51 | log.Println(l.sprintFunc(v...)) 52 | } 53 | 54 | // Print a formatted string 55 | func (l *ColorLogger) Printf(format string, v ...interface{}) { 56 | log.Print(l.sprintfFunc(format, v...)) 57 | } 58 | 59 | // Print a formatted string with a newline 60 | func (l *ColorLogger) Printlnf(format string, v ...interface{}) { 61 | log.Println(l.sprintfFunc(format, v...)) 62 | } 63 | -------------------------------------------------------------------------------- /shared/utils/math/math.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package math 21 | 22 | import ( 23 | "math" 24 | ) 25 | 26 | // Round a float64 down to a number of places 27 | func RoundDown(val float64, places int) float64 { 28 | return math.Floor(val*math.Pow10(places)) / math.Pow10(places) 29 | } 30 | 31 | // Round a float64 up to a number of places 32 | func RoundUp(val float64, places int) float64 { 33 | return math.Ceil(val*math.Pow10(places)) / math.Pow10(places) 34 | } 35 | -------------------------------------------------------------------------------- /shared/utils/net/http.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | ) 10 | 11 | func MakePostRequest(requestUrl string, requestBody interface{}) (*http.Response, error) { 12 | requestBodyBytes, err := json.Marshal(requestBody) 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | req, err := http.NewRequest("POST", requestUrl, bytes.NewBuffer(requestBodyBytes)) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | req.Header.Set("Content-Type", "application/json") 23 | 24 | client := &http.Client{} 25 | resp, err := client.Do(req) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | return resp, nil 31 | } 32 | 33 | func MakeGetRequest(requestUrl string, queryParameters interface{}) (*http.Response, error) { 34 | queryValues := url.Values{} 35 | queryParamsJSON, err := json.Marshal(queryParameters) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | err = json.Unmarshal(queryParamsJSON, &queryValues) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | req, err := http.NewRequest("GET", fmt.Sprintf("%s?%s", requestUrl, queryValues.Encode()), nil) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | client := &http.Client{} 51 | resp, err := client.Do(req) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | return resp, nil 57 | } 58 | -------------------------------------------------------------------------------- /shared/utils/net/net.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package net 21 | 22 | import ( 23 | "fmt" 24 | "regexp" 25 | ) 26 | 27 | // Add a default port to a host address 28 | func DefaultPort(host string, port string) string { 29 | if !regexp.MustCompile(":\\d+$").MatchString(host) { 30 | return fmt.Sprintf("%s:%s", host, port) 31 | } 32 | return host 33 | } 34 | -------------------------------------------------------------------------------- /shared/utils/stader/merkle-proof-download.go: -------------------------------------------------------------------------------- 1 | package stader 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/stader-labs/stader-node/shared/services" 8 | stader_backend "github.com/stader-labs/stader-node/shared/types/stader-backend" 9 | "github.com/stader-labs/stader-node/shared/utils/net" 10 | "github.com/urfave/cli" 11 | "net/http" 12 | ) 13 | 14 | func GetAllMerkleProofsForOperator(c *cli.Context, operator common.Address) ([]*stader_backend.CycleMerkleProofs, error) { 15 | config, err := services.GetConfig(c) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | res, err := net.MakeGetRequest(fmt.Sprintf(config.StaderNode.GetMerkleProofApi(), operator.Hex()), struct{}{}) 21 | if err != nil { 22 | return nil, err 23 | } 24 | defer res.Body.Close() 25 | if res.StatusCode == http.StatusBadRequest { 26 | return []*stader_backend.CycleMerkleProofs{}, nil 27 | } 28 | if res.StatusCode != http.StatusOK { 29 | return nil, fmt.Errorf("error while getting all merkle proofs for operator %s", operator.Hex()) 30 | } 31 | 32 | var allMerkleProofs []*stader_backend.CycleMerkleProofs 33 | err = json.NewDecoder(res.Body).Decode(&allMerkleProofs) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return allMerkleProofs, nil 38 | } 39 | -------------------------------------------------------------------------------- /shared/utils/stader/node-diversity.go: -------------------------------------------------------------------------------- 1 | package stader 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/stader-labs/stader-node/shared/services" 8 | stader_backend "github.com/stader-labs/stader-node/shared/types/stader-backend" 9 | "github.com/stader-labs/stader-node/shared/utils/net" 10 | "github.com/urfave/cli" 11 | ) 12 | 13 | func SendNodeDiversityResponseType( 14 | c *cli.Context, 15 | request *stader_backend.NodeDiversityRequest, 16 | ) (*stader_backend.NodeDiversityResponseType, error) { 17 | config, err := services.GetConfig(c) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | res, err := net.MakePostRequest(config.StaderNode.GetNodeDiversityApi(), request) 23 | if err != nil { 24 | return nil, fmt.Errorf("request to GetNodeDiversityApi %w", err) 25 | } 26 | defer res.Body.Close() 27 | 28 | var resp stader_backend.NodeDiversityResponseType 29 | err = json.NewDecoder(res.Body).Decode(&resp) 30 | 31 | if err != nil { 32 | return nil, fmt.Errorf("decode NodeDiversityResponseType %w", err) 33 | } 34 | 35 | return &resp, nil 36 | } 37 | -------------------------------------------------------------------------------- /shared/utils/stdr/fee-recipient.go: -------------------------------------------------------------------------------- 1 | package stdr 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 5 | "github.com/ethereum/go-ethereum/common" 6 | "github.com/stader-labs/stader-node/stader-lib/node" 7 | "github.com/stader-labs/stader-node/stader-lib/stader" 8 | stader_config "github.com/stader-labs/stader-node/stader-lib/stader-config" 9 | ) 10 | 11 | type FeeRecipientInfo struct { 12 | SocializingPoolAddress common.Address `json:"socializingPoolAddress"` 13 | FeeDistributorAddress common.Address `json:"feeDistributorAddress"` 14 | IsInSocializingPool bool `json:"isInSocializingPool"` 15 | } 16 | 17 | func GetFeeRecipientInfo(prn *stader.PermissionlessNodeRegistryContractManager, vf *stader.VaultFactoryContractManager, sdcfg *stader.StaderConfigContractManager, nodeAddress common.Address, opts *bind.CallOpts) (*FeeRecipientInfo, error) { 18 | feeRecipientInfo := FeeRecipientInfo{ 19 | SocializingPoolAddress: common.Address{}, 20 | FeeDistributorAddress: common.Address{}, 21 | IsInSocializingPool: false, 22 | } 23 | 24 | operatorId, err := node.GetOperatorId(prn, nodeAddress, opts) 25 | if err != nil { 26 | return nil, err 27 | } 28 | operatorInfo, err := node.GetOperatorInfo(prn, operatorId, opts) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | if operatorInfo.OptedForSocializingPool { 34 | feeRecipientInfo.IsInSocializingPool = true 35 | socializingPoolAddress, err := stader_config.GetSocializingPoolContractAddress(sdcfg, nil) 36 | if err != nil { 37 | return nil, err 38 | } 39 | feeRecipientInfo.SocializingPoolAddress = socializingPoolAddress 40 | } else { 41 | nodeElRewardAddress, err := node.GetNodeElRewardAddress(prn, 1, operatorId, opts) 42 | if err != nil { 43 | return nil, err 44 | } 45 | feeRecipientInfo.FeeDistributorAddress = nodeElRewardAddress 46 | } 47 | 48 | return &feeRecipientInfo, nil 49 | } 50 | -------------------------------------------------------------------------------- /shared/utils/string-utils/str-convs.go: -------------------------------------------------------------------------------- 1 | package string_utils 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "strings" 7 | ) 8 | 9 | func StringifyArray(arr []*big.Int) string { 10 | var strArr []string 11 | for _, v := range arr { 12 | strArr = append(strArr, v.String()) 13 | } 14 | return strings.Join(strArr, ",") 15 | } 16 | 17 | // write a method given a comma seperated value of string numbers, get the big Ints back 18 | func DestringifyArray(arr string) ([]*big.Int, error) { 19 | var intArr []*big.Int 20 | for _, v := range strings.Split(arr, ",") { 21 | i, ok := new(big.Int).SetString(v, 10) 22 | if !ok { 23 | return nil, fmt.Errorf("could not parse string to big int: %s", v) 24 | } 25 | intArr = append(intArr, i) 26 | } 27 | return intArr, nil 28 | } 29 | -------------------------------------------------------------------------------- /shared/utils/sys/cpu-flags.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package sys 21 | 22 | import ( 23 | "runtime" 24 | "sort" 25 | 26 | "github.com/klauspost/cpuid/v2" 27 | ) 28 | 29 | // Returns the CPU features that are required to run "modern" images but are not present on the node's CPU 30 | func GetMissingModernCpuFeatures() []string { 31 | var features map[cpuid.FeatureID]string 32 | switch runtime.GOARCH { 33 | case "amd64": 34 | features = map[cpuid.FeatureID]string{ 35 | cpuid.ADX: "adx", 36 | //cpuid.AESNI: "aes", 37 | cpuid.AVX: "avx", 38 | cpuid.AVX2: "avx2", 39 | cpuid.BMI1: "bmi1", 40 | cpuid.BMI2: "bmi2", 41 | cpuid.CLMUL: "clmul", 42 | cpuid.MMX: "mmx", 43 | cpuid.SSE: "sse", 44 | cpuid.SSE2: "sse2", 45 | cpuid.SSSE3: "ssse3", 46 | cpuid.SSE4: "sse4.1", 47 | cpuid.SSE42: "sse4.2", 48 | } 49 | default: 50 | features = map[cpuid.FeatureID]string{} 51 | } 52 | 53 | unsupportedFeatures := []string{} 54 | for feature, name := range features { 55 | if !cpuid.CPU.Supports(feature) { 56 | unsupportedFeatures = append(unsupportedFeatures, name) 57 | } 58 | } 59 | 60 | sort.Strings(unsupportedFeatures) 61 | return unsupportedFeatures 62 | } 63 | -------------------------------------------------------------------------------- /shared/utils/term/term_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | /* 5 | This work is licensed and released under GNU GPL v3 or any other later versions. 6 | The full text of the license is below/ found at 7 | 8 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | */ 23 | 24 | package term 25 | 26 | import ( 27 | "os" 28 | "os/exec" 29 | ) 30 | 31 | // Clear terminal output 32 | func Clear() error { 33 | cmd := exec.Command("clear") 34 | cmd.Stdout = os.Stdout 35 | return cmd.Run() 36 | } 37 | -------------------------------------------------------------------------------- /shared/utils/term/term_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | /* 5 | This work is licensed and released under GNU GPL v3 or any other later versions. 6 | The full text of the license is below/ found at 7 | 8 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | */ 23 | 24 | package term 25 | 26 | import ( 27 | "os" 28 | "os/exec" 29 | ) 30 | 31 | // Clear terminal output 32 | func Clear() error { 33 | cmd := exec.Command("cmd", "/c", "cls") 34 | cmd.Stdout = os.Stdout 35 | return cmd.Run() 36 | } 37 | -------------------------------------------------------------------------------- /shared/utils/validator/bls.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package validator 21 | 22 | // BLS signing root with domain 23 | type signingRoot struct { 24 | ObjectRoot []byte `ssz-size:"32"` 25 | Domain []byte `ssz-size:"32"` 26 | } 27 | -------------------------------------------------------------------------------- /shared/utils/validator/deposit-data.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package validator 21 | 22 | import ( 23 | "github.com/ethereum/go-ethereum/common" 24 | "github.com/stader-labs/stader-node/shared/types/eth2" 25 | eth2types "github.com/wealdtech/go-eth2-types/v2" 26 | 27 | "github.com/stader-labs/stader-node/shared/services/beacon" 28 | ) 29 | 30 | // Get deposit data & root for a given validator key and withdrawal credentials 31 | func GetDepositData(validatorKey *eth2types.BLSPrivateKey, withdrawalCredentials common.Hash, eth2Config beacon.Eth2Config, amount uint64) (eth2.DepositData, common.Hash, error) { 32 | // Build deposit data 33 | dd := eth2.DepositDataNoSignature{ 34 | PublicKey: validatorKey.PublicKey().Marshal(), 35 | WithdrawalCredentials: withdrawalCredentials[:], 36 | Amount: amount, 37 | } 38 | 39 | // Get signing root 40 | or, err := dd.HashTreeRoot() 41 | if err != nil { 42 | return eth2.DepositData{}, common.Hash{}, err 43 | } 44 | 45 | sr := eth2.SigningRoot{ 46 | ObjectRoot: or[:], 47 | Domain: eth2types.Domain(eth2types.DomainDeposit, eth2Config.GenesisForkVersion, eth2types.ZeroGenesisValidatorsRoot), 48 | } 49 | 50 | // Get signing root with domain 51 | srHash, err := sr.HashTreeRoot() 52 | if err != nil { 53 | return eth2.DepositData{}, common.Hash{}, err 54 | } 55 | 56 | // Build deposit data struct (with signature) 57 | var depositData = eth2.DepositData{ 58 | PublicKey: dd.PublicKey, 59 | WithdrawalCredentials: dd.WithdrawalCredentials, 60 | Amount: dd.Amount, 61 | Signature: validatorKey.Sign(srHash[:]).Marshal(), 62 | } 63 | 64 | // Get deposit data root 65 | depositDataRoot, err := depositData.HashTreeRoot() 66 | if err != nil { 67 | return eth2.DepositData{}, common.Hash{}, err 68 | } 69 | 70 | // Return 71 | return depositData, depositDataRoot, nil 72 | 73 | } 74 | -------------------------------------------------------------------------------- /shared/utils/validator/voluntary-exit.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package validator 21 | 22 | import ( 23 | "github.com/stader-labs/stader-node/shared/types/eth2" 24 | "github.com/stader-labs/stader-node/stader-lib/types" 25 | eth2types "github.com/wealdtech/go-eth2-types/v2" 26 | ) 27 | 28 | // Get a voluntary exit message signature for a given validator key and index 29 | func GetSignedExitMessage(validatorKey *eth2types.BLSPrivateKey, validatorIndex uint64, epoch uint64, signatureDomain []byte) (types.ValidatorSignature, [32]byte, error) { 30 | 31 | // Build voluntary exit message 32 | exitMessage := eth2.VoluntaryExit{ 33 | Epoch: epoch, 34 | ValidatorIndex: validatorIndex, 35 | } 36 | 37 | // Get object root 38 | or, err := exitMessage.HashTreeRoot() 39 | if err != nil { 40 | return types.ValidatorSignature{}, [32]byte{}, err 41 | } 42 | 43 | // Get signing root 44 | sr := eth2.SigningRoot{ 45 | ObjectRoot: or[:], 46 | Domain: signatureDomain, 47 | } 48 | 49 | srHash, err := sr.HashTreeRoot() 50 | if err != nil { 51 | return types.ValidatorSignature{}, [32]byte{}, err 52 | } 53 | 54 | // Sign message 55 | signature := validatorKey.Sign(srHash[:]).Marshal() 56 | 57 | // Return 58 | return types.BytesToValidatorSignature(signature), srHash, nil 59 | 60 | } 61 | -------------------------------------------------------------------------------- /shared/utils/wallet/recover-keys.go: -------------------------------------------------------------------------------- 1 | package wallet 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/stader-labs/stader-node/shared/services/wallet" 8 | "github.com/stader-labs/stader-node/shared/utils/stdr" 9 | "github.com/stader-labs/stader-node/stader-lib/node" 10 | "github.com/stader-labs/stader-node/stader-lib/stader" 11 | "github.com/stader-labs/stader-node/stader-lib/types" 12 | ) 13 | 14 | const ( 15 | pageSize uint = 20 16 | pageLimit uint = 2000 17 | ) 18 | 19 | func RecoverStaderKeys(pnr *stader.PermissionlessNodeRegistryContractManager, address common.Address, w *wallet.Wallet, testOnly bool) ([]types.ValidatorPubkey, error) { 20 | recoveredKeys := []types.ValidatorPubkey{} 21 | operatorId, err := node.GetOperatorId(pnr, address, nil) 22 | if err != nil { 23 | return nil, err 24 | } 25 | // Get node's validating pubkeys 26 | allOperatorValidators, _, err := stdr.GetAllValidatorsRegisteredWithOperator(pnr, operatorId, address, nil) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | // Recover conventionally generated keys 32 | pageStart := uint(0) 33 | for { 34 | if pageStart >= pageLimit { 35 | return nil, fmt.Errorf("attempt limit exceeded (%d keys)", pageLimit) 36 | } 37 | pageEnd := pageStart + pageSize 38 | if pageEnd > pageLimit { 39 | pageEnd = pageLimit 40 | } 41 | 42 | // Get the keys for this bucket 43 | keys, err := w.GetValidatorKeys(pageStart, pageEnd-pageStart) 44 | if err != nil { 45 | return nil, err 46 | } 47 | for _, validatorKey := range keys { 48 | _, exists := allOperatorValidators[validatorKey.PublicKey] 49 | if exists { 50 | // Found one! 51 | delete(allOperatorValidators, validatorKey.PublicKey) 52 | if !testOnly { 53 | err := w.SaveValidatorKey(validatorKey) 54 | if err != nil { 55 | return nil, fmt.Errorf("error recovering validator keys: %w", err) 56 | } 57 | recoveredKeys = append(recoveredKeys, validatorKey.PublicKey) 58 | } 59 | } 60 | } 61 | 62 | if len(allOperatorValidators) == 0 { 63 | // All keys recovered! 64 | break 65 | } 66 | 67 | // Run another iteration with the next bucket 68 | pageStart = pageEnd 69 | } 70 | 71 | return recoveredKeys, nil 72 | 73 | } 74 | -------------------------------------------------------------------------------- /shared/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without eve n the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package shared 21 | 22 | const BinaryBucket string = "/stader-node-build/permissionless" 23 | const DockerAccount string = "staderlabs" 24 | const StaderVersion string = "1.6.5" 25 | 26 | const Logo string = ` 27 | _____ _ _ _ _ 𝅺 28 | / ____| | | | | | | | 𝅺 29 | | (___ | |_ __ _ __| | ___ _ __ | | __ _| |__ ___ 30 | \___ \| __/ _' |/ _' |/ _ \ '__| | | / _' | '_ \/ __| 31 | ____) | || (_| | (_| | __/ | | |___| (_| | |_) \__ \ 32 | |_____/ \__\__,_|\__,_|\___|_| |______\__,_|_.__/|___/` 33 | -------------------------------------------------------------------------------- /sszgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # Generates the ssz encoding methods for eth2 types with fastssz 22 | # Install sszgen with `go get github.com/ferranbt/fastssz/sszgen` 23 | rm -f ./shared/types/eth2/types_encoding.go 24 | sszgen --path ./shared/types/eth2 -------------------------------------------------------------------------------- /stader-cli/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | export CGO_ENABLED=0 22 | cd /stader-node/stader-cli 23 | 24 | # Build x64 version 25 | GOOS=linux GOARCH=amd64 go build -o stader-cli-linux-amd64 stader-cli.go 26 | GOOS=darwin GOARCH=amd64 go build -o stader-cli-darwin-amd64 stader-cli.go 27 | 28 | # Build the arm64 version 29 | GOOS=linux GOARCH=arm64 go build -o stader-cli-linux-arm64 stader-cli.go 30 | GOOS=darwin GOARCH=arm64 go build -o stader-cli-darwin-arm64 stader-cli.go 31 | -------------------------------------------------------------------------------- /stader-cli/node/download-sp-merkle-proofs.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | "github.com/stader-labs/stader-node/shared/services/stader" 6 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 7 | "github.com/urfave/cli" 8 | ) 9 | 10 | func downloadSPMerkleProofs(c *cli.Context) error { 11 | 12 | staderClient, err := stader.NewClientFromCtx(c) 13 | if err != nil { 14 | return err 15 | } 16 | defer staderClient.Close() 17 | 18 | // Check and assign the EC status 19 | err = cliutils.CheckClientStatus(staderClient) 20 | if err != nil { 21 | return err 22 | } 23 | 24 | canDownloadSpMerkleProofs, err := staderClient.CanDownloadSpMerkleProofs() 25 | if err != nil { 26 | return err 27 | } 28 | if canDownloadSpMerkleProofs.NoMissingCycles { 29 | fmt.Println("There are no missing cycles to download! All proofs are up to date!") 30 | return nil 31 | } 32 | 33 | fmt.Printf("Following cycles are missing: %v\n", canDownloadSpMerkleProofs.MissingCycles) 34 | 35 | // Prompt for confirmation 36 | if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf( 37 | "Are you sure you want to download the missing merkle proofs?"))) { 38 | fmt.Println("Cancelled.") 39 | return nil 40 | } 41 | 42 | fmt.Println("Downloading missing merkle proofs.....") 43 | 44 | res, err := staderClient.DownloadSpMerkleProofs() 45 | if err != nil { 46 | return err 47 | } 48 | 49 | fmt.Printf("Successfully downloaded the merkle proofs for cycles: %v\n", res.DownloadedCycles) 50 | 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /stader-cli/node/get-contracts-info.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/stader-labs/stader-node/shared/services/stader" 7 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 8 | "github.com/stader-labs/stader-node/shared/utils/log" 9 | "github.com/urfave/cli" 10 | ) 11 | 12 | func getContractsInfo(c *cli.Context) error { 13 | staderClient, err := stader.NewClientFromCtx(c) 14 | if err != nil { 15 | return err 16 | } 17 | defer staderClient.Close() 18 | 19 | // Check and assign the EC status 20 | err = cliutils.CheckClientStatus(staderClient) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | // Get node fee 26 | response, err := staderClient.GetContractsInfo() 27 | if err != nil { 28 | return err 29 | } 30 | 31 | fmt.Printf("%s=== Beacon Network Contract Details ===%s\n", log.ColorGreen, log.ColorReset) 32 | fmt.Printf("Beacon Network: %d\n\n", response.BeaconNetwork) 33 | fmt.Printf("Beacon Deposit Contract: %s\n\n", response.BeaconDepositContract) 34 | 35 | fmt.Printf("%s=== Stader Network Contract Details ===%s\n", log.ColorGreen, log.ColorReset) 36 | fmt.Printf("Network: %d\n\n", response.Network) 37 | fmt.Printf("Stader Config: %s\n\n", response.StaderConfig) 38 | fmt.Printf("Permissionless Node Registry: %s\n\n", response.PermissionlessNodeRegistry) 39 | fmt.Printf("Vault Factory: %s\n\n", response.VaultFactory) 40 | fmt.Printf("Sd Collateral Lock: %s\n\n", response.SdCollateralContract) 41 | fmt.Printf("EthX Token: %s\n\n", response.EthxToken) 42 | fmt.Printf("Sd Token: %s\n\n", response.SdToken) 43 | fmt.Printf("Socializing Pool: %s\n\n", response.SocializingPoolContract) 44 | fmt.Printf("Permissionless Pool: %s\n\n", response.PermisionlessPool) 45 | fmt.Printf("Stader Oracle: %s\n\n", response.StaderOracle) 46 | fmt.Printf("Sd Utility Pool: %s\n\n", response.SdUtilityContract) 47 | fmt.Printf("Pre-sign encryption key is %s\n\n", response.EncryptionKey) 48 | 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /stader-cli/node/send-el-rewards.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/stader-labs/stader-node/shared/services/gas" 7 | "github.com/stader-labs/stader-node/shared/services/stader" 8 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 9 | "github.com/stader-labs/stader-node/stader-lib/utils/eth" 10 | "github.com/urfave/cli" 11 | ) 12 | 13 | func SendElRewards(c *cli.Context) error { 14 | staderClient, err := stader.NewClientFromCtx(c) 15 | if err != nil { 16 | return err 17 | } 18 | defer staderClient.Close() 19 | 20 | // Check and assign the EC status 21 | err = cliutils.CheckClientStatus(staderClient) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | // Print what network we're on 27 | err = cliutils.PrintNetwork(staderClient) 28 | 29 | // Check if we can Withdraw El Rewards 30 | canClaimElRewardsResponse, err := staderClient.CanSendElRewards() 31 | if err != nil { 32 | return err 33 | } 34 | if canClaimElRewardsResponse.NoElRewards { 35 | fmt.Printf("No El Rewards to withdraw\n") 36 | return nil 37 | } 38 | 39 | err = gas.AssignMaxFeeAndLimit(canClaimElRewardsResponse.GasInfo, staderClient, c.Bool("yes")) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | // Prompt for confirmation 45 | if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf( 46 | "Are you sure you want to send El Rewards to claim vault?"))) { 47 | fmt.Println("Cancelled.") 48 | return nil 49 | } 50 | 51 | res, err := staderClient.SendElRewards() 52 | if err != nil { 53 | return err 54 | } 55 | 56 | fmt.Printf("Sending %s EL Rewards to Claim Vault\n\n", eth.DisplayAmountInUnits(res.ElRewardsAmount, "eth")) 57 | cliutils.PrintTransactionHash(staderClient, res.TxHash) 58 | 59 | if _, err = staderClient.WaitForTransaction(res.TxHash); err != nil { 60 | return err 61 | } 62 | 63 | // Log & return 64 | fmt.Printf("Sent %s EL Rewards to Claim Vault\n\n", eth.DisplayAmountInUnits(res.ElRewardsAmount, "eth")) 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /stader-cli/node/sign-message.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package node 21 | 22 | import ( 23 | "fmt" 24 | 25 | "encoding/json" 26 | 27 | "github.com/ethereum/go-ethereum/common" 28 | "github.com/urfave/cli" 29 | 30 | "github.com/stader-labs/stader-node/shared/services/stader" 31 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 32 | ) 33 | 34 | const signatureVersion = 1 35 | 36 | type PersonalSignature struct { 37 | Address common.Address `json:"address"` 38 | Message string `json:"msg"` 39 | Signature string `json:"sig"` 40 | Version string `json:"version"` // beaconcha.in expects a string 41 | } 42 | 43 | func signMessage(c *cli.Context) error { 44 | 45 | staderClient, err := stader.NewClientFromCtx(c) 46 | if err != nil { 47 | return err 48 | } 49 | defer staderClient.Close() 50 | 51 | // Get & check wallet status 52 | status, err := staderClient.WalletStatus() 53 | if err != nil { 54 | return err 55 | } 56 | 57 | if !status.WalletInitialized { 58 | fmt.Println("The node wallet is not initialized.") 59 | return nil 60 | } 61 | 62 | message := c.String("message") 63 | for message == "" { 64 | message = cliutils.Prompt("Please enter the message you want to sign: (EIP-191 personal_sign)", "^.+$", "Please enter the message you want to sign: (EIP-191 personal_sign)") 65 | } 66 | 67 | response, err := staderClient.SignMessage(message) 68 | if err != nil { 69 | return err 70 | } 71 | 72 | // Print the signature 73 | formattedSignature := PersonalSignature{ 74 | Address: status.AccountAddress, 75 | Message: message, 76 | Signature: response.SignedData, 77 | Version: fmt.Sprint(signatureVersion), 78 | } 79 | bytes, err := json.MarshalIndent(formattedSignature, "", " ") 80 | if err != nil { 81 | return err 82 | } 83 | 84 | fmt.Printf("Signed Error:\n\n%s\n", string(bytes)) 85 | 86 | return nil 87 | 88 | } 89 | -------------------------------------------------------------------------------- /stader-cli/node/update-operator-name.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | "github.com/stader-labs/stader-node/shared/services/gas" 6 | "github.com/stader-labs/stader-node/shared/services/stader" 7 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 8 | "github.com/urfave/cli" 9 | ) 10 | 11 | func updateOperatorName(c *cli.Context, operatorName string) error { 12 | 13 | staderClient, err := stader.NewClientFromCtx(c) 14 | if err != nil { 15 | return err 16 | } 17 | defer staderClient.Close() 18 | 19 | // check if we can update the el 20 | res, err := staderClient.CanUpdateOperatorName(operatorName) 21 | if err != nil { 22 | return err 23 | } 24 | if res.OperatorNotActive { 25 | fmt.Println("Operator not active") 26 | return nil 27 | } 28 | if res.OperatorNameTooLong { 29 | fmt.Println("Operator name too long") 30 | return nil 31 | } 32 | if res.NothingToUpdate { 33 | fmt.Println("Nothing to update") 34 | return nil 35 | } 36 | if res.IsPermissionlessNodeRegistryPaused { 37 | fmt.Println("Permissionless Node Registry is paused.") 38 | return nil 39 | } 40 | 41 | err = gas.AssignMaxFeeAndLimit(res.GasInfo, staderClient, c.Bool("yes")) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf( 47 | "Are you sure you want to update your operator name?"))) { 48 | fmt.Println("Cancelled.") 49 | return nil 50 | } 51 | 52 | // update the socializing pool el 53 | response, err := staderClient.UpdateOperatorName(operatorName) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | fmt.Println("Updating operator name...") 59 | 60 | cliutils.PrintTransactionHash(staderClient, response.TxHash) 61 | _, err = staderClient.WaitForTransaction(response.TxHash) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | fmt.Println("Operator name updated!") 67 | 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /stader-cli/service/configFallback.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package service 21 | 22 | import ( 23 | stdCf "github.com/stader-labs/stader-node/shared/services/config" 24 | "github.com/stader-labs/stader-node/shared/types/config" 25 | ) 26 | 27 | func setUIFallbackClient(cfg *stdCf.StaderConfig, newSettings map[string]interface{}) error { 28 | newSettings[keys.Fc_use_fallback_clients] = cfg.UseFallbackClients.Value.(bool) 29 | newSettings[keys.Fc_true_reconnect_delay] = cfg.ReconnectDelay.Value 30 | 31 | selectedCC, _ := cfg.GetSelectedConsensusClientConfig() 32 | switch selectedCC.GetName() { 33 | case string(config.ConsensusClient_Prysm): 34 | newSettings[keys.Fc_true_execution_client_url] = cfg.FallbackPrysm.EcHttpUrl.Value 35 | newSettings[keys.Fc_true_beacon_node_url] = cfg.FallbackPrysm.CcHttpUrl.Value 36 | default: 37 | newSettings[keys.Fc_true_execution_client_url] = cfg.FallbackNormal.EcHttpUrl.Value 38 | newSettings[keys.Fc_true_beacon_node_url] = cfg.FallbackNormal.CcHttpUrl.Value 39 | } 40 | 41 | newSettings[keys.Fc_true_beacon_node_json_rpc_url] = cfg.FallbackPrysm.JsonRpcUrl.Value 42 | return nil 43 | } 44 | 45 | func updateFallbackClient(cfg *stdCf.StaderConfig, newSettings map[string]interface{}) error { 46 | cfg.UseFallbackClients.Value = newSettings[keys.Fc_use_fallback_clients] 47 | 48 | if cfg.UseFallbackClients.Value.(bool) { 49 | cfg.ReconnectDelay.Value = newSettings[keys.Fc_true_reconnect_delay] 50 | cfg.FallbackNormal.EcHttpUrl.Value = newSettings[keys.Fc_true_execution_client_url] 51 | cfg.FallbackNormal.CcHttpUrl.Value = newSettings[keys.Fc_true_beacon_node_url] 52 | 53 | cfg.FallbackPrysm.EcHttpUrl.Value = newSettings[keys.Fc_true_execution_client_url] 54 | cfg.FallbackPrysm.CcHttpUrl.Value = newSettings[keys.Fc_true_beacon_node_url] 55 | cfg.FallbackPrysm.JsonRpcUrl.Value = newSettings[keys.Fc_true_beacon_node_json_rpc_url] 56 | } 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /stader-cli/service/guardian.tmpl: -------------------------------------------------------------------------------- 1 | # This work is licensed and released under GNU GPL v3 or any other later versions. 2 | # The full text of the license is below/ found at 3 | 4 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 5 | 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | # Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY 20 | # If you want to overwrite some of these values with your own customizations, 21 | # please add them to `override/guardian.yml`. 22 | # 23 | # See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration 24 | # for more information on overriding specific parameters of docker-compose files. 25 | 26 | version: "3.7" 27 | services: 28 | guardian: 29 | image: ${STADER_NODE_IMAGE} 30 | container_name: ${COMPOSE_PROJECT_NAME}_guardian 31 | restart: unless-stopped 32 | ports: [${GUARDIAN_OPEN_PORTS}] 33 | volumes: 34 | - ${STADER_FOLDER}:/.stader 35 | - ${STADER_DATA_FOLDER}:/.stader/data 36 | networks: 37 | - net 38 | command: "-m 0.0.0.0 -r ${NODE_METRICS_PORT:-9104} guardian" 39 | cap_drop: 40 | - all 41 | cap_add: 42 | - dac_override 43 | security_opt: 44 | - no-new-privileges 45 | networks: 46 | net: -------------------------------------------------------------------------------- /stader-cli/validator/exit-validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | "github.com/stader-labs/stader-node/shared/services/stader" 6 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 7 | "github.com/stader-labs/stader-node/stader-lib/types" 8 | "github.com/urfave/cli" 9 | ) 10 | 11 | func ExitValidator(c *cli.Context, validatorPubKey types.ValidatorPubkey) error { 12 | staderClient, err := stader.NewClientFromCtx(c) 13 | if err != nil { 14 | return err 15 | } 16 | defer staderClient.Close() 17 | 18 | // Check and assign the EC status 19 | err = cliutils.CheckClientStatus(staderClient) 20 | if err != nil { 21 | return err 22 | } 23 | 24 | // check canExit 25 | response, err := staderClient.CanExitValidator(validatorPubKey) 26 | if err != nil { 27 | return err 28 | } 29 | if response.ValidatorNotRegistered { 30 | fmt.Println("Validator not registered!") 31 | return nil 32 | } 33 | if response.ValidatorTooYoung { 34 | fmt.Println("Validator too young!") 35 | return nil 36 | } 37 | if response.ValidatorExiting { 38 | fmt.Println("Validator already exiting!") 39 | return nil 40 | } 41 | if response.ValidatorNotActive { 42 | fmt.Println("Validator not active!") 43 | return nil 44 | } 45 | 46 | // Prompt for confirmation 47 | if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf( 48 | "Are you sure you want to exit validator %s?", validatorPubKey))) { 49 | fmt.Println("Cancelled.") 50 | return nil 51 | } 52 | 53 | // now exit 54 | exitResponse, err := staderClient.ExitValidator(validatorPubKey) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | fmt.Printf("Exiting validator %s, you check check the validator status at %s\n", validatorPubKey, fmt.Sprintf("%s/validator/%s#withdrawals", exitResponse.BeaconChainUrl, validatorPubKey)) 60 | 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /stader-cli/validator/send-cl-rewards.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/stader-labs/stader-node/shared/services/gas" 7 | 8 | "github.com/stader-labs/stader-node/shared/services/stader" 9 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 10 | "github.com/stader-labs/stader-node/stader-lib/types" 11 | "github.com/stader-labs/stader-node/stader-lib/utils/eth" 12 | "github.com/urfave/cli" 13 | ) 14 | 15 | func SendClRewards(c *cli.Context, validatorPubKey types.ValidatorPubkey) error { 16 | staderClient, err := stader.NewClientFromCtx(c) 17 | if err != nil { 18 | return err 19 | } 20 | defer staderClient.Close() 21 | 22 | // Check and assign the EC status 23 | err = cliutils.CheckClientStatus(staderClient) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | // Print what network we're on 29 | err = cliutils.PrintNetwork(staderClient) 30 | 31 | canClaimClRewardsResponse, err := staderClient.CanSendClRewards(validatorPubKey) 32 | if err != nil { 33 | return err 34 | } 35 | if canClaimClRewardsResponse.NoClRewards { 36 | fmt.Printf("No CL rewards to withdraw for validator %s\n", validatorPubKey.String()) 37 | return nil 38 | } 39 | if canClaimClRewardsResponse.TooManyClRewards { 40 | fmt.Printf("Too many CL rewards to withdraw for validator %s.\n", validatorPubKey.String()) 41 | fmt.Printf("If you have exited the validator, Please wait for Stader Oracles to settle your funds!\n") 42 | fmt.Printf("If you have not exited the validator, Please reach out to the Stader Team on discord!\n") 43 | return nil 44 | } 45 | if canClaimClRewardsResponse.ValidatorNotFound { 46 | fmt.Printf("Validator %s not found\n", validatorPubKey.String()) 47 | return nil 48 | } 49 | if canClaimClRewardsResponse.VaultAlreadySettled { 50 | fmt.Printf("Vault for validator %s has already been settled\n", validatorPubKey.String()) 51 | return nil 52 | } 53 | 54 | err = gas.AssignMaxFeeAndLimit(canClaimClRewardsResponse.GasInfo, staderClient, c.Bool("yes")) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | // Prompt for confirmation 60 | if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf( 61 | "Are you sure you want to send CL rewards for validator %s to claim vault?", validatorPubKey))) { 62 | fmt.Println("Cancelled.") 63 | return nil 64 | } 65 | 66 | res, err := staderClient.SendClRewards(validatorPubKey) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | fmt.Printf("Sending %s CL Rewards to Claim vault\n\n", eth.DisplayAmountInUnits(res.ClRewardsAmount, "eth")) 72 | cliutils.PrintTransactionHash(staderClient, res.TxHash) 73 | if _, err = staderClient.WaitForTransaction(res.TxHash); err != nil { 74 | return err 75 | } 76 | 77 | // Log & return 78 | fmt.Printf("Sent %s CL Rewards to Claim vault\n\n", eth.DisplayAmountInUnits(res.ClRewardsAmount, "eth")) 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /stader-cli/wallet/bip39/mnemonic-validator.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package bip39 21 | 22 | import ( 23 | "errors" 24 | "sort" 25 | "strings" 26 | 27 | "github.com/tyler-smith/go-bip39" 28 | ) 29 | 30 | type MnemonicValidator struct { 31 | mnemonic []string 32 | } 33 | 34 | func Create(length int) *MnemonicValidator { 35 | 36 | if length <= 0 { 37 | return nil 38 | } 39 | 40 | out := &MnemonicValidator{} 41 | 42 | out.mnemonic = make([]string, 0, length) 43 | 44 | return out 45 | } 46 | 47 | func (mv *MnemonicValidator) AddWord(input string) error { 48 | wordList := bip39.GetWordList() 49 | 50 | idx := sort.SearchStrings(wordList, input) 51 | if idx >= len(wordList) { 52 | return errors.New("Invalid word") 53 | } 54 | 55 | if wordList[idx] != input && (len(input) < 4 || wordList[idx][:4] != input[:4]) { 56 | return errors.New("Invalid word") 57 | } 58 | 59 | mv.mnemonic = append(mv.mnemonic, wordList[idx]) 60 | return nil 61 | } 62 | 63 | func (mv *MnemonicValidator) Filled() bool { 64 | return len(mv.mnemonic) == cap(mv.mnemonic) 65 | } 66 | 67 | func (mv *MnemonicValidator) Finalize() (string, error) { 68 | 69 | if mv.Filled() == false { 70 | return "", errors.New("Not enough words were entered.") 71 | } 72 | 73 | mnemonic := strings.Join(mv.mnemonic, " ") 74 | if bip39.IsMnemonicValid(mnemonic) { 75 | return mnemonic, nil 76 | } 77 | 78 | return "", errors.New("Invalid mnemonic") 79 | } 80 | -------------------------------------------------------------------------------- /stader-cli/wallet/export.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "fmt" 24 | "os" 25 | 26 | "github.com/urfave/cli" 27 | 28 | "github.com/stader-labs/stader-node/shared/services/stader" 29 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 30 | ) 31 | 32 | func exportWallet(c *cli.Context) error { 33 | 34 | staderCLient, err := stader.NewClientFromCtx(c) 35 | if err != nil { 36 | return err 37 | } 38 | defer staderCLient.Close() 39 | 40 | // Get & check wallet status 41 | status, err := staderCLient.WalletStatus() 42 | if err != nil { 43 | return err 44 | } 45 | if !status.WalletInitialized { 46 | fmt.Println("The node wallet is not initialized.") 47 | return nil 48 | } 49 | 50 | if !c.GlobalBool("secure-session") { 51 | // Check if stdout is interactive 52 | stat, err := os.Stdout.Stat() 53 | if err != nil { 54 | fmt.Fprintf(os.Stderr, "An error occurred while determining whether or not the output is a tty: %s\n"+ 55 | "Use \"stader-cli --secure-session wallet export\" to bypass.\n", err.Error()) 56 | os.Exit(1) 57 | } 58 | 59 | if (stat.Mode()&os.ModeCharDevice) == os.ModeCharDevice && 60 | !cliutils.ConfirmSecureSession("Exporting a wallet will print sensitive information to your screen.") { 61 | return nil 62 | } 63 | } 64 | 65 | // Export wallet 66 | export, err := staderCLient.ExportWallet() 67 | if err != nil { 68 | return err 69 | } 70 | 71 | // Print wallet & return 72 | fmt.Println("Node account private key:") 73 | fmt.Println("") 74 | fmt.Println(export.AccountPrivateKey) 75 | fmt.Println("") 76 | fmt.Println("Wallet password:") 77 | fmt.Println("") 78 | fmt.Println(export.Password) 79 | fmt.Println("") 80 | fmt.Println("Wallet file:") 81 | fmt.Println("============") 82 | fmt.Println("") 83 | fmt.Println(export.Wallet) 84 | fmt.Println("") 85 | fmt.Println("============") 86 | return nil 87 | 88 | } 89 | -------------------------------------------------------------------------------- /stader-cli/wallet/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "fmt" 24 | 25 | "github.com/stader-labs/stader-node/shared/services/stader" 26 | "github.com/urfave/cli" 27 | 28 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 29 | ) 30 | 31 | func getStatus(c *cli.Context) error { 32 | 33 | staderClient, err := stader.NewClientFromCtx(c) 34 | if err != nil { 35 | return err 36 | } 37 | defer staderClient.Close() 38 | 39 | // Print what network we're on 40 | err = cliutils.PrintNetwork(staderClient) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | // Get wallet status 46 | status, err := staderClient.WalletStatus() 47 | if err != nil { 48 | return err 49 | } 50 | 51 | // Print status & return 52 | if status.WalletInitialized { 53 | fmt.Println("The node wallet is initialized.") 54 | fmt.Printf("Node account: %s\n", status.AccountAddress.Hex()) 55 | fmt.Printf("Current Nonce: %d\n", status.CurrentNonce) 56 | fmt.Printf("Pending Nonce: %d\n", status.PendingNonce) 57 | } else { 58 | fmt.Println("The node wallet has not been initialized.") 59 | } 60 | return nil 61 | 62 | } 63 | -------------------------------------------------------------------------------- /stader-lib/README.md: -------------------------------------------------------------------------------- 1 | # Stader-node-go 2 | A Golang library for interacting with the stader node network. Parts of this code leverage opensource code from the ethereum community. 3 | -------------------------------------------------------------------------------- /stader-lib/node/node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 5 | "github.com/stader-labs/stader-node/stader-lib/stader" 6 | ) 7 | 8 | func IsPermissionlessNodeRegistryPaused(pnr *stader.PermissionlessNodeRegistryContractManager, opts *bind.CallOpts) (bool, error) { 9 | return pnr.PermissionlessNodeRegistry.Paused(opts) 10 | } 11 | -------------------------------------------------------------------------------- /stader-lib/penalty-tracker/penalty-tracker.go: -------------------------------------------------------------------------------- 1 | package penalty_tracker 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 5 | "github.com/stader-labs/stader-node/stader-lib/stader" 6 | "github.com/stader-labs/stader-node/stader-lib/types" 7 | "math/big" 8 | ) 9 | 10 | func GetCumulativeValidatorPenalty(pt *stader.PenaltyTrackerContractManager, validatorPubKey types.ValidatorPubkey, opts *bind.CallOpts) (*big.Int, error) { 11 | return pt.Penalty.TotalPenaltyAmount(opts, validatorPubKey.Bytes()) 12 | } 13 | -------------------------------------------------------------------------------- /stader-lib/pool-utils/pool-utils.go: -------------------------------------------------------------------------------- 1 | package pool_utils 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 5 | "github.com/ethereum/go-ethereum/common" 6 | "github.com/stader-labs/stader-node/stader-lib/stader" 7 | "github.com/stader-labs/stader-node/stader-lib/types" 8 | "math/big" 9 | ) 10 | 11 | func CalculateRewardShare(pool_utils *stader.PoolUtilsContractManager, poolId uint8, totalRewards *big.Int, opts *bind.CallOpts) (types.RewardShare, error) { 12 | return pool_utils.PoolUtils.CalculateRewardShare(opts, poolId, totalRewards) 13 | } 14 | 15 | func IsExistingOperator(pool_utils *stader.PoolUtilsContractManager, operatorAddress common.Address, opts *bind.CallOpts) (bool, error) { 16 | return pool_utils.PoolUtils.IsExistingOperator(opts, operatorAddress) 17 | } 18 | -------------------------------------------------------------------------------- /stader-lib/stader/abi.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package stader 21 | 22 | import ( 23 | "bytes" 24 | "compress/zlib" 25 | "encoding/base64" 26 | "fmt" 27 | 28 | "github.com/ethereum/go-ethereum/accounts/abi" 29 | ) 30 | 31 | // Decode, decompress and parse a zlib-compressed, base64-encoded ABI 32 | func DecodeAbi(abiEncoded string) (*abi.ABI, error) { 33 | 34 | // base64 decode 35 | abiCompressed, err := base64.StdEncoding.DecodeString(abiEncoded) 36 | if err != nil { 37 | return nil, fmt.Errorf("Could not decode base64 data: %w", err) 38 | } 39 | 40 | // zlib decompress 41 | byteReader := bytes.NewReader(abiCompressed) 42 | zlibReader, err := zlib.NewReader(byteReader) 43 | if err != nil { 44 | return nil, fmt.Errorf("Could not decompress zlib data: %w", err) 45 | } 46 | defer func() { 47 | _ = zlibReader.Close() 48 | }() 49 | 50 | // Parse ABI 51 | abiParsed, err := abi.JSON(zlibReader) 52 | if err != nil { 53 | return nil, fmt.Errorf("Could not parse JSON: %w", err) 54 | } 55 | 56 | // Return 57 | return &abiParsed, nil 58 | 59 | } 60 | 61 | // zlib-compress and base64-encode an ABI JSON string 62 | func EncodeAbiStr(abiStr string) (string, error) { 63 | 64 | // zlib compress 65 | var abiCompressed bytes.Buffer 66 | zlibWriter := zlib.NewWriter(&abiCompressed) 67 | if _, err := zlibWriter.Write([]byte(abiStr)); err != nil { 68 | return "", fmt.Errorf("Could not zlib-compress ABI string: %w", err) 69 | } 70 | if err := zlibWriter.Flush(); err != nil { 71 | return "", fmt.Errorf("Could not zlib-compress ABI string: %w", err) 72 | } 73 | if err := zlibWriter.Close(); err != nil { 74 | return "", fmt.Errorf("Could not zlib-compress ABI string: %w", err) 75 | } 76 | 77 | // base64 encode & return 78 | return base64.StdEncoding.EncodeToString(abiCompressed.Bytes()), nil 79 | 80 | } 81 | -------------------------------------------------------------------------------- /stader-lib/stake-pool-manager/stake-pool-manager.go: -------------------------------------------------------------------------------- 1 | package stake_pool_manager 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 5 | "github.com/stader-labs/stader-node/stader-lib/stader" 6 | "math/big" 7 | ) 8 | 9 | func GetTotalAssets(spm *stader.StakePoolManagerContractManager, opts *bind.CallOpts) (*big.Int, error) { 10 | return spm.StakePoolManager.TotalAssets(opts) 11 | } 12 | -------------------------------------------------------------------------------- /stader-lib/tokens/native.go: -------------------------------------------------------------------------------- 1 | package tokens 2 | 3 | import ( 4 | "context" 5 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 6 | "github.com/ethereum/go-ethereum/common" 7 | "github.com/stader-labs/stader-node/stader-lib/stader" 8 | "math/big" 9 | ) 10 | 11 | func GetEthBalance(client stader.ExecutionClient, address common.Address, opts *bind.CallOpts) (*big.Int, error) { 12 | var blockNumber *big.Int 13 | if opts != nil { 14 | blockNumber = opts.BlockNumber 15 | } 16 | 17 | ethBalance, err := client.BalanceAt(context.Background(), address, blockNumber) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | return ethBalance, nil 23 | } 24 | -------------------------------------------------------------------------------- /stader-lib/types/operator.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "github.com/ethereum/go-ethereum/common" 4 | 5 | type OperatorInfo struct { 6 | Active bool 7 | OptedForSocializingPool bool 8 | OperatorName string 9 | OperatorRewardAddress common.Address 10 | OperatorAddress common.Address 11 | } 12 | -------------------------------------------------------------------------------- /stader-lib/types/pool-utils.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "math/big" 4 | 5 | type RewardShare struct { 6 | UserShare *big.Int 7 | OperatorShare *big.Int 8 | ProtocolShare *big.Int 9 | } 10 | -------------------------------------------------------------------------------- /stader-lib/types/sd-collateral.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "math/big" 4 | 5 | type PoolThresholdInfo struct { 6 | MinThreshold *big.Int 7 | MaxThreshold *big.Int 8 | WithdrawThreshold *big.Int 9 | Units string 10 | } 11 | 12 | type OperatorWithdrawInfo struct { 13 | LastWithdrawReqTimestamp *big.Int 14 | TotalSDWithdrawReqAmount *big.Int 15 | } 16 | -------------------------------------------------------------------------------- /stader-lib/types/socializing-pool.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "math/big" 4 | 5 | type RewardCycleDetails struct { 6 | CurrentIndex *big.Int 7 | CurrentStartBlock *big.Int 8 | CurrentEndBlock *big.Int 9 | } 10 | 11 | type CurrentRewardCycleDetails struct { 12 | StartBlock *big.Int 13 | EndBlock *big.Int 14 | } 15 | -------------------------------------------------------------------------------- /stader-lib/types/validator.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/ethereum/go-ethereum/common" 5 | "math/big" 6 | ) 7 | 8 | type ValidatorContractInfo struct { 9 | Status uint8 10 | Pubkey []byte 11 | PreDepositSignature []byte 12 | DepositSignature []byte 13 | WithdrawVaultAddress common.Address 14 | OperatorId *big.Int 15 | DepositBlock *big.Int 16 | WithdrawnBlock *big.Int 17 | } 18 | -------------------------------------------------------------------------------- /stader-lib/utils/eth/units.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package eth 21 | 22 | import ( 23 | "math/big" 24 | "strconv" 25 | ) 26 | 27 | // Conversion factors 28 | const ( 29 | WeiPerEth float64 = 1e18 30 | WeiPerGwei float64 = 1e9 31 | Decimal = 18 32 | BaseAmountInEth = 4 33 | Threshold = 1e12 34 | ) 35 | 36 | func DisplayAmountInUnits(wei *big.Int, denom string) string { 37 | gweiDenom := " gwei" 38 | if denom == "sd" { 39 | gweiDenom = " gwei SD" 40 | } 41 | 42 | regDenom := " ETH" 43 | if denom == "sd" { 44 | regDenom = " SD" 45 | } 46 | 47 | if wei == nil { 48 | return "" 49 | } 50 | 51 | if wei.Cmp(big.NewInt(Threshold)) < 0 && wei.Cmp(big.NewInt(0)) != 0 { 52 | return strconv.FormatFloat(WeiToGwei(wei), 'f', 6, 64) + gweiDenom 53 | } 54 | 55 | return strconv.FormatFloat(WeiToEth(wei), 'f', 6, 64) + regDenom 56 | } 57 | 58 | // Convert wei to eth 59 | func WeiToEth(wei *big.Int) float64 { 60 | var weiFloat big.Float 61 | var eth big.Float 62 | weiFloat.SetInt(wei) 63 | eth.Quo(&weiFloat, big.NewFloat(WeiPerEth)) 64 | eth64, _ := eth.Float64() 65 | return eth64 66 | } 67 | 68 | // Convert eth to wei 69 | func EthToWei(eth float64) *big.Int { 70 | var ethFloat big.Float 71 | var weiFloat big.Float 72 | var wei big.Int 73 | ethFloat.SetString(strconv.FormatFloat(eth, 'f', -1, 64)) 74 | weiFloat.Mul(ðFloat, big.NewFloat(WeiPerEth)) 75 | weiFloat.Int(&wei) 76 | return &wei 77 | } 78 | 79 | // Convert wei to gigawei 80 | func WeiToGwei(wei *big.Int) float64 { 81 | var weiFloat big.Float 82 | var gwei big.Float 83 | weiFloat.SetInt(wei) 84 | gwei.Quo(&weiFloat, big.NewFloat(WeiPerGwei)) 85 | gwei64, _ := gwei.Float64() 86 | return gwei64 87 | } 88 | 89 | // Convert gigawei to wei 90 | func GweiToWei(gwei float64) *big.Int { 91 | var gweiFloat big.Float 92 | var weiFloat big.Float 93 | var wei big.Int 94 | gweiFloat.SetString(strconv.FormatFloat(gwei, 'f', -1, 64)) 95 | weiFloat.Mul(&gweiFloat, big.NewFloat(WeiPerGwei)) 96 | weiFloat.Int(&wei) 97 | return &wei 98 | } 99 | -------------------------------------------------------------------------------- /stader-lib/utils/json/json.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package json 21 | 22 | import ( 23 | "encoding/json" 24 | "fmt" 25 | ) 26 | 27 | func Marshal(v interface{}) ([]byte, error) { 28 | return json.Marshal(v) 29 | } 30 | 31 | func Unmarshal(data []byte, v interface{}) error { 32 | err := json.Unmarshal(data, v) 33 | if err != nil { 34 | return fmt.Errorf("%w\nUnable to Unmarshal JSON string %s", err, string(data)) 35 | } 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /stader-lib/utils/sd/sd.go: -------------------------------------------------------------------------------- 1 | package sd 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "strconv" 7 | 8 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 9 | "github.com/stader-labs/stader-node/stader-lib/utils/eth" 10 | ) 11 | 12 | const ( 13 | SDFloatStringEqualityThreshold = 0.1 14 | ) 15 | 16 | var SDWeiEqualityThreshold = eth.EthToWei(SDFloatStringEqualityThreshold) 17 | 18 | func WeiAlmostEqual(lhs, rhs *big.Int) bool { 19 | diversity := new(big.Int).Sub(lhs, rhs) 20 | 21 | return diversity.CmpAbs(SDWeiEqualityThreshold) <= 0 22 | } 23 | 24 | func PromptChooseSDWithMaxMin(msg, errMsg string, min, max *big.Int) (*big.Int, error) { 25 | var utilityAmountWei *big.Int 26 | 27 | var errParse error 28 | 29 | for { 30 | s := cliutils.Prompt( 31 | msg, 32 | `^[0-9]\d*(\.\d+)?$`, 33 | errMsg) 34 | 35 | var utilityAmountFloat float64 36 | utilityAmountFloat, errParse = strconv.ParseFloat(s, 64) 37 | 38 | if errParse != nil { 39 | fmt.Println(errMsg) 40 | continue 41 | } 42 | 43 | utilityAmountWei = eth.EthToWei(utilityAmountFloat) 44 | 45 | if utilityAmountWei.Cmp(min) < 0 || utilityAmountWei.Cmp(max) > 0 || utilityAmountWei.Cmp(big.NewInt(0)) == 0 { 46 | fmt.Println(errMsg) 47 | continue 48 | } 49 | 50 | break 51 | } 52 | 53 | return utilityAmountWei, errParse 54 | } 55 | -------------------------------------------------------------------------------- /stader-lib/utils/wait.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package utils 21 | 22 | import ( 23 | "context" 24 | "errors" 25 | "fmt" 26 | "time" 27 | 28 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 29 | "github.com/ethereum/go-ethereum/common" 30 | "github.com/ethereum/go-ethereum/core/types" 31 | "github.com/stader-labs/stader-node/stader-lib/stader" 32 | ) 33 | 34 | // Wait for a transaction to get mined 35 | func WaitForTransaction(client stader.ExecutionClient, hash common.Hash) (*types.Receipt, error) { 36 | 37 | var tx *types.Transaction 38 | var err error 39 | 40 | // Get the transaction from its hash, retrying for 30 sec if it wasn't found 41 | for i := 0; i < 30; i++ { 42 | if i == 29 { 43 | return nil, fmt.Errorf("Transaction not found after 30 seconds.") 44 | } 45 | 46 | tx, _, err = client.TransactionByHash(context.Background(), hash) 47 | if err != nil { 48 | if err.Error() == "not found" { 49 | time.Sleep(1 * time.Second) 50 | continue 51 | } 52 | return nil, err 53 | } else { 54 | break 55 | } 56 | } 57 | 58 | // Wait for transaction to be mined 59 | txReceipt, err := bind.WaitMined(context.Background(), client, tx) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | // Check transaction status 65 | if txReceipt.Status == 0 { 66 | return txReceipt, errors.New("Transaction failed with status 0") 67 | } 68 | 69 | // Return 70 | return txReceipt, nil 71 | } 72 | -------------------------------------------------------------------------------- /stader/api/node/get-contracts-info.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/urfave/cli" 7 | 8 | "github.com/stader-labs/stader-node/shared/services" 9 | "github.com/stader-labs/stader-node/shared/types/api" 10 | ) 11 | 12 | func getContractsInfo(c *cli.Context) (*api.ContractsInfoResponse, error) { 13 | // Response 14 | response := api.ContractsInfoResponse{} 15 | 16 | // Get the ETH1 network ID 17 | config, err := services.GetConfig(c) 18 | if err != nil { 19 | return nil, fmt.Errorf("Error getting configuration: %w", err) 20 | } 21 | 22 | response.Network = uint64(config.StaderNode.GetChainID()) 23 | response.EncryptionKey = config.StaderNode.GetPresignEncryptionKey() 24 | 25 | // Get the Beacon Client info 26 | bc, err := services.GetBeaconClient(c) 27 | if err != nil { 28 | return nil, fmt.Errorf("Error getting beacon client: %w", err) 29 | } 30 | 31 | eth2DepositContract, err := bc.GetEth2DepositContract() 32 | if err != nil { 33 | return nil, fmt.Errorf("Error getting beacon client deposit contract: %w", err) 34 | } 35 | 36 | response.BeaconNetwork = eth2DepositContract.ChainID 37 | response.BeaconDepositContract = eth2DepositContract.Address 38 | 39 | response.SdCollateralContract, err = services.GetSdCollateralAddress(c) 40 | if err != nil { 41 | return nil, err 42 | } 43 | response.StaderConfig = config.StaderNode.GetStaderConfigAddress() 44 | 45 | response.EthxToken, err = services.GetEthxTokenAddress(c) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | response.SdToken, err = services.GetSdTokenAddress(c) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | response.PermissionlessNodeRegistry, err = services.GetPermissionlessNodeRegistryAddress(c) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | response.VaultFactory, err = services.GetVaultFactoryAddress(c) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | response.SocializingPoolContract, err = services.GetSocializingPoolAddress(c) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | response.PermisionlessPool, err = services.GetPermissionlessPoolAddress(c) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | response.StaderOracle, err = services.GetStaderOracleAddress(c) 76 | if err != nil { 77 | return nil, err 78 | } 79 | 80 | response.StakePoolManager, err = services.GetStakePoolManagerAddress(c) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | response.SdUtilityContract, err = services.GetSdUtilityAddress(c) 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | // Return response 91 | return &response, nil 92 | 93 | } 94 | -------------------------------------------------------------------------------- /stader/api/node/repay-sd.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/ethereum/go-ethereum/accounts/abi" 7 | "github.com/ethereum/go-ethereum/core/types" 8 | "github.com/stader-labs/stader-node/stader-lib/sdutility" 9 | "github.com/stader-labs/stader-node/stader-lib/stader" 10 | 11 | "github.com/urfave/cli" 12 | 13 | "github.com/stader-labs/stader-node/shared/services" 14 | "github.com/stader-labs/stader-node/shared/types/api" 15 | ) 16 | 17 | func canRepaySD(c *cli.Context, amountWei *big.Int) (*api.CanRepaySDResponse, error) { 18 | // Get services 19 | if err := services.RequireNodeWallet(c); err != nil { 20 | return nil, err 21 | } 22 | 23 | w, err := services.GetWallet(c) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | // Response 29 | response := api.CanRepaySDResponse{} 30 | 31 | sdu, err := services.GetSdUtilityContract(c) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | isAmountMaxUint256 := amountWei.Cmp(abi.MaxUint256) == 0 37 | 38 | // Get gas estimates 39 | opts, err := w.GetNodeAccountTransactor() 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | var gasInfo stader.GasInfo 45 | 46 | if isAmountMaxUint256 { 47 | gasInfo, err = sdutility.EstimateRepayFullAmount(sdu, opts) 48 | if err != nil { 49 | return nil, err 50 | } 51 | } else { 52 | gasInfo, err = sdutility.EstimateRepay(sdu, amountWei, opts) 53 | if err != nil { 54 | return nil, err 55 | } 56 | } 57 | 58 | response.GasInfo = gasInfo 59 | 60 | return &response, nil 61 | } 62 | 63 | func repaySD(c *cli.Context, amountWei *big.Int) (*api.NodeRepaySDResponse, error) { 64 | // Get services 65 | if err := services.RequireNodeWallet(c); err != nil { 66 | return nil, err 67 | } 68 | 69 | w, err := services.GetWallet(c) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | sdu, err := services.GetSdUtilityContract(c) 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | // Get gas estimates 80 | opts, err := w.GetNodeAccountTransactor() 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | isAmountMaxUint256 := amountWei.Cmp(abi.MaxUint256) == 0 86 | 87 | // Response 88 | response := api.NodeRepaySDResponse{} 89 | 90 | var tx *types.Transaction 91 | if isAmountMaxUint256 { 92 | tx, err = sdutility.RepayFullAmount(sdu, opts) 93 | if err != nil { 94 | return nil, err 95 | } 96 | } else { 97 | tx, err = sdutility.Repay(sdu, amountWei, opts) 98 | if err != nil { 99 | return nil, err 100 | } 101 | } 102 | 103 | response.TxHash = tx.Hash() 104 | 105 | return &response, nil 106 | } 107 | -------------------------------------------------------------------------------- /stader/api/node/sd-status.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/stader-labs/stader-node/stader-lib/node" 7 | sd_collateral "github.com/stader-labs/stader-node/stader-lib/sd-collateral" 8 | "github.com/stader-labs/stader-node/stader/api/validator" 9 | 10 | "github.com/urfave/cli" 11 | 12 | "github.com/stader-labs/stader-node/shared/services" 13 | "github.com/stader-labs/stader-node/shared/types/api" 14 | ) 15 | 16 | func getSDStatus(c *cli.Context, numValidators *big.Int) (*api.GetSdStatusResponse, error) { 17 | sdc, err := services.GetSdCollateralContract(c) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | sdt, err := services.GetSdTokenContract(c) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | sdu, err := services.GetSdUtilityContract(c) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | w, err := services.GetWallet(c) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | // Get node account 38 | nodeAccount, err := w.GetNodeAccount() 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | prn, err := services.GetPermissionlessNodeRegistry(c) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | operatorID, err := node.GetOperatorId(prn, nodeAccount.Address, nil) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | totalValidatorKeys, err := node.GetTotalValidatorKeys(prn, operatorID, nil) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | totalValidatorNonTerminalKeys, err := node.GetTotalNonTerminalValidatorKeys(prn, nodeAccount.Address, totalValidatorKeys, nil) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | numValidatorsPostAdd := new(big.Int).Add(numValidators, big.NewInt(int64(totalValidatorNonTerminalKeys))) 64 | 65 | sdStatus, err := validator.GetSDStatus(sdc, sdu, sdt, nodeAccount.Address, numValidatorsPostAdd) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | hasEnoughSdCollateral, err := sd_collateral.HasEnoughSdCollateral(sdc, nodeAccount.Address, 1, numValidatorsPostAdd, nil) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | sdStatus.NotEnoughSdCollateral = !hasEnoughSdCollateral 76 | 77 | return &api.GetSdStatusResponse{ 78 | SDStatus: sdStatus, 79 | }, nil 80 | } 81 | -------------------------------------------------------------------------------- /stader/api/node/sign-message.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package node 21 | 22 | import ( 23 | "encoding/hex" 24 | "fmt" 25 | _ "time/tzdata" 26 | 27 | "github.com/urfave/cli" 28 | 29 | "github.com/stader-labs/stader-node/shared/services" 30 | "github.com/stader-labs/stader-node/shared/types/api" 31 | hexutils "github.com/stader-labs/stader-node/shared/utils/hex" 32 | ) 33 | 34 | func signMessage(c *cli.Context, message string) (*api.NodeSignResponse, error) { 35 | // Get services 36 | w, err := services.GetWallet(c) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | // Response 42 | response := api.NodeSignResponse{} 43 | signedBytes, err := w.SignMessage(message) 44 | if err != nil { 45 | return nil, fmt.Errorf("Error signing message [%s]: %w", message, err) 46 | } 47 | response.SignedData = hexutils.AddPrefix(hex.EncodeToString(signedBytes)) 48 | 49 | // Return response 50 | return &response, nil 51 | 52 | } 53 | -------------------------------------------------------------------------------- /stader/api/node/sign.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package node 21 | 22 | import ( 23 | "encoding/hex" 24 | "fmt" 25 | _ "time/tzdata" 26 | 27 | "github.com/urfave/cli" 28 | 29 | "github.com/stader-labs/stader-node/shared/services" 30 | "github.com/stader-labs/stader-node/shared/types/api" 31 | hexutils "github.com/stader-labs/stader-node/shared/utils/hex" 32 | ) 33 | 34 | func sign(c *cli.Context, serializedTx string) (*api.NodeSignResponse, error) { 35 | 36 | // Get services 37 | if err := services.RequireNodeRegistered(c); err != nil { 38 | return nil, err 39 | } 40 | w, err := services.GetWallet(c) 41 | if err != nil { 42 | return nil, err 43 | } 44 | // Response 45 | response := api.NodeSignResponse{} 46 | 47 | serializedTx = hexutils.RemovePrefix(serializedTx) 48 | bytes, err := hex.DecodeString(serializedTx) 49 | if err != nil { 50 | return nil, fmt.Errorf("Error parsing TX bytes [%s]: %w", serializedTx, err) 51 | } 52 | 53 | signedBytes, err := w.Sign(bytes) 54 | if err != nil { 55 | return nil, fmt.Errorf("Error signing TX [%s]: %w", serializedTx, err) 56 | } 57 | response.SignedData = hexutils.AddPrefix(hex.EncodeToString(signedBytes)) 58 | 59 | // Return response 60 | return &response, nil 61 | 62 | } 63 | -------------------------------------------------------------------------------- /stader/api/node/sync.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package node 21 | 22 | import ( 23 | "github.com/urfave/cli" 24 | 25 | "github.com/stader-labs/stader-node/shared/services" 26 | "github.com/stader-labs/stader-node/shared/types/api" 27 | ) 28 | 29 | func getSyncProgress(c *cli.Context) (*api.NodeSyncProgressResponse, error) { 30 | 31 | // Response 32 | response := api.NodeSyncProgressResponse{} 33 | 34 | cfg, err := services.GetConfig(c) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | // Get the EC manager 40 | ecMgr, err := services.GetEthClient(c) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | // Get the status of the EC and fallback EC 46 | ecStatus := ecMgr.CheckStatus(cfg) 47 | response.EcStatus = *ecStatus 48 | 49 | // Get the BC manager 50 | bcMgr, err := services.GetBeaconClient(c) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | // Get the status of the BC and fallback BC 56 | bcStatus := bcMgr.CheckStatus() 57 | response.BcStatus = *bcStatus 58 | 59 | // Return response 60 | return &response, nil 61 | 62 | } 63 | -------------------------------------------------------------------------------- /stader/api/node/utility-sd.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/stader-labs/stader-node/stader-lib/node" 7 | "github.com/urfave/cli" 8 | 9 | "github.com/stader-labs/stader-node/shared/services" 10 | "github.com/stader-labs/stader-node/shared/types/api" 11 | "github.com/stader-labs/stader-node/stader-lib/sdutility" 12 | ) 13 | 14 | func canUtilitySd(c *cli.Context, amountWei *big.Int) (*api.CanUtilitySDResponse, error) { 15 | if err := services.RequireNodeWallet(c); err != nil { 16 | return nil, err 17 | } 18 | 19 | w, err := services.GetWallet(c) 20 | if err != nil { 21 | return nil, err 22 | } 23 | 24 | nodeAccount, err := w.GetNodeAccount() 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | prn, err := services.GetPermissionlessNodeRegistry(c) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | // Response 35 | response := api.CanUtilitySDResponse{} 36 | 37 | sdu, err := services.GetSdUtilityContract(c) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | operatorID, err := node.GetOperatorId(prn, nodeAccount.Address, nil) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | totalValidatorKeys, err := node.GetTotalValidatorKeys(prn, operatorID, nil) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | totalValidatorNonTerminalKeys, err := node.GetTotalNonTerminalValidatorKeys(prn, nodeAccount.Address, totalValidatorKeys, nil) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | response.NonTerminalValidators = totalValidatorNonTerminalKeys 58 | 59 | // Get gas estimates 60 | opts, err := w.GetNodeAccountTransactor() 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | gasInfo, err := sdutility.EstimateUtilize(sdu, amountWei, opts) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | response.GasInfo = gasInfo 71 | 72 | return &response, nil 73 | } 74 | 75 | func utilitySd(c *cli.Context, amountWei *big.Int) (*api.NodeUtilitySDResponse, error) { 76 | // Get services 77 | if err := services.RequireNodeWallet(c); err != nil { 78 | return nil, err 79 | } 80 | 81 | w, err := services.GetWallet(c) 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | sdu, err := services.GetSdUtilityContract(c) 87 | if err != nil { 88 | return nil, err 89 | } 90 | 91 | // Get gas estimates 92 | opts, err := w.GetNodeAccountTransactor() 93 | if err != nil { 94 | return nil, err 95 | } 96 | 97 | // Response 98 | response := api.NodeUtilitySDResponse{} 99 | 100 | tx, err := sdutility.Utilize(sdu, amountWei, opts) 101 | if err != nil { 102 | return nil, err 103 | } 104 | 105 | response.TxHash = tx.Hash() 106 | 107 | return &response, nil 108 | } 109 | -------------------------------------------------------------------------------- /stader/api/service/commands.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package service 21 | 22 | import ( 23 | "github.com/urfave/cli" 24 | 25 | "github.com/stader-labs/stader-node/shared/utils/api" 26 | cliutils "github.com/stader-labs/stader-node/shared/utils/cli" 27 | ) 28 | 29 | // Register subcommands 30 | func RegisterSubcommands(command *cli.Command, name string, aliases []string) { 31 | command.Subcommands = append(command.Subcommands, cli.Command{ 32 | Name: name, 33 | Aliases: aliases, 34 | Usage: "Manage the deposit queue", 35 | Subcommands: []cli.Command{ 36 | { 37 | Name: "terminate-data-folder", 38 | Aliases: []string{"t"}, 39 | Usage: "Deletes the data folder including the wallet file, password file, and all validator keys - don't use this unless you have a very good reason to do it (such as switching from Prater to Mainnet)", 40 | UsageText: "stader-cli api service terminate-data-folder", 41 | Action: func(c *cli.Context) error { 42 | 43 | // Validate args 44 | if err := cliutils.ValidateArgCount(c, 0); err != nil { 45 | return err 46 | } 47 | 48 | // Run 49 | api.PrintResponse(terminateDataFolder(c)) 50 | return nil 51 | 52 | }, 53 | }, 54 | 55 | { 56 | Name: "get-client-status", 57 | Aliases: []string{"g"}, 58 | Usage: "Gets the status of the configured Execution and Beacon clients", 59 | UsageText: "stader-cli api service get-client-status", 60 | Action: func(c *cli.Context) error { 61 | 62 | // Validate args 63 | if err := cliutils.ValidateArgCount(c, 0); err != nil { 64 | return err 65 | } 66 | 67 | // Run 68 | api.PrintResponse(getClientStatus(c)) 69 | return nil 70 | 71 | }, 72 | }, 73 | }, 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /stader/api/service/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package service 21 | 22 | import ( 23 | "github.com/urfave/cli" 24 | 25 | "github.com/stader-labs/stader-node/shared/services" 26 | "github.com/stader-labs/stader-node/shared/types/api" 27 | ) 28 | 29 | // Gets the status of the configured Execution clients 30 | func getClientStatus(c *cli.Context) (*api.ClientStatusResponse, error) { 31 | 32 | // Get services 33 | ec, err := services.GetEthClient(c) 34 | if err != nil { 35 | return nil, err 36 | } 37 | bc, err := services.GetBeaconClient(c) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | cfg, err := services.GetConfig(c) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | // Response 48 | response := api.ClientStatusResponse{} 49 | 50 | // Get the EC manager status 51 | ecMgrStatus := ec.CheckStatus(cfg) 52 | response.EcManagerStatus = *ecMgrStatus 53 | 54 | // Get the BC manager status 55 | bcMgrStatus := bc.CheckStatus() 56 | response.BcManagerStatus = *bcMgrStatus 57 | 58 | // Return response 59 | return &response, nil 60 | 61 | } 62 | -------------------------------------------------------------------------------- /stader/api/wallet/export.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "encoding/hex" 24 | 25 | "github.com/urfave/cli" 26 | 27 | "github.com/stader-labs/stader-node/shared/services" 28 | "github.com/stader-labs/stader-node/shared/types/api" 29 | ) 30 | 31 | func exportWallet(c *cli.Context) (*api.ExportWalletResponse, error) { 32 | 33 | // Get services 34 | if err := services.RequireNodeWallet(c); err != nil { 35 | return nil, err 36 | } 37 | pm, err := services.GetPasswordManager(c) 38 | if err != nil { 39 | return nil, err 40 | } 41 | w, err := services.GetWallet(c) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | // Response 47 | response := api.ExportWalletResponse{} 48 | 49 | // Get password 50 | password, err := pm.GetPassword() 51 | if err != nil { 52 | return nil, err 53 | } 54 | response.Password = password 55 | 56 | // Serialize wallet 57 | wallet, err := w.String() 58 | if err != nil { 59 | return nil, err 60 | } 61 | response.Wallet = wallet 62 | 63 | // Get account private key 64 | privateKey, err := w.GetNodePrivateKeyBytes() 65 | if err != nil { 66 | return nil, err 67 | } 68 | response.AccountPrivateKey = hex.EncodeToString(privateKey) 69 | 70 | // Return response 71 | return &response, nil 72 | 73 | } 74 | -------------------------------------------------------------------------------- /stader/api/wallet/init.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "errors" 24 | 25 | "github.com/urfave/cli" 26 | 27 | "github.com/stader-labs/stader-node/shared/services" 28 | "github.com/stader-labs/stader-node/shared/services/wallet" 29 | "github.com/stader-labs/stader-node/shared/types/api" 30 | ) 31 | 32 | func initWallet(c *cli.Context) (*api.InitWalletResponse, error) { 33 | 34 | // Get services 35 | if err := services.RequireNodePassword(c); err != nil { 36 | return nil, err 37 | } 38 | w, err := services.GetWallet(c) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | // Response 44 | response := api.InitWalletResponse{} 45 | 46 | // Check if wallet is already initialized 47 | if w.IsInitialized() { 48 | return nil, errors.New("The wallet is already initialized") 49 | } 50 | 51 | // Get the derivation path 52 | path := c.String("derivation-path") 53 | switch path { 54 | case "": 55 | path = wallet.DefaultNodeKeyPath 56 | case "ledgerLive": 57 | path = wallet.LedgerLiveNodeKeyPath 58 | case "mew": 59 | path = wallet.MyEtherWalletNodeKeyPath 60 | } 61 | 62 | // Initialize wallet but don't save it 63 | mnemonic, err := w.Initialize(path, 0) 64 | if err != nil { 65 | return nil, err 66 | } 67 | response.Mnemonic = mnemonic 68 | 69 | // Get node account 70 | nodeAccount, err := w.GetNodeAccount() 71 | if err != nil { 72 | return nil, err 73 | } 74 | response.AccountAddress = nodeAccount.Address 75 | 76 | // Return response 77 | return &response, nil 78 | 79 | } 80 | -------------------------------------------------------------------------------- /stader/api/wallet/purge.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "fmt" 24 | 25 | "github.com/stader-labs/stader-node/shared/services" 26 | "github.com/stader-labs/stader-node/shared/types/api" 27 | "github.com/stader-labs/stader-node/shared/utils/validator" 28 | "github.com/urfave/cli" 29 | ) 30 | 31 | func purge(c *cli.Context) (*api.PurgeResponse, error) { 32 | 33 | cfg, err := services.GetConfig(c) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | w, err := services.GetWallet(c) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | pm, err := services.GetPasswordManager(c) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | bc, err := services.GetBeaconClient(c) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | d, err := services.GetDocker(c) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | response := api.PurgeResponse{} 59 | 60 | // Stop the VC to unlock keystores and slashing DBs 61 | err = validator.StopValidator(cfg, bc, nil, d) 62 | if err != nil { 63 | return nil, fmt.Errorf("error stopping validator client: %w", err) 64 | } 65 | 66 | // Delete the VC directories 67 | err = w.DeleteValidatorStores() 68 | if err != nil { 69 | return nil, fmt.Errorf("error deleting validator storage: %w", err) 70 | } 71 | 72 | // Delete the wallet and password 73 | err = w.Delete() 74 | if err != nil { 75 | return nil, fmt.Errorf("error deleting wallet: %w", err) 76 | } 77 | err = pm.DeletePassword() 78 | if err != nil { 79 | return nil, fmt.Errorf("error deleting password: %w", err) 80 | } 81 | 82 | // Restart the VC once cleanup is done 83 | err = validator.RestartValidator(cfg, bc, nil, d) 84 | if err != nil { 85 | return nil, fmt.Errorf("error restarting validator client: %w", err) 86 | } 87 | 88 | return &response, nil 89 | } 90 | -------------------------------------------------------------------------------- /stader/api/wallet/set-password.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "errors" 24 | 25 | "github.com/urfave/cli" 26 | 27 | "github.com/stader-labs/stader-node/shared/services" 28 | "github.com/stader-labs/stader-node/shared/types/api" 29 | ) 30 | 31 | func setPassword(c *cli.Context, password string) (*api.SetPasswordResponse, error) { 32 | 33 | // Get services 34 | pm, err := services.GetPasswordManager(c) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | // Response 40 | response := api.SetPasswordResponse{} 41 | 42 | // Check if password is already set 43 | if pm.IsPasswordSet() { 44 | return nil, errors.New("The node password is already set") 45 | } 46 | 47 | // Set password 48 | if err := pm.SetPassword(password); err != nil { 49 | return nil, err 50 | } 51 | 52 | // Return response 53 | return &response, nil 54 | 55 | } 56 | -------------------------------------------------------------------------------- /stader/api/wallet/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | This work is licensed and released under GNU GPL v3 or any other later versions. 3 | The full text of the license is below/ found at 4 | 5 | (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | package wallet 21 | 22 | import ( 23 | "context" 24 | "math/big" 25 | 26 | "github.com/urfave/cli" 27 | 28 | "github.com/stader-labs/stader-node/shared/services" 29 | "github.com/stader-labs/stader-node/shared/types/api" 30 | ) 31 | 32 | func getStatus(c *cli.Context) (*api.WalletStatusResponse, error) { 33 | 34 | // Get services 35 | pm, err := services.GetPasswordManager(c) 36 | if err != nil { 37 | return nil, err 38 | } 39 | w, err := services.GetWallet(c) 40 | if err != nil { 41 | return nil, err 42 | } 43 | ec, err := services.GetEthClient(c) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | // Response 49 | response := api.WalletStatusResponse{} 50 | 51 | // Get wallet status 52 | response.PasswordSet = pm.IsPasswordSet() 53 | response.WalletInitialized = w.IsInitialized() 54 | 55 | // Get accounts if initialized 56 | if response.WalletInitialized { 57 | 58 | // Get node account 59 | nodeAccount, err := w.GetNodeAccount() 60 | if err != nil { 61 | return nil, err 62 | } 63 | response.AccountAddress = nodeAccount.Address 64 | 65 | currentBlockNumber, err := ec.BlockNumber(context.Background()) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | currentNonce, err := ec.NonceAt(context.Background(), nodeAccount.Address, big.NewInt(int64(currentBlockNumber))) 71 | if err != nil { 72 | return nil, err 73 | } 74 | pendingNonce, err := ec.PendingNonceAt(context.Background(), nodeAccount.Address) 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | response.PendingNonce = big.NewInt(int64(pendingNonce)) 80 | response.CurrentNonce = big.NewInt(int64(currentNonce)) 81 | } 82 | 83 | // Return response 84 | return &response, nil 85 | 86 | } 87 | -------------------------------------------------------------------------------- /stader/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | export CGO_ENABLED=1 22 | cd /stader-node/stader 23 | 24 | # 25 | ## Build x64 version 26 | CGO_CFLAGS="-O -D__BLST_PORTABLE__" GOARCH=amd64 GOOS=linux go build -o stader-daemon-linux-amd64 stader.go 27 | # 28 | ## Build the arm64 version 29 | CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-cpp CGO_CFLAGS="-O -D__BLST_PORTABLE__" GOARCH=arm64 GOOS=linux go build -o stader-daemon-linux-arm64 stader.go -------------------------------------------------------------------------------- /stader/ec_migrate multi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | 22 | EC_CHAINDATA_DIR=/ethclient 23 | EXTERNAL_DIR=/mnt/external 24 | 25 | # Get the core count 26 | CORE_COUNT=$(grep -c ^processor /proc/cpuinfo) 27 | if [ -z "$CORE_COUNT" ]; then 28 | CORE_COUNT=1 29 | elif [ "$CORE_COUNT" -lt 1 ]; then 30 | CORE_COUNT=1 31 | fi 32 | 33 | RSYNC_CMD="xargs -n1 -P${CORE_COUNT} -I% rsync -a --progress %" 34 | 35 | if [ "$EC_MIGRATE_MODE" = "export" ]; then 36 | ls $EC_CHAINDATA_DIR/* | $RSYNC_CMD $EXTERNAL_DIR 37 | elif [ "$EC_MIGRATE_MODE" = "import" ]; then 38 | rm -rf $EC_CHAINDATA_DIR/* 39 | ls $EXTERNAL_DIR/* | $RSYNC_CMD $EC_CHAINDATA_DIR 40 | else 41 | echo "Unknown migrate mode \"$EC_MIGRATE_MODE\"" 42 | fi -------------------------------------------------------------------------------- /stader/ec_migrate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | EC_CHAINDATA_DIR=/ethclient 22 | EXTERNAL_DIR=/mnt/external 23 | 24 | if [ "$OPERATION" = "size" ]; then 25 | 26 | if [ ! -d $EXTERNAL_DIR ]; then 27 | echo "Source path is not a directory." 1>&2 28 | exit 1 29 | else 30 | # Get the space used by the external directory 31 | DIR_SIZE=$(du -s -k $EXTERNAL_DIR | awk -F '\\s*' '{print $1}') 32 | if [ ! -z "$DIR_SIZE" ]; then 33 | # The size will be in KB because of Busybox, so turn it into bytes 34 | expr $DIR_SIZE \* 1024 35 | else 36 | echo "Failed to get source directory size." 1>&2 37 | exit 2 38 | fi 39 | fi 40 | 41 | else 42 | 43 | RSYNC_CMD="rsync -a --progress" 44 | 45 | if [ "$EC_MIGRATE_MODE" = "export" ]; then 46 | $RSYNC_CMD $EC_CHAINDATA_DIR/* $EXTERNAL_DIR 47 | elif [ "$EC_MIGRATE_MODE" = "import" ]; then 48 | rm -rf $EC_CHAINDATA_DIR/* 49 | $RSYNC_CMD $EXTERNAL_DIR/* $EC_CHAINDATA_DIR 50 | else 51 | echo "Unknown migrate mode \"$EC_MIGRATE_MODE\"" 52 | fi 53 | 54 | fi -------------------------------------------------------------------------------- /stader/guardian/collector/constants.go: -------------------------------------------------------------------------------- 1 | package collector 2 | 3 | const namespace = "stader" 4 | 5 | // Validator rewards & performance => stader_validator_rewards_performance + key 6 | const OperatorSub = "operator" 7 | 8 | const ActiveValidators = "active_validators" //GetAllActiveValidators _PermissionlessNodeRegistry 9 | const BeaconChainQueuedValidators = "beacon_chain_queued_validators" //BeaconChainQueuedValidators _PermissionlessNodeRegistry 10 | const StaderQueuedValidators = "stader_queued_validators" 11 | const SlashedValidators = "slashed_validators" //GetValidatorStatus 12 | const ExitingValidators = "exiting_validators" //GetValidatorStatus 13 | const WithdrawnValidators = "withdrawn_validators" //GetValidatorStatus 14 | const InitializedValidators = "initialized_validators" //GetValidatorStatus 15 | const InvalidSignatureValidators = "invalid_signature_validators" //GetValidatorStatus 16 | const FrontRunValidators = "front_run_validators" //GetValidatorStatus 17 | const FundsSettledValidators = "funds_settled_validators" //GetValidatorStatus 18 | 19 | const TotalETHBonded = "total_eth_bonded" 20 | const TotalSDBonded = "total_sd_bonded" 21 | const SdCollateral = "sd_collateral" 22 | const SdCollateralInEth = "sd_collateral_in_eth" 23 | const EthCollateral = "eth_collateral" 24 | const CumulativePenalty = "cumulative_penalty" 25 | const ClaimedSocializingPoolELRewards = "claimed_socializing_pool_el_rewards" 26 | const ClaimedSocializingPoolSDrewards = "claimed_socializing_pool_sd_rewards" 27 | const UnclaimedNonSocializingPoolELRewards = "unclaimed_non_socializing_pool_el_rewards" 28 | const UnclaimedSocializingPoolELRewards = "unclaimed_socializing_pool_el_rewards" 29 | const UnclaimedSocializingPoolSdRewards = "unclaimed_socializing_pool_sd_rewards" 30 | const UnclaimedCLRewards = "unclaimed_cl_rewards" 31 | const NextRewardCycleTime = "next_reward_cycle_time" 32 | const SDUtilized = "sd_utilized" 33 | const SDUtilizedInterest = "sd_utilized_interest" 34 | const SdCollateralPct = "sd_collateral_pct" 35 | const LockedEth = "eth_locked" 36 | const HeathFactor = "heath_factor" 37 | const TotalSDUtilizationPosition = "sd_utility_position" 38 | const TotalSDSelfBonded = "total_sd_self_bonded" 39 | const LiquidationStatus = "liquidation_status" 40 | const ClaimVaultBalance = "claim_vault_balance" 41 | 42 | // Node Health => stader_node_health+ key 43 | const NodeSub = "node_health" 44 | const CPUUsage = "cpu_usage" 45 | const CPUUsageTimeSeries = "cpu_usage_time_series" 46 | const RAMUsage = "ram_usage" 47 | const RAMUsageTimeSeries = "ram_usage_time_series" 48 | const DiskSpaceUsed = "disk_space_used" 49 | const SSDLatency = "ssd_latency" 50 | const TotalIO = "total_io" 51 | const IOWaiTTime = "io_wait_time" 52 | const NetworkUsage = "network_usage" 53 | const NetworkLatency = "network_latency" 54 | const ECPeers = "ec_peers" 55 | const NBCPeers = "nbc_peers" 56 | -------------------------------------------------------------------------------- /stader/node/merkle-proofs-download.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/mitchellh/go-homedir" 7 | "github.com/stader-labs/stader-node/shared/services" 8 | "github.com/stader-labs/stader-node/shared/services/config" 9 | "github.com/stader-labs/stader-node/shared/services/wallet" 10 | "github.com/stader-labs/stader-node/shared/utils/log" 11 | "github.com/stader-labs/stader-node/shared/utils/stader" 12 | "github.com/urfave/cli" 13 | "os" 14 | ) 15 | 16 | type MerkleProofsDownloader struct { 17 | c *cli.Context 18 | log log.ColorLogger 19 | cfg *config.StaderConfig 20 | w *wallet.Wallet 21 | } 22 | 23 | func NewMerkleProofsDownloader(c *cli.Context, logger log.ColorLogger) (*MerkleProofsDownloader, error) { 24 | cfg, err := services.GetConfig(c) 25 | if err != nil { 26 | return nil, err 27 | } 28 | w, err := services.GetWallet(c) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | return &MerkleProofsDownloader{ 34 | c: c, 35 | log: logger, 36 | cfg: cfg, 37 | w: w, 38 | }, nil 39 | } 40 | 41 | func (m *MerkleProofsDownloader) run() error { 42 | // Wait for eth client to sync 43 | if err := services.WaitEthClientSynced(m.c, true); err != nil { 44 | return err 45 | } 46 | 47 | nodeAccount, err := m.w.GetNodeAccount() 48 | if err != nil { 49 | return err 50 | } 51 | 52 | allMerkleProofs, err := stader.GetAllMerkleProofsForOperator(m.c, nodeAccount.Address) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | downloadedCycles := []int64{} 58 | 59 | for _, cycleMerkleProof := range allMerkleProofs { 60 | cycleMerkleProofFile := m.cfg.StaderNode.GetSpRewardCyclePath(cycleMerkleProof.Cycle, true) 61 | absolutePathOfProofFile, err := homedir.Expand(cycleMerkleProofFile) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | _, err = os.Stat(cycleMerkleProofFile) 67 | if !os.IsNotExist(err) && err != nil { 68 | return err 69 | } 70 | if !os.IsNotExist(err) { 71 | m.log.Printlnf("Merkle proof for cycle %d already exists, skipping", cycleMerkleProof.Cycle) 72 | continue 73 | } 74 | 75 | m.log.Printlnf("Downloading merkle proof for cycle %d", cycleMerkleProof.Cycle) 76 | file, err := os.Create(absolutePathOfProofFile) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | encoder := json.NewEncoder(file) 82 | err = encoder.Encode(cycleMerkleProof) 83 | if err != nil { 84 | return fmt.Errorf("error encoding JSON: %v", err) 85 | } 86 | 87 | downloadedCycles = append(downloadedCycles, cycleMerkleProof.Cycle) 88 | } 89 | 90 | if len(downloadedCycles) == 0 { 91 | m.log.Printlnf("No merkle proofs to download") 92 | return nil 93 | } else { 94 | m.log.Printlnf("Downloaded merkle proofs for cycles: %v", downloadedCycles) 95 | } 96 | 97 | return nil 98 | } 99 | -------------------------------------------------------------------------------- /stader/prune_provision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This work is licensed and released under GNU GPL v3 or any other later versions. 4 | # The full text of the license is below/ found at 5 | 6 | # (c) 2023 Rocket Pool Pty Ltd. Modified under GNU GPL v3. [1.5.0] 7 | 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | touch /ethclient/prune.lock -------------------------------------------------------------------------------- /update-abis.sh: -------------------------------------------------------------------------------- 1 | # enter in stader-lib/contracts and throw and error if it fails 2 | echo "Updating ABIs..." 3 | 4 | cd ./stader-lib/contracts; 5 | 6 | abigen --abi ./../../abis/VaultFactory.abi.json --pkg contracts --type VaultFactory --out vault-factory.go; 7 | abigen --abi ./../../abis/ValidatorWithdrawVault.abi.json --pkg contracts --type ValidatorWithdrawVault --out validator-withdraw-vault.go; 8 | abigen --abi ./../../abis/StakePoolManager.abi.json --pkg contracts --type StakePoolManager --out stake-pool-manager.go; 9 | abigen --abi ./../../abis/StaderConfig.abi.json --pkg contracts --type StaderConfig --out stader-config.go; 10 | abigen --abi ./../../abis/SocializingPool.abi.json --pkg contracts --type SocializingPool --out socializing-pool.go; 11 | abigen --abi ./../../abis/PoolUtils.abi.json --pkg contracts --type PoolUtils --out pool-utils.go; 12 | abigen --abi ./../../abis/PermissionlessPool.abi.json --pkg contracts --type PermissionlessPool --out permissionless-pool.go; 13 | abigen --abi ./../../abis/PermissionlessNodeRegistry.abi.json --pkg contracts --type PermissionlessNodeRegistry --out permissionless-node-registry.go; 14 | abigen --abi ./../../abis/Penalty.abi.json --pkg contracts --type PenaltyTracker --out penalty.go; 15 | abigen --abi ./../../abis/NodeElRewardVault.abi.json --pkg contracts --type NodeElRewardVault --out node-el-reward-vault.go; 16 | abigen --abi ./../../abis/OperatorRewardsCollector.abi.json --pkg contracts --type OperatorRewardsCollector --out operator-rewards-collector.go; 17 | abigen --abi ./../../abis/SdCollateral.abi.json --pkg contracts --type SdCollateral --out sd-collateral.go; 18 | abigen --abi ./../../abis/SDUtilityPool.abi.json --pkg contracts --type SDUtilityPool --out sd-utility.go; 19 | 20 | cd ../..; 21 | 22 | echo "Done updating ABIs." --------------------------------------------------------------------------------