├── LICENSE ├── README.md ├── agave-beginners-guide.md ├── building-solana-from-source.md ├── setting-up-a-solana-devnet-validator.md ├── solana-benchmarks.md ├── solana-validator-faq.md └── staking-on-solana.md /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hello 2 | 3 | The tutorials I've published here were initially made for myself. I made them to help me remember the tasks I performed to set up and maintain my Solana devnet validator. Then I figured they could also benefit others. Please note that I am a Linux novice, so I really have no idea what I’m talking about in most of these tutorials. I will not be held responsible for the shipwreck your system may or may not be after following any of the instructions here. Still, I have tried my best to provide correct, understandable and user friendly information. 4 | 5 | Most of the information here is compiled from the official [Solana docs](https://docs.solana.com/) and the replies I’ve gotten from helpful people in the [Solana Discord](https://solana.com/discord). Since setting up my first validator I have become quite involved with the community. Come find me and other helpful people in the Discord to resolve any issues you may have. My username is [@agjell](https://discordapp.com/users/242641884680421376) and my display name is `andrebo ⭐ nordstar.one`). 6 | 7 | # My validators 8 | 9 | Mainnet || 10 | :--------------|- 11 | Name | [nordstar.one](https://nordstar.one/) 12 | Identity | NordEHiwa6wT5TCjdeWJzpsA7DSmWQPqfSS7m2b6cv3 13 | Vote account | NoRDTy8jpkpjPR7yxahVdoEUPngbojPhFU5jb8TtY4m 14 | Solana Beach | [Link](https://solanabeach.io/validator/NoRDTy8jpkpjPR7yxahVdoEUPngbojPhFU5jb8TtY4m) 15 | Validators.app | [Link](https://www.validators.app/validators/NordEHiwa6wT5TCjdeWJzpsA7DSmWQPqfSS7m2b6cv3?network=mainnet) 16 | 17 | Testnet || 18 | :--------------|- 19 | Identity | 4jhyvbBHbsRDF6och7pDQ7ahYTUr7wNkAYJTLLuMUtku 20 | Vote account | B1PPUQyKFTsQMC3yy8tw16wkrZhZX4btdLS3s7KJFNT 21 | Validators.app | [Link](https://www.validators.app/validators/4jhyvbBHbsRDF6och7pDQ7ahYTUr7wNkAYJTLLuMUtku?network=testnet) 22 | -------------------------------------------------------------------------------- /agave-beginners-guide.md: -------------------------------------------------------------------------------- 1 | # Beginners guide to setting up a Solana validator (Agave) 2 | 3 | 1. [Introduction](#1-introduction) 4 | 2. [Hardware requirements](#2-hardware-requirements) 5 | 3. [Install and configure Ubuntu server](#3-install-and-configure-ubuntu-server) 6 | 4. [Create an unprivileged user](#4-create-an-unprivileged-user) 7 | 5. [Install and configure Agave](#5-install-and-configure-agave) 8 | 6. [Create keypairs](#6-create-keypairs) 9 | 7. [Create startup script](#7-create-startup-script) 10 | 8. [Create validator service](#8-create-validator-service) 11 | 9. [Tune system settings](#9-tune-system-settings) 12 | 10. [Set up log rotation](#10-set-up-log-rotation) 13 | 11. [Start the validator](#11-start-the-validator) 14 | 12. [Monitor the validator](#12-monitor-the-validator) 15 | 16 | 17 | ## 1. Introduction 18 | 19 | This tutorial is for Solana beginners. It is a rewritten and updated version of my original [devnet validator tutorial](https://github.com/agjell/sol-tutorials/blob/master/setting-up-a-solana-devnet-validator.md). I've adapted this one for the Agave validator client, and have tested it on a fresh install of Ubuntu 24.04.2 LTS. The process is applicable for mainnet, testnet and devnet, but must be adapted by the user accordingly. I have used **mainnet** as an example throughout. Please post an issue if something is not working as expected! 20 | 21 | 22 | ## 2. Hardware requirements 23 | 24 | Follow by the hardware requirements in the [official docs](https://docs.anza.xyz/operations/requirements) for mainnet, testnet and devnet, respectively. You may also have a look at the community maintained [Solana Hardware Compatibility List](https://solanahcl.org/). This tutorial assumes a setup with three SSDs, which is the minimum recommendation for a mainnet validator. 25 | 26 | 27 | ## 3. Install and configure Ubuntu server 28 | 29 | First you need to [install Ubuntu server](https://documentation.ubuntu.com/server/tutorial/basic-installation/). Remember to check `[X] Install OpenSSH server` during the Ubuntu installation if you want to access your validator remotely. If you forget it during the main installation you can follow [this](https://documentation.ubuntu.com/server/how-to/security/openssh-server/index.html) guide afterwards. You can read about how to connect to the server remotely over SSH [here](https://www.howtogeek.com/311287/how-to-connect-to-an-ssh-server-from-windows-macos-or-linux/). 30 | 31 | The first thing I do after logging in to a fresh install is to update it: 32 | ```bash 33 | sudo apt update && sudo apt upgrade --assume-yes 34 | ``` 35 | 36 | ### A note about partitioning 37 | 38 | You will need to partition, format and mount any extra SSDs. If you don't know how, the internet is your friend. I will give you a few pointers, though. In my opinion, the easiest way to partition is by choosing `(X) Custom storage layout` during the Ubuntu installation. If you end up doing it after the installation, the process usually involves the following tools: [`lsblk`](https://manpages.ubuntu.com/manpages/noble/en/man8/lsblk.8.html), [`fdisk`](https://manpages.ubuntu.com/manpages/noble/en/man8/fdisk.8.html), [`mkfs`](https://manpages.ubuntu.com/manpages/noble/en/man8/mkfs.8.html), [`blkid`](https://manpages.ubuntu.com/manpages/noble/en/man8/blkid.8.html), [`fstab`](https://manpages.ubuntu.com/manpages/noble/en/man5/fstab.5.html), and [`mount`](https://manpages.ubuntu.com/manpages/noble/en/man8/mount.8.html). 39 | 40 | I have added an example of a functional partition layout with a corresponding `/etc/fstab` configuration below, based on three NVMe SSDs: 41 | - One for system, home, snapshots and swap 42 | - One for accounts data 43 | - One for ledger data 44 | 45 | #### Functional partition layout: 46 | ``` 47 | $ lsblk 48 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS 49 | nvme1n1 259:4 0 3.5T 0 disk 50 | └─nvme1n1p1 259:0 0 3.5T 0 part /mnt/accounts 51 | nvme2n1 259:7 0 3.5T 0 disk 52 | └─nvme2n1p1 259:8 0 3.5T 0 part /mnt/ledger 53 | nvme3n1 259:6 0 3.5T 0 disk 54 | ├─nvme3n1p1 259:9 0 1G 0 part /boot/efi 55 | ├─nvme3n1p2 259:10 0 200G 0 part / 56 | ├─nvme3n1p3 259:11 0 1T 0 part /home 57 | ├─nvme3n1p4 259:12 0 1.8T 0 part /mnt/snapshots 58 | └─nvme3n1p5 259:13 0 500G 0 part [SWAP] 59 | ``` 60 | The large swap partition is not required. It is a safety valve, however, and will give you more time to act if the validator is about to run out of memory (OOM). 61 | 62 | #### Functional fstab configuration: 63 | ``` 64 | $ cat /etc/fstab 65 | # 66 | UUID=0F93-AAF9 /boot/efi vfat defaults 0 1 67 | UUID=011e5bee-d1f8-43fc-aeb4-2af3a65df7ac / ext4 defaults 0 1 68 | UUID=abe402c4-ad18-4cce-9a53-e0a84189fc21 /home ext4 noatime 0 2 69 | UUID=67506fe9-4226-4c06-a5e1-4c16479735ac /mnt/accounts ext4 noatime 0 0 70 | UUID=79332ac3-56b2-406c-9e64-3fbf0860f906 /mnt/snapshots ext4 noatime 0 0 71 | UUID=38bb59b1-c07c-4e02-9c1f-f512d2d92d07 /mnt/ledger ext4 noatime 0 0 72 | UUID=48f7f4ef-a475-4964-b2c2-277e1601ba98 none swap sw 0 0 73 | ``` 74 | 75 | 76 | ## 4. Create an unprivileged user 77 | 78 | During the Ubuntu installation you created a user with root privileges; a user that can perform `sudo` commands. This user is needed to administer the system. However, the Agave validator client does not require root privileges, and it is considered poor practice to run Agave as “root" or as another privileged user. You should therefore create an unprivileged user to run the validator client. For example the user "sol": 79 | ```bash 80 | sudo adduser sol 81 | ``` 82 | 83 | Then you can switch to the new user account by running: 84 | ```bash 85 | sudo su - sol 86 | ``` 87 | 88 | To get back to the admin user account you simply run: 89 | ```bash 90 | exit 91 | ``` 92 | 93 | Using the `su` command makes it easy to switch between users without having to log out and back in. You can also open two separate terminal windows, each logged in as separate users. I have highlighted the applicable user account for each chapter below. 94 | 95 | 96 | ## 5. Install and configure Agave 97 | 98 | ```diff 99 | ! Perform as user “sol” 100 | ``` 101 | 102 | You can either install the prebuilt binaries or build your own binaries. In this tutorial we're installing the prebuilt binaries, as this is the easiest way to get going. If you prefer building your own binaries from source you can check out my tutorial [here](https://github.com/agjell/sol-tutorials/blob/master/building-solana-from-source.md). 103 | 104 | You should first check the officially recommended version in Discord for either [mainnet](https://discord.com/channels/428295358100013066/669406841830244375), [testnet](https://discord.com/channels/428295358100013066/594138785558691840) or [devnet](https://discord.com/channels/428295358100013066/749059399875690557). Replace the version number in the command below with the recommendation from Discord. You can also find the most recent installation command in the [Agave docs](https://docs.anza.xyz/cli/install), but the version provided there is usually **not recommended** for mainnet. 105 | ```bash 106 | sh -c "$(curl -sSfL https://release.anza.xyz/v2.2.15/install)" 107 | ``` 108 | 109 | After the installation is complete, close and reopen the terminal or log out and in again (as “sol”). This is done to load the environment variable that was added to `~/.profile` during the installation, which enables "sol" to run the `solana` and `agave` commands from any directory. 110 | 111 | Then configure the Agave client to target a cluster. You can specify "testnet" or "devnet" as well. 112 | ```bash 113 | solana config set --url mainnet-beta 114 | ``` 115 | 116 | Verify that the cluster is reachable by running a command. For example: 117 | ```bash 118 | solana gossip 119 | ``` 120 | It should return a list of validators. 121 | 122 | You can get information about any command by running `command --help` or `command subcommand --help`. For example 123 | ```bash 124 | solana --help 125 | ``` 126 | ```bash 127 | solana config --help 128 | ``` 129 | 130 | ## 6. Create keypairs 131 | 132 | ```diff 133 | ! Perform as user “sol” 134 | ``` 135 | 136 | To run a validator you need three keypairs. These represent accounts that the validator use to interact with Solana. All accounts have a public key associated with them, which identifies the account in the system. The keypairs needed are 137 | 138 | - a wallet keypair, which 139 | - is used to transfer voting funds to the validator 140 | - is used to withdraw rewards from the vote account 141 | - a validator identity keypair, which 142 | - represent your validators identity 143 | - pays voting fees 144 | - signs transactions 145 | - a voting account keypair, which 146 | - is used for voting by the validator 147 | - receives validator rewards 148 | 149 | When you run the command to create a keypair, you are prompted to enter a passphrase. The client then returns a pubkey (public key) and a seed phrase in the terminal. You **must** store both the passphrase and the seed phrase securely, as these are required to recreate the keypair in the future. Do not give your passphrase, seed phrase or keypair to anyone! 150 | 151 | ### Wallet 152 | 153 | First create the wallet keypair: 154 | ```bash 155 | solana-keygen new --outfile ~/wallet-keypair.json 156 | ``` 157 | 158 | ### Validator identity 159 | 160 | Second, create the validator identity keypair: 161 | ```bash 162 | solana-keygen new --outfile ~/validator-keypair.json 163 | ``` 164 | 165 | Which can also be appended to the client configuration: 166 | ```bash 167 | solana config set --keypair ~/validator-keypair.json 168 | ``` 169 | 170 | Because the validator pays the voting fees, you will need to transfer some SOL to its identity account (pubkey). There are many ways to do this. This is an example of how to transfer 1 SOL from the wallet to the validator, where the the transaction fee is deducted from the wallet: 171 | ```bash 172 | solana transfer --allow-unfunded-recipient \ 173 | --fee-payer ~/wallet-keypair.json \ 174 | --from ~/wallet-keypair.json ~/validator-keypair.json 1 175 | ``` 176 | 177 | You can check the account balance by running: 178 | ```bash 179 | solana balance ~/validator-keypair.json 180 | ``` 181 | 182 | ### Vote account 183 | 184 | Third, create the vote account keypair: 185 | ```bash 186 | solana-keygen new --outfile ~/vote-account-keypair.json 187 | ``` 188 | 189 | Then you need to register the account as a vote account on the blockchain, and set an authorized withdrawer. In this example the transaction fee is deducted from the validator keypair, and the wallet is set as the authorized withdrawer: 190 | ```bash 191 | solana create-vote-account \ 192 | --fee-payer ~/validator-keypair.json \ 193 | ~/vote-account-keypair.json ~/validator-keypair.json ~/wallet-keypair.json 194 | ``` 195 | That's it for keypairs! 196 | 197 | ## 7. Create startup script 198 | 199 | Next up is to create a shell script that contains all the flags and options needed for your validator. The script will be executed by a system service, which you're going to set up later. 200 | 201 | ```diff 202 | ! Perform as user “sol” 203 | ``` 204 | 205 | Create the `start-validator.sh` script inside the home directory (`~/`) of “sol”: 206 | ```bash 207 | tee ~/start-validator.sh > /dev/null < /dev/null < /dev/null < 346 | * - nofile 2000000 347 | EOT 348 | ``` 349 | 350 | ```bash 351 | sudo tee /etc/sysctl.d/20-solana.conf > /dev/null < /dev/null <`. I replace "version" with the latest **mainnet** version number from the Agave [GitHub](https://github.com/anza-xyz/agave/releases) page: 54 | ```bash 55 | git clone https://github.com/anza-xyz/agave.git --depth 1 --branch v2.2.15 ~/agave-src-v2.2.15 56 | ``` 57 | 58 | Then I run the `cargo-install-all.sh` script to build and install Agave. I assign `~/.local/share/solana/install/releases/2.2.15` as my installation directory, to mimic the directory structure of the pre-built binaries. 59 | ```bash 60 | bash ~/agave-src-v2.2.15/scripts/cargo-install-all.sh ~/.local/share/solana/install/releases/2.2.15 61 | ``` 62 | The script will automatically check for dependencies and download any that are missing. The build process will take some time. When it's done it provides a PATH variable for the binaries. I ignore this, as I make a more useful one in the following step. 63 | 64 | When installing the *pre-built* binaries, the installer automatically creates a symbolic link from the installation directory (`*/2.2.15`) to another directory (`*/active_release`). This link can be used in service files and environment variables, so these won't have to be amended on every Agave update. When building from source I have to create that link manually: 65 | ```bash 66 | ln --symbolic ~/.local/share/solana/install/releases/2.2.15 ~/.local/share/solana/install/active_release 67 | ``` 68 | 69 | To make sure I can run the binaries from any directory I need to add a PATH variable to `~/.profile`. Note that I use the symbolic link from above here: 70 | ```bash 71 | echo 'export PATH=~/.local/share/solana/install/active_release/bin:$PATH' >> ~/.profile 72 | ``` 73 | 74 | ### Finishing steps 75 | 76 | At this point I usually log out and back in again (to reload `~/.profile`), and run a command to verify that the client is working: 77 | ```bash 78 | solana --version 79 | ``` 80 | 81 | The system should respond with the version I just installed. If it doesn't, I retrace my steps and trouble-shoot. If everything is working as expected I delete the source directory: 82 | ```bash 83 | rm -rf ~/agave-src-v2.2.15 84 | ``` 85 | Installation complete! The remaining configuration may be done with the help of my [setup tutorial](https://github.com/agjell/sol-tutorials/blob/master/setting-up-a-solana-devnet-validator.md#configure-solana). 86 | 87 | 88 | ## Update an existing installation 89 | ```diff 90 | ! Perform as unprivileged user (for example "sol") 91 | ``` 92 | 93 | Updating an existing (self built) Agave installation largely follows the same procedure as the initial install. Below I will repeat the necessary steps from above, but spare you the explanations. For the sake of ease, you may also jump straight to the [all-in-one command](#all-in-one-build-command). 94 | 95 | First I clone the new release (find the most recent one on [GitHub](https://github.com/anza-xyz/agave/releases)): 96 | ```bash 97 | git clone https://github.com/anza-xyz/agave.git --depth 1 --branch v2.2.15 ~/agave-src-v2.2.15 98 | ``` 99 | 100 | Followed by the build and installation process: 101 | ```bash 102 | bash ~/agave-src-v2.2.15/scripts/cargo-install-all.sh ~/.local/share/solana/install/releases/2.2.15 103 | ``` 104 | 105 | Next I replace the symbolic link, pointing it to the new installation. I need to use `--force` and `--no-dereference` to overwrite the old link: 106 | ```bash 107 | ln --force --no-dereference --symbolic \ 108 | ~/.local/share/solana/install/releases/2.2.15 ~/.local/share/solana/install/active_release 109 | ``` 110 | 111 | Then I run a command to verify that the client is working: 112 | ```bash 113 | solana --version 114 | ``` 115 | 116 | If it replies with the updated version tag I delete the source files: 117 | ```bash 118 | rm -rf ~/agave-src-v2.2.15 119 | ``` 120 | 121 | Update complete! After a few days of stable operation I delete the binaries from the previous build. 122 | 123 | 124 | ## All-in-one build command 125 | 126 | Lastly, I have combined all the necessary commands to build/update Agave into one. This command presumes I have already installed Rust and the required dependencies. Here I first define an environment variable "TAG" with the version I want to build. This version is then called by all the consecutive commands. 127 | 128 | ```bash 129 | export TAG=v2.2.15 && \ 130 | git clone https://github.com/anza-xyz/agave.git --depth 1 --branch $TAG ~/agave-src-$TAG && \ 131 | bash ~/agave-src-$TAG/scripts/cargo-install-all.sh ~/.local/share/solana/install/releases/$TAG && \ 132 | ln --force --no-dereference --symbolic ~/.local/share/solana/install/releases/$TAG ~/.local/share/solana/install/active_release && \ 133 | solana --version 134 | ``` 135 | 136 | If you are only building binaries for a validator you can append the `--validator-only` flag to `cargo-install-all.sh`. By doing this the build process completes faster, because less binaries are built. Like this: 137 | ```bash 138 | export TAG=v2.2.15 && \ 139 | git clone https://github.com/anza-xyz/agave.git --depth 1 --branch $TAG ~/agave-src-$TAG && \ 140 | bash ~/agave-src-$TAG/scripts/cargo-install-all.sh --validator-only ~/.local/share/solana/install/releases/$TAG && \ 141 | ln --force --no-dereference --symbolic ~/.local/share/solana/install/releases/$TAG ~/.local/share/solana/install/active_release && \ 142 | solana --version 143 | ``` 144 | 145 | That's it! 146 | -------------------------------------------------------------------------------- /setting-up-a-solana-devnet-validator.md: -------------------------------------------------------------------------------- 1 | # This tutorial is outdated and replaced with a new beginners guide [here](https://github.com/agjell/sol-tutorials/blob/master/agave-beginners-guide.md). The information below will not be updated. 2 | 3 | # Setting up a Solana devnet validator 4 | 5 | 1. [Introduction](#introduction) 6 | 2. [Hardware requirements](#hardware-requirements) 7 | 3. [Install Ubuntu server](#install-ubuntu-server) 8 | 4. [Create RAM disk and swap spillover (optional)](#create-ram-disk-and-swap-spillover-optional) 9 | 5. [Install Solana](#install-solana) 10 | 6. [Configure Solana](#configure-solana) 11 | 7. [Create startup script and system service](#create-startup-script-and-system-service) 12 | 8. [Set up log rotation (optional)](#set-up-log-rotation-optional) 13 | 9. [Starting the validator](#starting-the-validator) 14 | 10. [Useful commands](#useful-commands) 15 | 16 | 17 | ## Introduction 18 | 19 | Setting up a devnet validator was the first thing I did to become familiar with Solana. I started by following the [official documentation](https://docs.solana.com/running-validator), and asked people in the [Solana Discord](https://solana.com/discord) when I stubled into issues. The official docs were a bit outdated when I set up for the first time. This is to be expected in a rapidly developing project, as code development is usually prioritized higher than documentation. To simplify the setup process for myself later, I decided to make this detailed step-by-step tutorial. Hopefully it can be useful to others as well. 20 | 21 | If you have general questions about running a validator, you may find answers to them in my unofficial [FAQ](https://github.com/agjell/sol-tutorials/blob/master/solana-validator-faq.md). 22 | 23 | 24 | ## Hardware requirements 25 | 26 | Running a devnet validator does not require a high end system. This makes devnet an ideal playground to experiment and get to know Solana, before considering a mainnet setup. Hardware requirements for mainnet are _a lot_ higher, and can be found [here](https://docs.solana.com/running-validator/validator-reqs). My devnet validator was running on an old computer with a quad core CPU, 16 GB RAM and a 256 GB SATA SSD. 27 | 28 | You _will_ need an SSD, as a mechanical drive will not be able to handle the amount of IOPS (input/output operations per second) that Solana demands. SATA SSDs may be usable in devnet. Running testnet and mainnet validators requires NVMe SSDs with high speed, high IOPS and high endurance ratings. 29 | 30 | If you have a very old CPU you may need to [build Solana from source](https://github.com/agjell/sol-tutorials/blob/master/building-solana-from-source.md). Be aware of this if the prebuilt binaries crash at launch. The prebuilt binaries should run in most modern systems without problems, though. 31 | 32 | 33 | ## Install Ubuntu server 34 | 35 | First we need to [install Ubuntu server](https://ubuntu.com/tutorials/install-ubuntu-server). The installation can be downloaded from [their website](https://ubuntu.com/download/server). You can use [Rufus](https://rufus.ie/) to create a bootable USB drive for installing Ubuntu (tutorial [here](https://ubuntu.com/tutorials/create-a-usb-stick-on-windows)). 36 | 37 | Remember to tick off on “Install OpenSSH server” during the Ubuntu installation process if you want to access your validator remotely. If you forget it during the main installation you can follow [this](https://ubuntu.com/server/docs/service-openssh) guide afterwards. You can read about how to connect to the server remotely over SSH [here](https://www.howtogeek.com/311287/how-to-connect-to-an-ssh-server-from-windows-macos-or-linux/). 38 | 39 | The first thing I do after logging into a fresh installation is to install updates: 40 | ```bash 41 | sudo apt update && sudo apt upgrade --assume-yes 42 | ``` 43 | 44 | Solana does not require root privileges, and It is considered poor practice to run Solana as “root". It’s also considered good to practice the principle of least privilege. This basically means that no user, process or application should ever have higher privileges than they need to fulfill their intended purpose. I therefore create a new user, “sol", which will be running the validator service as a regular user: 45 | ```bash 46 | sudo adduser sol 47 | ``` 48 | 49 | After creating the new user, I use that account as my “base”. By that I mean that I always log in as “sol” initially. If I need to run a command that require root privileges, I switch to an account with those privileges by running `su - username` from the console. Replace “username” with whatever username you assigned during the Ubuntu installation. To get back to the “sol” account I run `exit` in the console. This makes it easy to switch between users without having to log out and back in. Some of the instructions below require root privileges, but I have written where that applies. 50 | 51 | 52 | ## Create RAM disk and swap spillover (optional) 53 | 54 | As I mentioned above, Solana require a high amount of IOPS. This is especially true for processing accounts data. To reduce wear on my SSD I prefer storing accounts in a [RAM disk](https://en.wikipedia.org/wiki/RAM_drive). Especially since I’m already using an old and worn SSD, which may fail at any time. 55 | 56 | The steps in this section are optional, and only concern storage for the accounts data (contrary to the ledger data, also known as “rocksdb”). If you would rather store accounts on an SSD, skip to “Install Solana” further below. 57 | 58 | ### Create RAM disk 59 | 60 | ```diff 61 | ! Perform as user with root privileges 62 | ``` 63 | 64 | The RAM disk will act as the primary storage for accounts. To create it, I first have to create a [mount point](https://help.ubuntu.com/community/Mount): 65 | ```bash 66 | sudo mkdir /mnt/ramdisk 67 | ``` 68 | 69 | Second, I append the RAM disk configuration in [fstab](https://help.ubuntu.com/community/Fstab) to make it permanent (i.e. appear on system boot). Access is limited to the user “sol”, and size set to 16 GB, as this is currently more than enough for devnet accounts data: 70 | ```bash 71 | echo 'tmpfs /mnt/ramdisk tmpfs rw,noexec,nodev,nosuid,noatime,size=16G,user=sol 0 0' | \ 72 | sudo tee --append /etc/fstab > /dev/null 73 | ``` 74 | 75 | Then I reload fstab and mount all entries: 76 | ```bash 77 | sudo mount --all --verbose 78 | ``` 79 | 80 | ### Create a swap spillover file 81 | 82 | ```diff 83 | ! Perform as user with root privileges 84 | ``` 85 | 86 | In some cases my system may need more RAM than I have available. For those cases I need a [swap](https://help.ubuntu.com/community/SwapFaq) file that can act as reserve. If RAM utilization expands beyond my physical RAM, the excess data will spill over into swap and ensure the validator can continue running. 87 | 88 | Any spillover into swap should be temporary, so I usually monitor if the RAM disk and swap space starts filling up. If that happens there is likely something wrong. 89 | 90 | Ubuntu server creates a swap file by default, but I want a bigger one to ensure I have enough space. So I delete the existing one and create a new one. To do this, I first fetch a list of the current swap files in the system: 91 | ```bash 92 | sudo swapon --show 93 | ``` 94 | 95 | My system replies: 96 | ``` 97 | NAME TYPE SIZE USED PRIO 98 | /swap.img file 4G 0B -2 99 | ``` 100 | 101 | I can see there's a 4 GB swap file called `/swap.img`. Let's disable it: 102 | ```bash 103 | sudo swapoff /swap.img 104 | ``` 105 | 106 | And delete the leftover file: 107 | ```bash 108 | sudo rm /swap.img 109 | ``` 110 | 111 | I also need to delete delete the reference to `swap.img` from fstab: 112 | ```bash 113 | sudo sed --in-place '/swap.img/d' /etc/fstab 114 | ``` 115 | 116 | Then I create a new swap file that will hold 16 GB: 117 | ```bash 118 | sudo dd if=/dev/zero of=/swapfile bs=1M count=16K 119 | ``` 120 | 121 | I need to set permissions for it to ensure access is limited to “root”: 122 | ```bash 123 | sudo chmod 600 /swapfile 124 | ``` 125 | 126 | And configure the file as a swap area: 127 | ```bash 128 | sudo mkswap /swapfile 129 | ``` 130 | 131 | For the swap area to appear on every system boot I need to add it to fstab: 132 | ```bash 133 | echo '/swapfile none swap sw 0 0' | sudo tee --append /etc/fstab > /dev/null 134 | ``` 135 | 136 | To ensure the system is using RAM as much as possible, and swap as little as possible, I decrease “[swappiness](https://help.ubuntu.com/community/SwapFaq#What_is_swappiness_and_how_do_I_change_it.3F)” to 1 and reload `sysctl`. This is probably not needed in a modern system. I only do this to protect my worn SSD. 137 | ```bash 138 | echo 'vm.swappiness=1' | sudo tee --append /etc/sysctl.conf > /dev/null 139 | ``` 140 | ```bash 141 | sudo sysctl --load 142 | ``` 143 | 144 | Finally I enable all swaps from fstab by running: 145 | ```bash 146 | sudo swapon --all --verbose 147 | ``` 148 | I have now created the RAM disk and swap file, and can move to the installation phase. 149 | 150 | ## Install Solana 151 | 152 | As I mentioned above, you can either install the prebuilt binaries or build your own binaries. I have only included instructions to install the prebuilt binaries in this tutorial, as this will work for most people. However, I have also made a tutorial on building binaries from source, which you can find [here](https://github.com/agjell/sol-tutorials/blob/master/building-solana-from-source.md). 153 | 154 | ### Install prebuilt binaries 155 | 156 | ```diff 157 | ! Perform as user “sol” 158 | ``` 159 | 160 | This is by far the easiest way to install Solana. Check for the most recent version on [GitHub](https://github.com/solana-labs/solana/releases/latest), and replace the version number in the command below. You can also copy the most recent installation command from the [Solana docs](https://docs.solana.com/cli/install-solana-cli-tools#use-solanas-install-tool). 161 | ```bash 162 | sh -c "$(curl -sSfL https://release.solana.com/v1.16.20/install)" 163 | ``` 164 | 165 | After the installation is complete I close and reopen the terminal, or log out and in again (as “sol”). I do this to enable the environment variables that were added to `~/.profile` during the installation. These tell the system to look for binaries in the Solana installation directory, so I can run the Solana commands from any directory in the system. 166 | 167 | ## Configure Solana 168 | 169 | In this section I’ll connect the validator to the Solana network and set up the necessary accounts. 170 | 171 | ### Joining devnet 172 | 173 | First I configure Solana to connect to devnet: 174 | ```bash 175 | solana config set --url devnet 176 | ``` 177 | 178 | Then I verify that the cluster is reachable by running a random command. For example: 179 | ```bash 180 | solana gossip 181 | ``` 182 | It should reply with a list of validators. 183 | 184 | ### Setting up accounts 185 | 186 | The account structure can be a bit confusing, but this is how I understand it (I may be wrong). There are four account types: system accounts, voting accounts, staking accounts and nonce accounts. Each account type has different properties, that I won’t go into here (mostly because I have no clue). The system account is the default type. All accounts have a public key associated with them, which identifies them in the system. For a new devnet validator I usually create two system accounts and a voting account (I won't cover staking accounts or nonce accounts). Specifically: 187 | 188 | - a wallet (system account), which 189 | - simulates the owners' wallet 190 | - is used to transfer voting funds to the validator 191 | - is used to withdraw rewards from the vote account 192 | - a validator identity (system account), which 193 | - represents the validators identity 194 | - pays voting fees 195 | - signs transactions 196 | - a voting account, which 197 | - is used for voting by the validator 198 | - receives validator rewards 199 | 200 | When creating system accounts and voting accounts we need to provide a password. Each account creation produce a keypair file, and Solana provides us with the accounts' public key and seed phrase. The seed phrase is needed to recover a lost account (e.g. if you delete the keypair or lose the password). I usually store everything securely in a password manager, like [Bitwarden](https://bitwarden.com/) or [KeePass](https://keepass.info/ "https://keepass.info/"). 201 | 202 | #### Wallet 203 | 204 | Let’s get started. I first create the wallet: 205 | ```bash 206 | solana-keygen new --outfile ~/wallet-keypair.json 207 | ``` 208 | 209 | Then I airdrop 1 SOL into it (this black magic is not possible on mainnet, for obvious reasons): 210 | ```bash 211 | solana airdrop 1 ~/wallet-keypair.json 212 | ``` 213 | 214 | Solana replies with the balance, but we can verify the balance manually like this: 215 | ```bash 216 | solana balance ~/wallet-keypair.json 217 | ``` 218 | 219 | #### Validator identity 220 | 221 | Second is the validator identity: 222 | ```bash 223 | solana-keygen new --outfile ~/validator-keypair.json 224 | ``` 225 | 226 | Which I need to assign to my Solana configuration: 227 | ```bash 228 | solana config set --keypair ~/validator-keypair.json 229 | ``` 230 | 231 | Because the validator pays the voting fees, I need to give it some SOL. I can either airdrop or transfer to it. To simulate a real life operation I will transfer 0.5 SOL from the wallet: 232 | ```bash 233 | solana transfer --allow-unfunded-recipient \ 234 | --fee-payer ~/wallet-keypair.json \ 235 | --from ~/wallet-keypair.json ~/validator-keypair.json 0.5 236 | ``` 237 | 238 | Then I can check the validator account balance. Note that we don't need to provide the account identity here, because Solana uses the one from the configuration (that we just set): 239 | ```bash 240 | solana balance 241 | ``` 242 | 243 | #### Vote account 244 | 245 | Third is the vote account: 246 | ```bash 247 | solana-keygen new --outfile ~/vote-account-keypair.json 248 | ``` 249 | 250 | Then I tell Solana that this is a vote account, so it inherits the properties of that account type. I also set my wallet as an authorized withdrawer: 251 | ```bash 252 | solana create-vote-account \ 253 | ~/vote-account-keypair.json ~/validator-keypair.json ~/wallet-keypair.json 254 | ``` 255 | That's it for accounts! 256 | 257 | ## Create startup script and system service 258 | 259 | To launch the Solana validator I’m using a shell script that contains all the flags and options needed for my configuration (a “wrapper” script). The script is executed by a system service, which ensures that Solana starts automatically on every boot and reboot. To ensure smooth validator operation I also have to do some necessary system tuning. Below I will take you through how I set all that up. 260 | 261 | ### Create wrapper script 262 | 263 | ```diff 264 | ! Perform as user “sol” 265 | ``` 266 | 267 | I’m using Nano to create and edit the script (proving I’m a pleb). You’ll recognize a lot of the file and directory references in the launch script from the sections above. Remember this if you chose other names for your files and directories. 268 | 269 | I create the file `start-validator.sh` inside the home directory (`~/`) of “sol”: 270 | ```bash 271 | nano ~/start-validator.sh 272 | ``` 273 | 274 | Nano will create and open an empty file. Inside it I paste the following: 275 | ```bash 276 | #!/bin/bash 277 | exec solana-validator \ 278 | --entrypoint entrypoint.devnet.solana.com:8001 \ 279 | --entrypoint entrypoint2.devnet.solana.com:8001 \ 280 | --entrypoint entrypoint3.devnet.solana.com:8001 \ 281 | --entrypoint entrypoint4.devnet.solana.com:8001 \ 282 | --entrypoint entrypoint5.devnet.solana.com:8001 \ 283 | --known-validator dv1ZAGvdsz5hHLwWXsVnM94hWf1pjbKVau1QVkaMJ92 \ 284 | --known-validator dv2eQHeP4RFrJZ6UeiZWoc3XTtmtZCUKxxCApCDcRNV \ 285 | --known-validator dv4ACNkpYPcE3aKmYDqZm9G5EB3J4MRoeE7WNDRBVJB \ 286 | --known-validator dv3qDFk1DTF36Z62bNvrCXe9sKATA6xvVy6A798xxAS \ 287 | --expected-genesis-hash EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG \ 288 | --dynamic-port-range 8000-8020 \ 289 | --rpc-port 8899 \ 290 | --only-known-rpc \ 291 | --wal-recovery-mode skip_any_corrupted_record \ 292 | --identity ~/validator-keypair.json \ 293 | --vote-account ~/vote-account-keypair.json \ 294 | --log ~/log/validator.log \ 295 | --accounts /mnt/ramdisk/solana-accounts \ 296 | --ledger ~/ledger \ 297 | --limit-ledger-size 298 | ``` 299 | 300 | I won’t go through the flags and options, but you can study them by running `solana-validator --help`. I will say this, though: prepending `solana-validator` with `exec` is necessary to make log rotation work properly. More about that later. Also, to store the minimum amount of ledger you have to set `--limit-ledger-size 50000000`. Press **Ctrl+S** to save the file and **Ctrl+X** to exit Nano. 301 | 302 | We need to make the script executable, or else it won’t launch: 303 | ```bash 304 | chmod +x ~/start-validator.sh 305 | ``` 306 | 307 | Note that my script points to a “log” directory inside the home folder. Let’s create it: 308 | ```bash 309 | mkdir ~/log 310 | ``` 311 | 312 | ### Create validator service 313 | 314 | ```diff 315 | ! Perform as user with root privileges 316 | ``` 317 | 318 | Running the validator as a system service makes it easy to start it automatically at boot. The system can also restart services automatically if they crash, as the service manager monitors all services continously. 319 | 320 | I start by creating the `validator.service` file: 321 | ```bash 322 | sudo nano /etc/systemd/system/validator.service 323 | ``` 324 | 325 | Inside the file I paste the following: 326 | ``` 327 | [Unit] 328 | Description=Solana Validator 329 | After=network.target 330 | StartLimitIntervalSec=0 331 | 332 | [Service] 333 | Type=simple 334 | Restart=on-failure 335 | RestartSec=1 336 | LimitNOFILE=2000000 337 | LogRateLimitIntervalSec=0 338 | User=sol 339 | Environment=PATH=/bin:/usr/bin:/home/sol/.local/share/solana/install/active_release/bin 340 | Environment=SOLANA_METRICS_CONFIG=host=https://metrics.solana.com:8086,db=devnet,u=scratch_writer,p=topsecret 341 | ExecStart=/home/sol/start-validator.sh 342 | 343 | [Install] 344 | WantedBy=multi-user.target 345 | ``` 346 | 347 | Save and exit (**Ctrl+S** and **Ctrl+X**). 348 | 349 | To let the system know about the new service I reload the service manager: 350 | ```bash 351 | sudo systemctl daemon-reload 352 | ``` 353 | The valdator service is now almost ready to run. 354 | 355 | ### Tune system settings 356 | 357 | To ensure that the validator service is able to operate smoothly, I must tune some system settings before I can start it. First I have to increase the "nofile" limit. Copy and paste all lines into the terminal, and press **Enter**: 358 | ```bash 359 | sudo tee /etc/security/limits.d/90-solana-nofiles.conf > /dev/null < 362 | * - nofile 2000000 363 | EOT 364 | ``` 365 | 366 | Then I adjust some other settings: 367 | ```bash 368 | sudo tee /etc/sysctl.d/20-solana.conf > /dev/null < ~/leader-schedule-epoch-$(solana epoch)-$(solana address).txt 515 | ``` 516 | 517 | Show info about the current epoch: 518 | ```bash 519 | solana epoch-info 520 | ``` 521 | 522 | List all validators: 523 | ```bash 524 | solana validators 525 | ``` 526 | 527 | I can also check live metrics for the network and my node here: [https://metrics.solana.com:3000/](https://metrics.solana.com:3000/) 528 | -------------------------------------------------------------------------------- /solana-benchmarks.md: -------------------------------------------------------------------------------- 1 | 2 | # Solana benchmarks 3 | 4 | **TLDR:** versions 1.5.11 to 1.5.13 were the highest performers, all scoring an average of over 132,000 transactions per seconds (TPS), with very little variance between the three runs I performed per version. Version 1.5.13 scored ~248% (**!**) higher than v1.5.19, which was the lowest performer. The latter scored an average of 38,154 TPS; a performance drop of ~71% compared to v1.5.13. 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Setup](#setup) 8 | 3. [Results](#results) 9 | 4. [Cheat sheet](#cheat-sheet) 10 | 11 | ## Introduction 12 | 13 | I ran these benchmarks ([from these instructions](https://docs.solana.com/cluster/bench-tps)) after the launch of Solana CLI v1.7.1. Numerous validators reported they were unable to catch up after upgrading, and switching back to v1.7.0 would solve the problem for some. This made me wonder if it was possible to measure performance differences between software versions. As it turned out, it was! And the differences were significant, although not between the versions I expected. I started benchmarking at v1.7.1 and stopped when I got to v1.5.5, at which point I had struggled with very high memory usage since v1.5.10. These earlier software versions would saturate my memory after the first or second run, making it problematic to complete three runs per version (which was the plan). I haven't posted the results of v1.5.5 because the benchmark produced errors during one of the runs. This is a useful find in itself, though. Newer versions seem generally better at managing memory usage. 14 | 15 | 16 | ## Setup 17 | 18 | Since I wasn't planning on performing so many tests, I didn't consider my test setup that thoroughly. If I had, I would have tested on Ubuntu, which is the officially recommended distro for Solana. I performed the tests on a secondary validator (my backup), which I was currently experimenting with Fedora on. Testing on Fedora can have some advantages, especially when testing on more recent hardware (like the AMD Zen 3 architecture). Fedora comes with newer kernels with support for more hardware, and offer newer software through their package manager. The disadvantage is that newer software can be less stable. Running the benchmarks on a different operating system than the developers are using is another disadvantage. Anyway, it is what it is. 19 | 20 | Every version tested was built with `target-cpu=native` ("znver2" in my case). I ran all the binaries from RAM (tmpfs) in an attempt to exclude SSD performance as a variable. However, it became a variable when testing the versions that caused the highest memory usage, as memory started spilling over into swap. I ran `bench-tps.sh` three consecutive times per build, and rebooted the computer between every build. The test setup was as follows: 21 | 22 | - Hardware 23 | - AMD Ryzen 9 3950X (stock) 24 | - Gigabyte B550 Aorus Elite V2 25 | - Crucial 64 GB DDR4-3600 (16-18-18-38) 26 | - Software 27 | - Fedora 34 28 | - Kernel 5.12.9-300.fc34.x86_64 29 | - GCC 11.1.1 30 | - LLVM v12.0.0 31 | - Rustc v1.52.1 32 | 33 | 34 | ## Results 35 | 36 | It's worth noting that the margin of error is likely a few thousand TPS. The smaller differences should therefore be ignored. The difference between v1.6.7 and 1.6.8, for instance, is most likely within margin of error and can be considered noise. The interesting finds here are the larger differences. At least to me. The "variance" column displays the difference between lowest and highest score for each respective version. 37 | 38 | Version| Run 1 | Run 2 | Run 3 | Average|Variance| Note 39 | :----- | -----: | -----: | -----: | -----: | -----: | :-------------------------------------- 40 | 1.7.3 | 63552 | 60928 | 60603 | 61694 | 4,6 % | 41 | 1.7.2 | 69076 | 65467 | 61830 | 65458 | 10.5 % | 42 | 1.7.1 | 68809 | 64800 | 63526 | 65712 | 7.7 % | 43 | 1.7.0 | 70616 | 66914 | 64766 | 67432 | 8.3 % | Significant regression from 1.6.x 44 | 1.6.14 | 91710 | 90103 | 87758 | 89857 | 4.3 % | 45 | 1.6.13 | 96028 | 92618 | 88695 | 92447 | 7.6 % | 46 | 1.6.12 | 97274 | 94613 | 91405 | 94431 | 6.0 % | 47 | 1.6.11 | 92858 | 91452 | 87618 | 90642 | 5.6 % | 48 | 1.6.10 | 97333 | 93641 | 91792 | 94255 | 5.7 % | 49 | 1.6.9 | 93111 | 88321 | 85482 | 88971 | 8.2 % | 50 | 1.6.8 | 95996 | 89891 | 89343 | 91743 | 6.9 % | 51 | 1.6.7 | 97043 | 91970 | 90288 | 93100 | 7.0 % | 52 | 1.6.6 | 94915 | 92135 | 91198 | 92749 | 3.9 % | 53 | 1.6.5 | 94256 | 89341 | 88652 | 90750 | 5.9 % | Significant regression from 1.6.4 54 | 1.6.4 | 129145 | 127152 | 122380 | 126226 | 5.2 % | Significant progression from 1.6.3 55 | 1.6.3 | 107981 | 104891 | 102335 | 105069 | 5.2 % | Significant regression from 1.6.2 56 | 1.6.2 | 125177 | 120774 | 117028 | 120993 | 6.5 % | Significant progression from 1.6.1 57 | 1.6.1 | 39042 | 38105 | 37982 | 38376 | 2.7 % | Significant regression from 1.6.0 58 | 1.6.0 | 67424 | 68355 | 68232 | 68004 | 1.4 % | Significant progression from 1.5.19 59 | 1.5.19 | 38714 | 38165 | 37581 | 38154 | 2.9 % | **Lowest performer** 60 | 1.5.18 | 44656 | 44379 | 43799 | 44278 | 1.9 % | 61 | 1.5.17 | 41952 | 42065 | 40766 | 41594 | 3.1 % | 62 | 1.5.16 | 46776 | 46186 | 46387 | 46450 | 1.3 % | 63 | 1.5.15 | 46540 | 45957 | 45785 | 46094 | 1.6 % | Significant regression from 1.5.14 64 | 1.5.14 | 77004 | 76682 | 75812 | 76499 | 1.5 % | Significant regression from 1.5.13 65 | 1.5.13 | 133307 | 132757 | 132470 | 132845 | 0.6 % | **Highest performer** 66 | 1.5.12 | 132840 | 132659 | 132250 | 132583 | 0.4 % | Lowest variance between tests 67 | 1.5.11 | 133401 | 132010 | 130847 | 132086 | 1.9 % | 68 | 1.5.10 | 133699 | 134032 | 113442 | 127058 | 15.4 % | High memory usage impacting third run 69 | 1.5.9 | 132951 | 130184 | 78604 | 113913 | 40.9 % | High memory usage impacting third run 70 | 1.5.8 | 133817 | 133789 | 129643 | 132416 | 3.1 % | High memory usage. but no impact (?) 71 | 1.5.7 | 132401 | 132706 | 121857 | 128988 | 8.2 % | High memory usage impacting third run 72 | 1.5.6 | 134510 | 120728 | 109883 | 121707 | 18.3 % | High memory usage impacting two runs 73 | 74 | 75 | ## Cheat sheet 76 | 77 | I made this cheat sheet for people wanting to benchmark their system. 78 | 79 | First you need to install prerequisites, for which you need root privileges. This command is for people running Ubuntu: 80 | ```bash 81 | sudo apt update && sudo apt install -y \ 82 | libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang make gcc 83 | ``` 84 | 85 | Then you need to install rustup: 86 | ```bash 87 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 88 | source $HOME/.cargo/env 89 | ``` 90 | 91 | After installations are complete, open two more SSH shells (so you have three in total) and perform the following commands in order: 92 | 93 | *Shell 1* 94 | ```bash 95 | git clone https://github.com/solana-labs/solana.git --branch v1.7.1 ~/solana-src-v1.7.1 96 | cd ~/solana-src-v1.7.1 97 | cargo build --release 98 | NDEBUG=1 ./multinode-demo/setup.sh 99 | NDEBUG=1 ./multinode-demo/faucet.sh 100 | ``` 101 | Continue when you see `Faucet started` near the bottom of your shell window. 102 | 103 | *Shell 2* 104 | ```bash 105 | cd ~/solana-src-v1.7.1 106 | NDEBUG=1 ./multinode-demo/bootstrap-validator.sh 107 | ``` 108 | Continue when you see stuff rolling down the screen faster than you can read it. You'll know what I mean. 109 | 110 | *Shell 3 (this starts the benchmark)* 111 | ```bash 112 | cd ~/solana-src-v1.7.1 113 | NDEBUG=1 ./multinode-demo/bench-tps.sh 114 | ``` 115 | It takes some time to run `bench-tps.sh`. When it is done it will present the results; maximum and average transactions per second. 116 | -------------------------------------------------------------------------------- /solana-validator-faq.md: -------------------------------------------------------------------------------- 1 | # Solana validator FAQ (unofficial) 2 | _Written by Andrebo, with assistance from Zantetsu._ 3 | 4 | Every day we get lots of similar questions about validating in the Solana discord. In this FAQ we have tried to address most of them. Before asking in the discord, please try to find answers to your questions below. 5 | 6 | 1. [Can I mine SOL?](#1) 7 | 2. [Can anyone become a validator?](#2) 8 | 3. [Do I need any skills?](#3) 9 | 4. [Can I validate on a Windows computer?](#4) 10 | 5. [Why isn't it easier to be a Solana validator?](#5) 11 | 6. [What are the hardware requirements?](#6) 12 | * [Are the requirements for mainnet, testnet and devnet the same? Can I get by with less?](#6a) 13 | * [How big is the ledger? How much storage space do I need for my validator?](#6b) 14 | 7. [What are the network requirements?](#7) 15 | 8. [Can I run a validator from my home?](#8) 16 | 9. [How do I set up a validator?](#9) 17 | 10. [Does it cost anything to validate?](#10) 18 | 11. [How do I make my rewards as a validator?](#11) 19 | 12. [How much stake is needed to be profitable, and can future rewards be calculated?](#12) 20 | 13. [How can I attract stake to my validator?](#13) 21 | 14. [Can I get stake from the Solana foundation?](#14) 22 | 15. [What is slashing, and what is the likelihood of my validator getting slashed?](#15) 23 | 16. [What is Tour de SOL?](#16) 24 | 17. [Where can I find more information about Solana?](#17) 25 | 26 | 27 |
28 | 29 | ## 1. Can I mine SOL? 30 | 31 | No. SOL cannot be mined. Miners are part of proof-of-work blockchains. Solana is based on proof-of-stake, where a “validator” is roughly the equivalent of a miner (but still different). You’ll find lots of information about these concepts on YouTube, Wikipedia and other sites. You should know the basics of proof-of-stake before reading any further. 32 | 33 | 34 |
35 | 36 | ## 2. Can anyone become a validator? 37 | 38 | Yes. The Solana network is permissionless, so anyone can become a validator. Please continue reading this FAQ to get more knowledge about running a validator node. 39 | 40 | 41 |
42 | 43 | ## 3. Do I need any skills? 44 | 45 | Yes. You need to be comfortable with command line interfaces and Linux administration. These skills are necessary for operating a validator node day-to-day. All validators have a responsibility to run their node in a secure manner, which requires sufficient knowledge about the operating system, the hardware, the network configuration and the relevant risks. There is no way around this! 46 | 47 | One way to learn is by [setting up a validator on devnet](https://github.com/agjell/sol-tutorials/blob/master/setting-up-a-solana-devnet-validator.md) or testnet, and run it like you would a mainnet validator. Important tasks are securing and maintaining your validator, keeping the Solana software up to date in accordance with the Discord announcements, and monitoring your validator performance to ensure the highest uptime possible. Spend enough time learning before you think about becoming a mainnet validator. 48 | 49 | 50 |
51 | 52 | ## 4. Can I validate on a Windows computer? 53 | 54 | No (well, sort of). The Solana validation runtime does not yet work on Windows. Technically you can validate through a Linux virtual machine on a Windows computer, but you would still need the Linux skills mentioned above, in addition to the skills needed to run a virtual machine securely. You would also lose some performance to the host operating system. 55 | 56 | 57 |
58 | 59 | ## 5. Why isn't it easier to be a Solana validator? 60 | 61 | The Solana team is working hard to create the worlds fastest blockchain. Orders of magnitude faster than any other blockchain. Transferring the performance gains made during development to real-life improvements requires attentive and dedicated validators. All validators are responsible for managing risks, maintaining their node, ensuring the highest uptime possible, troubleshooting errors, interpreting logs, reporting bugs, upgrading hardware, keeping up to date on relevant topics etc. Validators need to be up to the tasks required of them, or else network performance will suffer. Being second-fastest is not an option. 62 | 63 | 64 |
65 | 66 | ## 6. What are the hardware requirements? 67 | 68 | You can find the official hardware requirements in the [Solana docs](https://docs.solana.com/running-validator/validator-reqs). Some people think the requirements are too high. They are not. It's not possible to create the highest performing blockchain with mediocre hardware. 69 | 70 | *Note: The validator software runs better on high clock frequencies, so it's not only core count that matters. High boost frequencies matter just as much. A 32-core CPU @ 2 GHz will probably struggle, while a 16-core CPU @ 3 GHz can perform well. This is partly because one thread (running [proof of history](https://medium.com/solana-labs/proof-of-history-a-clock-for-blockchain-cf47a61a9274)) will run at full capacity all the time. Older server CPUs with lower clocks are therefore less likely to be good performers, even if they have many cores.* 71 | 72 | 73 |
74 | 75 | ### 6a. Are the requirements for mainnet, testnet and devnet the same? Can I get by with less? 76 | 77 | You may want to have a look at the [difference between devnet, testnet and mainnet in the docs](https://docs.solana.com/clusters) before going any further. Unless you already know the difference, that is. 78 | 79 | #### Mainnet 80 | 81 | Mainnet validators should follow the [official requirements](https://docs.solana.com/running-validator/validator-reqs#hardware-recommendations). Running a mainnet validator comes with responsibilities. Real people with real assets rely on the continuous operation and well being of mainnet. To ensure this, it's critical that the network and its validators have enough performance headroom. The team is also working to increase performance, which is not possible if there is no headroom to scale into. 82 | 83 | #### Testnet 84 | 85 | Officially the hardware requirements for testnet are the same as for mainnet. This makes sense, as testnet is where the team test updates, functionality, performance and stability ([more info here](https://docs.solana.com/clusters#testnet)). This means the load on testnet can be higher than on mainnet. However, since testnet is somewhat of a playground, with non-real assets at play, there is room to experiment. 86 | 87 | The network is permissionless, so anyone can set up with the hardware they have and see how it fares. 8-core CPUs like the AMD Ryzen 7 3700X and the Intel i9-9900K have proved sufficient in the past. You can likely get by with 32 GB RAM, but 64 GB would be more ideal. The official SSD recommendations from the docs are firm; at least one NVMe SSD with high IOPS and TBW ratings is needed. It's worth noting that previously working configurations may be outdated in the near future. As Solana is in rapid development, testnet demand can change rapidly. This is another reason to abide by the official recommendation. 88 | 89 | #### Devnet 90 | 91 | Again, the requirements are officially the same as for mainnet. Though devnet usually has much less transaction throughput than mainnet or testnet. If you're looking to become a validator, devnet is a natural place to start. You can get to know the software and take Solana for a spin; in peace and without any pressure to perform. Validating on devnet is also a good way to learn without having to spend much. Most geeks have the hardware needed to run devnet stored somewhere dusty. A devnet validator can likely get by on any decent 4-core CPU. 16 GB RAM might work. An NVMe SSD is recommended, but a SATA SSD could work if the Solana accounts data is stored in RAM. You may get away with a 250 GB SSD if you run with the minimum ledger size (see next question). You can follow [this tutorial](https://github.com/agjell/sol-tutorials/blob/master/setting-up-a-solana-devnet-validator.md) on how to set up a devnet validator. 92 | 93 | 94 |
95 | 96 | ### 6b. How big is the ledger? How much storage space do I need for my validator? 97 | 98 | The ledger is infinitely big. You won't need to store the whole ledger, and you probably wouldn't have room for it anyway. Validators only store part of the ledger. You control how much of the ledger you store by passing the `--limit-ledger-size` option when you start your validator. If you don't specify a number it uses the default value of 200 million shreds. This requires ~400-500 GB of storage space. The minimum value you can pass is 50 million shreds (`--limit-ledger-size 50000000`). If you want to store an epoch worth of ledger (which can be useful for monitoring purposes) you need to specify ~260-270 million shreds. 99 | 100 | 101 |
102 | 103 | ## 7. What are the network requirements? 104 | 105 | The official requirement states 1 Gbit/s. Mainnet validators should abide by this. Current real-life usage indicates a minimum of 300 Mbit/s up and down. Egress is often higher than ingress. Highly staked nodes can have three to four times more egress than ingress traffic. 106 | 107 | 108 |
109 | 110 | ## 8. Can I run a validator from my home? 111 | 112 | Running a validator requires awareness about any risks relevant to its secure and continuous operation, and running it from home even more so. A data center will usually ensure the necessary physical protection (access/theft/fire/flood etc.) in addition to high network and power availability. At home you need to mitigate those risks yourself. Will your node or any network components be accessible to others? Do you have kids or pets? Are there a lot of break-ins where you live? Is your power grid stable? Is your internet connection up to the task? Is your network shared with others? Do you have close to 100 % internet uptime? Is your area susceptible to natural disasters? You should think about all of these risks before you run a validator from home. Outsourcing some risk to a data center may be worth the cost. 113 | 114 | 115 |
116 | 117 | ## 9. How do I set up a validator? 118 | 119 | 1. [Install Ubuntu](https://ubuntu.com/tutorials/install-ubuntu-server) 120 | 2. [Install the Solana command line interface (CLI)](https://docs.solana.com/cli/install-solana-cli-tools) 121 | 3. [Configure and start the validator software](https://docs.solana.com/running-validator/validator-start) 122 | 123 | You can also see this tutorial on [how to set up a devnet validator](https://github.com/agjell/sol-tutorials/blob/master/setting-up-a-solana-devnet-validator.md). 124 | 125 | 126 |
127 | 128 | ## 10. Does it cost anything to validate? 129 | 130 | Yes. A fee is charged for every transaction on the blockchain. A validator is expected to vote on all the blocks it receives, to help achieve network consensus. Every vote is a transaction, with the fee being charged to the validator. The voting costs for running a validator is currently ~1.1 SOL per day. A validator needs sufficient stake to make more in rewards than it spends on voting fees. 131 | 132 | 133 |
134 | 135 | ## 11. How do I make my rewards as a validator? 136 | 137 | Solana is based on proof-of-stake, which is fundamentally different from proof-of-work. In a proof-of-stake blockchain a validator needs stake delegated to it to make rewards. More stake equals more rewards, because validators with higher stake are chosen to write new transactions to the ledger more often. The assumption is that nodes with higher stake are more trustworthy, because people have trusted them with their tokens. Stable returns are the result of high uptime, valid voting at a high rate, and producing valid blocks within their required time slot. The validator has incentive to be a good actor because stakers can withdraw their stake at any time. Losing stake means losing rewards. The stakers incentive is to get yield on their tokens. The yield depends on the commission the validator charges. You can read more about Staking in [this section of the docs](https://docs.solana.com/staking). 138 | 139 | 140 |
141 | 142 | ## 12. How much stake is needed to be profitable, and can future rewards be calculated? 143 | 144 | The amount of stake a validator needs to be profitable depends on multiple factors: 145 | 146 | - Hardware costs 147 | - Network costs 148 | - Validator voting costs 149 | - Validator commission 150 | - Price of SOL tokens 151 | - Amount of transactions in the network 152 | 153 | Unfortunately there is no official way of calculating rewards. However, Zantetsu (from the Solana discord) has made a [spreadsheet](https://docs.google.com/spreadsheets/d/1HPU_uG3iJ_ns27CItdWGllW0c-Pn07J0_LEDZs1otQY/edit?usp=sharing) based on their experience. You can make your own copy of the spreadsheet and play with the numbers. 154 | 155 | 156 |
157 | 158 | ## 13. How can I attract stake to my validator? 159 | 160 | That’s for you to figure out! As rewards can be considerable, you should have more than enough incentive to attract stake. Being a resource for the community is a good start. Building something useful, suggesting amendments to the code, filing bug reports or supporting people in the Discord are actions that can attract attention (and stake) to validators. 161 | 162 | 163 |
164 | 165 | ## 14. Can I get stake from the Solana foundation? 166 | 167 | Yes, you may be eligible to get stake via the [Solana Foundation Delegation Program](https://solana.foundation/delegation-program). Check out their [FAQ](https://solana.foundation/faq) for more information. 168 | 169 | 170 |
171 | 172 | ## 15. What is slashing, and what is the likelihood of my validator getting slashed? 173 | 174 | The following is stated about slashing in the [docs](https://docs.solana.com/staking): 175 | >Slashing involves the removal and destruction of a portion of a validator's delegated stake in response to intentional malicious behavior, such as creating invalid transactions or censoring certain types of transactions or network participants. 176 | 177 | There is currently zero likelihood of a validator getting slashed, as slashing is not yet implemented. You can read more about slashing in the docs [here](https://docs.solana.com/proposals/slashing) and [here](https://docs.solana.com/proposals/optimistic-confirmation-and-slashing). 178 | 179 | 180 |
181 | 182 | ## 16. What is Tour de SOL? 183 | 184 | Tour de SOL (TdS) was Solanas incentivized testnet program, where people were compensated for running testnet validators. Tour de SOL is permanently closed, but its function has been transfered to the [Solana Foundation Delegation Program](#14). 185 | 186 | 187 |
188 | 189 | ## 17. Where can I find more information about Solana? 190 | 191 | - [The official website](https://solana.com/) 192 | - [Documentation](https://docs.solana.com/) 193 | - [Discord chatroom](https://discordapp.com/invite/pquxPsq) 194 | - [News on Medium](https://medium.com/solana-labs) 195 | - [Forum](https://forums.solana.com/) 196 | - [Podcast](https://podcast.solana.com/) 197 | - [Telegram channel](https://t.me/solana) 198 | - [YouTube channel](https://www.youtube.com/c/Solanalabs/) 199 | - [GitHub project page](https://github.com/solana-labs/) 200 | - [Soltraders](http://t.me/soltraders) on Telegram (for price and trading talk) 201 | -------------------------------------------------------------------------------- /staking-on-solana.md: -------------------------------------------------------------------------------- 1 | # Staking on Solana 2 | 3 | 1. [Introduction](#introduction) 4 | 2. [Create wallet (optional)](#create-wallet-optional) 5 | 3. [Create stake account](#create-stake-account) 6 | 4. [Delegate stake](#delegate-stake) 7 | 5. [Deactivate stake](#deactivate-stake) 8 | 6. [Withdraw stake](#withdraw-stake) 9 | 7. [Merge stake accounts](#merge-stake-accounts) 10 | 8. [More staking resources](#more-staking-resources) 11 | 12 | 13 | ## Introduction 14 | 15 | A staker is someone that has SOL and wants to put them to work to collect rewards. They can do this by staking SOL on a validator. A validator, on the other hand, needs SOL staked on it to earn rewards for itself (or its' owner, to be precise). More stake equals more rewards, because more stake means a validator is chosen to write new transactions to the ledger more often. This means that stakers and validators can benefit from each other. You can read more about staking in the [docs](https://docs.solana.com/staking). 16 | 17 | This guide is only intended for people operating in Solana devnet or testnet. Although the procedure will be somewhat similar for mainnet, my experience and knowledge of mainnet operations is too limited to say. 18 | 19 | The process of staking involves creating a stake account, transferring SOL to it and delegating it to a validator. SOL placed in a stake account is simply referred to as "stake". 20 | 21 | 22 | ## Create wallet (optional) 23 | 24 | This step is optional, as you may already have a wallet you can use. For the sake of demonstration I will create one: 25 | ```bash 26 | solana-keygen new -o ~/staker-wallet-keypair.json 27 | ``` 28 | 29 | I save the password and seed phrase somewhere securely. Then I airdrop 1 SOL into it, that I will stake on a validator later: 30 | ```bash 31 | solana airdrop 1 ~/staker-wallet-keypair.json 32 | ``` 33 | 34 | Solana replies with the balance, but we can verify the balance manually like this: 35 | ```bash 36 | solana balance ~/staker-wallet-keypair.json 37 | ``` 38 | 39 | 40 | ## Create stake account 41 | 42 | Now for the stake account. We don't need to set passwords for stake accounts, as they are fully controlled by their assigned "withdraw"- and "stake authorities". I start out by creating a regular system account: 43 | ```bash 44 | solana-keygen new --no-passphrase -o ~/stake-account-keypair.json 45 | ``` 46 | 47 | Solana replies with the public key of the account. I copy it and save it somewhere safe. Then I use the keypair I just made as a base to create the stake account, and transfer 0.5 SOL to it from my wallet. I also assign my wallet as the withdraw authority and the stake authority of the account: 48 | ```bash 49 | solana create-stake-account \ 50 | --fee-payer ~/staker-wallet-keypair.json \ 51 | --stake-authority ~/staker-wallet-keypair.json \ 52 | --withdraw-authority ~/staker-wallet-keypair.json \ 53 | --from ~/staker-wallet-keypair.json \ 54 | ~/stake-account-keypair.json 0.5 55 | ``` 56 | 57 | If the transaction succeeds I may delete the keypair file, provided I've taken note of the stake account public key. If I haven't got the public key I must retrieve it and save it before I delete the keypair: 58 | ```bash 59 | solana address -k ~/stake-account-keypair.json 60 | ``` 61 | ```bash 62 | rm ~/stake-account-keypair.json 63 | ``` 64 | Note that if you loose access to the withdraw authority account, you also loose control of the stake account and its' contents! 65 | 66 | 67 | ## Delegate stake 68 | 69 | Lastly I need to delegate the stake. This is done to the vote account of a validator, *not* the validator identity. I do it like this: 70 | ```bash 71 | solana delegate-stake \ 72 | --fee-payer ~/staker-wallet-keypair.json \ 73 | --stake-authority ~/staker-wallet-keypair.json \ 74 | 75 | ``` 76 | 77 | We can view information about the stake account by running: 78 | ```bash 79 | solana stake-account 80 | ``` 81 | There is a "warmup"-period for activating stake. It's not clear how long that period is (cf. [docs](https://docs.solana.com/implemented-proposals/staking-rewards#stake-warmup-cooldown-withdrawal)), but in my limited experience it has been a few days or so. 82 | 83 | 84 | ## Deactivate stake 85 | 86 | At some point I may want to deactivate the stake. Either because I want to delegate it to another validator, or because I want to withdraw it back to my wallet. I do it by running: 87 | ```bash 88 | solana deactivate-stake \ 89 | --fee-payer ~/staker-wallet-keypair.json \ 90 | --stake-authority ~/staker-wallet-keypair.json \ 91 | 92 | ``` 93 | Just like there is a warmup period to activate stake, there is a "cooldown" period to deactivate stake. That means I'll have to wait to redelegate or withdraw my stake until they are released. 94 | 95 | 96 | ## Withdraw stake 97 | 98 | When the cooldown period is over I can withdraw my stake. First I'll check the balance of the stake account: 99 | ```bash 100 | solana balance 101 | ``` 102 | 103 | Then I'll withdraw 0.5 SOL back to my wallet: 104 | ```bash 105 | solana withdraw-stake \ 106 | --fee-payer ~/staker-wallet-keypair.json \ 107 | --withdraw-authority ~/staker-wallet-keypair.json \ 108 | ~/staker-wallet-keypair.json 0.5 109 | ``` 110 | 111 | 112 | ## Merge stake accounts 113 | 114 | We can merge two stake accounts on certain conditions (see [here](https://docs.solana.com/staking/stake-accounts#merging-stake-accounts)). To merge stake accounts that have active stake (live accounts) they both need to 115 | 116 | - have the same stake authority 117 | - be associated with the same vote account 118 | - have identical vote credits (being active on the same vote account for at least one epoch) 119 | 120 | If the conditions are met I can merge two stake accounts by running: 121 | ```bash 122 | solana merge-stake \ 123 | --fee-payer ~/staker-wallet-keypair.json \ 124 | --stake-authority ~/staker-wallet-keypair.json \ 125 | 126 | ``` 127 | 128 | 129 | ## More staking resources 130 | 131 | There is more to staking than what I have shown above. The following Solana docs contains a lot of useful information: 132 | 133 | - [Staking on Solana](https://docs.solana.com/staking) 134 | - [Delegate stake](https://docs.solana.com/cli/delegate-stake) 135 | - [Manage stake accounts](https://docs.solana.com/cli/manage-stake-accounts) 136 | - [Validator stake](https://docs.solana.com/running-validator/validator-stake) 137 | - [Staking rewards](https://docs.solana.com/implemented-proposals/staking-rewards) 138 | --------------------------------------------------------------------------------