diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..afeb11a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @dappnode/package-mantainers diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..a765d82 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,42 @@ +--- +name: Bug report +about: Create a report to help us improve +title: +labels: +assignees: +--- + + + + +**Describe the bug** + + + +**To Reproduce** + + + +**Expected behavior** + + + +**Screenshots** + + + +**DAppNode version:** + + + +- Package version: +- OS: +- Browser + +**Additional context** + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..11bbebf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: "" +assignees: "" +--- + + + + +**Is your feature request related to a problem? Please describe.** + + + +**Describe the solution you'd like** + + + +**Describe alternatives you've considered** + + + +**Additional context** + + diff --git a/.github/workflows/auto_check.yml b/.github/workflows/auto_check.yml new file mode 100644 index 0000000..a3d75fa --- /dev/null +++ b/.github/workflows/auto_check.yml @@ -0,0 +1,19 @@ +name: Bump upstream version + +on: + schedule: + - cron: "00 */4 * * *" + push: + branches: + - "master" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npx @dappnode/dappnodesdk github-action bump-upstream + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PINATA_API_KEY: ${{ secrets.PINATA_API_KEY }} + PINATA_SECRET_API_KEY: ${{ secrets.PINATA_SECRET_API_KEY }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..cf36978 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,40 @@ +name: "Main" +on: + pull_request: + push: + branches: + - "main" + - "master" + - "v[0-9]+.[0-9]+.[0-9]+" + paths-ignore: + - "README.md" + +jobs: + build-test: + runs-on: ubuntu-latest + name: Build test + if: github.event_name != 'push' + steps: + - uses: actions/checkout@v4 + - run: npx @dappnode/dappnodesdk build --variant mainnet --skip_save + + # e2e-test: + # runs-on: mainnet + # needs: build-test + # if: github.event_name != 'push' + # name: End to end tests + # steps: + # - uses: actions/checkout@v4 + # - run: npx @dappnode/dappnodesdk@latest github-action test-end-to-end --errorLogsTimeout 120 --healthCheckUrl http://beacon-chain.prysm.dappnode:3500/eth/v1/beacon/genesis --network mainnet --environmentByService="{\"beacon-chain\":{\"CHECKPOINT_SYNC_URL\":\"https://checkpoint-sync.dappnode.io\"}}" + + release: + name: Release + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - uses: actions/checkout@v4 + - name: Publish + run: npx @dappnode/dappnodesdk publish patch --dappnode_team_preset --all-varians + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEVELOPER_ADDRESS: "0xf35960302a07022aba880dffaec2fdd64d5bf1c1" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4481d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# DNP artifacts +build_*/ +docker-compose-tmp.yml diff --git a/DISCLAIMER.md b/DISCLAIMER.md new file mode 100644 index 0000000..6cf38ce --- /dev/null +++ b/DISCLAIMER.md @@ -0,0 +1,147 @@ +## Terms of Use - DAppNode + +Effective as of Oct 14, 2020 + +By downloading, accessing or using this DAppNode Package ("DNP"), you (referenced herein as “you” or the “user”) certify that you have read and agreed to the terms and conditions below (the “Terms”) which form a binding contract between you and DAppNode Association (referenced herein as “we” or “us”). If you do not agree to the Terms, do not download or use DAppNode. + +### About DAppNode + +DAppNode is Free Open Source Software ("FOSS") aimed at facilitating the use of decentralized technologies. DAppNode is developed by the DAppNode Association, a voluntary association with the purpose of empowering users to participate in decentralized networks and to help such networks become more resilient by promoting the deployment of more nodes. +The modular structure of the DAppNode FOSS allows for the wrapping of 3rd party software with the intention of facilitating its deployment. In no way we are responsible for the misuse of such software and in no way we warrant its functionalities. We accept no responsibiity for its errors, or for the errors that the wrapping process might have introduced. Any usage of DAppNode and a DNP is strictly at your own risk. + +### About this DNP + +This software is experimental, presented 'as is' and inherently carries risks. By installing it, you acknowledge that DAppNode Association has done its best to mitigate these risks and accept to waive any liability or responsibility for DAppNode Association in case of any shortage, discrepancy, damage, loss or destruction of any digital asset managed within this DAppNode package. + +This package stores private keys. Neither DAppNode Association nor the developers of this software can have access to your private keys, nor help you recover it if you lose them. + +You are solely responsible for keeping your private keys and password safe and to perform secure backups, as well as to restrict access to your computer and other equipment. To the extent permitted by applicable law, you agree to be responsible for all activities that have been conducted from your account. You must take all necessary steps to ensure that your private key, password, and recovery phrase remain confidential and secured. + +This is experimental open source software released under an GPLv3 license and may contain errors and/or bugs. No guarantee or representations whatsoever is made regarding its suitability (or its use) for any purpose or regarding its compliance with any applicable laws and regulations. Use of the software is at your own risk and discretion and by using the software you acknowledge that you have read this disclaimer, understand its contents, assume all risk related thereto and hereby release, waive, discharge and covenant not to sue DAppNode Association or any officers, employees or affiliates from and for any direct or indirect liability resulting from the use of the software as permissible by applicable laws and regulations. + +### Licensing Terms + +DAppNode FOSS is a fully open-source software program licensed pursuant to the GNU General Public License v3.0. + +The DAppNode name, the term “DAppNode” and all related names, logos, product and service names, designs and slogans are trademarks of DAppNode Association or its affiliates and/or licensors. You must not use such marks without our prior written permission. + +### Risks of Operating DAppNode + +The use of DAppNode and the 3rd party software included within its different DNPs can lead to loss of money. Blockchain technologies and in particular Ethereum are still experimental systems and ETH and other cryptocurrencies remain a risky investment. You alone are responsible for your actions on DAppNode including the security of your ETH and meeting any applicable minimum system requirements. + +Furthermore the Wider Crypto Industry including Ethereum is still nascesnt in most respects: Technologically it remains experimental and as such laws and regulations surrounding the industry are still developing, many of which contrast dramatically with the ideological values of much of the Ethereum community mainly related to censorhip. + +Use the 3rd party software included within its different DNPs might be subject to Terms and Conditions of the 3rd party. DAppNode association has done its best to include such Terms and Conditions, however we do not warrant the accuracy, completeness or usefulness of the 3rd party Terms and Conditions. Any reliance you place on such information is strictly at your own risk. We recommend consulting with the 3rd party responsible for the software for its most updated Terms and Conditions. + +We make no claims that DAppNode is appropriate or permitted for use in any specific jurisdiction. Access to DAppNode may not be legal by certain persons or in certain jurisdictions or countries. If you access DAppNode, you do so on your own initiative and are responsible for compliance with local laws. + +Some Internet plans will charge an additional amount for any excess upload bandwidth used that isn’t included in the plan and may terminate your connection without warning because of overuse. We advise that you check whether your Internet connection is subjected to such limitations and monitor your bandwidth use so that you can stop DAppNode before you reach your bandwidth limit. + +### OFAC + MEV-Boost + +One of the most contentious issues in Ethereum at the moment is related to a new technology known as Proposer-Builder Separation (PBS). So far, the primary implementation of this protocol is highly centralized to a single program called MEV-Boost, which is developed by Flashbots. This technology is designed to try to increase rewards for block proposers by finding the (MEV) Maximal Extractable Value. It is the profit a block proposer (miner or validator) can make through their ability to arbitrarily include, exclude, or re-order transactions from the blocks they propose. MEV-Boost accomplishes this by outsourcing the block building/transaction bundling duties of the validator to an external specialized builder running a builder relay(s). There are many builder relays availible from several different sources. The main differences between builder relays are primarily how they bundle these transactions, however the more important difference is whether or not the relay censors any transactions, by not includidng them in the block, regardless of the fee or tip the transaction is paying to be included in the block. This censorship is a legal and regulatory quandary that goes against the very ideological nature of Ethereum as a censorship resistent, free, open, and permissionless financial ecosystem. + +The censorship at the crux of this quandary is related to the Office of Foreign Asset Control (OFAC) which is one of the enforcement arms of the United States Treasury Department. OFAC has wide authority over financial transactions and is charged with monitoring and enforcing US financial sanctions against certain countries, organizations, and individuals. Penalties are strong for OFAC violations and the reach of OFAC extends far beyond US borders; according to OFAC's October 2021 "Sanctions Compliance Guidance for the Virtual Currency Industry", when asked "Who Must Comply with OFAC Sanctions?" the response is as follows: "All U.S. persons are required to comply with OFAC regulations. This includes all U.S. citizens and lawful permanent residents, +wherever located; all individuals and entities within the United States; and all entities organized under the laws of the United States or +any jurisdiction within the United States, including any foreign branches of those entities. Accordingly, anyone engaging in virtual currency +activities in the United States, or that involve U.S. individuals or entities, should be aware of OFAC sanctions requirements and the +circumstances in which they must comply with those requirements. +Depending on the authorities governing each sanctions program, others may also be required to adhere to OFAC sanctions requirements. +For example, OFAC’s Cuba, Iran, and North Korea sanctions programs extend sanctions prohibitions to certain foreign entities owned or +controlled by U.S. persons or U.S. financial institutions. Certain activities by non-U.S. persons that involve the United States, U.S. persons, +or goods or services exported from the United States may also be subject to OFAC sanctions regulations. +Additionally, in most sanctions programs, any transaction that causes a violation — including a transaction by a non-U.S. person that causes +a U.S. person to violate sanctions — is also prohibited. For certain sanctions programs, U.S. persons, wherever located, also are prohibited +from facilitating actions on behalf of non-U.S. persons if the activity would be prohibited by sanctions regulations if directly performed by a +U.S. person or within the United States. +**Strict Liability Regulations** +OFAC may impose civil penalties for sanctions violations generally based on a strict liability legal standard. This means that, in many cases, +a U.S. person may be held civilly liable for sanctions violations even without having knowledge or reason to know it was engaging in such +a violation. As a general matter, however, OFAC takes into consideration the totality of facts and circumstances surrounding an apparent +violation to determine the appropriate enforcement response. " + +As such, relay providers offer: + - Non-Compliant: relays that attempt to maximize the fees paid to the block proposer by using every possible strategy, including not filtering or censoring any transactions, even those that may be destined to or coming from an address that has been blacklisted by OFAC. + - Compliant: relays that attempt to maximize fees paid to the block proposor, but filter out and censor any transactions destined to or coming from an OFAC blacklisted address. + +Your use of DAppNode is subject to all applicable laws of any governmental authority You are subject to, including, without limitation, federal, state and foreign securities laws, tax laws, tariff and trade laws, ordinances, judgments, decrees, injunctions, writs and orders or like actions of any governmental authority and rules, regulations, orders, interpretations, licenses, and permits of any federal, regional, state, county, municipal or other governmental authority and you agree to comply with all such laws in Your use of DAppNode. You are solely responsible for determining what rules and regulations apply to Your personal actions that may arise as the result of using MEV-Boost and/or any relays that do not comply with OFAC. The owners of, or contributors to, DAppNode are not responsible for any unnanounced changes to the availability or reliability of any relays, nor determining the rules and regulations that apply to cryptocurrency transactions users may propose using the DAppNode Platform. DAppNode does not explicitly endorse the use of MEV-Boost or any paricular relay in any way; it is Your responsibility to determine what laws apply to You and abide by them. DAppNode will not be held liable for any of your choices or actions as a result of using DAppNode. Continued use of DAppNode constitutes Your understanding and agreement with these updated terms. + +### Warranty Disclaimer + +DAPPNODE IS PROVIDED ON AN “AS-IS” BASIS AND MAY INCLUDE ERRORS, OMISSIONS, OR OTHER INACCURACIES. DAPPNODE ASSOCIATION AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT DAPNODDE FOR ANY PURPOSE, AND HEREBY EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT OR ANY OTHER IMPLIED WARRANTY UNDER THE UNIFORM COMPUTER INFORMATION TRANSACTIONS ACT AS ENACTED BY ANY STATE. WE ALSO MAKE NO REPRESENTATIONS OR WARRANTIES THAT DAPPNODE WILL OPERATE ERROR-FREE, UNINTERRUPTED, OR IN A MANNER THAT WILL MEET YOUR REQUIREMENTS AND/OR NEEDS. THEREFORE, YOU ASSUME THE ENTIRE RISK REGARDING THE QUALITY AND/OR PERFORMANCE OF DAPPNODE AND ANY TRANSACTIONS ENTERED INTO THEREON. + +### Limitation of Liability + +In no event will DAppNode Association or any of its contributors be liable, whether in contract, warranty, tort (including negligence, whether active, passive or imputed), product liability, strict liability or other theory, breach of statutory duty or otherwise arising out of, or in connection with, your use of DAppNode, for any direct, indirect, incidental, special or consequential damages (including any loss of profits or data, business interruption or other pecuniary loss, or damage, loss or other compromise of data, in each case whether direct, indirect, incidental, special or consequential) arising out of the use of DAppNode, even if we or other users have been advised of the possibility of such damages. The foregoing limitations and disclaimers shall apply to the maximum extent permitted by applicable law, even if any remedy fails of its essential purpose. You acknowledge and agree that the limitations of liability afforded us hereunder constitute a material and actual inducement and condition to entering into these Terms, and are reasonable, fair and equitable in scope to protect our legitimate interests in light of the fact that we are not receiving consideration from you for providing DAppNode. + +### Indemnification + +To the maximum extent permitted by law, you will defend, indemnify and hold DAppNode and its contributors harmless from and against any and all claims, actions, suits, investigations, or proceedings by any third party (including any party or purported party to or beneficiary or purported beneficiary of any transaction on DAppNode), as well as any and all losses, liabilities, +damages, costs, and expenses (including reasonable attorneys’ fees) arising out of, accruing from, or in any way related to (i) your breach of the terms of this Agreement, (ii) any transaction, or the failure to occur of any transaction on DAppNode, and (iii) your negligence, fraud, or willful misconduct. + +### Compliance with Laws and Tax Obligations + +Your use of DAppNode is subject to all applicable laws of any governmental authority, including, without limitation, federal, state and foreign securities laws, tax laws, tariff and trade laws, ordinances, judgments, decrees, injunctions, writs and orders or like actions of any governmental authority and rules, regulations, orders, interpretations, licenses, and permits of any federal, regional, state, county, municipal or other governmental authority and you agree to comply with all such laws in your use of DAppNode. The users of DAppNode are solely responsible to determinate what, if any, taxes apply to their cryptocurrency transactions. The owners of, or contributors to, DAppNode are not responsible for determining the taxes that apply to cryptocurrency transactions. + +### Miscellaneous + +We reserve the right to revise these Terms, and your rights and obligations are at all times subject to the then-current Terms provided on DAppNode. Your continued use of DAppNode constitutes acceptance of such revised Terms. + +These Terms constitute the entire agreement between you and DAppNode Association regarding use of DAppNode FOSS and will supersede all prior agreements whether, written or oral. No usage of trade or other regular practice or method of dealing between the parties will be used to modify, interpret, supplement, or alter the terms of these Terms. + +If any portion of these Terms is held invalid or unenforceable, such invalidity or enforceability will not affect the other provisions of these Terms, which will remain in full force and effect, and the invalid or unenforceable portion will be given effect to the greatest extent possible. The failure of a party to require performance of any provision will not affect that party’s right to require performance at any time thereafter, nor will a waiver of any breach or default of these Terms or any provision of these Terms constitute a waiver of any subsequent breach or default or a waiver of the provision itself. + + +## Terms of Use - Prysm + +Effective as of Oct 14, 2020 + +By downloading, accessing or using the Prysm implementation (“Prysm”), you (referenced herein as “you” or the “user”) certify that you have read and agreed to the terms and conditions below (the “Terms”) which form a binding contract between you and Prysmatic Labs (referenced herein as “we” or “us”). If you do not agree to the Terms, do not download or use Prysm. + +### About Prysm + +Prysm is a client implementation for Ethereum 2.0 Phase 0 protocol for a proof-of-stake blockchain. To participate in the network, a user must send ETH from the Eth1.0 chain into a validator deposit contract, which will queue in the user as a validator in the system. Validators participate in proposing and voting on blocks in the protocol, and the network applies rewards/penalties based on their behavior. A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the official documentation portal, however, we do not warrant the accuracy, completeness or usefulness of this documentation. Any reliance you place on such information is strictly at your own risk. + +### Licensing Terms + +Prysm is a fully open-source software program licensed pursuant to the GNU General Public License v3.0. + +The Prysmatic Labs name, the term “Prysm” and all related names, logos, product and service names, designs and slogans are trademarks of Prysmatic Labs or its affiliates and/or licensors. You must not use such marks without our prior written permission. + +### Risks of Operating Prysm + +The use of Prysm and acting as a validator on the Ethereum 2.0 network can lead to loss of money. Ethereum is still an experimental system and ETH remains a risky investment. You alone are responsible for your actions on Prysm including the security of your ETH and meeting any applicable minimum system requirements. + +Use of Prysm and the ability to receive rewards or penalties may be affected at any time by mistakes made by the user or other users, software problems such as bugs, errors, incorrectly constructed transactions, unsafe cryptographic libraries or malware affecting the network, technical failures in the hardware of a user, security problems experienced by a user and/or actions or inactions of third parties and/or events experienced by third parties, among other risks. We cannot and do not guarantee that any user of Prysm will make money, that the Prysm network will operate in accordance with the documentation or that transactions will be effective or secure. + +We make no claims that Prysm is appropriate or permitted for use in any specific jurisdiction. Access to Prysm may not be legal by certain persons or in certain jurisdictions or countries. If you access Prysm, you do so on your own initiative and are responsible for compliance with local laws. + +Some Internet plans will charge an additional amount for any excess upload bandwidth used that isn’t included in the plan and may terminate your connection without warning because of overuse. We advise that you check whether your Internet connection is subjected to such limitations and monitor your bandwidth use so that you can stop Prysm before you reach your upload limit. + +### Warranty Disclaimer + +PRYSM IS PROVIDED ON AN “AS-IS” BASIS AND MAY INCLUDE ERRORS, OMISSIONS, OR OTHER INACCURACIES. PRYSMATIC LABS AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT PRYSM FOR ANY PURPOSE, AND HEREBY EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT OR ANY OTHER IMPLIED WARRANTY UNDER THE UNIFORM COMPUTER INFORMATION TRANSACTIONS ACT AS ENACTED BY ANY STATE. WE ALSO MAKE NO REPRESENTATIONS OR WARRANTIES THAT PRYSM WILL OPERATE ERROR-FREE, UNINTERRUPTED, OR IN A MANNER THAT WILL MEET YOUR REQUIREMENTS AND/OR NEEDS. THEREFORE, YOU ASSUME THE ENTIRE RISK REGARDING THE QUALITY AND/OR PERFORMANCE OF PRYSM AND ANY TRANSACTIONS ENTERED INTO THEREON. + +### Limitation of Liability + +In no event will Prysmatic Labs or any of its contributors be liable, whether in contract, warranty, tort (including negligence, whether active, passive or imputed), product liability, strict liability or other theory, breach of statutory duty or otherwise arising out of, or in connection with, your use of Prysm, for any direct, indirect, incidental, special or consequential damages (including any loss of profits or data, business interruption or other pecuniary loss, or damage, loss or other compromise of data, in each case whether direct, indirect, incidental, special or consequential) arising out of use Prysm, even if we or other users have been advised of the possibility of such damages. The foregoing limitations and disclaimers shall apply to the maximum extent permitted by applicable law, even if any remedy fails of its essential purpose. You acknowledge and agree that the limitations of liability afforded us hereunder constitute a material and actual inducement and condition to entering into these Terms, and are reasonable, fair and equitable in scope to protect our legitimate interests in light of the fact that we are not receiving consideration from you for providing Prysm. + +### Indemnification + +To the maximum extent permitted by law, you will defend, indemnify and hold Prysmatic Labs and its contributors harmless from and against any and all claims, actions, suits, investigations, or proceedings by any third party (including any party or purported party to or beneficiary or purported beneficiary of any transaction on Prysm), as well as any and all losses, liabilities, +damages, costs, and expenses (including reasonable attorneys’ fees) arising out of, accruing from, or in any way related to (i) your breach of the terms of this Agreement, (ii) any transaction, or the failure to occur of any transaction on Prysm, and (iii) your negligence, fraud, or willful misconduct. + +### Compliance with Laws and Tax Obligations + +Your use of Prysm is subject to all applicable laws of any governmental authority, including, without limitation, federal, state and foreign securities laws, tax laws, tariff and trade laws, ordinances, judgments, decrees, injunctions, writs and orders or like actions of any governmental authority and rules, regulations, orders, interpretations, licenses, and permits of any federal, +regional, state, county, municipal or other governmental authority and you agree to comply with all such laws in your use of Prysm. The users of Prysm are solely responsible to determinate what, if any, taxes apply to their ETH transactions. The owners of, or contributors to, Prysm are not responsible for determining the taxes that apply to ETH transactions. + +### Miscellaneous + +These Terms will be construed and enforced in accordance with the laws of the state of Illinois as applied to agreements entered into and completely performed in Illinois. You agree to the personal jurisdiction by and venue in Illinois and waive any objection to such jurisdiction or venue. + +We reserve the right to revise these Terms, and your rights and obligations are at all times subject to the then-current Terms provided on Prysm. Your continued use of Prysm constitutes acceptance of such revised Terms. + +These Terms constitute the entire agreement between you and Prysmatic Labs regarding use of Prysm and will supersede all prior agreements whether, written or oral. No usage of trade or other regular practice or method of dealing between the parties will be used to modify, interpret, supplement, or alter the terms of these Terms. + +If any portion of these Terms is held invalid or unenforceable, such invalidity or enforceability will not affect the other provisions of these Terms, which will remain in full force and effect, and the invalid or unenforceable portion will be given effect to the greatest extent possible. The failure of a party to require performance of any provision will not affect that party’s right to require performance at any time thereafter, nor will a waiver of any breach or default of these Terms or any provision of these Terms constitute a waiver of any subsequent breach or default or a waiver of the provision itself. diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md new file mode 100644 index 0000000..a0af8e7 --- /dev/null +++ b/GETTING_STARTED.md @@ -0,0 +1,5 @@ +## Welcome to the Merged Ethereum Mainnet Consensus Client: Prysm + +- Your keystores should now managed in the [Staking Brain](http://brain.web3signer.dappnode) +- Don't have the Web3signer installed yet? It can be manually installed [here](http://my.dappnode/installer/my/web3signer.dnp.dappnode.eth) +- All Staking management now has a new home in the comprehensive [StakersUI](http://my.dappnode/stakers/ethereum) diff --git a/README.md b/README.md new file mode 100644 index 0000000..a17d362 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Lodestar Dappnode Package + +**Lodestar ETH2.0 Beacon chain + validator** + +Go Ethereum Consensus Layer Implementation by Prysmatic Labs. + +![avatar](avatar.png) diff --git a/avatar.png b/avatar.png new file mode 100644 index 0000000..240b9bc Binary files /dev/null and b/avatar.png differ diff --git a/beacon-chain/Dockerfile b/beacon-chain/Dockerfile new file mode 100644 index 0000000..8e094cc --- /dev/null +++ b/beacon-chain/Dockerfile @@ -0,0 +1,37 @@ +FROM debian:bullseye-slim AS builder + +ARG NETWORK + +# Use ldd to copy dependencies of grep +RUN mkdir /deps +RUN ldd /bin/grep | tr -s '[:space:]' '\n' | grep '^/' | xargs -I {} cp -v {} /deps || true + +ENV LUKSO_CONFIG_PATH=/configs/lukso \ + LUKSO_SHARED_CONFIG_URL=https://raw.githubusercontent.com/lukso-network/network-configs/main/mainnet/shared + +RUN mkdir -p ${LUKSO_CONFIG_PATH} && \ + if [ "${NETWORK}" = "lukso" ]; then \ + wget ${LUKSO_SHARED_CONFIG_URL}/genesis.ssz -O ${LUKSO_CONFIG_PATH}/genesis.ssz && \ + wget ${LUKSO_SHARED_CONFIG_URL}/config.yaml -O ${LUKSO_CONFIG_PATH}/config.yaml; \ + fi + +ARG UPSTREAM_VERSION +FROM gcr.io/prysmaticlabs/prysm/beacon-chain:${UPSTREAM_VERSION} + +COPY jwtsecret.hex /jwtsecret +COPY entrypoint.sh /usr/local/bin/entrypoint.sh + +COPY --from=builder /bin/sh /bin/sh +COPY --from=builder /bin/grep /bin/grep +COPY --from=builder /deps/* /lib/ + +ENV JWT_PATH=/jwtsecret \ + VALIDATOR_PORT=3500 \ + DATA_DIR=/data \ + LUKSO_CONFIG_PATH=/configs/lukso \ + LUKSO_GENESIS_FILE_PATH=${LUKSO_CONFIG_PATH}/genesis.ssz \ + LUKSO_CHAIN_CONFIG_FILE_PATH=${LUKSO_CONFIG_PATH}/config.yaml + +COPY --from=builder /configs /configs + +ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ] \ No newline at end of file diff --git a/beacon-chain/entrypoint.sh b/beacon-chain/entrypoint.sh new file mode 100755 index 0000000..0f7c11a --- /dev/null +++ b/beacon-chain/entrypoint.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +SUPPORTED_NETWORKS="sepolia lukso holesky mainnet" +CHECKPOINT_SYNC_FLAG_1="--checkpoint-sync-url" +CHECKPOINT_SYNC_FLAG_2="--genesis-beacon-api-url" +MEVBOOST_FLAGS="--http-mev-relay" + +handle_network() { + case "$NETWORK" in + "holesky") + set_beacon_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "--holesky" + ;; + "lukso") + set_beacon_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "--chain-config-file=$LUKSO_CONFIG_PATH --contract-deployment-block=0 --bootstrap-node=enr:-MK4QJ-Bt9HATy4GQawPbDDTArtnt_phuWiVVoWKhS7-DSNjVzmGKBI9xKzpyRtpeCWd3qA9737FTdkKGDgtHfF4N-6GAYlzJCVRh2F0dG5ldHOIAAAAAAAAAACEZXRoMpA2ulfbQgAABP__________gmlkgnY0gmlwhCKTScGJc2VjcDI1NmsxoQJNpNUERqKhA8eDDC4tovG3a59NXVOW16JDFAWXoFFTEYhzeW5jbmV0cwCDdGNwgjLIg3VkcIIu4A","enr:-MK4QDOs4pISOkkYbVHnGYHC5EhYCsVzwguun6sFZjLTqrY6Kx_AoE-YyHvqBIHDUwyQqESC4-B3o6DigPQNfKpdhXiGAYgmPWCdh2F0dG5ldHOIAAAAAAAAAACEZXRoMpA2ulfbQgAABP__________gmlkgnY0gmlwhCIgwNOJc2VjcDI1NmsxoQNGVC8JPcsqsZPoohLP1ujAYpBfS0dBwiz4LeoUQ-k5OohzeW5jbmV0cwCDdGNwgjLIg3VkcIIu4A" + ;; + "mainnet") + set_beacon_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "--mainnet" + ;; + "sepolia") + set_beacon_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "--sepolia" + ;; + *) + echo "[ERROR - entrypoint] Unsupported network: $NETWORK" + exit 1 + ;; + esac +} + +handle_checkpoint() { + # Check if network is lukso and checkpoint sync url is empty + if [ "${NETWORK}" = "lukso" ] && [ -z "${CHECKPOINT_SYNC_URL}" ]; then + echo "[INFO - entrypoint] Syncing LUKSO chain from genesis" + add_flag_to_extra_opts "--genesis-state=${LUKSO_GENESIS_FILE_PATH}" + else + # Prysm needs these 2 flags to be set for checkpoint sync + set_checkpointsync_url "${CHECKPOINT_SYNC_FLAG_1}" "${CHECKPOINT_SYNC_URL}" + set_checkpointsync_url "${CHECKPOINT_SYNC_FLAG_2}" "${CHECKPOINT_SYNC_URL}" + fi +} + +run_beacon() { + echo "[INFO - entrypoint] Running beacon service" + + # shellcheck disable=SC2086 + exec /beacon-chain \ + --accept-terms-of-use \ + --datadir=${DATA_DIR} \ + --jwt-secret="${JWT_PATH}" \ + --execution-endpoint="${ENGINE_API_URL}" \ + --monitoring-host=0.0.0.0 \ + --grpc-gateway-host=0.0.0.0 \ + --grpc-gateway-port="${VALIDATOR_PORT}" \ + --grpc-gateway-corsdomain="${CORSDOMAIN}" \ + --rpc-host=0.0.0.0 \ + --verbosity="${VERBOSITY}" \ + --p2p-tcp-port="${P2P_TCP_PORT}" \ + --p2p-udp-port="${P2P_UDP_PORT}" \ + --p2p-max-peers="$MAX_PEERS" \ + --min-sync-peers="$MIN_SYNC_PEERS" \ + --subscribe-all-subnets="$SUBSCRIBE_ALL_SUBNETS" ${EXTRA_OPTS} +} + +validate_fee_recipient +handle_network +handle_checkpoint +set_mevboost_flag "${MEVBOOST_FLAGS}" +add_flag_to_extra_opts "--suggested-fee-recipient=${FEE_RECIPIENT}" +run_beacon diff --git a/beacon-chain/jwtsecret.hex b/beacon-chain/jwtsecret.hex new file mode 100644 index 0000000..68dc70a --- /dev/null +++ b/beacon-chain/jwtsecret.hex @@ -0,0 +1 @@ +7ad9cfdec75eceb662f5e48f5765701c17f51a5233a60fbcfa5f9e495fa99d18 \ No newline at end of file diff --git a/dappnode_package.json b/dappnode_package.json new file mode 100644 index 0000000..09bacc8 --- /dev/null +++ b/dappnode_package.json @@ -0,0 +1,47 @@ +{ + "upstream": [ + { + "repo": "prysmaticlabs/prysm", + "version": "v5.0.4", + "arg": "UPSTREAM_VERSION" + }, + { + "repo": "dappnode/staker-package-scripts", + "version": "v0.1.0", + "arg": "STAKER_SCRIPTS_VERSION" + } + ], + "shortDescription": "Prysm mainnet ETH2.0 Beacon chain + validator", + "description": "Validate with Prysm: a Go implementation of the Ethereum 2.0 Serenity protocol and open source project created by Prysmatic Labs.\n\nIt includes a Grafana dashboard for the [DMS](http://my.dappnode/#/installer/dms.dnp.dappnode.eth) thanks to the amazing work of [metanull-operator](https://github.com/metanull-operator/eth2-grafana)", + "type": "service", + "author": "DAppNode Association (https://github.com/dappnode)", + "architectures": ["linux/amd64", "linux/arm64"], + "mainService": "beacon-chain", + "contributors": [ + "dappLion (https://github.com/dapplion)" + ], + "chain": { + "driver": "ethereum-beacon-chain", + "serviceName": "beacon-chain", + "portNumber": 3500 + }, + "license": "GPL-3.0", + "repository": { + "type": "git", + "url": "git+https://github.com/dappnode/DAppNodePackage-prysm-generic.git" + }, + "bugs": { + "url": "https://github.com/dappnode/DAppNodePackage-prysm-generic/issues" + }, + "requirements": { + "minimumDappnodeVersion": "0.2.60" + }, + "categories": ["Blockchain", "ETH2.0"], + "style": { + "featuredBackground": "linear-gradient(67deg, #16000c, #123939)", + "featuredColor": "white" + }, + "warnings": { + "onRemove": "Make sure your StakersUI does not have this client selected! Double check in the Stakers Tab in the left NavBar" + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..440bc62 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +version: "3.5" +services: + beacon-chain: + build: + context: beacon-chain + args: + UPSTREAM_VERSION: v5.0.4 + STAKER_SCRIPTS_VERSION: v0.1.0 + volumes: + - "beacon-chain-data:/data" + restart: unless-stopped + environment: + CHECKPOINT_SYNC_URL: "" + EXTRA_OPTS: "" + FEE_RECIPIENT: "" + VERBOSITY: info + MIN_SYNC_PEERS: "3" + MAX_PEERS: "70" + SUBSCRIBE_ALL_SUBNETS: "false" + validator: + build: + context: validator + args: + UPSTREAM_VERSION: v5.0.4 + STAKER_SCRIPTS_VERSION: v0.1.0 + volumes: + - "validator-data:/root/" + restart: unless-stopped + environment: + LOG_TYPE: INFO + GRAFFITI: validating_from_DAppNode + EXTRA_OPTS: "" + FEE_RECIPIENT: "" + VERBOSITY: info +volumes: + beacon-chain-data: {} + validator-data: {} diff --git a/package_variants/holesky/dappnode_package.json b/package_variants/holesky/dappnode_package.json new file mode 100644 index 0000000..3b4a352 --- /dev/null +++ b/package_variants/holesky/dappnode_package.json @@ -0,0 +1,20 @@ +{ + "name": "prysm-holesky.dnp.dappnode.eth", + "version": "0.1.4", + "links": { + "ui": "http://brain.web3signer-holesky.dappnode", + "homepage": "https://prysmaticlabs.com/", + "readme": "https://github.com/dappnode/DAppNodePackage-prysm-generic", + "docs": "https://docs.prylabs.network/docs/getting-started" + }, + "globalEnvs": [ + { + "envs": ["EXECUTION_CLIENT_HOLESKY", "MEVBOOST_HOLESKY"], + "services": ["beacon-chain"] + }, + { + "envs": ["MEVBOOST_HOLESKY"], + "services": ["validator"] + } + ] +} diff --git a/package_variants/holesky/docker-compose.yml b/package_variants/holesky/docker-compose.yml new file mode 100644 index 0000000..ee9dbb1 --- /dev/null +++ b/package_variants/holesky/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3.5" +services: + beacon-chain: + build: + args: + NETWORK: holesky + P2P_TCP_PORT: 14503 + P2P_UDP_PORT: 14503 + ports: + - 14503:14503/tcp + - 14503:14503/udp + environment: + CORSDOMAIN: "http://prysm-holesky.dappnode" + validator: + build: + args: + NETWORK: holesky + BEACON_RPC_PROVIDER: "beacon-chain.prysm-holesky.dappnode:4000" + BEACON_RPC_GATEWAY_PROVIDER: "beacon-chain.prysm-holesky.dappnode:3500" diff --git a/package_variants/holesky/prometheus-targets.json b/package_variants/holesky/prometheus-targets.json new file mode 100644 index 0000000..03a8dd6 --- /dev/null +++ b/package_variants/holesky/prometheus-targets.json @@ -0,0 +1,20 @@ +[ + { + "labels": { + "package": "prysm-holesky.dnp.dappnode.eth", + "service": "beacon-chain.prysm-holesky.dappnode" + }, + "targets": [ + "beacon-chain.prysm-holesky.dappnode:8080" + ] + }, + { + "labels": { + "package": "prysm-holesky.dnp.dappnode.eth", + "service": "validator.prysm-holesky.dappnode" + }, + "targets": [ + "validator.prysm-holesky.dappnode:8081" + ] + } +] \ No newline at end of file diff --git a/package_variants/lukso/dappnode_package.json b/package_variants/lukso/dappnode_package.json new file mode 100644 index 0000000..78e016c --- /dev/null +++ b/package_variants/lukso/dappnode_package.json @@ -0,0 +1,16 @@ +{ + "name": "prysm-lukso.dnp.dappnode.eth", + "version": "0.1.1", + "links": { + "ui": "http://brain.web3signer-lukso.dappnode", + "homepage": "https://prysmaticlabs.com/", + "readme": "https://github.com/dappnode/DAppNodePackage-prysm-generic", + "docs": "https://docs.prylabs.network/docs/getting-started" + }, + "globalEnvs": [ + { + "envs": ["EXECUTION_CLIENT_LUKSO"], + "services": ["beacon-chain"] + } + ] +} diff --git a/package_variants/lukso/docker-compose.yml b/package_variants/lukso/docker-compose.yml new file mode 100644 index 0000000..514cbd0 --- /dev/null +++ b/package_variants/lukso/docker-compose.yml @@ -0,0 +1,22 @@ +version: "3.5" +services: + beacon-chain: + build: + args: + NETWORK: lukso + P2P_TCP_PORT: 12603 + P2P_UDP_PORT: 12603 + ports: + - 12603:12603/tcp + - 12603:12603/udp + environment: + CORSDOMAIN: "http://prysm-lukso.dappnode" + MIN_SYNC_PEERS: "1" + MAX_PEERS: "250" + SUBSCRIBE_ALL_SUBNETS: "true" + validator: + build: + args: + NETWORK: lukso + BEACON_RPC_PROVIDER: "beacon-chain.prysm-lukso.dappnode:4000" + BEACON_RPC_GATEWAY_PROVIDER: "beacon-chain.prysm-lukso.dappnode:3500" diff --git a/package_variants/lukso/prometheus-targets.json b/package_variants/lukso/prometheus-targets.json new file mode 100644 index 0000000..dfd5251 --- /dev/null +++ b/package_variants/lukso/prometheus-targets.json @@ -0,0 +1,20 @@ +[ + { + "labels": { + "package": "prysm-lukso.dnp.dappnode.eth", + "service": "beacon-chain.prysm-lukso.dappnode" + }, + "targets": [ + "beacon-chain.prysm-lukso.dappnode:8080" + ] + }, + { + "labels": { + "package": "prysm-lukso.dnp.dappnode.eth", + "service": "validator.prysm-lukso.dappnode" + }, + "targets": [ + "validator.prysm-lukso.dappnode:8081" + ] + } +] \ No newline at end of file diff --git a/package_variants/mainnet/dappnode_package.json b/package_variants/mainnet/dappnode_package.json new file mode 100644 index 0000000..f9c9a1b --- /dev/null +++ b/package_variants/mainnet/dappnode_package.json @@ -0,0 +1,20 @@ +{ + "name": "prysm.dnp.dappnode.eth", + "version": "3.0.14", + "links": { + "ui": "http://brain.web3signer.dappnode", + "homepage": "https://prysmaticlabs.com/", + "readme": "https://github.com/dappnode/DAppNodePackage-prysm", + "docs": "https://docs.prylabs.network/docs/getting-started" + }, + "globalEnvs": [ + { + "envs": ["EXECUTION_CLIENT_MAINNET", "MEVBOOST_MAINNET"], + "services": ["beacon-chain"] + }, + { + "envs": ["MEVBOOST_MAINNET"], + "services": ["validator"] + } + ] +} diff --git a/package_variants/mainnet/docker-compose.yml b/package_variants/mainnet/docker-compose.yml new file mode 100644 index 0000000..696d246 --- /dev/null +++ b/package_variants/mainnet/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3.5" +services: + beacon-chain: + build: + args: + NETWORK: mainnet + P2P_TCP_PORT: 13103 + P2P_UDP_PORT: 12103 + ports: + - 13103:13103/tcp + - 12103:12103/udp + environment: + CORSDOMAIN: "http://prysm.dappnode" + validator: + build: + args: + NETWORK: mainnet + BEACON_RPC_PROVIDER: "beacon-chain.prysm.dappnode:4000" + BEACON_RPC_GATEWAY_PROVIDER: "beacon-chain.prysm.dappnode:3500" diff --git a/package_variants/mainnet/prometheus-targets.json b/package_variants/mainnet/prometheus-targets.json new file mode 100644 index 0000000..ba5ca89 --- /dev/null +++ b/package_variants/mainnet/prometheus-targets.json @@ -0,0 +1,20 @@ +[ + { + "labels": { + "package": "prysm.dnp.dappnode.eth", + "service": "beacon-chain.prysm.dappnode" + }, + "targets": [ + "beacon-chain.prysm.dappnode:8080" + ] + }, + { + "labels": { + "package": "prysm.dnp.dappnode.eth", + "service": "validator.prysm.dappnode" + }, + "targets": [ + "validator.prysm.dappnode:8081" + ] + } +] \ No newline at end of file diff --git a/prysm-grafana-dashboard.json b/prysm-grafana-dashboard.json new file mode 100644 index 0000000..b248917 --- /dev/null +++ b/prysm-grafana-dashboard.json @@ -0,0 +1,4440 @@ + +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 10, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "#37872D", + "#37872D", + "#37872D" + ], + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 95, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "0,0", + "timeFrom": null, + "timeShift": null, + "title": "Status", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "#1F60C4", + "#1F60C4", + "#1F60C4" + ], + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 56, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Network Status", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "datasource": null, + "description": "Sum of all validator balances.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 4, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ETH" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 94, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"})", + "instant": true, + "interval": "", + "legendFormat": "vbal", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Validator Balance (ETH)", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "Total ETH return on the initial effective stake of active local validators.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 4, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#F2495C", + "value": null + }, + { + "color": "#F2CC0C", + "value": 0 + }, + { + "color": "#73BF69", + "value": 0.0001 + } + ] + }, + "unit": "ETH" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 52, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"})-(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16 and validator_statuses{service=\"validator.prysm.dappnode\"} == 3)*32)", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Earnings (ETH)", + "type": "stat" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Total percentage return on the initial effective stake of active local validators. Excess deposits will be reflected as earnings.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 70, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "(sum(validator_balance{service=\"validator.prysm.dappnode\"}) - (count(validator_balance{service=\"validator.prysm.dappnode\"} > 16 and validator_statuses{service=\"validator.prysm.dappnode\"} == 3)*32))/(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16 and validator_statuses{service=\"validator.prysm.dappnode\"} == 3)*32) ", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Total Return", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "datasource": null, + "description": "Number of beacon nodes to which this node is connected.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 10 + }, + { + "color": "yellow", + "value": 20 + }, + { + "color": "green", + "value": 30 + } + ] + }, + "unit": "peers" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 98, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "p2p_peer_count{state=\"Connected\",service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Peer Count", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "The percentage of ETH balances expected to attest that are actually attesting.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.66 + }, + { + "color": "yellow", + "value": 0.8 + }, + { + "color": "green", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 23, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "(beacon_prev_epoch_target_gwei{service=\"beacon-chain.prysm.dappnode\"} / beacon_prev_epoch_active_gwei{service=\"beacon-chain.prysm.dappnode\"} )", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Participation Rate", + "type": "stat" + }, + { + "datasource": null, + "description": "A metric expressing the distance between the current finalized epoch and the expected finalized epoch based on the genesis time. 100% means the expected and current finalized epochs are the same. The metric reaches 0% when the finalized epoch is 25 epochs behind the expected epoch.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 0, + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.88 + }, + { + "color": "#EAB839", + "value": 0.92 + }, + { + "color": "green", + "value": 0.96 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 73, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "clamp_min((1-(4*((floor(beacon_clock_time_slot{service=\"beacon-chain.prysm.dappnode\"}/32) - beacon_finalized_epoch{service=\"beacon-chain.prysm.dappnode\"} - 2)/100))),0)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Network Liveness", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "The percentage of ETH balances expected to attest that are actually attesting.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 4, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 1 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "(beacon_prev_epoch_target_gwei{service=\"beacon-chain.prysm.dappnode\"} / beacon_prev_epoch_active_gwei{service=\"beacon-chain.prysm.dappnode\"} )", + "interval": "", + "legendFormat": "participation rate", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": false, + "line": true, + "op": "lt", + "value": 0.66, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Participation Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "percentunit", + "label": "Participation Rate", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "Prometheus", + "description": "Sum of all validator balances multiplied by the price of ETH in USD.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 4 + }, + "id": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "ethusd ", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "ethusd", + "refId": "A" + }, + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"})", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "balance", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Validator Balance (USD)", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "total_validator_value", + "binary": { + "left": "ethusd", + "operator": "*", + "reducer": "sum", + "right": "balance" + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + }, + "replaceFields": true + } + } + ], + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "Total earnings in USD.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "min": 0, + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 4 + }, + "id": 101, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"})-(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16 and validator_statuses{service=\"validator.prysm.dappnode\"} == 3)*32)", + "instant": true, + "interval": "", + "legendFormat": "total_balance", + "refId": "A" + }, + { + "expr": "ethusd", + "instant": true, + "interval": "", + "legendFormat": "ethusd", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Earnings (USD)", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Total Earnings (USD)", + "binary": { + "left": "total_balance", + "operator": "*", + "reducer": "sum", + "right": "ethusd" + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + }, + "replaceFields": true + } + } + ], + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "Price of ETH in USD.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "min": 0, + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "currencyUSD" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 4 + }, + "id": 102, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "ethusd", + "instant": true, + "interval": "", + "legendFormat": "ethusd", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "ETH Price (USD)", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Total Earnings (USD)", + "binary": { + "left": "total_balance", + "operator": "*", + "reducer": "sum", + "right": "ethusd" + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + }, + "replaceFields": true + } + } + ], + "type": "stat" + }, + { + "datasource": null, + "description": "Average inclusion distance of the last attestations by all validators.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 2 + }, + { + "color": "orange", + "value": 3 + }, + { + "color": "red", + "value": 4 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 4 + }, + "id": 104, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "avg(validator_inclusion_distance)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Avg. Last Inclusion Distance", + "type": "stat" + }, + { + "datasource": null, + "description": "Current, justified, and finalized epochs. In this order, these three values should be sequentially decreasing.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 0, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(135, 135, 135)", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 12, + "y": 4 + }, + "id": 27, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "floor(beacon_clock_time_slot{service=\"beacon-chain.prysm.dappnode\"} / 32)", + "instant": true, + "interval": "", + "legendFormat": "current", + "refId": "A" + }, + { + "expr": "beacon_current_justified_epoch{service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "justified", + "refId": "C" + }, + { + "expr": "beacon_finalized_epoch {service=\"beacon-chain.prysm.dappnode\"} ", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "finalized", + "refId": "D" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Epochs", + "type": "stat" + }, + { + "datasource": null, + "description": "Current slot and head slot", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(135, 135, 135)", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 15, + "y": 4 + }, + "id": 29, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "beacon_slot{service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "current slot", + "refId": "A" + }, + { + "expr": "beacon_head_slot{service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "head slot", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Slots", + "type": "stat" + }, + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "#FA6400", + "#FA6400", + "#FA6400" + ], + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 96, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "0,0", + "timeFrom": null, + "timeShift": null, + "title": "Local Validators", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "#F2495C", + "#F2495C", + "#F2495C" + ], + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 65, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Network Validators", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Increase in all local validator balances over the last hour", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "ETH", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 8 + }, + "id": 77, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "#5794F2", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 1h != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) + (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 1h > 16))", + "instant": false, + "interval": "", + "intervalFactor": 3, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Hourly Earnings", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#d44a3a", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Increase in all local validator balances over the last day", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "ETH", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 8 + }, + "id": 48, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 1d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) + (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 1d > 16))", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Daily Earnings", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Increase in all local validator balances over the last week", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "ETH", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 8 + }, + "id": 49, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.3", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 7d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) + (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 7d > 16))", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Weekly Earnings", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#299c46" + ], + "datasource": null, + "decimals": 4, + "description": "Increase in all local validator balances over the last month", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "ETH", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 8 + }, + "id": 50, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 30d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) + (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 30d > 16))", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Monthly Earnings", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "datasource": null, + "description": "Counts of active, slashed and exited validators.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 0, + "displayName": "", + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 12, + "y": 8 + }, + "id": 71, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "validator_count{state=\"Active\",service=\"beacon-chain.prysm.dappnode\"} ", + "instant": true, + "interval": "", + "legendFormat": "active", + "refId": "C" + }, + { + "expr": "validator_count{state=\"Slashed\",service=\"beacon-chain.prysm.dappnode\"} ", + "instant": true, + "interval": "", + "legendFormat": "slashed", + "refId": "B" + }, + { + "expr": "validator_count{state=\"Exited\",service=\"beacon-chain.prysm.dappnode\"} ", + "instant": true, + "interval": "", + "legendFormat": "exited", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Validator Counts", + "type": "stat" + }, + { + "aliasColors": { + "active validators": "rgba(239, 132, 60, 0.57)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "Number of pending and existing validators over time. Pending validators are shown as positive values, while exiting validators are shown as negative values.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 15, + "y": 8 + }, + "hiddenSeries": false, + "id": 64, + "interval": "", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.7.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "exiting", + "transform": "negative-Y" + }, + { + "alias": "active validators", + "yaxis": 2 + }, + { + "alias": "slashing", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "validator_count{state=\"Pending\",service=\"beacon-chain.prysm.dappnode\"}", + "interval": "", + "legendFormat": "pending", + "refId": "B" + }, + { + "expr": "validator_count{state=\"Exiting\",service=\"beacon-chain.prysm.dappnode\"}", + "interval": "", + "legendFormat": "exiting", + "refId": "A" + }, + { + "expr": "validator_count{state=\"Slashing\",service=\"beacon-chain.prysm.dappnode\"}", + "interval": "", + "legendFormat": "slashing", + "refId": "C" + }, + { + "expr": "validator_count{service=\"beacon-chain.prysm.dappnode\", state=\"Active\"}", + "interval": "", + "legendFormat": "active validators", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Validators", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "validators", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": null, + "description": "Current number of pending and exiting validators", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 8 + }, + "id": 88, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "validator_count{state=\"Pending\",service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "pending", + "refId": "B" + }, + { + "expr": "validator_count{state=\"Exiting\",service=\"beacon-chain.prysm.dappnode\"}", + "instant": true, + "interval": "", + "legendFormat": "exiting", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Validator Queues", + "type": "stat" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Percentage increase in all local validator balances over the last hour", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 11 + }, + "id": 82, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "annualized hourly return", + "targets": [ + { + "expr": "((sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 1h != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) +\t(32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 1h > 16)))/(32 * avg_over_time(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)[1h:]))) * 365 * 24", + "hide": false, + "interval": "", + "legendFormat": "annualized hourly return", + "refId": "B" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Hourly Return, Annualized", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Percentage increase in all local validator balances over the last day", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 11 + }, + "id": 69, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "annualized daily return", + "targets": [ + { + "expr": "((sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 1d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) +\t(32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 1d > 16)))/(32 * avg_over_time(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)[1d:]))) * 365", + "hide": false, + "interval": "", + "legendFormat": "annualized daily return", + "refId": "B" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Daily Return, Annualized", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Percentage increase in all local validator balances over the last week", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 11 + }, + "id": 83, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "annualized weekly return", + "targets": [ + { + "expr": "((sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 7d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) +\t(32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 7d > 16)))/(32 * avg_over_time(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)[7d:]))) * (365/7)", + "hide": false, + "interval": "", + "legendFormat": "annualized weekly return", + "refId": "B" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Weekly Return, Annualized", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#F2495C", + "#FADE2A", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Percentage increase in all local validator balances over the last month", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 11 + }, + "id": 84, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": 0 + }, + "tableColumn": "", + "targets": [ + { + "expr": "((sum(validator_balance{service=\"validator.prysm.dappnode\"}) - sum(validator_balance{service=\"validator.prysm.dappnode\"} offset 30d != 0) - (32 * count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)) +\t(32 * count(validator_balance{service=\"validator.prysm.dappnode\"} offset 30d > 16)))/(32 * avg_over_time(count(validator_balance{service=\"validator.prysm.dappnode\"} > 16)[30d:]))) * (365/30)", + "hide": false, + "interval": "", + "legendFormat": "annualized monthly return", + "refId": "B" + } + ], + "thresholds": "-0, 0.0001", + "timeFrom": null, + "timeShift": null, + "title": "Monthly Return, Annualized", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorValue": true, + "colors": [ + "#d44a3a", + "#73BF69", + "#73BF69" + ], + "datasource": null, + "decimals": 4, + "description": "Average validator balance across the network", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 12, + "y": 11 + }, + "id": 33, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.3", + "postfix": "ETH", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true, + "ymax": null, + "ymin": null + }, + "tableColumn": "eth", + "targets": [ + { + "expr": "validators_total_balance{state=\"Active\",service=\"beacon-chain.prysm.dappnode\"} / validator_count{state=\"Active\",service=\"beacon-chain.prysm.dappnode\"} / 1000000000", + "interval": "", + "legendFormat": "eth", + "refId": "A" + } + ], + "thresholds": "32", + "timeFrom": null, + "timeShift": null, + "title": "Avg. Balance", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "datasource": null, + "description": "Estimated length of time until all pending and exiting validators have cleared the queues.", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "m" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 11 + }, + "id": 87, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "((validator_count{state=\"Pending\",service=\"beacon-chain.prysm.dappnode\"}/4)*6.4)", + "instant": true, + "interval": "", + "legendFormat": "pending", + "refId": "B" + }, + { + "expr": "((validator_count{state=\"Exiting\",service=\"beacon-chain.prysm.dappnode\"}/4)*6.4)", + "instant": true, + "interval": "", + "legendFormat": "exiting", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Queue Lengths", + "type": "stat" + }, + { + "columns": [], + "datasource": null, + "description": "validator stats by public key over the lifetime of the validator process ", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 54, + "interval": "", + "links": [], + "pageSize": null, + "pluginVersion": "6.5.1", + "showHeader": true, + "sort": { + "col": 2, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "job", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "public key", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "", + "linkUrl": "", + "pattern": "pubkey", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "instance", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "__name__", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "attested", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "aggregated", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "proposed", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "failed attestations", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "failed aggregations", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "balance", + "align": "auto", + "colorMode": "value", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 4, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "", + "linkUrl": "", + "mappingType": 1, + "pattern": "Value #F", + "thresholds": [ + "24", + "32" + ], + "type": "number", + "unit": "short" + }, + { + "alias": "pubkey", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "beaconcha.in", + "linkUrl": "http://beaconcha.in/validator/${__cell_1:raw}", + "mappingType": 1, + "pattern": "pubkey_short", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "last inclusion distance", + "align": "auto", + "colorMode": null, + "colors": [ + "#F2495C", + "#FF9830", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Value #H", + "thresholds": [ + "" + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_replace(max by(pubkey) (validator_balance{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "balance", + "refId": "F" + }, + { + "expr": "label_replace(max by(pubkey) (validator_successful_proposals{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "E" + }, + { + "expr": "label_replace(max by(pubkey) (validator_successful_attestations{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "expr": "label_replace(max by(pubkey) (validator_successful_aggregations{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "C" + }, + { + "expr": "label_replace(max by(pubkey) (validator_failed_attestations{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "B" + }, + { + "expr": "label_replace(max by(pubkey) (validator_failed_aggregations{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "D" + }, + { + "expr": "label_replace(max by(pubkey) (validator_balance{service=\"validator.prysm.dappnode\"}), \"pubkey\", \"$1\", \"pubkey_short\", \"(.{10}).*\") ", + "interval": "", + "legendFormat": "", + "refId": "G" + }, + { + "expr": "label_replace(max by(pubkey) (validator_inclusion_distance{service=\"validator.prysm.dappnode\"}), \"pubkey_short\", \"$1\", \"pubkey\", \"(.{10}).*\") ", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "H" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Validator Process Stats", + "transform": "table", + "type": "table-old" + }, + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "#8F3BB8", + "#8F3BB8", + "#8F3BB8" + ], + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 57, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "0,0", + "timeFrom": null, + "timeShift": null, + "title": "Client Status", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "The number of peers to which the beacon chain is connected", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 4, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 5, + "legend": { + "avg": true, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "p2p_peer_count{state=\"Connected\",service=\"beacon-chain.prysm.dappnode\"}", + "interval": "", + "legendFormat": "peers", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": false, + "line": true, + "op": "lt", + "value": 10, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Peers", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Peers", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorPrefix": false, + "colorValue": true, + "colors": [ + "#F2495C", + "rgba(237, 129, 40, 0.89)", + "#299c46" + ], + "datasource": null, + "decimals": 1, + "description": "The length of time the beacon chain process has been running", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "h", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 18, + "y": 15 + }, + "id": 45, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "(s)", + "postfixFontSize": "80%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "(time()-process_start_time_seconds{service=\"beacon-chain.prysm.dappnode\"})/3600", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "48,96", + "timeFrom": null, + "timeShift": null, + "title": "Beacon Uptime", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "Average number of log messages received per hour over the selected time range", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.001 + } + ] + }, + "unit": "/hr" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 15 + }, + "id": 79, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "sum(rate(log_entries_total{service=\"beacon-chain.prysm.dappnode\", level=\"error\"}[$__range]))*3600", + "instant": false, + "interval": "", + "legendFormat": "errors", + "refId": "A" + }, + { + "expr": "sum(rate(log_entries_total{service=\"beacon-chain.prysm.dappnode\", level=\"warning\"}[$__range]))*3600", + "instant": false, + "interval": "", + "legendFormat": "warnings", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Beacon Logs", + "type": "stat" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorPostfix": true, + "colorPrefix": false, + "colorValue": true, + "colors": [ + "#F2495C", + "rgba(237, 129, 40, 0.89)", + "#299c46" + ], + "datasource": null, + "decimals": 1, + "description": "The length of time the validator process has been running", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "h", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 18, + "y": 18 + }, + "id": 74, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "pluginVersion": "6.7.2", + "postfix": "(s)", + "postfixFontSize": "80%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "(time()-process_start_time_seconds{service=\"validator.prysm.dappnode\"})/3600", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "48,96", + "timeFrom": null, + "timeShift": null, + "title": "Validator Uptime", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "Average number of log messages received per hour over the selected time range", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "noValue": "0", + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.001 + } + ] + }, + "unit": "/hr" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 18 + }, + "id": 76, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.0", + "targets": [ + { + "expr": "sum(rate(log_entries_total{service=\"validator.prysm.dappnode\", level=\"error\"}[$__range]))*3600", + "instant": false, + "interval": "", + "legendFormat": "errors", + "refId": "B" + }, + { + "expr": "sum(rate(log_entries_total{service=\"validator.prysm.dappnode\", level=\"warning\"}[$__range]))*3600", + "interval": "", + "legendFormat": "warnings", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Validator Logs", + "type": "stat" + }, + { + "cacheTimeout": null, + "colorBackground": true, + "colorValue": false, + "colors": [ + "rgb(105, 70, 0)", + "rgb(105, 70, 0)", + "rgb(105, 70, 0)" + ], + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 58, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "20%", + "prefix": "", + "prefixFontSize": "20%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "1", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "0,0", + "timeFrom": null, + "timeShift": null, + "title": "Server", + "type": "singlestat", + "valueFontSize": "20%", + "valueMaps": [ + { + "op": "=", + "text": "", + "value": "null" + }, + { + "op": "=", + "text": "", + "value": "1" + } + ], + "valueName": "current" + }, + { + "aliasColors": { + "Free": "rgb(51, 51, 51)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "decimals": 2, + "description": "Beacon chain and validator memory usage on the server.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 99, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "beacon memory", + "fill": 0, + "fillGradient": 0, + "stack": false + }, + { + "alias": "validator memory", + "fill": 0, + "fillGradient": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_resident_memory_bytes{service=\"beacon-chain.prysm.dappnode\"}", + "interval": "", + "legendFormat": "beacon memory", + "refId": "F" + }, + { + "expr": "process_resident_memory_bytes{service=\"validator.prysm.dappnode\"}", + "interval": "", + "legendFormat": "validator memory", + "refId": "G" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Memory Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "GB", + "logBase": 1, + "max": "16000000000", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "idle": "rgb(51, 51, 51)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "decimals": 2, + "description": "Processor usage on the server", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 8, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 22 + }, + "hiddenSeries": false, + "id": 20, + "interval": "", + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": true, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"system\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"system\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "system", + "refId": "A" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"user\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"user\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "user", + "refId": "B" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"nice\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"nice\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "nice", + "refId": "C" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"iowait\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"iowait\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "iowait", + "refId": "D" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"steal\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"steal\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "steal", + "refId": "E" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"idle\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"idle\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "idle", + "refId": "F" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"irq\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"irq\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "irq", + "refId": "G" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"softirq\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"softirq\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "softirq", + "refId": "H" + }, + { + "expr": "sum(irate(node_cpu_seconds_total{mode=\"guest\",job=\"nodeexporter\"}[5m])) or sum(irate(node_cpu{mode=\"guest\",job=\"nodeexporter\"}[5m]))", + "interval": "", + "intervalFactor": 10, + "legendFormat": "guest", + "refId": "I" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "%", + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "Network transmission (tx) and reception (rx) rates", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 4, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{id=\"/\",interface!~\"br.*|lo\"}[1m]))*8 / 1048576", + "interval": "", + "intervalFactor": 5, + "legendFormat": "rx", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{id=\"/\",interface!~\"br.*|lo\"}[1m]))*8 /1048576", + "interval": "", + "intervalFactor": 5, + "legendFormat": "tx", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Mbps", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 22 + }, + "hiddenSeries": false, + "id": 92, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(node_filesystem_size_bytes{job=\"nodeexporter\"})-sum(node_filesystem_avail_bytes{job=\"nodeexporter\"}))/sum(node_filesystem_size_bytes{job=\"nodeexporter\"})", + "interval": "", + "legendFormat": "disk usage", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "percentunit", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "decbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Free": "rgb(51, 51, 51)" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "decimals": 2, + "description": "Memory usage on the server", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 4, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "beacon memory", + "fill": 0, + "fillGradient": 0, + "stack": false + }, + { + "alias": "validator memory", + "fill": 0, + "fillGradient": 0, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "( node_memory_MemTotal_bytes{job=\"nodeexporter\"} - node_memory_MemFree_bytes{job=\"nodeexporter\"} - node_memory_Buffers_bytes{job=\"nodeexporter\"} - node_memory_Cached_bytes{job=\"nodeexporter\"} - node_memory_SwapCached_bytes{job=\"nodeexporter\"} - node_memory_Slab_bytes{job=\"nodeexporter\"} - node_memory_PageTables_bytes{job=\"nodeexporter\"} - node_memory_VmallocUsed_bytes{job=\"nodeexporter\"} ) or ( node_memory_MemTotal{job=\"nodeexporter\"} - node_memory_MemFree{job=\"nodeexporter\"} - node_memory_Buffers{job=\"nodeexporter\"} - node_memory_Cached{job=\"nodeexporter\"} - node_memory_SwapCached{job=\"nodeexporter\"} - node_memory_Slab{job=\"nodeexporter\"} - node_memory_PageTables{job=\"nodeexporter\"} - node_memory_VmallocUsed{job=\"nodeexporter\"} )", + "interval": "", + "intervalFactor": 2, + "legendFormat": "apps", + "refId": "A" + }, + { + "expr": "node_memory_Buffers_bytes{job=\"nodeexporter\"} or node_memory_Buffers{job=\"nodeexporter\"}", + "interval": "", + "intervalFactor": 2, + "legendFormat": "buffers", + "refId": "B" + }, + { + "expr": "node_memory_Cached_bytes{job=\"nodeexporter\"} or node_memory_Cached{job=\"nodeexporter\"}", + "interval": "", + "intervalFactor": 2, + "legendFormat": "cached", + "refId": "C" + }, + { + "expr": "node_memory_MemFree_bytes{job=\"nodeexporter\"} or node_memory_MemFree{job=\"nodeexporter\"}", + "interval": "", + "legendFormat": "free", + "refId": "D" + }, + { + "expr": "node_memory_Slab_bytes{job=\"nodeexporter\"} or node_memory_Slab{job=\"nodeexporter\"}", + "interval": "", + "legendFormat": "slab", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Server Memory Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "label": "GB", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 28 + }, + "hiddenSeries": false, + "id": 90, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_hwmon_temp_celsius{chip=\"platform_coretemp_0\",job=\"nodeexporter\",sensor=\"temp1\"}", + "interval": "", + "intervalFactor": 1, + "legendFormat": "cpu temp", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Temp", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 4, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 28 + }, + "hiddenSeries": false, + "id": 81, + "legend": { + "avg": true, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "probe_duration_seconds{instance=\"google\"}", + "interval": "", + "intervalFactor": 10, + "legendFormat": "{{instance}}", + "refId": "A" + }, + { + "expr": "probe_duration_seconds{instance=\"cloudflare\"}", + "interval": "", + "intervalFactor": 10, + "legendFormat": "{{instance}}", + "refId": "B" + }, + { + "expr": "probe_duration_seconds{instance=\"remote\"}", + "interval": "", + "intervalFactor": 10, + "legendFormat": "{{instance}}", + "refId": "C" + }, + { + "expr": "probe_duration_seconds{instance=\"dyndns\"}", + "interval": "", + "intervalFactor": 10, + "legendFormat": "{{instance}}", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ping", + "tooltip": { + "shared": true, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "time": { + "from": "now-2d", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "DAppNode ETH2 Prysm", + "uid": "DNPEPPD", + "version": 2 +} diff --git a/setup-wizard.yml b/setup-wizard.yml new file mode 100644 index 0000000..1671fa3 --- /dev/null +++ b/setup-wizard.yml @@ -0,0 +1,33 @@ +version: "2" +fields: + - id: GRAFFITI + target: + type: environment + name: GRAFFITI + service: validator + title: Graffiti + maxLength: 32 + description: >- + Add a string to your proposed blocks, which will be seen on the block explorer + - id: checkpointSyncUrl + target: + type: environment + name: CHECKPOINT_SYNC_URL + service: beacon-chain + title: Checkpoint for fast sync + description: >- + To get Prysm up and running in only a few minutes, you can start Prysm from a recent finalized checkpoint state rather than syncing from genesis. This is substantially **faster** and consumes **less resources** than syncing from genesis, while still providing all the same features. Be sure you are using a trusted node for the fast sync. Check the [Prysm docs](https://docs.prylabs.network/docs/prysm-usage/checkpoint-sync) for more information. + Use the Dappnode Official endpoint `https://checkpoint-sync.dappnode.io` or get your checkpoint sync from [Infura](https://infura.io/) (i.e https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX@eth2-beacon.infura.io) + *Note - If you are going to provide your own checkpoint sync endpoint, make sure you do not use a slash `/` at the end of the URL.* + required: false + - id: feeRecipientAddress + target: + type: environment + name: FEE_RECIPIENT + service: [beacon-chain, validator] + title: Fee Recipient Address + description: >- + Fee Recipient is a feature that lets you specify a priority fee recipient address on your validator client instance and beacon node. Make sure this is an address you control. After The Merge, Execution Clients will begin depositing priority fees into this address whenever your validator proposes a new block. + required: true + pattern: "^0x[a-fA-F0-9]{40}$" + patternErrorMessage: Must be a valid address (0x1fd16a...) diff --git a/validator/Dockerfile b/validator/Dockerfile new file mode 100644 index 0000000..a7d97ad --- /dev/null +++ b/validator/Dockerfile @@ -0,0 +1,31 @@ +ARG UPSTREAM_VERSION +FROM gcr.io/prysmaticlabs/prysm/validator:${UPSTREAM_VERSION} + +ARG NETWORK +ARG STAKER_SCRIPTS_VERSION +ARG DATA_DIR=/root/.eth2validators +ARG WALLET_DIR=/root/.eth2validators/prysm-wallet-v2 + +RUN mkdir -p ${WALLET_DIR} + +COPY auth-token ${WALLET_DIR}/auth-token +COPY entrypoint.sh /usr/local/bin/entrypoint.sh + +ENV VALIDATOR_PORT=3500 \ + DATA_DIR=${DATA_DIR} \ + WALLET_DIR=${WALLET_DIR} \ + NETWORK=${NETWORK} \ + LUKSO_CONFIG_PATH=/configs/lukso/shared/config.yaml \ + STAKER_SCRIPTS_URL=https://github.com/dappnode/staker-package-scripts/releases/download/${STAKER_SCRIPTS_VERSION} \ + LUKSO_CONFIG_URL=https://raw.githubusercontent.com/lukso-network/network-configs/main/mainnet/shared/config.yaml + +ADD ${STAKER_SCRIPTS_URL}/consensus_tools.sh /etc/profile.d/ + +RUN chmod +rx /usr/local/bin/entrypoint.sh /etc/profile.d/consensus_tools.sh + +RUN if [ "${NETWORK}" = "lukso" ]; then \ + mkdir -p $(dirname ${LUKSO_CONFIG_PATH}) && \ + wget ${LUKSO_CONFIG_URL} -O ${LUKSO_CONFIG_PATH}; \ + fi + +ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ] \ No newline at end of file diff --git a/validator/auth-token b/validator/auth-token new file mode 100644 index 0000000..783a085 --- /dev/null +++ b/validator/auth-token @@ -0,0 +1,2 @@ +b5bbbaf533b625a93741978857f13d7adeca58445a1fb00ecf3373420b92776c +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.MxwOozSH-TLbW_XKepjyYDHm2IT8Ki0tD3AHuajfNMg \ No newline at end of file diff --git a/validator/entrypoint.sh b/validator/entrypoint.sh new file mode 100755 index 0000000..e9a35fd --- /dev/null +++ b/validator/entrypoint.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +SUPPORTED_NETWORKS="sepolia lukso holesky mainnet" +MEVBOOST_FLAG="--enable-builder" +SKIP_MEVBOOST_URL="true" +CLIENT="prysm" + +handle_network() { + case "$NETWORK" in + "holesky") + set_validator_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "${CLIENT}" "--holesky" + ;; + "lukso") + set_validator_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "${CLIENT}" "--chain-config-file=$LUKSO_CONFIG_PATH" + ;; + "mainnet") + set_validator_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "${CLIENT}" "--mainnet" + ;; + "sepolia") + set_validator_config_by_network "${NETWORK}" "${SUPPORTED_NETWORKS}" "${CLIENT}" "--sepolia" + ;; + *) + echo "[ERROR - entrypoint] Unsupported network: $NETWORK" + exit 1 + ;; + esac +} + +get_beacon_rpc_url() { + + beacon_domain_and_protocol=$(echo "$BEACON_API_URL" | cut -d':' -f1,2) + + BEACON_RPC_4000="${beacon_domain_and_protocol}:4000" +} + +run_validator() { + echo "[INFO - entrypoint] Running validator service" + + # shellcheck disable=SC2086 + exec /validator \ + --datadir="${DATA_DIR}" \ + --wallet-dir="${WALLET_DIR}" \ + --monitoring-host 0.0.0.0 \ + --beacon-rpc-provider="${BEACON_API_URL}" \ + --beacon-rpc-gateway-provider="${BEACON_RPC_4000}" \ + --validators-external-signer-url="${WEB3SIGNER_API_URL}" \ + --grpc-gateway-host=0.0.0.0 \ + --grpc-gateway-port="${VALIDATOR_PORT}" \ + --grpc-gateway-corsdomain=http://0.0.0.0:"${VALIDATOR_PORT}" \ + --graffiti="${GRAFFITI}" \ + --suggested-fee-recipient="${FEE_RECIPIENT}" \ + --verbosity="${VERBOSITY}" \ + --web \ + --accept-terms-of-use \ + --enable-doppelganger ${EXTRA_OPTS} +} + +format_graffiti +handle_network +get_beacon_rpc_url +set_mevboost_flag "${MEVBOOST_FLAG}" "${SKIP_MEVBOOST_URL}" +run_validator